调整业务模块
This commit is contained in:
@@ -571,17 +571,17 @@ const buildCarrierContractOptions = contractRows => {
|
||||
item => String(item.contractCategory || '').trim() === '承运商合同'
|
||||
);
|
||||
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;
|
||||
return result;
|
||||
}, {});
|
||||
return validContracts
|
||||
.map(contract => {
|
||||
const carrierName = String(contract.partyB || '').trim();
|
||||
const carrierName = String(contract.partyA || contract.partyAName || '').trim();
|
||||
if (!contract.id || !carrierName) return null;
|
||||
const identifier = contract.contractName || contract.contractNo || contract.id;
|
||||
return {
|
||||
id: contract.partyBId || contract.customerId || '',
|
||||
id: contract.partyAId || contract.partyAUserId || contract.customerId || '',
|
||||
carrierContractId: contract.id,
|
||||
carrierName,
|
||||
label: nameCounts[carrierName] > 1 ? `${carrierName}(${identifier})` : carrierName,
|
||||
@@ -607,7 +607,11 @@ const syncCarrierOptions = () => {
|
||||
carrierOptions.value = [];
|
||||
return;
|
||||
}
|
||||
const carrierId = customerContract?.partyBId || customerContract?.customerId || '';
|
||||
const carrierId =
|
||||
customerContract?.partyBId ||
|
||||
customerContract?.partyBUserId ||
|
||||
customerContract?.customerId ||
|
||||
'';
|
||||
carrierOptions.value = [{ id: carrierId, carrierName, label: carrierName, value: carrierName }];
|
||||
form.carrierId = carrierId;
|
||||
form.carrierIds = carrierId ? [carrierId] : [];
|
||||
|
||||
@@ -5413,8 +5413,8 @@ export default {
|
||||
}
|
||||
},
|
||||
fillSelfOperatedCarrierFromContract(contract = {}) {
|
||||
if (this.form.carrierType !== '自运' || this.waybillHasCarrierContracts === true) return;
|
||||
const carrierName = String(contract.partyB || '').trim();
|
||||
if (this.form.carrierType !== '自运') return;
|
||||
const carrierName = String(contract.partyB || contract.partyBName || '').trim();
|
||||
if (!carrierName) return;
|
||||
const exists = this.taskCarrierOptions.some(
|
||||
item => String(item.value || item.carrierName || '') === carrierName
|
||||
@@ -5462,17 +5462,18 @@ export default {
|
||||
},
|
||||
getWaybillCarrierContractOptions(contracts = []) {
|
||||
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;
|
||||
return counts;
|
||||
}, {});
|
||||
return contracts
|
||||
.map(contract => {
|
||||
const carrierName = String(contract.partyB || '').trim();
|
||||
const carrierName = String(contract.partyA || contract.partyAName || '').trim();
|
||||
if (!carrierName || !contract.id) return null;
|
||||
const contractIdentifier = contract.contractName || contract.contractNo || contract.id;
|
||||
return {
|
||||
id: contract.id,
|
||||
carrierId: contract.partyAId || contract.partyAUserId || contract.customerId || '',
|
||||
value: contract.id,
|
||||
label:
|
||||
carrierNameCounts[carrierName] > 1
|
||||
@@ -5581,28 +5582,15 @@ export default {
|
||||
return Promise.all([contractPromise, detailPromise])
|
||||
.then(([carrierContractOptions, options]) => {
|
||||
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 === '自运') {
|
||||
this.taskCarrierOptions = [];
|
||||
const customerContract = this.contractOptions.find(
|
||||
item => String(item.id) === String(this.form.contractId)
|
||||
);
|
||||
this.fillSelfOperatedCarrierFromContract(customerContract);
|
||||
return this.taskCarrierOptions;
|
||||
}
|
||||
this.taskCarrierOptions = options || [];
|
||||
return this.taskCarrierOptions;
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
@@ -337,11 +337,15 @@
|
||||
clearable
|
||||
maxlength="32"
|
||||
placeholder="请输入发票号码"
|
||||
@keyup.enter="claimInvoices"
|
||||
@keyup.enter="openInvoiceClaimDialog"
|
||||
/>
|
||||
</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-form-item>
|
||||
@@ -407,6 +411,67 @@
|
||||
</el-table>
|
||||
</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
|
||||
v-if="readonly"
|
||||
:title="form.settlementType === 'receivable' ? '收款信息' : '付款信息'"
|
||||
@@ -523,7 +588,7 @@
|
||||
<template #default="{ row }">{{ displayValue(row.changeType) }}</template>
|
||||
</el-table-column>
|
||||
<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 prop="operationType" label="类型" min-width="110" align="center">
|
||||
<template #default="{ row }">{{ displayValue(row.operationType) }}</template>
|
||||
@@ -843,6 +908,7 @@ import {
|
||||
getFeeOptions,
|
||||
getNextNo,
|
||||
getReceiptClaims,
|
||||
claimInvoices as claimInvoicesApi,
|
||||
save,
|
||||
} from '@/api/settlement/formalSettlement';
|
||||
import {
|
||||
@@ -898,6 +964,14 @@ export default {
|
||||
invoices: [],
|
||||
invoiceClaimNo: '',
|
||||
invoiceClaimLoading: false,
|
||||
invoiceClaimDialog: {
|
||||
visible: false,
|
||||
loading: false,
|
||||
confirming: false,
|
||||
rows: [],
|
||||
selected: [],
|
||||
page: { current: 1, size: 10, total: 0 },
|
||||
},
|
||||
attachmentUploadFiles: [],
|
||||
attachmentTypeOptions: [],
|
||||
attachmentFileTypes: [
|
||||
@@ -1034,6 +1108,11 @@ export default {
|
||||
});
|
||||
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: {
|
||||
modelValue: {
|
||||
@@ -1103,6 +1182,9 @@ export default {
|
||||
this.selectedAttachmentRows = [];
|
||||
this.invoices = [];
|
||||
this.invoiceClaimNo = '';
|
||||
this.invoiceClaimDialog.visible = false;
|
||||
this.invoiceClaimDialog.rows = [];
|
||||
this.invoiceClaimDialog.selected = [];
|
||||
this.attachmentUploadFiles = [];
|
||||
this.billingRuleDialog = {
|
||||
visible: false,
|
||||
@@ -1864,6 +1946,78 @@ export default {
|
||||
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() {
|
||||
const invoiceNumbers = new Set();
|
||||
let matchedTotal = 0;
|
||||
@@ -2000,7 +2154,8 @@ export default {
|
||||
return this.$message.warning('请完善手工费用的费用类型和费用项');
|
||||
}
|
||||
if (!this.validateInvoices()) return;
|
||||
if (!this.validateAttachments()) return;
|
||||
// 附件类型仅做提示,不阻断正式结算单新增/保存提交。
|
||||
this.validateAttachments();
|
||||
this.saving = true;
|
||||
try {
|
||||
await save(this.buildSavePayload());
|
||||
@@ -2014,6 +2169,10 @@ export default {
|
||||
displayValue(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) {
|
||||
const labels = {
|
||||
bank_transfer: '银行转账',
|
||||
|
||||
@@ -82,12 +82,7 @@
|
||||
添加费用
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table
|
||||
:data="summaryFees"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummarySums"
|
||||
>
|
||||
<el-table :data="summaryFees" border show-summary :summary-method="getSummarySums">
|
||||
<el-table-column type="index" label="序号" width="64" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in summaryColumns"
|
||||
@@ -261,7 +256,7 @@
|
||||
<span v-else-if="pageMode && column.prop === 'mileage'">
|
||||
{{ formatDetailMileage(row[column.prop]) }}
|
||||
</span>
|
||||
<span v-else-if="pageMode && column.prop === 'transportType'">
|
||||
<span v-else-if="column.prop === 'transportType'">
|
||||
{{ transportTypeName(row[column.prop]) }}
|
||||
</span>
|
||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
||||
@@ -374,6 +369,12 @@
|
||||
<span v-else-if="column.prop === 'billStatus'">
|
||||
{{ advanceStatusName(row.billStatus) }}
|
||||
</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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -381,7 +382,7 @@
|
||||
</section-card>
|
||||
|
||||
<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
|
||||
v-for="column in changeTableColumns"
|
||||
@@ -671,103 +672,131 @@
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-table v-loading="adjustDialog.loading" :data="adjustRows" border>
|
||||
<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="cargoType" label="货物类型" min-width="130" align="center" />
|
||||
<el-table-column label="计费规则" min-width="190" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="pre-settlement-editor__billing-rule-cell">
|
||||
<span>{{ displayValue(billingRuleName(row)) }}</span>
|
||||
<el-icon
|
||||
class="pre-settlement-editor__billing-rule-icon"
|
||||
title="查看计费规则详情"
|
||||
@click="openBillingRuleInfo(row)"
|
||||
>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运输总量" min-width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="adjustDialog.readonly">{{ formatQuantity(row) }}</span>
|
||||
<el-input-number
|
||||
v-else
|
||||
v-model="row.transportQuantity"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
<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-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="cargoType" label="货物类型" min-width="130" align="center" />
|
||||
<el-table-column label="计费规则" min-width="190" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="pre-settlement-editor__billing-rule-cell">
|
||||
<span>{{ displayValue(billingRuleName(row)) }}</span>
|
||||
<el-icon
|
||||
class="pre-settlement-editor__billing-rule-icon"
|
||||
title="查看计费规则详情"
|
||||
@click="openBillingRuleInfo(row)"
|
||||
>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运输总量" min-width="150" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="adjustDialog.readonly">{{ formatQuantity(row) }}</span>
|
||||
<el-input-number
|
||||
v-else
|
||||
v-model="row.transportQuantity"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="里程(KM)" min-width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.mileage"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运输单价" min-width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.unitPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="feeItem in adjustFeeItemNames"
|
||||
:key="feeItem"
|
||||
:label="feeItem"
|
||||
min-width="140"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.feeItems[feeItem]"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
@change="recalculateAdjustRow(row, feeItem)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算金额(含税)" min-width="170" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.settlementAmountTax"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.remark" maxlength="200" :disabled="adjustDialog.readonly" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form
|
||||
v-if="!adjustDialog.readonly"
|
||||
:model="adjustDialog"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
class="pre-settlement-editor__adjust-reason"
|
||||
>
|
||||
<el-form-item label="调整原因">
|
||||
<el-input v-model="adjustDialog.reason" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</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
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="里程(KM)" min-width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.mileage"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运输单价" min-width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.unitPrice"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="feeItem in adjustFeeItemNames"
|
||||
:key="feeItem"
|
||||
:label="feeItem"
|
||||
min-width="140"
|
||||
align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.feeItems[feeItem]"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
@change="recalculateAdjustRow(row, feeItem)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算金额(含税)" min-width="170" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="row.settlementAmountTax"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
:disabled="adjustDialog.readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.remark" maxlength="200" :disabled="adjustDialog.readonly" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form
|
||||
v-if="!adjustDialog.readonly"
|
||||
:model="adjustDialog"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
class="pre-settlement-editor__adjust-reason"
|
||||
>
|
||||
<el-form-item label="调整原因">
|
||||
<el-input v-model="adjustDialog.reason" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<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>
|
||||
<el-button @click="adjustDialog.visible = false">取消</el-button>
|
||||
<el-button
|
||||
@@ -781,6 +810,36 @@
|
||||
</template>
|
||||
</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
|
||||
v-model="billingRuleDialog.visible"
|
||||
title="计费规则详情"
|
||||
@@ -1010,10 +1069,15 @@ export default {
|
||||
loading: false,
|
||||
saving: false,
|
||||
readonly: false,
|
||||
activeTab: 'adjust',
|
||||
detailId: '',
|
||||
detailLineNo: '',
|
||||
reason: '',
|
||||
},
|
||||
adjustRows: [],
|
||||
adjustChangeRecordVisible: false,
|
||||
adjustChangeRecord: null,
|
||||
adjustChangeRecordDetailRows: [],
|
||||
billingRuleDialog: {
|
||||
visible: false,
|
||||
rule: null,
|
||||
@@ -1105,7 +1169,7 @@ export default {
|
||||
);
|
||||
},
|
||||
visibleDetailColumns() {
|
||||
if (!this.pageMode) return this.detailColumns;
|
||||
if (!this.readonly && !this.pageMode) return this.detailColumns;
|
||||
return this.detailColumns.filter(column => column.prop !== 'settlementAmountNoTax');
|
||||
},
|
||||
detailFeeItemNames() {
|
||||
@@ -1132,6 +1196,13 @@ export default {
|
||||
});
|
||||
return Array.from(names);
|
||||
},
|
||||
adjustChangeRecords() {
|
||||
return this.changeRecords.filter(
|
||||
row =>
|
||||
row.changeType === '结算明细项' &&
|
||||
String(row.lineNo ?? '') === String(this.adjustDialog.detailLineNo ?? '')
|
||||
);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
@@ -1229,6 +1300,12 @@ export default {
|
||||
this.attachments = [];
|
||||
this.selectedAttachmentRows = [];
|
||||
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.rule = null;
|
||||
this.contractOptions = [];
|
||||
@@ -1247,7 +1324,11 @@ export default {
|
||||
this.form = { ...emptyPreSettlementForm(), ...detail };
|
||||
this.summaryFees = (detail.summaryFees || []).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.attachments = this.parseAttachments(detail.attachmentsJson);
|
||||
this.selectedAttachmentRows = [];
|
||||
@@ -1360,7 +1441,11 @@ export default {
|
||||
},
|
||||
async loadTransportTypeOptions() {
|
||||
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) {
|
||||
const contract = this.contractOptions.find(item => String(item.id) === String(id));
|
||||
@@ -1720,7 +1805,9 @@ export default {
|
||||
this.adjustDialog.visible = true;
|
||||
this.adjustDialog.loading = true;
|
||||
this.adjustDialog.readonly = readonly;
|
||||
this.adjustDialog.activeTab = 'adjust';
|
||||
this.adjustDialog.detailId = detailRow.id;
|
||||
this.adjustDialog.detailLineNo = detailRow.lineNo;
|
||||
this.adjustDialog.reason = '';
|
||||
try {
|
||||
const { data } = await getDetailFees(detailRow.id);
|
||||
@@ -1733,6 +1820,42 @@ export default {
|
||||
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) {
|
||||
return this.normalizeBillingRule(row).name;
|
||||
},
|
||||
@@ -2035,6 +2158,14 @@ export default {
|
||||
}[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) {
|
||||
if (row.changeType !== '结算明细项') return '';
|
||||
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) {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
@@ -577,9 +577,7 @@ export default {
|
||||
return `${Number(value || 0).toFixed(2)} ${currency || 'RMB'}`;
|
||||
},
|
||||
paymentRemaining(row) {
|
||||
const remaining =
|
||||
row?.remainingPayableAmount ??
|
||||
Number(row?.settlementAmount || 0) - Number(row?.appliedPaymentAmount || 0);
|
||||
const remaining = Number(row?.settlementAmount || 0) - Number(row?.paidAmount || 0);
|
||||
return Math.max(0, Number(remaining || 0));
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user