feat(approval): 新增业务审批流程及配置管理

- 新增审批配置主子表(biz_approval_config / biz_approval_config_user),支持或签
- 5 个业务模块接入审批: 采购订单/客户报价/供应商报价/发货单/订单异议
- 统一审批动作接口(提交/通过/驳回),status=10 表示审批中
- 新增"待我审批"聚合页面,按业务类型筛选
- 修复 logback 写本地路径报错,去除文件 appender
- 修复 Redis SSL 配置在 Spring Boot 4 下需对象格式
- 补齐部分业务表缺失的 update_by/update_time 审计列

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 11:14:46 +08:00
parent 0180388a2f
commit 7ffc140cf8
69 changed files with 1563 additions and 446 deletions

View File

@@ -120,6 +120,12 @@
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"
@@ -185,7 +191,7 @@
</el-row>
<el-divider content-position="left">
<span style="font-weight:700;color:#1a2c4e">报价明细</span>
<span style="font-weight:700;color:#333333">报价明细</span>
<el-tooltip content="选择RFQ后可自动加载物料需求" placement="top">
<i class="el-icon-question" style="margin-left:6px;color:#909399;cursor:pointer"></i>
</el-tooltip>
@@ -372,7 +378,8 @@ import { listQuotation, getQuotation, addQuotation, updateQuotation,
import { listRfq, getRfqItems } from "@/api/bid/rfq";
import { listSupplier } from "@/api/bid/supplier";
import { addDelivery } from "@/api/bid/delivery";
import logoImg from "@/assets/logo/logo.png";
import { submitApproval, approveBiz, rejectBiz } from "@/api/bid/approvalAction";
import logoImg from "@/assets/logo/logo.svg";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
@@ -495,6 +502,20 @@ export default {
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(); });
},
handleApprove(row) {
this.$modal.confirm("确认通过该报价审批?").then(() => approveBiz("QUOTATION", row.quotationId))
.then(() => { this.$modal.msgSuccess("审批通过"); this.getList(); });
},
handleApprovalReject(row) {
this.$prompt("请输入驳回原因", "驳回", { inputPattern: /.+/, inputErrorMessage: "请填写原因" })
.then(({ value }) => rejectBiz("QUOTATION", row.quotationId, value))
.then(() => { this.$modal.msgSuccess("已驳回"); this.getList(); })
.catch(() => {});
},
handleAccept(row) {
this.$modal.confirm("确认采纳此报价?").then(() => acceptQuotation(row.quotationId))
.then(() => { this.$modal.msgSuccess("已采纳"); this.getList(); });
@@ -591,8 +612,8 @@ export default {
} catch(e) { this.$message.error("导出失败:" + e.message); }
finally { this.pdfLoading = false; }
},
statusType(s) { return { draft: "info", submitted: "warning", accepted: "success", rejected: "danger" }[s] || ""; },
statusLabel(s) { return { draft: "草稿", submitted: "已提交", accepted: "已采纳", rejected: "已拒绝" }[s] || s; },
statusType(s) { return { draft: "info", submitted: "warning", "10": "warning", accepted: "success", rejected: "danger" }[s] || ""; },
statusLabel(s) { return { draft: "草稿", submitted: "已提交", "10": "审批中", accepted: "已采纳", rejected: "已拒绝" }[s] || s; },
statusIcon(s) { return { draft: "el-icon-edit-outline", submitted: "el-icon-time", accepted: "el-icon-circle-check", rejected: "el-icon-circle-close" }[s] || "el-icon-document"; }
}
};
@@ -606,7 +627,7 @@ export default {
/* ── 搜索 ── */
.jd-filter-bar {
background: #f5f5f5;
background: #ffffff;
padding: 12px 16px 4px;
border-radius: 2px;
::v-deep .el-form-item {
@@ -677,6 +698,6 @@ export default {
tbody tr:nth-child(even) td { background: #f9fbff; }
}
.amount-cell { color: #e4393c; font-weight: 600; }
.total-cell { font-size: 15px; background: #fff5f5 !important; font-weight: 700; }
.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; }
</style>