feat(finance): 新增付款单附件功能并优化表格显示

- 在新增付款单表单中添加附件上传组件
- 修改表格样式设置避免滚动条冲突
- 移除表格固定高度限制提升用户体验
- 在付款单详情页面显示附件信息
- 添加付款单删除功能支持预付款单删除
- 付款单编号列添加链接跳转至详情页
- 后端实体类和数据库映射增加文件ID字段
- 实现附件查询服务关联付款单数据
- 货币金额显示格式化为货币格式
- 文件上传组件集成到付款单流程中
dev_1.0.0
chenhao 2026-01-29 17:14:42 +08:00
parent a56d750f2d
commit 45f69d527e
8 changed files with 105 additions and 20 deletions

View File

@ -111,6 +111,14 @@ export function applyRefund(id) {
needLoading: true needLoading: true
}) })
} }
export function deletePayment(id) {
return request({
url: '/finance/payment/remove',
method: 'post',
params:{ids:id},
needLoading: true
})
}
export function applyRefundApprove(id) { export function applyRefundApprove(id) {
return request({ return request({

View File

@ -417,7 +417,7 @@ export default {
return prev; return prev;
} }
}, 0); }, 0);
sums[index] = sums[index].toFixed(2); sums[index] = this.formatCurrency(sums[index]);
} else { } else {
sums[index] = 'N/A'; sums[index] = 'N/A';
} }

View File

@ -1,7 +1,8 @@
<template> <template>
<el-dialog title="新增付款单" :visible.sync="internalVisible" width="1200px" @close="handleClose" <el-dialog title="新增付款单" :visible.sync="internalVisible" width="1200px" @close="handleClose"
:close-on-click-modal="false" append-to-body> :close-on-click-modal="false" append-to-body>
<el-form ref="form" :model="form" :rules="rules" style="max-height: 70vh" label-width="120px"> <div style="max-height: 70vh;overflow: auto">
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="制造商名称" prop="vendorCode"> <el-form-item label="制造商名称" prop="vendorCode">
@ -53,6 +54,12 @@
style="width: 100%"></el-input> style="width: 100%"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<el-form-item label="附件" prop="fileId">
<file-upload :value="fileList" @file-list-changed="handleFileListChanged" :limit="1"
:file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf']"/>
</el-form-item>
</el-col>
</el-row> </el-row>
<!-- Tables --> <!-- Tables -->
<div v-if="form.vendorCode"> <div v-if="form.vendorCode">
@ -64,7 +71,6 @@
border border
style="width: 100%" style="width: 100%"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
max-height="300"
row-key="id" row-key="id"
show-summary show-summary
:summary-method="getPayableSummary" :summary-method="getPayableSummary"
@ -133,7 +139,7 @@
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
@select="handleSelect" @select="handleSelect"
@select-all="handleSelectAll" @select-all="handleSelectAll"
max-height="300"
row-key="id" row-key="id"
> >
<el-table-column type="selection" width="55" reserve-selection></el-table-column> <el-table-column type="selection" width="55" reserve-selection></el-table-column>
@ -160,6 +166,7 @@
请先选择制造商 请先选择制造商
</div> </div>
</el-form> </el-form>
</div>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<!-- <div v-if="form.paymentBillType === 'FROM_PAYABLE'" style="float: left; line-height: 36px;">--> <!-- <div v-if="form.paymentBillType === 'FROM_PAYABLE'" style="float: left; line-height: 36px;">-->
<!-- <span style="margin-right: 20px;">计划付款总金额: <el-tag type="success">{{--> <!-- <span style="margin-right: 20px;">计划付款总金额: <el-tag type="success">{{-->
@ -192,10 +199,11 @@
import {listAllVendor} from "@/api/base/vendor"; import {listAllVendor} from "@/api/base/vendor";
import {listPayableBills, listOrders} from "@/api/finance/payment"; import {listPayableBills, listOrders} from "@/api/finance/payment";
import PaymentPlanSelector from "../../payable/components/PaymentPlan"; import PaymentPlanSelector from "../../payable/components/PaymentPlan";
import FileUpload from "@/components/FileUpload";
export default { export default {
name: "AddForm", name: "AddForm",
components: {PaymentPlanSelector}, components: {PaymentPlanSelector, FileUpload},
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
@ -221,7 +229,8 @@ export default {
vendorName: null, vendorName: null,
remark: null, remark: null,
totalPriceWithTax: 0, totalPriceWithTax: 0,
estimatedPaymentTime: null estimatedPaymentTime: null,
fileId: null
}, },
rules: { rules: {
vendorCode: [{required: true, message: "制造商名称不能为空", trigger: "change"}], vendorCode: [{required: true, message: "制造商名称不能为空", trigger: "change"}],
@ -234,6 +243,7 @@ export default {
isPaymentPlanSelectorOpen: false, isPaymentPlanSelectorOpen: false,
choosePayable: {}, choosePayable: {},
currentPayableOrderIndexForPlan: -1, currentPayableOrderIndexForPlan: -1,
fileList: [],
}; };
}, },
computed: { computed: {
@ -287,6 +297,10 @@ export default {
this.selectedRows = []; this.selectedRows = [];
this.loadTableData(); this.loadTableData();
}, },
handleFileListChanged(fileList) {
this.fileList = fileList;
this.form.fileId = this.fileList.map(f => f.id).filter(id => !!id).join(',')
},
loadTableData() { loadTableData() {
if (!this.form.vendorCode) return; if (!this.form.vendorCode) return;
@ -460,7 +474,8 @@ export default {
vendorName: this.form.vendorName, vendorName: this.form.vendorName,
remark: this.form.remark, remark: this.form.remark,
payableOrders: processedPayableOrders, payableOrders: processedPayableOrders,
totalMergePaymentAmount: this.totalPlannedAmount totalMergePaymentAmount: this.totalPlannedAmount,
fileId: this.form.fileId
}; };
this.$emit("submit", submitData); this.$emit("submit", submitData);
@ -484,7 +499,8 @@ export default {
projectName:order.projectName, projectName:order.projectName,
remark: this.form.remark, remark: this.form.remark,
paymentTime: this.form.estimatedPaymentTime, paymentTime: this.form.estimatedPaymentTime,
totalPriceWithTax:this.form.totalPriceWithTax totalPriceWithTax:this.form.totalPriceWithTax,
fileId: this.form.fileId
}; };
this.$emit("submit", submitData); this.$emit("submit", submitData);

View File

@ -92,6 +92,12 @@
<el-col :span="24"> <el-col :span="24">
<div class="detail-item">其它特别说明: {{ detail.remark }}</div> <div class="detail-item">其它特别说明: {{ detail.remark }}</div>
</el-col> </el-col>
<el-col :span="24">
<div class="detail-item">
<span style="margin-right: 10px">附件:</span>
<file-upload :value="detail.fileList" :disabled="true" :show-remove="false" :show-upload-btn="false"/>
</div>
</el-col>
</el-row> </el-row>
</div> </div>
</div> </div>
@ -121,8 +127,11 @@
</template> </template>
<script> <script>
import FileUpload from "@/components/FileUpload";
export default { export default {
name: "DetailDrawer", name: "DetailDrawer",
components: {FileUpload},
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,

View File

@ -149,7 +149,11 @@
</el-row> </el-row>
<el-table v-loading="loading" :data="paymentList" show-summary :summary-method="getSummaries"> <el-table v-loading="loading" :data="paymentList" show-summary :summary-method="getSummaries">
<el-table-column label="采购-付款单编号" width="200" align="center" prop="paymentBillCode"/> <el-table-column label="采购-付款单编号" width="200" align="center" prop="paymentBillCode">
<template slot-scope="scope">
<a @click="handleDetail(scope.row)" class="link-type">{{ scope.row.paymentBillCode }}</a>
</template>
</el-table-column>
<el-table-column label="预计付款时间" align="center" prop="paymentTime" width="180"> <el-table-column label="预计付款时间" align="center" prop="paymentTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.paymentTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> <span>{{ parseTime(scope.row.paymentTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@ -215,13 +219,7 @@
v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && (scope.row.paymentBillType==='FROM_PAYABLE'||scope.row.paymentBillType==='PRE_PAYMENT')" v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && (scope.row.paymentBillType==='FROM_PAYABLE'||scope.row.paymentBillType==='PRE_PAYMENT')"
@click="applyPayment(scope.row)" @click="applyPayment(scope.row)"
>申请付款</el-button> >申请付款</el-button>
<!-- <el-button-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-position"-->
<!-- v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && scope.row.paymentBillType==='REFUND' "-->
<!-- @click="applyRefundApprove(scope.row)"-->
<!-- >发起退款</el-button>-->
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
@ -243,6 +241,15 @@
v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.paymentStatus==='1'||scope.row.paymentStatus==='3')" v-if="(scope.row.approveStatus === '2' || scope.row.approveStatus==='3') && (scope.row.paymentStatus==='1'||scope.row.paymentStatus==='3')"
@click="handleRevoke(scope.row)" @click="handleRevoke(scope.row)"
>撤销</el-button> >撤销</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
v-hasPermi="['finance:payment:remove']"
v-show="(scope.row.approveStatus==='0' || scope.row.approveStatus==='3') && scope.row.paymentBillType==='PRE_PAYMENT' && scope.row.paymentStatus === '1' "
@click="handleDelete(scope.row.id)"
>删除
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -309,7 +316,7 @@ import {
applyRefund, applyRefund,
addPayment, addPayment,
handleRevoke, handleRevoke,
exportPayment exportPayment, deletePayment
} from "@/api/finance/payment"; } from "@/api/finance/payment";
import { addDateRange } from "@/utils/ruoyi"; import { addDateRange } from "@/utils/ruoyi";
import DetailDrawer from "./components/DetailDrawer.vue"; import DetailDrawer from "./components/DetailDrawer.vue";
@ -497,6 +504,14 @@ export default {
this.$modal.msgSuccess("申请退款成功"); this.$modal.msgSuccess("申请退款成功");
}).catch(() => {}); }).catch(() => {});
}, },
handleDelete(id){
this.$modal.confirm('确认删除该笔预付单数据吗?').then(() => {
return deletePayment(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
handleRevoke(row) { handleRevoke(row) {
let msg=row.paymentBillType==='REFUND'?'是否将该笔采购-退款单撤销,将退款单撤销至付款单':'是否将该笔采购-付款单撤销,撤销至付款单未审批状态'; let msg=row.paymentBillType==='REFUND'?'是否将该笔采购-退款单撤销,将退款单撤销至付款单':'是否将该笔采购-付款单撤销,撤销至付款单未审批状态';
this.$modal.confirm(msg).then(() => { this.$modal.confirm(msg).then(() => {
@ -525,7 +540,7 @@ export default {
return prev; return prev;
} }
}, 0); }, 0);
sums[index] = sums[index].toFixed(2); sums[index] = this.formatCurrency(sums[index]);
} else { } else {
sums[index] = 'N/A'; sums[index] = 'N/A';
} }

View File

@ -145,6 +145,12 @@ public class OmsPaymentBill extends BaseEntity
private BigDecimal writeOffAmountWithoutTax; private BigDecimal writeOffAmountWithoutTax;
private BigDecimal writeOffTaxAmount; private BigDecimal writeOffTaxAmount;
/** 附件ID多个以逗号分隔 */
private String fileId;
/** 附件列表 */
private List<OmsFileLog> fileList;
@Getter @Getter
public enum PaymentBillTypeEnum { public enum PaymentBillTypeEnum {

View File

@ -69,6 +69,8 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
protected ManagementService managementService; protected ManagementService managementService;
@Autowired @Autowired
private IOmsPayableWriteOffService writeOffService; private IOmsPayableWriteOffService writeOffService;
@Autowired
private IOmsFileLogService omsFileLogService;
/** /**
* *
* *
@ -78,7 +80,20 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
@Override @Override
public OmsPaymentBill selectOmsPaymentBillById(Long id) public OmsPaymentBill selectOmsPaymentBillById(Long id)
{ {
return omsPaymentBillMapper.selectOmsPaymentBillById(id); OmsPaymentBill omsPaymentBill = omsPaymentBillMapper.selectOmsPaymentBillById(id);
if (omsPaymentBill != null && StrUtil.isNotEmpty(omsPaymentBill.getFileId())) {
List<Integer> idList = StrUtil.split(omsPaymentBill.getFileId(), ',')
.stream()
.map(Integer::valueOf)
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(idList)) {
OmsFileLog query = new OmsFileLog();
query.setIdList(idList);
List<OmsFileLog> fileList = omsFileLogService.queryAll(query);
omsPaymentBill.setFileList(fileList);
}
}
return omsPaymentBill;
} }
/** /**
@ -186,6 +201,18 @@ public class OmsPaymentBillServiceImpl implements IOmsPaymentBillService , TodoC
@Override @Override
public PaymentBillDetailDTO query(Long id) { public PaymentBillDetailDTO query(Long id) {
PaymentBillDetailDTO paymentBillDetailDTO = omsPaymentBillMapper.selectPaymentBillDetail(id); PaymentBillDetailDTO paymentBillDetailDTO = omsPaymentBillMapper.selectPaymentBillDetail(id);
if (paymentBillDetailDTO != null && StrUtil.isNotEmpty(paymentBillDetailDTO.getFileId())) {
List<Integer> idList = StrUtil.split(paymentBillDetailDTO.getFileId(), ',')
.stream()
.map(Integer::valueOf)
.collect(Collectors.toList());
if (CollUtil.isNotEmpty(idList)) {
OmsFileLog query = new OmsFileLog();
query.setIdList(idList);
List<OmsFileLog> fileList = omsFileLogService.queryAll(query);
paymentBillDetailDTO.setFileList(fileList);
}
}
List<PaymentBillPayableDetailDTO> paymentBillPayableDetailDTOS = detailService.listPayableByPaymentCode(paymentBillDetailDTO.getPaymentBillCode()); List<PaymentBillPayableDetailDTO> paymentBillPayableDetailDTOS = detailService.listPayableByPaymentCode(paymentBillDetailDTO.getPaymentBillCode());
paymentBillDetailDTO.setPayableDetails(paymentBillPayableDetailDTOS); paymentBillDetailDTO.setPayableDetails(paymentBillPayableDetailDTOS);
return paymentBillDetailDTO; return paymentBillDetailDTO;

View File

@ -34,6 +34,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="payBankNumber" column="pay_bank_number" /> <result property="payBankNumber" column="pay_bank_number" />
<result property="payBankOpenAddress" column="pay_bank_open_address" /> <result property="payBankOpenAddress" column="pay_bank_open_address" />
<result property="bankNumber" column="bank_number" /> <result property="bankNumber" column="bank_number" />
<result property="fileId" column="file_id" />
<result property="refundStatus" column="refund_status" /> <result property="refundStatus" column="refund_status" />
</resultMap> </resultMap>
@ -101,7 +102,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
pb.pay_bank_number, pb.pay_bank_number,
pb.pay_bank_open_address, pb.pay_bank_open_address,
pb.bank_number, pb.bank_number,
pb.file_id,
pb.refund_status, pb.refund_status,
ovi.vendor_name, ovi.vendor_name,
ovi.pay_type, ovi.pay_type,
@ -270,6 +271,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payBankNumber != null">pay_bank_number,</if> <if test="payBankNumber != null">pay_bank_number,</if>
<if test="payBankOpenAddress != null">pay_bank_open_address,</if> <if test="payBankOpenAddress != null">pay_bank_open_address,</if>
<if test="bankNumber != null">bank_number,</if> <if test="bankNumber != null">bank_number,</if>
<if test="fileId != null">file_id,</if>
<if test="refundStatus != null">refund_status,</if> <if test="refundStatus != null">refund_status,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
@ -300,6 +302,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payBankNumber != null">#{payBankNumber},</if> <if test="payBankNumber != null">#{payBankNumber},</if>
<if test="payBankOpenAddress != null">#{payBankOpenAddress},</if> <if test="payBankOpenAddress != null">#{payBankOpenAddress},</if>
<if test="bankNumber != null">#{bankNumber},</if> <if test="bankNumber != null">#{bankNumber},</if>
<if test="fileId != null">#{fileId},</if>
<if test="refundStatus != null">#{refundStatus},</if> <if test="refundStatus != null">#{refundStatus},</if>
</trim> </trim>
</insert> </insert>
@ -334,6 +337,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="payBankNumber != null">pay_bank_number = #{payBankNumber},</if> <if test="payBankNumber != null">pay_bank_number = #{payBankNumber},</if>
<if test="payBankOpenAddress != null">pay_bank_open_address = #{payBankOpenAddress},</if> <if test="payBankOpenAddress != null">pay_bank_open_address = #{payBankOpenAddress},</if>
<if test="bankNumber != null">bank_number = #{bankNumber},</if> <if test="bankNumber != null">bank_number = #{bankNumber},</if>
<if test="fileId != null">file_id = #{fileId},</if>
<if test="refundStatus != null">refund_status = #{refundStatus},</if> <if test="refundStatus != null">refund_status = #{refundStatus},</if>
</trim> </trim>