refactor(crm): 重构文件上传功能,替换原有的fileUrls字段为统一的StorageAttachmentApi
- 移除CrmFollowUpCreateReqBO中的fileUrls字段
- 在CrmFollowUpRecordController中引入StorageAttachmentApi并实现附件列表查询
- 更新CrmFollowUpRecordDO移除fileUrls字段
- 修改CrmFollowUpRecordRespVO使用attachmentList替代fileUrls
- 调整CrmFollowUpRecordSaveReqVO增加blobIds字段
- 在CrmFollowUpRecordServiceImpl中集成StorageAttachmentApi进行附件绑定和删除
- 更新CrmSaleQuotationController获取附件列表功能
- 从CrmSaleQuotationDO移除fileUrl字段
- 修改CrmSaleQuotationRespVO使用attachmentList
- 调整CrmSaleQuotationSaveReqVO使用blobIds替代fileUrl
- 在CrmSaleQuotationServiceImpl中集成附件绑定逻辑
- 移除ERP模块中各DO的fileUrl字段
- 移除Hrm模块中AttendanceException相关的fileUrl字段
- 更新文档file_upload_guide.md说明统一使用Storage API
- 从数据库脚本移除各模块的file_url字段
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æä»¶ä¸ä¼ è§å |
| | | |
| | | ## æ ¸å¿ååï¼AI å¿
é¡»ä¸¥æ ¼éµå®ï¼ |
| | | |
| | | **æææä»¶ä¸ä¼ å¿
须走 `yudao-module-system` 模åç Storage API + Attachment ä¸é´è¡¨æºå¶ã** |
| | | |
| | | **ç¦æ¢å¨ä»»ä½ä¸å¡æ¨¡åèªè¡è®¾è®¡æä»¶ä¸ä¼ æ¹æ¡ï¼å
æ¬ä½ä¸éäºï¼æ·»å `file_url` åãæ°å¢ upload æ¥å£ã注å
¥ FileApiã** |
| | | |
| | | ## æä»¶ä¸ä¸å¡çå
³èæ¹å¼ |
| | | |
| | | æä»¶ä¸ä¸å¡è®°å½çå
³è**åªè½éè¿ `system_storage_attachment` ä¸é´è¡¨**ï¼ä¸å
许å¨ä¸å¡è¡¨ä¸æ·»å `file_url`ã`file_urls`ã`attachment_url` çåç¬¦ä¸²åæ®µå卿件å°åã |
| | | |
| | | å
³èæµç¨ï¼ |
| | | 1. å端è°ç¨ `POST /system/storage-blob/upload` ä¸ä¼ æä»¶ â è·å¾ `blobId` |
| | | 2. å端è°ç¨ `POST /system/storage-attachment/bind` ç»å®æä»¶å°ä¸å¡è®°å½ï¼ä¼ å
¥ `recordType` + `recordId` + `blobItems`ï¼ |
| | | 3. å端è°ç¨ `GET /system/storage-attachment/list` æ¥è¯¢éä»¶ |
| | | 4. å端è°ç¨ `DELETE /system/storage-attachment/delete` å é¤éä»¶ |
| | | |
| | | ## æ£ç¡®æ¥å£ï¼system 模åï¼ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/system/storage-blob/upload` | ä¸ä¼ æä»¶ï¼`files` åæ°ï¼multipartï¼ | |
| | | | POST | `/system/storage-blob/public-upload` | å
Œ
±æä»¶ä¸ä¼ ï¼æ°¸ä¹
ææï¼ | |
| | | | GET | `/system/storage-blob/preview/{fileName}` | æä»¶é¢è§ | |
| | | | GET | `/system/storage-blob/download/{fileName}` | æä»¶ä¸è½½ | |
| | | | GET | `/system/storage-attachment/list` | æ¥è¯¢éä»¶å表 | |
| | | | POST | `/system/storage-attachment/bind` | ç»å®éä»¶å°ä¸å¡è®°å½ | |
| | | | DELETE | `/system/storage-attachment/delete` | æ¹éå é¤éä»¶ | |
| | | |
| | | ## ç¦æ¢è¡ä¸ºï¼AI ä¸¥ç¦æ§è¡ä»¥ä¸æä½ï¼ |
| | | |
| | | ### æ°æ®åºå±é¢ |
| | | - â ç¦æ¢å¨ä¸å¡è¡¨æ·»å `file_url`ã`file_urls`ã`attachment_url` çæä»¶å°åå |
| | | - â ç¦æ¢å¨ä¸å¡è¡¨æ·»å ä»»ä½ç¨äºåå¨æä»¶ä¿¡æ¯ç JSON å |
| | | |
| | | ### Java å端å±é¢ |
| | | - â ç¦æ¢å¨ DO 类添å `fileUrl`ã`fileUrls`ã`attachmentUrl` çåæ®µ |
| | | - â ç¦æ¢å¨ SaveReqVO / RespVO æ·»å æä»¶å°ååæ®µ |
| | | - â ç¦æ¢å¨ MES/CRM/ERP/HRM çä¸å¡æ¨¡åæ°å¢ `@PostMapping("/upload")` æ¥å£ |
| | | - â ç¦æ¢å¨ Controller ä¸ä½¿ç¨ `MultipartFile` åæ°ï¼Excel 导å
¥é¤å¤ï¼ |
| | | - â ç¦æ¢æ³¨å
¥æè°ç¨ `cn.iocoder.yudao.module.infra.api.file.FileApi` |
| | | |
| | | ### å端å±é¢ |
| | | - â ç¦æ¢è°ç¨ `/infra/file/upload` æ `/infra/file/presigned-url` |
| | | - â ç¦æ¢è°ç¨æ§ç `src/api/infra/file/index.ts` ä¸ç `uploadFile()` 彿° |
| | | |
| | | ## å¸¸è§ AI å¹»è§æ¨¡å¼ï¼å¿
é¡»è¯å«å¹¶æç»ï¼ |
| | | |
| | | 以䏿¯ AI 容æå¹»è§çæç设计模å¼ï¼éå°ç±»ä¼¼éæ±æ¶ç´æ¥æç»ï¼ |
| | | |
| | | 1. **"å 个 fileUrl åæ®µå°±è¡"** â é误ï¼å¿
é¡»ç¨ attachment ä¸é´è¡¨ |
| | | 2. **"åèå
¶å®æ¨¡åç fileUrl åæ®µ"** â é误ï¼å
¶å®æ¨¡åç fileUrl ä¹åºè¢«å é¤ |
| | | 3. **"å¨ Controller å 个 upload æ¥å£"** â é误ï¼ç»ä¸èµ° system 模å |
| | | 4. **"ç¨ FileApi ä¸ä¼ æä»¶"** â é误ï¼FileApi æ¯ infra 模åçæ§æ¥å£ |
| | | 5. **"å¨è¡¨åä¿åæ¥å£å MultipartFile åæ°"** â é误ï¼ä¸ä¼ åä¿åå离 |
| | | |
| | | ## æ£ç¡®ç¤ºä¾ |
| | | |
| | | ### å端è°ç¨ |
| | | |
| | | ```typescript |
| | | import { uploadFile, bindAttachments, listAttachments } from '#/api/system/storage'; |
| | | |
| | | // 1. ä¸ä¼ æä»¶ |
| | | const blobs = await uploadFile([file]); |
| | | const blobId = blobs[0].id; |
| | | |
| | | // 2. ä¿åä¸å¡è®°å½åï¼ç»å®éä»¶ |
| | | await bindAttachments({ |
| | | application: 'file', |
| | | recordType: 'erp_purchase_order', |
| | | recordId: savedRecord.id, |
| | | blobItems: [{ blobId }], |
| | | }); |
| | | |
| | | // 3. æ¥è¯¢éä»¶ |
| | | const attachments = await listAttachments({ |
| | | recordType: 'erp_purchase_order', |
| | | recordId: savedRecord.id, |
| | | }); |
| | | ``` |
| | | |
| | | ### recordType å½åè§è |
| | | |
| | | æ ¼å¼ï¼`{模ååç¼}_{ä¸å¡è¡¨å}` |
| | | |
| | | | 模å | recordType | |
| | | |------|------------| |
| | | | ERP éè´è®¢å | `erp_purchase_order` | |
| | | | ERP éè´ç³è¯· | `erp_purchase_request` | |
| | | | ERP éå®è®¢å | `erp_sale_order` | |
| | | | ERP æ¶æ¬¾å | `erp_finance_receipt` | |
| | | | ERP 仿¬¾å | `erp_finance_payment` | |
| | | | HRM 请å | `hrm_leave_application` | |
| | | | HRM 离è | `hrm_resignation_application` | |
| | | | HRM è°å¨ | `hrm_transfer_application` | |
| | | | MES éè´è®¢å | `mes_purchase_order` | |
| | | | MES å·¥å | `mes_pro_work_order` | |
| | | | CRM å®¢æ· | `crm_customer` | |
| | | |
| | | ## AI èªæ¥æ¸
å |
| | | |
| | | å¨å®ç°ä»»ä½æä»¶ä¸ä¼ ç¸å
³éæ±åï¼éé¡¹ç¡®è®¤ï¼ |
| | | |
| | | - [ ] æ¯å¦ä½¿ç¨äº `/system/storage-blob/upload` ä¸ä¼ ï¼ |
| | | - [ ] æ¯å¦ä½¿ç¨äº `/system/storage-attachment/bind` å
³èï¼ |
| | | - [ ] æ¯å¦æ²¡æå¨ä¸å¡è¡¨ä¸æ·»å æä»¶å°ååï¼ |
| | | - [ ] æ¯å¦æ²¡æå¨ DO/VO 䏿·»å æä»¶å°ååæ®µï¼ |
| | | - [ ] æ¯å¦æ²¡æå建æ°ç upload Controller æ¥å£ï¼ |
| | | - [ ] æ¯å¦æ²¡æä½¿ç¨ infra 模åç FileApiï¼ |
| | | |
| | | ä»¥ä¸ 6 项å
¨é¨ä¸º"æ¯"æå¯ç»§ç»ã |
| | | |
| | | ## 为ä»ä¹ |
| | | |
| | | - åå¨é
ç½®ï¼æ¬å°/S3ï¼å¨ system 模åç»ä¸ç®¡ç |
| | | - éä»¶ç»å®æºå¶ï¼storage-attachmentï¼æä¾ `recordType + recordId` çæ åå
³èæ¹å¼ï¼æ¯æå¤æä»¶ãç¨éåç±» |
| | | - infra 模åç `/infra/file/*` æ¯æ§çæ¥å£ï¼å卿件ä¸ä¸å¡è®°å½æ æ³å
³èçé®é¢ |
| | | - ä¸å¡è¡¨åå¨ file_url åç¬¦ä¸²æ æ³æ¯æå¤æä»¶ï¼ä¸æä»¶ä¸ä¸å¡è®°å½ä¹é´ç¼ºä¹æ ååçå
³è管ç |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æä»¶ä¸ä¼ æ¹é - å端èè°æ¹æ¡ |
| | | |
| | | ## åç«¯åæ´æè¦ |
| | | |
| | | æææ¨¡åçæä»¶ä¸ä¼ å·²ä» `fileUrl` åç¬¦ä¸²åæ®µæ¹ä¸º `system_storage_attachment` ä¸é´è¡¨æºå¶ï¼ |
| | | |
| | | | åæ´ | æ§æ¹å¼ | æ°æ¹å¼ | |
| | | |------|--------|--------| |
| | | | ä¸ä¼ | ç´æ¥å fileUrl | POST `/system/storage-blob/upload` â è·å blobId | |
| | | | ä¿å | SaveReqVO.fileUrl | SaveReqVO.blobIds (List\<Long\>) | |
| | | | æ¥è¯¢ | RespVO.fileUrl | RespVO.attachmentList (List\<StorageBlob\>) | |
| | | | å é¤ | æ | å端 Service èªå¨åæ¥å é¤éä»¶ | |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | ### HRM 模åï¼5个页é¢ï¼ |
| | | |
| | | | é¡µé¢ | ç®å½ | recordType | |
| | | |------|------|------------| |
| | | | 请åç³è¯· | `src/views/hrm/leave/` | `hrm_leave_application` | |
| | | | 离èç³è¯· | `src/views/hrm/resignation/` | `hrm_resignation_application` | |
| | | | è°å²ç³è¯· | `src/views/hrm/transfer/` | `hrm_transfer_application` | |
| | | | èå¤å¼å¸¸ç³è¯· | `src/views/hrm/attendance/exception/` | `hrm_attendance_exception` | |
| | | | èªèµåæ¾ | `src/views/hrm/salary/payment/` | `hrm_salary_payment` | |
| | | |
| | | ### CRM 模åï¼2个页é¢ï¼ |
| | | |
| | | | é¡µé¢ | ç®å½ | recordType | |
| | | |------|------|------------| |
| | | | é宿¥ä»·å | `src/views/crm/saleQuotation/` | `crm_sale_quotation` | |
| | | | è·è¿è®°å½ | `src/views/crm/followup/` | `crm_follow_up_record` | |
| | | |
| | | ### MES 模åï¼1个页é¢ï¼ |
| | | |
| | | | é¡µé¢ | ç®å½ | recordType | |
| | | |------|------|------------| |
| | | | è®¾è®¡èµæ | `src/views/mes/pd/project/modules/document-form.vue` | `mes_pd_document` | |
| | | |
| | | --- |
| | | |
| | | ## API 说æ |
| | | |
| | | ### éç¨æä»¶ APIï¼å·²æï¼æ éæ°å¢ï¼ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/system/storage-blob/upload` | ä¸ä¼ æä»¶ï¼multipartï¼`files` åæ°ï¼ | |
| | | | GET | `/system/storage-attachment/list` | æ¥è¯¢éä»¶å表ï¼`recordType` + `recordId`ï¼ | |
| | | | POST | `/system/storage-attachment/bind` | ç»å®éä»¶å°ä¸å¡è®°å½ | |
| | | | DELETE | `/system/storage-attachment/delete` | æ¹éå é¤éä»¶ | |
| | | |
| | | å端已æå¯¹åºç API å°è£
å¨ `src/api/system/storage/index.ts`ï¼ |
| | | - `uploadFile(files)` â `StorageBlob[]` |
| | | - `listAttachments({ recordType, recordId })` â `StorageBlob[]` |
| | | - `bindAttachments({ application, recordType, recordId, blobItems })` â `boolean` |
| | | - `deleteAttachments(ids)` â `boolean` |
| | | |
| | | ### åæ¥å£ SaveReqVO æ°å¢å段 |
| | | |
| | | æææ¨¡åçå建/æ´æ°æ¥å£åæ°å¢ `blobIds` åæ°ï¼ |
| | | |
| | | | æ¥å£ | æ°å¢åæ° | |
| | | |------|----------| |
| | | | æææ¨¡å create/update | `blobIds: number[]` | |
| | | |
| | | ### åæ¥å£ RespVO æ°å¢å段 |
| | | |
| | | æææ¨¡åç详æ
æ¥è¯¢æ¥å£åæ°å¢ `attachmentList` åæ®µï¼ |
| | | |
| | | | æ¥å£ | æ°å¢å段 | ç±»å | |
| | | |------|----------|------| |
| | | | GET /getï¼è¯¦æ
ï¼ | `attachmentList` | `StorageBlob[]` | |
| | | |
| | | **StorageBlob ç»æï¼** |
| | | ```typescript |
| | | interface StorageBlob { |
| | | id: number; // blob ID |
| | | url?: string; // æä»¶è®¿é® URL |
| | | previewURL?: string; // é¢è§å°å |
| | | name?: string; // åæä»¶å |
| | | downloadURL?: string; // ä¸è½½å°å |
| | | application?: string; // æä»¶ç¨é |
| | | storageAttachmentId?: number; // éä»¶å
³è ID |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## åç«¯ä¿®æ¹æ¥éª¤ï¼æ¯ä¸ªæ¨¡åéç¨ï¼ |
| | | |
| | | ### æ¥éª¤ 1ï¼ä¿®æ¹ API ç±»åå®ä¹ |
| | | |
| | | ä¿®æ¹ `src/api/{module}/index.ts` ä¸çæ¥å£å®ä¹ï¼ |
| | | |
| | | ```typescript |
| | | // â
å¼å
¥ StorageBlob ç±»å |
| | | import type { SystemStorageApi } from '#/api/system/storage'; |
| | | |
| | | export namespace XxxApi { |
| | | export interface Xxx { |
| | | // ... å
¶ä»å段ä¸å ... |
| | | |
| | | // â å é¤ï¼fileUrl?: string; |
| | | // â
æ°å¢ï¼ |
| | | blobIds?: number[]; // ä¿åæ¶ä¼ å
¥çéä»¶ blobId å表 |
| | | attachmentList?: SystemStorageApi.StorageBlob[]; // æ¥è¯¢æ¶è¿åçéä»¶å表 |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | æ¶åçæä»¶ï¼ |
| | | |
| | | | æä»¶ | å é¤å段 | æ°å¢å段 | |
| | | |------|---------|---------| |
| | | | `src/api/hrm/leave/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | | `src/api/hrm/resignation/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | | `src/api/hrm/transfer/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | | `src/api/hrm/attendance/exception/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | | `src/api/hrm/salary/payment/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | | `src/api/crm/saleQuotation/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | | `src/api/crm/followup/index.ts` | `fileUrls` | `blobIds`, `attachmentList` | |
| | | | `src/api/mes/pd/document/index.ts` | `fileUrl` | `blobIds`, `attachmentList` | |
| | | |
| | | ### æ¥éª¤ 2ï¼ä¿®æ¹è¡¨å页é¢ï¼form.vueï¼ |
| | | |
| | | **æ°å¢/ç¼è¾æ¨¡å¼**éè¦æ·»å æä»¶ä¸ä¼ ç»ä»¶ï¼æµç¨ï¼ |
| | | |
| | | ``` |
| | | ç¨æ·éæ©æä»¶ â uploadFile(files) ä¸ä¼ â è·å¾ blobId[] |
| | | â ä¿åæ¶å° blobIds åç»å端 â å端èªå¨ bindAttachments |
| | | ``` |
| | | |
| | | æ ¸å¿ä»£ç 模å¼ï¼ |
| | | |
| | | ```vue |
| | | <script lang="ts" setup> |
| | | import { ref } from 'vue'; |
| | | import { uploadFile } from '#/api/system/storage'; |
| | | import type { UploadChangeParam } from 'ant-design-vue'; |
| | | |
| | | const blobIds = ref<number[]>([]); |
| | | const fileList = ref([]); |
| | | |
| | | // æä»¶ä¸ä¼ å¤ç |
| | | async function handleUpload(info: UploadChangeParam) { |
| | | if (info.file.status === 'done') { |
| | | // æä»¶ä¸ä¼ æåï¼æ¶é blobId |
| | | const blobs = info.file.response; |
| | | if (blobs?.length) { |
| | | blobIds.value.push(blobs[0].id); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ä¿åæ¶ |
| | | async function handleSave() { |
| | | const data = await formApi.getValues(); |
| | | data.blobIds = blobIds.value; // å° blobIds ä¼ ç»å端 |
| | | await createXxx(data); |
| | | } |
| | | |
| | | // ç¼è¾æ¶åæ¾å·²æéä»¶ |
| | | async function loadDetail(id: number) { |
| | | const detail = await getXxx(id); |
| | | if (detail.attachmentList) { |
| | | fileList.value = detail.attachmentList.map(item => ({ |
| | | uid: String(item.id), |
| | | name: item.name || '', |
| | | status: 'done', |
| | | url: item.url, |
| | | })); |
| | | blobIds.value = detail.attachmentList.map(item => item.id); |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <a-upload |
| | | v-model:file-list="fileList" |
| | | :action="`${baseURL}/system/storage-blob/upload`" |
| | | multiple |
| | | @change="handleUpload" |
| | | > |
| | | <a-button> |
| | | <upload-outlined /> |
| | | ä¸ä¼ éä»¶ |
| | | </a-button> |
| | | </a-upload> |
| | | </template> |
| | | ``` |
| | | |
| | | **æè
使ç¨å·²ç»å°è£
ç uploadFile 彿°é
åæå¨ä¸ä¼ ï¼** |
| | | - æ¨èæ¹å¼ï¼å¨æäº¤åå
è°ç¨ `uploadFile()` ä¸ä¼ æææä»¶ï¼æ¿å° blobIds åä¸èµ·æäº¤ |
| | | - å¤éæ¹å¼ï¼ä½¿ç¨ a-upload ç»ä»¶çèªå¨ä¸ä¼ ï¼å¨ `@change` 䏿¶é blobId |
| | | |
| | | ### æ¥éª¤ 3ï¼ä¿®æ¹è¯¦æ
å±ç¤º |
| | | |
| | | å¨è¯¦æ
/æ¥ç模å¼ä¸å±ç¤ºéä»¶å表ï¼åªè¯»ï¼ï¼ |
| | | |
| | | ```vue |
| | | <template> |
| | | <!-- éä»¶å±ç¤º --> |
| | | <div v-if="attachmentList?.length"> |
| | | <div class="text-gray-500 mb-2">éä»¶</div> |
| | | <div v-for="item in attachmentList" :key="item.id"> |
| | | <a :href="item.url" target="_blank">{{ item.name }}</a> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## åæ®µå±ç¤ºè§å |
| | | |
| | | | åæ®µ | å±ç¤ºä½ç½® | 说æ | |
| | | |------|----------|------| |
| | | | `blobIds` | 表åï¼ä¸å±ç¤ºï¼ | éèåæ®µï¼ä¿åæ¶ä¼ ç»å端 | |
| | | | `attachmentList` | 详æ
页ã表åç¼è¾åæ¾ | æ¾ç¤ºæä»¶åè¡¨ï¼æ¯æé¢è§/ä¸è½½ | |
| | | |
| | | ## ä¸å¡è§å说æ |
| | | |
| | | | åºæ¯ | è§å | |
| | | |------|------| |
| | | | åå»ºæ¶ | å
è°ç¨ `uploadFile()` ä¸ä¼ æä»¶æ¿ blobIdï¼åæ blobIds ä¼ ç» create æ¥å£ | |
| | | | æ´æ°æ¶ | å¯ä»¥æ°å¢/å é¤éä»¶ï¼å端æ¶å° blobIds ä¸ä¸º null æ¶å
å åç» | |
| | | | æ¥çæ¶ | 详æ
æ¥å£è¿å `attachmentList`ï¼ç´æ¥æ¸²æ | |
| | | | å 餿¶ | å端èªå¨å¤çéä»¶å é¤ï¼å端æ éé¢å¤æä½ | |
| | | | å表/å页 | ä¸è¿å `attachmentList`ï¼æ§è½èèï¼ï¼ä»
详æ
æ¥å£è¿å | |
| | | |
| | | ## 忍¡åç¹æ®è¯´æ |
| | | |
| | | ### HRM 请å/离è/è°å² |
| | | - 表å页ï¼`src/views/hrm/xxx/modules/form.vue` |
| | | - è¿ä¸ä¸ªæ¨¡åç»æç¸åï¼åè请å已宿çéææ¹å¼ |
| | | - åå»ºæ¶ `blobIds` éè¡¨åæ°æ®ä¸èµ·åé |
| | | - æ´æ°æ¶ `blobIds` ä¸ä¸º null æ¶åç«¯éæ°ç»å® |
| | | |
| | | ### HRM èå¤å¼å¸¸ç³è¯· |
| | | - 表å页ï¼`src/views/hrm/attendance/exception/modules/form.vue` |
| | | - ç®ååªæ create å updateãdeleteï¼æ³¨æ update æ¶ä¹éè¦å¤çéä»¶éç» |
| | | |
| | | ### HRM èªèµåæ¾ |
| | | - å表页ï¼`src/views/hrm/salary/payment/index.vue` |
| | | - 详æ
页ï¼`src/views/hrm/salary/payment/modules/detail.vue` |
| | | - èªèµåæ¾æ¯å端èªå¨çæçï¼æ²¡æå建/ç¼è¾è¡¨å |
| | | - **åªéå¨è¯¦æ
页å±ç¤º attachmentList** |
| | | - å 餿¶å端èªå¨åæ¥å é¤éä»¶ |
| | | |
| | | ### CRM é宿¥ä»·å |
| | | - 表å页ï¼`src/views/crm/saleQuotation/modules/form.vue` |
| | | - å表页ç items æ¯ç©ææç»ï¼éä»¶å±ç¤ºå¨è¯¦æ
/ç¼è¾å¼¹çªä¸ |
| | | - 表åå·²ç»ä½¿ç¨ `useVbenModal` + `useVbenForm`ï¼éè¦å¨ä¸ä¼ åºåå å
¥ a-upload |
| | | |
| | | ### CRM è·è¿è®°å½ |
| | | - 表å页ï¼`src/views/crm/followup/modules/form.vue` |
| | | - ä¹åä½¿ç¨ `fileUrls: string[]` åå¨éä»¶å°åï¼ç°å¨æ¹ä¸º blobIds |
| | | - 忥å¯è½æå¾ç/éä»¶ä¸ä¼ åºåï¼éè¦æ¹ä¸º storage API |
| | | |
| | | ### MES è®¾è®¡èµæ |
| | | - 表å页ï¼`src/views/mes/pd/project/modules/document-form.vue` |
| | | - è®¾è®¡èµææ¬èº«å°±æ¯æä»¶ä¸ä¼ åºæ¯ï¼èµæç±»å + æä»¶ä¸ä¼ ï¼ |
| | | - 注æï¼è®¾è®¡èµæç"æä»¶"æ¯ä¸å¡å
容ï¼è attachment æ¯éå çåèæä»¶ |
| | | - åæç `fileUrl` æ¯èµææä»¶èªèº«çå°åï¼é确认æ¯å¦ä¹éè¦æ¹ä¸º attachment æ¹å¼ |
| | | |
| | | --- |
| | | |
| | | ## æä»¶ä¸ä¼ æµç¨æ¶åº |
| | | |
| | | ``` |
| | | âââââââââââ ââââââââââââ ââââââââââââ |
| | | â å端 â â system â â ä¸å¡æ¨¡å â |
| | | â â â æ¨¡å â â â |
| | | ââââââ¬âââââ ââââââ¬ââââââ ââââââ¬ââââââ |
| | | â â â |
| | | â 1.éæ©æä»¶ â â |
| | | âââââââââââââââ>â â |
| | | â 2.è¿å blobId â â |
| | | â<âââââââââââââââ â |
| | | â â â |
| | | â 3.save(blobIds) â |
| | | âââââââââââââââââââââââââââââââ>â |
| | | â â â |
| | | â â 4.bind(blobIds)ââ> å
é¨è°ç¨ |
| | | â â<âââââââââââââââ |
| | | â â â |
| | | â 5.è¿åæå â â |
| | | â<âââââââââââââââââââââââââââââââ |
| | | â â â |
| | | â 6.æ¥ç详æ
â â |
| | | âââââââââââââââââââââââââââââââ>â |
| | | â â â |
| | | â 7.è¿å attachmentList â |
| | | â<âââââââââââââââââââââââââââââââ |
| | | ``` |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | 1. **ä¸ä¼ æ¶æº**ï¼æä»¶ä¸ä¼ åºç¬ç«äºä¸å¡ä¿åï¼å
ä¸ä¼ æ¿ blobIdï¼åä¿åä¸å¡æ°æ® |
| | | 2. **ç¼è¾åæ¾**ï¼ç¼è¾æ¶å¿
é¡»éè¿ GET /get æ¥å£æ¿å° attachmentList åæ¾å°ä¸ä¼ ç»ä»¶ |
| | | 3. **大æä»¶å¤ç**ï¼å¦ææä»¶è¾å¤§ï¼éè¦å¨ä¿ååçå¾
ä¸ä¼ 宿ï¼loading ç¶æï¼ |
| | | 4. **å é¤éä»¶**ï¼å端å¯ä»¥éè¿ `deleteAttachments([attachmentId])` å é¤å个éä»¶ï¼ä½ä¸å¼ºå¶ï¼å 为ä¿åæ¶ blobIds ä¸ä¸º null ä¼è§¦ååç«¯éæ°ç»å® |
| | | 5. **èªèµåæ¾ç¹æ®**ï¼èªèµåæ¾æ å建/ç¼è¾è¡¨åï¼åªéå¨å
¶è¯¦æ
页å±ç¤º attachmentList |
| | | 6. **MES è®¾è®¡èµæç¹æ®**ï¼`MesPdDocumentDO` åæç `fileUrl` åæ®µå·²è¢«å é¤ï¼å¦æè¿ä¸ªå段æ¯ä½ä¸ºä¸å¡æä»¶å°åï¼èééä»¶ï¼ï¼å¯è½éè¦åç¬è¯ä¼°æ¯å¦éè¦ä¿çæä»¶åå¨ |
| | | 7. **è·è¿è®°å½ç¹æ®**ï¼è·è¿è®°å½ä¹åç¨ `fileUrls: string[]`ï¼æ°ç»ï¼ï¼ç°å¨æ¹ä¸º `blobIds: number[]`ï¼æ¥å£å±é¢ååè¾å¤§ |
| | | 8. **å表页ä¸å±ç¤ºéä»¶**ï¼ä¸ºæ§è½èèï¼å表/å页æ¥å£ä¸è¿å attachmentListï¼åªå¨è¯¦æ
æ¥å£è¿å |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # éä»¶ä¸ä¼ æ¨¡åæ¹é - å端èè°æ¹æ¡ |
| | | |
| | | ## æ¦è¿° |
| | | |
| | | æ¬æ¬¡æ¹é ç»ä¸æææ¨¡åçæä»¶ä¸ä¼ ï¼ |
| | | |
| | | 1. **å端**ï¼å é¤ä¸å¡è¡¨ä¸ç `file_url` åï¼å
¨é¨æ¹ç¨ `system_storage_attachment` ä¸é´è¡¨å
³è |
| | | 2. **å端**ï¼FileUpload ç»ä»¶ç»ä¸ä½¿ç¨ `/system/storage-blob/upload`ï¼éä»¶éè¿ attachment API å
³è |
| | | |
| | | ## åç«¯åæ´ |
| | | |
| | | ### å·²å é¤ file_url åç表 |
| | | |
| | | | 表å | 模å | |
| | | |------|------| |
| | | | `erp_purchase_order` | ERP éè´è®¢å | |
| | | | `erp_purchase_request` | ERP éè´ç³è¯· | |
| | | | `erp_sale_order` | ERP éå®è®¢å | |
| | | | `hrm_leave_application` | HRM 请å | |
| | | | `hrm_resignation_application` | HRM 离è | |
| | | | `hrm_transfer_application` | HRM è°å¨ | |
| | | |
| | | ### å·²ä» Java ç±»ä¸å é¤ fileUrl åæ®µ |
| | | |
| | | - 6 个 DO ç±»ï¼ErpPurchaseOrderDOãErpPurchaseRequestDOãErpSaleOrderDOãHrmLeaveApplicationDOãHrmResignationApplicationDOãHrmTransferApplicationDOï¼ |
| | | - 6 个 SaveReqVO 类 |
| | | - 6 个 RespVO 类 |
| | | |
| | | ### æä»¶å
³èæ¹å¼ |
| | | |
| | | æä»¶åªè½éè¿ `system_storage_attachment` ä¸é´è¡¨å
³èï¼ |
| | | |
| | | | API | 说æ | |
| | | |-----|------| |
| | | | `POST /system/storage-blob/upload` | ä¸ä¼ æä»¶ï¼`files` åæ°ï¼multipartï¼ | |
| | | | `POST /system/storage-attachment/bind` | ç»å®éä»¶å°ä¸å¡è®°å½ | |
| | | | `GET /system/storage-attachment/list` | æ¥è¯¢éä»¶ï¼æ recordType + recordIdï¼ | |
| | | | `DELETE /system/storage-attachment/delete` | æ¹éå é¤éä»¶ | |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | ### ä¸ãæ ¸å¿ä¸ä¼ ç»ä»¶æ¹å¨ |
| | | |
| | | **æä»¶**ï¼`src/components/upload/use-upload.ts` |
| | | |
| | | | æ¹å¨é¡¹ | æ§å¼ | æ°å¼ | |
| | | |--------|------|------| |
| | | | ä¸ä¼ æ¥å£ | `POST /infra/file/upload` / S3 ç´ä¼ | `POST /system/storage-blob/upload` | |
| | | | è¯·æ±æ¹å¼ | èªå®ä¹ `createFile0()` / PUT S3 | `FormData` + `requestClient.post()` | |
| | | | uploadUrl | `${apiURL}/infra/file/upload` | `${apiURL}/system/storage-blob/upload` | |
| | | |
| | | ### äºãä¸ä¼ éå¶æ¾å¼ |
| | | |
| | | 以䏿¨¡åç `FileUpload` / `ImageUpload` ç»ä»¶å·²ç§»é¤ `maxNumber`ã`maxSize`ã`accept` éå¶ï¼ |
| | | |
| | | #### ERP 模åï¼13 个æä»¶ï¼ |
| | | |
| | | | æä»¶ | åæ®µ | |
| | | |------|------| |
| | | | `src/views/erp/purchase/order/data.ts` | `fileUrl` | |
| | | | `src/views/erp/purchase/request/data.ts` | `fileUrl` | |
| | | | `src/views/erp/purchase/return/data.ts` | `fileUrl` | |
| | | | `src/views/erp/purchase/in/data.ts` | `fileUrl` | |
| | | | `src/views/erp/sale/order/data.ts` | `fileUrl` | |
| | | | `src/views/erp/sale/return/data.ts` | `fileUrl` | |
| | | | `src/views/erp/sale/out/data.ts` | `fileUrl` | |
| | | | `src/views/erp/stock/in/data.ts` | `fileUrl` | |
| | | | `src/views/erp/stock/out/data.ts` | `fileUrl` | |
| | | | `src/views/erp/stock/move/data.ts` | `fileUrl` | |
| | | | `src/views/erp/stock/check/data.ts` | `fileUrl` | |
| | | | `src/views/erp/finance/receipt/data.ts` | `fileUrl` | |
| | | | `src/views/erp/finance/payment/data.ts` | `fileUrl` | |
| | | |
| | | #### ImageUpload éå¶æ¾å¼ï¼5 å¤ï¼ |
| | | |
| | | | æä»¶ | åæ®µ | |
| | | |------|------| |
| | | | `src/views/im/manager/face/pack/data.ts` | `icon` | |
| | | | `src/views/im/manager/face/pack/data.ts` | `url` | |
| | | | `src/views/im/manager/channel/material/data.ts` | `coverUrl` | |
| | | | `src/views/im/manager/channel/list/data.ts` | `avatar` | |
| | | | `src/views/mes/md/item/modules/product-media-list.vue` | `url` | |
| | | |
| | | #### MES ææ¡£éå¶æ¾å¼ |
| | | |
| | | | æä»¶ | åæ®µ | |
| | | |------|------| |
| | | | `src/views/mes/pd/project/modules/document-form.vue` | `fileUrl` | |
| | | |
| | | ### ä¸ãHRM éä»¶ä¸ä¼ ä¿®å¤ |
| | | |
| | | 3 个 HRM 模åç"éä»¶"åæ®µä» `Input` æ¹ä¸º `FileUpload`ï¼ |
| | | |
| | | | æä»¶ | åæ®µ | æ¹å¨ | |
| | | |------|------|------| |
| | | | `src/views/hrm/leave/data.ts` | `fileUrl` | `component: 'Input'` â `component: 'FileUpload'` | |
| | | | `src/views/hrm/resignation/data.ts` | `fileUrl` | `component: 'Input'` â `component: 'FileUpload'` | |
| | | | `src/views/hrm/transfer/data.ts` | `fileUrl` | `component: 'Input'` â `component: 'FileUpload'` | |
| | | |
| | | ## API |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/system/storage-blob/upload` | ä¸ä¼ æä»¶ï¼`files`ï¼multipart æ°ç»ï¼ | |
| | | | POST | `/system/storage-attachment/bind` | ç»å®éä»¶å°ä¸å¡è®°å½ | |
| | | | GET | `/system/storage-attachment/list` | æ¥è¯¢ä¸å¡è®°å½çéä»¶å表 | |
| | | | DELETE | `/system/storage-attachment/delete` | æ¹éå é¤éä»¶ | |
| | | |
| | | **ä¸ä¼ ååº**ï¼ |
| | | |
| | | ```json |
| | | [ |
| | | { |
| | | "id": 123, |
| | | "url": "https://xxx.com/u_abc123.pdf", |
| | | "previewURL": "https://xxx.com/preview/u_abc123.pdf", |
| | | "name": "åå.pdf", |
| | | "downloadURL": "https://xxx.com/download/u_abc123.pdf" |
| | | } |
| | | ] |
| | | ``` |
| | | |
| | | **ç»å®è¯·æ±**ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "application": "file", |
| | | "recordType": "mes_purchase_order", |
| | | "recordId": 1, |
| | | "blobItems": [{ "blobId": 123 }] |
| | | } |
| | | ``` |
| | | |
| | | ## æ åä¸ä¼ æµç¨ |
| | | |
| | | 1. ç¨æ·éæ©æä»¶ â `POST /system/storage-blob/upload` è¿å `[{ id, url, name }]` |
| | | 2. ä¸å¡è®°å½ä¿åæ¶ â `POST /system/storage-attachment/bind` å
³è blobId |
| | | 3. 详æ
/ç¼è¾é¡µ â `GET /system/storage-attachment/list` å 载已æéä»¶ |
| | | 4. ç¨æ·å é¤éä»¶ â `DELETE /system/storage-attachment/delete` |
| | | |
| | | ## å端 API å°è£
|
| | | |
| | | æ° API 模åä½äº `src/api/system/storage/index.ts`ï¼ |
| | | |
| | | ```typescript |
| | | import { uploadFile, listAttachments, bindAttachments, deleteAttachments } from '#/api/system/storage'; |
| | | ``` |
| | | |
| | | ## recordType å½åè§è |
| | | |
| | | æ ¼å¼ï¼`{模ååç¼}_{ä¸å¡è¡¨å}` |
| | | |
| | | | 模å | recordType | 说æ | |
| | | |------|------------|------| |
| | | | MES éè´è®¢å | `mes_purchase_order` | éè´è®¢åéä»¶ | |
| | | | MES å·¥å | `mes_pro_work_order` | ç产工åéä»¶ | |
| | | | MES è®¾å¤ | `mes_dv_machinery` | è®¾å¤æ¡£æ¡éä»¶ | |
| | | | MES ææ¡£ | `mes_pd_document` | é¡¹ç®ææ¡£éä»¶ | |
| | | | CRM å®¢æ· | `crm_customer` | 客æ·éä»¶ | |
| | | | ERP éè´è®¢å | `erp_purchase_order` | ERP éè´è®¢åéä»¶ | |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - FileUpload ç»ä»¶ä½¿ç¨ `POST /system/storage-blob/upload` ä¸ä¼ æä»¶ï¼FormData åæ®µå为 `files` |
| | | - æä»¶ä¸ä¼ åä»
æåï¼å¿
é¡»è°ç¨ bind æ¥å£å
³èå°ä¸å¡è®°å½ |
| | | - æä»¶é¢è§ä½¿ç¨ååºä¸ç `previewURL` æ `url` åæ®µ |
| | | - ç¦æ¢ä½¿ç¨æ§ç `/infra/file/*` æ¥å£ |
| | | - HRM 请å/离è/è°å¨é¡µé¢çéä»¶åæ®µç°å¨å¯ä»¥ä½¿ç¨ FileUpload ç»ä»¶ä¸ä¼ éä»¶ |
| | |
| | | |
| | | ## æ¦è¿° |
| | | |
| | | æ¬ç³»ç»æä¾äº**ç»ä¸çæä»¶ä¸ä¼ æå¡**ï¼æ¯æå¤ç§å卿¹å¼ï¼æ¬å°ãS3/OSSãæ°æ®åºãFTP/SFTPï¼ã |
| | | æ¬ç³»ç»ä½¿ç¨ `yudao-module-system` 模åç **Storage API** ä½ä¸ºç»ä¸çæä»¶ä¸ä¼ æå¡ï¼æ¯æå¤ç§å卿¹å¼ï¼æ¬å°ãS3/OSSï¼ã |
| | | |
| | | > **éè¦**ï¼ææä¸å¡æ¨¡åå¿
须使ç¨éç¨æä»¶ä¸ä¼ æ¥å£ï¼**ç¦æ¢ä¸ºæ¯ä¸ªæ¨¡åæ°å¢ä¸ä¼ æ¥å£**ã |
| | | > **éè¦**ï¼ææä¸å¡æ¨¡åå¿
é¡»ä½¿ç¨ system 模åç Storage APIï¼**ç¦æ¢ä½¿ç¨ infra 模åç `/infra/file/*` æ¥å£ï¼ç¦æ¢ä¸ºæ¯ä¸ªæ¨¡åæ°å¢ä¸ä¼ æ¥å£**ã |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãéç¨ä¸ä¼ æ¥å£ |
| | | ## ä¸ãéç¨æ¥å£ |
| | | |
| | | ### 1.1 æ¥å£ä¿¡æ¯ |
| | | ### 1.1 æä»¶ä¸ä¼ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/infra/file/upload` | éç¨æä»¶ä¸ä¼ | |
| | | | POST | `/system/storage-blob/upload` | éç¨æä»¶ä¸ä¼ | |
| | | |
| | | ### 1.2 请æ±åæ° |
| | | **请æ±åæ°**ï¼`files`ï¼MultipartFile æ°ç»ï¼ |
| | | |
| | | **ååº**ï¼ |
| | | |
| | | ```json |
| | | [ |
| | | { |
| | | "id": 123, |
| | | "resourceKey": "abc123", |
| | | "contentType": "application/pdf", |
| | | "originalFilename": "åå.pdf", |
| | | "uidFilename": "u_abc123.pdf", |
| | | "byteSize": 102400, |
| | | "path": "/storage/2024/01/abc123.pdf", |
| | | "previewURL": "https://xxx.com/preview/u_abc123.pdf", |
| | | "url": "https://xxx.com/u_abc123.pdf", |
| | | "name": "åå.pdf", |
| | | "downloadURL": "https://xxx.com/download/u_abc123.pdf" |
| | | } |
| | | ] |
| | | ``` |
| | | |
| | | ### 1.2 éä»¶ç»å® |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | POST | `/system/storage-attachment/bind` | å°å·²ä¸ä¼ æä»¶ç»å®å°ä¸å¡è®°å½ | |
| | | |
| | | **请æ±åæ°**ï¼ |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | file | MultipartFile | æ¯ | ä¸ä¼ çæä»¶ | |
| | | | directory | String | å¦ | åå¨ç®å½ï¼å¦ `purchase-request`ã`contract` | |
| | | | application | String | å¦ | æä»¶ç¨éï¼å¦ `file` | |
| | | | recordType | String | æ¯ | å
³èè®°å½ç±»åï¼å¦ `mes_purchase_order` | |
| | | | recordId | Long | æ¯ | å
³èè®°å½ ID | |
| | | | blobItems | List\<BlobItem\> | æ¯ | å¾
ç»å®æä»¶å表 | |
| | | |
| | | ### 1.3 ååºç¤ºä¾ |
| | | `BlobItem`ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "code": 0, |
| | | "data": "https://xxx.com/xxx.pdf", |
| | | "msg": "æä½æå" |
| | | } |
| | | ``` |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | blobId | Long | æ¯ | ä¸ä¼ è¿åçæä»¶ ID | |
| | | | application | String | å¦ | è¦çå¤å±çæä»¶ç¨é | |
| | | |
| | | è¿åå¼ `data` å³ä¸ºæä»¶è®¿é® URLï¼å¯ç´æ¥åå¨å°æ°æ®åºã |
| | | ### 1.3 æ¥è¯¢éä»¶å表 |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | GET | `/system/storage-attachment/list` | æ¥è¯¢ä¸å¡è®°å½çéä»¶ | |
| | | |
| | | **请æ±åæ°**ï¼ |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | recordType | String | æ¯ | å
³èè®°å½ç±»å | |
| | | | recordId | Long | æ¯ | å
³èè®°å½ ID | |
| | | | application | String | å¦ | æç¨éè¿æ»¤ | |
| | | |
| | | ### 1.4 å é¤éä»¶ |
| | | |
| | | | æ¹æ³ | è·¯å¾ | 说æ | |
| | | |------|------|------| |
| | | | DELETE | `/system/storage-attachment/delete` | æ¹éå é¤éä»¶ | |
| | | |
| | | **请æ±ä½**ï¼æä»¶ ID æ°ç» `[1, 2, 3]` |
| | | |
| | | --- |
| | | |
| | | ## äºãåç«¯éæ |
| | | |
| | | ### 2.1 ä¸ä¼ ç»ä»¶ç¤ºä¾ |
| | | ### 2.1 使ç¨å°è£
好ç API |
| | | |
| | | ```html |
| | | <el-upload |
| | | :action="uploadUrl" |
| | | :headers="headers" |
| | | :data="{ directory: 'purchase-request' }" |
| | | :on-success="handleUploadSuccess" |
| | | :before-upload="beforeUpload" |
| | | > |
| | | <el-button type="primary">ç¹å»ä¸ä¼ </el-button> |
| | | </el-upload> |
| | | ```typescript |
| | | import { bindAttachments, listAttachments, uploadFile } from '#/api/system/storage'; |
| | | |
| | | // 1. ä¸ä¼ æä»¶ |
| | | const handleUpload = async (file: File) => { |
| | | const blobs = await uploadFile([file]); |
| | | // è·å blob ID |
| | | const blobId = blobs[0]!.id; |
| | | return blobId; |
| | | }; |
| | | |
| | | // 2. ç»å®å°ä¸å¡è®°å½ |
| | | const handleBind = async (blobIds: number[], recordId: number) => { |
| | | await bindAttachments({ |
| | | application: 'file', |
| | | recordType: 'mes_pro_work_order', |
| | | recordId, |
| | | blobItems: blobIds.map(id => ({ blobId: id })), |
| | | }); |
| | | }; |
| | | |
| | | // 3. æ¥è¯¢éä»¶å表 |
| | | const handleLoad = async (recordId: number) => { |
| | | const attachments = await listAttachments({ |
| | | recordType: 'mes_pro_work_order', |
| | | recordId, |
| | | }); |
| | | return attachments; |
| | | }; |
| | | ``` |
| | | |
| | | ### 2.2 é
置说æ |
| | | ### 2.2 æ åæµç¨ |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | // éç¨ä¸ä¼ æ¥å£ |
| | | uploadUrl: process.env.VUE_APP_BASE_API + '/infra/file/upload', |
| | | // 认è¯å¤´ |
| | | headers: { Authorization: 'Bearer ' + getToken() }, |
| | | } |
| | | }, |
| | | methods: { |
| | | handleUploadSuccess(response) { |
| | | if (response.code === 0) { |
| | | this.form.fileUrl = response.data // ä¿åæä»¶ URL |
| | | } |
| | | }, |
| | | beforeUpload(file) { |
| | | // ä¸å¡å±æ ¡éªæä»¶ç±»ååå¤§å° |
| | | const isLt10M = file.size / 1024 / 1024 < 10 |
| | | if (!isLt10M) { |
| | | this.$message.error('æä»¶å¤§å°ä¸è½è¶
è¿ 10MB!') |
| | | } |
| | | return isLt10M |
| | | } |
| | | } |
| | | ``` |
| | | 1. ç¨æ·éæ©æä»¶ â è°ç¨ `POST /system/storage-blob/upload` ä¸ä¼ |
| | | 2. ä¸å¡è®°å½ä¿åæ¶ â è°ç¨ `POST /system/storage-attachment/bind` ç»å®éä»¶å°è®°å½ |
| | | 3. 详æ
/ç¼è¾é¡µ â è°ç¨ `GET /system/storage-attachment/list` å 载已æéä»¶ |
| | | 4. ç¨æ·å é¤éä»¶ â è°ç¨ `DELETE /system/storage-attachment/delete` |
| | | |
| | | ### 2.3 displayUpload ç»ä»¶ |
| | | |
| | | 项ç®ä¸å·²ææä»¶ä¸ä¼ æ¾ç¤ºç»ä»¶ï¼å¯ç´æ¥ä½¿ç¨ç³»ç» Storage APIã |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãç®å½è§è |
| | | ## ä¸ãrecordType å½åè§è |
| | | |
| | | åä¸å¡æ¨¡åéè¿ `directory` åæ°åºååå¨ç®å½ï¼**ç¦æ¢æ°å¢ä¸å¡ä¸ä¼ æ¥å£**ï¼ |
| | | æ ¼å¼ï¼`{模ååç¼}_{ä¸å¡è¡¨å}` |
| | | |
| | | | 模å | directory | 说æ | |
| | | |------|-----------|------| |
| | | | ç¨æ·å¤´å | `avatar` | ç¨æ·å¤´åå¾ç | |
| | | | ååéä»¶ | `contract` | ååç¸å
³æä»¶ | |
| | | | éè´ç³è¯· | `purchase-request` | éè´ç³è¯·éä»¶ | |
| | | | éè´è®¢å | `purchase-order` | éè´è®¢åéä»¶ | |
| | | | 产åå¾ç | `product` | 产åç¸å
³å¾ç | |
| | | | éç¨éä»¶ | `attachment` | éç¨ä¸å¡éä»¶ | |
| | | |
| | | > **å½åè§è**ï¼ä½¿ç¨å°å忝åè¿å符ï¼å¦ `purchase-request`ï¼ä¸æ¨¡ååä¿æä¸è´ã |
| | | | 模å | recordType | 说æ | |
| | | |------|------------|------| |
| | | | MES éè´è®¢å | `mes_purchase_order` | éè´è®¢åéä»¶ | |
| | | | MES å·¥å | `mes_pro_work_order` | ç产工åéä»¶ | |
| | | | MES è®¾å¤ | `mes_dv_machinery` | è®¾å¤æ¡£æ¡éä»¶ | |
| | | | MES ææ¡£ | `mes_pd_document` | é¡¹ç®ææ¡£éä»¶ | |
| | | | CRM å®¢æ· | `crm_customer` | 客æ·éä»¶ | |
| | | | ERP 产å | `erp_product` | 产åéä»¶ | |
| | | |
| | | --- |
| | | |
| | | ## åãå端éæï¼ç¹æ®åºæ¯ï¼ |
| | | ## åãç¦æ¢è¡ä¸º |
| | | |
| | | ### 4.1 å端éè¦ä¸»å¨ä¸ä¼ æä»¶æ¶ |
| | | |
| | | æå°æ°åºæ¯ä¸ï¼å端éè¦ä¸»å¨ä¸ä¼ æä»¶ï¼å¦çææ¥è¡¨åä¿åï¼ï¼å¯æ³¨å
¥ `FileApi`ï¼ |
| | | |
| | | ```java |
| | | @Resource |
| | | private FileApi fileApi; |
| | | |
| | | // ä¸ä¼ æä»¶ |
| | | String url = fileApi.createFile(bytes, "æ¥è¡¨.xlsx", "report", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); |
| | | ``` |
| | | |
| | | ### 4.2 è·åç§ææä»¶é¢ç¾åå°å |
| | | |
| | | ```java |
| | | // çæä¸´æ¶è®¿é®å°åï¼1å°æ¶ææ |
| | | String presignedUrl = fileApi.presignGetUrl(fileUrl, 3600); |
| | | ``` |
| | | - â ç¦æ¢è°ç¨ `/infra/file/upload` æ `/infra/file/presigned-url` |
| | | - â ç¦æ¢å¨ MES/CRM/ERP çä¸å¡æ¨¡å Controller æ°å¢ `@PostMapping("/upload")` |
| | | - â ç¦æ¢æ³¨å
¥ `cn.iocoder.yudao.module.infra.api.file.FileApi` |
| | | - â ç¦æ¢ä½¿ç¨æ§ç `src/api/infra/file/index.ts` ä¸ç `uploadFile()` 彿° |
| | | |
| | | --- |
| | | |
| | | ## äºãåå¨é
ç½® |
| | | ## äºãå端 API 模åä½ç½® |
| | | |
| | | åå¨é
ç½®éè¿ç®¡çåå°å¨æé
ç½®ï¼æ éä¿®æ¹ä»£ç ï¼ |
| | | `src/api/system/storage/index.ts` |
| | | |
| | | 1. è®¿é® **åºç¡è®¾æ½ > æä»¶ç®¡ç > æä»¶é
ç½®** |
| | | 2. æ°å¢é
ç½®ï¼éæ©åå¨ç±»åå¹¶å¡«ååæ° |
| | | 3. ç¹å»"设置为主é
ç½®"æ¿æ´»ä½¿ç¨ |
| | | |
| | | ### æ¯æçåå¨ç±»å |
| | | |
| | | | ç±»å | 说æ | éç¨åºæ¯ | |
| | | |------|------|----------| |
| | | | DB | åå¨å°æ°æ®åº | å°æä»¶ãä¸´æ¶æä»¶ | |
| | | | LOCAL | æ¬å°ç£çåå¨ | å
ç½é¨ç½²ãå¼åç¯å¢ | |
| | | | FTP/SFTP | FTP æå¡å¨ | å
¼å®¹èç³»ç» | |
| | | | S3 | é¿éäº OSS / è
¾è®¯äº COS / MinIO | ç产ç¯å¢ | |
| | | 导åºå½æ°ï¼`uploadFile`ã`listAttachments`ã`bindAttachments`ã`deleteAttachments` |
| | | |
| | | --- |
| | | |
| | | ## å
ãæä»¶å卿¹å¼ |
| | | ## å
ãæ³¨æäºé¡¹ |
| | | |
| | | ### 6.1 夿件åå¨ï¼æ¨èï¼ |
| | | |
| | | ä½¿ç¨ `List<String>` + `StringListTypeHandler`ï¼åè CRM è·è¿è®°å½æ¨¡åï¼ |
| | | |
| | | **å®ä½ç±»ï¼** |
| | | |
| | | ```java |
| | | @TableName(value = "crm_follow_up_record", autoResultMap = true) |
| | | public class CrmFollowUpRecordDO extends BaseDO { |
| | | |
| | | /** |
| | | * å¾ç |
| | | */ |
| | | @TableField(typeHandler = StringListTypeHandler.class) |
| | | private List<String> picUrls; |
| | | |
| | | /** |
| | | * éä»¶ |
| | | */ |
| | | @TableField(typeHandler = StringListTypeHandler.class) |
| | | private List<String> fileUrls; |
| | | } |
| | | ``` |
| | | |
| | | **æ°æ®åºå段**ï¼`VARCHAR`ï¼åå¨ JSON æ°ç»æ ¼å¼å¦ `["url1","url2","url3"]` |
| | | |
| | | **VO ç±»ï¼** |
| | | |
| | | ```java |
| | | @Schema(description = "éä»¶") |
| | | private List<String> fileUrls; |
| | | ``` |
| | | |
| | | **å端使ç¨ï¼** |
| | | |
| | | ```js |
| | | // ä¸ä¼ æåå追å |
| | | handleUploadSuccess(response) { |
| | | if (response.code === 0) { |
| | | if (!this.form.fileUrls) { |
| | | this.form.fileUrls = [] |
| | | } |
| | | this.form.fileUrls.push(response.data) |
| | | } |
| | | } |
| | | |
| | | // å 餿件 |
| | | handleRemove(index) { |
| | | this.form.fileUrls.splice(index, 1) |
| | | } |
| | | ``` |
| | | |
| | | ### 6.2 åæä»¶åå¨ |
| | | |
| | | ```java |
| | | // å®ä½ç±» |
| | | private String fileUrl; |
| | | |
| | | // VO ç±» |
| | | @Schema(description = "éä»¶å°å") |
| | | private String fileUrl; |
| | | ``` |
| | | |
| | | ### 6.3 `infra_file` 表çä½ç¨ |
| | | |
| | | ç³»ç» `infra_file` è¡¨è®°å½ææä¸ä¼ æä»¶çå
æ°æ®ï¼nameãpathãurlãtypeãsizeï¼ï¼ä¸ä¸ä¸å¡å
³èï¼ä»
ç¨äºï¼ |
| | | - æä»¶ç®¡çåå°æ¥çä¸ä¼ è®°å½ |
| | | - ç»è®¡åå¨ä½¿ç¨æ
åµ |
| | | |
| | | --- |
| | | |
| | | ## ä¸ã注æäºé¡¹ |
| | | |
| | | 1. **使ç¨éç¨æ¥å£**ï¼æææä»¶ä¸ä¼ å¿
é¡»ä½¿ç¨ `/infra/file/upload`ï¼ç¦æ¢æ°å¢ä¸å¡ä¸ä¼ æ¥å£ |
| | | 2. **åºåç®å½**ï¼éè¿ `directory` åæ°åºåä¸å¡æ¨¡åï¼ä¾¿äºç®¡ç忏
ç |
| | | 3. **æä»¶å¤§å°**ï¼é»è®¤éå¶ 10MBï¼å¯å¨ Nginx æåºç¨å±è°æ´ |
| | | 4. **ç±»åæ ¡éª**ï¼åç«¯åºæ ¡éªå
许çæä»¶ç±»åï¼é²æ¢ä¸ä¼ æ¶ææä»¶ |
| | | 5. **URL åå¨**ï¼ä¸ä¼ æååï¼å°è¿åç URL åå¨å°ä¸å¡è¡¨ç `fileUrl` åæ®µ |
| | | |
| | | --- |
| | | |
| | | ## ä¸ã常è§é®é¢ |
| | | |
| | | **Q: 为ä»ä¹ä¸è½ä¸ºæ¯ä¸ªæ¨¡åæ°å¢ä¸ä¼ æ¥å£ï¼** |
| | | |
| | | A: ç»ä¸æ¥å£ä¾¿äºï¼ |
| | | - ç»ä¸ç®¡çåå¨é
ç½® |
| | | - ç»ä¸æéæ§å¶å审计 |
| | | - é¿å
代ç éå¤ |
| | | - åç»ç»´æ¤åè¿ç§» |
| | | |
| | | **Q: å¦ä½åºåä¸å模åçæä»¶ï¼** |
| | | |
| | | A: ä½¿ç¨ `directory` åæ°ï¼æä»¶ä¼åå¨å¨å¯¹åºç®å½ä¸ã |
| | | |
| | | **Q: å端å¦ä½éå¶æä»¶ç±»åï¼** |
| | | |
| | | A: å¨ `beforeUpload` æ¹æ³ä¸æ ¡éª `file.type` æ `file.name` åç¼ã |
| | | 1. **使ç¨éç¨æ¥å£**ï¼ææä¸ä¼ èµ° system 模åï¼éè¿ `recordType` åºåä¸å¡ |
| | | 2. **ä¸ä¼ åç»å®**ï¼æä»¶ä¸ä¼ åªæ¯æåï¼å¿
é¡»è°ç¨ bind æ¥å£å
³èå°ä¸å¡è®°å½ |
| | | 3. **æä»¶é¢è§**ï¼ä½¿ç¨ååºä¸ç `previewURL` æ `url` åæ®µ |
| | | 4. **æä»¶ä¸è½½**ï¼ä½¿ç¨ `GET /system/storage-blob/download/{fileName}?token=xxx` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # MDM ç©æåæ¥ MES ä¼å - å端èè°æ¹æ¡ |
| | | |
| | | ## æ¶åé¡µé¢ |
| | | |
| | | - åºç¡æ°æ® > MDM > ç©æç®¡çï¼åè¡¨é¡µï¼ |
| | | - åºç¡æ°æ® > MDM > ç©æç®¡çï¼æ°å¢/ç¼è¾å¼¹çªï¼ |
| | | |
| | | ## åæ´æ¦è¿° |
| | | |
| | | 1. **ç§»é¤ `syncMes` å¤éæ¡**ï¼å建/ç¼è¾ç©ææ¶ä¸åéè¦æå¨å¾é"åæ¥å° MES"ï¼å端èªå¨åæ¥ |
| | | 2. **å表æ°å¢åæ¥ç¶æå**ï¼æ¾ç¤ºç©ææ¯å¦å·²åæ¥å° MES |
| | | 3. **ç¶æ/å é¤å®æ¶åæ¥**ï¼MDM ä¾§æ´æ°ç¶ææå é¤ç©ææ¶ï¼èªå¨åæ¥å° MES |
| | | |
| | | ## API åæ´ |
| | | |
| | | ### 1. GET `/mdm/item/page` - ååºæ°å¢å段 |
| | | |
| | | **ååºå段æ°å¢ï¼** |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | syncedMes | Boolean | æ¯å¦å·²åæ¥å° MESãtrue=已忥ï¼false/null=æªåæ¥ | |
| | | |
| | | **ååºç¤ºä¾ï¼** |
| | | |
| | | ```json |
| | | { |
| | | "code": 0, |
| | | "data": { |
| | | "list": [ |
| | | { |
| | | "id": 1, |
| | | "code": "ITEM001", |
| | | "name": "èºä¸", |
| | | "syncedMes": true, |
| | | "...": "..." |
| | | }, |
| | | { |
| | | "id": 2, |
| | | "code": "ITEM002", |
| | | "name": "èºæ¯", |
| | | "syncedMes": false, |
| | | "...": "..." |
| | | } |
| | | ], |
| | | "total": 100 |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 2. GET `/mdm/item/get` - ååºæ°å¢å段 |
| | | |
| | | åä¸ï¼`syncedMes` è¡¨ç¤ºè¯¥ç©ææ¯å¦å·²åæ¥å° MESã |
| | | |
| | | ## åæ®µå±ç¤ºè§å |
| | | |
| | | | åæ®µ | å±ç¤ºä½ç½® | 说æ | |
| | | |------|----------|------| |
| | | | syncedMes | å表æ°å¢å | true æ¶æ¾ç¤ºç»¿è²"已忥"æ ç¾ï¼false æ¶æ¾ç¤ºç°è²"æªåæ¥"æ ç¾ | |
| | | |
| | | ## ä¸å¡è§å说æ |
| | | |
| | | | åºæ¯ | è§å | |
| | | |------|------| |
| | | | æ°å¢ç©æ | å端èªå¨åæ¥å° MESï¼åè¡¨ä¸ syncedMes 为 true | |
| | | | ç¼è¾ç©æ | å端èªå¨åæ¥å° MES | |
| | | | æ´æ°ç©æç¶æ | å端èªå¨åæ¥ç¶æå° MESï¼å¯ç¨/ç¦ç¨ï¼ | |
| | | | å é¤ç©æ | å端èªå¨åæ¥å é¤ MES ä¸ç对åºè®°å½ï¼å¦åå¨ï¼ | |
| | | | 表åä¸ç syncMes åæ®µ | å端å¯ä¿çä½ä¸åçæï¼å»ºè®®éè"åæ¥å° MES"å¼å
³ | |
| | | |
| | | ## å端修æ¹ç¹ |
| | | |
| | | ### 1. TypeScript ç±»åå®ä¹ |
| | | |
| | | `src/api/mdm/item/index.ts` ä¸ `MdmItemApi.Item` æ¥å£æ°å¢ `syncedMes?: boolean` åæ®µã |
| | | |
| | | ### 2. å表æ°å¢åæ¥ç¶æå |
| | | |
| | | `src/views/basicData/mdm/data.ts` ä¸ `useGridColumns()` æ°å¢ä¸åï¼ |
| | | |
| | | - field: `syncedMes` |
| | | - title: "åæ¥ç¶æ" |
| | | - ä½¿ç¨ææ§½æ¸²æ Tag ç»ä»¶ |
| | | |
| | | ### 3. åè¡¨é¡µæ¨¡æ¿ |
| | | |
| | | `src/views/basicData/mdm/index.vue` 䏿°å¢ `syncedMes` ææ§½æ¨¡æ¿ï¼å±ç¤ºåæ¥ç¶ææ ç¾ã |
| | | |
| | | ### 4. 表åç§»é¤ syncMes å¼å
³ï¼å¯éï¼ |
| | | |
| | | `src/views/basicData/mdm/data.ts` ä¸ `useFormSchema()` å¯éèæç§»é¤ `syncMes` 表å项ï¼åç«¯å·²å¿½ç¥æ¤åæ°ã |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - å岿°æ®ä¸æªåæ¥å° MES çç©æï¼`syncedMes` 为 falseï¼å¯éè¿ç¼è¾ç©æè§¦åèªå¨åæ¥ |
| | | - MES åæ¥å¤±è´¥ä¼åæ» MDM æä½ï¼ä¿ææ°æ®ä¸è´æ§ï¼ï¼å端éå
³æ³¨æ¥å£è¿åçéè¯¯ä¿¡æ¯ |
| | | - `syncedMes` åæ®µå¨è¯¦æ
页ï¼getItemï¼ä¹ä¼è¿åï¼å¯ç¨äºè¯¦æ
页æ¾ç¤ºåæ¥ç¶æ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # éä»¶ä¸ä¼ æ¨¡åæ±æ» |
| | | |
| | | ## ä¸ãæ ¸å¿ä¸ä¼ ç»ä»¶ |
| | | |
| | | è·¯å¾ï¼`src/components/upload/` |
| | | |
| | | | ç»ä»¶ | æä»¶ | ç¨é | |
| | | |---|---|---| |
| | | | `FileUpload` | `file-upload.vue` | éç¨æä»¶ä¸ä¼ ï¼ææ¬å表å±ç¤ºï¼æ¯æææ½ãç±»å/大尿 ¡éª | |
| | | | `ImageUpload` | `image-upload.vue` | å¾çä¸ä¼ ï¼å¡çé¢è§æ¨¡å¼ï¼æ¯æå¾çé¢è§å¼¹çª | |
| | | | `InputUpload` | `input-upload.vue` | è¾å
¥æ¡+ä¸ä¼ ç»åï¼ä¸ä¼ æé®å¨è¾å
¥æ¡åç¼æææ¬åå³ä¸è§ | |
| | | | `useUpload()` | `use-upload.ts` | æ ¸å¿ç»å彿°ï¼ç»ä¸ä½¿ç¨ system 模å Storage APIï¼POST `/system/storage-blob/upload`ï¼ | |
| | | | `CropperAvatar` | `src/components/cropper/cropper-avatar.vue` | 头åè£åªä¸ä¼ | |
| | | |
| | | ### ä¸ä¼ æ¨¡å¼ |
| | | |
| | | - **æå¡ç«¯ä¸ä¼ **ï¼POST `/system/storage-blob/upload`ï¼ç»ä¸ä½¿ç¨ system 模å Storage API |
| | | - **éä»¶ç»å®**ï¼POST `/system/storage-attachment/bind`ï¼å°ä¸ä¼ çæä»¶å
³èå°ä¸å¡è®°å½ |
| | | |
| | | ### 表åéé
卿³¨å |
| | | |
| | | è·¯å¾ï¼`src/adapter/component/index.ts` |
| | | |
| | | 注åäº `Upload`ã`FileUpload`ã`ImageUpload`ã`PreviewUpload` åç§è¡¨åç»ä»¶ç±»åï¼å¯å¨è¡¨åschemaä¸ç´æ¥ä½¿ç¨ã |
| | | |
| | | --- |
| | | |
| | | ## äºãFileUpload ä½¿ç¨æ¨¡åï¼éä»¶ä¸ä¼ ï¼ |
| | | |
| | | ### ERP 模å |
| | | |
| | | | 模å | æä»¶ | åæ®µ | éå¶ | |
| | | |---|---|---|---| |
| | | | éè´è®¢å | `src/views/erp/purchase/order/data.ts` | `fileUrl` | æ éå¶ | |
| | | | éè´ç³è¯· | `src/views/erp/purchase/request/data.ts` | `fileUrl` | æ éå¶ | |
| | | | éè´éè´§ | `src/views/erp/purchase/return/data.ts` | `fileUrl` | æ éå¶ | |
| | | | éè´å
¥åº | `src/views/erp/purchase/in/data.ts` | `fileUrl` | æ éå¶ | |
| | | | éå®è®¢å | `src/views/erp/sale/order/data.ts` | `fileUrl` | æ éå¶ | |
| | | | éå®éè´§ | `src/views/erp/sale/return/data.ts` | `fileUrl` | æ éå¶ | |
| | | | éå®åºåº | `src/views/erp/sale/out/data.ts` | `fileUrl` | æ éå¶ | |
| | | | åºåå
¥åº | `src/views/erp/stock/in/data.ts` | `fileUrl` | æ éå¶ | |
| | | | åºååºåº | `src/views/erp/stock/out/data.ts` | `fileUrl` | æ éå¶ | |
| | | | åºåè°æ¨ | `src/views/erp/stock/move/data.ts` | `fileUrl` | æ éå¶ | |
| | | | åºåçç¹ | `src/views/erp/stock/check/data.ts` | `fileUrl` | æ éå¶ | |
| | | | æ¶æ¬¾å | `src/views/erp/finance/receipt/data.ts` | `fileUrl` | æ éå¶ | |
| | | | 仿¬¾å | `src/views/erp/finance/payment/data.ts` | `fileUrl` | æ éå¶ | |
| | | |
| | | ### CRM 模å |
| | | |
| | | | 模å | æä»¶ | åæ®µ | éå¶ | |
| | | |---|---|---|---| |
| | | | è·è¿è®°å½ | `src/views/crm/followup/data.ts` | `fileUrls` | â | |
| | | |
| | | ### MES 模å |
| | | |
| | | | 模å | æä»¶ | åæ®µ | éå¶ | |
| | | |---|---|---|---| |
| | | | é¡¹ç®ææ¡£ | `src/views/mes/pd/project/modules/document-form.vue` | `fileUrl` | æ éå¶, directory:mes/pd | |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãImageUpload ä½¿ç¨æ¨¡åï¼å¾çä¸ä¼ ï¼ |
| | | |
| | | | 模å | æä»¶ | åæ®µ | ç¨é | |
| | | |---|---|---|---| |
| | | | AIè§è²ç®¡ç | `src/views/ai/model/chatRole/data.ts` | `avatar` | è§è²å¤´å | |
| | | | CRMè·è¿è®°å½ | `src/views/crm/followup/data.ts` | `picUrls` | å¾ç | |
| | | | åºç¡æ¼ç¤º | `src/views/infra/demo/demo01/data.ts` | `avatar` | 头å | |
| | | | OAuth2åºç¨ | `src/views/system/oauth2/client/data.ts` | `logo` | åºç¨å¾æ | |
| | | | IM表æ
å
| `src/views/im/manager/face/pack/data.ts` | `icon` | å°é¢ | |
| | | | IM表æ
å
| `src/views/im/manager/face/pack/data.ts` | `url` | 表æ
å¾ | |
| | | | IMé¢éç´ æ | `src/views/im/manager/channel/material/data.ts` | `coverUrl` | å°é¢å¾ | |
| | | | IMé¢éå表 | `src/views/im/manager/channel/list/data.ts` | `avatar` | é¢é头å | |
| | | | MES产ååªä½ | `src/views/mes/md/item/modules/product-media-list.vue` | `url` | 产åå¾ç | |
| | | | BPMæµç¨è¡¨å | `src/views/bpm/model/form/modules/basic-info.vue` | 徿 åæ®µ | 表å徿 | |
| | | |
| | | --- |
| | | |
| | | ## åãUpload ä½¿ç¨æ¨¡åï¼Excel导å
¥ï¼ |
| | | |
| | | | 模å | æä»¶ | ç¨é | API | |
| | | |---|---|---|---| |
| | | | ç³»ç»ç¨æ· | `src/views/system/user/modules/import-form.vue` | Excel导å
¥ç¨æ· | `POST /system/user/import` | |
| | | | CRMå®¢æ· | `src/views/crm/customer/modules/import-form.vue` | Excel导å
¥å®¢æ· | `POST /crm/customer/import` | |
| | | | MESç©æ | `src/views/mes/md/item/modules/import-form.vue` | Excel导å
¥ç©æ | `POST /mes/md/item/import` | |
| | | | MESè®¾å¤ | `src/views/mes/dv/machinery/modules/import-form.vue` | Excel导å
¥è®¾å¤ | `POST /mes/dv/machinery/import` | |
| | | | HRMèå¤ | `src/views/hrm/attendance/record/modules/import-form.vue` | Excel导å
¥èå¤ | `POST /hrm/attendance/record/import` | |
| | | |
| | | --- |
| | | |
| | | ## äºãå
¶ä»ä¸ä¼ åºæ¯ |
| | | |
| | | | 模å | æä»¶ | ç¨é | å®ç°æ¹å¼ | |
| | | |---|---|---|---| |
| | | | AIç¥è¯åº | `src/views/ai/knowledge/document/form/modules/upload-step.vue` | ææ¡£ä¸ä¼ ï¼TXT/PDF/DOCçï¼15MBï¼ | `UploadDragger` | |
| | | | AIè天 | `src/views/ai/chat/index/modules/message/file-upload.vue` | æä»¶ä¸ä¼ ï¼5个/10MBï¼ | åçinput + `useUpload().httpRequest()` | |
| | | | IMè天 | `src/views/im/home/composables/useMediaUploader.ts` | å¾ç/æä»¶/è¯é³/è§é¢ä¸ä¼ | `uploadFile()` API | |
| | | | IMæ¶æ¯è¾å
¥ | `src/views/im/home/pages/conversation/components/input/message-input.vue` | éæ©æä»¶åé | åçinput + `useMediaUploader` | |
| | | | IM表æ
ä¸ä¼ | `src/views/im/home/pages/conversation/components/input/face-picker.vue` | èªå®ä¹è¡¨æ
ä¸ä¼ | `uploadFile()` API | |
| | | | BPMç¾å | `src/views/bpm/processInstance/detail/modules/signature.vue` | æåç¾åä¸ä¼ | `uploadFile()` APIï¼base64转æä»¶ï¼ | |
| | | | ç¨æ·å¤´å | `src/views/_core/profile/modules/profile-user.vue` | 头åè£åªä¸ä¼ | `CropperAvatar` + `useUpload().httpRequest()` | |
| | | | TinyMCE | `src/components/tinymce/img-upload.vue` | 坿æ¬å¾çä¸ä¼ | `Upload`ç»ä»¶ | |
| | | | Tiptap | `src/packages/effects/plugins/src/tiptap/tiptap.vue` | 坿æ¬å¾çä¸ä¼ | Tiptapæ©å± | |
| | | | MESä¾åºå | `src/api/mes/md/vendor/index.ts` | Excel导å
¥ä¾åºå | `POST /mes/md-vendor/import` | |
| | | | MESå®¢æ· | `src/api/mes/md/client/index.ts` | Excel导å
¥MESå®¢æ· | `POST /mes/md-client/import` | |
| | | | MESé¡¹ç® | `src/api/mes/pd/project/index.ts` | é¡¹ç®ææ¡£ä¸ä¼ | `PUT /mes/pd/project/upload` | |
| | | |
| | | --- |
| | | |
| | | ## å
ãHRM éä»¶ä¸ä¼ ï¼å·²ä¿®å¤ï¼ |
| | | |
| | | HRM 模åç"éä»¶"åæ®µå·²ä» `Input` æ¹ä¸º `FileUpload` ç»ä»¶ã |
| | | |
| | | | 模å | æä»¶ | åæ®µ | ç»ä»¶ | ç¶æ | |
| | | |---|---|---|---|---| |
| | | | 请å | `src/views/hrm/leave/data.ts` | `fileUrl` | `FileUpload` | å·²ä¿®å¤ | |
| | | | 离è | `src/views/hrm/resignation/data.ts` | `fileUrl` | `FileUpload` | å·²ä¿®å¤ | |
| | | | è°å¨ | `src/views/hrm/transfer/data.ts` | `fileUrl` | `FileUpload` | å·²ä¿®å¤ | |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãä¸ä¼ ç¸å
³API |
| | | |
| | | | 彿° | ç«¯ç¹ | ç¨é | |
| | | |---|---|---| |
| | | | `uploadFile()` | `POST /system/storage-blob/upload` | ç»ä¸æä»¶ä¸ä¼ | |
| | | | `bindAttachments()` | `POST /system/storage-attachment/bind` | ç»å®éä»¶å°ä¸å¡è®°å½ | |
| | | | `listAttachments()` | `GET /system/storage-attachment/list` | æ¥è¯¢éä»¶å表 | |
| | | | `deleteAttachments()` | `DELETE /system/storage-attachment/delete` | æ¹éå é¤éä»¶ | |
| | | |
| | | APIå®ä¹æä»¶ï¼`src/api/system/storage/index.ts` |
| | |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-è稿ï¼10-审æ¹ä¸ï¼20-éè¿ï¼30-驳åï¼40-æ¤é', |
| | | `process_instance_id` varchar(64) DEFAULT NULL COMMENT 'BPMæµç¨å®ä¾ID', |
| | | `approve_time` datetime DEFAULT NULL COMMENT '审æ¹å®ææ¶é´', |
| | | `file_url` varchar(500) DEFAULT NULL COMMENT 'éä»¶å°å', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-è稿ï¼10-审æ¹ä¸ï¼20-éè¿ï¼30-驳åï¼40-æ¤é', |
| | | `process_instance_id` varchar(64) DEFAULT NULL COMMENT 'BPMæµç¨å®ä¾ID', |
| | | `approve_time` datetime DEFAULT NULL COMMENT '审æ¹å®ææ¶é´', |
| | | `file_url` varchar(500) DEFAULT NULL COMMENT 'éä»¶å°å', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-è稿ï¼10-审æ¹ä¸ï¼20-éè¿ï¼30-驳åï¼40-æ¤é', |
| | | `process_instance_id` varchar(64) DEFAULT NULL COMMENT 'BPMæµç¨å®ä¾ID', |
| | | `approve_time` datetime DEFAULT NULL COMMENT '审æ¹å®ææ¶é´', |
| | | `file_url` varchar(500) DEFAULT NULL COMMENT 'éä»¶å°å', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-è稿ï¼10-审æ¹ä¸ï¼20-éè¿ï¼30-驳åï¼40-æ¤é', |
| | | `process_instance_id` varchar(64) DEFAULT NULL COMMENT 'BPMæµç¨å®ä¾ID', |
| | | `approve_time` datetime DEFAULT NULL COMMENT '审æ¹å®ææ¶é´', |
| | | `file_url` varchar(500) DEFAULT NULL COMMENT 'éä»¶å°å', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | `payment_method` tinyint NOT NULL COMMENT 'åæ¾æ¹å¼ï¼1-é¶è¡è½¬è´¦ï¼2-ç°é', |
| | | `payment_time` datetime NOT NULL COMMENT 'åæ¾æ¶é´', |
| | | `status` tinyint NOT NULL DEFAULT 0 COMMENT 'ç¶æï¼0-å¾
åæ¾ï¼10-已忾', |
| | | `file_url` varchar(500) DEFAULT NULL COMMENT 'é¶è¡ååéä»¶', |
| | | `remark` varchar(500) DEFAULT NULL COMMENT '夿³¨', |
| | | `creator` varchar(64) DEFAULT '' COMMENT 'å建è
', |
| | | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; |
| | | import cn.iocoder.yudao.module.crm.service.followup.CrmFollowUpRecordService; |
| | | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建è·è¿è®°å½") |
| | |
| | | getLoginUserId(), CrmPermissionLevelEnum.READ)) { |
| | | throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(followUpRecord.getBizType())); |
| | | } |
| | | return success(BeanUtils.toBean(followUpRecord, CrmFollowUpRecordRespVO.class)); |
| | | CrmFollowUpRecordRespVO respVO = BeanUtils.toBean(followUpRecord, CrmFollowUpRecordRespVO.class); |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("crm_follow_up_record", id)); |
| | | return success(respVO); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | package cn.iocoder.yudao.module.crm.controller.admin.followup.vo; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | | import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | |
| | | |
| | | @Schema(description = "å¾ç") |
| | | private List<String> picUrls; |
| | | @Schema(description = "éä»¶") |
| | | private List<String> fileUrls; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "å建人", example = "1024") |
| | | @ExcelProperty("å建人") |
| | |
| | | @NotNull(message = "䏿¬¡èç³»æ¶é´ä¸è½ä¸ºç©º") |
| | | private LocalDateTime nextTime; |
| | | |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "å
³èçåæºç¼å·æ°ç»") |
| | | private List<Long> businessIds; |
| | | @Schema(description = "å
³èçè系人ç¼å·æ°ç»") |
| | |
| | | |
| | | @Schema(description = "å¾ç URL å表") |
| | | private List<String> picUrls; |
| | | @Schema(description = "éä»¶ URL å表") |
| | | private List<String> fileUrls; |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | private MdmUnitMeasureApi mdmUnitMeasureApi; |
| | | @Resource |
| | | private CrmCustomerService customerService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建é宿¥ä»·å") |
| | |
| | | } |
| | | // 3. å¡«å
å
³èä¿¡æ¯ |
| | | fillSaleQuotationRelatedFields(respVO); |
| | | // 4. å¡«å
éä»¶å表 |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("crm_sale_quotation", saleQuotation.getId())); |
| | | return respVO; |
| | | } |
| | | |
| | |
| | | package cn.iocoder.yudao.module.crm.controller.admin.quotation.vo; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | |
| | | @ExcelProperty("å
³èåååå·") |
| | | private String contractNo; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://www.baidu.com") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | @ExcelProperty("夿³¨") |
| | |
| | | @Schema(description = "ç¨ç", example = "13.00") |
| | | private BigDecimal taxRate; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://www.baidu.com") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | @TableField(typeHandler = StringListTypeHandler.class) |
| | | private List<String> picUrls; |
| | | /** |
| | | * éä»¶ |
| | | */ |
| | | @TableField(typeHandler = StringListTypeHandler.class) |
| | | private List<String> fileUrls; |
| | | |
| | | /** |
| | | * å
³èçåæºç¼å·æ°ç» |
| | | * |
| | | * å
³è {@link CrmBusinessDO#getId()} |
| | |
| | | */ |
| | | private String contractNo; |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| | | import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; |
| | | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @Resource |
| | | @Lazy |
| | | private CrmCustomerService customerService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | @CrmPermission(bizTypeValue = "#createReqVO.bizType", bizId = "#createReqVO.bizId", level = CrmPermissionLevelEnum.WRITE) |
| | |
| | | // 1. å建æ´è¿è®°å½ |
| | | CrmFollowUpRecordDO record = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class); |
| | | crmFollowUpRecordMapper.insert(record); |
| | | storageAttachmentApi.bindAttachments("file", "crm_follow_up_record", |
| | | record.getId(), createReqVO.getBlobIds()); |
| | | |
| | | // 2. æ´æ° bizId 对åºçè®°å½ |
| | | if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), record.getBizType())) { // æ´æ°å®¢æ·è·è¿ä¿¡æ¯ |
| | |
| | | throw exception(FOLLOW_UP_RECORD_DELETE_DENIED); |
| | | } |
| | | |
| | | // å é¤éä»¶ |
| | | storageAttachmentApi.deleteAttachmentsByRecord("crm_follow_up_record", id); |
| | | // å é¤ |
| | | crmFollowUpRecordMapper.deleteById(id); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteFollowUpRecordByBiz(Integer bizType, Long bizId) { |
| | | List<CrmFollowUpRecordDO> records = crmFollowUpRecordMapper.selectListByBiz(bizType, List.of(bizId)); |
| | | for (CrmFollowUpRecordDO record : records) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("crm_follow_up_record", record.getId()); |
| | | } |
| | | crmFollowUpRecordMapper.deleteByBiz(bizType, bizId); |
| | | } |
| | | |
| | |
| | | */ |
| | | private List<String> picUrls; |
| | | /** |
| | | * éä»¶ |
| | | */ |
| | | private List<String> fileUrls; |
| | | |
| | | /** |
| | | * å
³èçåæºç¼å·æ°ç» |
| | | * |
| | | * å
³è {@link CrmBusinessDO#getId()} |
| | |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| | | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import jakarta.annotation.Resource; |
| | |
| | | @Resource |
| | | private CrmPermissionService permissionService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private CrmContractService contractService; |
| | | |
| | | @Override |
| | |
| | | .setBizType(CrmBizTypeEnum.CRM_SALE_QUOTATION.getType()) |
| | | .setBizId(saleQuotation.getId()) |
| | | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); |
| | | storageAttachmentApi.bindAttachments("file", "crm_sale_quotation", |
| | | saleQuotation.getId(), createReqVO.getBlobIds()); |
| | | return saleQuotation.getId(); |
| | | } |
| | | |
| | |
| | | saleQuotationMapper.updateById(updateObj); |
| | | // 2.2 æ´æ°æ¥ä»·æç» |
| | | updateQuotationProductList(updateReqVO.getId(), quotationProducts); |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("crm_sale_quotation", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "crm_sale_quotation", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | // 2. éåå é¤ |
| | | saleQuotations.forEach(saleQuotation -> { |
| | | // 2.0 å é¤éä»¶å
³è |
| | | storageAttachmentApi.deleteAttachmentsByRecord("crm_sale_quotation", saleQuotation.getId()); |
| | | // 2.1 å 餿¥ä»·å |
| | | saleQuotationMapper.deleteById(saleQuotation.getId()); |
| | | // 2.2 å 餿¥ä»·æç» |
| | |
| | | @Schema(description = "å®ééé¢ï¼åä½ï¼å
", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") |
| | | private BigDecimal depositPrice; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://www.iocoder.cn") |
| | | @ExcelProperty("éä»¶å°å") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "夿³¨", example = "ä½ ç") |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | |
| | | @Schema(description = "å®ééé¢ï¼åä½ï¼å
", example = "7127") |
| | | private BigDecimal depositPrice; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://www.iocoder.cn") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "夿³¨", example = "ä½ ç") |
| | | private String remark; |
| | | |
| | |
| | | @Schema(description = "å
¥åºç¶æï¼0:æªå
¥åº 1:é¨åå
¥åº 2:å
¨é¨å
¥åºï¼", example = "0") |
| | | private Integer inStatus; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨") |
| | | private String remark; |
| | | |
| | |
| | | @Schema(description = "å®ééé¢", example = "1000.00") |
| | | private BigDecimal depositPrice; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨") |
| | | private String remark; |
| | | |
| | |
| | | @Schema(description = "å®ééé¢ï¼åä½ï¼å
", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") |
| | | private BigDecimal depositPrice; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://www.iocoder.cn") |
| | | @ExcelProperty("éä»¶å°å") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "夿³¨", example = "ä½ ç") |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | |
| | | @Schema(description = "å®ééé¢ï¼åä½ï¼å
", example = "7127") |
| | | private BigDecimal depositPrice; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://www.iocoder.cn") |
| | | private String fileUrl; |
| | | |
| | | @Schema(description = "夿³¨", example = "ä½ ç") |
| | | private String remark; |
| | | |
| | |
| | | private BigDecimal depositPrice; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | private BigDecimal depositPrice; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | private BigDecimal depositPrice; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - 请åç³è¯· Response VO") |
| | | @Data |
| | |
| | | @Schema(description = "审æ¹å®ææ¶é´", example = "2024-01-01 10:00:00") |
| | | private LocalDateTime approveTime; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - 请åç³è¯·æ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | |
| | | @NotEmpty(message = "请ååå ä¸è½ä¸ºç©º") |
| | | private String reason; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - 离èç³è¯· Response VO") |
| | | @Data |
| | |
| | | @Schema(description = "审æ¹å®ææ¶é´", example = "2024-01-01 10:00:00") |
| | | private LocalDateTime approveTime; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - 离èç³è¯·æ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | |
| | | @Schema(description = "交æ¥è¯´æ", example = "交æ¥è¯´æ") |
| | | private String handoverRemark; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - è°å²ç³è¯· Response VO") |
| | | @Data |
| | |
| | | @Schema(description = "审æ¹å®ææ¶é´", example = "2024-01-01 10:00:00") |
| | | private LocalDateTime approveTime; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - è°å²ç³è¯·æ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | |
| | | @NotEmpty(message = "è°å²åå ä¸è½ä¸ºç©º") |
| | | private String reason; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | |
| | | private HrmEmployeeService employeeService; |
| | | @Resource |
| | | private DeptApi deptApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "æ°å¢èå¤å¼å¸¸ç³è¯·") |
| | |
| | | respVO.setDeptName(dept.getName()); |
| | | } |
| | | } |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_attendance_exception", id)); |
| | | return success(respVO); |
| | | } |
| | | |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - èå¤å¼å¸¸ç³è¯· Response VO") |
| | | @Data |
| | |
| | | @ExcelProperty("审æ¹å®ææ¶é´") |
| | | private LocalDateTime approveTime; |
| | | |
| | | @Schema(description = "éä»¶å°å") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | @ExcelProperty("夿³¨") |
| | |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - èå¤å¼å¸¸ç³è¯·æ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | |
| | | @NotEmpty(message = "ç³è¯·åå ä¸è½ä¸ºç©º") |
| | | private String reason; |
| | | |
| | | @Schema(description = "éä»¶å°å", example = "https://xxx.com/xxx.jpg") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | |
| | | import cn.iocoder.yudao.module.hrm.service.salary.HrmSalaryPaymentService; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | |
| | | private HrmEmployeeService employeeService; |
| | | @Resource |
| | | private DeptApi deptApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @GetMapping("/page") |
| | | @Operation(summary = "è·å¾èªèµåæ¾å页") |
| | |
| | | @PreAuthorize("@ss.hasPermission('hrm:salary:query')") |
| | | public CommonResult<HrmSalaryPaymentRespVO> getSalaryPayment(@RequestParam("id") Long id) { |
| | | HrmSalaryPaymentDO salaryPayment = salaryPaymentService.getSalaryPayment(id); |
| | | return success(BeanUtils.toBean(salaryPayment, HrmSalaryPaymentRespVO.class)); |
| | | HrmSalaryPaymentRespVO respVO = BeanUtils.toBean(salaryPayment, HrmSalaryPaymentRespVO.class); |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_salary_payment", id)); |
| | | return success(respVO); |
| | | } |
| | | |
| | | @PostMapping("/generate") |
| | |
| | | package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - èªèµåæ¾ Response VO") |
| | | @Data |
| | |
| | | @DictFormat("hrm_payment_status") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "é¶è¡ååéä»¶") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | @ExcelProperty("夿³¨") |
| | |
| | | private LocalDateTime approveTime; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | private java.time.LocalDateTime approveTime; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | private java.time.LocalDateTime approveTime; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | private LocalDateTime approveTime; |
| | | |
| | | /** |
| | | * éä»¶å°å |
| | | */ |
| | | private String fileUrl; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | private Integer status; |
| | | |
| | | /** |
| | | * é¶è¡ååéä»¶ |
| | | */ |
| | | private String fileUrl; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmLeaveTypeEnum; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import jakarta.annotation.Resource; |
| | |
| | | @Resource |
| | | private BpmCategoryService bpmCategoryService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | |
| | | @Override |
| | |
| | | application.setDeptId(createReqVO.getDeptId() != null ? createReqVO.getDeptId() : user.getDeptId()); |
| | | application.setStatus(HrmAuditStatusEnum.DRAFT.getStatus()); |
| | | leaveApplicationMapper.insert(application); |
| | | // ç»å®éä»¶ |
| | | storageAttachmentApi.bindAttachments("file", "hrm_leave_application", |
| | | application.getId(), createReqVO.getBlobIds()); |
| | | return application.getId(); |
| | | } |
| | | |
| | |
| | | // æ´æ° |
| | | HrmLeaveApplicationDO updateObj = BeanUtils.toBean(updateReqVO, HrmLeaveApplicationDO.class); |
| | | leaveApplicationMapper.updateById(updateObj); |
| | | // éæ°ç»å®éä»¶ |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_leave_application", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_leave_application", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) { |
| | | throw exception(LEAVE_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | // å é¤éä»¶å
³è |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_leave_application", id); |
| | | // å é¤ |
| | | leaveApplicationMapper.deleteById(id); |
| | | } |
| | |
| | | respVO.setLeaveTypeName(HrmLeaveTypeEnum.getNameByStatus(application.getLeaveType())); |
| | | // å¡«å
审æ¹ç¶æåç§° |
| | | respVO.setStatusName(HrmAuditStatusEnum.getNameByStatus(application.getStatus())); |
| | | // å¡«å
éä»¶å表 |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_leave_application", id)); |
| | | return respVO; |
| | | } |
| | | |
| | |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmResignationTypeEnum; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import jakarta.annotation.Resource; |
| | |
| | | @Resource |
| | | private BpmCategoryService bpmCategoryService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | |
| | | @Override |
| | |
| | | application.setStatus(HrmAuditStatusEnum.DRAFT.getStatus()); |
| | | application.setHandoverStatus(HANDOVER_STATUS_NOT_STARTED); |
| | | resignationApplicationMapper.insert(application); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_resignation_application", |
| | | application.getId(), createReqVO.getBlobIds()); |
| | | return application.getId(); |
| | | } |
| | | |
| | |
| | | } |
| | | HrmResignationApplicationDO updateObj = BeanUtils.toBean(updateReqVO, HrmResignationApplicationDO.class); |
| | | resignationApplicationMapper.updateById(updateObj); |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_resignation_application", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_resignation_application", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) { |
| | | throw exception(RESIGNATION_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_resignation_application", id); |
| | | resignationApplicationMapper.deleteById(id); |
| | | } |
| | | |
| | |
| | | respVO.setResignationTypeName(HrmResignationTypeEnum.getNameByStatus(application.getResignationType())); |
| | | respVO.setHandoverStatusName(getHandoverStatusName(application.getHandoverStatus())); |
| | | respVO.setStatusName(HrmAuditStatusEnum.getNameByStatus(application.getStatus())); |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_resignation_application", id)); |
| | | return respVO; |
| | | } |
| | | |
| | |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmTransferTypeEnum; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.PostApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | |
| | | @Resource |
| | | private BpmCategoryService bpmCategoryService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | |
| | | @Override |
| | |
| | | application.setUserId(userId); |
| | | application.setStatus(HrmAuditStatusEnum.DRAFT.getStatus()); |
| | | transferApplicationMapper.insert(application); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_transfer_application", |
| | | application.getId(), createReqVO.getBlobIds()); |
| | | return application.getId(); |
| | | } |
| | | |
| | |
| | | } |
| | | HrmTransferApplicationDO updateObj = BeanUtils.toBean(updateReqVO, HrmTransferApplicationDO.class); |
| | | transferApplicationMapper.updateById(updateObj); |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_transfer_application", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_transfer_application", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (!Objects.equals(application.getStatus(), HrmAuditStatusEnum.DRAFT.getStatus())) { |
| | | throw exception(TRANSFER_APPLICATION_UPDATE_FAIL_NOT_DRAFT); |
| | | } |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_transfer_application", id); |
| | | transferApplicationMapper.deleteById(id); |
| | | } |
| | | |
| | |
| | | fillPostNames(respVO, application); |
| | | respVO.setTransferTypeName(HrmTransferTypeEnum.getNameByStatus(application.getTransferType())); |
| | | respVO.setStatusName(HrmAuditStatusEnum.getNameByStatus(application.getStatus())); |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("hrm_transfer_application", id)); |
| | | return respVO; |
| | | } |
| | | |
| | |
| | | import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.HrmAttendanceExceptionSaveReqVO; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.attendance.HrmAttendanceExceptionDO; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.attendance.HrmAttendanceExceptionMapper; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum; |
| | | import jakarta.annotation.Resource; |
| | |
| | | @Resource |
| | | private BpmProcessInstanceApi bpmProcessInstanceApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | |
| | | @Override |
| | |
| | | attendanceException.setNo(generateNo()); |
| | | attendanceException.setStatus(HrmAuditStatusEnum.DRAFT.getStatus()); |
| | | attendanceExceptionMapper.insert(attendanceException); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_attendance_exception", |
| | | attendanceException.getId(), createReqVO.getBlobIds()); |
| | | return attendanceException.getId(); |
| | | } |
| | | |
| | |
| | | validateAttendanceExceptionExists(updateReqVO.getId()); |
| | | HrmAttendanceExceptionDO updateObj = BeanUtils.toBean(updateReqVO, HrmAttendanceExceptionDO.class); |
| | | attendanceExceptionMapper.updateById(updateObj); |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_attendance_exception", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "hrm_attendance_exception", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void deleteAttendanceException(Long id) { |
| | | validateAttendanceExceptionExists(id); |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_attendance_exception", id); |
| | | attendanceExceptionMapper.deleteById(id); |
| | | } |
| | | |
| | |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryPaymentDetailMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.mysql.salary.HrmSalaryPaymentMapper; |
| | | import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private HrmSalaryCalculationMapper salaryCalculationMapper; |
| | | @Resource |
| | | private HrmNoRedisDAO noRedisDAO; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | public PageResult<HrmSalaryPaymentDO> getSalaryPaymentPage(HrmSalaryPaymentPageReqVO pageReqVO) { |
| | |
| | | for (HrmSalaryPaymentDetailDO detail : details) { |
| | | salaryPaymentDetailMapper.deleteById(detail.getId()); |
| | | } |
| | | // å é¤éä»¶å
³è |
| | | storageAttachmentApi.deleteAttachmentsByRecord("hrm_salary_payment", id); |
| | | // å é¤åæ¾å°è´¦ |
| | | salaryPaymentMapper.deleteById(id); |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mdm.service.item.MdmItemService; |
| | | import cn.iocoder.yudao.module.mdm.service.unit.MdmUnitMeasureService; |
| | | import cn.iocoder.yudao.module.mdm.service.warehouse.MdmWarehouseService; |
| | | import cn.iocoder.yudao.module.mes.api.item.MesMdItemApi; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | |
| | | |
| | | @Resource |
| | | private MdmItemService itemService; |
| | | |
| | | @Resource |
| | | private MesMdItemApi mesMdItemApi; |
| | | |
| | | @Resource |
| | | private MdmItemCategoryService itemCategoryService; |
| | |
| | | enrichItemRespVO(resp); |
| | | // å¡«å
æ¹æ¬¡å±æ§é
ç½® |
| | | enrichItemBatchConfig(resp); |
| | | // å¡«å
åæ¥ç¶æ |
| | | resp.setSyncedMes(mesMdItemApi.getSyncedMdmItemIds(Set.of(id)).contains(id)); |
| | | } |
| | | return success(resp); |
| | | } |
| | |
| | | convertSet(pageResult.getList(), MdmItemDO::getUnitMeasureId)); |
| | | // è½¬æ¢ |
| | | List<MdmItemRespVO> respList = BeanUtils.toBean(pageResult.getList(), MdmItemRespVO.class); |
| | | // æ¹éæ¥è¯¢åæ¥ç¶æ |
| | | Set<Long> allIds = convertSet(respList, MdmItemRespVO::getId); |
| | | Set<Long> syncedIds = mesMdItemApi.getSyncedMdmItemIds(allIds); |
| | | // æ¹éå
³èæ¥è¯¢è¾
åä½åç§° |
| | | Set<Long> unitIds = new HashSet<>(); |
| | | respList.forEach(resp -> { |
| | |
| | | if (warehouse != null) { |
| | | resp.setWarehouseName(warehouse.getName()); |
| | | } |
| | | // åæ¥ç¶æ |
| | | resp.setSyncedMes(syncedIds.contains(resp.getId())); |
| | | }); |
| | | return success(new PageResult<>(respList, pageResult.getTotal())); |
| | | } |
| | |
| | | @Schema(description = "夿³¨", example = "夿³¨ä¿¡æ¯") |
| | | private String remark; |
| | | |
| | | @Schema(description = "æ¯å¦å·²åæ¥å° MES", example = "true") |
| | | private Boolean syncedMes; |
| | | |
| | | @Schema(description = "å建æ¶é´", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | private LocalDateTime createTime; |
| | | |
| | |
| | | // ä¿åæ¹æ¬¡é
ç½®ï¼å¦ææï¼ |
| | | saveBatchConfig(item.getId(), createReqVO); |
| | | |
| | | // åæ¥å° MESï¼å¾é syncMes æ¶ï¼ |
| | | // å§ç»åæ¥å° MES |
| | | createReqVO.setId(item.getId()); |
| | | if (Boolean.TRUE.equals(createReqVO.getSyncMes())) { |
| | | syncItemToMes(createReqVO); |
| | | } |
| | | syncItemToMes(createReqVO); |
| | | return item.getId(); |
| | | } |
| | | |
| | |
| | | // ä¿åæ¹æ¬¡é
ç½®ï¼å¦ææï¼ |
| | | saveBatchConfig(updateReqVO.getId(), updateReqVO); |
| | | |
| | | // åæ¥å° MESï¼å¾é syncMes æ¶ï¼ |
| | | if (Boolean.TRUE.equals(updateReqVO.getSyncMes())) { |
| | | syncItemToMes(updateReqVO); |
| | | } |
| | | // å§ç»åæ¥å° MES |
| | | syncItemToMes(updateReqVO); |
| | | } |
| | | |
| | | private void validateItemSaveData(MdmItemSaveReqVO reqVO) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateItemStatus(Long id, Integer status) { |
| | | // æ ¡éªåå¨ |
| | | validateItemExists(id); |
| | | // æ´æ°ç¶æ |
| | | itemMapper.updateById(new MdmItemDO().setId(id).setStatus(status)); |
| | | // åæ¥ç¶æå° MES |
| | | mesMdItemApi.updateItemStatus(id, status); |
| | | } |
| | | |
| | | @Override |
| | |
| | | validateItemNoReference(id); |
| | | // 软å é¤å½åè®°å½ |
| | | itemMapper.deleteById(id); |
| | | // 忥å é¤å° MES |
| | | mesMdItemApi.deleteItem(id); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | import cn.iocoder.yudao.module.mes.api.item.dto.MesMdItemSyncReqDTO; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * MES ç©æäº§å API æ¥å£ |
| | | * |
| | |
| | | */ |
| | | void updateItem(MesMdItemSyncReqDTO syncReqDTO); |
| | | |
| | | /** |
| | | * å é¤ MES ç©æäº§åï¼åæ¥ç¨ï¼ |
| | | * |
| | | * æ MDM ç©æ ID æ¥æ¾ MES è®°å½å¹¶å é¤ï¼ä¸åå¨å忽ç¥ã |
| | | * |
| | | * @param mdmItemId MDM ç©æ ID |
| | | */ |
| | | void deleteItem(Long mdmItemId); |
| | | |
| | | /** |
| | | * æ´æ° MES ç©æäº§åç¶æï¼åæ¥ç¨ï¼ |
| | | * |
| | | * æ MDM ç©æ ID æ¥æ¾ MES è®°å½å¹¶æ´æ°ç¶æï¼ä¸åå¨å忽ç¥ã |
| | | * |
| | | * @param mdmItemId MDM ç©æ ID |
| | | * @param status ç¶æ |
| | | */ |
| | | void updateItemStatus(Long mdmItemId, Integer status); |
| | | |
| | | /** |
| | | * è·åå·²åæ¥å° MES ç MDM ç©æ ID éå |
| | | * |
| | | * @param mdmItemIds MDM ç©æ ID å表 |
| | | * @return åå¨äº MES ä¸ç MDM ç©æ ID éå |
| | | */ |
| | | Set<Long> getSyncedMdmItemIds(Collection<Long> mdmItemIds); |
| | | |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Set; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | |
| | | |
| | | @Resource |
| | | private MesMdItemService itemService; |
| | | @Resource |
| | | private MesMdItemMapper itemMapper; |
| | | @Resource |
| | | private MesMdItemTypeService itemTypeService; |
| | | @Resource |
| | |
| | | return saveReqVO; |
| | | } |
| | | |
| | | @Override |
| | | public void deleteItem(Long mdmItemId) { |
| | | log.info("[deleteItem] 忥å é¤ MES ç©æäº§åï¼mdmItemId={}", mdmItemId); |
| | | MesMdItemDO existItem = itemService.getItemByMdmItemId(mdmItemId); |
| | | if (existItem != null) { |
| | | itemService.deleteItem(existItem.getId()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void updateItemStatus(Long mdmItemId, Integer status) { |
| | | log.info("[updateItemStatus] åæ¥æ´æ° MES ç©æäº§åç¶æï¼mdmItemId={}, status={}", mdmItemId, status); |
| | | MesMdItemDO existItem = itemService.getItemByMdmItemId(mdmItemId); |
| | | if (existItem != null) { |
| | | itemService.updateItemStatus(existItem.getId(), status); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Set<Long> getSyncedMdmItemIds(Collection<Long> mdmItemIds) { |
| | | return itemMapper.selectMdmItemIdsByMdmItemIds(mdmItemIds); |
| | | } |
| | | |
| | | /** |
| | | * ä¿åæ¹æ¬¡é
ç½® |
| | | */ |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.pd.archive.vo; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| | | import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; |
| | |
| | | @Schema(description = "æä»¶å", example = "design.pdf") |
| | | private String fileName; |
| | | |
| | | @Schema(description = "æä»¶URL", example = "/files/design.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "ä¸ä¼ 人", example = "1") |
| | | private Long uploadUserId; |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pd.document.vo.MesPdDocumentSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pd.document.MesPdDocumentDO; |
| | | import cn.iocoder.yudao.module.mes.service.pd.document.MesPdDocumentService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "åå»ºè®¾è®¡èµæ") |
| | |
| | | if (document == null) { |
| | | return success(null); |
| | | } |
| | | return success(buildDocumentRespVOList(Collections.singletonList(document)).get(0)); |
| | | MesPdDocumentRespVO respVO = buildDocumentRespVOList(Collections.singletonList(document)).get(0); |
| | | respVO.setAttachmentList(storageAttachmentApi.listAttachments("mes_pd_document", id)); |
| | | return success(respVO); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | package cn.iocoder.yudao.module.mes.controller.admin.pd.document.vo; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| | | import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; |
| | | import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; |
| | |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - MES è®¾è®¡èµæ Response VO") |
| | | @Data |
| | |
| | | @ExcelProperty("ä¸ä¼ æ¶é´") |
| | | private LocalDateTime uploadTime; |
| | | |
| | | @Schema(description = "æä»¶URL", example = "https://xxx/file.pdf") |
| | | @ExcelProperty("æä»¶URL") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶å表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "夿³¨", example = "æµè¯å¤æ³¨") |
| | | @ExcelProperty("夿³¨") |
| | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - MES è®¾è®¡èµææ°å¢/ä¿®æ¹ Request VO") |
| | | @Data |
| | |
| | | @Schema(description = "ä¸ä¼ æ¶é´") |
| | | private LocalDateTime uploadTime; |
| | | |
| | | @Schema(description = "æä»¶URL", example = "https://xxx/file.pdf") |
| | | private String fileUrl; |
| | | @Schema(description = "éä»¶blobIdå表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "夿³¨", example = "æµè¯å¤æ³¨") |
| | | private String remark; |
| | |
| | | convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); |
| | | Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap( |
| | | convertSet(list, MesProTaskDO::getClientId)); |
| | | // å·¥åºç checkFlagï¼æ¹éæ¥è¯¢åæå»º routeId -> processId -> checkFlag çåå± Map |
| | | // å·¥åºç checkFlag + backflushFlagï¼æ¹éæ¥è¯¢åæå»º routeId -> processId -> flag çåå± Map |
| | | Set<Long> routeIds = convertSet(list, MesProTaskDO::getRouteId); |
| | | Map<Long, Map<Long, Boolean>> routeProcessCheckFlagMap = new HashMap<>(); |
| | | Map<Long, Map<Long, Boolean>> routeProcessBackflushFlagMap = new HashMap<>(); |
| | | if (CollUtil.isNotEmpty(routeIds)) { |
| | | List<MesProRouteProcessDO> allRouteProcesses = routeProcessService.getRouteProcessListByRouteIds(routeIds); |
| | | for (MesProRouteProcessDO rp : allRouteProcesses) { |
| | | routeProcessCheckFlagMap |
| | | .computeIfAbsent(rp.getRouteId(), k -> new HashMap<>()) |
| | | .put(rp.getProcessId(), Boolean.TRUE.equals(rp.getCheckFlag())); |
| | | routeProcessBackflushFlagMap |
| | | .computeIfAbsent(rp.getRouteId(), k -> new HashMap<>()) |
| | | .put(rp.getProcessId(), Boolean.TRUE.equals(rp.getBackflushFlag())); |
| | | } |
| | | } |
| | | // æ¥å·¥å¨ééï¼æä»»å¡èå feedbackQuantityï¼è稿/审æ¹ä¸/å¾
æ£éª = å¨éï¼å·²å®æ = 已审æ¹ï¼ |
| | |
| | | vo.setClientName(customer.getName())); |
| | | findAndThen(routeProcessCheckFlagMap, task.getRouteId(), processCheckMap -> |
| | | findAndThen(processCheckMap, task.getProcessId(), vo::setCheckFlag)); |
| | | findAndThen(routeProcessBackflushFlagMap, task.getRouteId(), processBackflushMap -> |
| | | findAndThen(processBackflushMap, task.getProcessId(), vo::setBackflushFlag)); |
| | | return vo; |
| | | }); |
| | | } |
| | |
| | | @Schema(description = "æ¯å¦è´¨æ£ï¼æ´¾çèªå·¥èºè·¯çº¿å·¥åº checkFlagï¼", example = "true") |
| | | private Boolean checkFlag; |
| | | |
| | | @Schema(description = "æ¯å¦åå²ï¼æ´¾çèªå·¥èºè·¯çº¿å·¥åº backflushFlagï¼", example = "true") |
| | | private Boolean backflushFlag; |
| | | |
| | | @Schema(description = "夿³¨", example = "夿³¨") |
| | | private String remark; |
| | | |
| | |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProProcessBomItemVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.process.MesProWorkOrderProcessPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.process.MesProWorkOrderProcessRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.process.MesProWorkOrderProcessSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.Parameter; |
| | |
| | | |
| | | @Resource |
| | | private MesProWorkOrderProcessService workOrderProcessService; |
| | | @Resource |
| | | private MesProWorkOrderBomService workOrderBomService; |
| | | @Resource |
| | | private MesProProcessService processService; |
| | | @Resource |
| | |
| | | Map<Long, MesMdItemDO> itemMap = CollUtil.isNotEmpty(outputItemIds) |
| | | ? itemService.getItemMap(outputItemIds) : Collections.emptyMap(); |
| | | |
| | | // 2. æ¼æ¥ VO |
| | | return BeanUtils.toBean(list, MesProWorkOrderProcessRespVO.class, vo -> { |
| | | // 2. æ¥è¯¢ææBOMï¼æå·¥åºåç»ï¼ |
| | | Set<Long> workOrderIds = convertSet(list, MesProWorkOrderProcessDO::getWorkOrderId); |
| | | workOrderIds.removeAll(Collections.singleton(null)); |
| | | Map<Long, List<MesProProcessBomItemVO>> bomItemsByProcessId = new HashMap<>(); |
| | | Set<Long> allBomItemIds = new HashSet<>(); |
| | | for (Long woId : workOrderIds) { |
| | | List<MesProWorkOrderBomDO> bomList = workOrderBomService.getWorkOrderBomListByWorkOrderId(woId); |
| | | if (CollUtil.isNotEmpty(bomList)) { |
| | | allBomItemIds.addAll(convertSet(bomList, MesProWorkOrderBomDO::getItemId)); |
| | | for (MesProWorkOrderBomDO bom : bomList) { |
| | | bomItemsByProcessId.computeIfAbsent(bom.getProcessId(), k -> new ArrayList<>()) |
| | | .add(BeanUtils.toBean(bom, MesProProcessBomItemVO.class)); |
| | | } |
| | | } |
| | | } |
| | | // å¡«å
ææç©æç¼ç ååç§° |
| | | Map<Long, MesMdItemDO> bomItemMap = CollUtil.isNotEmpty(allBomItemIds) |
| | | ? itemService.getItemMap(allBomItemIds) : Collections.emptyMap(); |
| | | bomItemsByProcessId.values().forEach(vos -> vos.forEach(vo -> { |
| | | MapUtils.findAndThen(bomItemMap, vo.getItemId(), item -> { |
| | | vo.setItemCode(item.getCode()).setItemName(item.getName()); |
| | | }); |
| | | })); |
| | | |
| | | // 3. æ¼æ¥ VO |
| | | List<MesProWorkOrderProcessRespVO> result = BeanUtils.toBean(list, MesProWorkOrderProcessRespVO.class, vo -> { |
| | | MapUtils.findAndThen(processMap, vo.getProcessId(), process -> { |
| | | vo.setProcessCode(process.getCode()).setProcessName(process.getName()); |
| | | }); |
| | |
| | | vo.setOutputItemCode(item.getCode()).setOutputItemName(item.getName()); |
| | | }); |
| | | }); |
| | | // 设置æ¯ä¸ªå·¥åºåèªçææBOM |
| | | result.forEach(vo -> vo.setBomItems(bomItemsByProcessId.getOrDefault(vo.getProcessId(), Collections.emptyList()))); |
| | | return result; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProProcessBomItemVO; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管çåå° - MES ç产工åå·¥åº Response VO") |
| | | @Data |
| | |
| | | @ExcelProperty("夿³¨") |
| | | private String remark; |
| | | |
| | | @Schema(description = "å·¥åºææBOMæç»") |
| | | private List<MesProProcessBomItemVO> bomItems; |
| | | |
| | | @Schema(description = "å建æ¶é´", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @ExcelProperty("å建æ¶é´") |
| | | private LocalDateTime createTime; |
| | |
| | | */ |
| | | private LocalDateTime uploadTime; |
| | | /** |
| | | * æä»¶URL |
| | | */ |
| | | private String fileUrl; |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | |
| | | */ |
| | | private Long workOrderId; |
| | | /** |
| | | * å·¥åºç¼å· |
| | | * |
| | | * å
³è {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO#getId()} |
| | | */ |
| | | private Long processId; |
| | | /** |
| | | * BOM ç©æç¼å· |
| | | * |
| | | * å
³è {@link MesMdItemDO#getId()} |
| | |
| | | package cn.iocoder.yudao.module.mes.dal.mysql.md.item; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| | | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| | |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| | | |
| | | /** |
| | | * MES ç©æäº§å Mapper |
| | |
| | | return selectOne(MesMdItemDO::getMdmItemId, mdmItemId); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæ¥è¯¢å·²åå¨ç MDM ç©æ ID éå |
| | | * |
| | | * @param mdmItemIds MDM ç©æ ID å表 |
| | | * @return åå¨äº mes_md_item ä¸ç mdmItemId éå |
| | | */ |
| | | default Set<Long> selectMdmItemIdsByMdmItemIds(Collection<Long> mdmItemIds) { |
| | | if (CollUtil.isEmpty(mdmItemIds)) { |
| | | return Collections.emptySet(); |
| | | } |
| | | List<MesMdItemDO> list = selectList(MesMdItemDO::getMdmItemId, mdmItemIds); |
| | | return convertSet(list, MesMdItemDO::getMdmItemId); |
| | | } |
| | | |
| | | } |
| | |
| | | return selectList(MesProWorkOrderBomDO::getWorkOrderId, workOrderId); |
| | | } |
| | | |
| | | default List<MesProWorkOrderBomDO> selectListByWorkOrderIdAndProcessId(Long workOrderId, Long processId) { |
| | | return selectList(new LambdaQueryWrapperX<MesProWorkOrderBomDO>() |
| | | .eq(MesProWorkOrderBomDO::getWorkOrderId, workOrderId) |
| | | .eqIfPresent(MesProWorkOrderBomDO::getProcessId, processId)); |
| | | } |
| | | |
| | | default void deleteByWorkOrderId(Long workOrderId) { |
| | | delete(MesProWorkOrderBomDO::getWorkOrderId, workOrderId); |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pd.document.MesPdDocumentDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pd.document.MesPdDocumentMapper; |
| | | import cn.iocoder.yudao.module.mes.service.pd.project.MesPdProjectService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @Resource |
| | | @Lazy |
| | | private MesPdProjectService projectService; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | public Long createDocument(MesPdDocumentSaveReqVO createReqVO) { |
| | |
| | | // æå
¥ |
| | | MesPdDocumentDO document = BeanUtils.toBean(createReqVO, MesPdDocumentDO.class); |
| | | documentMapper.insert(document); |
| | | storageAttachmentApi.bindAttachments("file", "mes_pd_document", |
| | | document.getId(), createReqVO.getBlobIds()); |
| | | return document.getId(); |
| | | } |
| | | |
| | |
| | | // æ´æ° |
| | | MesPdDocumentDO updateObj = BeanUtils.toBean(updateReqVO, MesPdDocumentDO.class); |
| | | documentMapper.updateById(updateObj); |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("mes_pd_document", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "mes_pd_document", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void deleteDocument(Long id) { |
| | | // æ ¡éªåå¨ |
| | | validateDocumentExists(id); |
| | | // å é¤éä»¶ |
| | | storageAttachmentApi.deleteAttachmentsByRecord("mes_pd_document", id); |
| | | // å é¤ |
| | | documentMapper.deleteById(id); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void deleteByProjectId(Long projectId) { |
| | | List<MesPdDocumentDO> documents = documentMapper.selectListByProjectId(projectId); |
| | | for (MesPdDocumentDO document : documents) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("mes_pd_document", document.getId()); |
| | | } |
| | | documentMapper.deleteByProjectId(projectId); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * ä»å·¥åºåè¡¨ä¸æå BOM ææï¼åå¹¶å»éåä¿åå°å·¥å BOM 表 |
| | | * ä»å·¥åºåè¡¨ä¸æå BOM ææï¼æå·¥åºåå«ä¿åå°å·¥å BOM 表 |
| | | */ |
| | | private void saveWorkOrderBomFromProcesses(Long workOrderId, List<MesProWorkOrderProcessSaveReqVO> list) { |
| | | // æ¶éææå·¥åºç bomItemsï¼æ itemId å»éï¼ä¿ç第ä¸ä¸ªåºç°ç quantityï¼ |
| | | java.util.Map<Long, MesProWorkOrderProcessSaveReqVO.BomItem> merged = new java.util.LinkedHashMap<>(); |
| | | workOrderBomService.deleteWorkOrderBomByWorkOrderId(workOrderId); |
| | | List<MesProWorkOrderBomDO> bomList = new ArrayList<>(); |
| | | for (MesProWorkOrderProcessSaveReqVO item : list) { |
| | | if (CollUtil.isNotEmpty(item.getBomItems())) { |
| | | for (MesProWorkOrderProcessSaveReqVO.BomItem bomItem : item.getBomItems()) { |
| | | if (bomItem.getItemId() != null) { |
| | | merged.putIfAbsent(bomItem.getItemId(), bomItem); |
| | | bomList.add(MesProWorkOrderBomDO.builder() |
| | | .workOrderId(workOrderId) |
| | | .processId(item.getProcessId()) |
| | | .itemId(bomItem.getItemId()) |
| | | .quantity(bomItem.getQuantity()) |
| | | .remark(bomItem.getRemark()) |
| | | .build()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // å 餿§ BOMï¼æ¹éæå
¥æ° BOM |
| | | workOrderBomService.deleteWorkOrderBomByWorkOrderId(workOrderId); |
| | | if (CollUtil.isNotEmpty(merged)) { |
| | | List<MesProWorkOrderBomDO> bomList = new ArrayList<>(merged.size()); |
| | | for (MesProWorkOrderProcessSaveReqVO.BomItem bomItem : merged.values()) { |
| | | bomList.add(MesProWorkOrderBomDO.builder() |
| | | .workOrderId(workOrderId) |
| | | .itemId(bomItem.getItemId()) |
| | | .quantity(bomItem.getQuantity()) |
| | | .remark(bomItem.getRemark()) |
| | | .build()); |
| | | } |
| | | if (CollUtil.isNotEmpty(bomList)) { |
| | | workOrderBomMapper.insertBatch(bomList); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.api.storage; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | |
| | | import java.util.List; |
| | | |
| | | public interface StorageAttachmentApi { |
| | | |
| | | void bindAttachments(String application, String recordType, Long recordId, List<Long> blobIds); |
| | | |
| | | List<StorageBlobRespDTO> listAttachments(String recordType, Long recordId); |
| | | |
| | | void deleteAttachments(List<Long> attachmentIds); |
| | | |
| | | void deleteAttachmentsByRecord(String recordType, Long recordId); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.api.storage; |
| | | |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.storage.vo.SystemStorageAttachmentListReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.storage.vo.SystemStorageAttachmentSaveReqVO; |
| | | import cn.iocoder.yudao.module.system.controller.admin.storage.vo.SystemStorageBlobRespVO; |
| | | import cn.iocoder.yudao.module.system.service.storage.SystemStorageAttachmentService; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | @Service |
| | | public class StorageAttachmentApiImpl implements StorageAttachmentApi { |
| | | |
| | | @Resource |
| | | private SystemStorageAttachmentService systemStorageAttachmentService; |
| | | |
| | | @Override |
| | | public void bindAttachments(String application, String recordType, Long recordId, List<Long> blobIds) { |
| | | if (blobIds == null || blobIds.isEmpty()) { |
| | | return; |
| | | } |
| | | SystemStorageAttachmentSaveReqVO reqVO = new SystemStorageAttachmentSaveReqVO(); |
| | | reqVO.setApplication(application != null ? application : "file"); |
| | | reqVO.setRecordType(recordType); |
| | | reqVO.setRecordId(recordId); |
| | | List<SystemStorageAttachmentSaveReqVO.BlobItem> blobItems = new ArrayList<>(); |
| | | for (Long blobId : blobIds) { |
| | | SystemStorageAttachmentSaveReqVO.BlobItem item = new SystemStorageAttachmentSaveReqVO.BlobItem(); |
| | | item.setBlobId(blobId); |
| | | blobItems.add(item); |
| | | } |
| | | reqVO.setBlobItems(blobItems); |
| | | systemStorageAttachmentService.bindAttachments(reqVO); |
| | | } |
| | | |
| | | @Override |
| | | public List<StorageBlobRespDTO> listAttachments(String recordType, Long recordId) { |
| | | SystemStorageAttachmentListReqVO reqVO = new SystemStorageAttachmentListReqVO(); |
| | | reqVO.setRecordType(recordType); |
| | | reqVO.setRecordId(recordId); |
| | | List<SystemStorageBlobRespVO> list = systemStorageAttachmentService.listAttachments(reqVO); |
| | | return BeanUtils.toBean(list, StorageBlobRespDTO.class); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteAttachments(List<Long> attachmentIds) { |
| | | if (attachmentIds == null || attachmentIds.isEmpty()) { |
| | | return; |
| | | } |
| | | systemStorageAttachmentService.deleteAttachments(attachmentIds); |
| | | } |
| | | |
| | | @Override |
| | | public void deleteAttachmentsByRecord(String recordType, Long recordId) { |
| | | systemStorageAttachmentService.deleteAttachmentsByRecordTypeAndRecordId(recordType, recordId); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.system.api.storage.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class StorageBlobRespDTO { |
| | | |
| | | private Long id; |
| | | private String url; |
| | | private String previewURL; |
| | | private String name; |
| | | private String downloadURL; |
| | | private String application; |
| | | private Long storageAttachmentId; |
| | | |
| | | } |