5fcb82c0c0
2、新增收付款模块
853 lines
29 KiB
Vue
853 lines
29 KiB
Vue
<template>
|
||
<basic-container class="payment-form-page">
|
||
<div class="payment-form-page__title">
|
||
{{ readonly ? '查看付款申请' : recordId ? '编辑付款申请' : '新增付款申请' }}
|
||
</div>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="form"
|
||
:rules="rules"
|
||
label-position="right"
|
||
label-width="auto"
|
||
class="payment-form-page__form"
|
||
>
|
||
<section class="payment-form-page__section">
|
||
<div class="payment-form-page__section-title">付款基本信息</div>
|
||
<el-row :gutter="24">
|
||
<el-col :span="12"
|
||
><el-form-item label="单据号"
|
||
><el-input
|
||
v-model="form.paymentNo"
|
||
disabled
|
||
placeholder="系统自动生成" /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="付款类型" prop="paymentType"
|
||
><el-select v-model="form.paymentType" :disabled="readonly" @change="handleTypeChange"
|
||
><el-option
|
||
v-for="item in paymentTypeOptions"
|
||
:key="item.value"
|
||
v-bind="item" /></el-select></el-form-item
|
||
></el-col>
|
||
<el-col v-if="form.paymentType !== 'project_advance'" :span="12"
|
||
><el-form-item label="结算单号" prop="referenceId"
|
||
><el-input
|
||
v-model="referenceLabel"
|
||
readonly
|
||
:disabled="readonly"
|
||
placeholder="请选择预结算/正式结算单"
|
||
><template #append
|
||
><el-button :disabled="readonly" @click="openReference">选择</el-button></template
|
||
></el-input
|
||
></el-form-item
|
||
></el-col
|
||
>
|
||
<el-col :span="12"
|
||
><el-form-item label="所属项目"
|
||
><el-input v-model="form.projectName" disabled
|
||
><template v-if="form.paymentType === 'project_advance'" #append
|
||
><el-button :disabled="readonly" @click="openReference">选择</el-button></template
|
||
></el-input
|
||
></el-form-item
|
||
></el-col
|
||
>
|
||
<el-col :span="12"
|
||
><el-form-item label="合同名称"
|
||
><el-input v-model="form.contractName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="结算金额"
|
||
><el-input v-model="form.settlementAmount" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="可付款金额"
|
||
><el-input v-model="form.payableAmount" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="票款类型"
|
||
><el-input v-model="form.billType" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="付款比例" prop="paymentRatio"
|
||
><el-input-number
|
||
v-model="form.paymentRatio"
|
||
:disabled="readonly"
|
||
:min="0"
|
||
:max="100"
|
||
:precision="2"
|
||
:controls="false"
|
||
style="width: 100%" /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="申请付款金额" prop="appliedAmount"
|
||
><el-input-number
|
||
v-model="form.appliedAmount"
|
||
:disabled="readonly"
|
||
:min="0"
|
||
:precision="2"
|
||
:controls="false"
|
||
style="width: 100%" /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="付款方式" prop="paymentMethod"
|
||
><el-select
|
||
v-model="form.paymentMethod"
|
||
:disabled="readonly"
|
||
@change="handlePaymentMethodChange"
|
||
><el-option
|
||
v-for="item in paymentMethodOptions"
|
||
:key="item.value"
|
||
v-bind="item" /></el-select></el-form-item
|
||
></el-col>
|
||
<el-col v-if="billPayment" :span="12"
|
||
><el-form-item label="汇票票据" prop="billLedgerId"
|
||
><el-select
|
||
v-model="form.billLedgerId"
|
||
:disabled="readonly"
|
||
filterable
|
||
remote
|
||
reserve-keyword
|
||
:remote-method="loadBillOptions"
|
||
:loading="billLoading"
|
||
placeholder="请选择可用汇票"
|
||
@change="handleBillChange"
|
||
><el-option
|
||
v-for="item in billOptions"
|
||
:key="item.id"
|
||
:label="`${item.billNo}|余额${formatMoney(item.availableBalance)}|${
|
||
item.maturityDate
|
||
}`"
|
||
:value="item.id" /></el-select></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="收款方"
|
||
><el-input v-model="form.payeeName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="收款账号"
|
||
><el-input v-model="form.bankAccount" :disabled="readonly" /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="开户银行"
|
||
><el-input v-model="form.bankName" :disabled="readonly" /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="申请人"
|
||
><el-input v-model="form.applicantName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="12"
|
||
><el-form-item label="申请日期"
|
||
><el-input v-model="form.applyDate" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="24"
|
||
><el-form-item label="备注"
|
||
><el-input
|
||
v-model="form.remark"
|
||
:disabled="readonly"
|
||
type="textarea"
|
||
maxlength="200"
|
||
show-word-limit /></el-form-item
|
||
></el-col>
|
||
</el-row>
|
||
</section>
|
||
<section class="payment-form-page__section">
|
||
<div class="payment-form-page__section-title">结算信息</div>
|
||
<el-table :data="settlementRows" border
|
||
><el-table-column type="index" label="序号" width="70" /><el-table-column
|
||
prop="settlementNo"
|
||
label="结算单号"
|
||
min-width="150" /><el-table-column
|
||
prop="settlementAmount"
|
||
label="结算总金额"
|
||
min-width="130" /><el-table-column
|
||
prop="payableAmount"
|
||
label="可付款金额"
|
||
min-width="130" /><el-table-column
|
||
prop="paymentRatio"
|
||
label="付款比例"
|
||
min-width="110" /><el-table-column
|
||
prop="appliedAmount"
|
||
label="付款金额"
|
||
min-width="130"
|
||
/></el-table>
|
||
</section>
|
||
<section class="payment-form-page__section">
|
||
<div class="payment-form-page__section-title">发票信息</div>
|
||
<div class="payment-form-page__section-actions">
|
||
<el-button type="primary" plain :disabled="readonly" @click="addInvoice"
|
||
>新增发票</el-button
|
||
>
|
||
</div>
|
||
<el-table :data="form.invoices" border
|
||
><el-table-column type="index" label="序号" width="70" /><el-table-column
|
||
prop="settlementNo"
|
||
label="结算单号"
|
||
min-width="120"
|
||
/><el-table-column label="发票号" min-width="140"
|
||
><template #default="{ row }"
|
||
><el-input v-model="row.invoiceNo" :disabled="readonly" /></template></el-table-column
|
||
><el-table-column label="开票日期" min-width="150"
|
||
><template #default="{ row }"
|
||
><el-date-picker
|
||
v-model="row.invoiceDate"
|
||
value-format="YYYY-MM-DD"
|
||
:disabled="readonly" /></template></el-table-column
|
||
><el-table-column label="发票类型" min-width="130"
|
||
><template #default="{ row }"
|
||
><el-input
|
||
v-model="row.invoiceType"
|
||
:disabled="readonly" /></template></el-table-column
|
||
><el-table-column label="税率" min-width="100"
|
||
><template #default="{ row }"
|
||
><el-input-number
|
||
v-model="row.taxRate"
|
||
:disabled="readonly"
|
||
:min="0"
|
||
:max="100"
|
||
:controls="false" /></template></el-table-column
|
||
><el-table-column label="发票金额(含税)" min-width="150"
|
||
><template #default="{ row }"
|
||
><el-input-number
|
||
v-model="row.invoiceAmount"
|
||
:disabled="readonly"
|
||
:min="0"
|
||
:precision="2"
|
||
:controls="false" /></template></el-table-column
|
||
><el-table-column label="匹配金额(含税)" min-width="150"
|
||
><template #default="{ row }"
|
||
><el-input-number
|
||
v-model="row.matchedAmount"
|
||
:disabled="readonly"
|
||
:min="0"
|
||
:precision="2"
|
||
:controls="false" /></template></el-table-column
|
||
><el-table-column label="操作" width="100"
|
||
><template #default="{ $index }"
|
||
><el-link v-if="!readonly" type="danger" @click="form.invoices.splice($index, 1)"
|
||
>删除</el-link
|
||
></template
|
||
></el-table-column
|
||
></el-table
|
||
>
|
||
</section>
|
||
<section class="payment-form-page__section">
|
||
<div class="payment-form-page__section-title">付款记录</div>
|
||
<el-table :data="paymentRecords" border
|
||
><el-table-column type="index" label="序号" width="70" /><el-table-column
|
||
prop="paidAmount"
|
||
label="付款金额"
|
||
min-width="160" /><el-table-column
|
||
prop="paidDate"
|
||
label="付款日期"
|
||
min-width="150" /><el-table-column
|
||
prop="paymentNo"
|
||
label="付款单号"
|
||
min-width="160" /><el-table-column
|
||
prop="kingdeeBillNo"
|
||
label="付款凭证"
|
||
min-width="160"
|
||
/></el-table>
|
||
</section>
|
||
<section class="payment-form-page__section">
|
||
<div class="payment-form-page__section-title">附件</div>
|
||
<vehicle-attachment-upload
|
||
v-model="form.attachments"
|
||
:readonly="readonly"
|
||
:multiple="true"
|
||
:limit="20"
|
||
:max-size="500"
|
||
:file-types="attachmentFileTypes"
|
||
:show-file-list="false"
|
||
button-text="上传附件"
|
||
@change="normalizeAttachments"
|
||
/><el-table :data="form.attachments" border
|
||
><el-table-column type="index" label="序号" width="70" /><el-table-column
|
||
label="附件类型"
|
||
width="160"
|
||
><template #default="{ row }"
|
||
><el-select v-model="row.attachmentType" :disabled="readonly"
|
||
><el-option label="磅单" value="weighing_slip" /><el-option
|
||
label="结算单"
|
||
value="settlement" /><el-option label="合同签章文件" value="contract" /><el-option
|
||
label="特批附件"
|
||
value="special_approval" /><el-option
|
||
label="其他"
|
||
value="other" /></el-select></template></el-table-column
|
||
><el-table-column prop="originalName" label="文件名" min-width="220" /><el-table-column
|
||
label="附件描述"
|
||
min-width="220"
|
||
><template #default="{ row }"
|
||
><el-input
|
||
v-model="row.description"
|
||
:disabled="readonly"
|
||
maxlength="200" /></template></el-table-column
|
||
><el-table-column prop="size" label="文件大小" width="120" /><el-table-column
|
||
prop="uploadUserName"
|
||
label="上传人"
|
||
width="130"
|
||
/><el-table-column prop="uploadTime" label="上传时间" width="170" /><el-table-column
|
||
label="操作"
|
||
width="100"
|
||
><template #default="{ row, $index }"
|
||
><el-link type="primary" :href="row.url || row.link" target="_blank">查看</el-link
|
||
><el-link v-if="!readonly" type="danger" @click="form.attachments.splice($index, 1)"
|
||
>删除</el-link
|
||
></template
|
||
></el-table-column
|
||
></el-table
|
||
>
|
||
</section>
|
||
<div class="payment-form-page__actions">
|
||
<el-button @click="goBack">返回</el-button
|
||
><el-button v-if="!readonly && canSave" @click="saveDraft">保存</el-button
|
||
><el-button
|
||
v-if="!readonly && canSave && hasPermission('payment_application_submit')"
|
||
type="primary"
|
||
@click="submitForm"
|
||
>提交</el-button
|
||
>
|
||
</div>
|
||
</el-form>
|
||
<el-dialog
|
||
v-model="referenceVisible"
|
||
:title="form.paymentType === 'project_advance' ? '选择项目合同' : '选择结算单'"
|
||
width="80%"
|
||
><el-table
|
||
v-if="form.paymentType === 'project_advance'"
|
||
:data="contractRows"
|
||
border
|
||
@row-click="selectContract"
|
||
><el-table-column prop="projectName" label="所属项目" /><el-table-column
|
||
prop="contractNo"
|
||
label="合同编号" /><el-table-column
|
||
prop="contractName"
|
||
label="合同名称" /><el-table-column prop="deptName" label="所属组织" /></el-table
|
||
><el-tabs v-else v-model="referenceTab"
|
||
><el-tab-pane label="正式结算单" name="formal"
|
||
><el-table :data="formalRows" border @row-click="selectFormal"
|
||
><el-table-column prop="formalSettlementNo" label="结算单号" /><el-table-column
|
||
prop="projectName"
|
||
label="所属项目" /><el-table-column
|
||
prop="contractName"
|
||
label="合同名称" /><el-table-column
|
||
prop="settlementAmount"
|
||
label="结算金额" /></el-table></el-tab-pane
|
||
><el-tab-pane label="预结算单" name="pre"
|
||
><el-table :data="preRows" border @row-click="selectPre"
|
||
><el-table-column prop="preSettlementNo" label="结算单号" /><el-table-column
|
||
prop="projectName"
|
||
label="所属项目" /><el-table-column
|
||
prop="contractName"
|
||
label="合同名称" /><el-table-column
|
||
prop="settlementAmount"
|
||
label="结算金额" /></el-table></el-tab-pane></el-tabs
|
||
></el-dialog>
|
||
</basic-container>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapGetters } from 'vuex';
|
||
import * as api from '@/api/payment/paymentApplication';
|
||
import * as billLedgerApi from '@/api/payment/billLedger';
|
||
import * as formalApi from '@/api/settlement/formalSettlement';
|
||
import * as preApi from '@/api/settlement/preSettlement';
|
||
|
||
const emptyForm = () => ({
|
||
id: null,
|
||
paymentNo: '',
|
||
paymentType: 'project_advance',
|
||
settlementId: null,
|
||
preSettlementId: null,
|
||
projectId: null,
|
||
projectName: '',
|
||
deptId: null,
|
||
deptName: '',
|
||
contractId: null,
|
||
contractNo: '',
|
||
contractName: '',
|
||
payerName: '',
|
||
payeeName: '',
|
||
settlementAmount: 0,
|
||
payableAmount: 0,
|
||
billType: '',
|
||
paymentRatio: 50,
|
||
appliedAmount: 0,
|
||
paymentMethod: 'bank_transfer',
|
||
billLedgerId: null,
|
||
billNo: '',
|
||
receiptAccountId: null,
|
||
receiptAccountName: '',
|
||
bankName: '',
|
||
bankAccount: '',
|
||
applicantName: '',
|
||
applyDate: '',
|
||
remark: '',
|
||
attachments: [],
|
||
invoices: [],
|
||
});
|
||
export default {
|
||
name: 'PaymentApplicationForm',
|
||
data() {
|
||
return {
|
||
form: emptyForm(),
|
||
amountSyncing: false,
|
||
paymentRecords: [],
|
||
referenceVisible: false,
|
||
referenceTab: 'formal',
|
||
formalRows: [],
|
||
preRows: [],
|
||
contractRows: [],
|
||
billOptions: [],
|
||
billLoading: false,
|
||
paymentTypeOptions: api.paymentTypeOptions,
|
||
paymentMethodOptions: api.paymentMethodOptions,
|
||
attachmentFileTypes: [
|
||
'pdf',
|
||
'bmp',
|
||
'jpeg',
|
||
'png',
|
||
'jpg',
|
||
'doc',
|
||
'docx',
|
||
'ppt',
|
||
'pptx',
|
||
'xlsx',
|
||
'xls',
|
||
'eml',
|
||
'msg',
|
||
'zip',
|
||
'rar',
|
||
],
|
||
rules: {
|
||
paymentType: [{ required: true, message: '请选择付款类型' }],
|
||
referenceId: [{ validator: this.validateReference, trigger: 'change' }],
|
||
paymentMethod: [{ required: true, message: '请选择付款方式' }],
|
||
billLedgerId: [{ validator: this.validateBillLedger, trigger: 'change' }],
|
||
appliedAmount: [{ validator: this.validateAppliedAmount, trigger: 'change' }],
|
||
},
|
||
};
|
||
},
|
||
computed: {
|
||
...mapGetters(['permission']),
|
||
recordId() {
|
||
return this.$route.query.id || '';
|
||
},
|
||
readonly() {
|
||
return this.$route.query.mode === 'view';
|
||
},
|
||
canSave() {
|
||
const code = this.recordId ? 'payment_application_edit' : 'payment_application_add';
|
||
return this.hasPermission(code);
|
||
},
|
||
billPayment() {
|
||
return ['bank_draft', 'commercial_draft'].includes(this.form.paymentMethod);
|
||
},
|
||
referenceLabel() {
|
||
return this.form.settlementNo || this.form.preSettlementNo || '';
|
||
},
|
||
settlementRows() {
|
||
if (!this.referenceLabel) return [];
|
||
return [
|
||
{
|
||
settlementNo: this.referenceLabel,
|
||
settlementAmount: this.form.settlementAmount,
|
||
payableAmount: this.form.payableAmount,
|
||
paymentRatio: this.form.paymentRatio,
|
||
appliedAmount: this.form.appliedAmount,
|
||
},
|
||
];
|
||
},
|
||
},
|
||
watch: {
|
||
'form.paymentRatio'(value) {
|
||
if (this.amountSyncing || !Number(this.form.payableAmount)) return;
|
||
this.amountSyncing = true;
|
||
this.form.appliedAmount = Number(
|
||
((Number(this.form.payableAmount) * Number(value || 0)) / 100).toFixed(2)
|
||
);
|
||
this.$nextTick(() => {
|
||
this.amountSyncing = false;
|
||
});
|
||
},
|
||
'form.appliedAmount'(value) {
|
||
if (this.amountSyncing || !Number(this.form.payableAmount)) return;
|
||
this.amountSyncing = true;
|
||
this.form.paymentRatio = Number(
|
||
((Number(value || 0) / Number(this.form.payableAmount)) * 100).toFixed(2)
|
||
);
|
||
this.$nextTick(() => {
|
||
this.amountSyncing = false;
|
||
});
|
||
},
|
||
},
|
||
created() {
|
||
this.initialize();
|
||
},
|
||
methods: {
|
||
hasPermission(code) {
|
||
return this.permission?.[code] !== false;
|
||
},
|
||
validateReference(rule, value, callback) {
|
||
if (this.form.paymentType === 'progress_advance' && !this.form.preSettlementId) {
|
||
callback(new Error('请选择预结算单'));
|
||
return;
|
||
}
|
||
if (this.form.paymentType === 'settlement_payment' && !this.form.settlementId) {
|
||
callback(new Error('请选择正式结算单'));
|
||
return;
|
||
}
|
||
callback();
|
||
},
|
||
validateAppliedAmount(rule, value, callback) {
|
||
const amount = Number(value);
|
||
const payableAmount = Number(this.form.payableAmount || 0);
|
||
if (!Number.isFinite(amount) || amount < 0) {
|
||
callback(new Error('申请付款金额不能小于0'));
|
||
return;
|
||
}
|
||
if (payableAmount > 0 && amount > payableAmount) {
|
||
callback(new Error('申请付款金额不能超过可付款金额'));
|
||
return;
|
||
}
|
||
callback();
|
||
},
|
||
validateBillLedger(rule, value, callback) {
|
||
if (!this.billPayment) {
|
||
callback();
|
||
return;
|
||
}
|
||
if (!value) {
|
||
callback(new Error('请选择可用汇票'));
|
||
return;
|
||
}
|
||
const selected = this.billOptions.find(item => String(item.id) === String(value));
|
||
if (
|
||
selected &&
|
||
Number(this.form.appliedAmount || 0) > Number(selected.availableBalance || 0)
|
||
) {
|
||
callback(new Error('申请付款金额不能超过汇票可用余额'));
|
||
return;
|
||
}
|
||
callback();
|
||
},
|
||
validateInvoices() {
|
||
const appliedAmount = Number(this.form.appliedAmount || 0);
|
||
let matchedTotal = 0;
|
||
for (const invoice of this.form.invoices || []) {
|
||
const invoiceAmount = Number(invoice.invoiceAmount || 0);
|
||
const matchedAmount = Number(invoice.matchedAmount || 0);
|
||
if (invoiceAmount < 0 || matchedAmount < 0) {
|
||
throw new Error('发票金额和匹配金额不能小于0');
|
||
}
|
||
if (matchedAmount > invoiceAmount) {
|
||
throw new Error('单张发票匹配金额不能超过发票金额');
|
||
}
|
||
matchedTotal += matchedAmount;
|
||
}
|
||
if (matchedTotal > appliedAmount) {
|
||
throw new Error('发票匹配金额合计不能超过申请付款金额');
|
||
}
|
||
},
|
||
unwrapData(response) {
|
||
const body = response?.data || response || {};
|
||
return body?.data || body;
|
||
},
|
||
async initialize() {
|
||
if (this.recordId) {
|
||
const data = this.unwrapData(await api.getDetail(this.recordId));
|
||
this.form = {
|
||
...emptyForm(),
|
||
...data,
|
||
attachments: this.parse(data.attachmentsJson),
|
||
invoices: data.invoices || [],
|
||
};
|
||
this.paymentRecords = data.paymentRecords || [];
|
||
if (this.billPayment) await this.loadBillOptions('', data.billLedgerId);
|
||
} else {
|
||
this.form.applyDate = this.$dayjs().format('YYYY-MM-DD');
|
||
this.form.applicantName =
|
||
this.$store.getters.userInfo?.realName || this.$store.getters.userInfo?.userName || '';
|
||
}
|
||
},
|
||
parse(value) {
|
||
if (!value) return [];
|
||
if (Array.isArray(value)) return value;
|
||
try {
|
||
return JSON.parse(value) || [];
|
||
} catch {
|
||
return [];
|
||
}
|
||
},
|
||
handleTypeChange() {
|
||
if (this.form.paymentType === 'project_advance') {
|
||
this.form.settlementId = null;
|
||
this.form.preSettlementId = null;
|
||
}
|
||
},
|
||
async handlePaymentMethodChange() {
|
||
if (!this.billPayment) {
|
||
this.form.billLedgerId = null;
|
||
this.form.billNo = '';
|
||
this.billOptions = [];
|
||
return;
|
||
}
|
||
await this.loadBillOptions();
|
||
},
|
||
async loadBillOptions(keyword = '', selectedId = this.form.billLedgerId) {
|
||
if (!this.billPayment) return;
|
||
this.billLoading = true;
|
||
try {
|
||
this.billOptions =
|
||
this.unwrapData(
|
||
await billLedgerApi.getAvailableOptions(keyword, this.form.deptId, selectedId)
|
||
) || [];
|
||
} finally {
|
||
this.billLoading = false;
|
||
}
|
||
},
|
||
handleBillChange(id) {
|
||
const selected = this.billOptions.find(item => String(item.id) === String(id));
|
||
this.form.billNo = selected?.billNo || '';
|
||
this.$refs.formRef?.validateField('billLedgerId').catch(() => {});
|
||
},
|
||
async loadReferences() {
|
||
const [formalResponse, preResponse, contractResponse] = await Promise.all([
|
||
formalApi.getList(1, 100, { settlementType: 'payable', approvalStatus: 'approved' }),
|
||
preApi.getList(1, 100, { settlementType: 'payable', approvalStatus: 'approved' }),
|
||
formalApi.getContractOptions(''),
|
||
]);
|
||
const formal = this.unwrapData(formalResponse);
|
||
const pre = this.unwrapData(preResponse);
|
||
this.formalRows = formal.records || [];
|
||
this.preRows = pre.records || [];
|
||
this.contractRows = this.unwrapData(contractResponse) || [];
|
||
},
|
||
async openReference() {
|
||
await this.loadReferences();
|
||
this.referenceVisible = true;
|
||
},
|
||
selectContract(row) {
|
||
Object.assign(this.form, {
|
||
projectId: row.projectId,
|
||
projectName: row.projectName,
|
||
deptId: row.deptId,
|
||
deptName: row.deptName,
|
||
contractId: row.id,
|
||
contractNo: row.contractNo,
|
||
contractName: row.contractName,
|
||
payerName: row.payerName,
|
||
payeeName: row.payeeName,
|
||
billType: '项目预付',
|
||
});
|
||
this.referenceVisible = false;
|
||
if (this.billPayment) this.loadBillOptions();
|
||
},
|
||
selectFormal(row) {
|
||
Object.assign(this.form, {
|
||
settlementId: row.id,
|
||
preSettlementId: null,
|
||
settlementNo: row.formalSettlementNo,
|
||
projectName: row.projectName,
|
||
deptId: row.deptId,
|
||
deptName: row.deptName,
|
||
contractName: row.contractName,
|
||
settlementAmount: row.settlementAmount,
|
||
payableAmount: Math.max(
|
||
0,
|
||
Number(row.settlementAmount || 0) - Number(row.appliedPaymentAmount || 0)
|
||
),
|
||
billType: '正式结算单',
|
||
payeeName: row.payeeName,
|
||
});
|
||
this.referenceVisible = false;
|
||
if (this.billPayment) this.loadBillOptions();
|
||
},
|
||
selectPre(row) {
|
||
Object.assign(this.form, {
|
||
preSettlementId: row.id,
|
||
settlementId: null,
|
||
preSettlementNo: row.preSettlementNo,
|
||
projectName: row.projectName,
|
||
deptId: row.deptId,
|
||
deptName: row.deptName,
|
||
contractName: row.contractName,
|
||
settlementAmount: row.settlementAmount,
|
||
payableAmount: Math.max(
|
||
0,
|
||
Number(row.settlementAmount || 0) - Number(row.advanceAppliedAmount || 0)
|
||
),
|
||
billType: '预结算单',
|
||
payeeName: row.payeeName,
|
||
});
|
||
this.referenceVisible = false;
|
||
if (this.billPayment) this.loadBillOptions();
|
||
},
|
||
addInvoice() {
|
||
this.form.invoices.push({
|
||
settlementNo: this.referenceLabel,
|
||
invoiceNo: '',
|
||
invoiceDate: '',
|
||
invoiceType: '',
|
||
taxRate: 3,
|
||
invoiceAmount: 0,
|
||
matchedAmount: 0,
|
||
attachmentJson: '',
|
||
});
|
||
},
|
||
normalizeAttachments(files) {
|
||
const userName =
|
||
this.$store.getters.userInfo?.realName || this.$store.getters.userInfo?.userName || '';
|
||
const time = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||
this.form.attachments = (files || []).map(file => ({
|
||
...file,
|
||
attachmentType: file.attachmentType || 'other',
|
||
description: file.description || '',
|
||
uploadUserName: file.uploadUserName || userName,
|
||
uploadTime: file.uploadTime || time,
|
||
}));
|
||
},
|
||
payload() {
|
||
const {
|
||
id,
|
||
paymentType,
|
||
settlementId,
|
||
preSettlementId,
|
||
projectId,
|
||
projectName,
|
||
deptId,
|
||
deptName,
|
||
contractId,
|
||
contractNo,
|
||
contractName,
|
||
payerName,
|
||
payeeName,
|
||
settlementAmount,
|
||
payableAmount,
|
||
billType,
|
||
paymentRatio,
|
||
appliedAmount,
|
||
paymentMethod,
|
||
billLedgerId,
|
||
billNo,
|
||
receiptAccountId,
|
||
receiptAccountName,
|
||
bankName,
|
||
bankAccount,
|
||
attachments,
|
||
remark,
|
||
invoices,
|
||
} = this.form;
|
||
return {
|
||
id,
|
||
paymentType,
|
||
settlementId,
|
||
preSettlementId,
|
||
projectId,
|
||
projectName,
|
||
deptId,
|
||
deptName,
|
||
contractId,
|
||
contractNo,
|
||
contractName,
|
||
payerName,
|
||
payeeName,
|
||
settlementAmount,
|
||
payableAmount,
|
||
billType,
|
||
paymentRatio,
|
||
appliedAmount,
|
||
paymentMethod,
|
||
billLedgerId,
|
||
billNo,
|
||
receiptAccountId,
|
||
receiptAccountName,
|
||
bankName,
|
||
bankAccount,
|
||
attachmentsJson: JSON.stringify(attachments || []),
|
||
remark,
|
||
invoices,
|
||
};
|
||
},
|
||
async saveDraft() {
|
||
await this.$refs.formRef.validate();
|
||
if (this.form.paymentType === 'project_advance' && !this.form.projectId) {
|
||
this.$message.warning('请选择所属项目');
|
||
return false;
|
||
}
|
||
try {
|
||
this.validateInvoices();
|
||
} catch (error) {
|
||
this.$message.warning(error.message);
|
||
return false;
|
||
}
|
||
const data = this.unwrapData(await api.save(this.payload()));
|
||
this.form.id = data;
|
||
this.$message.success('保存成功');
|
||
return true;
|
||
},
|
||
async submitForm() {
|
||
const saved = await this.saveDraft();
|
||
if (!saved) return;
|
||
await api.submit({ id: this.form.id });
|
||
this.$message.success('提交成功');
|
||
this.goBack();
|
||
},
|
||
goBack() {
|
||
this.$router.push('/payment/payment-application');
|
||
},
|
||
formatMoney(value) {
|
||
return Number(value || 0).toFixed(2);
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.payment-form-page__title,
|
||
.payment-form-page__section-title {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin-bottom: 16px;
|
||
}
|
||
.payment-form-page__title::before,
|
||
.payment-form-page__section-title::before {
|
||
width: 4px;
|
||
height: 20px;
|
||
margin-right: 8px;
|
||
background: #409eff;
|
||
content: '';
|
||
}
|
||
.payment-form-page__section {
|
||
margin-bottom: 24px;
|
||
}
|
||
.payment-form-page__section-title {
|
||
font-size: 16px;
|
||
}
|
||
.payment-form-page__section-actions {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin-bottom: 8px;
|
||
}
|
||
.payment-form-page__actions {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 16px;
|
||
padding: 24px 0;
|
||
border-top: 1px solid #eff1f7;
|
||
}
|
||
.payment-form-page :deep(.el-form-item) {
|
||
margin-bottom: 16px;
|
||
}
|
||
.payment-form-page :deep(.el-table) {
|
||
--el-table-border-color: #eff1f7;
|
||
}
|
||
.payment-form-page :deep(.el-table__body tr:nth-child(even) > td.el-table__cell) {
|
||
background: #fafafa;
|
||
}
|
||
:deep(.payment-form-page.basic-container .basic-container__card > .el-card__body) {
|
||
padding: 0;
|
||
}
|
||
</style>
|