|
|
|
|
@ -147,12 +147,12 @@
|
|
|
|
|
<el-table-column label="项目名称" align="center" prop="projectName" width="150" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="合同编号" align="center" prop="contractCode" width="120" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="合同名称" align="center" prop="contractName" width="150" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="分款阶段" align="center" prop="stageName" width="100" />
|
|
|
|
|
<el-table-column label="分款金额" align="center" width="100">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
<span class="font-medium">¥{{ formatMoney(row.detailAmount) }}</span>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="分款阶段" align="center" prop="stageName" width="100" />
|
|
|
|
|
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
|
|
|
|
|
<el-table-column label="操作" align="center" width="100" fixed="right">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
@ -236,8 +236,8 @@
|
|
|
|
|
<ContractSelectDialog v-model:visible="showContractDialog" @contract-selected="handleContractSelected" />
|
|
|
|
|
|
|
|
|
|
<!-- 分款明细表单对话框 -->
|
|
|
|
|
<el-dialog :title="detailDialog.title" v-model="detailDialog.visible" width="500px" append-to-body>
|
|
|
|
|
<el-form ref="detailFormRef" :model="detailForm" :rules="detailRules" label-width="100px">
|
|
|
|
|
<el-dialog :title="detailDialog.title" v-model="detailDialog.visible" width="560px" append-to-body>
|
|
|
|
|
<el-form ref="detailFormRef" :model="detailForm" :rules="detailRules" label-width="120px">
|
|
|
|
|
<el-form-item label="项目编号">
|
|
|
|
|
<el-input v-model="detailForm.projectCode" disabled />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
@ -250,10 +250,23 @@
|
|
|
|
|
<el-form-item label="合同名称">
|
|
|
|
|
<el-input v-model="detailForm.contractName" disabled />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="合同额">
|
|
|
|
|
<span class="font-medium text-gray-800">{{ contractTotalPriceDisplay }}</span>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="分款节点" prop="paymentStageId">
|
|
|
|
|
<el-select v-model="detailForm.paymentStageId" placeholder="请选择分款节点" style="width: 100%">
|
|
|
|
|
<div style="display: flex; flex-flow: row nowrap; align-items: center; gap: 12px; width: 100%; min-width: 0; overflow-x: auto">
|
|
|
|
|
<el-select v-model="detailForm.paymentStageId" placeholder="请选择分款节点" style="width: 150px; flex-shrink: 0">
|
|
|
|
|
<el-option v-for="stage in paymentStageList" :key="stage.paymentStageId" :label="stage.stageName" :value="stage.paymentStageId" />
|
|
|
|
|
</el-select>
|
|
|
|
|
<template v-if="detailForm.paymentStageId">
|
|
|
|
|
<span style="white-space: nowrap; flex-shrink: 0">
|
|
|
|
|
回款比例 <span>{{ selectedStagePaymentRatioText }}</span>
|
|
|
|
|
</span>
|
|
|
|
|
<span style="white-space: nowrap; flex-shrink: 0">
|
|
|
|
|
金额 <span>¥{{ formatMoneyOrDash(selectedStageContractShareAmount) }}</span>
|
|
|
|
|
</span>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="分款金额" prop="detailAmount">
|
|
|
|
|
<el-input-number
|
|
|
|
|
@ -264,7 +277,6 @@
|
|
|
|
|
placeholder="请输入分款金额"
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
controls-position="right"
|
|
|
|
|
@change="handleDetailAmountChange"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="备注">
|
|
|
|
|
@ -297,10 +309,9 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup name="FinAccountInstallment" lang="ts">
|
|
|
|
|
import { importFinAccountInstallment, listFinAccountInstallment } from '@/api/oa/erp/finAccountInstallment';
|
|
|
|
|
import { listFinAccountInstallment } from '@/api/oa/erp/finAccountInstallment';
|
|
|
|
|
import {
|
|
|
|
|
addFinAccountInstallmentDetail,
|
|
|
|
|
delFinAccountInstallmentDetail,
|
|
|
|
|
getErpFinAccountInstallmentDetailList,
|
|
|
|
|
updateFinAccountInstallmentDetail,
|
|
|
|
|
deleteInstallmentDetailByBo
|
|
|
|
|
@ -308,10 +319,8 @@ import {
|
|
|
|
|
import { FinAccountInstallmentQuery, FinAccountInstallmentVO } from '@/api/oa/erp/finAccountInstallment/types';
|
|
|
|
|
import { FinAccountInstallmentDetailForm, FinAccountInstallmentDetailVO } from '@/api/oa/erp/finAccountInstallmentDetail/types';
|
|
|
|
|
import { getErpContractPaymentMethodJoinList } from '@/api/oa/erp/finAccountReceivable';
|
|
|
|
|
import { PaymentStageVO } from '@/api/oa/base/paymentStage/types';
|
|
|
|
|
|
|
|
|
|
import { getToken } from '@/utils/auth';
|
|
|
|
|
import { DArrowLeft, UploadFilled } from '@element-plus/icons-vue';
|
|
|
|
|
import { DArrowLeft } from '@element-plus/icons-vue';
|
|
|
|
|
import ProjectSelectDialog from '@/views/oa/components/ProjectSelectDialog.vue';
|
|
|
|
|
import ContractSelectDialog from '@/views/oa/components/ContractSelectDialog.vue';
|
|
|
|
|
import { globalHeaders } from '@/utils/request';
|
|
|
|
|
@ -366,12 +375,10 @@ const formRemainingAmount = computed(() => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 导入对话框
|
|
|
|
|
const showImportDialog = ref(false);
|
|
|
|
|
const uploadRef = ref();
|
|
|
|
|
const importLoading = ref(false);
|
|
|
|
|
const importPreviewData = ref<any[]>([]);
|
|
|
|
|
const duplicateCount = ref(0);
|
|
|
|
|
const uploadHeaders = ref({ Authorization: 'Bearer ' + getToken() });
|
|
|
|
|
const importFile = ref<File | null>(null);
|
|
|
|
|
|
|
|
|
|
// 项目选择对话框
|
|
|
|
|
@ -379,26 +386,84 @@ const showProjectDialog = ref(false);
|
|
|
|
|
const showContractDialog = ref(false);
|
|
|
|
|
const selectedProject = ref<any>(null);
|
|
|
|
|
|
|
|
|
|
const paymentStageList = ref<PaymentStageVO[]>([]);
|
|
|
|
|
/** 新增时查询应收款节点信息列表 */
|
|
|
|
|
/** 合同付款节点 join 列表(含支付比例、节点约定金额等) */
|
|
|
|
|
interface ContractPaymentStageJoinRow {
|
|
|
|
|
paymentStageId: string | number;
|
|
|
|
|
stageName?: string;
|
|
|
|
|
paymentPercentage?: number | string;
|
|
|
|
|
paymentAmount?: number | string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const paymentStageList = ref<ContractPaymentStageJoinRow[]>([]);
|
|
|
|
|
|
|
|
|
|
/** 当前表单关联合同的合同额(总价),用于展示与节点金额推算 */
|
|
|
|
|
const detailFormContractTotalPrice = ref<number | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
const formatMoney = (money: number | undefined | null) => {
|
|
|
|
|
if (money === undefined || money === null) return '0.00';
|
|
|
|
|
return money.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formatMoneyOrDash = (money: number | undefined | null) => {
|
|
|
|
|
if (money === undefined || money === null || Number.isNaN(Number(money))) return '—';
|
|
|
|
|
return formatMoney(money);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const contractTotalPriceDisplay = computed(() => {
|
|
|
|
|
const v = detailFormContractTotalPrice.value;
|
|
|
|
|
if (v === undefined || v === null || Number.isNaN(Number(v))) return '—';
|
|
|
|
|
return `¥${formatMoney(v)}`;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const selectedPaymentStageRow = computed(() => {
|
|
|
|
|
const id = detailForm.paymentStageId;
|
|
|
|
|
if (id == null || id === '') return null;
|
|
|
|
|
return paymentStageList.value.find((s) => String(s.paymentStageId) === String(id)) ?? null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const selectedStagePaymentRatioText = computed(() => {
|
|
|
|
|
const row = selectedPaymentStageRow.value;
|
|
|
|
|
if (row && row.paymentPercentage !== undefined && row.paymentPercentage !== null && row.paymentPercentage !== '') {
|
|
|
|
|
const n = Number(row.paymentPercentage);
|
|
|
|
|
if (!Number.isNaN(n)) return `${n}%`;
|
|
|
|
|
}
|
|
|
|
|
const p = detailForm.contractPaymentPercentage;
|
|
|
|
|
if (p !== undefined && p !== null && !Number.isNaN(Number(p))) {
|
|
|
|
|
const n = Number(p);
|
|
|
|
|
if (!Number.isNaN(n)) return `${n}%`;
|
|
|
|
|
}
|
|
|
|
|
return '—';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/** 当前节点约定回款金额:优先付款节点列表;否则用明细 join 带回的合同节点金额/比例推算 */
|
|
|
|
|
const selectedStageContractShareAmount = computed(() => {
|
|
|
|
|
const row = selectedPaymentStageRow.value;
|
|
|
|
|
if (row) {
|
|
|
|
|
const backend = row.paymentAmount !== undefined && row.paymentAmount !== null && row.paymentAmount !== '' ? Number(row.paymentAmount) : NaN;
|
|
|
|
|
if (!Number.isNaN(backend)) return backend;
|
|
|
|
|
const total = Number(detailFormContractTotalPrice.value);
|
|
|
|
|
const pct = Number(row.paymentPercentage);
|
|
|
|
|
if (!Number.isNaN(total) && !Number.isNaN(pct)) return (total * pct) / 100;
|
|
|
|
|
}
|
|
|
|
|
const dAmt = detailForm.contractPaymentAmount;
|
|
|
|
|
if (dAmt !== undefined && dAmt !== null && !Number.isNaN(Number(dAmt))) {
|
|
|
|
|
return Number(dAmt);
|
|
|
|
|
}
|
|
|
|
|
const total = Number(detailFormContractTotalPrice.value);
|
|
|
|
|
const pct = Number(detailForm.contractPaymentPercentage);
|
|
|
|
|
if (!Number.isNaN(total) && !Number.isNaN(pct)) return (total * pct) / 100;
|
|
|
|
|
return undefined;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/** 新增时查询合同付款节点列表 */
|
|
|
|
|
const getPaymentStages = async (contractId) => {
|
|
|
|
|
paymentStageList.value = [];
|
|
|
|
|
if (contractId && contractId !== '') {
|
|
|
|
|
const res = await getErpContractPaymentMethodJoinList({ contractId: contractId });
|
|
|
|
|
console.log(res.data);
|
|
|
|
|
paymentStageList.value = res.data;
|
|
|
|
|
paymentStageList.value = (res.data || []) as ContractPaymentStageJoinRow[];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 付款阶段Mock数据
|
|
|
|
|
// const paymentStageList = ref([
|
|
|
|
|
// { id: 1, stageName: '预付款', stageOrder: 1 },
|
|
|
|
|
// { id: 2, stageName: '进度款', stageOrder: 2 },
|
|
|
|
|
// { id: 3, stageName: '验收款', stageOrder: 3 },
|
|
|
|
|
// { id: 4, stageName: '尾款', stageOrder: 4 },
|
|
|
|
|
// { id: 5, stageName: '质保金', stageOrder: 5 }
|
|
|
|
|
// ]);
|
|
|
|
|
|
|
|
|
|
// 分款明细表单
|
|
|
|
|
const detailDialog = reactive({
|
|
|
|
|
visible: false,
|
|
|
|
|
@ -417,19 +482,41 @@ const initDetailForm: FinAccountInstallmentDetailForm = {
|
|
|
|
|
contractName: undefined,
|
|
|
|
|
paymentStageId: undefined,
|
|
|
|
|
detailAmount: undefined,
|
|
|
|
|
remark: undefined
|
|
|
|
|
installmentStatus: undefined,
|
|
|
|
|
remark: undefined,
|
|
|
|
|
contractTotalPrice: undefined,
|
|
|
|
|
contractPaymentPercentage: undefined,
|
|
|
|
|
contractPaymentAmount: undefined
|
|
|
|
|
};
|
|
|
|
|
const detailForm = reactive<FinAccountInstallmentDetailForm>({ ...initDetailForm });
|
|
|
|
|
|
|
|
|
|
function validateDetailAmountNotExceedNode(_rule: unknown, value: unknown, callback: (e?: Error) => void) {
|
|
|
|
|
const max = selectedStageContractShareAmount.value;
|
|
|
|
|
if (max == null || Number.isNaN(Number(max))) {
|
|
|
|
|
callback();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const maxN = Number(max);
|
|
|
|
|
const v = Number(value);
|
|
|
|
|
if (value === undefined || value === null || value === '' || Number.isNaN(v)) {
|
|
|
|
|
callback();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const vCents = Math.round(v * 100);
|
|
|
|
|
const maxCents = Math.round(maxN * 100);
|
|
|
|
|
if (vCents > maxCents) {
|
|
|
|
|
callback(new Error(`分款金额不能大于节点约定金额(¥${formatMoney(maxN)})`));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
callback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const detailRules = {
|
|
|
|
|
paymentStageId: [{ required: true, message: '请选择分款节点', trigger: 'change' }],
|
|
|
|
|
detailAmount: [{ required: true, message: '请输入分款金额', trigger: 'blur' }]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 格式化金额
|
|
|
|
|
const formatMoney = (money: number | undefined | null) => {
|
|
|
|
|
if (money === undefined || money === null) return '0.00';
|
|
|
|
|
return money.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
|
|
|
detailAmount: [
|
|
|
|
|
{ required: true, message: '请输入分款金额', trigger: 'blur' },
|
|
|
|
|
{ validator: validateDetailAmountNotExceedNode, trigger: ['blur', 'change'] }
|
|
|
|
|
]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const INSTALLMENT_STATUS = {
|
|
|
|
|
@ -438,26 +525,21 @@ const INSTALLMENT_STATUS = {
|
|
|
|
|
COMPLETE: '2' //分款完成
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取状态类型
|
|
|
|
|
const getStatusType = (status: string | undefined) => {
|
|
|
|
|
if (!status) return 'info';
|
|
|
|
|
const map: Record<string, string> = {
|
|
|
|
|
'0': 'warning', // 未分款 - 黄色
|
|
|
|
|
'1': 'primary', // 部分分款 - 蓝色
|
|
|
|
|
'2': 'success' // 已分款完成 - 绿色
|
|
|
|
|
};
|
|
|
|
|
return map[status] || 'info';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取状态文本
|
|
|
|
|
const getStatusText = (status: string | undefined) => {
|
|
|
|
|
if (!status) return '未知';
|
|
|
|
|
const map: Record<string, string> = {
|
|
|
|
|
'0': '未分款',
|
|
|
|
|
'1': '部分分款',
|
|
|
|
|
'2': '已分款完成'
|
|
|
|
|
};
|
|
|
|
|
return map[status] || '未知';
|
|
|
|
|
/** 明细列表刷新后,按剩余回款与已分款情况同步左侧选中行及列表中的分款状态 */
|
|
|
|
|
const syncSelectedInstallmentStatusWithDetailList = () => {
|
|
|
|
|
if (!selectedInstallment.value) return;
|
|
|
|
|
const newStatus =
|
|
|
|
|
remainingAmount.value === 0
|
|
|
|
|
? INSTALLMENT_STATUS.COMPLETE
|
|
|
|
|
: allocatedAmount.value > 0
|
|
|
|
|
? INSTALLMENT_STATUS.PARTIALLY
|
|
|
|
|
: INSTALLMENT_STATUS.NOT;
|
|
|
|
|
selectedInstallment.value.installmentStatus = newStatus;
|
|
|
|
|
const id = selectedInstallment.value.accountInstallmentId;
|
|
|
|
|
const index = finAccountInstallmentList.value.findIndex((item) => item.accountInstallmentId === id);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
finAccountInstallmentList.value[index].installmentStatus = newStatus;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*** 用户导入参数 */
|
|
|
|
|
@ -573,8 +655,6 @@ const handleAddDetail = () => {
|
|
|
|
|
// 项目选择回调
|
|
|
|
|
const handleProjectSelected = (data: any) => {
|
|
|
|
|
selectedProject.value = data.project;
|
|
|
|
|
|
|
|
|
|
console.log(data);
|
|
|
|
|
// 如果是无合同项目(contractFlag !== '1'),需要选择合同
|
|
|
|
|
if (data.project.contractFlag !== '1') {
|
|
|
|
|
showContractDialog.value = true;
|
|
|
|
|
@ -593,8 +673,11 @@ const handleContractSelected = (contract: any) => {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 填充分款明细表单
|
|
|
|
|
// 填充分款明细表单(新增:分款金额在选定分款节点后由节点约定金额带出,见 syncAddDetailAmountFromSelectedStage)
|
|
|
|
|
const fillDetailForm = (project: any, contract: any) => {
|
|
|
|
|
const totalPriceRaw = contract?.totalPrice;
|
|
|
|
|
detailFormContractTotalPrice.value =
|
|
|
|
|
totalPriceRaw !== undefined && totalPriceRaw !== null && totalPriceRaw !== '' ? Number(totalPriceRaw) : undefined;
|
|
|
|
|
Object.assign(detailForm, {
|
|
|
|
|
installmentDetailId: undefined,
|
|
|
|
|
accountInstallmentId: selectedInstallment.value?.accountInstallmentId,
|
|
|
|
|
@ -606,23 +689,45 @@ const fillDetailForm = (project: any, contract: any) => {
|
|
|
|
|
contractName: contract?.contractName || '',
|
|
|
|
|
paymentStageId: undefined,
|
|
|
|
|
detailAmount: undefined,
|
|
|
|
|
remark: undefined
|
|
|
|
|
remark: undefined,
|
|
|
|
|
contractTotalPrice: undefined,
|
|
|
|
|
contractPaymentPercentage: undefined,
|
|
|
|
|
contractPaymentAmount: undefined
|
|
|
|
|
});
|
|
|
|
|
detailDialog.title = '新增分款明细';
|
|
|
|
|
detailDialog.visible = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 编辑分款明细
|
|
|
|
|
const handleEditDetail = (row: FinAccountInstallmentDetailVO) => {
|
|
|
|
|
/** 新增明细:选定分款节点后,分款金额默认取当前节点约定金额 */
|
|
|
|
|
const syncAddDetailAmountFromSelectedStage = () => {
|
|
|
|
|
if (!detailDialog.visible || detailForm.installmentDetailId) return;
|
|
|
|
|
|
|
|
|
|
let next: number | undefined;
|
|
|
|
|
if (detailForm.paymentStageId != null && detailForm.paymentStageId !== '') {
|
|
|
|
|
const raw = selectedStageContractShareAmount.value;
|
|
|
|
|
const n = raw != null && !Number.isNaN(Number(raw)) ? Number(raw) : NaN;
|
|
|
|
|
if (!Number.isNaN(n) && n > 0) {
|
|
|
|
|
const rounded = Math.round(n * 100) / 100;
|
|
|
|
|
next = rounded < 0.01 ? 0.01 : rounded;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
detailForm.detailAmount = next;
|
|
|
|
|
|
|
|
|
|
if (detailFormRef.value) {
|
|
|
|
|
nextTick(() => detailFormRef.value?.validateField('detailAmount'));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 编辑分款明细(合同额、节点比例/金额由列表接口 join 返回,不再请求 getContractInfo)
|
|
|
|
|
const handleEditDetail = async (row: FinAccountInstallmentDetailVO) => {
|
|
|
|
|
Object.assign(detailForm, row);
|
|
|
|
|
detailDialog.title = '编辑分款明细';
|
|
|
|
|
detailDialog.visible = true;
|
|
|
|
|
getPaymentStages(detailForm.contractId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 分款金额变化时触发校验提示更新
|
|
|
|
|
const handleDetailAmountChange = () => {
|
|
|
|
|
// 通过computed自动更新formRemainingAmount
|
|
|
|
|
const tp = row.contractTotalPrice;
|
|
|
|
|
detailFormContractTotalPrice.value =
|
|
|
|
|
tp !== undefined && tp !== null && !Number.isNaN(Number(tp)) ? Number(tp) : undefined;
|
|
|
|
|
await getPaymentStages(detailForm.contractId);
|
|
|
|
|
nextTick(() => detailFormRef.value?.validateField('detailAmount'));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 删除分款明细
|
|
|
|
|
@ -635,16 +740,7 @@ const handleDeleteDetail = async (row: FinAccountInstallmentDetailVO) => {
|
|
|
|
|
await deleteInstallmentDetailByBo(deleteForm);
|
|
|
|
|
proxy?.$modal.msgSuccess('删除成功');
|
|
|
|
|
await getDetailList();
|
|
|
|
|
// 更新左侧选中行的状态
|
|
|
|
|
if (selectedInstallment.value) {
|
|
|
|
|
const newStatus = remainingAmount.value === 0 ? INSTALLMENT_STATUS.COMPLETE : (allocatedAmount.value > 0 ? INSTALLMENT_STATUS.PARTIALLY : INSTALLMENT_STATUS.NOT);
|
|
|
|
|
selectedInstallment.value.installmentStatus = newStatus;
|
|
|
|
|
// 同时更新左侧列表中对应记录的状态
|
|
|
|
|
const index = finAccountInstallmentList.value.findIndex((item) => item.accountInstallmentId === selectedInstallment.value?.accountInstallmentId);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
finAccountInstallmentList.value[index].installmentStatus = newStatus;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
syncSelectedInstallmentStatusWithDetailList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 提交分款明细表单
|
|
|
|
|
@ -664,16 +760,7 @@ const submitDetailForm = async () => {
|
|
|
|
|
}
|
|
|
|
|
detailDialog.visible = false;
|
|
|
|
|
await getDetailList();
|
|
|
|
|
// 更新左侧选中行的状态
|
|
|
|
|
if (selectedInstallment.value) {
|
|
|
|
|
const newStatus = remainingAmount.value === 0 ? INSTALLMENT_STATUS.COMPLETE : (allocatedAmount.value > 0 ? INSTALLMENT_STATUS.PARTIALLY : INSTALLMENT_STATUS.NOT);
|
|
|
|
|
selectedInstallment.value.installmentStatus = newStatus;
|
|
|
|
|
// 同时更新左侧列表中对应记录的状态
|
|
|
|
|
const index = finAccountInstallmentList.value.findIndex((item) => item.accountInstallmentId === selectedInstallment.value?.accountInstallmentId);
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
finAccountInstallmentList.value[index].installmentStatus = newStatus;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
syncSelectedInstallmentStatusWithDetailList();
|
|
|
|
|
} finally {
|
|
|
|
|
detailButtonLoading.value = false;
|
|
|
|
|
}
|
|
|
|
|
@ -682,7 +769,6 @@ const submitDetailForm = async () => {
|
|
|
|
|
// 取消分款明细
|
|
|
|
|
const cancelDetail = () => {
|
|
|
|
|
detailDialog.visible = false;
|
|
|
|
|
Object.assign(detailForm, initDetailForm);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Excel导入相关
|
|
|
|
|
@ -720,25 +806,31 @@ const submitImport = async () => {
|
|
|
|
|
uploadRef.value?.submit();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 监听导入对话框关闭
|
|
|
|
|
watch(showImportDialog, (val) => {
|
|
|
|
|
if (!val) {
|
|
|
|
|
importPreviewData.value = [];
|
|
|
|
|
importFile.value = null;
|
|
|
|
|
uploadRef.value?.clearFiles();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 监听分款明细对话框关闭
|
|
|
|
|
watch(
|
|
|
|
|
() => detailDialog.visible,
|
|
|
|
|
(val) => {
|
|
|
|
|
if (!val) {
|
|
|
|
|
Object.assign(detailForm, initDetailForm);
|
|
|
|
|
detailFormContractTotalPrice.value = undefined;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => [
|
|
|
|
|
detailDialog.visible,
|
|
|
|
|
detailForm.installmentDetailId,
|
|
|
|
|
detailForm.paymentStageId,
|
|
|
|
|
paymentStageList.value,
|
|
|
|
|
detailFormContractTotalPrice.value
|
|
|
|
|
],
|
|
|
|
|
() => {
|
|
|
|
|
syncAddDetailAmountFromSelectedStage();
|
|
|
|
|
},
|
|
|
|
|
{ flush: 'post' }
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 初始化
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
getList();
|
|
|
|
|
|