调整业务模块

This commit is contained in:
2026-09-05 23:26:37 +08:00
parent 3bac9b6472
commit 6a6d10dc79
6 changed files with 437 additions and 138 deletions
+2
View File
@@ -44,3 +44,5 @@ export const applyPayment = data =>
request({ url: `${baseUrl}/apply-payment`, method: 'post', data }); request({ url: `${baseUrl}/apply-payment`, method: 'post', data });
export const applyPayments = data => export const applyPayments = data =>
request({ url: `${baseUrl}/apply-payments`, method: 'post', data }); request({ url: `${baseUrl}/apply-payments`, method: 'post', data });
export const claimInvoices = data =>
request({ url: `${baseUrl}/claim-invoices`, method: 'post', data });
@@ -571,17 +571,17 @@ const buildCarrierContractOptions = contractRows => {
item => String(item.contractCategory || '').trim() === '承运商合同' item => String(item.contractCategory || '').trim() === '承运商合同'
); );
const nameCounts = validContracts.reduce((result, item) => { const nameCounts = validContracts.reduce((result, item) => {
const name = String(item.partyB || '').trim(); const name = String(item.partyA || item.partyAName || '').trim();
if (name) result[name] = (result[name] || 0) + 1; if (name) result[name] = (result[name] || 0) + 1;
return result; return result;
}, {}); }, {});
return validContracts return validContracts
.map(contract => { .map(contract => {
const carrierName = String(contract.partyB || '').trim(); const carrierName = String(contract.partyA || contract.partyAName || '').trim();
if (!contract.id || !carrierName) return null; if (!contract.id || !carrierName) return null;
const identifier = contract.contractName || contract.contractNo || contract.id; const identifier = contract.contractName || contract.contractNo || contract.id;
return { return {
id: contract.partyBId || contract.customerId || '', id: contract.partyAId || contract.partyAUserId || contract.customerId || '',
carrierContractId: contract.id, carrierContractId: contract.id,
carrierName, carrierName,
label: nameCounts[carrierName] > 1 ? `${carrierName}${identifier}` : carrierName, label: nameCounts[carrierName] > 1 ? `${carrierName}${identifier}` : carrierName,
@@ -607,7 +607,11 @@ const syncCarrierOptions = () => {
carrierOptions.value = []; carrierOptions.value = [];
return; return;
} }
const carrierId = customerContract?.partyBId || customerContract?.customerId || ''; const carrierId =
customerContract?.partyBId ||
customerContract?.partyBUserId ||
customerContract?.customerId ||
'';
carrierOptions.value = [{ id: carrierId, carrierName, label: carrierName, value: carrierName }]; carrierOptions.value = [{ id: carrierId, carrierName, label: carrierName, value: carrierName }];
form.carrierId = carrierId; form.carrierId = carrierId;
form.carrierIds = carrierId ? [carrierId] : []; form.carrierIds = carrierId ? [carrierId] : [];
@@ -5413,8 +5413,8 @@ export default {
} }
}, },
fillSelfOperatedCarrierFromContract(contract = {}) { fillSelfOperatedCarrierFromContract(contract = {}) {
if (this.form.carrierType !== '自运' || this.waybillHasCarrierContracts === true) return; if (this.form.carrierType !== '自运') return;
const carrierName = String(contract.partyB || '').trim(); const carrierName = String(contract.partyB || contract.partyBName || '').trim();
if (!carrierName) return; if (!carrierName) return;
const exists = this.taskCarrierOptions.some( const exists = this.taskCarrierOptions.some(
item => String(item.value || item.carrierName || '') === carrierName item => String(item.value || item.carrierName || '') === carrierName
@@ -5462,17 +5462,18 @@ export default {
}, },
getWaybillCarrierContractOptions(contracts = []) { getWaybillCarrierContractOptions(contracts = []) {
const carrierNameCounts = contracts.reduce((counts, contract) => { const carrierNameCounts = contracts.reduce((counts, contract) => {
const carrierName = String(contract.partyB || '').trim(); const carrierName = String(contract.partyA || contract.partyAName || '').trim();
if (carrierName) counts[carrierName] = (counts[carrierName] || 0) + 1; if (carrierName) counts[carrierName] = (counts[carrierName] || 0) + 1;
return counts; return counts;
}, {}); }, {});
return contracts return contracts
.map(contract => { .map(contract => {
const carrierName = String(contract.partyB || '').trim(); const carrierName = String(contract.partyA || contract.partyAName || '').trim();
if (!carrierName || !contract.id) return null; if (!carrierName || !contract.id) return null;
const contractIdentifier = contract.contractName || contract.contractNo || contract.id; const contractIdentifier = contract.contractName || contract.contractNo || contract.id;
return { return {
id: contract.id, id: contract.id,
carrierId: contract.partyAId || contract.partyAUserId || contract.customerId || '',
value: contract.id, value: contract.id,
label: label:
carrierNameCounts[carrierName] > 1 carrierNameCounts[carrierName] > 1
@@ -5581,28 +5582,15 @@ export default {
return Promise.all([contractPromise, detailPromise]) return Promise.all([contractPromise, detailPromise])
.then(([carrierContractOptions, options]) => { .then(([carrierContractOptions, options]) => {
if (requestId !== this.taskCarrierRequestId) return this.taskCarrierOptions; if (requestId !== this.taskCarrierRequestId) return this.taskCarrierOptions;
if (carrierTypeAtRequest === '自运' && carrierContractOptions?.length) {
const selfCarrierOptions = carrierContractOptions.map(item => ({
...item,
value: item.carrierName,
}));
this.taskCarrierOptions = selfCarrierOptions;
const hasCurrentCarrier = selfCarrierOptions.some(
item => String(item.value || '') === String(this.form.carrierName || '')
);
if (!hasCurrentCarrier) {
this.form.carrierName = selfCarrierOptions[0].carrierName;
this.form.carrierId = '';
}
return selfCarrierOptions;
}
this.taskCarrierOptions = options || [];
if (carrierTypeAtRequest === '自运') { if (carrierTypeAtRequest === '自运') {
this.taskCarrierOptions = [];
const customerContract = this.contractOptions.find( const customerContract = this.contractOptions.find(
item => String(item.id) === String(this.form.contractId) item => String(item.id) === String(this.form.contractId)
); );
this.fillSelfOperatedCarrierFromContract(customerContract); this.fillSelfOperatedCarrierFromContract(customerContract);
return this.taskCarrierOptions;
} }
this.taskCarrierOptions = options || [];
return this.taskCarrierOptions; return this.taskCarrierOptions;
}) })
.finally(() => { .finally(() => {
@@ -337,11 +337,15 @@
clearable clearable
maxlength="32" maxlength="32"
placeholder="请输入发票号码" placeholder="请输入发票号码"
@keyup.enter="claimInvoices" @keyup.enter="openInvoiceClaimDialog"
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" :loading="invoiceClaimLoading" @click="claimInvoices"> <el-button
type="primary"
:loading="invoiceClaimLoading"
@click="openInvoiceClaimDialog"
>
认领查询 认领查询
</el-button> </el-button>
</el-form-item> </el-form-item>
@@ -407,6 +411,67 @@
</el-table> </el-table>
</section-card> </section-card>
<el-dialog
v-model="invoiceClaimDialog.visible"
title="查询可认领发票"
width="92%"
append-to-body
destroy-on-close
>
<el-table
ref="invoiceClaimTable"
v-loading="invoiceClaimDialog.loading"
:data="invoiceClaimPagedRows"
row-key="invoiceNo"
border
height="520"
@selection-change="invoiceClaimDialog.selected = $event"
>
<el-table-column
type="selection"
width="52"
fixed="left"
align="center"
reserve-selection
/>
<el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column prop="invoiceNo" label="发票号" min-width="180" align="center" />
<el-table-column prop="invoiceDate" label="开票日期" min-width="130" align="center" />
<el-table-column prop="invoiceType" label="发票类型" min-width="150" align="center" />
<el-table-column prop="issuerName" label="开票单位" min-width="180" align="center" />
<el-table-column prop="receiverName" label="受票单位" min-width="180" align="center" />
<el-table-column
prop="invoiceAmount"
label="发票金额(含税)"
min-width="160"
align="right"
>
<template #default="{ row }">{{ formatMoney(row.invoiceAmount) }}</template>
</el-table-column>
<el-table-column prop="matchedAmount" label="认领金额" min-width="140" align="right">
<template #default="{ row }">{{ formatMoney(row.matchedAmount) }}</template>
</el-table-column>
</el-table>
<div class="formal-editor__pagination">
<el-pagination
v-model:current-page="invoiceClaimDialog.page.current"
v-model:page-size="invoiceClaimDialog.page.size"
:total="invoiceClaimDialog.page.total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
/>
</div>
<template #footer>
<el-button @click="invoiceClaimDialog.visible = false">取消</el-button>
<el-button
type="primary"
:loading="invoiceClaimDialog.confirming"
@click="confirmInvoiceClaims"
>确认认领</el-button
>
</template>
</el-dialog>
<section-card <section-card
v-if="readonly" v-if="readonly"
:title="form.settlementType === 'receivable' ? '收款信息' : '付款信息'" :title="form.settlementType === 'receivable' ? '收款信息' : '付款信息'"
@@ -523,7 +588,7 @@
<template #default="{ row }">{{ displayValue(row.changeType) }}</template> <template #default="{ row }">{{ displayValue(row.changeType) }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="lineNo" label="行号" min-width="90" align="center"> <el-table-column prop="lineNo" label="行号" min-width="90" align="center">
<template #default="{ row }">{{ displayValue(row.lineNo) }}</template> <template #default="{ row }">{{ changeRecordLineNo(row) }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="operationType" label="类型" min-width="110" align="center"> <el-table-column prop="operationType" label="类型" min-width="110" align="center">
<template #default="{ row }">{{ displayValue(row.operationType) }}</template> <template #default="{ row }">{{ displayValue(row.operationType) }}</template>
@@ -843,6 +908,7 @@ import {
getFeeOptions, getFeeOptions,
getNextNo, getNextNo,
getReceiptClaims, getReceiptClaims,
claimInvoices as claimInvoicesApi,
save, save,
} from '@/api/settlement/formalSettlement'; } from '@/api/settlement/formalSettlement';
import { import {
@@ -898,6 +964,14 @@ export default {
invoices: [], invoices: [],
invoiceClaimNo: '', invoiceClaimNo: '',
invoiceClaimLoading: false, invoiceClaimLoading: false,
invoiceClaimDialog: {
visible: false,
loading: false,
confirming: false,
rows: [],
selected: [],
page: { current: 1, size: 10, total: 0 },
},
attachmentUploadFiles: [], attachmentUploadFiles: [],
attachmentTypeOptions: [], attachmentTypeOptions: [],
attachmentFileTypes: [ attachmentFileTypes: [
@@ -1034,6 +1108,11 @@ export default {
}); });
return Array.from(names); return Array.from(names);
}, },
invoiceClaimPagedRows() {
const { current, size } = this.invoiceClaimDialog.page;
const start = (current - 1) * size;
return this.invoiceClaimDialog.rows.slice(start, start + size);
},
}, },
watch: { watch: {
modelValue: { modelValue: {
@@ -1103,6 +1182,9 @@ export default {
this.selectedAttachmentRows = []; this.selectedAttachmentRows = [];
this.invoices = []; this.invoices = [];
this.invoiceClaimNo = ''; this.invoiceClaimNo = '';
this.invoiceClaimDialog.visible = false;
this.invoiceClaimDialog.rows = [];
this.invoiceClaimDialog.selected = [];
this.attachmentUploadFiles = []; this.attachmentUploadFiles = [];
this.billingRuleDialog = { this.billingRuleDialog = {
visible: false, visible: false,
@@ -1864,6 +1946,78 @@ export default {
this.invoiceClaimLoading = false; this.invoiceClaimLoading = false;
} }
}, },
openInvoiceClaimDialog() {
const stamp = Date.now();
this.invoiceClaimDialog.loading = true;
this.invoiceClaimDialog.rows = Array.from({ length: 80 }, (_, index) => {
const amount = Math.floor(1000 + Math.random() * 49000);
return {
invoiceNo: `MOCK${stamp}${String(index + 1).padStart(3, '0')}`.slice(0, 32),
invoiceDate: this.$dayjs()
.subtract(Math.floor(Math.random() * 90), 'day')
.format('YYYY-MM-DD'),
invoiceType: index % 2 ? '增值税普通发票' : '增值税专用发票',
issuerName: this.form.payerName || 'Mock开票单位',
receiverName: this.form.payeeName || 'Mock受票单位',
invoiceAmount: amount,
availableInvoiceAmount: amount,
matchedAmount: amount,
taxRate: [3, 6, 9, 13][index % 4],
attachmentJson: '',
mockData: true,
};
});
this.invoiceClaimDialog.selected = [];
this.invoiceClaimDialog.page.current = 1;
this.invoiceClaimDialog.page.total = 80;
this.invoiceClaimDialog.visible = true;
this.invoiceClaimDialog.loading = false;
},
async confirmInvoiceClaims() {
if (!this.invoiceClaimDialog.selected.length) {
this.$message.warning('请至少选择一条发票');
return;
}
this.invoiceClaimDialog.confirming = true;
try {
const existingNumbers = new Set(this.invoices.map(item => String(item.invoiceNo)));
let remaining = Math.max(
Number(this.form.settlementAmount || 0) -
this.invoices.reduce((total, item) => total + Number(item.matchedAmount || 0), 0),
0
);
const invoices = this.invoiceClaimDialog.selected
.filter(row => !existingNumbers.has(String(row.invoiceNo)))
.map(row => {
const sourceAmount = Number(row.matchedAmount || 0);
const matchedAmount =
Number(this.form.settlementAmount || 0) > 0
? Math.min(sourceAmount, remaining)
: sourceAmount;
if (Number(this.form.settlementAmount || 0) > 0) {
remaining = Math.max(0, remaining - matchedAmount);
}
return { ...row, matchedAmount };
})
.filter(row => row.matchedAmount > 0);
if (!invoices.length) {
this.$message.warning('当前正式结算单没有可认领的剩余金额');
return;
}
if (!this.form.id) {
this.invoices = [...this.invoices, ...invoices];
this.invoiceClaimDialog.visible = false;
this.$message.success(`已选择${invoices.length}条发票,保存正式结算单后生效`);
return;
}
await claimInvoicesApi({ formalSettlementId: this.form.id, invoices });
await this.loadFormalDetail(this.form.id);
this.invoiceClaimDialog.visible = false;
this.$message.success('发票认领成功,已同步正式结算单及关联付款单据');
} finally {
this.invoiceClaimDialog.confirming = false;
}
},
validateInvoices() { validateInvoices() {
const invoiceNumbers = new Set(); const invoiceNumbers = new Set();
let matchedTotal = 0; let matchedTotal = 0;
@@ -2000,7 +2154,8 @@ export default {
return this.$message.warning('请完善手工费用的费用类型和费用项'); return this.$message.warning('请完善手工费用的费用类型和费用项');
} }
if (!this.validateInvoices()) return; if (!this.validateInvoices()) return;
if (!this.validateAttachments()) return; // 附件类型仅做提示,不阻断正式结算单新增/保存提交。
this.validateAttachments();
this.saving = true; this.saving = true;
try { try {
await save(this.buildSavePayload()); await save(this.buildSavePayload());
@@ -2014,6 +2169,10 @@ export default {
displayValue(value) { displayValue(value) {
return value === null || value === undefined || value === '' ? '-' : value; return value === null || value === undefined || value === '' ? '-' : value;
}, },
changeRecordLineNo(row) {
const lineNo = row?.lineNo;
return lineNo === -1 || String(lineNo) === '-1' ? '' : this.displayValue(lineNo);
},
paymentMethodName(value) { paymentMethodName(value) {
const labels = { const labels = {
bank_transfer: '银行转账', bank_transfer: '银行转账',
@@ -82,12 +82,7 @@
添加费用 添加费用
</el-button> </el-button>
</template> </template>
<el-table <el-table :data="summaryFees" border show-summary :summary-method="getSummarySums">
:data="summaryFees"
border
show-summary
:summary-method="getSummarySums"
>
<el-table-column type="index" label="序号" width="64" align="center" /> <el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column <el-table-column
v-for="column in summaryColumns" v-for="column in summaryColumns"
@@ -261,7 +256,7 @@
<span v-else-if="pageMode && column.prop === 'mileage'"> <span v-else-if="pageMode && column.prop === 'mileage'">
{{ formatDetailMileage(row[column.prop]) }} {{ formatDetailMileage(row[column.prop]) }}
</span> </span>
<span v-else-if="pageMode && column.prop === 'transportType'"> <span v-else-if="column.prop === 'transportType'">
{{ transportTypeName(row[column.prop]) }} {{ transportTypeName(row[column.prop]) }}
</span> </span>
<span v-else>{{ displayValue(row[column.prop]) }}</span> <span v-else>{{ displayValue(row[column.prop]) }}</span>
@@ -374,6 +369,12 @@
<span v-else-if="column.prop === 'billStatus'"> <span v-else-if="column.prop === 'billStatus'">
{{ advanceStatusName(row.billStatus) }} {{ advanceStatusName(row.billStatus) }}
</span> </span>
<span v-else-if="column.prop === 'createUserName'">
{{ advanceCreateUserName(row) }}
</span>
<span v-else-if="column.prop === 'createTime'">
{{ advanceCreateTime(row) }}
</span>
<span v-else>{{ displayValue(row[column.prop]) }}</span> <span v-else>{{ displayValue(row[column.prop]) }}</span>
</template> </template>
</el-table-column> </el-table-column>
@@ -381,7 +382,7 @@
</section-card> </section-card>
<section-card v-if="form.id && readonly" title="变更记录"> <section-card v-if="form.id && readonly" title="变更记录">
<el-table :data="changeRecords" border> <el-table :data="adjustChangeRecords" border>
<el-table-column type="index" label="序号" width="64" align="center" /> <el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column <el-table-column
v-for="column in changeTableColumns" v-for="column in changeTableColumns"
@@ -671,6 +672,8 @@
append-to-body append-to-body
destroy-on-close destroy-on-close
> >
<el-tabs v-model="adjustDialog.activeTab" class="pre-settlement-editor__adjust-tabs">
<el-tab-pane label="结算明细调整" name="adjust">
<el-table v-loading="adjustDialog.loading" :data="adjustRows" border> <el-table v-loading="adjustDialog.loading" :data="adjustRows" border>
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" /> <el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
<el-table-column prop="cargoName" label="货物名称" min-width="140" align="center" /> <el-table-column prop="cargoName" label="货物名称" min-width="140" align="center" />
@@ -768,6 +771,32 @@
<el-input v-model="adjustDialog.reason" maxlength="200" show-word-limit /> <el-input v-model="adjustDialog.reason" maxlength="200" show-word-limit />
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-tab-pane>
<el-tab-pane label="变更记录" name="records">
<el-table :data="changeRecords" border>
<el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column prop="changeTime" label="变更日期" min-width="170" align="center" />
<el-table-column prop="operatorName" label="经办人" min-width="140" align="center" />
<el-table-column prop="changeType" label="变更类型" min-width="160" align="center" />
<el-table-column
prop="changeReason"
label="变更原因"
min-width="240"
align="center"
show-overflow-tooltip
/>
<el-table-column label="状态" min-width="120" align="center">
<template #default>已生效</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row }">
<el-link type="primary" @click="openAdjustChangeRecord(row)">查看详情</el-link>
</template>
</el-table-column>
</el-table>
<el-empty v-if="!adjustChangeRecords.length" description="暂无变更记录" :image-size="60" />
</el-tab-pane>
</el-tabs>
<template #footer> <template #footer>
<el-button @click="adjustDialog.visible = false">取消</el-button> <el-button @click="adjustDialog.visible = false">取消</el-button>
<el-button <el-button
@@ -781,6 +810,36 @@
</template> </template>
</el-dialog> </el-dialog>
<el-dialog
v-model="adjustChangeRecordVisible"
title="变更记录详情"
append-to-body
destroy-on-close
width="1100px"
top="10px"
class="pre-settlement-change-record-detail-dialog"
>
<div v-if="adjustChangeRecord" class="pre-settlement-change-record-detail-meta">
<span>变更日期:{{ adjustChangeRecord.changeTime || '-' }}</span>
<span>经办人:{{ adjustChangeRecord.operatorName || '-' }}</span>
<span>变更类型:{{ adjustChangeRecord.changeType || '-' }}</span>
<span>状态:已生效</span>
</div>
<el-table :data="adjustChangeRecordDetailRows" border :show-overflow-tooltip="false">
<el-table-column prop="field" label="变更字段" min-width="220" />
<el-table-column prop="before" label="变更前" min-width="330" />
<el-table-column prop="after" label="变更后" min-width="420" />
</el-table>
<el-empty
v-if="!adjustChangeRecordDetailRows.length"
description="暂无变更内容"
:image-size="60"
/>
<template #footer>
<el-button type="primary" @click="adjustChangeRecordVisible = false">关闭</el-button>
</template>
</el-dialog>
<el-dialog <el-dialog
v-model="billingRuleDialog.visible" v-model="billingRuleDialog.visible"
title="计费规则详情" title="计费规则详情"
@@ -1010,10 +1069,15 @@ export default {
loading: false, loading: false,
saving: false, saving: false,
readonly: false, readonly: false,
activeTab: 'adjust',
detailId: '', detailId: '',
detailLineNo: '',
reason: '', reason: '',
}, },
adjustRows: [], adjustRows: [],
adjustChangeRecordVisible: false,
adjustChangeRecord: null,
adjustChangeRecordDetailRows: [],
billingRuleDialog: { billingRuleDialog: {
visible: false, visible: false,
rule: null, rule: null,
@@ -1105,7 +1169,7 @@ export default {
); );
}, },
visibleDetailColumns() { visibleDetailColumns() {
if (!this.pageMode) return this.detailColumns; if (!this.readonly && !this.pageMode) return this.detailColumns;
return this.detailColumns.filter(column => column.prop !== 'settlementAmountNoTax'); return this.detailColumns.filter(column => column.prop !== 'settlementAmountNoTax');
}, },
detailFeeItemNames() { detailFeeItemNames() {
@@ -1132,6 +1196,13 @@ export default {
}); });
return Array.from(names); return Array.from(names);
}, },
adjustChangeRecords() {
return this.changeRecords.filter(
row =>
row.changeType === '结算明细项' &&
String(row.lineNo ?? '') === String(this.adjustDialog.detailLineNo ?? '')
);
},
}, },
watch: { watch: {
modelValue: { modelValue: {
@@ -1229,6 +1300,12 @@ export default {
this.attachments = []; this.attachments = [];
this.selectedAttachmentRows = []; this.selectedAttachmentRows = [];
this.adjustRows = []; this.adjustRows = [];
this.adjustDialog.activeTab = 'adjust';
this.adjustDialog.detailId = '';
this.adjustDialog.detailLineNo = '';
this.adjustChangeRecordVisible = false;
this.adjustChangeRecord = null;
this.adjustChangeRecordDetailRows = [];
this.billingRuleDialog.visible = false; this.billingRuleDialog.visible = false;
this.billingRuleDialog.rule = null; this.billingRuleDialog.rule = null;
this.contractOptions = []; this.contractOptions = [];
@@ -1247,7 +1324,11 @@ export default {
this.form = { ...emptyPreSettlementForm(), ...detail }; this.form = { ...emptyPreSettlementForm(), ...detail };
this.summaryFees = (detail.summaryFees || []).map(row => ({ ...row })); this.summaryFees = (detail.summaryFees || []).map(row => ({ ...row }));
this.details = (detail.details || []).map(row => ({ ...row })); this.details = (detail.details || []).map(row => ({ ...row }));
this.advances = detail.advances || []; this.advances = (detail.advances || []).map(row => ({
...row,
createUserName: row.createUserName || detail.createUserName,
createTime: row.createTime || detail.createTime,
}));
this.changeRecords = detail.changeRecords || []; this.changeRecords = detail.changeRecords || [];
this.attachments = this.parseAttachments(detail.attachmentsJson); this.attachments = this.parseAttachments(detail.attachmentsJson);
this.selectedAttachmentRows = []; this.selectedAttachmentRows = [];
@@ -1360,7 +1441,11 @@ export default {
}, },
async loadTransportTypeOptions() { async loadTransportTypeOptions() {
const { data } = await getDictionary({ code: 'transport_type' }); const { data } = await getDictionary({ code: 'transport_type' });
this.transportTypeOptions = data?.data || []; const records = Array.isArray(data?.data) ? data.data : data?.data?.records || [];
this.transportTypeOptions = records.map(item => ({
dictKey: item.dictKey ?? item.value,
dictValue: item.dictValue ?? item.label ?? item.name,
}));
}, },
handleContractChange(id) { handleContractChange(id) {
const contract = this.contractOptions.find(item => String(item.id) === String(id)); const contract = this.contractOptions.find(item => String(item.id) === String(id));
@@ -1720,7 +1805,9 @@ export default {
this.adjustDialog.visible = true; this.adjustDialog.visible = true;
this.adjustDialog.loading = true; this.adjustDialog.loading = true;
this.adjustDialog.readonly = readonly; this.adjustDialog.readonly = readonly;
this.adjustDialog.activeTab = 'adjust';
this.adjustDialog.detailId = detailRow.id; this.adjustDialog.detailId = detailRow.id;
this.adjustDialog.detailLineNo = detailRow.lineNo;
this.adjustDialog.reason = ''; this.adjustDialog.reason = '';
try { try {
const { data } = await getDetailFees(detailRow.id); const { data } = await getDetailFees(detailRow.id);
@@ -1733,6 +1820,42 @@ export default {
this.adjustDialog.loading = false; this.adjustDialog.loading = false;
} }
}, },
parseChangeRecordData(value) {
if (!value) return {};
if (typeof value === 'object') return value;
try {
const parsed = JSON.parse(value);
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
} catch (error) {
return {};
}
},
formatAdjustChangeValue(value) {
if (value === undefined || value === null || value === '') return '空';
if (typeof value === 'object') return JSON.stringify(value);
return String(value);
},
buildAdjustChangeRecordRows(row = {}) {
const before = this.parseChangeRecordData(row.beforeData);
const after = this.parseChangeRecordData(row.afterData);
const fields = [...new Set([...Object.keys(before), ...Object.keys(after)])];
const rows = fields
.filter(field => JSON.stringify(before[field]) !== JSON.stringify(after[field]))
.map(field => ({
field,
before: this.formatAdjustChangeValue(before[field]),
after: this.formatAdjustChangeValue(after[field]),
}));
if (row.changeContent)
rows.unshift({ field: '变更内容', before: '空', after: row.changeContent });
if (row.changeReason) rows.push({ field: '变更原因', before: '空', after: row.changeReason });
return rows;
},
openAdjustChangeRecord(row) {
this.adjustChangeRecord = row;
this.adjustChangeRecordDetailRows = this.buildAdjustChangeRecordRows(row);
this.adjustChangeRecordVisible = true;
},
billingRuleName(row) { billingRuleName(row) {
return this.normalizeBillingRule(row).name; return this.normalizeBillingRule(row).name;
}, },
@@ -2035,6 +2158,14 @@ export default {
}[status] || this.displayValue(status) }[status] || this.displayValue(status)
); );
}, },
advanceCreateUserName(row) {
return this.displayValue(
row?.createUserName || row?.advanceCreateUserName || row?.applyUserName
);
},
advanceCreateTime(row) {
return this.displayValue(row?.createTime || row?.advanceCreateTime || row?.applyTime);
},
changeRecordLineNo(row) { changeRecordLineNo(row) {
if (row.changeType !== '结算明细项') return ''; if (row.changeType !== '结算明细项') return '';
if (row.lineNo !== undefined && row.lineNo !== null && row.lineNo !== '') return row.lineNo; if (row.lineNo !== undefined && row.lineNo !== null && row.lineNo !== '') return row.lineNo;
@@ -2225,6 +2356,23 @@ export default {
} }
} }
.pre-settlement-change-record-detail-meta {
display: flex;
flex-wrap: wrap;
gap: 8px 32px;
margin-bottom: 16px;
color: #606266;
}
:deep(.pre-settlement-change-record-detail-dialog .el-dialog__body) {
padding-top: 12px;
}
:deep(.pre-settlement-change-record-detail-dialog .el-table .cell) {
white-space: pre-wrap;
word-break: break-all;
}
:deep(.pre-settlement-editor .el-dialog__body) { :deep(.pre-settlement-editor .el-dialog__body) {
padding: 12px 16px; padding: 12px 16px;
} }
+1 -3
View File
@@ -577,9 +577,7 @@ export default {
return `${Number(value || 0).toFixed(2)} ${currency || 'RMB'}`; return `${Number(value || 0).toFixed(2)} ${currency || 'RMB'}`;
}, },
paymentRemaining(row) { paymentRemaining(row) {
const remaining = const remaining = Number(row?.settlementAmount || 0) - Number(row?.paidAmount || 0);
row?.remainingPayableAmount ??
Number(row?.settlementAmount || 0) - Number(row?.appliedPaymentAmount || 0);
return Math.max(0, Number(remaining || 0)); return Math.max(0, Number(remaining || 0));
}, },
}, },