feat(bid): 优化供应商报价和甲方报价页面展示

1.  重构SupplierQuoteTab移除冗余空状态样式
2.  为CompareSection添加交期最快标识样式和逻辑
3.  全新重构ClientQuoteTab页面,优化表格布局与样式
This commit is contained in:
2026-05-29 19:53:23 +08:00
parent c871f184d8
commit be3212cbdb
3 changed files with 216 additions and 47 deletions

View File

@@ -1,30 +1,69 @@
<template>
<div>
<div style="margin-bottom:10px; text-align:right">
<div class="client-quote-tab">
<!-- 操作栏 -->
<div class="tab-toolbar">
<span class="tab-title">甲方报价记录</span>
<el-button size="mini" icon="el-icon-download" @click="exportExcel">导出Excel</el-button>
</div>
<el-table :data="list" v-loading="loading" border size="small">
<el-table-column label="报价日期" prop="create_time" width="160" />
<el-table-column label="甲方名称" prop="client_name" width="160" />
<el-table-column label="成本价(元)" prop="cost_price" width="120">
<template slot-scope="scope">¥{{ scope.row.cost_price }}</template>
</el-table-column>
<el-table-column label="单价(元)" prop="unit_price" width="120">
<template slot-scope="scope">¥{{ scope.row.unit_price }}</template>
</el-table-column>
<el-table-column label="成交价(元)" prop="total_price" width="120">
<template slot-scope="scope">¥{{ scope.row.total_price }}</template>
</el-table-column>
<el-table-column label="报价单号" prop="quote_no" width="150" />
<el-table-column label="状态" prop="quote_status" width="100">
<!-- 报价表格 -->
<el-table
:data="list"
v-loading="loading"
border
size="small"
class="quote-table"
:header-cell-style="headerStyle">
<el-table-column label="报价日期" width="120" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.quote_status === 'accepted' ? 'success' : 'danger'" size="small">
{{ scope.row.quote_status === 'accepted' ? '已接受' : '已拒绝' }}
<span class="date-cell">{{ formatDate(scope.row.create_time) }}</span>
</template>
</el-table-column>
<el-table-column label="甲方信息" min-width="200">
<template slot-scope="scope">
<div class="client-info">
<div class="client-name">{{ scope.row.client_name }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="成本价(元)" width="120" align="right">
<template slot-scope="scope">
<span class="price-cell cost-price">¥{{ formatPrice(scope.row.cost_price) }}</span>
</template>
</el-table-column>
<el-table-column label="单价(元)" width="120" align="right">
<template slot-scope="scope">
<span class="price-cell">¥{{ formatPrice(scope.row.unit_price) }}</span>
</template>
</el-table-column>
<el-table-column label="成交价(元)" width="120" align="right">
<template slot-scope="scope">
<span class="price-cell total-price">¥{{ formatPrice(scope.row.total_price) }}</span>
</template>
</el-table-column>
<el-table-column label="报价单号" width="150" align="center">
<template slot-scope="scope">
<span class="quote-no">{{ scope.row.quote_no }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag
:type="getStatusType(scope.row.quote_status)"
size="small"
effect="dark"
class="status-tag">
{{ getStatusText(scope.row.quote_status) }}
</el-tag>
</template>
</el-table-column>
</el-table>
<el-empty v-if="!loading && !list.length" description="暂无甲方报价" :image-size="80" />
</div>
</template>
@@ -45,9 +84,124 @@ export default {
this.loading = false;
}).catch(() => { this.loading = false; });
},
formatDate(dateStr) {
if (!dateStr) return '-';
const date = new Date(dateStr);
return date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' });
},
formatPrice(price) {
if (!price && price !== 0) return '-';
return Number(price).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
},
getStatusType(status) {
const map = { 'accepted': 'success', 'rejected': 'danger', 'pending': 'warning', 'draft': 'info' };
return map[status] || 'info';
},
getStatusText(status) {
const map = { 'accepted': '已接受', 'rejected': '已拒绝', 'pending': '待处理', 'draft': '草稿' };
return map[status] || status;
},
headerStyle() {
return {
background: '#f5f7fa',
color: '#606266',
fontWeight: 600,
fontSize: '13px'
};
},
exportExcel() {
this.$message.info('导出功能开发中');
}
}
};
</script>
<style scoped>
.client-quote-tab {
padding: 16px;
}
/* 工具栏 */
.tab-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding: 12px 16px;
background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
border-radius: 6px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.tab-title {
font-size: 15px;
font-weight: 600;
color: #303133;
}
/* 表格样式 */
.quote-table {
border-radius: 6px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
>>> .el-table__header-wrapper {
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
/* 日期单元格 */
.date-cell {
font-size: 13px;
color: #606266;
font-weight: 500;
}
/* 甲方信息 */
.client-info {
padding: 4px 0;
}
.client-name {
font-size: 14px;
font-weight: 600;
color: #303133;
line-height: 1.4;
}
/* 价格单元格 */
.price-cell {
font-size: 14px;
font-weight: 600;
color: #f56c6c;
}
.price-cell.cost-price {
color: #909399;
}
.price-cell.total-price {
color: #67c23a;
font-weight: 700;
}
/* 报价单号 */
.quote-no {
font-size: 12px;
color: #909399;
font-family: 'Courier New', monospace;
background: #f5f7fa;
padding: 2px 6px;
border-radius: 3px;
}
/* 状态标签 */
.status-tag {
font-weight: 500;
}
/* 行悬停效果 */
>>> .el-table__row:hover {
background-color: #f5f7fa !important;
}
</style>

View File

@@ -107,7 +107,10 @@
v-for="(quote, qIdx) in quoteMap[mat.materialId]"
:key="qIdx"
class="quote-row"
:class="{ 'is-lowest': isLowestPrice(mat.materialId, qIdx) }">
:class="{
'is-lowest': isLowestPrice(mat.materialId, qIdx),
'is-fastest': isFastestDelivery(mat.materialId, qIdx)
}">
<div class="qr-col supplier-col">
<span class="supplier-name" :title="quote.supplier_name">{{ quote.supplier_name }}</span>
<span v-if="quote.supplier_contact || quote.supplier_phone" class="supplier-contact">
@@ -115,10 +118,11 @@
</span>
</div>
<div class="qr-col price-col">
<span class="price-value">¥{{ formatPrice(quote.unit_price) }}</span>
<span v-if="isLowestPrice(mat.materialId, qIdx)" class="lowest-tag">最低</span>
<span class="price-value" :class="{ 'is-lowest-price': isLowestPrice(mat.materialId, qIdx) }">¥{{ formatPrice(quote.unit_price) }}</span>
</div>
<div class="qr-col delivery-col">
<span class="delivery-value" :class="{ 'is-fastest-delivery': isFastestDelivery(mat.materialId, qIdx) }">{{ quote.delivery_days || '—' }}</span>
</div>
<div class="qr-col delivery-col">{{ quote.delivery_days || '—' }}</div>
<div class="qr-col quote-no-col" :title="quote.quote_no">{{ quote.quote_no }}</div>
<div class="qr-col date-col">{{ formatDate(quote.submit_time) }}</div>
</div>
@@ -320,6 +324,17 @@ export default {
const quotes = this.quoteMap[materialId];
if (!quotes || !quotes.length) return false;
return quoteIndex === 0;
},
isFastestDelivery(materialId, quoteIndex) {
const quotes = this.quoteMap[materialId];
if (!quotes || !quotes.length) return false;
// 找出最小交期
const minDays = Math.min(...quotes.map(q => Number(q.delivery_days) || Infinity));
if (minDays === Infinity) return false;
// 检查当前报价的交期是否等于最小交期
const currentDays = Number(quotes[quoteIndex].delivery_days);
return currentDays === minDays;
}
}
};
@@ -569,6 +584,14 @@ export default {
background: linear-gradient(90deg, #f0f9eb 0%, #e8f5e0 100%);
border-left: 3px solid #67c23a;
}
.quote-row.is-fastest {
background: linear-gradient(90deg, #ecf5ff 0%, #d9ecff 100%);
border-left: 3px solid #409eff;
}
.quote-row.is-lowest.is-fastest {
background: linear-gradient(90deg, #f0f9eb 0%, #e8f5e0 50%, #ecf5ff 100%);
border-left: 3px solid #67c23a;
}
.qr-col {
text-align: center;
@@ -597,19 +620,24 @@ export default {
.price-value {
font-weight: 700;
color: #f56c6c;
color: #606266;
font-size: 14px;
}
.lowest-tag {
display: inline-block;
background: #67c23a;
color: #fff;
font-size: 10px;
padding: 1px 5px;
border-radius: 3px;
margin-left: 4px;
vertical-align: middle;
font-weight: 500;
.price-value.is-lowest-price {
color: #67c23a;
border-bottom: 2px solid #67c23a;
padding-bottom: 2px;
}
.delivery-value {
font-weight: 600;
color: #606266;
font-size: 14px;
}
.delivery-value.is-fastest-delivery {
color: #e6a23c;
border-bottom: 2px solid #e6a23c;
padding-bottom: 2px;
}
.qr-col.delivery-col,

View File

@@ -69,13 +69,6 @@
</template>
</el-table-column>
</el-table>
<!-- 空状态 -->
<el-empty v-if="!loading && !list.length" description="暂无供应商报价" :image-size="80">
<template #description>
<span class="empty-text">暂无供应商报价记录</span>
</template>
</el-empty>
</div>
</template>
@@ -222,12 +215,6 @@ export default {
font-weight: 500;
}
/* 空状态 */
.empty-text {
color: #909399;
font-size: 14px;
}
/* 行悬停效果 */
>>> .el-table__row:hover {
background-color: #f5f7fa !important;