调整收付款问题

This commit is contained in:
2026-08-31 19:29:57 +08:00
parent dea760ea1c
commit 449e4e1884
8 changed files with 149 additions and 51 deletions
+6 -2
View File
@@ -5,8 +5,12 @@ const baseUrl = '/blade-transport/invoice-application';
export const getList = (current, size, params) =>
request({ url: `${baseUrl}/list`, method: 'get', params: { current, size, ...params } });
export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } });
export const getSettlementCandidates = keyword =>
request({ url: `${baseUrl}/settlement-candidates`, method: 'get', params: { keyword } });
export const getSettlementCandidates = (current, size, params) =>
request({
url: `${baseUrl}/settlement-candidates`,
method: 'get',
params: { current, size, ...params },
});
export const getSettlementDetails = settlementIds =>
request({ url: `${baseUrl}/settlement-details`, method: 'get', params: { settlementIds } });
export const getReceiverInformation = settlementIds =>
+6
View File
@@ -32,6 +32,12 @@ export const syncKingdee = id =>
request({ url: `${baseUrl}/sync-kingdee`, method: 'post', params: { id } });
export const getDetailFees = detailId =>
request({ url: `${baseUrl}/detail-fees`, method: 'get', params: { detailId } });
export const getReceiptClaims = formalSettlementId =>
request({
url: `${baseUrl}/receipt-claims`,
method: 'get',
params: { formalSettlementId },
});
export const adjustDetail = data =>
request({ url: `${baseUrl}/adjust-detail`, method: 'post', data });
export const applyPayment = data =>
+2 -2
View File
@@ -11,13 +11,13 @@ export const preSettlementTableColumns = [
{ label: '本位币结算金额', prop: 'localSettlementAmount', minWidth: 150, money: true, precision: 2 },
{ label: '结算汇率', prop: 'exchangeRate', minWidth: 110, precision: 2 },
{
label: '申请预付金额(审核中的)',
label: '申请预付金额',
prop: 'advanceAppliedAmount',
minWidth: 190,
money: true,
},
{
label: '已付款金额(审核通过的)',
label: '已付款金额',
prop: 'advancePaidAmount',
minWidth: 200,
money: true,
+57 -13
View File
@@ -16,7 +16,7 @@
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="结算单" prop="settlementIds">
<el-input :model-value="settlementLabel" readonly placeholder="请选择应正式结算单">
<el-input :model-value="settlementLabel" readonly placeholder="请选择应正式结算单">
<template v-if="!readonly" #append>
<el-button @click="openSettlementDialog">选择</el-button>
</template>
@@ -414,7 +414,7 @@
<el-dialog
v-model="settlementDialog.visible"
title="选择应正式结算单"
title="选择应正式结算单"
width="86%"
append-to-body
>
@@ -423,18 +423,19 @@
v-model="settlementDialog.keyword"
clearable
placeholder="结算单号项目或合同"
@keyup.enter="loadSettlementCandidates"
@keyup.enter="handleSettlementSearch"
/>
<el-button type="primary" @click="loadSettlementCandidates">查询</el-button>
<el-button type="primary" @click="handleSettlementSearch">查询</el-button>
</div>
<el-table
ref="settlementTable"
v-loading="settlementDialog.loading"
:data="settlementDialog.rows"
row-key="id"
border
@selection-change="settlementDialog.selection = $event"
>
<el-table-column type="selection" width="52" align="center" />
<el-table-column type="selection" width="52" align="center" reserve-selection />
<el-table-column prop="formalSettlementNo" label="结算单号" min-width="170" />
<el-table-column prop="projectName" label="所属项目" min-width="150" />
<el-table-column prop="deptName" label="所属组织" min-width="150" />
@@ -454,6 +455,17 @@
</template>
</el-table-column>
</el-table>
<div class="invoice-form-page__dialog-pagination">
<el-pagination
v-model:current-page="settlementDialog.page.current"
v-model:page-size="settlementDialog.page.size"
:total="settlementDialog.page.total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@current-change="loadSettlementCandidates"
@size-change="handleSettlementSizeChange"
/>
</div>
<template #footer>
<el-button @click="settlementDialog.visible = false">取消</el-button>
<el-button type="primary" @click="confirmSettlements">确定</el-button>
@@ -539,6 +551,7 @@ export default {
keyword: '',
rows: [],
selection: [],
page: { current: 1, size: 10, total: 0 },
},
rules: {
settlementIds: [{ validator: this.validateSettlements, trigger: 'change' }],
@@ -798,23 +811,49 @@ export default {
},
async openSettlementDialog() {
this.settlementDialog.visible = true;
this.settlementDialog.page.current = 1;
this.settlementDialog.selection = [];
this.$nextTick(() => this.$refs.settlementTable?.clearSelection());
await this.loadSettlementCandidates();
},
async loadSettlementCandidates() {
this.settlementDialog.loading = true;
try {
const data = this.unwrapData(
await api.getSettlementCandidates(this.settlementDialog.keyword)
await api.getSettlementCandidates(
this.settlementDialog.page.current,
this.settlementDialog.page.size,
{
keyword: this.settlementDialog.keyword,
contractCategory: '客户合同',
settlementType: 'receivable',
invoiceStatus: 'unreceived',
}
)
);
const rows = Array.isArray(data) ? data : data?.records || [];
this.settlementDialog.rows = rows;
this.settlementDialog.page.total = Number(
Array.isArray(data) ? data.length : data?.total || 0
);
this.settlementDialog.rows = Array.isArray(data) ? data : data?.records || [];
} finally {
this.settlementDialog.loading = false;
}
},
handleSettlementSearch() {
this.settlementDialog.page.current = 1;
this.settlementDialog.selection = [];
this.$refs.settlementTable?.clearSelection();
this.loadSettlementCandidates();
},
handleSettlementSizeChange() {
this.settlementDialog.page.current = 1;
this.loadSettlementCandidates();
},
async confirmSettlements() {
const rows = this.settlementDialog.selection;
if (!rows.length) {
this.$message.warning('请至少选择一张应正式结算单');
this.$message.warning('请至少选择一张应正式结算单');
return;
}
await this.applySettlements(rows);
@@ -962,19 +1001,19 @@ export default {
},
handleDetailLink(row, column) {
if (column.prop === 'documentNo') {
this.openPayableDetail(row);
this.openReceivableDetail(row);
return;
}
if (column.prop === 'waybillNo') this.openWaybillDetail(row);
},
async openPayableDetail(row) {
async openReceivableDetail(row) {
let detailId = row.sourceDetailId || '';
if (!detailId && row.documentNo) {
try {
const data = this.unwrapData(
await getReceivablePayableDetailList(1, 1, {
documentNo: row.documentNo,
settlementType: 'payable',
settlementType: 'receivable',
})
);
detailId = (Array.isArray(data) ? data : data?.records || [])[0]?.id || '';
@@ -983,11 +1022,11 @@ export default {
}
}
if (!detailId) {
this.$message.info('当前记录未找到对应的应明细');
this.$message.info('当前记录未找到对应的应明细');
return;
}
this.$router.push({
path: '/settlement/payable-detail',
path: '/settlement/receivable-detail',
query: { detailId },
});
},
@@ -1186,6 +1225,11 @@ export default {
.invoice-form-page__dialog-search .el-input {
width: 360px;
}
.invoice-form-page__dialog-pagination {
display: flex;
justify-content: flex-end;
margin-top: 12px;
}
.invoice-form-page :deep(.el-table) {
--el-table-border-color: #eff1f7;
}
+10 -23
View File
@@ -164,9 +164,11 @@
></el-col>
<el-col :span="6"
><el-form-item label="收款账号" prop="receiptAccountId"
><span v-if="readonly">{{ form.bankAccount || '-' }}</span
><el-select
v-else
v-model="form.receiptAccountId"
:disabled="readonly || !form.payeeName"
:disabled="!form.payeeName"
:loading="receiptAccountLoading"
filterable
clearable
@@ -343,7 +345,7 @@
>
<div class="payment-form-page__attachment-upload">
<vehicle-attachment-upload
:model-value="form.attachments"
v-model="form.attachments"
:readonly="readonly"
:multiple="true"
:limit="20"
@@ -351,8 +353,7 @@
:file-types="attachmentFileTypes"
:show-file-list="false"
button-text="上传附件"
@update:model-value="normalizeAttachments"
@success="handleManualAttachmentUpload"
@change="normalizeAttachments"
/>
</div>
</section-card>
@@ -2045,6 +2046,9 @@ export default {
},
normalizeAttachments(files) {
const existingAttachments = this.form.attachments || [];
const userInfo = this.$store.getters.userInfo || {};
const uploadUserName = userInfo.realName || userInfo.userName || '';
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
this.form.attachments = (files || []).map(file => {
const fileUrl = this.attachmentFileUrl(file);
const existingFile = existingAttachments.find(item => {
@@ -2058,28 +2062,11 @@ export default {
attachmentType:
existingFile?.attachmentType || this.resolveAttachmentTypeByFileName(file),
description: file.description || existingFile?.description || '',
uploadUserName: existingFile?.uploadUserName || file.uploadUserName || uploadUserName,
uploadTime: existingFile?.uploadTime || file.uploadTime || uploadTime,
};
});
},
handleManualAttachmentUpload(uploadedFile) {
const uploadedUrl = this.attachmentFileUrl(uploadedFile);
const uploadedUid = uploadedFile?.uid;
const userInfo = this.$store.getters.userInfo || {};
const uploadUserName = userInfo.realName || userInfo.userName || '';
const uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
this.form.attachments = (this.form.attachments || []).map(file => {
const isUploadedFile =
(uploadedUid && file.uid === uploadedUid) ||
(uploadedUrl && this.attachmentFileUrl(file) === uploadedUrl);
return isUploadedFile
? {
...file,
uploadUserName,
uploadTime,
}
: file;
});
},
formatAttachmentSize(file = {}) {
const rawSize = file.size ?? file.fileSize ?? file.attachSize;
if (rawSize === undefined || rawSize === null || rawSize === '') return '-';
@@ -407,8 +407,51 @@
</el-table>
</section-card>
<section-card v-if="readonly" title="付款信息">
<el-table :data="paymentApplications" border>
<section-card
v-if="readonly"
:title="form.settlementType === 'receivable' ? '收款信息' : '付款信息'"
>
<el-table
v-if="form.settlementType === 'receivable'"
:data="receiptClaims"
border
empty-text="暂无收款认领数据"
>
<el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column
prop="receiptNoticeNo"
label="认领通知单"
min-width="160"
align="center"
/>
<el-table-column prop="payerName" label="付款人" min-width="150" align="center">
<template #default="{ row }">{{ displayValue(row.payerName) }}</template>
</el-table-column>
<el-table-column prop="receiptAmount" label="收款金额" min-width="130" align="center">
<template #default="{ row }">{{ formatMoney(row.receiptAmount) }}</template>
</el-table-column>
<el-table-column
prop="allocatedReceiptAmount"
label="本次认领金额"
min-width="145"
align="center"
>
<template #default="{ row }">{{ formatMoney(row.allocatedReceiptAmount) }}</template>
</el-table-column>
<el-table-column prop="transactionTime" label="交易时间" min-width="170" align="center">
<template #default="{ row }">{{ displayValue(row.transactionTime) }}</template>
</el-table-column>
<el-table-column prop="claimerName" label="认领人" min-width="120" align="center">
<template #default="{ row }">{{ displayValue(row.claimerName) }}</template>
</el-table-column>
<el-table-column prop="claimDate" label="认领日期" min-width="130" align="center">
<template #default="{ row }">{{ displayValue(row.claimDate) }}</template>
</el-table-column>
<el-table-column prop="claimStatusName" label="认领状态" min-width="120" align="center">
<template #default="{ row }">{{ displayValue(row.claimStatusName) }}</template>
</el-table-column>
</el-table>
<el-table v-else :data="paymentApplications" border>
<el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column prop="paymentTypeName" label="付款类型" min-width="120" align="center">
<template #default="{ row }">{{ displayValue(row.paymentTypeName) }}</template>
@@ -737,6 +780,7 @@ import {
getDetailFees,
getFeeOptions,
getNextNo,
getReceiptClaims,
save,
} from '@/api/settlement/formalSettlement';
import { getDetail as getPreSettlementDetail } from '@/api/settlement/preSettlement';
@@ -779,6 +823,7 @@ export default {
details: [],
summaryFees: [],
paymentApplications: [],
receiptClaims: [],
adjustments: [],
changeRecords: [],
attachments: [],
@@ -958,6 +1003,7 @@ export default {
this.details = [];
this.summaryFees = [];
this.paymentApplications = [];
this.receiptClaims = [];
this.adjustments = [];
this.changeRecords = [];
this.attachments = [];
@@ -1002,6 +1048,9 @@ export default {
this.details = data.details || [];
this.summaryFees = data.summaryFees || [];
this.paymentApplications = data.paymentApplications || [];
if (this.readonly && this.form.settlementType === 'receivable') {
this.receiptClaims = this.unwrapData(await getReceiptClaims(this.recordId)) || [];
}
this.adjustments = data.adjustments || [];
this.changeRecords = data.changeRecords || [];
this.attachments = this.parseAttachments(data.attachmentsJson);
@@ -1690,11 +1739,8 @@ export default {
.filter(row => row.pendingDetailAdjustment)
.map(row => ({
sourcePreSettlementDetailId:
row.sourcePreSettlementDetailId ||
(row.sourcePreSettlementId ? row.id : undefined),
sourceDetailId: row.sourcePreSettlementId
? undefined
: row.sourceDetailId || row.id,
row.sourcePreSettlementDetailId || (row.sourcePreSettlementId ? row.id : undefined),
sourceDetailId: row.sourcePreSettlementId ? undefined : row.sourceDetailId || row.id,
adjustAmount: Number(row.adjustAmount || 0),
})),
exchangeRateDate: this.form.exchangeRateDate,
+3
View File
@@ -131,6 +131,9 @@
<span v-else-if="column.precision !== undefined">
{{ formatNumber(row[column.prop], column.precision) }}
</span>
<span v-else-if="column.prop === 'sourceType'">
{{ row[column.prop] === '应收应付' ? '应付' : displayValue(row[column.prop]) }}
</span>
<span v-else>{{ displayValue(row[column.prop]) }}</span>
</template>
</el-table-column>
@@ -34,7 +34,12 @@
<div class="settlement-detail-page__toolbar-left">
<el-button type="primary" @click="openGenerateDialog">生成费用</el-button>
<el-button type="primary" plain @click="openUpdateFeeDialog">更新费用</el-button>
<el-button v-if="isPayable" type="primary" plain @click="openTransferDialog">
<el-button
v-if="isPayable || isReceivable"
type="primary"
plain
@click="openTransferDialog"
>
批量转结算
</el-button>
<el-button type="primary" plain @click="handleExport">导出</el-button>
@@ -457,6 +462,7 @@
v-model="transferForm.settlementBillType"
@change="handleTransferTypeChange"
>
<el-radio v-if="isPayable" label="pre">预结算单</el-radio>
<el-radio label="formal">正式结算单</el-radio>
</el-radio-group>
</el-form-item>
@@ -784,7 +790,7 @@ export default {
billingPlanOptions: [],
transferDialog: { visible: false, loading: false, submitting: false },
transferQuery: {},
transferForm: { settlementBillType: 'formal' },
transferForm: { settlementBillType: 'pre' },
transferRows: [],
transferSelection: [],
transferPage: { current: 1, size: 10, total: 0 },
@@ -1594,7 +1600,7 @@ export default {
},
openTransferDialog() {
this.transferDialog.visible = true;
this.transferForm = { settlementBillType: 'formal' };
this.transferForm = { settlementBillType: this.isReceivable ? 'formal' : 'pre' };
this.transferQuery = {};
this.transferRows = [];
this.transferSelection = [];
@@ -1724,7 +1730,9 @@ export default {
try {
const transferRows = await this.resolveTransferContractIds(this.transferSelection);
if (!transferRows) return;
const settlementBillType = this.transferForm.settlementBillType;
const settlementBillType = this.isReceivable
? 'formal'
: this.transferForm.settlementBillType;
const transferToken = createSettlementTransfer({
settlementBillType,
settlementType: this.settlementType || transferRows[0]?.settlementType,