feat(erp): 采购台账与采购退货界面改造
采购台账:
- 采购订单菜单/页面文案改为「采购台账」
- 表单新增采购类型、合同号、项目名称、付款日期(必填)、付款方式
- 支持选择销售订单 / 生产工单作为来源,自动带入单号与明细
- 明细新增产品编号(随物料选择带出),列表/详情展示
- 付款日期账期超 30 天标红并提示;销售订单新增收款日期及同样提醒
采购退货:
- 表单新增处理方式(退款/换货)、退款金额、合同号、附件上传
- 新增「提交审批」动作,接入采购 → 质量 → 仓库 BPM 流程
- 列表新增处理方式、退款金额、冲红单号、换货到货单号列
- 状态字典新增「审批中」
Co-Authored-By: Claude Code <noreply@anthropic.com>
| | |
| | | discountPrice?: number; // 伿 éé¢ï¼åä½ï¼å
|
| | | depositPrice?: number; // å®ééé¢ï¼åä½ï¼å
|
| | | accountId?: number; // ç»ç®è´¦æ·ç¼å· |
| | | purchaseType?: number; // éè´ç±»åï¼1ç产 2åå
¬ç¨å 3å
¶ä» |
| | | contractNo?: string; // ååå·ï¼æå·¥è¾å
¥ï¼ä¸èªå¨çæï¼ |
| | | projectName?: string; // 项ç®åç§°ï¼éå¿
å¡«ï¼ |
| | | paymentDate?: Date | string; // 仿¬¾æ¥æ |
| | | paymentMethod?: number; // 仿¬¾æ¹å¼ï¼1çµæ± 2æ±ç¥¨ 3ç°é 4ææºæ¯ä» |
| | | sourceType?: number; // æ¥æºç±»åï¼1ç产工å 3éå®è®¢å |
| | | sourceId?: number; // æ¥æºåç¼å· |
| | | sourceNo?: string; // æ¥æºåå· |
| | | sourceTypeName?: string; // æ¥æºç±»ååç§° |
| | | productCodes?: string; // 产åç¼å·å表ï¼MDM ç©æç¼ç ï¼éå·æ¼æ¥ï¼ |
| | | status?: number; // ç¶æ |
| | | remark?: string; // 夿³¨ |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // éä»¶å表 |
| | |
| | | seq?: number; // å端è¡å· |
| | | orderId?: number; // éè´è®¢åç¼å· |
| | | productId?: number; // 产åç¼å· |
| | | productCode?: string; // 产åç¼å·ï¼MDM ç©æç¼ç å¿«ç
§ï¼ |
| | | productName?: string; // 产ååç§° |
| | | productBarCode?: string; // äº§åæ¡ç |
| | | productUnitId?: number; // 产ååä½ç¼å· |
| | |
| | | accountId?: number; // æ¶æ¬¾è´¦æ·ç¼å· |
| | | saleUserId?: number; // éå®äººåç¼å· |
| | | orderTime: Date; // è®¢åæ¶é´ |
| | | receiptDate?: Date | string; // æ¶æ¬¾æ¥æ |
| | | totalCount: number; // å计æ°é |
| | | totalPrice: number; // å计éé¢ï¼åä½ï¼å
|
| | | status: number; // ç¶æ |
| | |
| | | vendorNickname?: string; // ä¾åºåç®ç§° |
| | | returnDate?: number | string; // éè´§æ¥æ |
| | | returnReason?: string; // éè´§åå |
| | | contractNo?: string; // éè´ååå·ï¼åªè¯»ï¼ä»éè´è®¢åå¿«ç
§ï¼ |
| | | handleType?: number; // å¤çæ¹å¼ï¼1鿬¾ 2æ¢è´§ |
| | | refundAmount?: number; // 鿬¾éé¢ |
| | | redFlushPaymentId?: number; // è´æ°å²çº¢ä»æ¬¾åç¼å· |
| | | redFlushPaymentNo?: string; // è´æ°å²çº¢ä»æ¬¾åå· |
| | | replacementNoticeId?: number; // æ¢è´§å°è´§éç¥åç¼å· |
| | | replacementNoticeCode?: string; // æ¢è´§å°è´§éç¥åå· |
| | | processInstanceId?: string; // BPM æµç¨å®ä¾ç¼å· |
| | | attachmentList?: { id: number; name?: string; url?: string }[]; // éä»¶å表 |
| | | blobIds?: number[]; // éä»¶ blobId åè¡¨ï¼æäº¤ç¨ï¼ |
| | | transportCode?: string; // è¿åå· |
| | | transportTelephone?: string; // èç³»çµè¯ |
| | | status?: number; // åæ®ç¶æ |
| | | statusName?: string; // ç¶æåç§° |
| | | remark?: string; // 夿³¨ |
| | | createTime?: Date; // å建æ¶é´ |
| | | } |
| | |
| | | return requestClient.put(`/mes/wm/return-vendor/submit?id=${id}`); |
| | | } |
| | | |
| | | /** æäº¤ä¾åºåéè´§å审æ¹ï¼BPMï¼éè´ -> è´¨é -> ä»åºï¼ */ |
| | | export function submitReturnVendorApproval( |
| | | id: number, |
| | | processDefinitionKey = 'purchase_return_vendor_approve', |
| | | ) { |
| | | return requestClient.put('/mes/wm/return-vendor/submit-approval', null, { |
| | | params: { id, processDefinitionKey }, |
| | | }); |
| | | } |
| | | |
| | | /** æ¥è¯¢ä¾åºåéè´§åéä»¶ */ |
| | | export function getReturnVendorAttachments(id: number) { |
| | | return requestClient.get< |
| | | { id: number; name?: string; url?: string }[] |
| | | >('/mes/wm/return-vendor/attachments', { params: { id } }); |
| | | } |
| | | |
| | | /** çæéè´éè´§è´æ°å²çº¢ä»æ¬¾åï¼å¹çï¼ */ |
| | | export function createReturnVendorRedFlush(id: number) { |
| | | return requestClient.post<number>('/mes/wm/return-vendor/red-flush', null, { |
| | | params: { id }, |
| | | }); |
| | | } |
| | | |
| | | /** çææ¢è´§å°è´§éç¥åï¼å¹çï¼ */ |
| | | export function createReturnVendorReplacementNotice(id: number) { |
| | | return requestClient.post<number>( |
| | | '/mes/wm/return-vendor/replacement-notice', |
| | | null, |
| | | { params: { id } }, |
| | | ); |
| | | } |
| | | |
| | | /** æ§è¡æ£è´§ */ |
| | | export function stockReturnVendor(id: number) { |
| | | return requestClient.put(`/mes/wm/return-vendor/stock?id=${id}`); |
| | |
| | | /** MES ä¾åºåéè´§åç¶ææä¸¾ */ |
| | | export const MesWmReturnVendorStatusEnum = { |
| | | PREPARE: MesOrderStatusConstants.DRAFT, |
| | | /** 审æ¹ä¸ï¼BPM æµç¨æµè½¬ä¸ï¼å¤ç¨ CONFIRMED=1ï¼ */ |
| | | BPM_APPROVING: MesOrderStatusConstants.CONFIRMED, |
| | | /** å¾
æ£è´§ï¼ä¿çæ§å½åï¼å¼ä»ä¸º 2ï¼ */ |
| | | APPROVING: MesOrderStatusConstants.APPROVING, |
| | | APPROVED: MesOrderStatusConstants.APPROVED, |
| | | FINISHED: MesOrderStatusConstants.FINISHED, |
| | | CANCELED: MesOrderStatusConstants.CANCELLED, |
| | | } as const; |
| | | |
| | | /** MES ä¾åºåéè´§åå¤çæ¹å¼æä¸¾ */ |
| | | export const MesWmReturnVendorHandleTypeEnum = { |
| | | REFUND: 1, |
| | | REPLACEMENT: 2, |
| | | } as const; |
| | | |
| | | /** MES åè´§éç¥åç¶ææä¸¾ */ |
| | | export const MesWmSalesNoticeStatusEnum = { |
| | | PREPARE: MesOrderStatusConstants.DRAFT, |
| | |
| | | const ERP_DICT = { |
| | | ERP_AUDIT_STATUS: 'erp_audit_status', // ERP 审æ¹ç¶æ |
| | | ERP_STOCK_RECORD_BIZ_TYPE: 'erp_stock_record_biz_type', // åºåæç»çä¸å¡ç±»å |
| | | ERP_PURCHASE_TYPE: 'erp_purchase_type', // éè´å°è´¦-éè´ç±»åï¼1ç产 2åå
¬ç¨å 3å
¶ä» |
| | | ERP_PAYMENT_METHOD: 'erp_payment_method', // éè´å°è´¦-仿¬¾æ¹å¼ï¼1çµæ± 2æ±ç¥¨ 3ç°é 4ææºæ¯ä» |
| | | } as const; |
| | | |
| | | /** ========== FINANCE - è´¢å¡ç®¡ç模å ========== */ |
| | |
| | | MES_WM_ARRIVAL_NOTICE_STATUS: 'mes_wm_arrival_notice_status', // MES å°è´§éç¥åç¶æ |
| | | MES_WM_ITEM_RECEIPT_STATUS: 'mes_wm_item_receipt_status', // MES éè´å
¥åºåç¶æ |
| | | MES_WM_RETURN_VENDOR_STATUS: 'mes_wm_return_vendor_status', // MES ä¾åºåéè´§åç¶æ |
| | | MES_WM_RETURN_VENDOR_HANDLE_TYPE: 'mes_wm_return_vendor_handle_type', // MES ä¾åºåéè´§å¤çæ¹å¼ï¼1鿬¾ 2æ¢è´§ |
| | | MES_WM_SALES_NOTICE_STATUS: 'mes_wm_sales_notice_status', // MES åè´§éç¥åç¶æ |
| | | MES_WM_RETURN_SALES_STATUS: 'mes_wm_return_sales_status', // MES éå®éè´§åç¶æ |
| | | MES_WM_RETURN_ISSUE_STATUS: 'mes_wm_return_issue_status', // MES ç产éæåç¶æ |
| | |
| | | import type { Recordable } from '@vben/types'; |
| | | |
| | | export * from './import-result'; |
| | | export * from './overdue'; |
| | | export * from './rangePickerProps'; |
| | | export * from './routerHelper'; |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import dayjs from 'dayjs'; |
| | | |
| | | /** è´¦æé»è®¤å¤©æ°ï¼ä»æ¬¾æ¥æ/æ¶æ¬¾æ¥æ è· ä¸å¡æ¥æ è¶
è¿è¯¥å¤©æ°å³è§ä¸ºè¶
æ */ |
| | | export const DEFAULT_ACCOUNT_PERIOD_DAYS = 30; |
| | | |
| | | /** |
| | | * 计ç®è´¦æå¤©æ°ï¼ç®æ æ¥æ - åºåæ¥æï¼æèªç¶å¤©åæ´ï¼ |
| | | * |
| | | * @param baseTime åºåæ¥æï¼éè´è®¢åæ¥æ / éå®è®¢åæ¥æï¼ |
| | | * @param targetTime ç®æ æ¥æï¼ä»æ¬¾æ¥æ / æ¶æ¬¾æ¥æï¼ |
| | | * @returns è´¦æå¤©æ°ï¼ä»»ä¸æ¥æä¸ºç©ºæéæ³æ¶è¿å null |
| | | */ |
| | | export function getAccountPeriodDays( |
| | | baseTime?: Date | null | string, |
| | | targetTime?: Date | null | string, |
| | | ): null | number { |
| | | if (!baseTime || !targetTime) { |
| | | return null; |
| | | } |
| | | const base = dayjs(baseTime); |
| | | const target = dayjs(targetTime); |
| | | if (!base.isValid() || !target.isValid()) { |
| | | return null; |
| | | } |
| | | return target.startOf('day').diff(base.startOf('day'), 'day'); |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦è¶
æ |
| | | * |
| | | * @param baseTime åºåæ¥æï¼éè´è®¢åæ¥æ / éå®è®¢åæ¥æï¼ |
| | | * @param targetTime ç®æ æ¥æï¼ä»æ¬¾æ¥æ / æ¶æ¬¾æ¥æï¼ |
| | | * @param days è´¦æä¸éï¼é»è®¤ 30 天 |
| | | */ |
| | | export function isOverdue( |
| | | baseTime?: Date | null | string, |
| | | targetTime?: Date | null | string, |
| | | days = DEFAULT_ACCOUNT_PERIOD_DAYS, |
| | | ): boolean { |
| | | const period = getAccountPeriodDays(baseTime, targetTime); |
| | | return period !== null && period > days; |
| | | } |
| | | |
| | | /** çæè¶
ææç¤ºææ¡ */ |
| | | export function getOverdueTip( |
| | | baseTime?: Date | null | string, |
| | | targetTime?: Date | null | string, |
| | | days = DEFAULT_ACCOUNT_PERIOD_DAYS, |
| | | ): string { |
| | | const period = getAccountPeriodDays(baseTime, targetTime); |
| | | if (period === null) { |
| | | return ''; |
| | | } |
| | | return `è´¦æ ${period} 天ï¼è¶
è¿ ${days} 天ï¼`; |
| | | } |
| | |
| | | import { getAccountSimpleList } from '#/api/erp/finance/account'; |
| | | import { getSupplierSimpleList } from '#/api/srm/supplier'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { getRangePickerDefaultProps, getOverdueTip, withoutFixedColumns } from '#/utils'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | import { getRangePickerDefaultProps, withoutFixedColumns } from '#/utils'; |
| | | import { ErpSaleOrderSelect } from '#/views/erp/sale/order/components'; |
| | | import { ProWorkOrderSelect } from '#/views/mes/pro/workorder/components'; |
| | | |
| | | /** 表åç±»å */ |
| | | export type FormType = 'create' | 'detail' | 'edit'; |
| | | |
| | | /** éè´æ¥æºç±»åï¼0 æ æ¥æºã1 ç产工åã3 éå®è®¢åï¼ä¸å端 ErpPurchaseOrderSourceTypeEnum 对é½ï¼ */ |
| | | export const PurchaseSourceTypeEnum = { |
| | | NONE: 0, |
| | | WORK_ORDER: 1, |
| | | SALE_ORDER: 3, |
| | | } as const; |
| | | |
| | | /** è¡¨åæ¥æºèå¨åè° */ |
| | | export interface FormSchemaHandlers { |
| | | /** æ¥æºç±»ååæ´ï¼ç¨äºæ¸
ç©ºå·²éæ¥æºåæ®ï¼ */ |
| | | onSourceTypeChange?: (sourceType: number | undefined) => void; |
| | | /** æ¥æºåæ®éä¸ï¼ç¨äºå¸¦å
¥éè´æç»ï¼ */ |
| | | onSourceOrderChange?: (sourceType: number, item: any) => void; |
| | | } |
| | | |
| | | /** 表åçé
置项 */ |
| | | export function useFormSchema(formType: FormType): VbenFormSchema[] { |
| | | export function useFormSchema( |
| | | formType: FormType, |
| | | handlers?: FormSchemaHandlers, |
| | | ): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'id', |
| | |
| | | valueField: 'id', |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'purchaseType', |
| | | label: 'éè´ç±»å', |
| | | component: 'Select', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©éè´ç±»å', |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.ERP_PURCHASE_TYPE, 'number'), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'contractNo', |
| | | label: 'ååå·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥ååå·ï¼æå·¥è¾å
¥ï¼ç³»ç»ä¸èªå¨çæï¼', |
| | | maxlength: 64, |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'projectName', |
| | | label: '项ç®åç§°', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥é¡¹ç®åç§°ï¼éå¿
å¡«ï¼', |
| | | maxlength: 255, |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'paymentDate', |
| | | label: '仿¬¾æ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ä»æ¬¾æ¥æ', |
| | | showTime: false, |
| | | format: 'YYYY-MM-DD', |
| | | valueFormat: 'YYYY-MM-DD HH:mm:ss', |
| | | }, |
| | | rules: 'required', |
| | | help: (values: { |
| | | orderTime?: Date | string; |
| | | paymentDate?: Date | string; |
| | | }) => { |
| | | const tip = getOverdueTip(values.orderTime, values.paymentDate); |
| | | return tip ? `â ${tip}ï¼è¯·ç¡®è®¤ä»æ¬¾è®¡å` : ''; |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'paymentMethod', |
| | | label: '仿¬¾æ¹å¼', |
| | | component: 'Select', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ä»æ¬¾æ¹å¼', |
| | | allowClear: true, |
| | | options: getDictOptions(DICT_TYPE.ERP_PAYMENT_METHOD, 'number'), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'sourceId', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'sourceNo', |
| | | component: 'Input', |
| | | dependencies: { |
| | | triggerFields: [''], |
| | | show: () => false, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'sourceType', |
| | | label: 'æ¥æºç±»å', |
| | | component: 'Select', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©æ¥æºç±»å', |
| | | allowClear: true, |
| | | options: [ |
| | | { label: 'æ æ¥æº', value: PurchaseSourceTypeEnum.NONE }, |
| | | { label: 'ç产工å', value: PurchaseSourceTypeEnum.WORK_ORDER }, |
| | | { label: 'éå®è®¢å', value: PurchaseSourceTypeEnum.SALE_ORDER }, |
| | | ], |
| | | onChange: (value: number | undefined) => |
| | | handlers?.onSourceTypeChange?.(value), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'sourceWorkOrderId', |
| | | label: 'ç产工å', |
| | | component: markRaw(ProWorkOrderSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ç产工å', |
| | | onChange: (item: any) => |
| | | handlers?.onSourceOrderChange?.(PurchaseSourceTypeEnum.WORK_ORDER, item), |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['sourceType'], |
| | | show: (values) => |
| | | values.sourceType === PurchaseSourceTypeEnum.WORK_ORDER, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'sourceSaleOrderId', |
| | | label: 'éå®è®¢å', |
| | | component: markRaw(ErpSaleOrderSelect), |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©éå®è®¢å', |
| | | onChange: (item: any) => |
| | | handlers?.onSourceOrderChange?.(PurchaseSourceTypeEnum.SALE_ORDER, item), |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['sourceType'], |
| | | show: (values) => |
| | | values.sourceType === PurchaseSourceTypeEnum.SALE_ORDER, |
| | | }, |
| | | }, |
| | | { |
| | | component: 'InputNumber', |
| | |
| | | slots: { default: 'productId' }, |
| | | }, |
| | | { |
| | | field: 'productCode', |
| | | title: '产åç¼å·', |
| | | minWidth: 140, |
| | | showOverflow: 'tooltip', |
| | | }, |
| | | { |
| | | field: 'productUnitName', |
| | | title: 'åä½', |
| | | minWidth: 80, |
| | |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'purchaseType', |
| | | label: 'éè´ç±»å', |
| | | component: 'Select', |
| | | componentProps: { |
| | | options: getDictOptions(DICT_TYPE.ERP_PURCHASE_TYPE, 'number'), |
| | | placeholder: 'è¯·éæ©éè´ç±»å', |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'contractNo', |
| | | label: 'ååå·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '请è¾å
¥ååå·', |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'paymentMethod', |
| | | label: '仿¬¾æ¹å¼', |
| | | component: 'Select', |
| | | componentProps: { |
| | | options: getDictOptions(DICT_TYPE.ERP_PAYMENT_METHOD, 'number'), |
| | | placeholder: 'è¯·éæ©ä»æ¬¾æ¹å¼', |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'paymentDate', |
| | | label: '仿¬¾æ¥æ', |
| | | component: 'RangePicker', |
| | | componentProps: { |
| | | ...getRangePickerDefaultProps(), |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'creator', |
| | | label: 'å建人', |
| | | component: 'ApiSelect', |
| | |
| | | minWidth: 120, |
| | | }, |
| | | { |
| | | field: 'productCodes', |
| | | title: '产åç¼å·', |
| | | showOverflow: 'tooltip', |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | field: 'supplierName', |
| | | title: 'ä¾åºå', |
| | | minWidth: 120, |
| | |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'purchaseType', |
| | | title: 'éè´ç±»å', |
| | | minWidth: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.ERP_PURCHASE_TYPE }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'contractNo', |
| | | title: 'ååå·', |
| | | minWidth: 140, |
| | | showOverflow: 'tooltip', |
| | | }, |
| | | { |
| | | field: 'paymentDate', |
| | | title: '仿¬¾æ¥æ', |
| | | width: 140, |
| | | slots: { default: 'paymentDate' }, |
| | | }, |
| | | { |
| | | field: 'paymentMethod', |
| | | title: '仿¬¾æ¹å¼', |
| | | minWidth: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.ERP_PAYMENT_METHOD }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'creatorName', |
| | | title: 'å建人', |
| | | minWidth: 120, |
| | |
| | | bordered: true, |
| | | column: 2, |
| | | schema: [ |
| | | { label: 'éè´è®¢åå·', field: 'no' }, |
| | | { label: 'éè´åå·', field: 'no' }, |
| | | { label: 'ä¾åºååç§°', field: 'supplierName', render: textRender }, |
| | | { |
| | | label: 'éè´ç±»å', |
| | | field: 'purchaseType', |
| | | render: (val) => |
| | | val == null |
| | | ? '-' |
| | | : h(DictTag, { type: DICT_TYPE.ERP_PURCHASE_TYPE, value: val }), |
| | | }, |
| | | { label: 'ååå·', field: 'contractNo', render: textRender }, |
| | | { label: '项ç®åç§°', field: 'projectName', render: textRender }, |
| | | { |
| | | label: 'è®¢åæ¶é´', |
| | | field: 'orderTime', |
| | | render: (val) => formatDate(val) as string, |
| | | }, |
| | | { |
| | | label: '仿¬¾æ¥æ', |
| | | field: 'paymentDate', |
| | | render: (val) => (val ? (formatDate(val) as string) : 'æªå¡«å'), |
| | | }, |
| | | { |
| | | label: '仿¬¾æ¹å¼', |
| | | field: 'paymentMethod', |
| | | render: (val) => |
| | | val == null |
| | | ? '-' |
| | | : h(DictTag, { type: DICT_TYPE.ERP_PAYMENT_METHOD, value: val }), |
| | | }, |
| | | { label: 'æ¥æºç±»å', field: 'sourceTypeName', render: textRender }, |
| | | { label: 'æ¥æºåå·', field: 'sourceNo', render: textRender }, |
| | | { label: '产åç¼å·', field: 'productCodes', render: textRender }, |
| | | { |
| | | label: 'å计æ°é', |
| | | field: 'totalCount', |
| | | render: (val) => erpCountInputFormatter(val) || '-', |
| | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; |
| | | |
| | | import { message, Tag } from 'ant-design-vue'; |
| | | import { message, Tag, Tooltip } from 'ant-design-vue'; |
| | | import dayjs from 'dayjs'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | |
| | | submitPurchaseOrder, |
| | | } from '#/api/erp/purchase/order'; |
| | | import { $t } from '#/locales'; |
| | | import { getOverdueTip, isOverdue } from '#/utils/overdue'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | | import Form from './modules/form.vue'; |
| | |
| | | /** 导åºè¡¨æ ¼ */ |
| | | async function handleExport() { |
| | | const data = await exportPurchaseOrder(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: 'éè´è®¢å.xls', source: data }); |
| | | downloadFileFromBlobPart({ fileName: 'éè´å°è´¦.xls', source: data }); |
| | | } |
| | | |
| | | /** 导å
¥éè´è®¢å */ |
| | |
| | | }); |
| | | try { |
| | | await submitPurchaseOrder(row.id!); |
| | | message.success(`éè´è®¢å ${row.no} å·²æäº¤å®¡æ¹`); |
| | | message.success(`éè´å°è´¦ ${row.no} å·²æäº¤å®¡æ¹`); |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | |
| | | <Page auto-content-height> |
| | | <FormModal @success="handleRefresh" /> |
| | | <ImportModal @success="handleRefresh" /> |
| | | <Grid table-title="éè´è®¢åå表"> |
| | | <Grid table-title="éè´å°è´¦å表"> |
| | | <template #toolbar-tools> |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: $t('ui.actionTitle.create', ['éè´è®¢å']), |
| | | label: $t('ui.actionTitle.create', ['éè´å°è´¦']), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.ADD, |
| | | auth: ['erp:purchase-order:create'], |
| | |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #paymentDate="{ row }"> |
| | | <Tooltip |
| | | v-if="row.paymentDate" |
| | | :title="getOverdueTip(row.orderTime, row.paymentDate)" |
| | | > |
| | | <span |
| | | :class=" |
| | | isOverdue(row.orderTime, row.paymentDate) |
| | | ? 'font-medium text-red-500' |
| | | : '' |
| | | " |
| | | > |
| | | {{ dayjs(row.paymentDate).format('YYYY-MM-DD') }} |
| | | </span> |
| | | </Tooltip> |
| | | <span v-else class="text-gray-400">æªå¡«å</span> |
| | | </template> |
| | | <template #inStatus="{ row }"> |
| | | <Tag v-if="row.inStatus === 0" color="default">æªå
¥åº</Tag> |
| | | <Tag v-else-if="row.inStatus === 1" color="warning">é¨åå
¥åº</Tag> |
| | |
| | | auth: ['erp:purchase-order:update-status'], |
| | | ifShow: () => row.status === 0, |
| | | popConfirm: { |
| | | title: `æäº¤éè´è®¢å${row.no}审æ¹åï¼`, |
| | | title: `æäº¤éè´å°è´¦${row.no}审æ¹åï¼`, |
| | | confirm: handleSubmit.bind(null, row), |
| | | }, |
| | | }, |
| | |
| | | getPurchaseOrder, |
| | | updatePurchaseOrder, |
| | | } from '#/api/erp/purchase/order'; |
| | | import { getSaleOrderItemListByOrderId } from '#/api/erp/sale/order'; |
| | | import { getWorkOrderBomItemListByWorkOrderId } from '#/api/mes/pro/workorder/bom'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../data'; |
| | | import { PurchaseSourceTypeEnum, useFormSchema } from '../data'; |
| | | import PurchaseOrderItemForm from './item-form.vue'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | |
| | | |
| | | const getTitle = computed(() => { |
| | | if (formType.value === 'create') { |
| | | return $t('ui.actionTitle.create', ['éè´è®¢å']); |
| | | return $t('ui.actionTitle.create', ['éè´å°è´¦']); |
| | | } else if (formType.value === 'edit') { |
| | | return $t('ui.actionTitle.edit', ['éè´è®¢å']); |
| | | return $t('ui.actionTitle.edit', ['éè´å°è´¦']); |
| | | } else { |
| | | return 'éè´è®¢å详æ
'; |
| | | return 'éè´å°è´¦è¯¦æ
'; |
| | | } |
| | | }); |
| | | |
| | | /** æ¥æºç±»ååæ´ï¼æ¸
ç©ºå·²éæ¥æºåæ®ï¼é¿å
æ¥æºåä¸ç±»åä¸ä¸è´ */ |
| | | function handleSourceTypeChange(sourceType: number | undefined) { |
| | | formApi.setValues({ |
| | | sourceWorkOrderId: undefined, |
| | | sourceSaleOrderId: undefined, |
| | | sourceId: undefined, |
| | | sourceNo: undefined, |
| | | }); |
| | | // éæ©ãæ æ¥æºãæ¶ä¸ä¿çæ¥æºç±»åå¼ |
| | | if (!sourceType) { |
| | | formApi.setFieldValue('sourceType', undefined); |
| | | } |
| | | } |
| | | |
| | | /** é䏿¥æºåæ®ï¼åå¡«æ¥æºä¿¡æ¯å¹¶å¸¦å
¥éè´æç» */ |
| | | async function handleSourceOrderChange(sourceType: number, item: any) { |
| | | if (!item?.id || formType.value === 'detail') { |
| | | return; |
| | | } |
| | | if (sourceType === PurchaseSourceTypeEnum.SALE_ORDER) { |
| | | const saleItems = await getSaleOrderItemListByOrderId(item.id); |
| | | if (saleItems?.length) { |
| | | handleUpdateItems( |
| | | saleItems.map((saleItem, index) => ({ |
| | | id: undefined, |
| | | seq: index + 1, |
| | | productId: saleItem.productId, |
| | | productName: saleItem.productName, |
| | | productUnitId: saleItem.productUnitId, |
| | | productUnitName: saleItem.productUnitName, |
| | | productPrice: saleItem.productPrice, |
| | | count: saleItem.count, |
| | | totalProductPrice: saleItem.totalProductPrice, |
| | | taxPercent: saleItem.taxPercent ?? 0, |
| | | taxPrice: saleItem.taxPrice, |
| | | totalPrice: saleItem.totalPrice, |
| | | remark: saleItem.remark, |
| | | qcCheckFlag: false, |
| | | })), |
| | | ); |
| | | } |
| | | await formApi.setFieldValue('sourceSaleOrderId', item.id); |
| | | } else if (sourceType === PurchaseSourceTypeEnum.WORK_ORDER) { |
| | | const bomItems = await getWorkOrderBomItemListByWorkOrderId(item.id); |
| | | if (bomItems?.length) { |
| | | handleUpdateItems( |
| | | bomItems.map((bomItem, index) => ({ |
| | | id: undefined, |
| | | seq: index + 1, |
| | | productId: bomItem.itemId, |
| | | productCode: bomItem.itemCode, |
| | | productName: bomItem.itemName, |
| | | productUnitId: bomItem.unitMeasureId, |
| | | productUnitName: bomItem.unitMeasureName, |
| | | productPrice: undefined, |
| | | count: bomItem.quantity ?? 1, |
| | | taxPercent: 0, |
| | | remark: bomItem.remark, |
| | | qcCheckFlag: false, |
| | | })), |
| | | ); |
| | | message.info('å·²æå·¥å BOM 带å
¥ç©æï¼è¯·è¡¥å¡«å«ç¨åä»·'); |
| | | } |
| | | await formApi.setFieldValue('sourceWorkOrderId', item.id); |
| | | } |
| | | await formApi.setValues({ |
| | | sourceType, |
| | | sourceId: item.id, |
| | | sourceNo: item.no ?? item.code, |
| | | }); |
| | | } |
| | | |
| | | const [Form, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | |
| | | }, |
| | | wrapperClass: 'grid-cols-3', |
| | | layout: 'vertical', |
| | | schema: useFormSchema(formType.value), |
| | | schema: useFormSchema(formType.value, { |
| | | onSourceTypeChange: handleSourceTypeChange, |
| | | onSourceOrderChange: handleSourceOrderChange, |
| | | }), |
| | | showDefaultActions: false, |
| | | handleValuesChange: (values, changedFields) => { |
| | | if (formData.value && changedFields.includes('discountPercent')) { |
| | |
| | | ...item, |
| | | id: undefined, |
| | | })); |
| | | // æ¥æºåæ®éæ©å¨æ¯å端è¾
å©åæ®µï¼æäº¤æ¶åªé sourceType/sourceId/sourceNo |
| | | delete (data as any).sourceWorkOrderId; |
| | | delete (data as any).sourceSaleOrderId; |
| | | if (!data.sourceType) { |
| | | data.sourceId = undefined; |
| | | data.sourceNo = undefined; |
| | | } |
| | | await (formType.value === 'create' |
| | | ? createPurchaseOrder(data) |
| | | : updatePurchaseOrder(data)); |
| | |
| | | const data = modalApi.getData<{ formType: FormType; id?: number }>(); |
| | | formType.value = data.formType; |
| | | formApi.setDisabled(formType.value === 'detail'); |
| | | formApi.updateSchema(useFormSchema(formType.value)); |
| | | formApi.updateSchema( |
| | | useFormSchema(formType.value, { |
| | | onSourceTypeChange: handleSourceTypeChange, |
| | | onSourceOrderChange: handleSourceOrderChange, |
| | | }), |
| | | ); |
| | | if (!data || !data.id) { |
| | | const accountList = await getAccountSimpleList(); |
| | | const defaultAccount = accountList.find((item) => item.defaultStatus); |
| | |
| | | try { |
| | | formData.value = await getPurchaseOrder(data.id); |
| | | await formApi.setValues(formData.value); |
| | | // åæ¾æ¥æºåæ®éæ©å¨ï¼å端åªå sourceIdï¼å端æ sourceType æ å°å°å¯¹åºéæ©å¨ï¼ |
| | | if (formData.value?.sourceId) { |
| | | if (formData.value.sourceType === PurchaseSourceTypeEnum.WORK_ORDER) { |
| | | await formApi.setFieldValue( |
| | | 'sourceWorkOrderId', |
| | | formData.value.sourceId, |
| | | ); |
| | | } else if ( |
| | | formData.value.sourceType === PurchaseSourceTypeEnum.SALE_ORDER |
| | | ) { |
| | | await formApi.setFieldValue('sourceSaleOrderId', formData.value.sourceId); |
| | | } |
| | | } |
| | | if (formData.value?.attachmentList?.length) { |
| | | const blobIds = formData.value.attachmentList.map((item) => ({ |
| | | uid: String(item.id), |
| | |
| | | const newRow = { |
| | | id: undefined, |
| | | productId: undefined, |
| | | productCode: undefined, |
| | | productUnitName: undefined, |
| | | productPrice: undefined, |
| | | count: 1, |
| | |
| | | return; |
| | | } |
| | | row.productId = item.id; |
| | | row.productCode = item.code; |
| | | row.productUnitId = item.unitMeasureId; |
| | | row.productUnitName = item.unitMeasureName; |
| | | row.productName = item.name; |
| | |
| | | import { z } from '#/adapter/form'; |
| | | import { getAccountSimpleList } from '#/api/erp/finance/account'; |
| | | import { getSimpleUserList } from '#/api/system/user'; |
| | | import { getRangePickerDefaultProps, withoutFixedColumns } from '#/utils'; |
| | | import { |
| | | getOverdueTip, |
| | | getRangePickerDefaultProps, |
| | | withoutFixedColumns, |
| | | } from '#/utils'; |
| | | import CrmCustomerSelect from '#/components/crm-customer-select.vue'; |
| | | import { MdmItemSelect } from '#/views/basicData/mdm/components'; |
| | | |
| | |
| | | valueFormat: 'YYYY-MM-DD HH:mm:ss', |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'receiptDate', |
| | | label: 'æ¶æ¬¾æ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©æ¶æ¬¾æ¥æ', |
| | | showTime: false, |
| | | format: 'YYYY-MM-DD', |
| | | valueFormat: 'YYYY-MM-DD HH:mm:ss', |
| | | }, |
| | | help: (values: { |
| | | orderTime?: Date | string; |
| | | receiptDate?: Date | string; |
| | | }) => { |
| | | const tip = getOverdueTip(values.orderTime, values.receiptDate); |
| | | return tip ? `â ${tip}ï¼è¯·ç¡®è®¤å款计å` : ''; |
| | | }, |
| | | }, |
| | | { |
| | | label: '客æ·', |
| | |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'receiptDate', |
| | | label: 'æ¶æ¬¾æ¥æ', |
| | | component: 'RangePicker', |
| | | componentProps: { |
| | | ...getRangePickerDefaultProps(), |
| | | showTime: false, |
| | | format: 'YYYY-MM-DD', |
| | | allowClear: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'supplierId', |
| | | label: '客æ·', |
| | | component: markRaw(CrmCustomerSelect), |
| | |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'receiptDate', |
| | | title: 'æ¶æ¬¾æ¥æ', |
| | | width: 140, |
| | | slots: { default: 'receiptDate' }, |
| | | }, |
| | | { |
| | | field: 'creatorName', |
| | | title: 'å建人', |
| | | minWidth: 120, |
| | |
| | | render: (val) => formatDate(val) as string, |
| | | }, |
| | | { |
| | | label: 'æ¶æ¬¾æ¥æ', |
| | | field: 'receiptDate', |
| | | render: (val) => (val ? (formatDate(val) as string) : 'æªå¡«å'), |
| | | }, |
| | | { |
| | | label: 'å计æ°é', |
| | | field: 'totalCount', |
| | | render: (val) => erpCountInputFormatter(val) || '-', |
| | |
| | | import { generateFromSaleOrder } from '#/api/mes/wm/salesnotice'; |
| | | import { $t } from '#/locales'; |
| | | import { automaticApproval } from '#/store/audit-policy'; |
| | | import { getOverdueTip, isOverdue } from '#/utils'; |
| | | |
| | | import { useGridColumns, useGridFormSchema } from './data'; |
| | | import Form from './modules/form.vue'; |
| | |
| | | </a> |
| | | <span v-else>-</span> |
| | | </template> |
| | | <template #receiptDate="{ row }"> |
| | | <Tooltip |
| | | v-if="row.receiptDate" |
| | | :title="getOverdueTip(row.orderTime, row.receiptDate)" |
| | | > |
| | | <span |
| | | :class=" |
| | | isOverdue(row.orderTime, row.receiptDate) |
| | | ? 'font-medium text-red-500' |
| | | : '' |
| | | " |
| | | > |
| | | {{ dayjs(row.receiptDate).format('YYYY-MM-DD') }} |
| | | </span> |
| | | </Tooltip> |
| | | <span v-else class="text-gray-400">æªå¡«å</span> |
| | | </template> |
| | | <template #status="{ row }"> |
| | | <Tag v-if="row.status === 0" color="default">æªæäº¤</Tag> |
| | | <Tag v-if="row.status === 15" color="processing">审æ¹ä¸</Tag> |
| | |
| | | if (item?.supplierId && formApi) { |
| | | formApi.setFieldValue('vendorId', item.supplierId); |
| | | formApi.setFieldValue('vendorName', item.supplierName); |
| | | formApi.setFieldValue('contractNo', item.contractNo ?? undefined); |
| | | } |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'contractNo', |
| | | label: 'éè´ååå·', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: 'éæ©éè´è®¢ååèªå¨å¸¦å
¥', |
| | | disabled: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'handleType', |
| | | label: 'å¤çæ¹å¼', |
| | | component: 'Select', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | placeholder: 'è¯·éæ©å¤çæ¹å¼', |
| | | allowClear: true, |
| | | options: [ |
| | | { label: '鿬¾', value: 1 }, |
| | | { label: 'æ¢è´§', value: 2 }, |
| | | ], |
| | | onChange: (value: number) => { |
| | | if (value !== 1) { |
| | | formApi?.setFieldValue('refundAmount', undefined); |
| | | } |
| | | }, |
| | | }, |
| | | rules: 'selectRequired', |
| | | help: '鿬¾ï¼å®æåèªå¨çæè´æ°å²çº¢ä»æ¬¾åï¼æ¢è´§ï¼å®æåèªå¨çæå°è´§éç¥åï¼éæ°å
¥åºå¹¶è´¨æ£ã', |
| | | }, |
| | | { |
| | | fieldName: 'refundAmount', |
| | | label: '鿬¾éé¢', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | placeholder: 'ç空åæéè´åä»·Ãéè´§æ°éèªå¨è®¡ç®', |
| | | min: 0, |
| | | precision: 2, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['handleType'], |
| | | show: (values) => values.handleType === 1, |
| | | }, |
| | | }, |
| | | { |
| | |
| | | rows: 3, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'blobIds', |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | formItemClass: 'col-span-3', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | showDescription: !isHeaderReadonly(formType), |
| | | disabled: isHeaderReadonly(formType), |
| | | }, |
| | | help: 'è´¨éé¨åèµ·éè´§æ¶ä¸ä¼ è´¨æ£æ¥åãä¸åæ ¼ç
§ççéä»¶ã', |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | |
| | | minWidth: 140, |
| | | }, |
| | | { |
| | | field: 'contractNo', |
| | | title: 'ååå·', |
| | | minWidth: 140, |
| | | showOverflow: 'tooltip', |
| | | }, |
| | | { |
| | | field: 'vendorCode', |
| | | title: 'ä¾åºåç¼ç ', |
| | | minWidth: 120, |
| | |
| | | formatter: 'formatDate', |
| | | }, |
| | | { |
| | | field: 'handleType', |
| | | title: 'å¤çæ¹å¼', |
| | | minWidth: 100, |
| | | cellRender: { |
| | | name: 'CellDict', |
| | | props: { type: DICT_TYPE.MES_WM_RETURN_VENDOR_HANDLE_TYPE }, |
| | | }, |
| | | }, |
| | | { |
| | | field: 'refundAmount', |
| | | title: '鿬¾éé¢', |
| | | minWidth: 120, |
| | | formatter: 'formatAmount2', |
| | | }, |
| | | { |
| | | field: 'redFlushPaymentNo', |
| | | title: 'å²çº¢åå·', |
| | | minWidth: 150, |
| | | showOverflow: 'tooltip', |
| | | }, |
| | | { |
| | | field: 'replacementNoticeCode', |
| | | title: 'æ¢è´§å°è´§åå·', |
| | | minWidth: 150, |
| | | showOverflow: 'tooltip', |
| | | }, |
| | | { |
| | | field: 'status', |
| | | title: 'åæ®ç¶æ', |
| | | minWidth: 110, |
| | |
| | | deleteReturnVendor, |
| | | exportReturnVendor, |
| | | getReturnVendorPage, |
| | | submitReturnVendorApproval, |
| | | } from '#/api/mes/wm/returnvendor'; |
| | | import { $t } from '#/locales'; |
| | | |
| | |
| | | /** ç¼è¾ä¾åºåéè´§å */ |
| | | function handleEdit(row: MesWmReturnVendorApi.ReturnVendor) { |
| | | formModalApi.setData({ formType: 'update', id: row.id }).open(); |
| | | } |
| | | |
| | | /** æäº¤å®¡æ¹ï¼BPMï¼éè´ -> è´¨é -> ä»åºï¼ */ |
| | | async function handleSubmitApproval(row: MesWmReturnVendorApi.ReturnVendor) { |
| | | const hideLoading = message.loading({ |
| | | content: 'æäº¤å®¡æ¹ä¸...', |
| | | duration: 0, |
| | | }); |
| | | try { |
| | | await submitReturnVendorApproval(row.id!); |
| | | message.success(`éè´§å ${row.code} å·²æäº¤å®¡æ¹`); |
| | | handleRefresh(); |
| | | } finally { |
| | | hideLoading(); |
| | | } |
| | | } |
| | | |
| | | /** æ§è¡æ£è´§ */ |
| | |
| | | }, |
| | | }, |
| | | { |
| | | label: 'æäº¤å®¡æ¹', |
| | | type: 'link', |
| | | auth: ['mes:wm-return-vendor:submit-approval'], |
| | | ifShow: row.status === MesWmReturnVendorStatusEnum.PREPARE, |
| | | popConfirm: { |
| | | title: `确认æäº¤${row.code}审æ¹ï¼æµç¨ï¼éè´ â è´¨é â ä»åº`, |
| | | confirm: handleSubmitApproval.bind(null, row), |
| | | }, |
| | | }, |
| | | { |
| | | label: 'æ§è¡æ£è´§', |
| | | type: 'link', |
| | | auth: ['mes:wm-return-vendor:update'], |
| | |
| | | danger: true, |
| | | auth: ['mes:wm-return-vendor:update'], |
| | | ifShow: |
| | | row.status === MesWmReturnVendorStatusEnum.BPM_APPROVING || |
| | | row.status === MesWmReturnVendorStatusEnum.APPROVING || |
| | | row.status === MesWmReturnVendorStatusEnum.APPROVED, |
| | | popConfirm: { |
| | |
| | | createReturnVendor, |
| | | finishReturnVendor, |
| | | getReturnVendor, |
| | | getReturnVendorAttachments, |
| | | stockReturnVendor, |
| | | submitReturnVendor, |
| | | submitReturnVendorApproval, |
| | | updateReturnVendor, |
| | | } from '#/api/mes/wm/returnvendor'; |
| | | import { $t } from '#/locales'; |
| | |
| | | await updateReturnVendor({ ...formData.value, ...data }); |
| | | originalSnapshot.value = current; |
| | | } |
| | | await submitReturnVendor(formData.value.id); |
| | | message.success('æäº¤æå'); |
| | | await submitReturnVendorApproval(formData.value.id); |
| | | message.success('æäº¤æåï¼å·²è¿å
¥éè´âè´¨éâä»åºå®¡æ¹æµç¨'); |
| | | await modalApi.close(); |
| | | emit('success'); |
| | | } finally { |
| | |
| | | ...formData.value, |
| | | returnDate: normalizeReturnDate(formData.value.returnDate), |
| | | }); |
| | | // åæ¾éä»¶ |
| | | const attachments = |
| | | (formData.value.attachmentList?.length ?? 0) > 0 |
| | | ? formData.value.attachmentList |
| | | : await getReturnVendorAttachments(data.id); |
| | | if (attachments?.length) { |
| | | await formApi.setFieldValue( |
| | | 'blobIds', |
| | | attachments.map((item) => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | })), |
| | | ); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |