调整业务模块
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user