更新前端页面,调整表单布局和样式,优化响应式设计,添加移动端卡片视图,修改AWS报价单的显示方式。

This commit is contained in:
wangqifan 2025-08-29 19:11:37 +08:00
parent 02ba9ea77f
commit 2376623df6
2 changed files with 486 additions and 298 deletions

View File

@ -7,7 +7,7 @@
<el-menu mode="horizontal" router :default-active="'/awsSearch'" class="menu" background-color="#3498db" text-color="#fff" active-text-color="#ffd04b">
<!-- <el-menu-item index="/"><i class="el-icon-s-finance"></i> 价格计算器</el-menu-item> -->
<el-menu-item index="/awsSearch"><i class="el-icon-search"></i>AWS报价</el-menu-item>
<el-menu-item index="/awsSearchDiscount"><i class="el-icon-search"></i>AWS折扣</el-menu-item>
<!-- <el-menu-item index="/awsSearchDiscount"><i class="el-icon-search"></i>AWS折扣</el-menu-item> -->
<!-- <el-menu-item index="/compare"><i class="el-icon-data-analysis"></i> 价格对比</el-menu-item> -->
</el-menu>
</div>

View File

@ -9,9 +9,9 @@
</template>
<div class="form-container">
<el-form :model="form" label-width="120px">
<el-form :model="form" label-width="120px" label-position="top">
<el-row :gutter="20">
<el-col :md="8" :sm="24">
<el-col :lg="8" :md="12" :sm="24">
<el-form-item label="CPU 核心数">
<el-input-number
v-model="form.cpu_cores"
@ -24,7 +24,7 @@
</el-form-item>
</el-col>
<el-col :md="8" :sm="24">
<el-col :lg="8" :md="12" :sm="24">
<el-form-item label="内存(GB)">
<el-input-number
v-model="form.memory_gb"
@ -37,7 +37,7 @@
</el-form-item>
</el-col>
<el-col :md="8" :sm="24">
<el-col :lg="8" :md="12" :sm="24">
<el-form-item label="磁盘(GB)">
<el-input-number
v-model="form.disk_gb"
@ -52,7 +52,7 @@
</el-row>
<el-row :gutter="20">
<el-col :md="6" :sm="24">
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="区域">
<el-select
v-model="form.region"
@ -72,7 +72,7 @@
</el-form-item>
</el-col>
<el-col :md="6" :sm="24">
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="操作系统">
<el-select v-model="form.operating_system" placeholder="选择操作系统" class="full-width">
<el-option label="Linux" value="Linux"></el-option>
@ -81,7 +81,7 @@
</el-form-item>
</el-col>
<el-col :md="6" :sm="24">
<el-col :lg="6" :md="12" :sm="24">
<el-form-item label="磁盘类型">
<el-select v-model="form.disk_type" disabled placeholder="磁盘类型" class="full-width">
<el-option label="GP3 (通用SSD)" value="gp3"></el-option>
@ -89,8 +89,8 @@
</el-form-item>
</el-col>
<el-col :md="6" :sm="24" class="flexible-col">
<el-form-item>
<el-col :lg="6" :md="12" :sm="24" class="flexible-col">
<el-form-item label=" " class="action-form-item">
<el-button type="primary" @click="searchInstances" icon="el-icon-search" class="search-button">搜索实例</el-button>
</el-form-item>
</el-col>
@ -105,17 +105,17 @@
<div v-else-if="searchResults.length" class="search-results animated fadeIn">
<h3><i class="el-icon-s-data"></i> 符合条件的实例</h3>
<!-- Desktop View: Table -->
<div v-if="!isMobile" class="table-responsive">
<el-table :data="searchResults" border style="width: 100%" :stripe="true" class="result-table">
<el-table-column prop="instance_type" label="实例类型" width="120">
<el-table-column prop="instance_type" label="实例类型" width="120" fixed>
<template #default="scope">
<div class="instance-type">
<el-tag type="info">{{ scope.row.instance_type }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column prop="description" label="描述" min-width="180"></el-table-column>
<el-table-column prop="cpu" label="CPU核心" width="100" align="center">
<template #default="scope">
<div class="spec-value">
@ -123,7 +123,6 @@
</div>
</template>
</el-table-column>
<el-table-column prop="memory" label="内存(GB)" width="100" align="center">
<template #default="scope">
<div class="spec-value">
@ -131,7 +130,6 @@
</div>
</template>
</el-table-column>
<el-table-column prop="disk_gb" label="磁盘(GB)" width="100" align="center">
<template #default="scope">
<div class="spec-value">
@ -139,7 +137,6 @@
</div>
</template>
</el-table-column>
<el-table-column label="每月价格" width="260">
<template #default="scope">
<div class="price-breakdown">
@ -158,8 +155,7 @@
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="200" align="center">
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="scope">
<div class="action-buttons-cell">
<el-button
@ -182,6 +178,53 @@
</el-table>
</div>
<!-- Mobile View: Cards -->
<div v-else class="mobile-results-list">
<el-card v-for="item in searchResults" :key="item.instance_type" class="result-card">
<div class="card-header-mobile">
<el-tag type="info" size="medium">{{ item.instance_type }}</el-tag>
<div class="total-price">${{ item.total_monthly_price.toFixed(2) }}<span class="price-unit">/</span></div>
</div>
<div class="card-content">
<p class="description">{{ item.description }}</p>
<div class="specs-list">
<div class="spec-item">
<i class="el-icon-cpu"></i>
<strong>CPU:</strong>
<span>{{ item.cpu }} 核心</span>
</div>
<div class="spec-item">
<i class="el-icon-coin"></i>
<strong>内存:</strong>
<span>{{ item.memory }} GB</span>
</div>
<div class="spec-item">
<i class="el-icon-folder"></i>
<strong>磁盘:</strong>
<span>{{ item.disk_gb }} GB</span>
</div>
</div>
</div>
<div class="card-actions">
<el-button
type="primary"
size="small"
@click="selectInstance(item)"
icon="el-icon-select">
查看详情
</el-button>
<el-button
type="success"
size="small"
@click="addToComparison(item)"
icon="el-icon-plus">
加入对比
</el-button>
</div>
</el-card>
</div>
</div>
<div v-else-if="searched" class="no-results">
<el-empty description="没有找到符合条件的实例,请尝试降低配置要求"></el-empty>
</div>
@ -191,37 +234,37 @@
<el-card class="instance-card">
<el-row :gutter="20">
<el-col :md="4" :sm="24">
<el-col :lg="4" :md="8" :sm="12" :xs="24">
<div class="instance-info-item">
<div class="info-label">实例类型</div>
<div class="info-value">{{ selectedInstance.instance_type }}</div>
</div>
</el-col>
<el-col :md="4" :sm="24">
<el-col :lg="4" :md="8" :sm="12" :xs="24">
<div class="instance-info-item">
<div class="info-label">CPU核心</div>
<div class="info-value">{{ selectedInstance.cpu }} </div>
</div>
</el-col>
<el-col :md="4" :sm="24">
<el-col :lg="4" :md="8" :sm="12" :xs="24">
<div class="instance-info-item">
<div class="info-label">内存</div>
<div class="info-value">{{ selectedInstance.memory }} GB</div>
</div>
</el-col>
<el-col :md="4" :sm="24">
<el-col :lg="4" :md="8" :sm="12" :xs="24">
<div class="instance-info-item">
<div class="info-label">磁盘</div>
<div class="info-value">{{ selectedInstance.disk_gb }} GB (GP3)</div>
</div>
</el-col>
<el-col :md="4" :sm="24">
<el-col :lg="4" :md="8" :sm="12" :xs="24">
<div class="instance-info-item">
<div class="info-label">区域</div>
<div class="info-value">{{ getRegionName(form.region) }}</div>
</div>
</el-col>
<el-col :md="4" :sm="24">
<el-col :lg="4" :md="8" :sm="12" :xs="24">
<div class="instance-info-item">
<div class="info-label">操作系统</div>
<div class="info-value">{{ form.operating_system }}</div>
@ -232,7 +275,7 @@
<el-divider content-position="center">价格信息</el-divider>
<el-row :gutter="20">
<el-col :md="8" :sm="24">
<el-col :lg="8" :md="24">
<div class="price-info-item">
<div class="price-icon"></div>
<div class="price-title">每小时价格</div>
@ -240,7 +283,7 @@
<div class="price-note">实例每小时费用</div>
</div>
</el-col>
<el-col :md="8" :sm="24">
<el-col :lg="8" :md="24">
<div class="price-info-item">
<div class="price-icon">💾</div>
<div class="price-title">存储价格</div>
@ -248,7 +291,7 @@
<div class="price-note">{{ selectedInstance.disk_gb }}GB GP3卷每天费用</div>
</div>
</el-col>
<el-col :md="8" :sm="24">
<el-col :lg="8" :md="24">
<div class="price-info-item total">
<div class="price-icon">💰</div>
<div class="price-title">每月总费用</div>
@ -274,32 +317,33 @@
<div class="quote-header">
<div class="quote-title">AWS亚马逊报价单</div>
<div class="quote-info">
<table class="info-table">
<tr>
<td class="info-label">联系人:</td>
<td class="info-value">
<el-input v-model="quoteInfo.contact" placeholder="请输入联系人"></el-input>
</td>
<td></td>
<td class="info-label">签发日期:</td>
<td class="info-value">{{ getCurrentDate() }}</td>
</tr>
<tr>
<td class="info-label">电话:</td>
<td class="info-value">
<el-input v-model="quoteInfo.phone" placeholder="请输入电话"></el-input>
</td>
<td></td>
<td class="info-label">电话:</td>
<td class="info-value"></td>
</tr>
</table>
<div class="info-row">
<div class="info-item">
<span class="info-label">联系人:</span>
<el-input v-model="quoteInfo.contact" placeholder="请输入联系人" size="small"></el-input>
</div>
<div class="info-item">
<span class="info-label">签发日期:</span>
<span class="info-value">{{ getCurrentDate() }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">电话:</span>
<el-input v-model="quoteInfo.phone" placeholder="请输入电话" size="small"></el-input>
</div>
<div class="info-item">
<span class="info-label">电话:</span>
<span class="info-value"></span>
</div>
</div>
</div>
</div>
<!-- 报价单内容 -->
<div class="table-responsive" v-if="!isMobile">
<el-table :data="comparisonList" border style="width: 100%" :stripe="true" class="comparison-table">
<el-table-column label="产品名称" width="80" align="center">
<el-table-column label="产品名称" width="80" align="center" fixed>
<template #default>
<span>EC2</span>
</template>
@ -341,7 +385,7 @@
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<el-table-column label="操作" width="80" align="center" fixed="right">
<template #default="scope">
<el-button
type="danger"
@ -353,12 +397,55 @@
</template>
</el-table-column>
</el-table>
</div>
<!-- Mobile: 卡片列表 -->
<div v-else class="mobile-comparison-list">
<el-card v-for="(item, idx) in comparisonList" :key="item.instance_type + '-' + idx" class="mobile-comparison-card">
<div class="mobile-comparison-header">
<div class="mobile-comparison-title">EC2</div>
<div class="mobile-comparison-price">${{ item.total_monthly_price.toFixed(2) }}<span class="price-unit">/</span></div>
</div>
<div class="mobile-comparison-body">
<div class="mobile-row">
<span class="mobile-label">规格</span>
<span class="mobile-value">{{ formatSpecDescription(item) }}</span>
</div>
<div class="mobile-row">
<span class="mobile-label">磁盘</span>
<span class="mobile-value">{{ item.disk_gb }}G GP3</span>
</div>
<div class="mobile-row">
<span class="mobile-label">系统</span>
<span class="mobile-value">{{ formatOS(item.operating_system) }}</span>
</div>
<div class="mobile-row">
<span class="mobile-label">区域</span>
<span class="mobile-value">{{ getRegionName(item.region) }}</span>
</div>
<div class="mobile-row">
<span class="mobile-label">年付</span>
<span class="mobile-value">${{ (item.total_monthly_price * 12).toFixed(2) }}</span>
</div>
</div>
<div class="mobile-comparison-actions">
<el-button
type="danger"
size="small"
@click="removeFromComparison(idx)"
icon="el-icon-delete"
plain>
移除
</el-button>
</div>
</el-card>
</div>
<!-- 说明事项 -->
<div class="quote-notes">
<div class="note-title">说明事项:</div>
<div class="note-items">
<div class="note-item">1. 以上价格仅包服务器和磁盘的费用, 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 美国$0.12USD/GB</div>
<div class="note-item">1. 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 美国$0.12USD/GB</div>
</div>
</div>
@ -396,30 +483,35 @@ export default {
operating_system: 'Linux' // Linux
},
regions: [],
filteredRegions: [], //
filteredRegions: [],
searchResults: [],
selectedInstance: null,
comparisonList: [], //
comparisonList: [],
loading: false,
searched: false,
quoteInfo: {
contact: '林先生',
phone: '18626324958'
},
isMobile: false
}
}
},
mounted() {
this.checkScreenSize();
window.addEventListener('resize', this.checkScreenSize);
},
beforeUnmount() {
window.removeEventListener('resize', this.checkScreenSize);
},
async created() {
try {
// 使API
this.regions = await apiService.getRegions()
this.filteredRegions = [...this.regions] //
this.filteredRegions = [...this.regions]
//
if (this.regions && this.regions.length > 0) {
this.form.region = this.regions[0].code
}
//
const savedComparison = localStorage.getItem('instance_comparison')
if (savedComparison) {
this.comparisonList = JSON.parse(savedComparison)
@ -430,6 +522,9 @@ export default {
}
},
methods: {
checkScreenSize() {
this.isMobile = window.innerWidth < 768;
},
filterRegions(query) {
if (query) {
this.filteredRegions = this.regions.filter(region => {
@ -448,7 +543,6 @@ export default {
this.loading = true
try {
// 使API
const data = await apiService.searchInstances({
cpu_cores: this.form.cpu_cores,
memory_gb: this.form.memory_gb,
@ -457,7 +551,6 @@ export default {
operating_system: this.form.operating_system
})
//
this.searchResults = data.map(item => ({
...item,
operating_system: this.form.operating_system,
@ -479,7 +572,6 @@ export default {
},
selectInstance(instance) {
this.selectedInstance = instance
//
setTimeout(() => {
const element = document.querySelector('.selected-instance')
if (element) {
@ -490,7 +582,6 @@ export default {
addToComparison(instance) {
if (!instance) return
//
const exists = this.comparisonList.find(
item => item.instance_type === instance.instance_type &&
item.region === this.form.region &&
@ -502,7 +593,6 @@ export default {
return
}
//
const comparisonInstance = {
...instance,
region: this.form.region,
@ -512,10 +602,8 @@ export default {
this.comparisonList.push(comparisonInstance)
this.$message.success('已添加到对比列表')
//
localStorage.setItem('instance_comparison', JSON.stringify(this.comparisonList))
//
setTimeout(() => {
const element = document.querySelector('.comparison-section')
if (element) {
@ -539,25 +627,14 @@ export default {
return
}
// 簿
const wb = XLSX.utils.book_new()
//
const titleRow = [['AWS亚马逊报价单']]
//
const infoRows = [
['联系人:', this.quoteInfo.contact, '', '签发日期:', this.getCurrentDate()],
['电话:', this.quoteInfo.phone, '', '电话:', '']
]
//
const emptyRow = ['', '', '', '', '', '', '']
//
const headerRow = ['产品名称', '规格型号', '磁盘', '操作系统', '区域', '官方月付全额 美元USD', '官方年付全额 美元USD']
//
const dataRows = this.comparisonList.map(instance => [
'EC2',
`${instance.cpu}${instance.memory}G ${instance.instance_type}`,
@ -567,52 +644,34 @@ export default {
instance.total_monthly_price.toFixed(2),
(instance.total_monthly_price * 12).toFixed(2)
])
//
const noteRows = [
emptyRow,
['说明事项:'],
['1. 以上价格仅包服务器和磁盘的费用, 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 均价$0.12USD/GB']
['1. 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 均价$0.12USD/GB']
]
//
const allRows = [...titleRow, ...infoRows, emptyRow, headerRow, ...dataRows, ...noteRows]
//
const ws = XLSX.utils.aoa_to_sheet(allRows)
//
const colWidths = [
{ wch: 15 }, // A
{ wch: 25 }, // B
{ wch: 15 }, // C
{ wch: 15 }, // D
{ wch: 25 }, // E
{ wch: 25 }, // F
{ wch: 25 } // G
{ wch: 15 }, { wch: 25 }, { wch: 15 }, { wch: 15 }, { wch: 25 }, { wch: 25 }, { wch: 25 }
]
ws['!cols'] = colWidths
//
const rowHeights = Array(allRows.length).fill({ hpt: 25 })
rowHeights[0] = { hpt: 35 } //
rowHeights[4] = { hpt: 30 } //
rowHeights[0] = { hpt: 35 }
rowHeights[4] = { hpt: 30 }
ws['!rows'] = rowHeights
//
const headerRowIndex = 4 //
const noteStartRow = headerRowIndex + dataRows.length + 2 //
const headerRowIndex = 4
const noteStartRow = headerRowIndex + dataRows.length + 2
ws['!merges'] = [
// (A1:G1)
{ s: { r: 0, c: 0 }, e: { r: 0, c: 6 } },
//
{ s: { r: noteStartRow, c: 0 }, e: { r: noteStartRow, c: 6 } },
{ s: { r: noteStartRow + 1, c: 0 }, e: { r: noteStartRow + 1, c: 6 } },
{ s: { r: noteStartRow + 2, c: 0 }, e: { r: noteStartRow + 2, c: 6 } }
]
//
for (let r = noteStartRow; r < noteStartRow + 3; r++) {
const cellRef = XLSX.utils.encode_cell({ r, c: 0 })
if (ws[cellRef]) {
@ -624,20 +683,13 @@ export default {
}
}
//
ws['A1'].s = {
font: { sz: 16, bold: true, color: { rgb: 'FFFFFF' } },
alignment: { horizontal: 'center', vertical: 'center' },
fill: { patternType: 'solid', fgColor: { rgb: '4472C4' } },
border: {
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
}
border: { top: { style: 'thin' }, bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' } }
}
//
const cols = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
cols.forEach(col => {
const cellRef = `${col}${headerRowIndex + 1}`
@ -646,35 +698,22 @@ export default {
font: { bold: true },
alignment: { horizontal: 'center', vertical: 'center' },
fill: { patternType: 'solid', fgColor: { rgb: 'E0E0E0' } },
border: {
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
}
border: { top: { style: 'thin' }, bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' } }
}
})
//
for (let r = 0; r < allRows.length; r++) {
for (let c = 0; c < 7; c++) {
const cellRef = XLSX.utils.encode_cell({ r, c })
if (!ws[cellRef]) ws[cellRef] = { v: '', t: 's' }
if (!ws[cellRef].s) ws[cellRef].s = {}
ws[cellRef].s.border = {
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
}
ws[cellRef].s.border = { top: { style: 'thin' }, bottom: { style: 'thin' }, left: { style: 'thin' }, right: { style: 'thin' } }
ws[cellRef].s.alignment = { horizontal: 'center', vertical: 'center' }
}
}
// 簿
XLSX.utils.book_append_sheet(wb, ws, 'AWS报价单')
// 簿
const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array', bookSST: true, cellStyles: true })
const blob = new Blob([wbout], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
saveAs(blob, 'AWS亚马逊报价单.xlsx')
@ -684,7 +723,6 @@ export default {
goToCalculator() {
if (!this.selectedInstance) return
//
const params = {
instance_type: this.selectedInstance.instance_type,
region: this.form.region,
@ -692,16 +730,13 @@ export default {
operating_system: this.form.operating_system
}
//
localStorage.setItem('calculator_params', JSON.stringify(params))
this.$router.push('/')
},
//
getRegionName(regionCode) {
const region = this.regions.find(r => r.code === regionCode)
return region ? region.name : regionCode
},
// YYYY/MM/DD
getCurrentDate() {
const date = new Date()
const year = date.getFullYear()
@ -709,11 +744,9 @@ export default {
const day = date.getDate().toString().padStart(2, '0')
return `${year}/${month}/${day}`
},
//
formatSpecDescription(instance) {
return `${instance.cpu}${instance.memory}G ${instance.instance_type}`
},
//
formatOS(os) {
if (os === 'Linux') return 'Linux'
if (os === 'Windows') return 'Windows'
@ -727,8 +760,7 @@ export default {
.instance-search {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 1;
padding: 15px;
}
.search-card {
@ -736,10 +768,6 @@ export default {
transition: all 0.3s ease;
}
.search-card:hover {
transform: translateY(-5px);
}
.card-header {
display: flex;
flex-direction: column;
@ -771,19 +799,13 @@ export default {
.flexible-col {
display: flex;
align-items: center;
align-items: flex-end;
}
.search-button {
width: 100%;
height: 40px;
font-size: 16px;
transition: all 0.3s ease;
}
.search-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
}
.loading-container {
@ -801,15 +823,14 @@ export default {
text-align: center;
}
.search-results h3 i {
margin-right: 8px;
color: var(--secondary-color);
}
.result-table {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.05);
}
.table-responsive {
overflow-x: auto;
width: 100%;
}
.instance-type {
@ -879,13 +900,8 @@ export default {
text-align: center;
}
.selected-instance h3 i {
margin-right: 8px;
color: var(--accent-color);
}
.instance-card {
border-left: 4px solid var(--accent-color);
border-left: 4px solid var(--accent-color, #409EFF);
}
.instance-info-item {
@ -956,6 +972,7 @@ export default {
justify-content: center;
gap: 15px;
margin-top: 20px;
flex-wrap: wrap;
}
.animated {
@ -978,21 +995,11 @@ export default {
animation-name: fadeIn;
}
@media (max-width: 768px) {
.action-buttons {
flex-direction: column;
}
.instance-info-item,
.price-info-item {
margin-bottom: 15px;
}
}
.action-buttons-cell {
display: flex;
flex-direction: column;
gap: 5px;
justify-content: center;
}
.comparison-section {
@ -1010,7 +1017,6 @@ export default {
.comparison-card {
margin-bottom: 20px;
position: relative;
}
.comparison-table {
@ -1033,26 +1039,29 @@ export default {
.quote-info {
border: 1px solid #e0e0e0;
padding: 10px;
}
.info-table {
width: 100%;
border-collapse: collapse;
.info-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 10px;
}
.info-row:last-child {
margin-bottom: 0;
}
.info-table td {
padding: 8px;
border: 1px solid #e0e0e0;
.info-item {
display: flex;
align-items: center;
gap: 8px;
flex: 1 1 250px;
}
.info-label {
width: 80px;
font-weight: bold;
background-color: #f5f5f5;
}
.info-value {
width: 200px;
white-space: nowrap;
}
.quote-notes {
@ -1060,6 +1069,7 @@ export default {
border: 1px solid #ffcc00;
background-color: #fffbea;
padding: 10px;
font-size: 14px;
}
.note-title {
@ -1067,18 +1077,196 @@ export default {
margin-bottom: 10px;
}
.note-items {
color: #333;
}
.note-item {
margin-bottom: 5px;
}
.quote-actions {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
flex-wrap: wrap;
gap: 15px;
}
.summary-item {
display: flex;
gap: 10px;
align-items: center;
}
.summary-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
/* Mobile Card Styles */
.mobile-results-list {
display: flex;
flex-direction: column;
gap: 15px;
}
.result-card {
border-left: 4px solid #409EFF;
}
.result-card .el-card__body {
padding: 0;
}
.card-header-mobile {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
border-bottom: 1px solid #EBEEF5;
}
.total-price {
font-size: 20px;
font-weight: bold;
color: #e67e22;
}
.price-unit {
font-size: 14px;
color: #7f8c8d;
margin-left: 4px;
}
.card-content {
padding: 15px;
}
.description {
font-size: 14px;
color: #555;
margin-bottom: 15px;
line-height: 1.6;
}
.specs-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.spec-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 15px;
}
.spec-item i {
color: #409EFF;
font-size: 18px;
}
.spec-item strong {
width: 50px;
}
.card-actions {
background-color: #fcfcfc;
border-top: 1px solid #EBEEF5;
padding: 10px 15px;
display: flex;
justify-content: flex-end;
gap: 10px;
}
.card-actions .el-button {
flex-grow: 1;
}
/* Responsive Styles */
@media (max-width: 992px) {
.el-form--label-top .el-form-item__label {
padding-bottom: 0;
}
.action-form-item {
margin-bottom: 0;
}
}
@media (max-width: 768px) {
.instance-search {
padding: 10px;
}
.card-header span {
font-size: 18px;
}
.form-container {
padding: 10px 0;
}
.flexible-col {
align-items: stretch;
}
.search-button {
margin-top: 0;
}
.action-buttons {
flex-direction: column;
}
.action-buttons .el-button {
width: 100%;
margin-left: 0 !important;
}
.instance-info-item,
.price-info-item {
margin-bottom: 15px;
}
.quote-actions {
flex-direction: column;
align-items: stretch;
}
.summary-buttons {
justify-content: center;
}
.summary-buttons .el-button {
flex-grow: 1;
}
}
</style>
<style scoped>
/* Mobile comparison card styles */
.mobile-comparison-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.mobile-comparison-card {
border-left: 4px solid #00bcd4;
}
.mobile-comparison-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
border-bottom: 1px solid #EBEEF5;
}
.mobile-comparison-title {
font-weight: 600;
}
.mobile-comparison-price {
font-size: 18px;
font-weight: 700;
color: #e67e22;
}
.mobile-comparison-body {
padding: 12px 16px;
display: flex;
flex-direction: column;
gap: 8px;
}
.mobile-row {
display: flex;
justify-content: space-between;
gap: 10px;
}
.mobile-label {
color: #7f8c8d;
min-width: 44px;
}
.mobile-value {
font-weight: 600;
color: #2c3e50;
}
.mobile-comparison-actions {
padding: 10px 16px 14px 16px;
display: flex;
justify-content: flex-end;
}
@media (min-width: 769px) {
.mobile-comparison-list { display: none; }
}
</style>