feat(@vben/web-antd): erp-优化上传附件及验证

- 修改订单时间格式为 timestamp
- 限制文件上传数量为 1
- 调整表格列宽和显示逻辑
- 优化子表单验证和提交逻辑
- 修复文件上传组件的兼容性问题
- 优化产品清单的初始化和验证
pull/181/head
nehc 2025-07-26 17:36:59 +08:00
parent 8a7239ce24
commit f242f1c37d
3 changed files with 138 additions and 31 deletions

View File

@ -44,7 +44,7 @@ export function useFormSchema(): VbenFormSchema[] {
placeholder: '选择订单时间', placeholder: '选择订单时间',
showTime: true, showTime: true,
format: 'YYYY-MM-DD HH:mm:ss', format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'x',
style: { width: '100%' }, style: { width: '100%' },
}, },
fieldName: 'orderTime', fieldName: 'orderTime',
@ -65,7 +65,7 @@ export function useFormSchema(): VbenFormSchema[] {
{ {
component: 'FileUpload', component: 'FileUpload',
componentProps: { componentProps: {
maxNumber: 5, maxNumber: 1,
maxSize: 10, maxSize: 10,
accept: [ accept: [
'pdf', 'pdf',
@ -340,17 +340,19 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
{ {
field: 'no', field: 'no',
title: '订单单号', title: '订单单号',
width: 260, width: 200,
fixed: 'left', fixed: 'left',
}, },
{ {
field: 'productNames', field: 'productNames',
title: '产品信息', title: '产品信息',
showOverflow: 'tooltip', showOverflow: 'tooltip',
minWidth: 120,
}, },
{ {
field: 'supplierName', field: 'supplierName',
title: '供应商', title: '供应商',
minWidth: 120,
}, },
{ {
field: 'orderTime', field: 'orderTime',
@ -361,40 +363,45 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
{ {
field: 'creatorName', field: 'creatorName',
title: '创建人', title: '创建人',
minWidth: 120,
}, },
{ {
field: 'totalCount', field: 'totalCount',
title: '总数量', title: '总数量',
formatter: 'formatNumber', minWidth: 120,
}, },
{ {
field: 'inCount', field: 'inCount',
title: '入库数量', title: '入库数量',
formatter: 'formatNumber', minWidth: 120,
}, },
{ {
field: 'returnCount', field: 'returnCount',
title: '退货数量', title: '退货数量',
formatter: 'formatNumber', minWidth: 120,
}, },
{ {
field: 'totalProductPrice', field: 'totalProductPrice',
title: '金额合计', title: '金额合计',
formatter: 'formatNumber', formatter: 'formatNumber',
minWidth: 120,
}, },
{ {
field: 'totalPrice', field: 'totalPrice',
title: '含税金额', title: '含税金额',
formatter: 'formatNumber', formatter: 'formatNumber',
minWidth: 120,
}, },
{ {
field: 'depositPrice', field: 'depositPrice',
title: '支付订金', title: '支付订金',
formatter: 'formatNumber', formatter: 'formatNumber',
minWidth: 120,
}, },
{ {
field: 'status', field: 'status',
title: '状态', title: '状态',
minWidth: 120,
cellRender: { cellRender: {
name: 'CellDict', name: 'CellDict',
props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, props: { type: DICT_TYPE.ERP_AUDIT_STATUS },

View File

@ -58,6 +58,16 @@ const [Grid, gridApi] = useVbenVxeGrid({
enabled: false, enabled: false,
}, },
}, },
gridEvents: {
// editClosed: ({ row }) => {
// // tableData
// const index = tableData.value.findIndex((item) => item.id === row.id);
// if (index !== -1) {
// tableData.value[index] = { ...row };
// emit('update:items', [...tableData.value]);
// }
// },
},
}); });
/** 监听外部传入的列数据 */ /** 监听外部传入的列数据 */
@ -107,7 +117,25 @@ onMounted(async () => {
}); });
function handleAdd() { function handleAdd() {
gridApi.grid.insertAt(null, -1); const newRow = {
id: tableData.value.length + 1,
productId: null,
productName: '',
productUnitId: null,
productUnitName: '',
productBarCode: '',
count: 1,
productPrice: 0,
totalProductPrice: 0,
taxPercent: 0,
taxPrice: 0,
totalPrice: 0,
stockCount: 0,
remark: '',
};
tableData.value.push(newRow);
gridApi.grid.insertAt(newRow, -1);
emit('update:items', [...tableData.value]);
} }
function handleDelete(row: ErpPurchaseOrderApi.PurchaseOrderItem) { function handleDelete(row: ErpPurchaseOrderApi.PurchaseOrderItem) {
@ -185,7 +213,8 @@ const getSummaries = (): {
}; };
}; };
const validate = async (): Promise<void> => { const validate = async (): Promise<boolean> => {
try {
for (let i = 0; i < tableData.value.length; i++) { for (let i = 0; i < tableData.value.length; i++) {
const item = tableData.value[i]; const item = tableData.value[i];
if (item) { if (item) {
@ -200,6 +229,11 @@ const validate = async (): Promise<void> => {
} }
} }
} }
return true;
} catch (error) {
console.error('验证失败:', error);
throw error;
}
}; };
const getData = (): ErpPurchaseOrderApi.PurchaseOrderItem[] => tableData.value; const getData = (): ErpPurchaseOrderApi.PurchaseOrderItem[] => tableData.value;
@ -212,7 +246,11 @@ const init = (
}); });
}; };
defineExpose({ validate, getData, init }); defineExpose({
validate,
getData,
init,
});
</script> </script>
<template> <template>

