From 0764bf3a422b703ec7a9b53815ee30c49b13aac8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=88=98=E6=B3=89=E4=BD=B3?= <1107186916@qq.com>
Date: Mon, 9 Nov 2026 18:18:15 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BC=80=E7=A5=A8=E7=94=B3=E8=AF=B7?=
=?UTF-8?q?=E6=8E=A5=E5=85=A5=E6=9A=82=E4=BC=B0=E6=88=90=E6=9C=AC=E4=B8=8E?=
=?UTF-8?q?=E5=86=B2=E9=94=80=E6=98=8E=E7=BB=86=E5=B1=95=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/option/payment/invoiceApplication.js | 1 +
.../payment/invoice-application-form.vue | 67 ++++++++++++++++++-
2 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/src/option/payment/invoiceApplication.js b/src/option/payment/invoiceApplication.js
index fa5ed87..3696382 100644
--- a/src/option/payment/invoiceApplication.js
+++ b/src/option/payment/invoiceApplication.js
@@ -6,6 +6,7 @@ export const invoiceApplicationTableColumns = [
{ prop: 'issuerName', label: '开票方', minWidth: 150 },
{ prop: 'receiverName', label: '受票方', minWidth: 150 },
{ prop: 'invoiceAmount', label: '开票金额', minWidth: 130, money: true },
+ { prop: 'estimatedCost', label: '暂估成本', minWidth: 130, money: true },
{ prop: 'createUserName', label: '创建人', minWidth: 110 },
{ prop: 'createTime', label: '创建时间', minWidth: 170 },
{ prop: 'approvalStatusName', label: '状态', minWidth: 110, status: true },
diff --git a/src/views/payment/invoice-application-form.vue b/src/views/payment/invoice-application-form.vue
index b4897ea..83b8138 100644
--- a/src/views/payment/invoice-application-form.vue
+++ b/src/views/payment/invoice-application-form.vue
@@ -86,6 +86,27 @@
/>
+
+
+
+ %
+
+
+
+
+
+
+
+
{{ formatMoney(row.settlementAmount) }}
+
+ {{ formatMoney(row.historyInvoicedAmount) }}
+
+
+ {{ formatMoney(row.allocatedInvoiceAmount) }}
+
+
+ {{ formatMoney(row.remainingUninvoicedAmount) }}
+
{{ formatMoney(row.availableInvoiceAmount) }}
-
- {{ formatMoney(row.allocatedInvoiceAmount) }}
-
@@ -385,6 +412,10 @@
+
+
+
+
@@ -491,6 +522,7 @@ import { getList as getReceivablePayableDetailList } from '@/api/settlement/rece
import { getDictionary } from '@/api/system/dictbiz';
import { invoiceApplicationDetailColumns } from '@/option/payment/invoiceApplication';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
+import InvoiceWriteOffTable from '@/components/invoice-write-off-table/main.vue';
import { getMkPublicDetail } from '@/api/mk-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
@@ -538,12 +570,15 @@ const emptyForm = () => ({
sheets: [emptySheet()],
attachments: [],
remark: '',
+ // 项目利润率(小数,如0.04表示4%;保存时后端快照并重算暂估成本)
+ profitRate: null,
});
export default {
name: 'InvoiceApplicationForm',
components: {
VehicleAttachmentTable,
+ InvoiceWriteOffTable,
},
data() {
return {
@@ -621,6 +656,24 @@ export default {
0
);
},
+ // 项目利润率百分数展示/输入(后端存小数:0.04 ↔ 4)
+ profitRatePercent() {
+ const rate = Number(this.form.profitRate);
+ if (!Number.isFinite(rate) || rate <= 0) return '';
+ return String(Math.round(rate * 10000) / 100);
+ },
+ // 暂估成本 = 开票不含税金额合计 × 项目利润率(实时计算,后端保存时重算覆盖)
+ estimatedCost() {
+ const rate = Number(this.form.profitRate);
+ if (!Number.isFinite(rate) || rate <= 0) return 0;
+ const amountNoTaxTotal = this.form.sheets.reduce(
+ (sheetTotal, sheet) =>
+ sheetTotal +
+ sheet.lines.reduce((lineTotal, line) => lineTotal + Number(line.amountNoTax || 0), 0),
+ 0
+ );
+ return amountNoTaxTotal * rate;
+ },
detailColumns() {
return [...this.detailBaseColumns, ...this.feeItemColumns];
},
@@ -732,6 +785,13 @@ export default {
this.transportTypeOptions.find(item => String(item.value) === String(value))?.label || value
);
},
+ // 项目利润率输入(百分数),转小数存储:4 → 0.04
+ handleProfitRateInput(value) {
+ let normalized = String(value || '').replace(/[^\d.]/g, '');
+ normalized = normalized.replace(/(\..*)\./g, '$1');
+ const percent = Number(normalized);
+ this.form.profitRate = Number.isFinite(percent) && percent > 0 ? percent / 100 : null;
+ },
invoiceItemNames(categoryName) {
return this.invoiceItems.filter(item => item.categoryName === categoryName);
},
@@ -1173,6 +1233,7 @@ export default {
contactName: this.form.contactName,
contactPhone: this.form.contactPhone,
email: this.form.email,
+ profitRate: Number(this.form.profitRate) > 0 ? Number(this.form.profitRate) : null,
attachmentsJson: JSON.stringify(this.form.attachments || []),
remark: this.form.remark,
settlements: this.form.settlements.map(item => ({