1、调整合同

2、调整项目
3、调整付款管理
This commit is contained in:
2026-08-26 02:31:12 +08:00
parent 3da2d428f3
commit dc5a2235eb
13 changed files with 1184 additions and 235 deletions
@@ -1056,6 +1056,7 @@ export default {
id: row.id || undefined,
feeType: row.feeType || '',
feeItem: row.feeItem,
originalAmount: Number(row.originalAmount || 0),
adjustAmount: Number(row.adjustAmount || 0),
remark: row.remark,
manualFlag: row.manualFlag || 0,
@@ -141,7 +141,17 @@
</section-card>
<section-card title="附件材料">
<el-table :data="attachments" border>
<div class="settlement-adjustment-editor__attachment-actions">
<el-button
type="primary"
:disabled="!attachments.length"
@click="batchDownloadAttachments"
>
批量下载
</el-button>
</div>
<el-table :data="attachments" border @selection-change="selectedAttachments = $event">
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="64" align="center" />
<el-table-column label="文件名" min-width="220" show-overflow-tooltip>
<template #default="{ row }">
@@ -264,6 +274,7 @@ export default {
fields: settlementAdjustmentFormFields,
details: [],
attachments: [],
selectedAttachments: [],
attachmentFileTypes: [
'pdf',
'bmp',
@@ -320,6 +331,7 @@ export default {
this.form = createSettlementAdjustmentForm();
this.details = [];
this.attachments = [];
this.selectedAttachments = [];
this.candidates = [];
this.feeRows = [];
if (!this.recordId) {
@@ -347,6 +359,22 @@ export default {
this.candidates = data?.data || data || [];
},
async handleFormalChange(id) {
if (!id) {
Object.assign(this.form, {
formalSettlementId: null,
formalSettlementNo: '',
settlementType: '',
projectName: '',
deptName: '',
customerName: '',
contractNo: '',
contractName: '',
originalSettlementAmount: 0,
});
this.details = [];
this.recalculate();
return;
}
const item = this.candidates.find(row => String(row.id) === String(id));
if (!item) return;
const { id: formalSettlementId, ...formalSettlement } = item;
@@ -358,6 +386,21 @@ export default {
});
this.details = [];
this.recalculate();
this.loading = true;
try {
const { data } = await api.getFormalDetails(formalSettlementId);
if (String(this.form.formalSettlementId) !== String(formalSettlementId)) return;
this.details = (data?.data || data || []).map(fee => ({
...fee,
originalAmountTax: Number(fee.originalAmountTax || 0),
adjustmentAmountTax: 0,
adjustmentAmountNoTax: null,
remark: '',
}));
this.recalculate();
} finally {
this.loading = false;
}
},
async openFeeDialog() {
const { data } = await api.getFormalDetails(this.form.formalSettlementId);
@@ -432,6 +475,7 @@ export default {
uploadUserName: file.uploadUserName || uploadUserName,
uploadTime: file.uploadTime || uploadTime,
}));
this.selectedAttachments = [];
},
parseAttachments(value) {
if (!value) return [];
@@ -467,8 +511,22 @@ export default {
}
downloadFileByUrl(url, this.attachmentName(file));
},
batchDownloadAttachments() {
const files = this.selectedAttachments.length ? this.selectedAttachments : this.attachments;
const downloadableFiles = files.filter(file => this.attachmentUrl(file));
if (!downloadableFiles.length) {
this.$message.warning(
this.selectedAttachments.length ? '所选附件暂无可下载地址' : '暂无可下载附件'
);
return;
}
downloadableFiles.forEach((file, index) => {
window.setTimeout(() => this.downloadAttachment(file), index * 200);
});
},
removeAttachment(index) {
this.attachments.splice(index, 1);
const [removed] = this.attachments.splice(index, 1);
this.selectedAttachments = this.selectedAttachments.filter(file => file !== removed);
},
},
};
@@ -484,6 +542,11 @@ export default {
padding: 12px 0;
text-align: right;
}
.settlement-adjustment-editor__attachment-actions {
display: flex;
justify-content: flex-end;
margin-bottom: 12px;
}
.settlement-adjustment-editor__attachment-upload {
padding-top: 12px;
}
+40 -110
View File
@@ -53,8 +53,8 @@
v-if="hasPermission('pre_settlement_advance')"
type="primary"
plain
disabled
@click="openAdvanceDialog"
:disabled="!selection.length"
@click="handleAdvanceApplication"
>
预付申请
</el-button>
@@ -215,52 +215,6 @@
@success="loadTable"
/>
<el-dialog v-model="advanceDialog.visible" title="预付申请" width="520px" append-to-body>
<el-form
ref="advanceFormRef"
:model="advanceForm"
:rules="advanceRules"
label-position="right"
label-width="auto"
>
<el-form-item label="预结算单号">
<span>{{ advanceDialog.row.preSettlementNo || '-' }}</span>
</el-form-item>
<el-form-item label="结算金额">
<span>
{{ formatMoney(advanceDialog.row.settlementAmount, advanceDialog.row.currency) }}
</span>
</el-form-item>
<el-form-item label="已申请预付金额">
<span>
{{ formatMoney(advanceDialog.row.advanceAppliedAmount, advanceDialog.row.currency) }}
</span>
</el-form-item>
<el-form-item label="申请预付金额" prop="appliedAmount">
<el-input-number
v-model="advanceForm.appliedAmount"
:min="0"
:max="advanceAvailableAmount"
:precision="2"
:controls="false"
/>
</el-form-item>
<el-form-item label="金蝶预付单号">
<el-input
v-model="advanceForm.kingdeeAdvanceNo"
maxlength="100"
placeholder="外部系统回写时可填写"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="advanceDialog.visible = false">取消</el-button>
<el-button type="primary" :loading="advanceDialog.submitting" @click="submitAdvance">
提交
</el-button>
</template>
</el-dialog>
<el-dialog
v-model="printDialog.visible"
title="打印"
@@ -316,7 +270,6 @@
import { ArrowDown, ArrowUp, Refresh } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
import {
applyAdvance,
approve,
exportList,
getDetail,
@@ -370,34 +323,6 @@ export default {
id: '',
readonly: false,
},
advanceDialog: {
visible: false,
submitting: false,
row: {},
},
advanceForm: {
appliedAmount: null,
kingdeeAdvanceNo: '',
},
advanceRules: {
appliedAmount: [
{ required: true, message: '请输入申请预付金额', trigger: 'blur' },
{
validator: (_rule, value, callback) => {
if (!value || Number(value) <= 0) {
callback(new Error('申请预付金额必须大于0'));
return;
}
if (Number(value) > this.advanceAvailableAmount) {
callback(new Error('申请预付金额不能超过剩余可申请金额'));
return;
}
callback();
},
trigger: ['blur', 'change'],
},
],
},
printDialog: {
visible: false,
loading: false,
@@ -422,13 +347,6 @@ export default {
visibleSearchFields() {
return this.searchExpanded ? this.searchFields : this.searchFields.slice(0, 4);
},
advanceAvailableAmount() {
return Math.max(
Number(this.advanceDialog.row.settlementAmount || 0) -
Number(this.advanceDialog.row.advanceAppliedAmount || 0),
0
);
},
},
watch: {
'$route.query.detailNo'(detailNo) {
@@ -525,37 +443,49 @@ export default {
}
return this.selection[0];
},
openAdvanceDialog() {
const row = this.selectedOne('预付申请');
if (!row) return;
handleAdvanceApplication() {
if (!this.selection.length) {
this.$message.warning('请选择需要发起预付申请的预结算单');
return;
}
if (this.selection.some(row => !row.contractId)) {
this.$message.warning('所选预结算单缺少合同ID,无法发起预付申请');
return;
}
const contractIds = new Set(this.selection.map(row => String(row.contractId)));
if (contractIds.size > 1) {
this.$message.warning('预付申请只能选择同一合同下的预结算单');
return;
}
if (
row.approvalStatus !== 'approved' ||
row.settlementType !== 'payable' ||
row.formalSettlementNo
this.selection.some(
row =>
row.approvalStatus !== 'approved' ||
row.settlementType !== 'payable' ||
row.formalSettlementNo
)
) {
this.$message.warning('仅审批通过、未转正式结算的应付预结算单可发起预付');
return;
}
this.advanceDialog.row = row;
this.advanceDialog.visible = true;
this.advanceForm = { appliedAmount: null, kingdeeAdvanceNo: '' };
this.$nextTick(() => this.$refs.advanceFormRef?.clearValidate());
},
async submitAdvance() {
await this.$refs.advanceFormRef?.validate();
this.advanceDialog.submitting = true;
try {
await applyAdvance({
preSettlementId: this.advanceDialog.row.id,
appliedAmount: this.advanceForm.appliedAmount,
kingdeeAdvanceNo: this.advanceForm.kingdeeAdvanceNo,
});
this.$message.success('预付申请提交成功');
this.advanceDialog.visible = false;
this.loadTable();
} finally {
this.advanceDialog.submitting = false;
}
const sourcePreSettlements = this.selection.map(row => ({
...row,
preSettlementId: row.preSettlementId || row.id,
}));
const transferToken = createSettlementTransfer({
sourcePreSettlements,
});
this.$router.push({
path: '/payment/payment-application/form',
query: {
mode: 'add',
transferToken,
preSettlementIds: sourcePreSettlements
.map(row => row.preSettlementId)
.filter(Boolean)
.join(','),
},
});
},
handleFormalSettlement() {
if (!this.selection.length) {