c3f05a342e
- 统一调整settlement、business、payment模块以及全局样式中.el-form-item的margin-bottom从16/18/20px改为14px - 保留搜索栏相关的.el-form-item间距为8px和特殊分组risk-disposal的28px - 修正多个页面和组件的局部样式覆盖问题,确保填写区表单项间距一致 - 更新element-ui.scss中.dialog-form--carded对应的margin-bottom为14px - 维护部分表单组件原本使用的重要样式不变,保证视觉统一且不影响特殊布局
1339 lines
48 KiB
Vue
1339 lines
48 KiB
Vue
<template>
|
||
<basic-container class="payment-form-page">
|
||
<div class="archive-page-form__title">
|
||
{{ readonly ? '查看付款申请' : recordId ? '编辑付款申请' : '新增付款申请' }}
|
||
</div>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="form"
|
||
:rules="rules"
|
||
label-position="right"
|
||
label-width="auto"
|
||
class="payment-form-page__form"
|
||
>
|
||
<section-card title="付款基本信息">
|
||
<el-row :gutter="24">
|
||
<el-col :span="6"
|
||
><el-form-item label="单据号"
|
||
><el-input
|
||
v-model="form.paymentNo"
|
||
disabled
|
||
placeholder="系统自动生成" /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><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="6"
|
||
><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="6"
|
||
><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="6"
|
||
><el-form-item label="合同名称"
|
||
><el-input v-model="form.contractName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><el-form-item label="结算金额"
|
||
><el-input v-model="form.settlementAmount" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><el-form-item label="可付款金额"
|
||
><el-input v-model="form.payableAmount" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><el-form-item label="票款类型"
|
||
><el-input v-model="form.billType" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><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="6"
|
||
><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="6"
|
||
><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="6"
|
||
><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="6"
|
||
><el-form-item label="收款方"
|
||
><el-input v-model="form.payeeName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><el-form-item label="收款账号" prop="receiptAccountId"
|
||
><el-select
|
||
v-model="form.receiptAccountId"
|
||
:disabled="readonly || !form.payeeName"
|
||
:loading="receiptAccountLoading"
|
||
filterable
|
||
clearable
|
||
placeholder="请选择收款方的收款账号"
|
||
no-data-text="该收款方未维护可用收款信息"
|
||
@change="handleReceiptAccountChange"
|
||
><el-option
|
||
v-for="item in receiptAccountOptions"
|
||
:key="item.id"
|
||
:label="receiptAccountLabel(item)"
|
||
:value="item.id" /></el-select></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><el-form-item label="开户银行"
|
||
><el-input v-model="form.bankName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><el-form-item label="申请人"
|
||
><el-input v-model="form.applicantName" disabled /></el-form-item
|
||
></el-col>
|
||
<el-col :span="6"
|
||
><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-card>
|
||
<section-card title="结算信息">
|
||
<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-card>
|
||
<section-card title="发票信息">
|
||
<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-card>
|
||
<section-card title="付款记录">
|
||
<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-card>
|
||
<section-card>
|
||
<template #title>
|
||
<span>附件</span>
|
||
<span v-if="missingAttachmentMaterials.length" class="payment-form-page__missing-text">
|
||
未上传:{{ missingAttachmentMaterials.map(item => item.label).join('、') }}
|
||
</span>
|
||
</template>
|
||
<div v-loading="attachmentRuleLoading" class="payment-form-page__attachment-checklist">
|
||
<span class="payment-form-page__attachment-checklist-label">材料清单</span>
|
||
<el-tag
|
||
v-for="item in requiredAttachmentMaterials"
|
||
:key="item.key"
|
||
:type="hasAttachmentMaterial(item) ? 'success' : 'danger'"
|
||
effect="plain"
|
||
>
|
||
{{ item.label }}({{ hasAttachmentMaterial(item) ? '已上传' : '未上传' }})
|
||
</el-tag>
|
||
</div>
|
||
<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="entrust_order" /><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
|
||
>
|
||
<div class="payment-form-page__attachment-upload">
|
||
<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"
|
||
/>
|
||
</div>
|
||
</section-card>
|
||
<div class="payment-form-page__actions">
|
||
<el-button @click="goBack">返回</el-button
|
||
><el-button v-if="!readonly && canSave" @click="saveDraft(false)">保存</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 { getDetail as getContractDetail } from '@/api/business/contract-manage';
|
||
import * as formalApi from '@/api/settlement/formalSettlement';
|
||
import * as preApi from '@/api/settlement/preSettlement';
|
||
import {
|
||
getDetail as getCustomerArchiveDetail,
|
||
getList as getCustomerArchiveList,
|
||
} from '@/api/vehicle/customer-archive';
|
||
import { readSettlementTransfer, removeSettlementTransfer } from '@/utils/settlement-transfer';
|
||
|
||
const ATTACHMENT_MATERIALS = {
|
||
weighingSlip: { key: 'weighingSlip', label: '磅单', keywords: ['磅单'] },
|
||
entrustOrder: { key: 'entrustOrder', label: '委托单', keywords: ['委托单'] },
|
||
settlement: { key: 'settlement', label: '结算单', keywords: ['结算单'] },
|
||
contract: {
|
||
key: 'contract',
|
||
label: '合同签章文件',
|
||
keywords: ['合同签章文件', '合同签章', '签章'],
|
||
},
|
||
specialApproval: {
|
||
key: 'specialApproval',
|
||
label: '特批附件',
|
||
keywords: ['特批附件', '特批'],
|
||
},
|
||
};
|
||
|
||
const MATERIAL_TYPE_MAP = {
|
||
weighingSlip: 'weighing_slip',
|
||
entrustOrder: 'entrust_order',
|
||
settlement: 'settlement',
|
||
contract: 'contract',
|
||
specialApproval: 'special_approval',
|
||
};
|
||
|
||
const emptyForm = () => ({
|
||
id: null,
|
||
paymentNo: '',
|
||
paymentType: 'project_advance',
|
||
settlementId: null,
|
||
preSettlementId: null,
|
||
preSettlementIds: [],
|
||
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,
|
||
transferPayload: null,
|
||
referenceRows: [],
|
||
paymentRecords: [],
|
||
referenceVisible: false,
|
||
referenceTab: 'formal',
|
||
formalRows: [],
|
||
preRows: [],
|
||
contractRows: [],
|
||
billOptions: [],
|
||
billLoading: false,
|
||
receiptAccountOptions: [],
|
||
receiptAccountLoading: false,
|
||
firstContractPayment: false,
|
||
payeeCustomerLevel: '',
|
||
attachmentRuleLoading: 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: '请选择付款方式' }],
|
||
receiptAccountId: [{ required: true, message: '请选择收款账号', trigger: 'change' }],
|
||
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() {
|
||
if (this.referenceRows.length) {
|
||
return this.referenceRows
|
||
.map(item => item.settlementNo)
|
||
.filter(Boolean)
|
||
.join('、');
|
||
}
|
||
return this.form.settlementNo || this.form.preSettlementNo || '';
|
||
},
|
||
settlementRows() {
|
||
if (this.referenceRows.length) {
|
||
return this.referenceRows.map(item => ({
|
||
...item,
|
||
paymentRatio: this.form.paymentRatio,
|
||
appliedAmount: Number(
|
||
((Number(item.payableAmount || 0) * Number(this.form.paymentRatio || 0)) / 100).toFixed(
|
||
2
|
||
)
|
||
),
|
||
}));
|
||
}
|
||
if (!this.referenceLabel) return [];
|
||
return [
|
||
{
|
||
settlementNo: this.referenceLabel,
|
||
settlementAmount: this.form.settlementAmount,
|
||
payableAmount: this.form.payableAmount,
|
||
paymentRatio: this.form.paymentRatio,
|
||
appliedAmount: this.form.appliedAmount,
|
||
},
|
||
];
|
||
},
|
||
highRiskPayee() {
|
||
const level = String(this.payeeCustomerLevel || '')
|
||
.trim()
|
||
.toUpperCase();
|
||
return ['D', 'D级', 'E', 'E级', 'F', 'F级'].includes(level) || level.includes('高风险');
|
||
},
|
||
requiredAttachmentMaterials() {
|
||
const materials = [ATTACHMENT_MATERIALS.weighingSlip, ATTACHMENT_MATERIALS.settlement];
|
||
if (this.form.paymentType === 'project_advance') {
|
||
materials.splice(1, 0, ATTACHMENT_MATERIALS.entrustOrder);
|
||
}
|
||
if (this.firstContractPayment) materials.push(ATTACHMENT_MATERIALS.contract);
|
||
if (this.highRiskPayee) materials.push(ATTACHMENT_MATERIALS.specialApproval);
|
||
return materials;
|
||
},
|
||
missingAttachmentMaterials() {
|
||
return this.requiredAttachmentMaterials.filter(item => !this.hasAttachmentMaterial(item));
|
||
},
|
||
},
|
||
watch: {
|
||
'$route.query.transferToken': async function (token, oldToken) {
|
||
if (!this.recordId && token && token !== oldToken) {
|
||
this.transferPayload = readSettlementTransfer(token);
|
||
await this.initialize();
|
||
}
|
||
},
|
||
'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.transferPayload = readSettlementTransfer(this.$route.query.transferToken);
|
||
this.initialize();
|
||
},
|
||
methods: {
|
||
hasPermission(code) {
|
||
return this.permission?.[code] !== false;
|
||
},
|
||
validateReference(rule, value, callback) {
|
||
if (
|
||
this.form.paymentType === 'progress_advance' &&
|
||
!this.form.preSettlementId &&
|
||
!this.form.preSettlementIds?.length
|
||
) {
|
||
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,
|
||
preSettlementIds: data.preSettlementIds?.length
|
||
? data.preSettlementIds
|
||
: data.preSettlementId
|
||
? [data.preSettlementId]
|
||
: [],
|
||
attachments: this.parse(data.attachmentsJson),
|
||
invoices: data.invoices || [],
|
||
};
|
||
const referenceRow = this.createReferenceRow(data);
|
||
this.referenceRows = referenceRow.settlementNo ? [referenceRow] : [];
|
||
this.paymentRecords = data.paymentRecords || [];
|
||
await this.loadReceiptAccountOptions(false);
|
||
await this.loadAttachmentRuleData(await this.loadCurrentSettlementDetails());
|
||
if (this.billPayment) await this.loadBillOptions('', data.billLedgerId);
|
||
} else {
|
||
this.form = emptyForm();
|
||
this.referenceRows = [];
|
||
this.form.applyDate = this.$dayjs().format('YYYY-MM-DD');
|
||
this.form.applicantName =
|
||
this.$store.getters.userInfo?.realName || this.$store.getters.userInfo?.userName || '';
|
||
await this.loadTransferredPreSettlements();
|
||
}
|
||
},
|
||
getTransferredPreSettlementIds() {
|
||
const payloadIds = (this.transferPayload?.sourcePreSettlements || []).map(
|
||
item => item.preSettlementId || item.id
|
||
);
|
||
const queryIds = String(this.$route.query.preSettlementIds || '')
|
||
.split(',')
|
||
.map(item => item.trim())
|
||
.filter(Boolean);
|
||
return [...new Set([...payloadIds, ...queryIds].map(String))];
|
||
},
|
||
async loadTransferredPreSettlements() {
|
||
const fallbackRows = this.transferPayload?.sourcePreSettlements || [];
|
||
const ids = this.getTransferredPreSettlementIds();
|
||
if (!ids.length) {
|
||
this.applyTransferredPreSettlements(fallbackRows);
|
||
await Promise.all([
|
||
this.loadReceiptAccountOptions(),
|
||
this.loadAttachmentRuleData(fallbackRows),
|
||
]);
|
||
return;
|
||
}
|
||
try {
|
||
const responses = await Promise.all(ids.map(id => preApi.getDetail(id)));
|
||
const rows = responses.map(response => this.unwrapData(response)).filter(item => item?.id);
|
||
const sourceRows = rows.length ? rows : fallbackRows;
|
||
this.applyTransferredPreSettlements(sourceRows);
|
||
await Promise.all([
|
||
this.loadReceiptAccountOptions(),
|
||
this.loadAttachmentRuleData(sourceRows),
|
||
]);
|
||
} catch (error) {
|
||
if (fallbackRows.length) {
|
||
this.applyTransferredPreSettlements(fallbackRows);
|
||
await Promise.all([
|
||
this.loadReceiptAccountOptions(),
|
||
this.loadAttachmentRuleData(fallbackRows),
|
||
]);
|
||
return;
|
||
}
|
||
this.$message.error('预结算信息加载失败,请返回后重新发起预付申请');
|
||
throw error;
|
||
}
|
||
},
|
||
createReferenceRow(row) {
|
||
const settlementAmount = Number(row.settlementAmount || 0);
|
||
const appliedAmount = Number(row.advanceAppliedAmount || row.appliedPaymentAmount || 0);
|
||
return {
|
||
id: row.preSettlementId || row.settlementId || row.id,
|
||
settlementNo: row.preSettlementNo || row.formalSettlementNo || row.settlementNo || '',
|
||
settlementAmount,
|
||
payableAmount:
|
||
row.payableAmount === undefined || row.payableAmount === null
|
||
? Math.max(0, settlementAmount - appliedAmount)
|
||
: Number(row.payableAmount || 0),
|
||
};
|
||
},
|
||
applyTransferredPreSettlements(rows = []) {
|
||
if (!rows.length) return;
|
||
const contractIds = new Set(rows.map(item => String(item.contractId || '')));
|
||
if (contractIds.size > 1 || contractIds.has('')) {
|
||
this.$message.warning('所选预结算单合同信息不一致,请返回后重新选择');
|
||
return;
|
||
}
|
||
const first = rows[0];
|
||
this.referenceRows = rows.map(item => this.createReferenceRow(item));
|
||
const settlementAmount = this.referenceRows.reduce(
|
||
(total, item) => total + Number(item.settlementAmount || 0),
|
||
0
|
||
);
|
||
const payableAmount = this.referenceRows.reduce(
|
||
(total, item) => total + Number(item.payableAmount || 0),
|
||
0
|
||
);
|
||
const paymentRatio = Number(this.form.paymentRatio || 0);
|
||
this.amountSyncing = true;
|
||
Object.assign(this.form, {
|
||
paymentType: 'progress_advance',
|
||
settlementId: null,
|
||
settlementNo: '',
|
||
preSettlementId: first.preSettlementId || first.id,
|
||
preSettlementIds: rows.map(item => item.preSettlementId || item.id),
|
||
preSettlementNo: this.referenceRows
|
||
.map(item => item.settlementNo)
|
||
.filter(Boolean)
|
||
.join('、'),
|
||
projectId: first.projectId,
|
||
projectName: first.projectName,
|
||
deptId: first.deptId,
|
||
deptName: first.deptName,
|
||
contractId: first.contractId,
|
||
contractNo: first.contractNo,
|
||
contractName: first.contractName,
|
||
payerName: first.payerName,
|
||
payeeName: first.payeeName,
|
||
settlementAmount: Number(settlementAmount.toFixed(2)),
|
||
payableAmount: Number(payableAmount.toFixed(2)),
|
||
billType: '预结算单',
|
||
appliedAmount: Number(((payableAmount * paymentRatio) / 100).toFixed(2)),
|
||
});
|
||
this.$nextTick(() => {
|
||
this.amountSyncing = false;
|
||
this.$refs.formRef?.clearValidate();
|
||
});
|
||
},
|
||
parse(value) {
|
||
if (!value) return [];
|
||
if (Array.isArray(value)) return value;
|
||
try {
|
||
return JSON.parse(value) || [];
|
||
} catch {
|
||
return [];
|
||
}
|
||
},
|
||
attachmentFileName(file) {
|
||
return String(file?.originalName || file?.name || file?.fileName || '').trim();
|
||
},
|
||
attachmentFileUrl(file) {
|
||
return file?.url || file?.link || file?.src || file?.domain || '';
|
||
},
|
||
attachmentMatchesMaterial(file, material) {
|
||
const fileName = this.attachmentFileName(file).toLocaleLowerCase();
|
||
return (
|
||
Boolean(this.attachmentFileUrl(file)) &&
|
||
material.keywords.some(keyword => fileName.includes(keyword.toLocaleLowerCase()))
|
||
);
|
||
},
|
||
hasAttachmentMaterial(material) {
|
||
return (this.form.attachments || []).some(file =>
|
||
this.attachmentMatchesMaterial(file, material)
|
||
);
|
||
},
|
||
resolveAttachmentMaterial(file, materials = Object.values(ATTACHMENT_MATERIALS)) {
|
||
return [...materials]
|
||
.sort(
|
||
(a, b) =>
|
||
Math.max(...b.keywords.map(String.length)) - Math.max(...a.keywords.map(String.length))
|
||
)
|
||
.find(material => this.attachmentMatchesMaterial(file, material));
|
||
},
|
||
mergeAutomaticAttachments(files, materials, sourceName) {
|
||
const existingUrls = new Set(
|
||
(this.form.attachments || []).map(file => this.attachmentFileUrl(file)).filter(Boolean)
|
||
);
|
||
const imported = (files || [])
|
||
.map(file => ({ file, material: this.resolveAttachmentMaterial(file, materials) }))
|
||
.filter(item => item.material && !existingUrls.has(this.attachmentFileUrl(item.file)))
|
||
.map(({ file, material }) => {
|
||
existingUrls.add(this.attachmentFileUrl(file));
|
||
return {
|
||
...file,
|
||
originalName: this.attachmentFileName(file),
|
||
name: this.attachmentFileName(file),
|
||
url: this.attachmentFileUrl(file),
|
||
link: file.link || this.attachmentFileUrl(file),
|
||
attachmentType: MATERIAL_TYPE_MAP[material.key],
|
||
description: file.description || `自动取自${sourceName}`,
|
||
sourceImported: true,
|
||
};
|
||
});
|
||
if (imported.length) this.form.attachments = [...this.form.attachments, ...imported];
|
||
},
|
||
async loadCurrentSettlementDetails() {
|
||
const requests = [];
|
||
if (this.form.preSettlementId) requests.push(preApi.getDetail(this.form.preSettlementId));
|
||
if (this.form.settlementId) requests.push(formalApi.getDetail(this.form.settlementId));
|
||
if (!requests.length) return [];
|
||
const responses = await Promise.all(requests);
|
||
return responses.map(response => this.unwrapData(response)).filter(item => item?.id);
|
||
},
|
||
async loadAttachmentRuleData(settlementRows = []) {
|
||
this.attachmentRuleLoading = true;
|
||
this.firstContractPayment = false;
|
||
try {
|
||
const settlementMaterials = [
|
||
ATTACHMENT_MATERIALS.weighingSlip,
|
||
ATTACHMENT_MATERIALS.entrustOrder,
|
||
ATTACHMENT_MATERIALS.settlement,
|
||
];
|
||
const settlementFiles = (settlementRows || []).flatMap(row =>
|
||
this.parse(row.attachmentsJson)
|
||
);
|
||
this.mergeAutomaticAttachments(settlementFiles, settlementMaterials, '结算单');
|
||
if (!this.form.contractId) {
|
||
this.firstContractPayment = false;
|
||
return;
|
||
}
|
||
const [contractResponse, paymentResponse] = await Promise.all([
|
||
getContractDetail(this.form.contractId),
|
||
api.getList(1, 9999, { contractId: this.form.contractId }),
|
||
]);
|
||
const contract = this.unwrapData(contractResponse) || {};
|
||
const payments = this.unwrapData(paymentResponse)?.records || [];
|
||
this.firstContractPayment = !payments.some(
|
||
item =>
|
||
String(item.contractId || '') === String(this.form.contractId) &&
|
||
String(item.id || '') !== String(this.form.id || '') &&
|
||
item.approvalStatus !== 'voided'
|
||
);
|
||
if (this.firstContractPayment) {
|
||
this.mergeAutomaticAttachments(
|
||
this.parse(contract.contractFileJson),
|
||
[ATTACHMENT_MATERIALS.contract],
|
||
'合同'
|
||
);
|
||
}
|
||
} catch (error) {
|
||
this.$message.warning('附件清单来源材料加载失败,请核对后手工补充');
|
||
} finally {
|
||
this.attachmentRuleLoading = false;
|
||
}
|
||
},
|
||
validateRequiredAttachments() {
|
||
if (!this.missingAttachmentMaterials.length) return true;
|
||
this.$message.warning(
|
||
`请先上传付款申请所需材料:${this.missingAttachmentMaterials
|
||
.map(item => item.label)
|
||
.join('、')}`
|
||
);
|
||
return false;
|
||
},
|
||
handleTypeChange() {
|
||
if (this.form.paymentType === 'project_advance') {
|
||
this.form.settlementId = null;
|
||
this.form.preSettlementId = null;
|
||
this.form.preSettlementIds = [];
|
||
this.form.settlementNo = '';
|
||
this.form.preSettlementNo = '';
|
||
this.referenceRows = [];
|
||
}
|
||
this.loadAttachmentRuleData([]);
|
||
},
|
||
clearReceiptAccount() {
|
||
Object.assign(this.form, {
|
||
receiptAccountId: null,
|
||
receiptAccountName: '',
|
||
bankName: '',
|
||
bankAccount: '',
|
||
});
|
||
},
|
||
customerRecords(response) {
|
||
return this.unwrapData(response)?.records || [];
|
||
},
|
||
async loadReceiptAccountOptions(autoSelectDefault = true) {
|
||
const payeeName = String(this.form.payeeName || '').trim();
|
||
const preserveCurrentValue = autoSelectDefault === false;
|
||
this.receiptAccountOptions = [];
|
||
this.payeeCustomerLevel = '';
|
||
if (!payeeName) {
|
||
if (!preserveCurrentValue) this.clearReceiptAccount();
|
||
return;
|
||
}
|
||
this.receiptAccountLoading = true;
|
||
try {
|
||
const [fullNameResponse, shortNameResponse] = await Promise.all([
|
||
getCustomerArchiveList(1, 20, {
|
||
fullName: payeeName,
|
||
approvalStatus: 'approved',
|
||
status: 1,
|
||
}),
|
||
getCustomerArchiveList(1, 20, {
|
||
shortName: payeeName,
|
||
approvalStatus: 'approved',
|
||
status: 1,
|
||
}),
|
||
]);
|
||
const customers = [
|
||
...this.customerRecords(fullNameResponse),
|
||
...this.customerRecords(shortNameResponse),
|
||
];
|
||
const customer = customers.find(
|
||
item => item.fullName === payeeName || item.shortName === payeeName
|
||
);
|
||
if (!customer?.id) {
|
||
if (!preserveCurrentValue) this.clearReceiptAccount();
|
||
return;
|
||
}
|
||
const detail = this.unwrapData(await getCustomerArchiveDetail(customer.id));
|
||
this.payeeCustomerLevel = detail.customerLevel || '';
|
||
this.receiptAccountOptions = (detail.receiptAccounts || []).map(item => ({
|
||
...item,
|
||
id: String(item.id),
|
||
}));
|
||
const selected = this.receiptAccountOptions.find(
|
||
item => String(item.id) === String(this.form.receiptAccountId || '')
|
||
);
|
||
if (selected) {
|
||
this.applyReceiptAccount(selected);
|
||
return;
|
||
}
|
||
if (preserveCurrentValue) return;
|
||
this.clearReceiptAccount();
|
||
if (autoSelectDefault && !this.readonly) {
|
||
const defaultAccount =
|
||
this.receiptAccountOptions.find(item => Number(item.isDefault) === 1) ||
|
||
(this.receiptAccountOptions.length === 1 ? this.receiptAccountOptions[0] : null);
|
||
if (defaultAccount) this.applyReceiptAccount(defaultAccount);
|
||
}
|
||
} catch (error) {
|
||
if (!preserveCurrentValue) this.clearReceiptAccount();
|
||
this.$message.warning('收款方的客商收款信息加载失败,请稍后重试');
|
||
} finally {
|
||
this.receiptAccountLoading = false;
|
||
}
|
||
},
|
||
receiptAccountLabel(item) {
|
||
return [item.accountName || item.accountHolderName, item.bankName, item.bankAccount]
|
||
.filter(Boolean)
|
||
.join('|');
|
||
},
|
||
applyReceiptAccount(account) {
|
||
Object.assign(this.form, {
|
||
receiptAccountId: account.id,
|
||
receiptAccountName: account.accountName || account.accountHolderName || '',
|
||
bankName: account.bankName || '',
|
||
bankAccount: account.bankAccount || '',
|
||
});
|
||
this.$nextTick(() => this.$refs.formRef?.validateField('receiptAccountId').catch(() => {}));
|
||
},
|
||
handleReceiptAccountChange(id) {
|
||
const account = this.receiptAccountOptions.find(item => String(item.id) === String(id || ''));
|
||
if (account) {
|
||
this.applyReceiptAccount(account);
|
||
return;
|
||
}
|
||
this.clearReceiptAccount();
|
||
},
|
||
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;
|
||
},
|
||
async selectContract(row) {
|
||
this.referenceRows = [];
|
||
this.clearReceiptAccount();
|
||
const settlementType = row.settlementType || 'payable';
|
||
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 || (settlementType === 'receivable' ? row.partyB : row.partyA) || '',
|
||
payeeName:
|
||
row.payeeName || (settlementType === 'receivable' ? row.partyA : row.partyB) || '',
|
||
billType: '项目预付',
|
||
});
|
||
this.referenceVisible = false;
|
||
await Promise.all([this.loadReceiptAccountOptions(), this.loadAttachmentRuleData([])]);
|
||
if (this.billPayment) this.loadBillOptions();
|
||
},
|
||
async selectFormal(row) {
|
||
this.referenceRows = [this.createReferenceRow(row)];
|
||
this.clearReceiptAccount();
|
||
Object.assign(this.form, {
|
||
settlementId: row.id,
|
||
preSettlementId: null,
|
||
preSettlementIds: [],
|
||
settlementNo: row.formalSettlementNo,
|
||
preSettlementNo: '',
|
||
projectId: row.projectId,
|
||
projectName: row.projectName,
|
||
deptId: row.deptId,
|
||
deptName: row.deptName,
|
||
contractId: row.contractId,
|
||
contractNo: row.contractNo,
|
||
contractName: row.contractName,
|
||
settlementAmount: row.settlementAmount,
|
||
payableAmount: Math.max(
|
||
0,
|
||
Number(row.settlementAmount || 0) - Number(row.appliedPaymentAmount || 0)
|
||
),
|
||
billType: '正式结算单',
|
||
payerName: row.payerName,
|
||
payeeName: row.payeeName,
|
||
});
|
||
this.referenceVisible = false;
|
||
const detail = this.unwrapData(await formalApi.getDetail(row.id));
|
||
await Promise.all([
|
||
this.loadReceiptAccountOptions(),
|
||
this.loadAttachmentRuleData(detail?.id ? [detail] : []),
|
||
]);
|
||
if (this.billPayment) this.loadBillOptions();
|
||
},
|
||
async selectPre(row) {
|
||
this.referenceRows = [this.createReferenceRow(row)];
|
||
this.clearReceiptAccount();
|
||
Object.assign(this.form, {
|
||
preSettlementId: row.id,
|
||
preSettlementIds: [row.id],
|
||
settlementId: null,
|
||
preSettlementNo: row.preSettlementNo,
|
||
settlementNo: '',
|
||
projectId: row.projectId,
|
||
projectName: row.projectName,
|
||
deptId: row.deptId,
|
||
deptName: row.deptName,
|
||
contractId: row.contractId,
|
||
contractNo: row.contractNo,
|
||
contractName: row.contractName,
|
||
settlementAmount: row.settlementAmount,
|
||
payableAmount: Math.max(
|
||
0,
|
||
Number(row.settlementAmount || 0) - Number(row.advanceAppliedAmount || 0)
|
||
),
|
||
billType: '预结算单',
|
||
payerName: row.payerName,
|
||
payeeName: row.payeeName,
|
||
});
|
||
this.referenceVisible = false;
|
||
const detail = this.unwrapData(await preApi.getDetail(row.id));
|
||
await Promise.all([
|
||
this.loadReceiptAccountOptions(),
|
||
this.loadAttachmentRuleData(detail?.id ? [detail] : []),
|
||
]);
|
||
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 ||
|
||
MATERIAL_TYPE_MAP[this.resolveAttachmentMaterial(file)?.key] ||
|
||
'other',
|
||
description: file.description || '',
|
||
uploadUserName: file.uploadUserName || userName,
|
||
uploadTime: file.uploadTime || time,
|
||
}));
|
||
},
|
||
payload() {
|
||
const {
|
||
id,
|
||
paymentType,
|
||
settlementId,
|
||
preSettlementId,
|
||
preSettlementIds,
|
||
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,
|
||
preSettlementIds,
|
||
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(validateMaterials = false) {
|
||
await this.$refs.formRef.validate();
|
||
if (this.form.paymentType === 'project_advance' && !this.form.projectId) {
|
||
this.$message.warning('请选择所属项目');
|
||
return false;
|
||
}
|
||
if (validateMaterials && !this.validateRequiredAttachments()) 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(true);
|
||
if (!saved) return;
|
||
await api.submit({ id: this.form.id });
|
||
this.$message.success('提交成功');
|
||
this.goBack();
|
||
},
|
||
goBack() {
|
||
removeSettlementTransfer(this.$route.query.transferToken);
|
||
this.$router.push('/payment/payment-application');
|
||
},
|
||
formatMoney(value) {
|
||
return Number(value || 0).toFixed(2);
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.payment-form-page__actions {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 16px;
|
||
padding: 24px 0;
|
||
border-top: 1px solid #eff1f7;
|
||
}
|
||
.payment-form-page__section-actions {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
margin-bottom: 8px;
|
||
}
|
||
.payment-form-page__attachment-upload {
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
margin-top: 12px;
|
||
}
|
||
.payment-form-page__missing-text {
|
||
margin-left: 12px;
|
||
color: var(--el-color-danger);
|
||
font-size: 13px;
|
||
font-weight: 400;
|
||
}
|
||
.payment-form-page__attachment-checklist {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-bottom: 12px;
|
||
}
|
||
.payment-form-page__attachment-checklist-label {
|
||
color: var(--el-text-color-regular);
|
||
font-weight: 600;
|
||
}
|
||
.payment-form-page__attachment-upload .vehicle-attachment-upload {
|
||
width: auto;
|
||
}
|
||
.payment-form-page__attachment-upload .el-upload {
|
||
display: inline-flex;
|
||
}
|
||
.payment-form-page :deep(.el-form-item) {
|
||
margin-bottom: 14px;
|
||
}
|
||
.payment-form-page :deep(.el-input-number .el-input__inner) {
|
||
text-align: left;
|
||
}
|
||
.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>
|