feat(purchaseorder): 添加采购单导出功能并优化界面显示

- 在后端控制器中实现export方法返回AjaxResult并设置审批状态过滤
- 添加exportPurchaseorder API函数用于导出采购订单数据
- 在前端界面添加导出按钮及权限控制
- 修改下载插件中的方法名为download替代name
- 修复多个选择组件中的表单提交阻止默认行为
- 优化采购单详情对话框和抽屉组件的属性格式化
- 隐藏采购订单实体类中部分字段的Excel导出注解
- 修正审批时间Excel导出的时间格式化设置
- 更新多个select组件中的键盘事件处理方式
dev_1.0.0
chenhao 2026-01-26 14:20:27 +08:00
parent dd2a7d99b6
commit baa4b52553
17 changed files with 76 additions and 37 deletions

View File

@ -106,6 +106,16 @@ export function recallPurchaseorder(id) {
method: 'put' method: 'put'
}) })
} }
export function exportPurchaseorder(data) {
return request({
url: '/sip/purchaseorder/export',
method: 'get',
params: data,
// headers: { 'Content-Type': 'multipart/form-data' },
needLoading: true
})
}
// 查询已审批采购单主表列表 // 查询已审批采购单主表列表
export function listApprovedPurchaseorder(query) { export function listApprovedPurchaseorder(query) {

View File

@ -9,13 +9,12 @@ const baseURL = process.env.VUE_APP_BASE_API
let downloadLoadingInstance let downloadLoadingInstance
export default { export default {
name(name, isDelete = true) { download(name, isDelete = true) {
var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
axios({ axios({
method: 'get', method: 'get',
url: url, url: url,
responseType: 'blob', responseType: 'blob',
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then((res) => { }).then((res) => {
const isBlob = blobValidate(res.data) const isBlob = blobValidate(res.data)
if (isBlob) { if (isBlob) {

View File

@ -1,6 +1,6 @@
<template> <template>
<el-dialog title="选择合同" :visible.sync="visible" width="800px" append-to-body @close="cancel"> <el-dialog title="选择合同" :visible.sync="visible" width="800px" append-to-body @close="cancel">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px"> <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px" @submit.native.prevent>
<el-form-item label="合同编号" prop="orderCode"> <el-form-item label="合同编号" prop="orderCode">
<el-input <el-input
v-model="queryParams.orderCode" v-model="queryParams.orderCode"

View File

@ -1,6 +1,6 @@
<template> <template>
<el-dialog title="选择项目" :visible.sync="internalVisible" width="800px" height="600px" append-to-body @close="handleClose"> <el-dialog title="选择项目" :visible.sync="internalVisible" width="800px" height="600px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="100px"> <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="100px" @submit.native.prevent>
<el-form-item label="项目编号" prop="projectCode"> <el-form-item label="项目编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable size="small" @keyup.enter.native="handleQuery"/> <el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable size="small" @keyup.enter.native="handleQuery"/>
</el-form-item> </el-form-item>

View File

@ -81,6 +81,17 @@
>新增 >新增
</el-button> </el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['sip:purchaseorder:export']"
>导出
</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
@ -189,7 +200,7 @@
/> />
<!-- 添加或修改采购单主表对话框 --> <!-- 添加或修改采购单主表对话框 -->
<el-dialog :title="title" :close-on-click-modal="false" :visible.sync="open" width="80vw" append-to-body > <el-dialog :title="title" :close-on-click-modal="false" :visible.sync="open" width="80vw" append-to-body>
<purchase-order-detail ref="purchaseOrderDetail" :order-data="currentOrderData" <purchase-order-detail ref="purchaseOrderDetail" :order-data="currentOrderData"
@close="open = false" @close="open = false"
@success="getList"> @success="getList">
@ -231,10 +242,10 @@
direction="rtl" direction="rtl"
size="80%" size="80%"
> >
<ApproveLayout title="采购单详情" v-if="showDetailDrawer"> <ApproveLayout title="采购单详情" v-if="showDetailDrawer">
<purchase-order-detail-view ref="detailViewOnly" :order-data="detailOrderData" @close="showDetailDrawer = false" <purchase-order-detail-view ref="detailViewOnly" :order-data="detailOrderData" @close="showDetailDrawer = false"
@success="getList" :showHistory="true" @success="getList" :showHistory="true"
@view-history-detail="handleViewHistoryDetailEvent"> @view-history-detail="handleViewHistoryDetailEvent">
</purchase-order-detail-view> </purchase-order-detail-view>
<template #footer> <template #footer>
<span>订单编号: {{ currentDetailPurchaseNo }}</span> <span>订单编号: {{ currentDetailPurchaseNo }}</span>
@ -249,8 +260,9 @@
direction="rtl" direction="rtl"
size="80%" size="80%"
> >
<ApproveLayout title="采购单历史详情" v-if="showHistoryDetailDrawer"> <ApproveLayout title="采购单历史详情" v-if="showHistoryDetailDrawer">
<purchase-order-detail-view ref="historyDetailView" :order-data="historyDetailOrderData" @close="showHistoryDetailDrawer = false"> <purchase-order-detail-view ref="historyDetailView" :order-data="historyDetailOrderData"
@close="showHistoryDetailDrawer = false">
</purchase-order-detail-view> </purchase-order-detail-view>
<template #footer> <template #footer>
<span>订单编号: {{ historyDetailOrderData ? historyDetailOrderData.purchaseNo : '' }}</span> <span>订单编号: {{ historyDetailOrderData ? historyDetailOrderData.purchaseNo : '' }}</span>
@ -272,11 +284,12 @@ import {
getPurchaseOrderHistory, getPurchaseOrderHistory,
getPurchaseOrderHistoryDetail, getPurchaseOrderHistoryDetail,
recallPurchaseorder, recallPurchaseorder,
vendorConfirmStatus // vendorConfirmStatus, exportPurchaseorder //
} from "@/api/sip/purchaseorder"; } from "@/api/sip/purchaseorder";
import PurchaseOrderDetail from './components/PurchaseOrderDetail'; import PurchaseOrderDetail from './components/PurchaseOrderDetail';
import ApproveLayout from "@/views/approve/ApproveLayout.vue"; import ApproveLayout from "@/views/approve/ApproveLayout.vue";
import PurchaseOrderDetailView from "@/views/purchaseorder/components/PurchaseOrderDetailView.vue"; import PurchaseOrderDetailView from "@/views/purchaseorder/components/PurchaseOrderDetailView.vue";
import {blobValidate} from "@/utils/ruoyi";
export default { export default {
name: "Purchaseorder", name: "Purchaseorder",
@ -333,7 +346,7 @@ export default {
approveStatus: null, approveStatus: null,
confirmStatus: null, confirmStatus: null,
status: null, status: null,
orderByColumn:'createTime', orderByColumn: 'createTime',
isAsc: 'desc' isAsc: 'desc'
}, },
// //
@ -346,7 +359,7 @@ export default {
console.log(this.$route.query) console.log(this.$route.query)
this.getList(); this.getList();
}, },
watch:{ watch: {
// //
open(val) { open(val) {
if (!val) { if (!val) {
@ -415,6 +428,13 @@ export default {
this.open = true; this.open = true;
this.title = "添加采购单主表"; this.title = "添加采购单主表";
}, },
handleExport() {
this.$modal.confirm('是否确认导出已审批的采购数据项?').then(() => {
return exportPurchaseorder(this.queryParams);
}).then(response => {
this.$download.download( response.msg)
})
},
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
getPurchaseorder(row.id).then(response => { getPurchaseorder(row.id).then(response => {
@ -423,11 +443,13 @@ export default {
this.open = true; this.open = true;
this.title = "修改采购单主表"; this.title = "修改采购单主表";
}); });
}, }
,
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
this.$refs.purchaseOrderDetail.submitForm() this.$refs.purchaseOrderDetail.submitForm()
}, }
,
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ids = row.id || this.ids; const ids = row.id || this.ids;
@ -438,13 +460,15 @@ export default {
this.$modal.msgSuccess("删除成功"); this.$modal.msgSuccess("删除成功");
}).catch(() => { }).catch(() => {
}); });
}, }
,
/** 申请采购按钮操作 */ /** 申请采购按钮操作 */
handleApply(row) { handleApply(row) {
this.currentApplyingOrder = row; // this.currentApplyingOrder = row; //
this.selectedFlowType = null; // this.selectedFlowType = null; //
this.openFlowTypeDialog = true; // this.openFlowTypeDialog = true; //
}, }
,
/** 查看详情按钮操作 */ /** 查看详情按钮操作 */
handleViewDetails(row) { handleViewDetails(row) {
getPurchaseorder(row.id).then(response => { getPurchaseorder(row.id).then(response => {
@ -452,7 +476,8 @@ export default {
this.currentDetailPurchaseNo = row.purchaseNo; this.currentDetailPurchaseNo = row.purchaseNo;
this.showDetailDrawer = true; this.showDetailDrawer = true;
}); });
}, }
,
/** 处理查看历史详情事件 */ /** 处理查看历史详情事件 */
handleViewHistoryDetailEvent(row) { handleViewHistoryDetailEvent(row) {
getPurchaseOrderHistoryDetail(row.id).then(response => { getPurchaseOrderHistoryDetail(row.id).then(response => {
@ -460,7 +485,8 @@ export default {
this.showHistoryDetailDrawer = true; this.showHistoryDetailDrawer = true;
this.showDetailDrawer = false; // this.showDetailDrawer = false; //
}); });
}, }
,
/** 提交申请采购(带流程类型) */ /** 提交申请采购(带流程类型) */
submitApplyWithFlowType() { submitApplyWithFlowType() {
this.$refs.flowTypeForm.validate(valid => { this.$refs.flowTypeForm.validate(valid => {
@ -477,7 +503,8 @@ export default {
}); });
} }
}); });
}, }
,
/** 撤回按钮操作 */ /** 撤回按钮操作 */
handleRecall(row) { handleRecall(row) {
this.$modal.confirm('是否确认撤回采购订单编号为"' + row.purchaseNo + '"的数据项?').then(() => { this.$modal.confirm('是否确认撤回采购订单编号为"' + row.purchaseNo + '"的数据项?').then(() => {
@ -488,7 +515,8 @@ export default {
this.getList(); // this.getList(); //
}).catch(() => { }).catch(() => {
}); });
}, }
,
/** 发起供应商确认操作 */ /** 发起供应商确认操作 */
handleInitiateVendorConfirmation(row) { handleInitiateVendorConfirmation(row) {
this.$modal.confirm('是否确认发起供应商确认编号为"' + row.purchaseNo + '"的数据项?', '警告', { this.$modal.confirm('是否确认发起供应商确认编号为"' + row.purchaseNo + '"的数据项?', '警告', {

View File

@ -391,7 +391,7 @@ export default {
this.$modal.confirm('是否确认导出所有办事处信息数据项?').then(() => { this.$modal.confirm('是否确认导出所有办事处信息数据项?').then(() => {
return exportAgent(this.queryParams); return exportAgent(this.queryParams);
}).then(response => { }).then(response => {
this.$download.name(response.msg); this.$download.download(response.msg);
}).catch(() => {}); }).catch(() => {});
} }
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<el-dialog title="选择代表处" :visible.sync="visible" :close-on-click-modal="false" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择代表处" :visible.sync="visible" :close-on-click-modal="false" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" @submit.native.prevent>
<el-form-item label="代表处名称" prop="agentName"> <el-form-item label="代表处名称" prop="agentName">
<el-input <el-input
v-model="queryParams.agentName" v-model="queryParams.agentName"

View File

@ -491,7 +491,7 @@ export default {
this.$modal.confirm('是否确认导出所有客户信息数据项?').then(() => { this.$modal.confirm('是否确认导出所有客户信息数据项?').then(() => {
return exportCustomer(this.queryParams); return exportCustomer(this.queryParams);
}).then(response => { }).then(response => {
this.$download.name(response.msg); this.$download.download(response.msg);
}).catch(() => {}); }).catch(() => {});
} }
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<el-dialog title="选择客户" :close-on-click-modal="false" :visible.sync="visible" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择客户" :close-on-click-modal="false" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" @submit.native.prevent>
<el-form-item label="客户名称" prop="customerName"> <el-form-item label="客户名称" prop="customerName">
<el-input <el-input
v-model="queryParams.customerName" v-model="queryParams.customerName"

View File

@ -514,7 +514,7 @@ export default {
this.$modal.confirm('是否确认导出所有代理商管理数据项?').then(() => { this.$modal.confirm('是否确认导出所有代理商管理数据项?').then(() => {
return exportPartner(this.queryParams); return exportPartner(this.queryParams);
}).then(response => { }).then(response => {
this.$download.name(response.msg); this.$download.download(response.msg);
}).catch(() => {}); }).catch(() => {});
}, },
/** 打开选择用户对话框 */ /** 打开选择用户对话框 */

View File

@ -1,12 +1,12 @@
<template> <template>
<el-dialog title="选择进货商" :close-on-click-modal="false" :visible.sync="visible" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择进货商" :close-on-click-modal="false" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" @submit.native.prevent>
<el-form-item label="进货商名称" prop="partnerName"> <el-form-item label="进货商名称" prop="partnerName">
<el-input <el-input
v-model="queryParams.partnerName" v-model="queryParams.partnerName"
placeholder="请输入进货商名称" placeholder="请输入进货商名称"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native.prevent="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>

View File

@ -1,7 +1,7 @@
<template> <template>
<el-dialog title="选择产品" :close-on-click-modal="false" :visible.sync="visible" width="60%" append-to-body @close="handleClose"> <el-dialog title="选择产品" :close-on-click-modal="false" :visible.sync="visible" width="60%" append-to-body @close="handleClose">
<div style="max-height: 60vh; overflow-y: auto;"> <div style="max-height: 60vh; overflow-y: auto;">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" @submit.native.prevent>
<el-form-item label="产品编码" prop="productCode"> <el-form-item label="产品编码" prop="productCode">
<el-input <el-input
v-model="queryParams.productCode" v-model="queryParams.productCode"

View File

@ -1,7 +1,7 @@
<template> <template>
<!-- 授权用户 --> <!-- 授权用户 -->
<el-dialog title="选择用户" :visible.sync="visible" width="800px" top="5vh" append-to-body> <el-dialog title="选择用户" :visible.sync="visible" width="800px" top="5vh" append-to-body>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" @submit.native.prevent>
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input <el-input
v-model="queryParams.userName" v-model="queryParams.userName"

View File

@ -1,6 +1,6 @@
<template> <template>
<el-dialog title="选择用户" :visible.sync="visible" width="800px" append-to-body @close="handleClose"> <el-dialog title="选择用户" :visible.sync="visible" width="800px" append-to-body @close="handleClose">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" @submit.native.prevent>
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input <el-input
v-model="queryParams.userName" v-model="queryParams.userName"

View File

@ -62,6 +62,7 @@ public class CommonController
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName); FileUtils.setAttachmentResponseHeader(response, realFileName);
response.setHeader("download-filename", FileUtils.percentEncode(realFileName));
FileUtils.writeBytes(filePath, response.getOutputStream()); FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete) if (delete)
{ {

View File

@ -140,12 +140,13 @@ public class OmsPurchaseOrderController extends BaseController
// @RequiresPermissions("sip:purchaseorder:export") // @RequiresPermissions("sip:purchaseorder:export")
@Anonymous @Anonymous
@GetMapping("/export") @GetMapping("/export")
public void export(OmsPurchaseOrder omsPurchaseOrder, HttpServletResponse response) public AjaxResult export(OmsPurchaseOrder omsPurchaseOrder, HttpServletResponse response)
{ {
omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
List<OmsPurchaseOrder> list = omsPurchaseOrderService.selectOmsPurchaseOrderList(omsPurchaseOrder); List<OmsPurchaseOrder> list = omsPurchaseOrderService.selectOmsPurchaseOrderList(omsPurchaseOrder);
todoService.fillPurchaseOrderApproveNode(list); todoService.fillPurchaseOrderApproveNode(list);
ExcelUtil<OmsPurchaseOrder> util = new ExcelUtil<OmsPurchaseOrder>(OmsPurchaseOrder.class); ExcelUtil<OmsPurchaseOrder> util = new ExcelUtil<OmsPurchaseOrder>(OmsPurchaseOrder.class);
util.exportExcel(response, list, "采购单主表数据"); return util.exportExcel( list, "采购单主表数据");
} }
/** /**

View File

@ -40,7 +40,7 @@ public class OmsPurchaseOrder extends BaseEntity
private String buyerAddress; private String buyerAddress;
/** 制造商ID */ /** 制造商ID */
@Excel(name = "制造商ID") // @Excel(name = "制造商ID")
private Long vendorId; private Long vendorId;
private String vendorCode; private String vendorCode;
private List<String> authVendorCodeList; private List<String> authVendorCodeList;
@ -55,7 +55,7 @@ public class OmsPurchaseOrder extends BaseEntity
private String currency; private String currency;
/** 采购员ID */ /** 采购员ID */
@Excel(name = "采购员ID") // @Excel(name = "采购员ID")
private Long purchaserId; private Long purchaserId;
@ -81,7 +81,7 @@ public class OmsPurchaseOrder extends BaseEntity
private String payMethod; private String payMethod;
/** 汇智负责人ID */ /** 汇智负责人ID */
@Excel(name = "汇智负责人ID") // @Excel(name = "汇智负责人ID")
private Long ownerId; private Long ownerId;
/** 汇智负责人姓名 */ /** 汇智负责人姓名 */
@ -101,7 +101,7 @@ public class OmsPurchaseOrder extends BaseEntity
private String approveStatus; private String approveStatus;
/** 审批时间 */ /** 审批时间 */
@Excel(name = "审批时间") @Excel(name = "审批时间", dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date approveTime; private Date approveTime;
/** 当前审批节点 */ /** 当前审批节点 */