Merge remote-tracking branch 'origin/master' into feature/20261019-bfi-all-web
# Conflicts: # src/views/settlement/formal-settlement.vue
This commit is contained in:
@@ -44,7 +44,8 @@
|
||||
reserve-keyword
|
||||
:remote-method="searchCustomers"
|
||||
:loading="customerLoading"
|
||||
placeholder="请选择客商基础档案"
|
||||
placeholder="请选择"
|
||||
@change="syncFeeBearer"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customerOptions"
|
||||
@@ -63,6 +64,7 @@
|
||||
allow-create
|
||||
default-first-option
|
||||
placeholder="请选择或输入"
|
||||
@change="syncFeeBearer"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in receiverOptions"
|
||||
@@ -74,7 +76,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="票面金额" prop="faceAmount">
|
||||
<el-form-item label="票面金额" prop="faceAmount" required>
|
||||
<el-input-number
|
||||
v-model="form.faceAmount"
|
||||
:min="0"
|
||||
@@ -111,17 +113,15 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="可用部门" prop="availableDeptIds">
|
||||
<el-tree-select
|
||||
v-model="form.availableDeptIds"
|
||||
:data="deptTree"
|
||||
:props="deptProps"
|
||||
node-key="id"
|
||||
multiple
|
||||
show-checkbox
|
||||
<el-cascader
|
||||
v-model="availableDeptCascaderValue"
|
||||
:options="businessDeptTreeOptions"
|
||||
:props="deptCascaderProps"
|
||||
placeholder="请选择"
|
||||
filterable
|
||||
clearable
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
placeholder="请选择,默认全部"
|
||||
@change="handleDeptChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -140,17 +140,9 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="费用承担方" prop="feeBearerId">
|
||||
<el-select
|
||||
v-model="form.feeBearerId"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
:remote-method="searchCustomers"
|
||||
:loading="customerLoading"
|
||||
placeholder="请选择客商基础档案"
|
||||
>
|
||||
<el-select v-model="form.feeBearerId" filterable clearable placeholder="请选择">
|
||||
<el-option
|
||||
v-for="item in customerOptions"
|
||||
v-for="item in feeBearerOptions"
|
||||
:key="item.id"
|
||||
:label="customerName(item)"
|
||||
:value="item.id"
|
||||
@@ -245,13 +237,13 @@ const emptyForm = () => ({
|
||||
billNo: '',
|
||||
issuerId: null,
|
||||
receiverName: '',
|
||||
billType: 'issued',
|
||||
billType: '',
|
||||
faceAmount: null,
|
||||
availableBalance: 0,
|
||||
issueDate: '',
|
||||
maturityDate: '',
|
||||
availableDeptIds: ['all'],
|
||||
availableDeptNames: '全部',
|
||||
availableDeptIds: [],
|
||||
availableDeptNames: '',
|
||||
feeBearerId: null,
|
||||
confirmedDiscountRate: null,
|
||||
issuingBank: '',
|
||||
@@ -272,9 +264,17 @@ export default {
|
||||
receiverOptions: [],
|
||||
customerLoading: false,
|
||||
saving: false,
|
||||
deptTree: [],
|
||||
businessDeptTreeOptions: [],
|
||||
deptMap: new Map(),
|
||||
deptProps: { label: 'title', value: 'id', children: 'children' },
|
||||
deptCascaderProps: {
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
children: 'children',
|
||||
multiple: true,
|
||||
checkStrictly: true,
|
||||
emitPath: true,
|
||||
expandTrigger: 'click',
|
||||
},
|
||||
bankOptions: [
|
||||
'中国工商银行',
|
||||
'中国农业银行',
|
||||
@@ -309,7 +309,10 @@ export default {
|
||||
issuerId: [{ required: true, message: '请选择出票单位', trigger: 'change' }],
|
||||
receiverName: [{ required: true, message: '请选择或输入收票单位', trigger: 'change' }],
|
||||
billType: [{ required: true, message: '请选择汇票类型', trigger: 'change' }],
|
||||
faceAmount: [{ validator: this.validateFaceAmount, trigger: 'change' }],
|
||||
faceAmount: [
|
||||
{ required: true, message: '请输入票面金额', trigger: 'change' },
|
||||
{ validator: this.validateFaceAmount, trigger: 'change' },
|
||||
],
|
||||
issueDate: [{ required: true, message: '请选择出票日期', trigger: 'change' }],
|
||||
maturityDate: [{ required: true, validator: this.validateMaturityDate, trigger: 'change' }],
|
||||
availableDeptIds: [{ validator: this.validateDepartments, trigger: 'change' }],
|
||||
@@ -340,6 +343,42 @@ export default {
|
||||
(Number(this.form.faceAmount || 0) * Number(this.form.confirmedDiscountRate || 0)) / 100
|
||||
);
|
||||
},
|
||||
// 可用部门:表单存部门 id,级联多选回显用根到节点的路径
|
||||
availableDeptCascaderValue: {
|
||||
get() {
|
||||
return (this.form.availableDeptIds || [])
|
||||
.filter(id => id !== undefined && id !== null && String(id) !== 'all' && String(id) !== '')
|
||||
.map(id => this.findDeptPath(id, this.businessDeptTreeOptions) || [String(id)]);
|
||||
},
|
||||
set(paths) {
|
||||
const ids = [
|
||||
...new Set(
|
||||
(paths || [])
|
||||
.map(path => {
|
||||
const nodes = Array.isArray(path) ? path.filter(item => item !== undefined && item !== null && item !== '') : [];
|
||||
return nodes.length ? String(nodes.at(-1)) : '';
|
||||
})
|
||||
.filter(Boolean)
|
||||
),
|
||||
];
|
||||
this.form.availableDeptIds = ids;
|
||||
this.form.availableDeptNames = ids
|
||||
.map(id => this.deptMap.get(String(id)))
|
||||
.filter(Boolean)
|
||||
.join('、');
|
||||
},
|
||||
},
|
||||
feeBearerOptions() {
|
||||
const issuer = this.customerOptions.find(item => String(item.id) === String(this.form.issuerId));
|
||||
const receiverName = String(this.form.receiverName || '').trim();
|
||||
const receiver = receiverName
|
||||
? this.customerOptions.find(item => this.customerName(item) === receiverName)
|
||||
: null;
|
||||
return [issuer, receiver].filter(
|
||||
(item, index, rows) =>
|
||||
item && rows.findIndex(row => row && String(row.id) === String(item.id)) === index
|
||||
);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initialize();
|
||||
@@ -352,7 +391,6 @@ export default {
|
||||
async initialize() {
|
||||
await Promise.all([this.loadDepartments(), this.searchCustomers('')]);
|
||||
if (!this.recordId) {
|
||||
this.form.issueDate = this.$dayjs().format('YYYY-MM-DD');
|
||||
return;
|
||||
}
|
||||
const data = this.unwrapData(await api.getDetail(this.recordId));
|
||||
@@ -361,14 +399,20 @@ export default {
|
||||
...data,
|
||||
confirmedDiscountRate: this.normalizeDiscountRate(data.confirmedDiscountRate),
|
||||
bankDiscountReferenceRate: this.normalizeDiscountRate(data.bankDiscountReferenceRate),
|
||||
availableDeptIds: this.parse(data.availableDeptIdsJson),
|
||||
availableDeptIds: this.parse(data.availableDeptIdsJson)
|
||||
.filter(id => String(id) !== 'all')
|
||||
.map(id => String(id)),
|
||||
attachments: this.parse(data.attachmentsJson),
|
||||
};
|
||||
this.usageRecords = data.usageRecords || [];
|
||||
this.receiverOptions = data.receiverName ? [data.receiverName] : [];
|
||||
this.ensureCustomerOption(data.issuerId, data.issuerName);
|
||||
this.ensureCustomerOption(data.feeBearerId, data.feeBearerName);
|
||||
this.handleDeptChange(this.form.availableDeptIds);
|
||||
this.form.availableDeptNames = (this.form.availableDeptIds || [])
|
||||
.map(id => this.deptMap.get(String(id)))
|
||||
.filter(Boolean)
|
||||
.join('、');
|
||||
this.syncFeeBearer();
|
||||
},
|
||||
parse(value) {
|
||||
if (!value) return [];
|
||||
@@ -381,22 +425,52 @@ export default {
|
||||
},
|
||||
async loadDepartments() {
|
||||
const response = await getDeptTree(this.userInfo?.tenantId);
|
||||
const rows = this.unwrapData(response) || [];
|
||||
this.deptTree = [{ id: 'all', title: '全部', children: rows }];
|
||||
this.deptMap = new Map([['all', '全部']]);
|
||||
this.flattenDepartments(rows).forEach(item => this.deptMap.set(String(item.id), item.title));
|
||||
const rows = this.excludeExternalOrganization(this.unwrapData(response) || []);
|
||||
this.businessDeptTreeOptions = this.toDeptCascaderOptions(rows);
|
||||
this.deptMap = new Map();
|
||||
this.flattenDepartments(rows).forEach(item =>
|
||||
this.deptMap.set(String(item.id), item.title || item.deptName || item.name)
|
||||
);
|
||||
},
|
||||
excludeExternalOrganization(list = []) {
|
||||
return list.reduce((result, item) => {
|
||||
const deptName = item.title || item.deptName || item.name;
|
||||
if (String(deptName || '').trim() === '外部组织') return result;
|
||||
result.push({
|
||||
...item,
|
||||
children: item.children?.length
|
||||
? this.excludeExternalOrganization(item.children)
|
||||
: item.children,
|
||||
});
|
||||
return result;
|
||||
}, []);
|
||||
},
|
||||
toDeptCascaderOptions(list = []) {
|
||||
return list.map(item => ({
|
||||
label: item.title || item.deptName || item.name,
|
||||
value: item.id == null || item.id === '' ? '' : String(item.id),
|
||||
children: item.children?.length ? this.toDeptCascaderOptions(item.children) : undefined,
|
||||
}));
|
||||
},
|
||||
flattenDepartments(rows) {
|
||||
return (rows || []).flatMap(item => [item, ...this.flattenDepartments(item.children || [])]);
|
||||
},
|
||||
handleDeptChange(values) {
|
||||
const ids = values || [];
|
||||
this.form.availableDeptNames = ids.some(item => String(item) === 'all')
|
||||
? '全部'
|
||||
: ids
|
||||
.map(item => this.deptMap.get(String(item)))
|
||||
.filter(Boolean)
|
||||
.join('、');
|
||||
findDeptPath(id, tree = [], parents = []) {
|
||||
const target = Array.isArray(id) ? id.at(-1) : id;
|
||||
if (target === undefined || target === null || target === '') return null;
|
||||
for (const node of tree || []) {
|
||||
const path = [...parents, node.value];
|
||||
if (String(node.value) === String(target)) return path;
|
||||
const matched = this.findDeptPath(target, node.children, path);
|
||||
if (matched) return matched;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
syncFeeBearer() {
|
||||
const allowed = this.feeBearerOptions.map(item => String(item.id));
|
||||
if (this.form.feeBearerId && !allowed.includes(String(this.form.feeBearerId))) {
|
||||
this.form.feeBearerId = null;
|
||||
}
|
||||
},
|
||||
async searchCustomers(keyword) {
|
||||
this.customerLoading = true;
|
||||
@@ -545,7 +619,7 @@ export default {
|
||||
.bill-ledger-form-page__form :deep(.el-select),
|
||||
.bill-ledger-form-page__form :deep(.el-input-number),
|
||||
.bill-ledger-form-page__form :deep(.el-date-editor),
|
||||
.bill-ledger-form-page__form :deep(.el-tree-select) {
|
||||
.bill-ledger-form-page__form :deep(.el-cascader) {
|
||||
width: 100%;
|
||||
}
|
||||
.bill-ledger-form-page__form :deep(.el-input-number .el-input__inner) {
|
||||
|
||||
@@ -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 }}
|
||||
@@ -173,7 +227,7 @@
|
||||
<el-input
|
||||
v-model="settlementDialog.keyword"
|
||||
clearable
|
||||
placeholder="3结算单号、项目或合同"
|
||||
placeholder="结算单号、项目或合同"
|
||||
@keyup.enter="loadSettlementCandidates"
|
||||
/>
|
||||
<el-button type="primary" @click="loadSettlementCandidates">查询</el-button>
|
||||
@@ -182,16 +236,32 @@
|
||||
ref="settlementTable"
|
||||
v-loading="settlementDialog.loading"
|
||||
:data="settlementDialog.rows"
|
||||
row-key="id"
|
||||
border
|
||||
@selection-change="settlementDialog.selection = $event"
|
||||
>
|
||||
<el-table-column type="selection" width="52" align="center" />
|
||||
<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 type="selection" width="52" align="center" reserve-selection />
|
||||
<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>
|
||||
@@ -206,7 +276,9 @@
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="settlementDialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmSettlements">确定</el-button>
|
||||
<el-button type="primary" @click="confirmSettlements">
|
||||
确定{{ settlementDialog.selection.length ? `(${settlementDialog.selection.length})` : '' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</basic-container>
|
||||
@@ -437,7 +509,15 @@ export default {
|
||||
},
|
||||
async openSettlementDialog() {
|
||||
this.settlementDialog.visible = true;
|
||||
this.settlementDialog.selection = [];
|
||||
await this.loadSettlementCandidates();
|
||||
await this.$nextTick();
|
||||
const selectedIds = new Set(this.settlementIds.map(id => String(id)));
|
||||
this.settlementDialog.rows.forEach(row => {
|
||||
if (selectedIds.has(String(row.id))) {
|
||||
this.$refs.settlementTable?.toggleRowSelection(row, true);
|
||||
}
|
||||
});
|
||||
},
|
||||
async loadSettlementCandidates() {
|
||||
this.settlementDialog.loading = true;
|
||||
@@ -468,11 +548,21 @@ export default {
|
||||
this.$message.warning('关联结算单必须属于同一项目、组织及收付款方');
|
||||
return;
|
||||
}
|
||||
const previousAmount = new Map(
|
||||
this.form.settlements.map(item => [
|
||||
String(item.formalSettlementId || item.settlementId),
|
||||
item.allocatedInvoiceAmount,
|
||||
])
|
||||
);
|
||||
this.form.settlements = rows.map(item => ({
|
||||
...item,
|
||||
formalSettlementId: item.id,
|
||||
settlementId: item.id,
|
||||
allocatedInvoiceAmount: rows.length === 1 ? Number(item.settlementAmount || 0) : 0,
|
||||
allocatedInvoiceAmount: previousAmount.has(String(item.id))
|
||||
? Number(previousAmount.get(String(item.id)) || 0)
|
||||
: rows.length === 1
|
||||
? Number(item.settlementAmount || 0)
|
||||
: 0,
|
||||
}));
|
||||
this.form.projectName = first.projectName;
|
||||
this.form.deptName = first.deptName;
|
||||
@@ -482,9 +572,8 @@ export default {
|
||||
await this.loadReferenceInformation();
|
||||
this.$refs.formRef?.validateField('settlementIds').catch(() => {});
|
||||
},
|
||||
async selectSettlement(row) {
|
||||
this.settlementDialog.selection = [row];
|
||||
await this.confirmSettlements();
|
||||
selectSettlement(row) {
|
||||
this.$refs.settlementTable?.toggleRowSelection(row);
|
||||
},
|
||||
async loadReferenceInformation() {
|
||||
const data = this.unwrapData(await api.getReferenceInformation(this.settlementIds.join(',')));
|
||||
@@ -617,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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -852,6 +852,8 @@ export default {
|
||||
billOptions: [],
|
||||
billLoading: false,
|
||||
billDialogVisible: false,
|
||||
settlementPayerName: '',
|
||||
settlementPayeeName: '',
|
||||
billQuery: {
|
||||
keyword: '',
|
||||
},
|
||||
@@ -1022,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,
|
||||
@@ -1096,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)
|
||||
@@ -1106,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)
|
||||
@@ -1119,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)
|
||||
@@ -1221,8 +1229,12 @@ export default {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
if (selected.billType && selected.billType !== 'received') {
|
||||
callback(new Error('汇票付款仅可选择收票类型的汇票'));
|
||||
if (
|
||||
selected.billType &&
|
||||
selected.billType !== 'received' &&
|
||||
!this.billMatchesSettlementParties(selected)
|
||||
) {
|
||||
callback(new Error('汇票付款仅可选择收票类型,或出票单位与收票单位均为当前结算收付款方的汇票'));
|
||||
return;
|
||||
}
|
||||
if (selected.maturityDate) {
|
||||
@@ -1541,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;
|
||||
@@ -1574,12 +1600,13 @@ 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)
|
||||
),
|
||||
});
|
||||
this.rememberSettlementParties(first.payerName, first.payeeName);
|
||||
this.paymentRecords = rows.flatMap(item =>
|
||||
(item.paymentRecords || item.paymentApplications || []).map(record => ({
|
||||
...record,
|
||||
@@ -1667,7 +1694,11 @@ export default {
|
||||
? 0
|
||||
: Number(row.payableAmount || 0);
|
||||
return {
|
||||
id: row.preSettlementId || (isPre ? row.settlementId : null) || row.settlementId || row.id,
|
||||
id:
|
||||
row.preSettlementId ||
|
||||
(isPre ? row.settlementId : null) ||
|
||||
row.settlementId ||
|
||||
(row.paymentNo ? null : row.id),
|
||||
settlementNo: row.preSettlementNo || row.formalSettlementNo || row.settlementNo || '',
|
||||
referenceType: isPre ? 'pre' : 'formal',
|
||||
settlementAmount: Number(Number(settlementAmount || 0).toFixed(2)),
|
||||
@@ -1827,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, {
|
||||
@@ -1865,9 +1898,10 @@ export default {
|
||||
settlementAmount: Number(settlementAmount.toFixed(2)),
|
||||
payableAmount: Number(payableAmount.toFixed(2)),
|
||||
billType: '',
|
||||
paymentRatio,
|
||||
paymentRatio: headerPaymentRatio,
|
||||
appliedAmount: headerAppliedAmount,
|
||||
});
|
||||
this.rememberSettlementParties(first.payerName, first.payeeName);
|
||||
this.paymentRecords = [];
|
||||
this.clearReceiptAccount();
|
||||
await this.fillBillTypeFromContract(first.contractId, true);
|
||||
@@ -2063,12 +2097,31 @@ export default {
|
||||
},
|
||||
resolveAttachmentMaterial(file, materials = Object.values(ATTACHMENT_MATERIALS)) {
|
||||
if (!this.attachmentFileUrl(file)) return null;
|
||||
const typeMatched = (materials || []).find(
|
||||
material => file.attachmentType === MATERIAL_TYPE_MAP[material.key]
|
||||
);
|
||||
const typeText = String(file.attachmentType || file.type || '')
|
||||
.trim()
|
||||
.toLocaleLowerCase();
|
||||
const typeMatched = (materials || []).find(material => {
|
||||
if (file.attachmentType === MATERIAL_TYPE_MAP[material.key]) return true;
|
||||
if (!typeText) return false;
|
||||
const label = String(material.label || '').toLocaleLowerCase();
|
||||
return (
|
||||
typeText === label ||
|
||||
material.keywords.some(keyword => {
|
||||
const normalizedKeyword = String(keyword).toLocaleLowerCase();
|
||||
return normalizedKeyword && typeText.includes(normalizedKeyword);
|
||||
})
|
||||
);
|
||||
});
|
||||
return typeMatched || this.matchAttachmentMaterialByFileName(file, materials);
|
||||
},
|
||||
mergeAutomaticAttachments(files, materials, sourceName, defaultMaterial = null, sourceKey = '') {
|
||||
mergeAutomaticAttachments(
|
||||
files,
|
||||
materials,
|
||||
sourceName,
|
||||
defaultMaterial = null,
|
||||
sourceKey = '',
|
||||
keepUnmatched = false
|
||||
) {
|
||||
const existingUrls = new Set(
|
||||
(this.form.attachments || []).map(file => this.attachmentFileUrl(file)).filter(Boolean)
|
||||
);
|
||||
@@ -2077,16 +2130,20 @@ export default {
|
||||
file,
|
||||
material: this.resolveAttachmentMaterial(file, materials) || defaultMaterial,
|
||||
}))
|
||||
.filter(item => item.material && !existingUrls.has(this.attachmentFileUrl(item.file)))
|
||||
.filter(item => {
|
||||
const url = this.attachmentFileUrl(item.file);
|
||||
return Boolean(url) && !existingUrls.has(url) && (item.material || keepUnmatched);
|
||||
})
|
||||
.map(({ file, material }) => {
|
||||
existingUrls.add(this.attachmentFileUrl(file));
|
||||
const url = this.attachmentFileUrl(file);
|
||||
existingUrls.add(url);
|
||||
return {
|
||||
...file,
|
||||
originalName: this.attachmentFileName(file),
|
||||
name: this.attachmentFileName(file),
|
||||
url: this.attachmentFileUrl(file),
|
||||
link: file.link || this.attachmentFileUrl(file),
|
||||
attachmentType: MATERIAL_TYPE_MAP[material.key],
|
||||
url,
|
||||
link: file.link || url,
|
||||
attachmentType: material ? MATERIAL_TYPE_MAP[material.key] : 'other',
|
||||
description: file.description || `自动取自${sourceName}`,
|
||||
sourceImported: true,
|
||||
sourceKey: sourceKey || undefined,
|
||||
@@ -2119,11 +2176,7 @@ export default {
|
||||
},
|
||||
/** 按当前结算单附件整批同步:先清旧关联,再写入新结算单上传的附件 */
|
||||
syncSettlementAttachments(settlementRows = []) {
|
||||
const settlementMaterials = [
|
||||
ATTACHMENT_MATERIALS.weighingSlip,
|
||||
ATTACHMENT_MATERIALS.entrustOrder,
|
||||
ATTACHMENT_MATERIALS.settlement,
|
||||
];
|
||||
const settlementMaterials = Object.values(ATTACHMENT_MATERIALS);
|
||||
const settlementFiles = (settlementRows || []).flatMap(row => this.parse(row.attachmentsJson));
|
||||
const nextUrlSet = new Set(
|
||||
settlementFiles.map(file => this.attachmentFileUrl(file)).filter(Boolean)
|
||||
@@ -2140,7 +2193,8 @@ export default {
|
||||
settlementMaterials,
|
||||
'结算单',
|
||||
null,
|
||||
'settlement'
|
||||
'settlement',
|
||||
true
|
||||
);
|
||||
this.linkedSettlementAttachmentUrls = imported
|
||||
.map(file => this.attachmentFileUrl(file))
|
||||
@@ -2547,7 +2601,13 @@ export default {
|
||||
try {
|
||||
this.billOptions =
|
||||
this.unwrapData(
|
||||
await billLedgerApi.getAvailableOptions(keyword, this.form.deptId, selectedId)
|
||||
await billLedgerApi.getAvailableOptions(
|
||||
keyword,
|
||||
this.form.deptId,
|
||||
selectedId,
|
||||
this.settlementPayerName,
|
||||
this.settlementPayeeName
|
||||
)
|
||||
) || [];
|
||||
} finally {
|
||||
this.billLoading = false;
|
||||
@@ -2569,7 +2629,9 @@ export default {
|
||||
this.billPage.size,
|
||||
String(this.billQuery.keyword || '').trim() || undefined,
|
||||
this.form.deptId,
|
||||
this.form.billLedgerId
|
||||
this.form.billLedgerId,
|
||||
this.settlementPayerName,
|
||||
this.settlementPayeeName
|
||||
);
|
||||
const data = this.unwrapData(response) || {};
|
||||
this.billRows = data.records || [];
|
||||
@@ -2590,9 +2652,27 @@ export default {
|
||||
this.billPage.current = 1;
|
||||
this.loadBillPage();
|
||||
},
|
||||
rememberSettlementParties(payerName, payeeName) {
|
||||
this.settlementPayerName = String(payerName || '').trim();
|
||||
this.settlementPayeeName = String(payeeName || '').trim();
|
||||
},
|
||||
billMatchesSettlementParties(row) {
|
||||
const issuer = String(row?.issuerName || '').trim();
|
||||
const receiver = String(row?.receiverName || '').trim();
|
||||
const payer = this.settlementPayerName;
|
||||
const payee = this.settlementPayeeName;
|
||||
if (!issuer || !receiver || !payer || !payee) return false;
|
||||
return (
|
||||
(issuer === payer && receiver === payee) || (issuer === payee && receiver === payer)
|
||||
);
|
||||
},
|
||||
selectBill(row) {
|
||||
if (row?.billType && row.billType !== 'received') {
|
||||
ElMessage.warning('汇票付款仅可选择收票类型的汇票');
|
||||
if (
|
||||
row?.billType &&
|
||||
row.billType !== 'received' &&
|
||||
!this.billMatchesSettlementParties(row)
|
||||
) {
|
||||
ElMessage.warning('汇票付款仅可选择收票类型,或出票单位与收票单位均为当前结算收付款方的汇票');
|
||||
return;
|
||||
}
|
||||
if (row?.maturityDate) {
|
||||
@@ -2848,6 +2928,7 @@ export default {
|
||||
payerName: row.payerName,
|
||||
payeeName: '',
|
||||
});
|
||||
this.rememberSettlementParties(row.payerName, row.payeeName);
|
||||
this.referenceVisible = false;
|
||||
this.refreshReferenceValidation();
|
||||
const detail = this.unwrapData(detailResponse);
|
||||
@@ -2930,6 +3011,7 @@ export default {
|
||||
payerName: row.payerName,
|
||||
payeeName: '',
|
||||
});
|
||||
this.rememberSettlementParties(row.payerName, row.payeeName);
|
||||
this.referenceVisible = false;
|
||||
this.refreshReferenceValidation();
|
||||
const detail = this.unwrapData(detailResponse);
|
||||
@@ -3014,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
|
||||
@@ -3042,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;
|
||||
@@ -3054,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);
|
||||
@@ -3068,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),
|
||||
@@ -3080,23 +3182,21 @@ 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();
|
||||
const {
|
||||
id,
|
||||
paymentType,
|
||||
@@ -3133,13 +3233,34 @@ export default {
|
||||
paymentType === 'progress_advance' ||
|
||||
(this.referenceRows.length > 0 &&
|
||||
this.referenceRows.every(item => item.referenceType === 'pre'));
|
||||
// 进度预付 / 仅预结算引用:强制不传正式结算单 ID,并兜底恢复预结算单 ID
|
||||
const resolvedPreSettlementId =
|
||||
preSettlementId ||
|
||||
preSettlementIds?.[0] ||
|
||||
(usePreSettlementOnly ? settlementId : null) ||
|
||||
null;
|
||||
const resolvedPreSettlementIds =
|
||||
preSettlementIds?.length > 0
|
||||
? preSettlementIds
|
||||
: resolvedPreSettlementId
|
||||
? [resolvedPreSettlementId]
|
||||
: [];
|
||||
const preSettlementNo = usePreSettlementOnly
|
||||
? this.form.preSettlementNo ||
|
||||
(this.referenceRows || [])
|
||||
.filter(item => item.referenceType === 'pre')
|
||||
.map(item => item.settlementNo)
|
||||
.filter(Boolean)
|
||||
.join('、')
|
||||
: this.form.preSettlementNo;
|
||||
return {
|
||||
id,
|
||||
paymentType,
|
||||
settlementId: usePreSettlementOnly ? null : settlementId,
|
||||
settlementIds: usePreSettlementOnly ? [] : settlementIds,
|
||||
preSettlementId,
|
||||
preSettlementIds,
|
||||
preSettlementId: usePreSettlementOnly ? resolvedPreSettlementId : preSettlementId,
|
||||
preSettlementIds: usePreSettlementOnly ? resolvedPreSettlementIds : preSettlementIds,
|
||||
preSettlementNo,
|
||||
projectId,
|
||||
projectName,
|
||||
deptId,
|
||||
@@ -3228,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();
|
||||
|
||||
@@ -302,7 +302,10 @@ export default {
|
||||
);
|
||||
},
|
||||
flowRemaining(flow) {
|
||||
return Math.max(Number(flow.unclaimedAmount || 0) - Number(flow.claimedAmount || 0), 0);
|
||||
const unclaimed = Number(flow.unclaimedAmount || 0);
|
||||
const receipt = Number(flow.receiptAmount || 0);
|
||||
const ceiling = unclaimed > 0 && receipt > 0 ? Math.min(unclaimed, receipt) : unclaimed || receipt;
|
||||
return Math.max(ceiling - Number(flow.claimedAmount || 0), 0);
|
||||
},
|
||||
maxAllocation(row) {
|
||||
const current = Number(row.settlement.allocations?.[row.flow.id] || 0);
|
||||
|
||||
@@ -252,10 +252,11 @@ export default {
|
||||
);
|
||||
},
|
||||
claimableAmount() {
|
||||
return Math.max(
|
||||
Number(this.form.unclaimedAmount || 0) - Number(this.form.claimedAmount || 0),
|
||||
0
|
||||
);
|
||||
const unclaimed = Number(this.form.unclaimedAmount || 0);
|
||||
const receipt = Number(this.form.receiptAmount || 0);
|
||||
const ceiling =
|
||||
unclaimed > 0 && receipt > 0 ? Math.min(unclaimed, receipt) : unclaimed || receipt;
|
||||
return Math.max(ceiling - Number(this.form.claimedAmount || 0), 0);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
@@ -274,14 +275,21 @@ export default {
|
||||
}
|
||||
const data = this.unwrapData(await api.getDetail(this.flowId));
|
||||
const userInfo = this.$store.getters.userInfo || {};
|
||||
// 部分认领继续认领:预填本流水历史关联且仍有剩余可认领金额的结算单
|
||||
const relatedSettlements = (data?.relatedSettlements || []).map(item => ({
|
||||
...item,
|
||||
formalSettlementId: item.id,
|
||||
settlementId: item.id,
|
||||
allocatedReceiptAmount: 0,
|
||||
}));
|
||||
this.form = {
|
||||
...emptyForm(),
|
||||
...data,
|
||||
claimerName: userInfo.realName || userInfo.userName || data.claimerName || '',
|
||||
claimerDeptName: userInfo.deptName || userInfo.dept_name || data.claimerDeptName || '',
|
||||
claimDate: this.$dayjs().format('YYYY-MM-DD'),
|
||||
settlementIds: [],
|
||||
settlements: [],
|
||||
settlementIds: relatedSettlements.map(item => item.formalSettlementId),
|
||||
settlements: relatedSettlements,
|
||||
attachments: [],
|
||||
};
|
||||
},
|
||||
@@ -347,7 +355,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
if (this.allocatedTotal > this.claimableAmount + 0.001) {
|
||||
this.$message.warning('累计认领金额不能超过公告未认领金额(剩余可认领金额)');
|
||||
this.$message.warning('累计认领金额不能超过剩余可认领金额');
|
||||
return;
|
||||
}
|
||||
for (const row of this.form.settlements)
|
||||
|
||||
Reference in New Issue
Block a user