refactor(upload): 重构文件上传组件以支持 blobId 存储
- 将 fileUrl 字段统一替换为 blobIds,实现附件存储的标准化
- 为 FileUpload 组件添加 valueKey、maxNumber 和 multiple 属性配置
- 移除各个模块中限制文件上传数量和类型的组件属性设置
- 重构文件上传逻辑,统一使用 system/storage API 进行文件上传
- 添加对 blobId 数组格式的支持,增强组件的数据处理能力
- 优化表单详情加载时的附件回显逻辑
- 新增 SystemStorageApi 相关类型定义和 API 方法
- 调整 ImageUpload 组件的默认配置,移除不必要的 maxNumber 限制
| | |
| | | import type { PageParam, PageResult } from '@vben/request'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace CrmFollowUpApi { |
| | | /** è·è¿è®°å½ä¿¡æ¯ */ |
| | |
| | | type: number; // è·è¿ç±»å |
| | | content: string; // è·è¿å
容 |
| | | picUrls: string[]; // å¾ç |
| | | fileUrls: string[]; // éä»¶ |
| | | blobIds?: number[]; // éä»¶ blobId å表 |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; // éä»¶å表 |
| | | nextTime: Date; // 䏿¬¡èç³»æ¶é´ |
| | | businessIds: number[]; // å
³èçåæºç¼å·æ°ç» |
| | | businesses: Business[]; // å
³èçåæºæ°ç» |
| | |
| | | import type { PageParam, PageResult } from '@vben/request'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace CrmSaleQuotationApi { |
| | | /** æ¥ä»·åä¿¡æ¯ */ |
| | |
| | | discountPercent: number; |
| | | totalPrice: number; |
| | | taxRate?: number; |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | remark?: string; |
| | | status: number; |
| | | contractId?: number; |
| | |
| | | import type { PageParam, PageResult } from '#/packages/effects/request/src'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace HrmAttendanceExceptionApi { |
| | | /** èå¤å¼å¸¸ç³è¯· */ |
| | |
| | | exceptionType?: number; |
| | | exceptionTypeName?: string; |
| | | reason?: string; |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | status?: number; |
| | | processInstanceId?: string; |
| | | remark?: string; |
| | |
| | | import type { PageParam, PageResult } from '#/packages/effects/request/src'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace HrmLeaveApi { |
| | | /** 请åç³è¯· */ |
| | |
| | | endTime?: string; |
| | | duration?: number; |
| | | reason?: string; |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | status?: number; |
| | | processInstanceId?: string; |
| | | remark?: string; |
| | |
| | | import type { PageParam, PageResult } from '#/packages/effects/request/src'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace HrmResignationApi { |
| | | /** 离èç³è¯· */ |
| | |
| | | handoverUserId?: number; |
| | | handoverUserName?: string; |
| | | handoverStatus?: number; |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | status?: number; |
| | | processInstanceId?: string; |
| | | remark?: string; |
| | |
| | | import type { PageParam, PageResult } from '#/packages/effects/request/src'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace HrmSalaryPaymentApi { |
| | | /** èªèµåæ¾å°è´¦ */ |
| | |
| | | paymentMethod?: number; |
| | | paymentTime?: string; |
| | | status?: number; |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | remark?: string; |
| | | createTime?: string; |
| | | } |
| | |
| | | import type { PageParam, PageResult } from '#/packages/effects/request/src'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace HrmTransferApi { |
| | | /** è°å²ç³è¯· */ |
| | |
| | | transferType?: number; |
| | | effectiveDate?: string; |
| | | reason?: string; |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | status?: number; |
| | | processInstanceId?: string; |
| | | remark?: string; |
| | |
| | | import type { PageParam, PageResult } from '#/packages/effects/request/src'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace MesPdDocumentApi { |
| | | /** è®¾è®¡èµæ */ |
| | |
| | | uploadUserNickname?: string; |
| | | /** ä¸ä¼ æ¶é´ */ |
| | | uploadTime?: number; |
| | | /** æä»¶URL */ |
| | | fileUrl?: string; |
| | | blobIds?: number[]; |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; |
| | | /** 夿³¨ */ |
| | | remark?: string; |
| | | /** å建æ¶é´ */ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | export namespace SystemStorageApi { |
| | | /** ä¸ä¼ æä»¶è¿åç Blob ä¿¡æ¯ */ |
| | | export interface StorageBlob { |
| | | id: number; // æä»¶ ID |
| | | resourceKey?: string; // èµæºå¯ä¸æ è¯ |
| | | contentType?: string; // MIME ç±»å |
| | | originalFilename?: string; // åæä»¶å |
| | | uidFilename?: string; // å¯ä¸æä»¶å |
| | | byteSize?: number; // æä»¶å¤§å°ï¼åèï¼ |
| | | path?: string; // æä»¶ç¸å¯¹è·¯å¾ |
| | | previewURL?: string; // é¢è§å°å |
| | | url?: string; // æä»¶è®¿é® URLï¼å
¼å®¹åæ®µï¼ |
| | | name?: string; // åæä»¶åï¼å
¼å®¹åæ®µï¼ |
| | | downloadURL?: string; // ä¸è½½å°å |
| | | storageAttachmentId?: number; // å
³èçéä»¶ ID |
| | | application?: string; // æä»¶ç¨é |
| | | } |
| | | |
| | | /** éä»¶ç»å®è¯·æ± */ |
| | | export interface AttachmentBindReq { |
| | | application?: string; // æä»¶ç¨é |
| | | recordType: string; // å
³èè®°å½ç±»å |
| | | recordId: number; // å
³èè®°å½ ID |
| | | blobItems: { blobId: number; application?: string }[]; // å¾
ç»å®çæä»¶å表 |
| | | } |
| | | |
| | | /** éä»¶å表æ¥è¯¢åæ° */ |
| | | export interface AttachmentListParams { |
| | | recordType: string; |
| | | recordId: number; |
| | | application?: string; |
| | | } |
| | | } |
| | | |
| | | /** ä¸ä¼ æä»¶ */ |
| | | export function uploadFile(files: globalThis.File[]) { |
| | | const formData = new FormData(); |
| | | files.forEach((file) => formData.append('files', file)); |
| | | return requestClient.post<SystemStorageApi.StorageBlob[]>( |
| | | '/system/storage-blob/upload', |
| | | formData, |
| | | ); |
| | | } |
| | | |
| | | /** æ¥è¯¢éä»¶å表 */ |
| | | export function listAttachments(params: SystemStorageApi.AttachmentListParams) { |
| | | return requestClient.get<SystemStorageApi.StorageBlob[]>( |
| | | '/system/storage-attachment/list', |
| | | { params }, |
| | | ); |
| | | } |
| | | |
| | | /** ç»å®éä»¶å°ä¸å¡è®°å½ */ |
| | | export function bindAttachments(data: SystemStorageApi.AttachmentBindReq) { |
| | | return requestClient.post<boolean>( |
| | | '/system/storage-attachment/bind', |
| | | data, |
| | | ); |
| | | } |
| | | |
| | | /** æ¹éå é¤éä»¶ */ |
| | | export function deleteAttachments(ids: number[]) { |
| | | return requestClient.delete<boolean>('/system/storage-attachment/delete', { |
| | | data: ids, |
| | | }); |
| | | } |
| | |
| | | returnText: false, |
| | | showDescription: false, |
| | | showDownloadIcon: true, |
| | | valueKey: 'url', |
| | | valuePrefix: '', |
| | | }); |
| | | const emit = defineEmits([ |
| | | 'change', |
| | |
| | | }; |
| | | } else if (item && isObject(item)) { |
| | | return item; |
| | | } else if (item && (typeof item === 'number' || typeof item === 'string')) { |
| | | return { |
| | | uid: `${-i}`, |
| | | name: `æä»¶ ${String(item)}`, |
| | | status: UploadResultStatus.DONE, |
| | | url: item, |
| | | response: { [props.valueKey]: item }, |
| | | } as UploadFile; |
| | | } |
| | | return null; |
| | | }) |
| | |
| | | if (item?.response && props?.resultField) { |
| | | return item?.response; |
| | | } |
| | | return item?.url || item?.response?.url || item?.response; |
| | | const val = |
| | | item?.response?.[props.valueKey] ?? |
| | | item?.[props.valueKey] ?? |
| | | item?.url ?? |
| | | item?.response?.url ?? |
| | | item?.response; |
| | | return props.valuePrefix ? `${props.valuePrefix}${val}` : val; |
| | | }); |
| | | |
| | | // å个æä»¶çæ
åµï¼æ ¹æ®è¾å
¥åæ°ç±»åå³å®è¿åæ ¼å¼ |
| | |
| | | helpText?: string; |
| | | listType?: UploadListType; |
| | | maxNumber?: number; // æå¤§æ°éçæä»¶ï¼Infinityä¸éå¶ |
| | | modelValue?: string | string[]; // v-model æ¯æ |
| | | modelValue?: string | string[] | number[]; // v-model æ¯æ |
| | | maxSize?: number; // æä»¶æå¤§å¤å°MB |
| | | multiple?: boolean; // æ¯å¦æ¯æå¤é |
| | | resultField?: string; // support xxx.xxx.xx |
| | | returnText?: boolean; // æ¯å¦è¿åæä»¶ææ¬å
容 |
| | | showDescription?: boolean; // æ¯å¦æ¾ç¤ºä¸é¢çæè¿° |
| | | showDownloadIcon?: boolean; // æ¯å¦æ¾ç¤ºä¸è½½æé® |
| | | value?: string | string[]; |
| | | value?: string | string[] | number[]; |
| | | valueKey?: string; // è¿åå¼çåæ®µåï¼é»è®¤ 'url'ï¼è®¾ä¸º 'id' æ¶è¿å blobId |
| | | valuePrefix?: string; // valueKey è¿åå¼çåç¼ |
| | | } |
| | |
| | | import type { Ref } from 'vue'; |
| | | |
| | | import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file'; |
| | | import type { AxiosProgressEvent } from '#/api/infra/file'; |
| | | |
| | | import { computed, unref } from 'vue'; |
| | | |
| | | import { useAppConfig } from '@vben/hooks'; |
| | | import { $t } from '@vben/locales'; |
| | | |
| | | import { createFile, getFilePresignedUrl, uploadFile } from '#/api/infra/file'; |
| | | import { baseRequestClient } from '#/api/request'; |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); |
| | | |
| | |
| | | // æ¯å¦ä½¿ç¨å端ç´è¿ä¸ä¼ |
| | | const isClientUpload = |
| | | UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE; |
| | | // éåElUploadä¸ä¼ æ¹æ³ |
| | | // éåä¸ä¼ æ¹æ³ï¼ç»ä¸èµ° system 模å Storage API |
| | | async function httpRequest( |
| | | file: File, |
| | | onUploadProgress?: AxiosProgressEvent, |
| | | ) { |
| | | // 模å¼ä¸ï¼å端ä¸ä¼ |
| | | if (isClientUpload) { |
| | | // 1.1 çææä»¶åç§° |
| | | const fileName = await generateFileName(file); |
| | | // 1.2 è·åæä»¶é¢ç¾åå°å |
| | | const presignedInfo = await getFilePresignedUrl(fileName, directory); |
| | | // 1.3 ä¸ä¼ æä»¶ |
| | | return baseRequestClient |
| | | .put(presignedInfo.uploadUrl, file, { |
| | | headers: { |
| | | 'Content-Type': file.type, |
| | | }, |
| | | }) |
| | | .then(() => { |
| | | // 1.4. è®°å½æä»¶ä¿¡æ¯å°å端ï¼å¼æ¥ï¼ |
| | | createFile0(presignedInfo, file); |
| | | // éç¥æåï¼æ°æ®æ ¼å¼ä¿æä¸å端ä¸ä¼ çè¿åç»æä¸è´ |
| | | return { url: presignedInfo.url }; |
| | | }); |
| | | } else { |
| | | // 模å¼äºï¼å端ä¸ä¼ |
| | | return uploadFile({ file, directory }, onUploadProgress); |
| | | } |
| | | const formData = new FormData(); |
| | | formData.append('files', file); |
| | | const blobs = await requestClient.post('/system/storage-blob/upload', formData, { |
| | | onUploadProgress, |
| | | }); |
| | | const blob = Array.isArray(blobs) ? blobs[0] : blobs; |
| | | return blob ? { url: blob.url || blob.previewURL, name: blob.name, id: blob.id } : {}; |
| | | } |
| | | |
| | | return { |
| | |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ä¸ä¼ URL |
| | | * è·å¾ä¸ä¼ URLï¼å
¼å®¹æ§çï¼å®é
è°ç¨èµ° httpRequestï¼ |
| | | */ |
| | | export function getUploadUrl(): string { |
| | | return `${apiURL}/infra/file/upload`; |
| | | } |
| | | |
| | | /** |
| | | * å建æä»¶ä¿¡æ¯ |
| | | * |
| | | * @param vo æä»¶é¢ç¾åä¿¡æ¯ |
| | | * @param file æä»¶ |
| | | */ |
| | | function createFile0( |
| | | vo: InfraFileApi.FilePresignedUrlRespVO, |
| | | file: File, |
| | | ): InfraFileApi.File { |
| | | const fileVO = { |
| | | configId: vo.configId, |
| | | url: vo.url, |
| | | path: vo.path, |
| | | name: file.name, |
| | | type: file.type, |
| | | size: file.size, |
| | | }; |
| | | createFile(fileVO); |
| | | return fileVO; |
| | | } |
| | | |
| | | /** |
| | | * çææä»¶åç§°ï¼ä½¿ç¨ç®æ³SHA256ï¼ |
| | | * |
| | | * @param file è¦ä¸ä¼ çæä»¶ |
| | | */ |
| | | async function generateFileName(file: File) { |
| | | // // 读åæä»¶å
容 |
| | | // const data = await file.arrayBuffer(); |
| | | // const wordArray = CryptoJS.lib.WordArray.create(data); |
| | | // // 计ç®SHA256 |
| | | // const sha256 = CryptoJS.SHA256(wordArray).toString(); |
| | | // // æ¼æ¥åç¼ |
| | | // const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.'))); |
| | | // return `${sha256}${ext}`; |
| | | return file.name; |
| | | return `${apiURL}/system/storage-blob/upload`; |
| | | } |
| | |
| | | component: 'ImageUpload', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrls', |
| | | fieldName: 'blobIds', |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'contactIds', |
| | |
| | | try { |
| | | // è®¾ç½®å° values |
| | | await formApi.setValues(data); |
| | | if (data.attachmentList?.length) { |
| | | await formApi.setFieldValue('blobIds', data.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | }))); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | placeholder: '请ä¸ä¼ éä»¶', |
| | | maxNumber: 5, |
| | | maxSize: 20, |
| | | accept: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'jpg', 'png'], |
| | | disabled: formType === 'detail', |
| | | }, |
| | | formItemClass: 'col-span-2', |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | maxSize: 10, |
| | | accept: [ |
| | | 'pdf', |
| | | 'doc', |
| | | 'docx', |
| | | 'xls', |
| | | 'xlsx', |
| | | 'txt', |
| | | 'jpg', |
| | | 'jpeg', |
| | | 'png', |
| | | ], |
| | | showDescription: formType !== 'detail', |
| | | disabled: formType === 'detail', |
| | | }, |
| | |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'blobIds', |
| | | label: 'éä»¶', |
| | | component: 'FileUpload', |
| | | formItemClass: 'col-span-2', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | component: 'Textarea', |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | await formApi.setValues(await getAttendanceException(data.id)); |
| | | const detail = await getAttendanceException(data.id); |
| | | await formApi.setValues(detail); |
| | | if (detail.attachmentList?.length) { |
| | | await formApi.setFieldValue('blobIds', detail.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | }))); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: 'éä»¶', |
| | | component: 'Input', |
| | | component: 'FileUpload', |
| | | formItemClass: 'col-span-2', |
| | | componentProps: { |
| | | placeholder: '请ä¸ä¼ éä»¶', |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | }, |
| | | }, |
| | | { |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | await formApi.setValues(await getLeave(data.id)); |
| | | const detail = await getLeave(data.id); |
| | | await formApi.setValues(detail); |
| | | if (detail.attachmentList?.length) { |
| | | await formApi.setFieldValue('blobIds', detail.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | }))); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: 'éä»¶', |
| | | component: 'Input', |
| | | component: 'FileUpload', |
| | | formItemClass: 'col-span-2', |
| | | componentProps: { |
| | | placeholder: '请ä¸ä¼ éä»¶', |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | }, |
| | | }, |
| | | { |
| | |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | await formApi.setValues(await getResignation(data.id)); |
| | | const detail = await getResignation(data.id); |
| | | await formApi.setValues(detail); |
| | | if (detail.attachmentList?.length) { |
| | | await formApi.setFieldValue('blobIds', detail.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | }))); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: 'éä»¶', |
| | | component: 'Input', |
| | | component: 'FileUpload', |
| | | formItemClass: 'col-span-2', |
| | | componentProps: { |
| | | placeholder: '请ä¸ä¼ éä»¶', |
| | | valueKey: 'id', |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | }, |
| | | }, |
| | | { |
| | |
| | | const transfer = await getTransfer(data.id); |
| | | currentEmployeeId.value = transfer.employeeId; |
| | | await formApi.setValues(transfer); |
| | | if (transfer.attachmentList?.length) { |
| | | await formApi.setFieldValue('blobIds', transfer.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | }))); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | |
| | | fieldName: 'avatar', |
| | | label: 'é¢é头å', |
| | | component: 'ImageUpload', |
| | | componentProps: { |
| | | maxNumber: 1 |
| | | }, |
| | | rules: 'required' |
| | | }, |
| | | { |
| | |
| | | fieldName: 'coverUrl', |
| | | label: 'å°é¢å¾', |
| | | component: 'ImageUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'summary', |
| | |
| | | fieldName: 'icon', |
| | | label: 'å°é¢', |
| | | component: 'ImageUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'name', |
| | |
| | | fieldName: 'url', |
| | | label: '表æ
å¾', |
| | | component: 'ImageUpload', |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | }, |
| | | rules: 'required', |
| | | }, |
| | | { |
| | |
| | | label: 'å¾ç', |
| | | component: markRaw(ImageUpload), |
| | | componentProps: { |
| | | maxNumber: 1, |
| | | showDescription: false, |
| | | }, |
| | | }, |
| | |
| | | rules: 'required', |
| | | }, |
| | | { |
| | | fieldName: 'fileUrl', |
| | | fieldName: 'blobIds', |
| | | label: 'æä»¶', |
| | | component: markRaw(FileUpload), |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | directory: 'mes/pd', |
| | | maxNumber: 1, |
| | | onChange: async (url: string) => { |
| | | if (url) { |
| | | await formApi?.setFieldValue('fileUrl', url); |
| | | } |
| | | }, |
| | | maxNumber: 10, |
| | | multiple: true, |
| | | }, |
| | | }, |
| | | { |
| | |
| | | try { |
| | | const detail = await getPdDocument(data.id); |
| | | await formApi.setValues(detail); |
| | | if (detail.attachmentList?.length) { |
| | | await formApi.setFieldValue('blobIds', detail.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | url: item.url || '', |
| | | status: 'done', |
| | | id: item.id, |
| | | }))); |
| | | } |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |