|
|
|
@ -0,0 +1,811 @@
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
|
|
<div class="p-3">
|
|
|
|
|
|
|
|
<el-card shadow="never" style="margin-top: 0; margin-bottom: 10px">
|
|
|
|
|
|
|
|
<!-- <template #header>-->
|
|
|
|
|
|
|
|
<!-- <div style="text-align: left; font-weight: bold; font-size: 24px">合同{{ form.contractId ? ' - 修改' : ' - 新增' }}</div>-->
|
|
|
|
|
|
|
|
<!-- </template>-->
|
|
|
|
|
|
|
|
<!-- 审批按钮组件 -->
|
|
|
|
|
|
|
|
<approvalButton
|
|
|
|
|
|
|
|
@submitForm="handleSave"
|
|
|
|
|
|
|
|
@approvalVerifyOpen="approvalVerifyOpen"
|
|
|
|
|
|
|
|
@handleApprovalRecord="handleApprovalRecord"
|
|
|
|
|
|
|
|
:buttonLoading="buttonLoading"
|
|
|
|
|
|
|
|
:id="form.invoiceId"
|
|
|
|
|
|
|
|
:status="form.flowStatus"
|
|
|
|
|
|
|
|
:pageType="routeParams.type"
|
|
|
|
|
|
|
|
:mode="false"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-card shadow="never" class="mb-[15px]" header="开票信息">
|
|
|
|
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="130px" status-icon>
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<!-- 第一行 -->
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="发出人员" prop="requestBy">
|
|
|
|
|
|
|
|
<el-select v-model="form.requestBy" placeholder="请选择发出人员" clearable filterable class="w-full" @change="handleUserChange">
|
|
|
|
|
|
|
|
<el-option v-for="user in userOptions" :key="user.userId" :label="user.nickName" :value="user.userId" />
|
|
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="发出部门" prop="requestDeptName">
|
|
|
|
|
|
|
|
<el-input v-model="form.requestDeptName" readonly />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="发出日期" prop="issueDate">
|
|
|
|
|
|
|
|
<el-date-picker v-model="form.issueDate" type="date" placeholder="请选择发出日期" value-format="YYYY-MM-DD" class="w-full" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<!-- 第二行:项目信息 -->
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="项目编号" prop="projectCode">
|
|
|
|
|
|
|
|
<el-input v-model="form.projectCode" placeholder="请选择项目编号" @click="handleSelectProject" readonly suffix-icon="Search">
|
|
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="项目名称" prop="projectName">
|
|
|
|
|
|
|
|
<el-input v-model="form.projectName" placeholder="项目名称" readonly />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="合同编号" prop="contractCode">
|
|
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
|
|
v-if="form.projectId && form.projectId !== '' && form.contractFlag === CONTRACT_FLAG.NO"
|
|
|
|
|
|
|
|
v-model="form.contractCode"
|
|
|
|
|
|
|
|
placeholder="请选择合同"
|
|
|
|
|
|
|
|
readonly
|
|
|
|
|
|
|
|
@click="showContractSelectDialog"
|
|
|
|
|
|
|
|
suffix-icon="Search"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<el-input v-else v-model="form.contractCode" readonly />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="客户名称" prop="customerName">
|
|
|
|
|
|
|
|
<el-input v-model="form.customerName" placeholder="客户名称" readonly />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="合同金额" prop="totalPrice">
|
|
|
|
|
|
|
|
<el-input v-model="form.totalPrice" placeholder="合同金额" readonly></el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="本次开具发票比例" prop="issuancePercentage">
|
|
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
|
|
v-model="form.issuancePercentage"
|
|
|
|
|
|
|
|
:precision="2"
|
|
|
|
|
|
|
|
:min="1"
|
|
|
|
|
|
|
|
:max="100"
|
|
|
|
|
|
|
|
placeholder="请输入开具发票比例"
|
|
|
|
|
|
|
|
style="width: 210px"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
</el-input-number>
|
|
|
|
|
|
|
|
<span style="margin-left: 5px">%</span>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
|
|
<el-form-item label="合同付款条款" prop="paymentMethod">
|
|
|
|
|
|
|
|
<span class="el-input__wrapper" style="padding: 0 11px; min-height: 32px; display: flex; align-items: center">
|
|
|
|
|
|
|
|
{{ paymentDescription }}
|
|
|
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="项目类型" prop="invoiceCategory">
|
|
|
|
|
|
|
|
<el-radio-group v-model="form.invoiceCategory">
|
|
|
|
|
|
|
|
<el-radio v-for="dict in invoice_category" :key="dict.value" :value="dict.value">{{ dict.label }} </el-radio>
|
|
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="累计回款金额" prop="returnedMoney">
|
|
|
|
|
|
|
|
<el-input-number v-model="form.returnedMoney" :precision="2" placeholder="请输入累计回款金额" style="width: 210px"></el-input-number>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="累计回款比例" prop="returnedRate">
|
|
|
|
|
|
|
|
<el-input v-model="form.returnedRate" placeholder="累计回款比例" readonly>
|
|
|
|
|
|
|
|
<template #append>%</template>
|
|
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="提前开票" prop="earlyFlag">
|
|
|
|
|
|
|
|
<el-radio-group v-model="form.earlyFlag">
|
|
|
|
|
|
|
|
<el-radio v-for="dict in early_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
|
|
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="验收日期" prop="acceptanceDate" v-if="form.earlyFlag !== EARLY_FLAG.YES">
|
|
|
|
|
|
|
|
<el-date-picker v-model="form.acceptanceDate" type="date" placeholder="请选择验收日期" value-format="YYYY-MM-DD" class="w-full" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
|
|
<el-form-item label="发货日期" prop="deliveryDate" v-if="form.earlyFlag !== EARLY_FLAG.YES">
|
|
|
|
|
|
|
|
<el-date-picker v-model="form.deliveryDate" type="date" placeholder="请选择发货日期" value-format="YYYY-MM-DD" class="w-full" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
|
|
<el-form-item label="提前开票原因" prop="earlyReason" v-if="form.earlyFlag === EARLY_FLAG.YES">
|
|
|
|
|
|
|
|
<el-input v-model="form.earlyReason" placeholder="请输入提前开票原因" type="textarea" :rows="1" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
|
|
<el-form-item label="发票备注信息" prop="remark">
|
|
|
|
|
|
|
|
<el-input v-model="form.remark" placeholder="请输入发票需备注的信息内容" type="textarea" :rows="1" />
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
|
|
<el-form-item
|
|
|
|
|
|
|
|
label="发票附件"
|
|
|
|
|
|
|
|
prop="ossId"
|
|
|
|
|
|
|
|
v-if="routeParams.type === 'update' || routeParams.type === 'view' || routeParams.type === 'approval'"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<!-- <el-button type="primary" plain icon="Upload" @click="handleFile">上传合同附件</el-button>-->
|
|
|
|
|
|
|
|
<FileUpload
|
|
|
|
|
|
|
|
v-model="ossIdString"
|
|
|
|
|
|
|
|
:limit="5"
|
|
|
|
|
|
|
|
:fileSize="20"
|
|
|
|
|
|
|
|
:fileType="['png', 'jpg', 'pdf', 'ofd', 'xml']"
|
|
|
|
|
|
|
|
:isShowTip="true"
|
|
|
|
|
|
|
|
:disabled="!hasInvoiceAttachPer"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 开票明细 -->
|
|
|
|
|
|
|
|
<el-card shadow="never" class="mb-[15px]" header="开票明细">
|
|
|
|
|
|
|
|
<template #header>
|
|
|
|
|
|
|
|
<div class="flex justify-between items-center">
|
|
|
|
|
|
|
|
<span class="font-medium">开票明细</span>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<el-button type="primary" plain size="small" icon="Plus" @click="handleAddItem">新增明细</el-button>
|
|
|
|
|
|
|
|
<el-button type="danger" plain size="small" icon="Delete" @click="handleDeleteItems" :disabled="selectedItems.length === 0"
|
|
|
|
|
|
|
|
>删除
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table :data="form.erpFinInvoiceDetailList" border stripe @selection-change="handleSelectionChange" max-height="400">
|
|
|
|
|
|
|
|
<el-table-column type="selection" width="55" align="center" />
|
|
|
|
|
|
|
|
<el-table-column label="序号" type="index" width="60" align="center" />
|
|
|
|
|
|
|
|
<el-table-column label="开票内容" prop="billingItems" min-width="160">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-input v-model="row.billingItems" placeholder="请输入开票内容" @change="handleItemChange($index)" />
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="规格型号" prop="specificationModel" min-width="140">
|
|
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
|
|
<el-input v-model="row.specificationModel" placeholder="请输入规格型号" />
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="单位" prop="unitName" width="120">
|
|
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
|
|
<el-input v-model="row.unitName" placeholder="请输入单位" />
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="数量" prop="quantity" width="145">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
|
|
v-model="row.quantity"
|
|
|
|
|
|
|
|
:min="0"
|
|
|
|
|
|
|
|
:precision="2"
|
|
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
|
|
@change="calculateItemAmount($index)"
|
|
|
|
|
|
|
|
style="width: 120px"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="税率(%)" prop="taxRate" width="145">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-input-number v-model="row.taxRate" :min="0" :max="100" :precision="2" controls-position="right" style="width: 120px" />
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<el-table-column label="单价(含税)" prop="unitPrice" width="145">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-input-number
|
|
|
|
|
|
|
|
v-model="row.unitPrice"
|
|
|
|
|
|
|
|
:min="0"
|
|
|
|
|
|
|
|
:precision="2"
|
|
|
|
|
|
|
|
controls-position="right"
|
|
|
|
|
|
|
|
@change="calculateItemAmount($index)"
|
|
|
|
|
|
|
|
style="width: 120px"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="金额(含税)" prop="totalPrice" width="140">
|
|
|
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
|
|
|
<span class="text-red-500 font-medium">{{ row.totalPrice?.toFixed(2) || '0.00' }}</span>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
<el-table-column label="操作" fixed="right" width="80" align="center">
|
|
|
|
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
|
|
|
|
<el-button link type="danger" icon="Delete" @click="handleRemoveItem($index, row)" />
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="flex justify-end mt-3 text-sm">
|
|
|
|
|
|
|
|
<div class="mr-4">
|
|
|
|
|
|
|
|
合计金额(含税):<span class="text-red-500 font-bold text-base">{{ totalInvoiceAmount }}</span>
|
|
|
|
|
|
|
|
元
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 项目选择弹窗 -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 项目选择弹窗组件 -->
|
|
|
|
|
|
|
|
<ProjectSelectDialog v-model:visible="projectSelectDialogVisible" projectCategory="1" @project-selected="handleProjectSelected" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 合同选择弹窗组件 -->
|
|
|
|
|
|
|
|
<ContractSelectDialog v-model:visible="contractSelectDialogVisible" @contract-selected="handleContractSelected" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 部门选择弹窗 (可根据实际组件调整) -->
|
|
|
|
|
|
|
|
<el-dialog v-model="deptDialogVisible" title="选择部门" width="600px" append-to-body>
|
|
|
|
|
|
|
|
<div class="p-3 text-center text-gray-500">请根据实际项目集成部门选择组件</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button @click="deptDialogVisible = false">取消</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="handleDeptSelected">确定</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 人员选择弹窗 (可根据实际组件调整) -->
|
|
|
|
|
|
|
|
<el-dialog v-model="userDialogVisible" title="选择人员" width="600px" append-to-body>
|
|
|
|
|
|
|
|
<div class="p-3 text-center text-gray-500">请根据实际项目集成人员选择组件</div>
|
|
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
|
|
<el-button @click="userDialogVisible = false">取消</el-button>
|
|
|
|
|
|
|
|
<el-button type="primary" @click="handleUserSelected">确定</el-button>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 提交审批组件 -->
|
|
|
|
|
|
|
|
<submitVerify ref="submitVerifyRef" @submit-callback="submitCallback" />
|
|
|
|
|
|
|
|
<!-- 审批记录 -->
|
|
|
|
|
|
|
|
<approvalRecord ref="approvalRecordRef" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
|
|
import api from '@/api/system/user';
|
|
|
|
|
|
|
|
import { ref, reactive, computed, onMounted } from 'vue';
|
|
|
|
|
|
|
|
import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
|
|
|
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
|
|
|
import ProjectSelectDialog from '@/views/oa/components/ProjectSelectDialog.vue';
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
|
|
|
getFinInvoiceInfo,
|
|
|
|
|
|
|
|
getBaseInfo,
|
|
|
|
|
|
|
|
addFinInvoiceInfo,
|
|
|
|
|
|
|
|
updateFinInvoiceInfo,
|
|
|
|
|
|
|
|
getContractPaymentMethodList,
|
|
|
|
|
|
|
|
updateInvoiceAttach
|
|
|
|
|
|
|
|
} from '@/api/oa/erp/finInvoiceInfo';
|
|
|
|
|
|
|
|
import { FinInvoiceInfoForm, FinInvoiceInfoQuery } from '@/api/oa/erp/finInvoiceInfo/types';
|
|
|
|
|
|
|
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
|
|
|
|
|
|
|
import { FinInvoiceDetailVO } from '@/api/oa/erp/finInvoiceDetail/types';
|
|
|
|
|
|
|
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
|
|
|
|
|
|
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
|
|
|
|
|
|
|
import { DeptTreeVO } from '@/api/system/dept/types';
|
|
|
|
|
|
|
|
import { ContractPaymentMethodVO } from '@/api/oa/erp/contractPaymentMethod/types';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { UserVO } from '@/api/system/user/types';
|
|
|
|
|
|
|
|
import ContractSelectDialog from '@/views/oa/components/ContractSelectDialog.vue';
|
|
|
|
|
|
|
|
import FileUpload from '@/components/FileUpload/index.vue';
|
|
|
|
|
|
|
|
import { checkPermi } from '@/utils/permission';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const userOptions = ref<UserVO[]>([]);
|
|
|
|
|
|
|
|
const deptOptions = ref<DeptTreeVO[]>([]);
|
|
|
|
|
|
|
|
const enabledDeptOptions = ref<DeptTreeVO[]>([]);
|
|
|
|
|
|
|
|
const contractPaymentMethodVoList = ref<ContractPaymentMethodVO[]>([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
const routeParams = ref<Record<string, any>>({ ...(route.query as Record<string, any>) });
|
|
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const buttonLoading = ref(false);
|
|
|
|
|
|
|
|
const formRef = ref<FormInstance>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const BUSINESS_STATUS = reactive({
|
|
|
|
|
|
|
|
DRAFT: '1', //暂存
|
|
|
|
|
|
|
|
WAITING: '2', //审批中
|
|
|
|
|
|
|
|
AVAILABLE: '3' //可用
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { early_flag, invoice_category } = toRefs<any>(proxy?.useDict('early_flag', 'invoice_category'));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const EARLY_FLAG = reactive({
|
|
|
|
|
|
|
|
YES: '1', //是
|
|
|
|
|
|
|
|
NO: '0' //否
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const CONTRACT_FLAG = {
|
|
|
|
|
|
|
|
YES: '1',
|
|
|
|
|
|
|
|
NO: '2'
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const hasInvoiceAttachPer = checkPermi(['oa/erp:finInvoiceInfo:invoiceAttach']);
|
|
|
|
|
|
|
|
console.log(hasInvoiceAttachPer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 弹窗可见性
|
|
|
|
|
|
|
|
const projectSelectDialogVisible = ref(false);
|
|
|
|
|
|
|
|
const deptDialogVisible = ref(false);
|
|
|
|
|
|
|
|
const userDialogVisible = ref(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 表格选中项
|
|
|
|
|
|
|
|
const selectedItems = ref<FinInvoiceDetailVO[]>([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const toDeletedInvoiceDetailIdList = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const initFormData: FinInvoiceInfoForm = {
|
|
|
|
|
|
|
|
invoiceId: undefined,
|
|
|
|
|
|
|
|
invoiceCode: undefined,
|
|
|
|
|
|
|
|
earlyFlag: undefined,
|
|
|
|
|
|
|
|
invoiceType: undefined,
|
|
|
|
|
|
|
|
issueAmount: undefined,
|
|
|
|
|
|
|
|
issuancePercentage: undefined,
|
|
|
|
|
|
|
|
redInkFlag: undefined,
|
|
|
|
|
|
|
|
projectId: undefined,
|
|
|
|
|
|
|
|
projectCode: undefined,
|
|
|
|
|
|
|
|
projectName: undefined,
|
|
|
|
|
|
|
|
acceptanceDate: undefined,
|
|
|
|
|
|
|
|
deliveryDate: undefined,
|
|
|
|
|
|
|
|
arrivalDate: undefined,
|
|
|
|
|
|
|
|
invoiceVersion: undefined,
|
|
|
|
|
|
|
|
invoiceCategory: undefined,
|
|
|
|
|
|
|
|
contractId: undefined,
|
|
|
|
|
|
|
|
totalPrice: undefined,
|
|
|
|
|
|
|
|
customerId: undefined,
|
|
|
|
|
|
|
|
customerName: undefined,
|
|
|
|
|
|
|
|
paymentMethod: undefined,
|
|
|
|
|
|
|
|
returnedMoney: undefined,
|
|
|
|
|
|
|
|
returnedRate: undefined,
|
|
|
|
|
|
|
|
feedingFlag: undefined,
|
|
|
|
|
|
|
|
costCompleteFlag: undefined,
|
|
|
|
|
|
|
|
saleOrderCreateFlag: undefined,
|
|
|
|
|
|
|
|
flowStatus: undefined,
|
|
|
|
|
|
|
|
invoiceStatus: undefined,
|
|
|
|
|
|
|
|
remark: undefined,
|
|
|
|
|
|
|
|
earlyReason: undefined,
|
|
|
|
|
|
|
|
erpFinInvoiceDetailList: []
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const data = reactive<PageData<FinInvoiceInfoForm, FinInvoiceInfoQuery>>({
|
|
|
|
|
|
|
|
form: { ...initFormData },
|
|
|
|
|
|
|
|
queryParams: {
|
|
|
|
|
|
|
|
params: {}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
rules: {
|
|
|
|
|
|
|
|
projectCode: [{ required: true, message: '项目不能为空', trigger: 'blur' }],
|
|
|
|
|
|
|
|
invoiceCategory: [{ required: true, message: '项目类型不能为空', trigger: 'blur' }],
|
|
|
|
|
|
|
|
earlyFlag: [{ required: true, message: '提前开票不能为空', trigger: 'blur' }]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { form, rules } = toRefs(data);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 附件ID字符串转换(用于FileUpload组件)
|
|
|
|
|
|
|
|
const ossIdString = computed({
|
|
|
|
|
|
|
|
get: () => {
|
|
|
|
|
|
|
|
if (form.value.ossId === undefined || form.value.ossId === null) {
|
|
|
|
|
|
|
|
return '';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return String(form.value.ossId);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
set: (val: string) => {
|
|
|
|
|
|
|
|
form.value.ossId = val || undefined;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => form.value.ossId,
|
|
|
|
|
|
|
|
async (newVal, oldVal) => {
|
|
|
|
|
|
|
|
// 使用 ?? 将 null 和 undefined 都统一为 'empty' 字符串
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 如果 ossId 从无到有,或者从有到无,或者值改变 (只在初始化完成后,并且值确实发生变化时才执行)
|
|
|
|
|
|
|
|
if (isInitialized.value) {
|
|
|
|
|
|
|
|
const normalizedOld = oldVal ?? 'empty';
|
|
|
|
|
|
|
|
const normalizedNew = newVal ?? 'empty';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log(normalizedOld + '---' + normalizedNew);
|
|
|
|
|
|
|
|
if (normalizedOld !== normalizedNew) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
|
|
|
console.log('附件发生变化,旧值:', oldVal, '新值:', newVal);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新数据库
|
|
|
|
|
|
|
|
const invoiceAttachForm = {
|
|
|
|
|
|
|
|
invoiceId: form.value.invoiceId,
|
|
|
|
|
|
|
|
ossId: form.value.ossId
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
await updateInvoiceAttach(invoiceAttachForm);
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{ immediate: false }
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getUserList = async () => {
|
|
|
|
|
|
|
|
const query = {};
|
|
|
|
|
|
|
|
const res = await api.getUserList(query);
|
|
|
|
|
|
|
|
userOptions.value = res.data;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleUserChange = async (newUserId) => {
|
|
|
|
|
|
|
|
const userOption = userOptions.value.find((item) => item.userId == newUserId);
|
|
|
|
|
|
|
|
form.value.requestDeptName = userOption.deptName;
|
|
|
|
|
|
|
|
form.value.requestDept = userOption.deptId;
|
|
|
|
|
|
|
|
form.value.requestByName = userOption.nickName;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getContractPaymentMethods = async (contractId) => {
|
|
|
|
|
|
|
|
const res = await getContractPaymentMethodList(contractId);
|
|
|
|
|
|
|
|
contractPaymentMethodVoList.value = res.data;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const paymentDescription = computed(() => {
|
|
|
|
|
|
|
|
return contractPaymentMethodVoList.value.map((item) => `${item.paymentDescription}`).join('.'); // 使用.连接
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 查询部门下拉树结构 */
|
|
|
|
|
|
|
|
const getDeptTree = async () => {
|
|
|
|
|
|
|
|
const res = await api.deptTreeSelect();
|
|
|
|
|
|
|
|
deptOptions.value = res.data;
|
|
|
|
|
|
|
|
enabledDeptOptions.value = filterDisabledDept(res.data);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 过滤禁用的部门 */
|
|
|
|
|
|
|
|
const filterDisabledDept = (deptList: DeptTreeVO[]) => {
|
|
|
|
|
|
|
|
return deptList.filter((dept) => {
|
|
|
|
|
|
|
|
if (dept.disabled) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dept.children && dept.children.length) {
|
|
|
|
|
|
|
|
dept.children = filterDisabledDept(dept.children);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算合计金额 - 自动更新 issueAmount 和 issuancePercentage
|
|
|
|
|
|
|
|
const totalInvoiceAmount = computed(() => {
|
|
|
|
|
|
|
|
const total = form.value.erpFinInvoiceDetailList.reduce((sum, item) => sum + (item.totalPrice || 0), 0).toFixed(2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新开票金额
|
|
|
|
|
|
|
|
form.value.issueAmount = total;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新开票比例(如果合同金额存在且不为0)
|
|
|
|
|
|
|
|
if (form.value.totalPrice && form.value.totalPrice > 0) {
|
|
|
|
|
|
|
|
form.value.issuancePercentage = Number(((total / form.value.totalPrice) * 100).toFixed(2));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
form.value.issuancePercentage = undefined;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return total;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 监听合同金额变化
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => form.value.totalPrice,
|
|
|
|
|
|
|
|
(newTotalPrice) => {
|
|
|
|
|
|
|
|
// 当合同金额变化时,重新计算开票比例
|
|
|
|
|
|
|
|
if (newTotalPrice && newTotalPrice > 0 && form.value.issueAmount) {
|
|
|
|
|
|
|
|
form.value.issuancePercentage = Number(((form.value.issueAmount / newTotalPrice) * 100).toFixed(2));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
form.value.issuancePercentage = undefined;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
calculateReturnedRate();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 监听累计回款金额变化
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => form.value.returnedMoney,
|
|
|
|
|
|
|
|
(newReturnedMoney) => {
|
|
|
|
|
|
|
|
// 实时计算回款比例
|
|
|
|
|
|
|
|
calculateReturnedRate();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算回款比例
|
|
|
|
|
|
|
|
const calculateReturnedRate = () => {
|
|
|
|
|
|
|
|
if (form.value.totalPrice && form.value.totalPrice > 0 && form.value.returnedMoney) {
|
|
|
|
|
|
|
|
form.value.returnedRate = Number(((form.value.returnedMoney / form.value.totalPrice) * 100).toFixed(2));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
form.value.returnedRate = undefined;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isInitialized = ref(false);
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
|
|
nextTick(async () => {
|
|
|
|
|
|
|
|
getUserList(); // 初始化部门数据
|
|
|
|
|
|
|
|
// 获取路由参数
|
|
|
|
|
|
|
|
routeParams.value = route.query;
|
|
|
|
|
|
|
|
console.log(route.query);
|
|
|
|
|
|
|
|
const id = routeParams.value.id as string | number;
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
proxy?.$modal.loading('正在加载数据,请稍后...');
|
|
|
|
|
|
|
|
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
|
|
|
|
|
|
|
|
const res = await getFinInvoiceInfo(id);
|
|
|
|
|
|
|
|
console.log(res);
|
|
|
|
|
|
|
|
Object.assign(form.value, res.data);
|
|
|
|
|
|
|
|
Object.assign(form.value.erpFinInvoiceDetailList, res.data.erpFinInvoiceDetailVoList);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const res = await getBaseInfo();
|
|
|
|
|
|
|
|
Object.assign(form.value, res.data);
|
|
|
|
|
|
|
|
handleAddItem();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 数据加载完成后,设置初始化标志为 true
|
|
|
|
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
isInitialized.value = true;
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
proxy?.$modal.closeLoading();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// onMounted(() => {
|
|
|
|
|
|
|
|
// const id = route.params?.id
|
|
|
|
|
|
|
|
// if (id) {
|
|
|
|
|
|
|
|
// getDetail(Number(id))
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// // 新增时默认添加一行空明细
|
|
|
|
|
|
|
|
// handleAddItem()
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 项目选择
|
|
|
|
|
|
|
|
const handleSelectProject = () => {
|
|
|
|
|
|
|
|
projectSelectDialogVisible.value = true;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理项目选择
|
|
|
|
|
|
|
|
const handleProjectSelected = (result: any) => {
|
|
|
|
|
|
|
|
const project = result.project;
|
|
|
|
|
|
|
|
Object.assign(form.value, {
|
|
|
|
|
|
|
|
contractId: result.contract?.contractId,
|
|
|
|
|
|
|
|
contractFlag: project.contractFlag,
|
|
|
|
|
|
|
|
projectId: project.projectId,
|
|
|
|
|
|
|
|
projectName: project.projectName,
|
|
|
|
|
|
|
|
projectCode: project.projectCode,
|
|
|
|
|
|
|
|
contractCode: result.contract?.contractCode,
|
|
|
|
|
|
|
|
contractName: result.contract?.contractName,
|
|
|
|
|
|
|
|
customerName: result.contract?.oneCustomerName,
|
|
|
|
|
|
|
|
totalPrice: result.contract?.totalPrice
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if (project.contractFlag === CONTRACT_FLAG.YES && result.contract?.contractId) {
|
|
|
|
|
|
|
|
getContractPaymentMethods(result.contract?.contractId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 合同选择弹窗相关
|
|
|
|
|
|
|
|
const contractSelectDialogVisible = ref(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 显示合同选择弹窗
|
|
|
|
|
|
|
|
const showContractSelectDialog = () => {
|
|
|
|
|
|
|
|
contractSelectDialogVisible.value = true;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 处理合同选择
|
|
|
|
|
|
|
|
const handleContractSelected = (contract: any) => {
|
|
|
|
|
|
|
|
Object.assign(form.value, {
|
|
|
|
|
|
|
|
contractId: contract.contractId,
|
|
|
|
|
|
|
|
contractCode: contract.contractCode,
|
|
|
|
|
|
|
|
contractName: contract.contractName,
|
|
|
|
|
|
|
|
customerName: contract.oneCustomerName,
|
|
|
|
|
|
|
|
totalPrice: contract.totalPrice
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getContractPaymentMethods(contract.contractId);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 部门选择
|
|
|
|
|
|
|
|
const handleSelectDept = () => {
|
|
|
|
|
|
|
|
deptDialogVisible.value = true;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleDeptSelected = () => {
|
|
|
|
|
|
|
|
// form.deptName = '财务部'; // 模拟选择
|
|
|
|
|
|
|
|
// form.deptId = 1;
|
|
|
|
|
|
|
|
deptDialogVisible.value = false;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 人员选择
|
|
|
|
|
|
|
|
const handleSelectUser = () => {
|
|
|
|
|
|
|
|
userDialogVisible.value = true;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleUserSelected = () => {
|
|
|
|
|
|
|
|
// form.userName = '张三'; // 模拟选择
|
|
|
|
|
|
|
|
// form.userId = 1;
|
|
|
|
|
|
|
|
userDialogVisible.value = false;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 表格操作
|
|
|
|
|
|
|
|
const handleAddItem = () => {
|
|
|
|
|
|
|
|
form.value.erpFinInvoiceDetailList.push({
|
|
|
|
|
|
|
|
billingItems: '',
|
|
|
|
|
|
|
|
specificationModel: '',
|
|
|
|
|
|
|
|
unitName: '',
|
|
|
|
|
|
|
|
quantity: undefined,
|
|
|
|
|
|
|
|
taxRate: undefined,
|
|
|
|
|
|
|
|
unitPrice: undefined,
|
|
|
|
|
|
|
|
totalPrice: 0
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleRemoveItem = (index: number, row: FinInvoiceDetailVO) => {
|
|
|
|
|
|
|
|
form.value.erpFinInvoiceDetailList.splice(index, 1);
|
|
|
|
|
|
|
|
if (row.invoiceDetailId) {
|
|
|
|
|
|
|
|
toDeletedInvoiceDetailIdList.value.push(row.invoiceDetailId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleDeleteItems = () => {
|
|
|
|
|
|
|
|
if (selectedItems.value.length === 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const remainingItems = form.value.erpFinInvoiceDetailList.filter((item) => !selectedItems.value.includes(item));
|
|
|
|
|
|
|
|
form.value.erpFinInvoiceDetailList = remainingItems;
|
|
|
|
|
|
|
|
selectedItems.value.forEach((row) => {
|
|
|
|
|
|
|
|
if (row.invoiceDetailId) {
|
|
|
|
|
|
|
|
toDeletedInvoiceDetailIdList.value.push(row.invoiceDetailId);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
selectedItems.value = [];
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleSelectionChange = (selection: FinInvoiceDetailVO[]) => {
|
|
|
|
|
|
|
|
selectedItems.value = selection;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算单个明细的金额
|
|
|
|
|
|
|
|
const calculateItemAmount = (index: number) => {
|
|
|
|
|
|
|
|
const item = form.value.erpFinInvoiceDetailList[index];
|
|
|
|
|
|
|
|
if (item.quantity && item.unitPrice) {
|
|
|
|
|
|
|
|
item.totalPrice = Number((item.quantity * item.unitPrice).toFixed(2));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
item.totalPrice = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 明细变更时触发计算
|
|
|
|
|
|
|
|
const handleItemChange = (index: number) => {
|
|
|
|
|
|
|
|
calculateItemAmount(index);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 审批相关组件引用
|
|
|
|
|
|
|
|
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
|
|
|
|
|
|
|
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 审批记录
|
|
|
|
|
|
|
|
const handleApprovalRecord = () => {
|
|
|
|
|
|
|
|
approvalRecordRef.value.init(form.value.invoiceId);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 提交回调
|
|
|
|
|
|
|
|
const submitCallback = async () => {
|
|
|
|
|
|
|
|
await proxy.$tab.closePage(route);
|
|
|
|
|
|
|
|
router.go(-1);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 审批
|
|
|
|
|
|
|
|
const approvalVerifyOpen = async () => {
|
|
|
|
|
|
|
|
await submitVerifyRef.value.openDialog(routeParams.value.taskId);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 保存
|
|
|
|
|
|
|
|
const handleSave = async (status: string, mode: boolean) => {
|
|
|
|
|
|
|
|
if (!formRef.value) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
|
|
|
await formRef.value.validate(async (valid) => {
|
|
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
|
|
|
if (form.value.erpFinInvoiceDetailList.length === 0) {
|
|
|
|
|
|
|
|
ElMessage.warning('请至少添加一条开票明细');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查明细是否有空项
|
|
|
|
|
|
|
|
const hasEmpty = form.value.erpFinInvoiceDetailList.some(
|
|
|
|
|
|
|
|
(item) => !item.billingItems || !item.unitName || !item.taxRate || item.quantity <= 0 || item.unitPrice <= 0
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hasEmpty) {
|
|
|
|
|
|
|
|
ElMessage.warning('请填写完整的开票明细信息');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 验证累计回款金额不能大于合同金额
|
|
|
|
|
|
|
|
if (form.value.returnedMoney && form.value.totalPrice && form.value.returnedMoney > form.value.totalPrice) {
|
|
|
|
|
|
|
|
ElMessage.warning('累计回款金额不能大于合同金额');
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (form.value.earlyFlag === EARLY_FLAG.YES) {
|
|
|
|
|
|
|
|
form.value.acceptanceDate = undefined;
|
|
|
|
|
|
|
|
form.value.deliveryDate = undefined;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
form.value.earlyReason = undefined;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
form.value.invoiceStatus = getInvoiceStatus(status);
|
|
|
|
|
|
|
|
form.value.flowStatus = getFlowStatus(status);
|
|
|
|
|
|
|
|
// 调用保存接口
|
|
|
|
|
|
|
|
if (form.value.invoiceId) {
|
|
|
|
|
|
|
|
form.value.toDeletedInvoiceDetailIdList = toDeletedInvoiceDetailIdList.value;
|
|
|
|
|
|
|
|
await updateFinInvoiceInfo(form.value);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
await addFinInvoiceInfo(form.value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ElMessage.success('保存成功');
|
|
|
|
|
|
|
|
// 返回列表页
|
|
|
|
|
|
|
|
goBack();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getInvoiceStatus = (status: string): string => {
|
|
|
|
|
|
|
|
return status === 'draft' ? BUSINESS_STATUS.DRAFT : BUSINESS_STATUS.WAITING;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getFlowStatus = (status: string): string => {
|
|
|
|
|
|
|
|
return status === 'draft' ? 'draft' : 'waiting';
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const goBack = () => {
|
|
|
|
|
|
|
|
const obj = {
|
|
|
|
|
|
|
|
path: '/fin/finInvoiceInfo',
|
|
|
|
|
|
|
|
query: {
|
|
|
|
|
|
|
|
t: Date.now(),
|
|
|
|
|
|
|
|
pageNum: routeParams.value.pageNum
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
proxy?.$tab.closeOpenPage(obj);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 取消返回
|
|
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
|
|
|
router.push('/oa/erp/finInvoiceInfo');
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
</script>
|