feat(bid): 优化报价单页面并新增RFQ详情路由

1. 合并规格和型号列为规格型号字段,简化表单布局
2. 调整表格列宽适配页面显示,新增表格横向滚动容器
3. 更新PDF导出表格表头与表单对齐
4. 新增/bid/rfq/detail路由用于跳转RFQ详情页
5. 修正物料数据同步逻辑,统一规格型号赋值
This commit is contained in:
2026-06-05 15:17:49 +08:00
parent ac2422ab8f
commit 5a1d7111cc
3 changed files with 58 additions and 50 deletions

View File

@@ -125,6 +125,20 @@ export const dynamicRoutes = [
}
]
},
{
path: '/bid/rfq/detail',
component: Layout,
hidden: true,
permissions: ['bid:rfq:query'],
children: [
{
path: '',
component: () => import('@/views/bid/rfq/detail'),
name: 'RfqDetail',
meta: { title: '报价请求详情', activeMenu: '/bid/rfq' }
}
]
},
// ── 统计分析 路由 ──
{
path: '/bid/report/dashboard',

View File

@@ -70,9 +70,10 @@
<span><strong>报价明细</strong></span>
<el-button style="float:right" type="primary" size="mini" icon="el-icon-plus" @click="addItem">添加行</el-button>
</div>
<div class="table-scroll-wrap">
<el-table :data="form.items" border size="small">
<el-table-column type="index" width="46" label="#" />
<el-table-column label="物料名称" min-width="200">
<el-table-column label="物料名称" width="200">
<template slot-scope="s">
<el-autocomplete
v-model="s.row.materialName"
@@ -104,57 +105,53 @@
</el-autocomplete>
</template>
</el-table-column>
<el-table-column label="规格" width="120">
<el-table-column label="规格型号" width="150">
<template slot-scope="s">
<el-input v-model="s.row.spec" size="mini" placeholder="规格" />
<el-input v-model="s.row.spec" size="mini" placeholder="规格型号" @change="s.row.modelNo = s.row.spec" />
</template>
</el-table-column>
<el-table-column label="型号" width="120">
<template slot-scope="s">
<el-input v-model="s.row.modelNo" size="mini" placeholder="型号" />
</template>
</el-table-column>
<el-table-column label="单位" width="70">
<el-table-column label="单位" width="60">
<template slot-scope="s">
<el-input v-model="s.row.unit" size="mini" placeholder="单位" />
</template>
</el-table-column>
<el-table-column label="数量" width="130">
<el-table-column label="数量" width="80">
<template slot-scope="s">
<el-input-number v-model="s.row.quantity" :min="0" size="mini" controls-position="right" style="width:100%" @change="calcRow(s.row)" />
</template>
</el-table-column>
<el-table-column label="成本价(元)" width="140">
<el-table-column label="成本价(元)" width="100">
<template slot-scope="s">
<el-input-number v-model="s.row.costPrice" :min="0" :precision="2" size="mini" controls-position="right" style="width:100%" @change="calcRow(s.row)" />
</template>
</el-table-column>
<el-table-column label="报价(元)" width="140">
<el-table-column label="报价(元)" width="100">
<template slot-scope="s">
<el-input-number v-model="s.row.unitPrice" :min="0" :precision="2" size="mini" controls-position="right" style="width:100%" @change="calcRow(s.row)" />
</template>
</el-table-column>
<el-table-column label="金额(元)" width="120" align="right">
<el-table-column label="金额(元)" width="100" align="right">
<template slot-scope="s">
<strong style="color:#409EFF">¥{{ s.row.totalPrice || '0.00' }}</strong>
</template>
</el-table-column>
<el-table-column label="毛利率" width="80" align="center">
<el-table-column label="毛利率" width="70" align="center">
<template slot-scope="s">
<span :style="{ color: marginColor(s.row) }">{{ calcMargin(s.row) }}%</span>
</template>
</el-table-column>
<el-table-column label="交货期(天)" width="90">
<el-table-column label="交货期(天)" width="70">
<template slot-scope="s">
<el-input-number v-model="s.row.deliveryDays" :min="0" size="mini" controls-position="right" style="width:100%" />
</template>
</el-table-column>
<el-table-column label="操作" width="60" align="center">
<el-table-column label="操作" width="50" align="center">
<template slot-scope="s">
<el-button type="text" icon="el-icon-delete" style="color:#f56c6c" @click="removeItem(s.$index)" />
</template>
</el-table-column>
</el-table>
</div>
<div class="total-bar">
<span>合计</span>
@@ -193,14 +190,13 @@
<div class="pdf-section-title">报价明细</div>
<table class="pdf-items-table">
<thead>
<tr><th>#</th><th>物料名称</th><th>规格</th><th>型号</th><th>单位</th><th>数量</th><th>单价()</th><th>金额()</th><th>交货期()</th></tr>
<tr><th>#</th><th>物料名称</th><th>规格型号</th><th>单位</th><th>数量</th><th>单价()</th><th>金额()</th><th>交货期()</th></tr>
</thead>
<tbody>
<tr v-for="(it, ii) in form.items" :key="ii">
<td>{{ ii + 1 }}</td>
<td>{{ it.materialName }}</td>
<td>{{ it.spec || '-' }}</td>
<td>{{ it.modelNo || '-' }}</td>
<td>{{ it.unit }}</td>
<td>{{ it.quantity }}</td>
<td>{{ it.unitPrice }}</td>
@@ -210,7 +206,7 @@
</tbody>
<tfoot>
<tr>
<td colspan="7" style="text-align:right;font-weight:bold;padding:10px 8px">合计金额</td>
<td colspan="6" style="text-align:right;font-weight:bold;padding:10px 8px">合计金额</td>
<td class="amount-cell total-cell" colspan="2">¥{{ grandTotal }}</td>
</tr>
</tfoot>
@@ -310,7 +306,7 @@ export default {
row.materialId = item.materialId;
row.materialName = item.materialName;
row.spec = item.spec || '';
row.modelNo = item.modelNo || item.spec || '';
row.modelNo = item.spec || '';
row.unit = item.unit || '件';
},
onMaterialChange(row) {
@@ -383,14 +379,18 @@ export default {
</script>
<style lang="scss" scoped>
.cq-detail { padding-bottom: 40px; }
.page-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:20px; padding:16px 0; border-bottom:1px solid #f0f2f5; flex-wrap:wrap; gap:10px; }
.cq-detail { overflow: hidden; padding-bottom: 40px; }
.page-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:20px; padding:16px 0; border-bottom:1px solid #f0f2f5; flex-wrap:wrap; gap:10px; overflow:hidden; }
.page-header-left { display:flex; align-items:center; gap:12px; }
.page-header-right { display:flex; gap:10px; }
.page-title { font-size:18px; font-weight:700; color:#1a2c4e; }
.info-card ::v-deep .el-card__body { padding: 20px; }
.total-bar { display:flex; align-items:center; justify-content:flex-end; padding:16px 20px; border-top:1px solid #f0f2f5; background:#fafbfc; }
/* 表格滚动容器 - 窄屏时横向滚动 */
.table-scroll-wrap { overflow-x: auto; }
.table-scroll-wrap >>> .el-table { min-width: 900px; }
/* 物料搜索建议下拉 */
/* 物料搜索下拉样式 - 加宽并优化展示 */
>>> .el-autocomplete-suggestion {

View File

@@ -162,7 +162,7 @@
<div class="items-table-wrap">
<el-table :data="form.items" border size="small" class="items-table">
<el-table-column type="index" width="44" label="#" />
<el-table-column label="物料名称" min-width="200">
<el-table-column label="物料名称" width="200">
<template slot-scope="s">
<el-autocomplete
v-model="s.row.materialName"
@@ -191,52 +191,47 @@
</el-autocomplete>
</template>
</el-table-column>
<el-table-column label="规格" width="120">
<el-table-column label="规格型号" width="150">
<template slot-scope="s">
<el-input v-model="s.row.spec" size="mini" placeholder="规格" />
<el-input v-model="s.row.spec" size="mini" placeholder="规格型号" @change="s.row.modelNo = s.row.spec" />
</template>
</el-table-column>
<el-table-column label="型号" width="120">
<template slot-scope="s">
<el-input v-model="s.row.modelNo" size="mini" placeholder="型号" />
</template>
</el-table-column>
<el-table-column label="单位" width="70">
<el-table-column label="单位" width="60">
<template slot-scope="s">
<el-input v-model="s.row.unit" size="mini" />
</template>
</el-table-column>
<el-table-column label="数量" width="130">
<el-table-column label="数量" width="80">
<template slot-scope="s">
<el-input-number v-model="s.row.quantity" :min="0" size="mini" controls-position="right" style="width:100%" @change="calcRow(s.row)" />
</template>
</el-table-column>
<el-table-column label="成本价(元)" width="140">
<el-table-column label="成本价(元)" width="100">
<template slot-scope="s">
<el-input-number v-model="s.row.costPrice" :min="0" :precision="2" size="mini" controls-position="right" style="width:100%" @change="calcRow(s.row)" />
</template>
</el-table-column>
<el-table-column label="报价(元)" width="140">
<el-table-column label="报价(元)" width="100">
<template slot-scope="s">
<el-input-number v-model="s.row.unitPrice" :min="0" :precision="2" size="mini" controls-position="right" style="width:100%" @change="calcRow(s.row)" />
</template>
</el-table-column>
<el-table-column label="金额(元)" width="120" align="right">
<el-table-column label="金额(元)" width="100" align="right">
<template slot-scope="s">
<strong style="color:#409EFF">¥{{ itemTotal(s.row) }}</strong>
</template>
</el-table-column>
<el-table-column label="毛利率" width="80" align="center">
<el-table-column label="毛利率" width="70" align="center">
<template slot-scope="s">
<span :style="{ color: marginColor(s.row) }">{{ calcMargin(s.row) }}%</span>
</template>
</el-table-column>
<el-table-column label="交期(天)" width="100">
<el-table-column label="交期(天)" width="70">
<template slot-scope="s">
<el-input-number v-model="s.row.deliveryDays" :min="0" size="mini" controls-position="right" style="width:100%" />
</template>
</el-table-column>
<el-table-column label="操作" width="60" align="center" fixed="right">
<el-table-column label="操作" width="50" align="center">
<template slot-scope="s">
<el-button type="text" icon="el-icon-delete" style="color:#f56c6c" @click="form.items.splice(s.$index, 1)" />
</template>
@@ -300,21 +295,20 @@
<div class="section-title">报价明细</div>
<el-table :data="detailData.items || []" border size="small" style="margin-top:12px">
<el-table-column type="index" width="46" label="#" />
<el-table-column label="物料名称" prop="materialName" min-width="140" />
<el-table-column label="规格" prop="spec" width="110" />
<el-table-column label="型号" prop="modelNo" width="100" />
<el-table-column label="单位" prop="unit" width="60" align="center" />
<el-table-column label="数量" prop="quantity" width="80" align="right" />
<el-table-column label="成本价" width="100" align="right">
<el-table-column label="物料名称" prop="materialName" min-width="150" />
<el-table-column label="规格型号" prop="spec" width="130" />
<el-table-column label="单位" prop="unit" width="55" align="center" />
<el-table-column label="数量" prop="quantity" width="70" align="right" />
<el-table-column label="成本价" width="90" align="right">
<template slot-scope="s">¥{{ s.row.costPrice | money }}</template>
</el-table-column>
<el-table-column label="单价" width="110" align="right">
<el-table-column label="单价" width="90" align="right">
<template slot-scope="s">¥{{ s.row.unitPrice | money }}</template>
</el-table-column>
<el-table-column label="金额" width="110" align="right">
<el-table-column label="金额" width="90" align="right">
<template slot-scope="s"><strong style="color:#409EFF">¥{{ s.row.totalPrice | money }}</strong></template>
</el-table-column>
<el-table-column label="交期(天)" prop="deliveryDays" width="80" align="center" />
<el-table-column label="交期(天)" prop="deliveryDays" width="65" align="center" />
</el-table>
<!-- 关联的RFQ列表 -->
@@ -525,7 +519,7 @@ export default {
}).then(res => {
this.detailOpen = false;
this.$modal.msgSuccess("RFQ已创建");
this.$router.push({ path: '/bid/rfq', query: { rfqId: res.data.rfqId, rfqNo: res.data.rfqNo, action: 'edit' } });
this.$router.push({ path: '/bid/rfq/detail', query: { rfqId: res.data.rfqId, rfqNo: res.data.rfqNo, edit: '1' } });
}).catch(() => {});
},
@@ -545,7 +539,7 @@ export default {
},
viewRfqDetail(rfq) {
this.detailOpen = false;
this.$router.push({ path: '/bid/rfq', query: { rfqId: rfq.rfqId, rfqNo: rfq.rfqNo, action: 'edit' } });
this.$router.push({ path: '/bid/rfq/detail', query: { rfqId: rfq.rfqId } });
},
rfqStatusType(s) { return { draft:"info", published:"warning", closed:"", completed:"success" }[s] || ""; },
rfqStatusLabel(s) { return { draft:"草稿", published:"已发布", closed:"已关闭", completed:"已完成" }[s] || s; },
@@ -568,7 +562,7 @@ export default {
row.materialId = item.materialId;
row.materialName = item.materialName;
row.spec = item.spec || '';
row.modelNo = item.modelNo || item.spec || '';
row.modelNo = item.spec || '';
row.unit = item.unit || '件';
},