🐛 修复收票付款与结算费用选择框长文本展示

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-21 11:53:56 +08:00
parent 8d25e186b1
commit 1c798046fd
3 changed files with 227 additions and 90 deletions
+102 -24
View File
@@ -16,13 +16,22 @@
<el-row :gutter="32">
<el-col :span="6">
<el-form-item label="发票号码" prop="invoiceNo">
<el-input v-model="form.invoiceNo" readonly placeholder="请选择金蝶票据池发票">
<template v-if="!readonly" #append>
<el-tooltip content="查询金蝶票据池" placement="top">
<el-button :icon="Search" @click="openInvoiceDialog" />
</el-tooltip>
</template>
</el-input>
<el-tooltip
:content="form.invoiceNo"
:disabled="!form.invoiceNo"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.invoiceNo" readonly placeholder="请选择金蝶票据池发票">
<template v-if="!readonly" #append>
<el-tooltip content="查询金蝶票据池" placement="top">
<el-button :icon="Search" @click="openInvoiceDialog" />
</el-tooltip>
</template>
</el-input>
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
@@ -32,7 +41,16 @@
</el-col>
<el-col :span="6">
<el-form-item label="发票类型">
<el-input v-model="form.invoiceType" disabled placeholder="从金蝶票据池带出" />
<el-tooltip
:content="form.invoiceType"
:disabled="!form.invoiceType"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.invoiceType" disabled placeholder="从金蝶票据池带出" />
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
@@ -64,23 +82,54 @@
</el-col>
<el-col :span="6">
<el-form-item label="受票单位">
<el-input v-model="form.receiverName" disabled placeholder="从金蝶票据池带出" />
<el-tooltip
:content="form.receiverName"
:disabled="!form.receiverName"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.receiverName" disabled placeholder="从金蝶票据池带出" />
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="开票单位">
<el-input v-model="form.issuerName" disabled placeholder="从金蝶票据池带出" />
<el-tooltip
:content="form.issuerName"
:disabled="!form.issuerName"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.issuerName" disabled placeholder="从金蝶票据池带出" />
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="关联结算单" prop="settlementIds">
<el-input :model-value="settlementLabel" readonly placeholder="请选择应付正式结算单">
<template v-if="!readonly" #append>
<el-tooltip content="选择付款结算单" placement="top">
<el-button :icon="Search" @click="openSettlementDialog" />
</el-tooltip>
</template>
</el-input>
<el-tooltip
:content="settlementLabel"
:disabled="!settlementLabel"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input
:model-value="settlementLabel"
readonly
placeholder="请选择应付正式结算单"
>
<template v-if="!readonly" #append>
<el-tooltip content="选择付款结算单" placement="top">
<el-button :icon="Search" @click="openSettlementDialog" />
</el-tooltip>
</template>
</el-input>
</div>
</el-tooltip>
</el-form-item>
</el-col>
</el-row>
@@ -89,7 +138,12 @@
<section-card title="结算信息">
<el-table :data="form.settlements" border>
<el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column label="结算单号" min-width="180" align="center">
<el-table-column
label="结算单号"
min-width="180"
align="center"
show-overflow-tooltip
>
<template #default="{ row }">
<el-link type="primary" @click="openSettlementDetail(row)">
{{ row.formalSettlementNo }}
@@ -187,12 +241,27 @@
@selection-change="settlementDialog.selection = $event"
>
<el-table-column type="selection" width="52" align="center" reserve-selection />
<el-table-column prop="formalSettlementNo" label="结算单号" min-width="170" />
<el-table-column prop="projectName" label="所属项目" min-width="150" />
<el-table-column prop="deptName" label="所属组织" min-width="150" />
<el-table-column prop="contractNo" label="合同编号" min-width="150" />
<el-table-column prop="payerName" label="付款方" min-width="150" />
<el-table-column prop="payeeName" label="收款方" min-width="150" />
<el-table-column
prop="formalSettlementNo"
label="结算单号"
min-width="170"
show-overflow-tooltip
/>
<el-table-column
prop="projectName"
label="所属项目"
min-width="150"
show-overflow-tooltip
/>
<el-table-column prop="deptName" label="所属组织" min-width="150" show-overflow-tooltip />
<el-table-column
prop="contractNo"
label="合同编号"
min-width="150"
show-overflow-tooltip
/>
<el-table-column prop="payerName" label="付款方" min-width="150" show-overflow-tooltip />
<el-table-column prop="payeeName" label="收款方" min-width="150" show-overflow-tooltip />
<el-table-column label="结算总金额" min-width="140" align="right">
<template #default="{ row }">{{ formatMoney(row.settlementAmount) }}</template>
</el-table-column>
@@ -637,6 +706,15 @@ export default {
.receipt-form-page__form :deep(.el-input-number) {
width: 100%;
}
.receipt-form-page__overflow-trigger {
display: block;
width: 100%;
min-width: 0;
}
.receipt-form-page__form :deep(.el-tooltip__trigger:not(.el-select__wrapper)) {
display: block;
width: 100%;
}
.receipt-form-page__remark :deep(.el-form-item__content) {
margin-left: 0 !important;
}
+86 -40
View File
@@ -121,7 +121,7 @@
><div class="payment-form-page__percentage-input">
<el-input-number
v-model="form.paymentRatio"
:disabled="readonly || multipleSettlementRows"
:disabled="readonly"
:min="0"
:max="100"
:precision="2"
@@ -134,7 +134,7 @@
><el-form-item label="申请付款金额" prop="appliedAmount"
><el-input-number
v-model="form.appliedAmount"
:disabled="readonly || multipleSettlementRows"
:disabled="readonly"
:min="0"
:precision="2"
:step="0.01"
@@ -1024,8 +1024,12 @@ export default {
},
settlementRows() {
if (this.referenceRows.length > 1) {
// 多结算单:行内比例/金额独立维护,不回落到表头比例(表头与结算信息不关联)
return this.referenceRows.map(item => {
const paymentRatio = item.paymentRatio ?? this.form.paymentRatio;
const paymentRatio =
item.paymentRatio === undefined || item.paymentRatio === null || item.paymentRatio === ''
? 0
: Number(item.paymentRatio);
const appliedAmount = Number(item.appliedAmount || 0);
return {
...item,
@@ -1098,7 +1102,8 @@ export default {
},
'form.paymentRatio'(value) {
this.checkContractPaymentRatio(value);
if (this.amountSyncing || this.multipleSettlementRows || !this.paymentAmountBase) return;
// 上方比例仅用于反算申请付款金额,不联动结算信息列表
if (this.amountSyncing || !this.paymentAmountBase) return;
this.amountSyncing = true;
this.form.appliedAmount = Number(
((this.paymentAmountBase * Number(value || 0)) / 100).toFixed(2)
@@ -1108,7 +1113,8 @@ export default {
});
},
'form.appliedAmount'(value) {
if (this.amountSyncing || this.multipleSettlementRows || !this.paymentAmountBase) return;
// 上方申请付款金额反算比例,不联动结算信息列表
if (this.amountSyncing || !this.paymentAmountBase) return;
this.amountSyncing = true;
this.form.paymentRatio = Number(
((Number(value || 0) / this.paymentAmountBase) * 100).toFixed(2)
@@ -1121,11 +1127,11 @@ export default {
if (
this.amountSyncing ||
this.form.paymentType === 'project_advance' ||
this.multipleSettlementRows ||
!this.paymentAmountBase
) {
return;
}
// 结算金额变化时按上方比例重算申请付款金额,仍不联动结算信息明细
this.amountSyncing = true;
this.form.appliedAmount = Number(
((this.paymentAmountBase * Number(this.form.paymentRatio || 0)) / 100).toFixed(2)
@@ -1547,13 +1553,27 @@ export default {
(total, item) => total + Number(item.payableAmount || 0),
0
);
const appliedAmount = referenceRows.reduce(
const multiple = referenceRows.length > 1;
// 多结算单:表头比例/申请金额独立;单结算单:沿用行金额或按比例计算
const paymentRatio = Number(this.form.paymentRatio || 0);
const rowsAppliedTotal = referenceRows.reduce(
(total, item) => total + Number(item.appliedAmount || 0),
0
);
const paymentRatio = settlementAmount
? Number(((appliedAmount / settlementAmount) * 100).toFixed(2))
: 0;
const headerAppliedAmount = multiple
? Number(((settlementAmount * paymentRatio) / 100).toFixed(2))
: Number(
(
rowsAppliedTotal > 0
? rowsAppliedTotal
: (payableAmount * paymentRatio) / 100
).toFixed(2)
);
const headerPaymentRatio = multiple
? paymentRatio
: settlementAmount
? Number(((headerAppliedAmount / settlementAmount) * 100).toFixed(2))
: paymentRatio;
const settlementIds = rows.map(item => item.settlementId || item.id).filter(Boolean);
this.amountSyncing = true;
this.referenceRows = referenceRows;
@@ -1580,8 +1600,8 @@ export default {
settlementAmount: Number(settlementAmount.toFixed(2)),
payableAmount: Number(payableAmount.toFixed(2)),
billType: '',
paymentRatio,
appliedAmount: Number(appliedAmount.toFixed(2)),
paymentRatio: headerPaymentRatio,
appliedAmount: headerAppliedAmount,
invoices: rows.flatMap(item =>
this.createInvoiceRows(item.invoices || [], item.formalSettlementNo || item.settlementNo)
),
@@ -1838,19 +1858,21 @@ export default {
(total, item) => total + Number(item.payableAmount || 0),
0
);
const appliedAmount = this.referenceRows.reduce(
const multiple = this.referenceRows.length > 1;
const paymentRatio = Number(this.form.paymentRatio || 0);
const rowsAppliedTotal = this.referenceRows.reduce(
(total, item) => total + Number(item.appliedAmount || 0),
0
);
const multiple = this.referenceRows.length > 1;
const paymentRatio = multiple
? settlementAmount
? Number(((appliedAmount / settlementAmount) * 100).toFixed(2))
: 0
: Number(this.form.paymentRatio || 0);
// 多结算单:表头申请金额只由上方比例计算;单结算单仍按可付款金额×比例
const headerAppliedAmount = multiple
? Number(appliedAmount.toFixed(2))
? Number(((settlementAmount * paymentRatio) / 100).toFixed(2))
: Number(((payableAmount * paymentRatio) / 100).toFixed(2));
const headerPaymentRatio = multiple
? paymentRatio
: settlementAmount && rowsAppliedTotal > 0
? Number(((rowsAppliedTotal / settlementAmount) * 100).toFixed(2))
: paymentRatio;
// 尾款付款场景下选择预付结算单时保留尾款付款类型,不强制改为进度预付
this.amountSyncing = true;
Object.assign(this.form, {
@@ -1876,7 +1898,7 @@ export default {
settlementAmount: Number(settlementAmount.toFixed(2)),
payableAmount: Number(payableAmount.toFixed(2)),
billType: '',
paymentRatio,
paymentRatio: headerPaymentRatio,
appliedAmount: headerAppliedAmount,
});
this.rememberSettlementParties(first.payerName, first.payeeName);
@@ -3074,19 +3096,16 @@ export default {
if (settlementAmount <= 0) return 100;
return Number(Math.min(100, (payableAmount / settlementAmount) * 100).toFixed(2));
},
/**
* 多结算单行金额规范化:仅在行内反算比例,不使用表头比例灌入(表头与结算信息不关联)。
*/
seedMultipleRowPayments(rows = []) {
if (rows.length <= 1) return;
const ratio = Number(this.form.paymentRatio || 0);
rows.forEach(item => {
const settlementAmount = Number(item.settlementAmount || 0);
const payableAmount = Number(item.payableAmount || 0);
const hasRatio =
item.paymentRatio !== null && item.paymentRatio !== undefined && item.paymentRatio !== '';
if (hasRatio) return;
let applied = Number(item.appliedAmount || 0);
if (applied <= 0 && ratio > 0) {
applied = Number(((settlementAmount * ratio) / 100).toFixed(2));
}
if (!Number.isFinite(applied) || applied < 0) applied = 0;
if (applied > payableAmount) applied = Number(payableAmount.toFixed(2));
item.appliedAmount = Number(applied.toFixed(2));
item.paymentRatio = settlementAmount
@@ -3102,6 +3121,25 @@ export default {
item.settlementNo === row.settlementNo
);
},
/** 结算信息付款金额合计 */
settlementRowsAppliedTotal(rows = this.referenceRows) {
return (rows || []).reduce((total, item) => total + Number(item.appliedAmount || 0), 0);
},
/** 结算信息合计不得超过上方申请付款金额 */
ensureSettlementAppliedWithinHeader(showWarning = true) {
if (!this.multipleSettlementRows) return true;
const headerApplied = Number(this.form.appliedAmount || 0);
const rowsTotal = Number(this.settlementRowsAppliedTotal().toFixed(2));
if (rowsTotal - headerApplied > 1e-8) {
if (showWarning) {
this.$message.warning(
`结算信息付款金额合计(${rowsTotal.toFixed(2)})不能大于申请付款金额(${headerApplied.toFixed(2)})`
);
}
return false;
}
return true;
},
handleRowPaymentRatioChange(row, value) {
const target = this.findReferenceRow(row);
if (!target) return;
@@ -3114,7 +3152,9 @@ export default {
target.paymentRatio = settlementAmount
? Number(((applied / settlementAmount) * 100).toFixed(2))
: Number(ratio.toFixed(2));
this.syncHeaderPaymentFromRows();
// 仅刷新结算金额/可付款金额合计,不回写表头申请金额与比例
this.syncHeaderSettlementTotalsFromRows();
this.ensureSettlementAppliedWithinHeader(true);
},
handleRowAppliedAmountChange(row, value) {
const target = this.findReferenceRow(row);
@@ -3128,9 +3168,11 @@ export default {
target.paymentRatio = settlementAmount
? Number(((target.appliedAmount / settlementAmount) * 100).toFixed(2))
: 0;
this.syncHeaderPaymentFromRows();
this.syncHeaderSettlementTotalsFromRows();
this.ensureSettlementAppliedWithinHeader(true);
},
syncHeaderPaymentFromRows() {
/** 多结算单时仅同步结算金额/可付款金额合计,申请付款金额与比例由上方独立维护 */
syncHeaderSettlementTotalsFromRows() {
if (this.referenceRows.length <= 1) return;
const settlementAmount = this.referenceRows.reduce(
(total, item) => total + Number(item.settlementAmount || 0),
@@ -3140,22 +3182,18 @@ export default {
(total, item) => total + Number(item.payableAmount || 0),
0
);
const appliedAmount = this.referenceRows.reduce(
(total, item) => total + Number(item.appliedAmount || 0),
0
);
this.amountSyncing = true;
this.form.settlementAmount = Number(settlementAmount.toFixed(2));
this.form.payableAmount = Number(payableAmount.toFixed(2));
this.form.appliedAmount = Number(appliedAmount.toFixed(2));
this.form.paymentRatio = settlementAmount
? Number(((appliedAmount / settlementAmount) * 100).toFixed(2))
: 0;
this.$nextTick(() => {
this.amountSyncing = false;
this.$refs.formRef?.validateField?.(['settlementAmount', 'paymentRatio', 'appliedAmount']);
this.$refs.formRef?.validateField?.(['settlementAmount', 'appliedAmount']);
});
},
/** @deprecated 兼容旧调用名,行为见 syncHeaderSettlementTotalsFromRows */
syncHeaderPaymentFromRows() {
this.syncHeaderSettlementTotalsFromRows();
},
payload() {
// 驳回重提前再清一次:避免历史误存的正式结算单 ID 盖过预结算引用
this.clearFormalReferenceWhenPreOnly();
@@ -3311,6 +3349,14 @@ export default {
ElMessage.warning(`${invalidRow.settlementNo || '结算单'}付款金额不能超过可付款金额`);
return false;
}
const rowsTotal = Number(this.settlementRowsAppliedTotal().toFixed(2));
if (rowsTotal - appliedAmount > 1e-8) {
this.clearMessages();
ElMessage.warning(
`结算信息付款金额合计(${rowsTotal.toFixed(2)})不能大于申请付款金额(${appliedAmount.toFixed(2)})`
);
return false;
}
}
if (this.form.paymentType === 'project_advance' && !this.form.projectId) {
this.clearMessages();
@@ -451,42 +451,42 @@
:model="updateFeeForm"
:rules="updateFeeRules"
label-position="right"
label-width="auto"
label-width="120px"
class="settlement-detail-page__dialog-form"
>
<el-form-item label="更新范围" prop="contractId">
<el-tooltip
:content="updateContractName"
:disabled="!updateContractName"
placement="top"
:show-after="200"
>
<el-input
:model-value="updateContractName"
class="settlement-detail-page__update-fee-control"
readonly
placeholder="请选择合同"
<div class="settlement-detail-page__update-fee-field">
<el-tooltip
:content="updateContractName"
:disabled="!updateContractName"
placement="top"
:show-after="200"
>
<template #append>
<el-button @click="openUpdateContractDialog">选择</el-button>
</template>
</el-input>
</el-tooltip>
<div class="settlement-detail-page__update-fee-trigger">
<el-input
:model-value="updateContractName"
class="settlement-detail-page__update-fee-control"
readonly
placeholder="请选择合同"
>
<template #append>
<el-button @click="openUpdateContractDialog">选择</el-button>
</template>
</el-input>
</div>
</el-tooltip>
</div>
</el-form-item>
<el-form-item label="合同计费方案" prop="billingPlanId">
<el-tooltip
:content="updateBillingPlanName"
:disabled="!updateBillingPlanName"
placement="top"
:show-after="200"
>
<div class="settlement-detail-page__update-fee-field">
<el-select
v-model="updateFeeForm.billingPlanId"
class="settlement-detail-page__update-fee-control"
clearable
filterable
:disabled="!updateFeeForm.contractId"
placeholder="请选择"
:placeholder="updateFeeForm.contractId ? '请选择' : '请先选择合同'"
:title="updateBillingPlanName || undefined"
>
<el-option
v-for="item in billingPlanOptions"
@@ -496,7 +496,7 @@
:title="item.name"
/>
</el-select>
</el-tooltip>
</div>
</el-form-item>
</el-form>
<template #footer>
@@ -3213,7 +3213,9 @@ export default {
min-width: 0;
}
:deep(.el-tooltip__trigger) {
// 仅作用于外层 tooltip 触发器,排除 el-select 内部下拉用的 .el-select__wrapper
// (后者也带 el-tooltip__trigger;若设为 block 会打断 flex,导致「请选择」与箭头叠在左上角)
:deep(.el-tooltip__trigger:not(.el-select__wrapper)) {
display: block;
width: 100%;
}
@@ -3223,8 +3225,19 @@ export default {
}
}
.settlement-detail-page__update-fee-field,
.settlement-detail-page__update-fee-trigger {
display: block;
width: 100%;
min-width: 0;
}
.settlement-detail-page__update-fee-control {
width: 100%;
:deep(.el-input-group) {
width: 100%;
}
}
.settlement-detail-page__adjust-input {