View File

@ -1,10 +1,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ErpPurchaseOrderApi } from '#/api/erp/purchase/order'; import type { ErpPurchaseOrderApi } from '#/api/erp/purchase/order';
import { computed, ref } from 'vue'; import { computed, nextTick, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui'; import { useVbenModal } from '@vben/common-ui';
import { formatDateTime } from '@vben/utils';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
@ -72,6 +71,9 @@ const handleUpdateTotalPrice = (totalPrice: number) => {
} }
}; };
/**
* 创建或更新采购订单
*/
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({
async onConfirm() { async onConfirm() {
const { valid } = await formApi.validate(); const { valid } = await formApi.validate();
@ -79,17 +81,49 @@ const [Modal, modalApi] = useVbenModal({
return; return;
} }
// //
if (itemFormRef.value && typeof itemFormRef.value.validate === 'function') { await nextTick(); //
await itemFormRef.value.validate();
// - itemFormRef.value 访
const itemFormInstance = Array.isArray(itemFormRef.value)
? itemFormRef.value[0]
: itemFormRef.value;
if (itemFormInstance && typeof itemFormInstance.validate === 'function') {
try {
const isValid = await itemFormInstance.validate();
if (!isValid) {
message.error('子表单验证失败');
return;
} }
} catch (error) {
message.error(error.message || '子表单验证失败');
return;
}
} else {
message.error('子表单验证方法不存在');
return;
}
//
if (!formData.value?.items || formData.value.items.length === 0) {
message.error('产品清单不能为空,请至少添加一个产品');
return;
}
modalApi.lock(); modalApi.lock();
// //
const data = const data =
(await formApi.getValues()) as ErpPurchaseOrderApi.PurchaseOrder; (await formApi.getValues()) as ErpPurchaseOrderApi.PurchaseOrder;
data.items = data.items = formData.value?.items;
itemFormRef.value && typeof itemFormRef.value.getData === 'function' if (data.items) {
? itemFormRef.value.getData() data.items = data.items.map((item) => {
: []; const { ...itemWithoutId } = item;
return itemWithoutId;
});
}
//
if (data.fileUrl && Array.isArray(data.fileUrl)) {
data.fileUrl = data.fileUrl.length > 0 ? data.fileUrl[0] : '';
}
try { try {
await (formType.value === 'create' await (formType.value === 'create'
? createPurchaseOrder(data) ? createPurchaseOrder(data)
@ -109,18 +143,46 @@ const [Modal, modalApi] = useVbenModal({
} }
// //
const data = modalApi.getData<{ id?: number; type: string }>(); const data = modalApi.getData<{ id?: number; type: string }>();
if (!data || !data.id) { if (!data) {
return; return;
} }
formType.value = data.type; formType.value = data.type;
if (!data.id) {
//
formData.value = { items: [] } as ErpPurchaseOrderApi.PurchaseOrder;
await nextTick();
const itemFormInstance = Array.isArray(itemFormRef.value)
? itemFormRef.value[0]
: itemFormRef.value;
if (itemFormInstance && typeof itemFormInstance.init === 'function') {
itemFormInstance.init([]);
}
return;
}
modalApi.lock(); modalApi.lock();
try { try {
formData.value = await getPurchaseOrder(data.id); formData.value = await getPurchaseOrder(data.id);
formData.value.orderTime = formatDateTime(formData.value.orderTime); // URLFileUpload
if (
formData.value.fileUrl &&
typeof formData.value.fileUrl === 'string'
) {
formData.value.fileUrl = formData.value.fileUrl
? [formData.value.fileUrl]
: [];
}
// values // values
await formApi.setValues(formData.value); await formApi.setValues(formData.value);
// //
itemFormRef.value?.init(formData.value.items || []); await nextTick();
const itemFormInstance = Array.isArray(itemFormRef.value)
? itemFormRef.value[0]
: itemFormRef.value;
if (itemFormInstance && typeof itemFormInstance.init === 'function') {
itemFormInstance.init(formData.value.items || []);
}
} finally { } finally {
modalApi.unlock(); modalApi.unlock();
} }