Merge remote-tracking branch 'origin/master' into feature/hcs-api-p0-web

This commit is contained in:
刘泉佳
2026-10-22 09:43:02 +08:00
108 changed files with 7779 additions and 1683 deletions
+117 -43
View File
@@ -44,7 +44,8 @@
reserve-keyword
:remote-method="searchCustomers"
:loading="customerLoading"
placeholder="请选择客商基础档案"
placeholder="请选择"
@change="syncFeeBearer"
>
<el-option
v-for="item in customerOptions"
@@ -63,6 +64,7 @@
allow-create
default-first-option
placeholder="请选择或输入"
@change="syncFeeBearer"
>
<el-option
v-for="item in receiverOptions"
@@ -74,7 +76,7 @@
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="票面金额" prop="faceAmount">
<el-form-item label="票面金额" prop="faceAmount" required>
<el-input-number
v-model="form.faceAmount"
:min="0"
@@ -111,17 +113,15 @@
</el-col>
<el-col :span="6">
<el-form-item label="可用部门" prop="availableDeptIds">
<el-tree-select
v-model="form.availableDeptIds"
:data="deptTree"
:props="deptProps"
node-key="id"
multiple
show-checkbox
<el-cascader
v-model="availableDeptCascaderValue"
:options="businessDeptTreeOptions"
:props="deptCascaderProps"
placeholder="请选择"
filterable
clearable
collapse-tags
collapse-tags-tooltip
placeholder="请选择,默认全部"
@change="handleDeptChange"
/>
</el-form-item>
</el-col>
@@ -140,17 +140,9 @@
</el-col>
<el-col :span="6">
<el-form-item label="费用承担方" prop="feeBearerId">
<el-select
v-model="form.feeBearerId"
filterable
remote
reserve-keyword
:remote-method="searchCustomers"
:loading="customerLoading"
placeholder="请选择客商基础档案"
>
<el-select v-model="form.feeBearerId" filterable clearable placeholder="请选择">
<el-option
v-for="item in customerOptions"
v-for="item in feeBearerOptions"
:key="item.id"
:label="customerName(item)"
:value="item.id"
@@ -245,13 +237,13 @@ const emptyForm = () => ({
billNo: '',
issuerId: null,
receiverName: '',
billType: 'issued',
billType: '',
faceAmount: null,
availableBalance: 0,
issueDate: '',
maturityDate: '',
availableDeptIds: ['all'],
availableDeptNames: '全部',
availableDeptIds: [],
availableDeptNames: '',
feeBearerId: null,
confirmedDiscountRate: null,
issuingBank: '',
@@ -272,9 +264,17 @@ export default {
receiverOptions: [],
customerLoading: false,
saving: false,
deptTree: [],
businessDeptTreeOptions: [],
deptMap: new Map(),
deptProps: { label: 'title', value: 'id', children: 'children' },
deptCascaderProps: {
label: 'label',
value: 'value',
children: 'children',
multiple: true,
checkStrictly: true,
emitPath: true,
expandTrigger: 'click',
},
bankOptions: [
'中国工商银行',
'中国农业银行',
@@ -309,7 +309,10 @@ export default {
issuerId: [{ required: true, message: '请选择出票单位', trigger: 'change' }],
receiverName: [{ required: true, message: '请选择或输入收票单位', trigger: 'change' }],
billType: [{ required: true, message: '请选择汇票类型', trigger: 'change' }],
faceAmount: [{ validator: this.validateFaceAmount, trigger: 'change' }],
faceAmount: [
{ required: true, message: '请输入票面金额', trigger: 'change' },
{ validator: this.validateFaceAmount, trigger: 'change' },
],
issueDate: [{ required: true, message: '请选择出票日期', trigger: 'change' }],
maturityDate: [{ required: true, validator: this.validateMaturityDate, trigger: 'change' }],
availableDeptIds: [{ validator: this.validateDepartments, trigger: 'change' }],
@@ -340,6 +343,42 @@ export default {
(Number(this.form.faceAmount || 0) * Number(this.form.confirmedDiscountRate || 0)) / 100
);
},
// 可用部门:表单存部门 id,级联多选回显用根到节点的路径
availableDeptCascaderValue: {
get() {
return (this.form.availableDeptIds || [])
.filter(id => id !== undefined && id !== null && String(id) !== 'all' && String(id) !== '')
.map(id => this.findDeptPath(id, this.businessDeptTreeOptions) || [String(id)]);
},
set(paths) {
const ids = [
...new Set(
(paths || [])
.map(path => {
const nodes = Array.isArray(path) ? path.filter(item => item !== undefined && item !== null && item !== '') : [];
return nodes.length ? String(nodes.at(-1)) : '';
})
.filter(Boolean)
),
];
this.form.availableDeptIds = ids;
this.form.availableDeptNames = ids
.map(id => this.deptMap.get(String(id)))
.filter(Boolean)
.join('、');
},
},
feeBearerOptions() {
const issuer = this.customerOptions.find(item => String(item.id) === String(this.form.issuerId));
const receiverName = String(this.form.receiverName || '').trim();
const receiver = receiverName
? this.customerOptions.find(item => this.customerName(item) === receiverName)
: null;
return [issuer, receiver].filter(
(item, index, rows) =>
item && rows.findIndex(row => row && String(row.id) === String(item.id)) === index
);
},
},
created() {
this.initialize();
@@ -352,7 +391,6 @@ export default {
async initialize() {
await Promise.all([this.loadDepartments(), this.searchCustomers('')]);
if (!this.recordId) {
this.form.issueDate = this.$dayjs().format('YYYY-MM-DD');
return;
}
const data = this.unwrapData(await api.getDetail(this.recordId));
@@ -361,14 +399,20 @@ export default {
...data,
confirmedDiscountRate: this.normalizeDiscountRate(data.confirmedDiscountRate),
bankDiscountReferenceRate: this.normalizeDiscountRate(data.bankDiscountReferenceRate),
availableDeptIds: this.parse(data.availableDeptIdsJson),
availableDeptIds: this.parse(data.availableDeptIdsJson)
.filter(id => String(id) !== 'all')
.map(id => String(id)),
attachments: this.parse(data.attachmentsJson),
};
this.usageRecords = data.usageRecords || [];
this.receiverOptions = data.receiverName ? [data.receiverName] : [];
this.ensureCustomerOption(data.issuerId, data.issuerName);
this.ensureCustomerOption(data.feeBearerId, data.feeBearerName);
this.handleDeptChange(this.form.availableDeptIds);
this.form.availableDeptNames = (this.form.availableDeptIds || [])
.map(id => this.deptMap.get(String(id)))
.filter(Boolean)
.join('、');
this.syncFeeBearer();
},
parse(value) {
if (!value) return [];
@@ -381,22 +425,52 @@ export default {
},
async loadDepartments() {
const response = await getDeptTree(this.userInfo?.tenantId);
const rows = this.unwrapData(response) || [];
this.deptTree = [{ id: 'all', title: '全部', children: rows }];
this.deptMap = new Map([['all', '全部']]);
this.flattenDepartments(rows).forEach(item => this.deptMap.set(String(item.id), item.title));
const rows = this.excludeExternalOrganization(this.unwrapData(response) || []);
this.businessDeptTreeOptions = this.toDeptCascaderOptions(rows);
this.deptMap = new Map();
this.flattenDepartments(rows).forEach(item =>
this.deptMap.set(String(item.id), item.title || item.deptName || item.name)
);
},
excludeExternalOrganization(list = []) {
return list.reduce((result, item) => {
const deptName = item.title || item.deptName || item.name;
if (String(deptName || '').trim() === '外部组织') return result;
result.push({
...item,
children: item.children?.length
? this.excludeExternalOrganization(item.children)
: item.children,
});
return result;
}, []);
},
toDeptCascaderOptions(list = []) {
return list.map(item => ({
label: item.title || item.deptName || item.name,
value: item.id == null || item.id === '' ? '' : String(item.id),
children: item.children?.length ? this.toDeptCascaderOptions(item.children) : undefined,
}));
},
flattenDepartments(rows) {
return (rows || []).flatMap(item => [item, ...this.flattenDepartments(item.children || [])]);
},
handleDeptChange(values) {
const ids = values || [];
this.form.availableDeptNames = ids.some(item => String(item) === 'all')
? '全部'
: ids
.map(item => this.deptMap.get(String(item)))
.filter(Boolean)
.join('、');
findDeptPath(id, tree = [], parents = []) {
const target = Array.isArray(id) ? id.at(-1) : id;
if (target === undefined || target === null || target === '') return null;
for (const node of tree || []) {
const path = [...parents, node.value];
if (String(node.value) === String(target)) return path;
const matched = this.findDeptPath(target, node.children, path);
if (matched) return matched;
}
return null;
},
syncFeeBearer() {
const allowed = this.feeBearerOptions.map(item => String(item.id));
if (this.form.feeBearerId && !allowed.includes(String(this.form.feeBearerId))) {
this.form.feeBearerId = null;
}
},
async searchCustomers(keyword) {
this.customerLoading = true;
@@ -545,7 +619,7 @@ export default {
.bill-ledger-form-page__form :deep(.el-select),
.bill-ledger-form-page__form :deep(.el-input-number),
.bill-ledger-form-page__form :deep(.el-date-editor),
.bill-ledger-form-page__form :deep(.el-tree-select) {
.bill-ledger-form-page__form :deep(.el-cascader) {
width: 100%;
}
.bill-ledger-form-page__form :deep(.el-input-number .el-input__inner) {
+2 -1
View File
@@ -140,7 +140,7 @@ import * as api from '@/api/payment/billPayment';
import * as billLedgerApi from '@/api/payment/billLedger';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { getMkPublicDetail } from '@/api/mk-process';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
const emptyForm = () => ({
id: null,
@@ -348,6 +348,7 @@ export default {
bizId: this.form.id,
subjectName: this.form.paymentNo || this.form.billNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: await loadMkEnabled().catch(() => false),
});
this.$message.success('提交成功');
this.goBack();
+1
View File
@@ -132,6 +132,7 @@ export default {
bizId: row.id,
subjectName: row.paymentNo || row.billNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: this.mkEnabled,
});
this.$message.success('提交成功');
this.loadTable();
@@ -492,7 +492,7 @@ import { getDictionary } from '@/api/system/dictbiz';
import { invoiceApplicationDetailColumns } from '@/option/payment/invoiceApplication';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { getMkPublicDetail } from '@/api/mk-process';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
let localId = 0;
const emptyLine = () => ({
@@ -774,7 +774,7 @@ export default {
},
validateSettlements(rule, value, callback) {
if (!this.form.settlements.length) {
callback(new Error('请选择正式结算单'));
callback(new Error('请选择付款结算单'));
return;
}
callback();
@@ -1208,13 +1208,14 @@ export default {
bizId: this.form.id,
subjectName: this.form.applicationNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: await loadMkEnabled().catch(() => false),
});
this.$message.success('提交成功');
this.goBack();
},
async syncReferenceData() {
if (!this.settlementIds.length) {
this.$message.warning('请先选择正式结算单');
this.$message.warning('请先选择付款结算单');
return;
}
await Promise.all([this.loadReceiverInformation(), this.loadSettlementDetails(false)]);
+12 -1
View File
@@ -359,7 +359,7 @@ export default {
item => String(item.formalSettlementNo || '').trim() === normalizedNo
);
if (!row?.id) {
this.$message.warning('未找到对应的正式结算单');
this.$message.warning('未找到对应的付款结算单');
return;
}
this.$router.push({
@@ -384,6 +384,7 @@ export default {
bizId: row.id,
subjectName: row.applicationNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: this.mkEnabled,
});
this.$message.success('提交成功');
this.loadTable();
@@ -504,6 +505,16 @@ export default {
tip: row.kingdeeLockFailReason || '系统将自动补偿重锁',
};
}
// 金蝶解锁终态标识:删单解锁的源单已作废,此标签用于区分人工作废与金蝶删单
if (row.kingdeeUnlockTime) {
const isDelete = row.kingdeeUnlockOperationName === '金蝶删单';
return {
show: true,
type: isDelete ? 'danger' : 'warning',
label: row.kingdeeUnlockOperationName || '金蝶解锁',
tip: `${row.kingdeeUnlockOperator || '-'} 于 ${this.$dayjs(row.kingdeeUnlockTime).format('YYYY-MM-DD HH:mm:ss')} 解锁`,
};
}
return { show: false };
},
displayValue(value) {
+131 -32
View File
@@ -16,13 +16,22 @@
<el-row :gutter="32">
<el-col :span="6">
<el-form-item label="发票号码" prop="invoiceNo">
<el-input v-model="form.invoiceNo" readonly placeholder="请选择金蝶票据池发票">
<template v-if="!readonly" #append>
<el-tooltip content="查询金蝶票据池" placement="top">
<el-button :icon="Search" @click="openInvoiceDialog" />
</el-tooltip>
</template>
</el-input>
<el-tooltip
:content="form.invoiceNo"
:disabled="!form.invoiceNo"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.invoiceNo" readonly placeholder="请选择金蝶票据池发票">
<template v-if="!readonly" #append>
<el-tooltip content="查询金蝶票据池" placement="top">
<el-button :icon="Search" @click="openInvoiceDialog" />
</el-tooltip>
</template>
</el-input>
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
@@ -32,7 +41,16 @@
</el-col>
<el-col :span="6">
<el-form-item label="发票类型">
<el-input v-model="form.invoiceType" disabled placeholder="从金蝶票据池带出" />
<el-tooltip
:content="form.invoiceType"
:disabled="!form.invoiceType"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.invoiceType" disabled placeholder="从金蝶票据池带出" />
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
@@ -64,23 +82,54 @@
</el-col>
<el-col :span="6">
<el-form-item label="受票单位">
<el-input v-model="form.receiverName" disabled placeholder="从金蝶票据池带出" />
<el-tooltip
:content="form.receiverName"
:disabled="!form.receiverName"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.receiverName" disabled placeholder="从金蝶票据池带出" />
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="开票单位">
<el-input v-model="form.issuerName" disabled placeholder="从金蝶票据池带出" />
<el-tooltip
:content="form.issuerName"
:disabled="!form.issuerName"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input v-model="form.issuerName" disabled placeholder="从金蝶票据池带出" />
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="关联结算单" prop="settlementIds">
<el-input :model-value="settlementLabel" readonly placeholder="请选择应付正式结算单">
<template v-if="!readonly" #append>
<el-tooltip content="选择正式结算单" placement="top">
<el-button :icon="Search" @click="openSettlementDialog" />
</el-tooltip>
</template>
</el-input>
<el-tooltip
:content="settlementLabel"
:disabled="!settlementLabel"
placement="top"
:show-after="200"
>
<div class="receipt-form-page__overflow-trigger">
<el-input
:model-value="settlementLabel"
readonly
placeholder="请选择应付正式结算单"
>
<template v-if="!readonly" #append>
<el-tooltip content="选择付款结算单" placement="top">
<el-button :icon="Search" @click="openSettlementDialog" />
</el-tooltip>
</template>
</el-input>
</div>
</el-tooltip>
</el-form-item>
</el-col>
</el-row>
@@ -89,7 +138,12 @@
<section-card title="结算信息">
<el-table :data="form.settlements" border>
<el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column label="结算单号" min-width="180" align="center">
<el-table-column
label="结算单号"
min-width="180"
align="center"
show-overflow-tooltip
>
<template #default="{ row }">
<el-link type="primary" @click="openSettlementDetail(row)">
{{ row.formalSettlementNo }}
@@ -173,7 +227,7 @@
<el-input
v-model="settlementDialog.keyword"
clearable
placeholder="3结算单号、项目或合同"
placeholder="结算单号、项目或合同"
@keyup.enter="loadSettlementCandidates"
/>
<el-button type="primary" @click="loadSettlementCandidates">查询</el-button>
@@ -182,16 +236,32 @@
ref="settlementTable"
v-loading="settlementDialog.loading"
:data="settlementDialog.rows"
row-key="id"
border
@selection-change="settlementDialog.selection = $event"
>
<el-table-column type="selection" width="52" align="center" />
<el-table-column prop="formalSettlementNo" label="结算单号" min-width="170" />
<el-table-column prop="projectName" label="所属项目" min-width="150" />
<el-table-column prop="deptName" label="所属组织" min-width="150" />
<el-table-column prop="contractNo" label="合同编号" min-width="150" />
<el-table-column prop="payerName" label="付款方" min-width="150" />
<el-table-column prop="payeeName" label="收款方" min-width="150" />
<el-table-column type="selection" width="52" align="center" reserve-selection />
<el-table-column
prop="formalSettlementNo"
label="结算单号"
min-width="170"
show-overflow-tooltip
/>
<el-table-column
prop="projectName"
label="所属项目"
min-width="150"
show-overflow-tooltip
/>
<el-table-column prop="deptName" label="所属组织" min-width="150" show-overflow-tooltip />
<el-table-column
prop="contractNo"
label="合同编号"
min-width="150"
show-overflow-tooltip
/>
<el-table-column prop="payerName" label="付款方" min-width="150" show-overflow-tooltip />
<el-table-column prop="payeeName" label="收款方" min-width="150" show-overflow-tooltip />
<el-table-column label="结算总金额" min-width="140" align="right">
<template #default="{ row }">{{ formatMoney(row.settlementAmount) }}</template>
</el-table-column>
@@ -206,7 +276,9 @@
</el-table>
<template #footer>
<el-button @click="settlementDialog.visible = false">取消</el-button>
<el-button type="primary" @click="confirmSettlements">确定</el-button>
<el-button type="primary" @click="confirmSettlements">
确定{{ settlementDialog.selection.length ? `(${settlementDialog.selection.length})` : '' }}
</el-button>
</template>
</el-dialog>
</basic-container>
@@ -219,7 +291,7 @@ import * as api from '@/api/payment/invoiceReceipt';
import KingdeeInvoicePoolDialog from '@/components/kingdee-invoice-pool-dialog/main.vue';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { getMkPublicDetail } from '@/api/mk-process';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
const emptyForm = () => ({
id: null,
@@ -437,7 +509,15 @@ export default {
},
async openSettlementDialog() {
this.settlementDialog.visible = true;
this.settlementDialog.selection = [];
await this.loadSettlementCandidates();
await this.$nextTick();
const selectedIds = new Set(this.settlementIds.map(id => String(id)));
this.settlementDialog.rows.forEach(row => {
if (selectedIds.has(String(row.id))) {
this.$refs.settlementTable?.toggleRowSelection(row, true);
}
});
},
async loadSettlementCandidates() {
this.settlementDialog.loading = true;
@@ -468,11 +548,21 @@ export default {
this.$message.warning('关联结算单必须属于同一项目、组织及收付款方');
return;
}
const previousAmount = new Map(
this.form.settlements.map(item => [
String(item.formalSettlementId || item.settlementId),
item.allocatedInvoiceAmount,
])
);
this.form.settlements = rows.map(item => ({
...item,
formalSettlementId: item.id,
settlementId: item.id,
allocatedInvoiceAmount: rows.length === 1 ? Number(item.settlementAmount || 0) : 0,
allocatedInvoiceAmount: previousAmount.has(String(item.id))
? Number(previousAmount.get(String(item.id)) || 0)
: rows.length === 1
? Number(item.settlementAmount || 0)
: 0,
}));
this.form.projectName = first.projectName;
this.form.deptName = first.deptName;
@@ -482,9 +572,8 @@ export default {
await this.loadReferenceInformation();
this.$refs.formRef?.validateField('settlementIds').catch(() => {});
},
async selectSettlement(row) {
this.settlementDialog.selection = [row];
await this.confirmSettlements();
selectSettlement(row) {
this.$refs.settlementTable?.toggleRowSelection(row);
},
async loadReferenceInformation() {
const data = this.unwrapData(await api.getReferenceInformation(this.settlementIds.join(',')));
@@ -571,6 +660,7 @@ export default {
bizId: this.form.id,
subjectName: this.form.invoiceNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: await loadMkEnabled().catch(() => false),
});
this.$message.success('提交成功');
this.goBack();
@@ -616,6 +706,15 @@ export default {
.receipt-form-page__form :deep(.el-input-number) {
width: 100%;
}
.receipt-form-page__overflow-trigger {
display: block;
width: 100%;
min-width: 0;
}
.receipt-form-page__form :deep(.el-tooltip__trigger:not(.el-select__wrapper)) {
display: block;
width: 100%;
}
.receipt-form-page__remark :deep(.el-form-item__content) {
margin-left: 0 !important;
}
+1
View File
@@ -341,6 +341,7 @@ export default {
bizId: row.id,
subjectName: row.invoiceNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: this.mkEnabled,
});
this.$message.success('提交成功');
this.loadTable();
File diff suppressed because it is too large Load Diff
+51 -7
View File
@@ -152,6 +152,9 @@ import organizationSearch from '@/mixins/organization-search';
import { getMKApprovalUrl } from '@/api/system/business-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
const paymentApplicationListRoute = '/payment/payment-application';
const paymentApplicationListRefreshKey = 'payment-application-list-refresh';
export default {
name: 'PaymentApplication',
mixins: [organizationSearch],
@@ -160,6 +163,7 @@ export default {
rows: [],
selection: [],
loading: false,
approveLoading: false,
syncLoading: false,
resultSyncing: false,
query: {},
@@ -193,7 +197,28 @@ export default {
this.mkEnabled = false;
});
},
activated() {
this.consumeListRefreshFlag();
},
watch: {
$route(to, from) {
if (
to.path === paymentApplicationListRoute &&
from?.path?.includes('/payment-application/form')
) {
this.consumeListRefreshFlag();
}
},
},
methods: {
/** 表单提交成功后带标记返回时,重新拉取列表 */
consumeListRefreshFlag() {
if (!sessionStorage.getItem(paymentApplicationListRefreshKey)) {
return;
}
sessionStorage.removeItem(paymentApplicationListRefreshKey);
this.onLoad(this.page);
},
hasPermission(code) {
return this.permission?.[code] !== false;
},
@@ -296,19 +321,28 @@ export default {
bizId: row.id,
subjectName: row.paymentNo || '',
approvalStatus: previousApprovalStatus,
mkEnabled: this.mkEnabled,
});
this.$message.closeAll?.();
this.$message.success('提交成功');
this.refreshChange();
},
async handleApprove(row) {
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
if (res.data.data === false) {
this.$message.warning(res.data.msg);
} else {
this.$message.success(res.data.msg || '审批通过');
// 防止重复点击:请求进行中忽略后续点击
if (this.approveLoading) return;
this.approveLoading = true;
try {
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
if (res.data.data === false) {
this.$message.warning(res.data.msg);
} else {
this.$message.success(res.data.msg || '审批通过');
}
this.refreshChange();
} finally {
this.approveLoading = false;
}
this.refreshChange();
},
handleMkAudit(row) {
if (!row?.id) {
@@ -441,6 +475,16 @@ export default {
tip: row.kingdeeLockFailReason || '系统将自动补偿重锁',
};
}
// 金蝶解锁终态标识:后端按 unlocked 锁记录回填(付款申请不作废,仅此标识可区分金蝶删单与推送失败)
if (row.kingdeeUnlockTime) {
const isDelete = row.kingdeeUnlockOperationName === '金蝶删单';
return {
show: true,
type: isDelete ? 'danger' : 'warning',
label: row.kingdeeUnlockOperationName || '金蝶解锁',
tip: `${row.kingdeeUnlockOperator || '-'} 于 ${this.$dayjs(row.kingdeeUnlockTime).format('YYYY-MM-DD HH:mm:ss')} 解锁`,
};
}
return { show: false };
},
displayValue(value) {
+18 -1
View File
@@ -46,6 +46,9 @@
<el-table-column label="金蝶未认领金额" min-width="140" align="right">
<template #default="{ row }">{{ formatMoney(row.unclaimedAmount) }}</template>
</el-table-column>
<el-table-column label="剩余可认领金额" min-width="140" align="right">
<template #default="{ row }">{{ formatMoney(flowRemaining(row)) }}</template>
</el-table-column>
<el-table-column prop="summary" label="摘要" min-width="180" show-overflow-tooltip />
</el-table>
<el-row :gutter="32" class="receipt-claim-batch-form-page__claim-info">
@@ -298,10 +301,24 @@ export default {
0
);
},
flowRemaining(flow) {
const unclaimed = Number(flow.unclaimedAmount || 0);
const receipt = Number(flow.receiptAmount || 0);
const ceiling = unclaimed > 0 && receipt > 0 ? Math.min(unclaimed, receipt) : unclaimed || receipt;
return Math.max(ceiling - Number(flow.claimedAmount || 0), 0);
},
maxAllocation(row) {
const current = Number(row.settlement.allocations?.[row.flow.id] || 0);
const otherTotal = this.settlementAllocatedTotal(row.settlement) - current;
return Math.max(this.settlementRemaining(row.settlement) - otherTotal, 0);
// 流水维度:该流水其余分摊已占用部分同样挤占剩余可认领金额
const flowOtherTotal = this.flowAllocatedTotal(row.flow.id) - current;
return Math.max(
Math.min(
this.settlementRemaining(row.settlement) - otherTotal,
this.flowRemaining(row.flow) - flowOtherTotal
),
0
);
},
handleAllocationChange(settlement) {
const total = this.settlementAllocatedTotal(settlement);
+15 -7
View File
@@ -252,10 +252,11 @@ export default {
);
},
claimableAmount() {
return Math.max(
Number(this.form.unclaimedAmount || 0) - Number(this.form.claimedAmount || 0),
0
);
const unclaimed = Number(this.form.unclaimedAmount || 0);
const receipt = Number(this.form.receiptAmount || 0);
const ceiling =
unclaimed > 0 && receipt > 0 ? Math.min(unclaimed, receipt) : unclaimed || receipt;
return Math.max(ceiling - Number(this.form.claimedAmount || 0), 0);
},
},
created() {
@@ -274,14 +275,21 @@ export default {
}
const data = this.unwrapData(await api.getDetail(this.flowId));
const userInfo = this.$store.getters.userInfo || {};
// 部分认领继续认领:预填本流水历史关联且仍有剩余可认领金额的结算单
const relatedSettlements = (data?.relatedSettlements || []).map(item => ({
...item,
formalSettlementId: item.id,
settlementId: item.id,
allocatedReceiptAmount: 0,
}));
this.form = {
...emptyForm(),
...data,
claimerName: userInfo.realName || userInfo.userName || data.claimerName || '',
claimerDeptName: userInfo.deptName || userInfo.dept_name || data.claimerDeptName || '',
claimDate: this.$dayjs().format('YYYY-MM-DD'),
settlementIds: [],
settlements: [],
settlementIds: relatedSettlements.map(item => item.formalSettlementId),
settlements: relatedSettlements,
attachments: [],
};
},
@@ -347,7 +355,7 @@ export default {
return;
}
if (this.allocatedTotal > this.claimableAmount + 0.001) {
this.$message.warning('累计认领金额不能超过公告未认领金额(剩余可认领金额)');
this.$message.warning('累计认领金额不能超过剩余可认领金额');
return;
}
for (const row of this.form.settlements)