refactor(erp): 将文件上传字段从 fileUrl 改为 blobIds 并支持多附件上传
- 将数据表单中的 fieldName 从 fileUrl 更改为 blobIds
- 为 FileUpload 组件添加 valueKey、maxNumber 和 multiple 配置
- 移除表单数据模型中的 fileUrl 属性定义
- 在表单加载时将 attachmentList 数据转换为 blobIds 格式
- 将 API 接口中的 fileUrl 字段替换为 attachmentList 对象数组
- 支持最多 10 个附件的批量上传功能
| | |
| | | paymentPrice: number; // 实际付款金额 |
| | | status: number; // 状态 |
| | | remark: string; // 备注 |
| | | fileUrl?: string; // 附件 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | accountId?: number; // 付款账户 |
| | | accountName?: string; // 账户名称 |
| | | financeUserId?: number; // 财务人员 |
| | |
| | | receiptPrice: number; // 实际收款金额 |
| | | status: number; // 状态 |
| | | remark: string; // 备注 |
| | | fileUrl?: string; // 附件 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | accountId?: number; // 收款账户 |
| | | accountName?: string; // 账户名称 |
| | | financeUserId?: number; // 财务人员 |
| | |
| | | accountId?: number; // 结算账户编号 |
| | | status?: number; // 状态 |
| | | remark?: string; // 备注 |
| | | fileUrl?: string; // 附件地址 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | inCount?: number; // 采购入库数量 |
| | | count?: number; // 数量 |
| | | returnCount?: number; // 采购退货数量 |
| | |
| | | supplierId?: number; // 供应商编号 |
| | | supplierName?: string; // 供应商名称 |
| | | discountPercent?: number; // 优惠率 |
| | | fileUrl?: string; // 附件地址 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | remark?: string; // 备注 |
| | | totalCount?: number; // 总数量 |
| | | totalPrice?: number; // 总金额 |
| | |
| | | remark: string; // 备注 |
| | | outCount: number; // 销售出库数量 |
| | | outStatus?: number; // 出库状态:0-未出库,1-部分出库,2-全部出库 |
| | | fileUrl?: string; // 附件地址 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | inCount?: number; // 采购入库数量 |
| | | returnCount: number; // 销售退货数量 |
| | | totalProductPrice?: number; // 产品金额,单位:元 |
| | |
| | | totalProductPrice?: number; // 合计商品金额 |
| | | taxPrice?: number; // 合计税额 |
| | | totalTaxPrice?: number; // 合计税额 |
| | | fileUrl?: string; // 附件地址 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | items?: SaleOutItem[]; |
| | | } |
| | | |
| | |
| | | totalProductPrice?: number; // 合计商品金额 |
| | | taxPrice?: number; // 合计税额 |
| | | totalTaxPrice?: number; // 合计税额 |
| | | fileUrl?: string; // 附件地址 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | items?: SaleReturnItem[]; |
| | | } |
| | | |
| | |
| | | totalPrice: number; // 合计金额,单位:元 |
| | | status: number; // 状态 |
| | | remark: string; // 备注 |
| | | fileUrl?: string; // 附件 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | productNames?: string; // 产品信息 |
| | | creatorName?: string; // 创建人 |
| | | items?: StockCheckItem[]; // 盘点产品清单 |
| | |
| | | totalPrice: number; // 合计金额,单位:元 |
| | | status: number; // 状态 |
| | | remark: string; // 备注 |
| | | fileUrl?: string; // 附件 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | productNames?: string; // 产品信息 |
| | | creatorName?: string; // 创建人 |
| | | items?: StockInItem[]; // 入库产品清单 |
| | |
| | | totalPrice: number; // 合计金额,单位:元 |
| | | status: number; // 状态 |
| | | remark: string; // 备注 |
| | | fileUrl?: string; // 附件 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | fromWarehouseId?: number; // 来源仓库编号 |
| | | createTime: Date; // 创建时间 |
| | | creator: string; // 创建人 |
| | |
| | | totalPrice: number; // 合计金额,单位:元 |
| | | status: number; // 状态 |
| | | remark: string; // 备注 |
| | | fileUrl?: string; // 附件 |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // 附件列表 |
| | | items?: StockOutItem[]; // 出库产品清单 |
| | | } |
| | | |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref< |
| | | ErpFinancePaymentApi.FinancePayment & { |
| | | fileUrl?: string; |
| | | } |
| | | ErpFinancePaymentApi.FinancePayment |
| | | >({ |
| | | id: undefined, |
| | | no: '', |
| | |
| | | financeUserId: undefined, |
| | | paymentTime: undefined, |
| | | remark: '', |
| | | fileUrl: undefined, |
| | | totalPrice: 0, |
| | | discountPrice: 0, |
| | | paymentPrice: 0, |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getFinancePayment(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref< |
| | | ErpFinanceReceiptApi.FinanceReceipt & { |
| | | fileUrl?: string; |
| | | } |
| | | ErpFinanceReceiptApi.FinanceReceipt |
| | | >({ |
| | | id: undefined, |
| | | no: '', |
| | |
| | | financeUserId: 0, |
| | | receiptTime: new Date(), |
| | | remark: '', |
| | | fileUrl: undefined, |
| | | totalPrice: 0, |
| | | discountPrice: 0, |
| | | receiptPrice: 0, |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getFinanceReceipt(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | accountId?: number; |
| | | customerId?: number; |
| | | discountPercent?: number; |
| | | fileUrl?: string; |
| | | order?: ErpPurchaseOrderApi.PurchaseOrder; |
| | | orderId?: number; |
| | | orderNo?: string; |
| | |
| | | accountId: undefined, |
| | | inTime: undefined, |
| | | remark: undefined, |
| | | fileUrl: undefined, |
| | | discountPercent: 0, |
| | | supplierId: undefined, |
| | | discountPrice: 0, |
| | |
| | | accountId: order.accountId!, |
| | | remark: order.remark!, |
| | | discountPercent: order.discountPercent!, |
| | | fileUrl: order.fileUrl!, |
| | | }; |
| | | // 将订单项设置到入库单项 |
| | | order.items!.forEach((item: any) => { |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseIn(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | ...item, |
| | | id: undefined, |
| | | })); |
| | | if (data.fileUrl && Array.isArray(data.fileUrl)) { |
| | | data.fileUrl = data.fileUrl.length > 0 ? data.fileUrl[0] : ''; |
| | | } |
| | | await (formType.value === 'create' |
| | | ? createPurchaseOrder(data) |
| | | : updatePurchaseOrder(data)); |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseOrder(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | modalApi.unlock(); |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | placeholder: '请上传附件', |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | disabled: formType === 'detail', |
| | | }, |
| | | formItemClass: 'col-span-2', |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | ErpPurchaseReturnApi.PurchaseReturn & { |
| | | accountId?: number; |
| | | discountPercent?: number; |
| | | fileUrl?: string; |
| | | order?: ErpPurchaseOrderApi.PurchaseOrder; |
| | | orderId?: number; |
| | | orderNo?: string; |
| | |
| | | accountId: undefined, |
| | | returnTime: undefined, |
| | | remark: undefined, |
| | | fileUrl: undefined, |
| | | discountPercent: 0, |
| | | supplierId: undefined, |
| | | discountPrice: 0, |
| | |
| | | accountId: order.accountId!, |
| | | remark: order.remark!, |
| | | discountPercent: order.discountPercent!, |
| | | fileUrl: order.fileUrl!, |
| | | }; |
| | | // 将订单项设置到退货单项 |
| | | order.items!.forEach((item: any) => { |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getPurchaseReturn(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | accountId?: number; |
| | | customerId?: number; |
| | | discountPercent?: number; |
| | | fileUrl?: string; |
| | | order?: ErpSaleOrderApi.SaleOrder; |
| | | orderId?: number; |
| | | orderNo?: string; |
| | |
| | | accountId: undefined, |
| | | outTime: undefined, |
| | | remark: undefined, |
| | | fileUrl: undefined, |
| | | discountPercent: 0, |
| | | customerId: undefined, |
| | | discountPrice: 0, |
| | |
| | | accountId: order.accountId!, |
| | | remark: order.remark!, |
| | | discountPercent: order.discountPercent!, |
| | | fileUrl: order.fileUrl!, |
| | | }; |
| | | // 将订单项设置到出库单项 |
| | | order.items!.forEach((item: any) => { |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getSaleOut(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | accountId?: number; |
| | | customerId?: number; |
| | | discountPercent?: number; |
| | | fileUrl?: string; |
| | | order?: ErpSaleOrderApi.SaleOrder; |
| | | orderId?: number; |
| | | orderNo?: string; |
| | |
| | | accountId: undefined, |
| | | returnTime: undefined, |
| | | remark: undefined, |
| | | fileUrl: undefined, |
| | | discountPercent: 0, |
| | | customerId: undefined, |
| | | discountPrice: 0, |
| | |
| | | accountId: order.accountId!, |
| | | remark: order.remark!, |
| | | discountPercent: order.discountPercent!, |
| | | fileUrl: order.fileUrl!, |
| | | }; |
| | | // 将订单项设置到退货单项 |
| | | order.items!.forEach((item: any) => { |
| | |
| | | modalApi.lock(); |
| | | try { |
| | | formData.value = await getSaleReturn(data.id); |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })); |
| | | formApi.setFieldValue('blobIds', blobIds); |
| | | } |
| | | // 设置到 values |
| | | await formApi.setValues(formData.value, false); |
| | | } finally { |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: '附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |