feat(bid): 完成批量业务优化与功能完善

1.  统一所有表格操作列样式,移除固定宽度避免布局溢出
2.  新增报价单自动编号与脏数据清理功能
3.  优化订单状态筛选与展示逻辑,新增closed状态支持
4.  完善操作日志管理,新增统计分析与详情查看功能
5.  优化报价单流程,调整提交审批逻辑与权限控制
6.  修复客户端订单查询SQL,优化关联查询逻辑
7.  新增报价单提交时自动更新提交时间的功能
This commit is contained in:
2026-06-18 20:17:02 +08:00
parent 7b71822a32
commit 41b2e3e772
31 changed files with 1146 additions and 205 deletions

View File

@@ -72,11 +72,20 @@
<el-col :span="1.5">
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">新建报价</el-button>
</el-col>
<el-col :span="1.5" v-if="!isSupplier">
<el-button type="danger" plain icon="el-icon-delete" size="mini" @click="handleCleanNullQuote">清理无编号数据</el-button>
</el-col>
</el-row>
<!-- 报价列表 -->
<el-table v-loading="loading" :data="list" border stripe>
<el-table-column label="报价单号" prop="quoteNo" width="155" />
<el-table-column label="报价单号" width="155">
<template slot-scope="s">
<span :style="{ color: s.row.quoteNo ? '#333' : '#c0c4cc' }">
{{ s.row.quoteNo || '(待编号)' }}
</span>
</template>
</el-table-column>
<el-table-column label="关联询价单" width="200">
<template slot-scope="s">
<div style="font-weight:600;color:#333">{{ s.row.rfqNo }}</div>
@@ -113,27 +122,42 @@
<span v-else style="color:#c0c4cc;font-size:12px">未提交</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="220" fixed="right">
<el-table-column label="操作" align="center" width="260" fixed="right" class-name="col-ops">
<template slot-scope="s">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(s.row)">查看</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(s.row)"
v-if="s.row.status==='draft'">编辑</el-button>
<el-button size="mini" type="text" style="color:#67C23A" icon="el-icon-upload2"
@click="handleSubmit(s.row)" v-if="s.row.status==='draft'">提交</el-button>
<el-button size="mini" type="text" style="color:#E6A23C" icon="el-icon-s-check"
@click="handleSubmitApproval(s.row)" v-if="s.row.status==='draft' || s.row.status==='submitted'">提交审批</el-button>
<el-button size="mini" type="text" style="color:#67C23A"
@click="handleApprove(s.row)" v-if="s.row.status==='10'">审批通过</el-button>
<el-button size="mini" type="text" style="color:#F56C6C"
@click="handleApprovalReject(s.row)" v-if="s.row.status==='10'">审批驳回</el-button>
<el-button size="mini" type="text" style="color:#67C23A" icon="el-icon-check"
@click="handleAccept(s.row)" v-if="s.row.status==='submitted' && !isSupplier">采纳</el-button>
<el-button size="mini" type="text" style="color:#F56C6C" icon="el-icon-close"
@click="handleReject(s.row)" v-if="s.row.status==='submitted' && !isSupplier">拒绝</el-button>
<el-button size="mini" type="text" style="color:#4A6FA5" icon="el-icon-s-order"
@click="handleCreateDelivery(s.row)" v-if="s.row.status==='accepted'">生成发货单</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" style="color:#f56c6c"
@click="handleDelete(s.row)" v-if="s.row.status==='draft'">删除</el-button>
<!-- 草稿提交审批是唯一送审入口 -->
<template v-if="s.row.status==='draft'">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(s.row)">编辑</el-button>
<el-button size="mini" type="text" style="color:#E6A23C" icon="el-icon-s-check"
@click="handleSubmitApproval(s.row)">提交审批</el-button>
<el-dropdown trigger="click" @command="c => handleDropdown(c, s.row)">
<el-button size="mini" type="text">更多<i class="el-icon-arrow-down el-icon--right" /></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="delete" icon="el-icon-delete">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<!-- 已提交历史遗留允许补交审批 -->
<template v-if="s.row.status==='submitted'">
<el-dropdown trigger="click" @command="c => handleDropdown(c, s.row)">
<el-button size="mini" type="text">更多<i class="el-icon-arrow-down el-icon--right" /></el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="submitApproval" icon="el-icon-s-check">提交审批</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<!-- 审批中审批人操作 -->
<template v-if="s.row.status==='10'">
<el-button size="mini" type="text" style="color:#67C23A" @click="handleApprove(s.row)">审批通过</el-button>
<el-button size="mini" type="text" style="color:#F56C6C" @click="handleApprovalReject(s.row)">审批驳回</el-button>
</template>
<!-- 已采纳生成发货单 -->
<el-button v-if="s.row.status==='accepted'" size="mini" type="text" style="color:#4A6FA5"
icon="el-icon-s-order" @click="handleCreateDelivery(s.row)">生成发货单</el-button>
</template>
</el-table-column>
</el-table>
@@ -273,7 +297,7 @@
<div slot="footer">
<el-button @click="dialogOpen = false">取消</el-button>
<el-button type="success" @click="submitForm('draft')" :loading="saving">保存草稿</el-button>
<el-button type="primary" @click="submitForm('submit')" :loading="submitting">保存并提交</el-button>
<el-button type="primary" @click="submitForm('approval')" :loading="submitting">保存并提交审批</el-button>
</div>
</el-dialog>
@@ -304,12 +328,12 @@
<div class="pdf-company">福安德综合报价系统</div>
<div class="pdf-doc-type">供应商报价单</div>
</div>
<div class="pdf-header-no">{{ detailData.quoteNo }}</div>
<div class="pdf-header-no">{{ detailData.quoteNo || '(待编号)' }}</div>
</div>
<div class="pdf-divider"></div>
<table class="pdf-meta-table">
<tr>
<td class="meta-label">报价单号</td><td class="meta-val">{{ detailData.quoteNo }}</td>
<td class="meta-label">报价单号</td><td class="meta-val">{{ detailData.quoteNo || '(待编号)' }}</td>
<td class="meta-label">供应商</td><td class="meta-val"><strong>{{ detailData.supplierName }}</strong></td>
</tr>
<tr>
@@ -374,7 +398,7 @@
<script>
import { listQuotation, getQuotation, addQuotation, updateQuotation,
submitQuotation, acceptQuotation, rejectQuotation, delQuotation } from "@/api/bid/quotation";
delQuotation, cleanNullQuoteNo } from "@/api/bid/quotation";
import { listRfq, getRfqItems } from "@/api/bid/rfq";
import { listSupplier } from "@/api/bid/supplier";
import { addDelivery } from "@/api/bid/delivery";
@@ -426,6 +450,10 @@ export default {
listSupplier({ pageSize: 200 }).then(r => { this.supplierOptions = r.rows || []; });
}
},
/** keep-alive 缓存激活时自动刷新(解决跨页面审批后状态不更新问题) */
activated() {
this.getList();
},
methods: {
getList() {
this.loading = true;
@@ -451,6 +479,13 @@ export default {
this.dialogTitle = "新建报价单";
this.dialogOpen = true;
},
/** 清理历史遗留的无编号报价单脏数据 */
handleCleanNullQuote() {
this.$modal.confirm("确认清理所有无报价单号的脏数据?此操作不可恢复!", "危险操作", { type: "warning" })
.then(() => cleanNullQuoteNo())
.then(r => { this.$modal.msgSuccess(r.msg || "清理成功"); this.getList(); })
.catch(() => {});
},
handleUpdate(row) {
getQuotation(row.quotationId).then(r => {
this.form = { ...r.data, items: r.data.items || [] };
@@ -498,10 +533,6 @@ export default {
itemTotal(row) {
return ((parseFloat(row.quantity) || 0) * (parseFloat(row.unitPrice) || 0)).toFixed(2);
},
handleSubmit(row) {
this.$modal.confirm("确认提交报价?提交后不可修改").then(() => submitQuotation(row.quotationId))
.then(() => { this.$modal.msgSuccess("提交成功"); this.getList(); });
},
handleSubmitApproval(row) {
this.$modal.confirm("确认提交审批?").then(() => submitApproval("QUOTATION", row.quotationId))
.then(() => { this.$modal.msgSuccess("已提交审批"); this.getList(); });
@@ -516,18 +547,18 @@ export default {
.then(() => { this.$modal.msgSuccess("已驳回"); this.getList(); })
.catch(() => {});
},
handleAccept(row) {
this.$modal.confirm("确认采纳此报价?").then(() => acceptQuotation(row.quotationId))
.then(() => { this.$modal.msgSuccess("已采纳"); this.getList(); });
},
handleReject(row) {
this.$modal.confirm("确认拒绝此报价?").then(() => rejectQuotation(row.quotationId))
.then(() => { this.$modal.msgSuccess("已拒绝"); this.getList(); });
},
handleDelete(row) {
this.$modal.confirm("确认删除?").then(() => delQuotation(row.quotationId))
.then(() => { this.$modal.msgSuccess("删除成功"); this.getList(); });
},
/** 「更多」下拉菜单统一路由 */
handleDropdown(command, row) {
const map = {
submitApproval:() => this.handleSubmitApproval(row),
delete: () => this.handleDelete(row),
};
if (map[command]) map[command]();
},
handleCreateDelivery(row) {
this.$modal.confirm("确认基于此报价单生成发货单?").then(() => {
return getQuotation(row.quotationId);
@@ -572,14 +603,14 @@ export default {
submitForm(mode) {
this.$refs.form.validate(valid => {
if (!valid) return;
if (mode === "submit") this.submitting = true;
if (mode === "approval") this.submitting = true;
else this.saving = true;
const action = this.form.quotationId ? updateQuotation : addQuotation;
action(this.form).then(res => {
const id = (res.data && res.data.quotationId) || this.form.quotationId;
if (mode === "submit" && id) {
return submitQuotation(id).then(() => {
this.$modal.msgSuccess("提交成功");
if (mode === "approval" && id) {
return submitApproval("QUOTATION", id).then(() => {
this.$modal.msgSuccess("提交审批");
this.dialogOpen = false;
this.getList();
});
@@ -700,4 +731,11 @@ export default {
.amount-cell { color: #e4393c; font-weight: 600; }
.total-cell { font-size: 15px; background: #fafafa !important; font-weight: 700; }
.pdf-footer { text-align: right; font-size: 11px; color: #aaa; margin-top: 10px; border-top: 1px solid #f0f2f5; padding-top: 8px; }
/* 操作列:禁止溢出省略,确保所有按钮完整显示 */
::v-deep .col-ops .cell {
overflow: visible !important;
text-overflow: clip !important;
white-space: nowrap;
}
</style>