docs/batch_trace_extended_frontend.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,305 @@ # æ¹æ¬¡è¿½æº¯æ©å± - å端èè°æ¹æ¡ ## æ¦è¿° å¨ç°ææ¹æ¬¡è¿½æº¯ï¼åå/ååï¼åºç¡ä¸ï¼æ©å± 4 个è½åï¼è¡¥é½æ¹æ¬¡å ¨é¾è·¯è¿½æº¯ï¼ 1. **éè´æ¥æº**ï¼ä»æ¹æ¬¡åæ¥éè´å ¥åºå + IQC è´¨æ£ç»è®ºï¼åæä¾§æé¾æéï¼ 2. **éå®å»å**ï¼ä»æ¹æ¬¡åæ¥éå®åºåºå + OQC è´¨æ£ç»è®ºï¼æåä¾§æé¾æéï¼ 3. **å·¥åºæµè½¬**ï¼ä»æ¹æ¬¡æ¥ç产åº/æå ¥çå·¥åºçº§äºä»¶ï¼æ é建表ï¼å¨æèåï¼ 4. **SN 忥**ï¼è¾å ¥ SN åºåå·ç´æ¥å®ä½æ¹æ¬¡å¹¶è·³è½¬è¯¦æ å端 4 ä¸ªæ°æ¥å£å已宿并ç¼è¯éè¿ï¼æ¬ææ¡£æå¯¼å端对æ¥ã --- ## ä¸ãæ¶åé¡µé¢ | é¡µé¢ | è·¯å¾ | æ¹å¨è¯´æ | |------|------|----------| | æ¹æ¬¡è¿½æº¯é¡µ | `src/views/mes/qc/batchtrace/index.vue` | 顶鍿°å¢ SN 忥è¾å ¥æ¡ | | 追溯详æ å¼¹çª | `src/views/mes/qc/batchtrace/modules/trace-detail.vue` | åé¡µç¾æ©å±ä¸º 5 个ï¼ç产/éè´æ¥æº/éå®å»å/å·¥åºæµè½¬/è´¨æ£ï¼ | | éè´æ¥æºåå表 | `src/views/mes/qc/batchtrace/modules/purchase-source-list.vue` | æ°å¢åç»ä»¶ | | éå®å»ååå表 | `src/views/mes/qc/batchtrace/modules/sales-target-list.vue` | æ°å¢åç»ä»¶ | | å·¥åºæµè½¬åå表 | `src/views/mes/qc/batchtrace/modules/process-trace-list.vue` | æ°å¢åç»ä»¶ | | æ¹æ¬¡ API | `src/api/mes/wm/batch/index.ts` | æ°å¢ 4 个æ¥å£å½æ° | | åå®ä¹ | `src/views/mes/qc/batchtrace/data.ts` | æ°å¢ 3 ç»åé ç½® | --- ## äºãAPI æ¥å£ ### 2.1 æ¹æ¬¡éè´æ¥æº **è¯·æ±æ¹å¼**ï¼GET **请æ±è·¯å¾**ï¼`/mes/wm/batch/purchase-sources` **请æ±åæ°**ï¼ | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | code | String | æ¯ | æ¹æ¬¡ç¼ç | **ååº**ï¼ ```json { "code": 0, "data": [ { "receiptCode": "IR20250713001", "receiptDate": "2026-08-01 10:00:00", "purchaseOrderCode": "PO20250701001", "vendorId": 20, "vendorCode": "VENDOR001", "vendorName": "ä¾åºåA", "iqcCode": "IQC20250713001", "checkResult": 1, "itemId": 100, "itemCode": "ITEM001", "itemName": "åæA", "batchCode": "BT20260731001", "receivedQuantity": 100 } ] } ``` **åæ®µè¯´æ**ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | receiptCode | String | éè´å ¥åºåå· | | receiptDate | Date | å ¥åºæ¥æ | | purchaseOrderCode | String | éè´è®¢åå· | | vendorCode / vendorName | String | ä¾åºåç¼ç /åç§°ï¼å端å¯åï¼ | | iqcCode | String | IQC è´¨æ£åå·ï¼å¯è½ä¸ºç©ºï¼ | | checkResult | Integer | IQC è´¨æ£ç»è®ºï¼åå ¸ `mes_qc_check_result` | | itemCode / itemName | String | ç©æç¼ç /åç§°ï¼å端å¯åï¼ | | batchCode | String | æ¹æ¬¡ç¼ç | | receivedQuantity | BigDecimal | å ¥åºæ°é | ### 2.2 æ¹æ¬¡éå®å»å **è¯·æ±æ¹å¼**ï¼GET **请æ±è·¯å¾**ï¼`/mes/wm/batch/sales-targets` **请æ±åæ°**ï¼ | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | code | String | æ¯ | æ¹æ¬¡ç¼ç | **ååº**ï¼ ```json { "code": 0, "data": [ { "salesCode": "SS20250713001", "salesDate": "2026-08-05 14:00:00", "salesOrderCode": "SO20250701001", "clientId": 30, "clientName": "客æ·A", "oqcCode": "OQC20250713001", "checkResult": 1, "itemId": 100, "itemCode": "ITEM001", "itemName": "æåA", "batchCode": "BT20260804001", "quantity": 50, "qualityStatus": 1 } ] } ``` **åæ®µè¯´æ**ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | salesCode | String | éå®åºåºåå· | | salesDate | Date | åºåºæ¥æ | | salesOrderCode | String | éå®è®¢åå· | | clientName | String | 客æ·åç§°ï¼å端å¯åï¼æ³¨æï¼å®¢æ·æ ç¼ç åæ®µï¼ | | oqcCode | String | OQC è´¨æ£åå·ï¼å¯è½ä¸ºç©ºï¼ | | checkResult | Integer | OQC è´¨æ£ç»è®ºï¼åå ¸ `mes_qc_check_result` | | itemCode / itemName | String | ç©æç¼ç /åç§°ï¼å端å¯åï¼ | | batchCode | String | æ¹æ¬¡ç¼ç | | quantity | BigDecimal | åºåºæ°é | | qualityStatus | Integer | è´¨éç¶æï¼åå ¸ `mes_wm_quality_status` | ### 2.3 æ¹æ¬¡å·¥åºæµè½¬ **è¯·æ±æ¹å¼**ï¼GET **请æ±è·¯å¾**ï¼`/mes/wm/batch/process-trace` **请æ±åæ°**ï¼ | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | code | String | æ¯ | æ¹æ¬¡ç¼ç | **ååº**ï¼ ```json { "code": 0, "data": [ { "eventType": "IN", "workOrderId": 50, "workOrderCode": "WO20260730001", "processId": 10, "processCode": "P001", "processName": "䏿", "batchCode": "BT20260804001", "quantity": 100, "qualityStatus": null, "eventTime": "2026-08-04 09:00:00", "processSort": 1 }, { "eventType": "OUT", "workOrderId": 50, "workOrderCode": "WO20260730001", "processId": 10, "processCode": "P001", "processName": "䏿", "batchCode": "BT20260804001", "quantity": 90, "qualityStatus": 1, "eventTime": "2026-08-04 10:00:00", "processSort": 1 } ] } ``` **åæ®µè¯´æ**ï¼ | åæ®µ | ç±»å | 说æ | |------|------|------| | eventType | String | äºä»¶ç±»åï¼`OUT` = 产åºã`IN` = æå ¥ | | workOrderCode | String | å·¥åå·ï¼å端å¯åï¼ | | processCode / processName | String | å·¥åºç¼ç /åç§°ï¼å端å¯åï¼ | | batchCode | String | æ¹æ¬¡ç¼ç | | quantity | BigDecimal | æ°éï¼OUT=äº§åºæ°éï¼IN=æå ¥æ°éï¼ | | qualityStatus | Integer | è´¨éç¶æï¼ä» OUT ä¾§æå¼ï¼IN 侧为 nullï¼ | | eventTime | Date | äºä»¶æ¶é´ï¼OUT=äº§åºæ¥æï¼IN=æ¶èæ¥æï¼ | | processSort | Integer | å·¥åºåºå·ï¼ç¨äºå±ç¤ºå·¥åºå åï¼ | **æåºè§å**ï¼å端已æ `workOrderId asc â processSort ascï¼ç©ºå¼ç½®åï¼â eventTime asc` æåºï¼åç«¯ç´æ¥æè¿å顺åºå±ç¤ºå³å¯ã ### 2.4 SN åæ¥æ¹æ¬¡ **è¯·æ±æ¹å¼**ï¼GET **请æ±è·¯å¾**ï¼`/mes/wm/batch/get-by-sn` **请æ±åæ°**ï¼ | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | sn | String | æ¯ | SN åºåå· | **ååº**ï¼ä¸ `GET /mes/wm/batch/get` å®å ¨ä¸è´ï¼`MesWmBatchRespVO`ï¼ï¼æªå½ä¸è¿å `data: null`ï¼ ```json { "code": 0, "data": { "id": 1, "code": "BT20260804001", "itemId": 100, "itemCode": "ITEM001", "itemName": "æåA", "vendorCode": "VENDOR001", "vendorName": "ä¾åºåA", "clientName": "客æ·A", "workOrderCode": "WO20260730001", "taskCode": "TASK001", "workstationCode": "WS001", "toolCode": "TOOL001", "lotNumber": "LOT20260801" } } ``` **说æ**ï¼SN å¨ `mes_wm_sn` 表éè¿ `code` å¯ä¸å¹é ï¼å½ä¸ååå ¶ `batch_code` åæ¥æ¹æ¬¡ãåç«¯æ ¹æ® `data` æ¯å¦ä¸ºç©ºå¤ææ¯å¦æç¤º"æªæ¾å°å¯¹åºæ¹æ¬¡"ã --- ## ä¸ãåæ®µå±ç¤ºè§å | åè½ | å±ç¤ºä½ç½® | åæ®µè¯´æ | |------|----------|----------| | éè´æ¥æº | 详æ å¼¹çªå页ç¾"éè´æ¥æº" | å ¥åºåå·ãå ¥åºæ¥æãéè´è®¢åãä¾åºåãIQCåå·ãIQCç»è®ºãç©æãæ°é | | éå®å»å | 详æ å¼¹çªå页ç¾"éå®å»å" | åºåºåå·ãåºåºæ¥æãéå®è®¢åã客æ·ãOQCåå·ãOQCç»è®ºãç©æãæ°éãè´¨éç¶æ | | å·¥åºæµè½¬ | 详æ å¼¹çªå页ç¾"å·¥åºæµè½¬" | äºä»¶ç±»åãå·¥åå·ãå·¥åºç¼ç /åç§°ãæ°éãæ¶é´ãè´¨éç¶æ | | SN 忥 | 追溯页顶é¨è¾å ¥æ¡ | è¾å ¥ SN â å½ä¸ç´æ¥æå¼æ¹æ¬¡è¯¦æ å¼¹çª | **åå ¸è¯´æ**ï¼ | åå ¸ | åå¼ | |------|------| | `mes_qc_check_result` | 1=åæ ¼ã2=ç¹éã3=éè´§ã4=æ¥åº | | `mes_wm_quality_status` | 0=å¾ æ£ã1=åæ ¼ã2=ä¸åæ ¼ | --- ## åãæ°æ®å¸¦å ¥è¯´æ | åºæ¯ | å¸¦å ¥è¯´æ | |------|----------| | 追溯页 â éè´æ¥æº | ç¹å»æ¹æ¬¡è¡ï¼æºå¸¦è¯¥è¡ç `code` è°ç¨ `getPurchaseSourceList(code)` | | 追溯页 â éå®å»å | ç¹å»æ¹æ¬¡è¡ï¼æºå¸¦è¯¥è¡ç `code` è°ç¨ `getSalesTargetList(code)` | | 追溯页 â å·¥åºæµè½¬ | ç¹å»æ¹æ¬¡è¡ï¼æºå¸¦è¯¥è¡ç `code` è°ç¨ `getProcessTraceList(code)` | | SN è¾å ¥æ¡ â 详æ | è¾å ¥ SN è°ç¨ `getBatchBySn(sn)`ï¼è¿åç `code` ä½ä¸ºè¯¦æ å¼¹çªæ¥è¯¢ä¾æ®ï¼æç´æ¥ä½¿ç¨è¿åæ°æ®ï¼ | --- ## äºãæ¥å£è°ç¨æ¶åº 1. 追溯页å è½½æ¹æ¬¡å表ï¼`/mes/wm/batch/page`ï¼ 2. ç¹å»ææ¹æ¬¡è¡ â æå¼è¯¦æ å¼¹çªï¼å¼¹çªå é»è®¤å±ç¤º"ç产"页ç¾ï¼åå/ååè¿½æº¯ï¼ 3. 忢"éè´æ¥æº/éå®å»å/å·¥åºæµè½¬"é¡µç¾æ¶ï¼æéè°ç¨å¯¹åºæ¥å£ï¼å»ºè®®æå è½½ï¼é¦æ¬¡åæ¢æè¯·æ±ï¼ 4. é¡¶é¨ SN è¾å ¥æ¡ â æå车æç¹å»æç´¢ â `getBatchBySn` â å½ä¸æå¼è¯¦æ å¼¹çªï¼æªå½ä¸æç¤ºæ è®°å½ --- ## å ãä¸å¡è§å说æ | åºæ¯ | è§å | |------|------| | åææ¹æ¬¡ | æéè´æ¥æºï¼å ¥åº+IQCï¼ï¼æ éå®å»åï¼å·¥åºæµè½¬ä»¥ IN æå ¥ä¸ºä¸» | | æåæ¹æ¬¡ | æéå®å»åï¼åºåº+OQCï¼ï¼æ éè´æ¥æºï¼å·¥åºæµè½¬ä»¥ OUT 产åºä¸ºä¸» | | ä¸é´æ¹æ¬¡ | åæ¶åå¨ IN ä¸ OUT äºä»¶ï¼ä½ç°å·¥åºçº§æµè½¬ | | è´¨æ£å缺失 | `iqcCode`/`oqcCode` å¯è½ä¸ºç©ºï¼åæ®æªå ³èï¼ï¼ç»è®ºåå±ç¤º"-" | | SN æªå½ä¸ | `get-by-sn` è¿å `data: null`ï¼å端æç¤º"æªæ¾å°è¯¥ SN 对åºçæ¹æ¬¡" | | æ°æ®ä¸ºç©º | ä¸ä¸ªåå表æ¥å£åå¯è½è¿å空æ°ç»ï¼é¡µé¢å±ç¤ºç©ºææç¤º | --- ## ä¸ã注æäºé¡¹ - ä¸ä¸ªå表æ¥å£ä¸æ¢æ forward/backward ç¸åï¼åéè¦ `mes:wm-batch:query` æé - å页ç¾å»ºè®®æå è½½ + ç¼åï¼é¿å æ¯æ¬¡åæ¢éå¤è¯·æ± - å·¥åºæµè½¬ç `processSort` ç±å端æå¥½åºï¼å端å¿åæåº - éå®ä¾§ `qualityStatus` 为åå ¸å¼ï¼å±ç¤ºç¨ `mes_wm_quality_status` åå ¸ç¿»è¯ - æµè¯ç¯å¢å¯è½å卿 `batchCode` çéå®åºåºè¡æ°æ®ï¼å±åå²èæ°æ®ï¼åç«¯å¯¹ç©ºåæ®µåå åºå±ç¤ºå³å¯ --- ## å «ãç¸å ³æ¥å£æ±æ» | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | /mes/wm/batch/purchase-sources | æ¹æ¬¡éè´æ¥æºï¼å ¥åº + IQCï¼ | | GET | /mes/wm/batch/sales-targets | æ¹æ¬¡éå®å»åï¼åºåº + OQCï¼ | | GET | /mes/wm/batch/process-trace | æ¹æ¬¡å·¥åºæµè½¬ï¼äº§åº/æå ¥ï¼ | | GET | /mes/wm/batch/get-by-sn | SN åæ¥æ¹æ¬¡ | docs/pd_project_bpm_approval_frontend.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,87 @@ # MES 产åé¡¹ç®æ¥å ¥ BPM å®¡æ¹ - å端èè°æ¹æ¡ ## æ¶åé¡µé¢ - ç产管æ§-产å设计-产åé¡¹ç® å表页ï¼`src/views/mes/pd/project/index.vue`ï¼ - 产åé¡¹ç® è¯¦æ 页ï¼`src/views/mes/pd/project/detail/index.vue`ï¼ - 产åé¡¹ç® æµç¨è¿åº¦ç»ä»¶ï¼`src/views/mes/pd/project/modules/workflow-timeline.vue`ï¼ ## ä¸å¡æµç¨ä¸æ°æ®å¸¦å ¥ 1. å¾ å®¡æ ¸(2) â å表/详æ ç¹ãæäº¤å®¡æ¹ãï¼å è° `GET /mes/pd/project/approve-process-list` è·åå¯ç¨ BPM æµç¨ â æå¼æµç¨éæ©å¼¹çª â é䏿µç¨åè° `PUT /mes/pd/project/submit-approval?id={id}&processDefinitionKey={key}` â 项ç®ç¶æå为 **审æ¹ä¸(5)** 2. BPM åå°å®¡æ¹éè¿ â å端çå¬å¨åè° â 项ç®ç¶æå为 **å¾ å½æ¡£(3)**ï¼å®¡æ¹é©³å/åæ¶ â ç¶æåå° **å¾ å®¡æ ¸(2)**ï¼å¯éæ°æäº¤ 3. 审æ¹ä¸(5) â å表/è¯¦æ æ¾ç¤ºãæ¥ç审æ¹ãæé® â 跳转 BPM æµç¨è¯¦æ 页æ¥ç审æ¹è¿åº¦ 4. å¾ å½æ¡£(3) â ç¹ã彿¡£ãâ `PUT /mes/pd/project/archive?id={id}` â ç¶æå为 **已彿¡£(4)** ## API | æ¹æ³ | è·¯å¾ | 说æ | |------|------|------| | GET | /mes/pd/project/approve-process-list | è·å¾å¯ç¨ BPM å®¡æ¹æµç¨å表 | | PUT | /mes/pd/project/submit-approval | æäº¤å®¡æ¹ï¼å¾ å®¡æ ¸â审æ¹ä¸ï¼ | | PUT | /mes/pd/project/archive | 彿¡£ï¼å¾ 彿¡£â已彿¡£ï¼ | **请æ±åæ°ï¼submit-approvalï¼ï¼** | åæ° | ç±»å | å¿ å¡« | 说æ | |------|------|------|------| | id | Long | æ¯ | 项ç®ç¼å· | | processDefinitionKey | String | æ¯ | éä¸ç BPM æµç¨å®ä¹ Key | **ååºåæ®µåæ´ï¼/getã/pageï¼ï¼** | åæ®µ | ç±»å | 说æ | |------|------|------| | processInstanceId | String | BPM æµç¨å®ä¾ç¼å·ï¼å®¡æ¹ä¸å以åæå¼ | **ååºç¤ºä¾ï¼approve-process-listï¼ï¼** ```json { "code": 0, "data": [ { "id": "xxx", "name": "产å项ç®å®¡æ¹æµç¨", "key": "mes-pd-project-audit" } ] } ``` ## åæ®µå±ç¤ºè§å | åæ®µ | å±ç¤ºä½ç½® | 说æ | |------|----------|------| | ç¶æ | å表ã详æ | æ°å¢åå ¸å¼ã审æ¹ä¸ã(value=5)ï¼å表 `CellDict` èªå¨æ¸²æ | | processInstanceId | å表/详æ ãæ¥ç审æ¹ã | æå¼ææ¾ç¤ºãæ¥ç审æ¹ãæé® | ## 页颿¹å¨ ### 1. å表页 index.vue - ãå®¡æ ¸ãæé®æ¹ä¸ºãæäº¤å®¡æ¹ãï¼`ifShow` ä»ä¸º `status === PENDING_AUDIT`ï¼ç¹å»å æ¥æµç¨å表ï¼ç©ºåæç¤ºãææ å¯ç¨å®¡æ¹æµç¨ï¼è¯·å é ç½® BPM æµç¨ãï¼ï¼æåæå¼æµç¨éæ©å¼¹çª - æ°å¢ãæ¥ç审æ¹ãæé®ï¼`ifShow` 为 `status === APPROVING` ä¸ `processInstanceId` æå¼ï¼ç¹å»è·³ BPM æµç¨è¯¦æ - æ°å¢æµç¨éæ©å¼¹çªç»ä»¶ `process-select-modal.vue`ï¼Select 䏿鿵ç¨ï¼é»è®¤é第ä¸ä¸ªï¼ç¡®è®¤åè° submit-approvalï¼ ### 2. 详æ 页 detail/index.vue - ãå®¡æ ¸éè¿ãæé®æ¹ä¸ºãæäº¤å®¡æ¹ãï¼é»è¾åä¸ï¼æååå·æ°è¯¦æ - æ°å¢ãæ¥ç审æ¹ãæé®ï¼`ifShow` 为审æ¹ä¸ç¶æï¼ç¹å»è·³ BPM æµç¨è¯¦æ - 顶鍿é®åºæ°å¢å®¡æ¹ä¸å¤æ ### 3. æµç¨è¿åº¦ç»ä»¶ workflow-timeline.vue - æ¥éª¤ç± 5 æ¥æ©ä¸º 6 æ¥ï¼å¾ åå¸ â å¾ ä¸ä¼ â å¾ å®¡æ ¸ â **审æ¹ä¸** â å¾ å½æ¡£ â 已彿¡£ - ç¶æå¼å°æ¥éª¤ç´¢å¼çæ å°éæ¾å¼å¤çï¼å®¡æ¹ä¸ value=5 æå¨å¾ å®¡æ ¸ä¹åï¼ ## ä¸å¡è§å说æ | åºæ¯ | è§å | |------|------| | æäº¤å®¡æ¹ | ä» å¾ å®¡æ ¸(2)ç¶æå¯æäº¤ï¼è¥é¡¹ç®ä¸å卿ªå®¡æ ¸çè®¾è®¡èµæï¼å端è¿åé误ã该项ç®ä¸å卿ªå®¡æ ¸çèµæã | | 审æ¹éè¿ | ç¶æ â å¾ å½æ¡£(3)ï¼å¯æ§è¡å½æ¡£ | | 审æ¹é©³å/åæ¶ | ç¶æ â å¾ å®¡æ ¸(2)ï¼å¯ä¿®æ¹åéæ°æäº¤ | | 彿¡£ | ä» å¾ å½æ¡£(3)ç¶æå¯å½æ¡£ï¼å½æ¡£åçæå°è´¦è®°å½ã项ç®ä¸å¯åä¿®æ¹ | ## 注æäºé¡¹ - éå å¨ BPM åå°æå·¥é¨ç½²å®¡æ¹æµç¨ï¼æµç¨ key=`mes-pd-project-audit`ï¼åç±»=`mes_pd_project_approve`ï¼ï¼å¦åãæäº¤å®¡æ¹ãæç¤ºææ å¯ç¨æµç¨ - æªæäº¤å®¡æ¹ï¼processInstanceId ä¸ºç©ºï¼æ¶ç¹ãæ¥ç审æ¹ãåºæç¤ºã该项ç®å°æªæäº¤å®¡æ¹ã - å岿°æ® status 0-4 ä¸åå½±åï¼æ¶é´çº¿ç»ä»¶éå ¼å®¹ç¶æå¼å°æ¥éª¤çéè¿ç»æ å° yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pd/project/MesPdProjectController.java
@@ -124,15 +124,24 @@ return success(true); } @PutMapping("/audit") @Operation(summary = "å®¡æ ¸è®¾è®¡é¡¹ç®ï¼å¾ å®¡æ ¸âå¾ å½æ¡£ï¼") @PutMapping("/submit-approval") @Operation(summary = "æäº¤è®¾è®¡é¡¹ç®å®¡æ¹ï¼å¾ å®¡æ ¸â审æ¹ä¸ï¼") @Parameter(name = "id", description = "ç¼å·", required = true) @Parameter(name = "processDefinitionKey", description = "æµç¨å®ä¹ Key", required = true) @PreAuthorize("@ss.hasPermission('mes:pd-project:update')") public CommonResult<Boolean> auditProject(@RequestParam("id") Long id) { projectService.auditProject(id); public CommonResult<Boolean> submitProjectApproval(@RequestParam("id") Long id, @RequestParam("processDefinitionKey") String processDefinitionKey) { projectService.submitProjectApproval(id, processDefinitionKey); return success(true); } @GetMapping("/approve-process-list") @Operation(summary = "è·å¾è®¾è®¡é¡¹ç®å®¡æ¹æµç¨å表") @PreAuthorize("@ss.hasPermission('mes:pd-project:update')") public CommonResult<List<Map<String, Object>>> getProjectApproveProcessDefinitionList() { return success(projectService.getProjectApproveProcessDefinitionList()); } @PutMapping("/archive") @Operation(summary = "彿¡£è®¾è®¡é¡¹ç®ï¼å¾ 彿¡£â已彿¡£ï¼ï¼åæ¶èªå¨åå»ºå½æ¡£å°è´¦") @Parameter(name = "id", description = "ç¼å·", required = true) yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pd/project/vo/MesPdProjectRespVO.java
@@ -66,6 +66,9 @@ @ExcelProperty("夿³¨") private String remark; @Schema(description = "BPM æµç¨å®ä¾ç¼å·") private String processInstanceId; @Schema(description = "å建æ¶é´", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("å建æ¶é´") private LocalDateTime createTime; yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java
@@ -6,7 +6,10 @@ 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.wm.batch.vo.MesWmBatchPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO; import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; @@ -15,6 +18,7 @@ import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; @@ -23,6 +27,7 @@ import cn.iocoder.yudao.module.mdm.api.unit.dto.MdmUnitMeasureRespDTO; import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService; @@ -71,6 +76,8 @@ private MesMdWorkstationService workstationService; @Resource private MesTmToolService toolService; @Resource private MesProProcessService processService; @GetMapping("/get") @Operation(summary = "è·å¾æ¹æ¬¡è¯¦æ ") @@ -105,6 +112,42 @@ public CommonResult<List<MesWmBatchRespVO>> getBackwardList(@RequestParam("code") @Valid String code) { List<MesWmBatchDO> list = batchService.getBackwardBatchList(code); return success(buildBatchRespVOList(list)); } @GetMapping("/purchase-sources") @Operation(summary = "æ¹æ¬¡éè´æ¥æºï¼éè´å ¥åºå + IQCï¼") @Parameter(name = "code", description = "æ¹æ¬¡ç¼ç ", required = true, example = "BATCH20250314001") @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") public CommonResult<List<MesWmBatchPurchaseSourceRespVO>> getPurchaseSourceList(@RequestParam("code") @Valid String code) { List<MesWmBatchPurchaseSourceRespVO> list = batchService.getPurchaseSourceList(code); return success(buildPurchaseSourceRespVOList(list)); } @GetMapping("/sales-targets") @Operation(summary = "æ¹æ¬¡éå®å»åï¼éå®åºåºå + OQCï¼") @Parameter(name = "code", description = "æ¹æ¬¡ç¼ç ", required = true, example = "BATCH20250314001") @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") public CommonResult<List<MesWmBatchSalesTargetRespVO>> getSalesTargetList(@RequestParam("code") @Valid String code) { List<MesWmBatchSalesTargetRespVO> list = batchService.getSalesTargetList(code); return success(buildSalesTargetRespVOList(list)); } @GetMapping("/process-trace") @Operation(summary = "æ¹æ¬¡å·¥åºæµè½¬ï¼äº§åº/æå ¥äºä»¶ï¼") @Parameter(name = "code", description = "æ¹æ¬¡ç¼ç ", required = true, example = "BATCH20250314001") @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") public CommonResult<List<MesWmBatchProcessTraceRespVO>> getProcessTraceList(@RequestParam("code") @Valid String code) { List<MesWmBatchProcessTraceRespVO> list = batchService.getProcessTraceList(code); return success(buildProcessTraceRespVOList(list)); } @GetMapping("/get-by-sn") @Operation(summary = "æ ¹æ® SN ç åæ¥æ¹æ¬¡") @Parameter(name = "sn", description = "SN åºåå·", required = true, example = "SN20250314001") @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") public CommonResult<MesWmBatchRespVO> getBatchBySn(@RequestParam("sn") @Valid String sn) { MesWmBatchDO batch = batchService.getBatchBySn(sn); return success(buildBatchRespVO(batch)); } // ==================== æ¼æ¥ VO ==================== @@ -162,4 +205,58 @@ return buildBatchRespVOList(Collections.singletonList(batch)).get(0); } private List<MesWmBatchPurchaseSourceRespVO> buildPurchaseSourceRespVOList(List<MesWmBatchPurchaseSourceRespVO> list) { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( convertSet(list, MesWmBatchPurchaseSourceRespVO::getItemId)); Map<Long, SrmSupplierRespDTO> vendorMap = srmSupplierApi.getSupplierList( convertSet(list, MesWmBatchPurchaseSourceRespVO::getVendorId)).getCheckedData().stream() .collect(Collectors.toMap(SrmSupplierRespDTO::getId, s -> s)); list.forEach(vo -> { MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { vo.setItemCode(item.getCode()).setItemName(item.getName()); }); MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor -> vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName())); }); return list; } private List<MesWmBatchSalesTargetRespVO> buildSalesTargetRespVOList(List<MesWmBatchSalesTargetRespVO> list) { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( convertSet(list, MesWmBatchSalesTargetRespVO::getItemId)); Map<Long, CrmCustomerRespDTO> clientMap = customerApi.getCustomerMap( convertSet(list, MesWmBatchSalesTargetRespVO::getClientId)); list.forEach(vo -> { MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { vo.setItemCode(item.getCode()).setItemName(item.getName()); }); MapUtils.findAndThen(clientMap, vo.getClientId(), client -> vo.setClientName(client.getName())); }); return list; } private List<MesWmBatchProcessTraceRespVO> buildProcessTraceRespVOList(List<MesWmBatchProcessTraceRespVO> list) { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap( convertSet(list, MesWmBatchProcessTraceRespVO::getWorkOrderId)); Map<Long, MesProProcessDO> processMap = processService.getProcessMap( convertSet(list, MesWmBatchProcessTraceRespVO::getProcessId)); list.forEach(vo -> { MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> vo.setWorkOrderCode(workOrder.getCode())); MapUtils.findAndThen(processMap, vo.getProcessId(), process -> vo.setProcessCode(process.getCode()).setProcessName(process.getName())); }); return list; } } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchProcessTraceRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管çåå° - MES æ¹æ¬¡å·¥åºæµè½¬ Response VO") @Data public class MesWmBatchProcessTraceRespVO { @Schema(description = "äºä»¶ç±»åï¼IN-å·¥åºæå ¥ / OUT-å·¥åºäº§åº", example = "OUT") private String eventType; @Schema(description = "ç产工å ID", example = "1") private Long workOrderId; @Schema(description = "ç产工åç¼å·", example = "WO20250801001") private String workOrderCode; @Schema(description = "å·¥åº ID", example = "1") private Long processId; @Schema(description = "å·¥åºç¼ç ", example = "PROC001") private String processCode; @Schema(description = "å·¥åºåç§°", example = "CNC å å·¥") private String processName; @Schema(description = "æ¹æ¬¡å·", example = "BATCH20250801001") private String batchCode; @Schema(description = "æ°é", example = "100") private BigDecimal quantity; @Schema(description = "è´¨éç¶æï¼åå ¸ mes_wm_quality_statusï¼ï¼ä» 产åºä¾§æå¼", example = "1") private Integer qualityStatus; @Schema(description = "äºä»¶æ¶é´") private LocalDateTime eventTime; @Schema(description = "å·¥åºåºå·ï¼æåºç¨ï¼", example = "1") private Integer processSort; } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchPurchaseSourceRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,52 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管çåå° - MES æ¹æ¬¡éè´æ¥æº Response VO") @Data public class MesWmBatchPurchaseSourceRespVO { @Schema(description = "éè´å ¥åºåå·", example = "IR20250731001") private String receiptCode; @Schema(description = "å ¥åºæ¥æ") private LocalDateTime receiptDate; @Schema(description = "éè´è®¢åç¼å·", example = "PO20250731001") private String purchaseOrderCode; @Schema(description = "ä¾åºå ID", example = "1") private Long vendorId; @Schema(description = "ä¾åºåç¼ç ", example = "V001") private String vendorCode; @Schema(description = "ä¾åºååç§°", example = "ä¾åºåA") private String vendorName; @Schema(description = "æ¥ææ£éªåå·ï¼IQCï¼", example = "IQC20250731001") private String iqcCode; @Schema(description = "IQC æ£éªç»è®ºï¼åå ¸ mes_qc_check_resultï¼", example = "1") private Integer checkResult; @Schema(description = "ç©æ ID", example = "1") private Long itemId; @Schema(description = "ç©æç¼ç ", example = "ITEM001") private String itemCode; @Schema(description = "ç©æåç§°", example = "产åA") private String itemName; @Schema(description = "æ¹æ¬¡å·", example = "BATCH20250731001") private String batchCode; @Schema(description = "å ¥åºæ°é", example = "100") private BigDecimal receivedQuantity; } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchSalesTargetRespVO.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,55 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管çåå° - MES æ¹æ¬¡éå®å»å Response VO") @Data public class MesWmBatchSalesTargetRespVO { @Schema(description = "éå®åºåºåå·", example = "SO20250801001") private String salesCode; @Schema(description = "åºåºæ¥æ") private LocalDateTime salesDate; @Schema(description = "éå®è®¢åç¼å·", example = "SO20250801001") private String salesOrderCode; @Schema(description = "å®¢æ· ID", example = "1") private Long clientId; @Schema(description = "客æ·ç¼ç ", example = "C001") private String clientCode; @Schema(description = "客æ·åç§°", example = "客æ·A") private String clientName; @Schema(description = "åºåæ£éªåå·ï¼OQCï¼", example = "OQC20250801001") private String oqcCode; @Schema(description = "OQC æ£éªç»è®ºï¼åå ¸ mes_qc_check_resultï¼", example = "1") private Integer checkResult; @Schema(description = "ç©æ ID", example = "1") private Long itemId; @Schema(description = "ç©æç¼ç ", example = "ITEM001") private String itemCode; @Schema(description = "ç©æåç§°", example = "产åA") private String itemName; @Schema(description = "æ¹æ¬¡å·", example = "BATCH20250801001") private String batchCode; @Schema(description = "åºåºæ°é", example = "100") private BigDecimal quantity; @Schema(description = "è´¨éç¶æï¼åå ¸ mes_wm_quality_statusï¼", example = "1") private Integer qualityStatus; } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pd/project/MesPdProjectDO.java
@@ -58,6 +58,14 @@ */ private Integer status; /** * BPM æµç¨å®ä¾ç¼å· */ private String processInstanceId; /** * BPM æµç¨å®ä¹ Key */ private String processDefinitionKey; /** * ä¸»è®¾è®¡å¸ * * å ³è AdminUserDO#getId() yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java
@@ -7,6 +7,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; @@ -185,4 +188,28 @@ */ List<MesWmBatchDO> selectListByBackward(String batchCode); /** * æ¥è¯¢æ¹æ¬¡éè´æ¥æºï¼éè´å ¥åºå + IQCï¼ * * @param batchCode æ¹æ¬¡å· * @return éè´æ¥æºå表 */ List<MesWmBatchPurchaseSourceRespVO> selectPurchaseSourceList(String batchCode); /** * æ¥è¯¢æ¹æ¬¡éå®å»åï¼éå®åºåºå + OQCï¼ * * @param batchCode æ¹æ¬¡å· * @return éå®å»åå表 */ List<MesWmBatchSalesTargetRespVO> selectSalesTargetList(String batchCode); /** * æ¥è¯¢æ¹æ¬¡å·¥åºæµè½¬ï¼äº§åº/æå ¥äºä»¶ï¼ * * @param batchCode æ¹æ¬¡å· * @return å·¥åºæµè½¬å表 */ List<MesWmBatchProcessTraceRespVO> selectProcessTraceList(String batchCode); } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -773,6 +773,9 @@ ErrorCode PD_PROJECT_NOT_UPLOAD_FOR_AUDIT = new ErrorCode(1_040_800_005, "åªæå¾ å®¡æ ¸ç¶æçè®¾è®¡é¡¹ç®æè½å®¡æ ¸"); ErrorCode PD_PROJECT_NOT_AUDIT_FOR_ARCHIVE = new ErrorCode(1_040_800_006, "åªæå¾ å½æ¡£ç¶æçè®¾è®¡é¡¹ç®æè½å½æ¡£"); ErrorCode PD_PROJECT_AUDIT_NOT_FINISHED = new ErrorCode(1_040_800_007, "该项ç®ä¸å卿ªå®¡æ ¸çèµæï¼è¯·å 宿ææèµæå®¡æ ¸"); ErrorCode PD_PROJECT_NOT_UPLOAD_FOR_APPROVAL = new ErrorCode(1_040_800_008, "åªæå¾ å®¡æ ¸ç¶æçè®¾è®¡é¡¹ç®æè½æäº¤å®¡æ¹"); ErrorCode PD_PROJECT_NOT_APPROVING = new ErrorCode(1_040_800_009, "设计项ç®ä¸å¤äºå®¡æ¹ä¸ç¶æ"); ErrorCode PD_PROJECT_BPM_CATEGORY_NOT_EXISTS = new ErrorCode(1_040_800_010, "设计项ç®å®¡æ¹åç±»ä¸åå¨ï¼è¯·å é ç½® BPM å®¡æ¹æµç¨"); // ========== MES 产å设计-èµæå表ï¼1-040-801-000ï¼ ========== ErrorCode PD_DOCUMENT_NOT_EXISTS = new ErrorCode(1_040_801_000, "è®¾è®¡èµæä¸åå¨"); yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesPdStatusConstants.java
@@ -32,5 +32,9 @@ * 已彿¡£ */ public static final int ARCHIVE = 4; /** * 审æ¹ä¸ï¼BPM 审æ¹è¿è¡ä¸ï¼ */ public static final int APPROVING = 5; } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pd/MesPdProjectStatusEnum.java
@@ -39,7 +39,7 @@ /** * å¾ å½æ¡£ * * å¯¹åº MesPdProjectService#auditProject æ¹æ³ * å¯¹åº MesPdProjectService#updateProjectAuditStatus æ¹æ³ï¼BPM 审æ¹éè¿åï¼ */ AUDIT(MesPdStatusConstants.AUDIT, "å¾ å½æ¡£"), /** @@ -47,7 +47,13 @@ * * å¯¹åº MesPdProjectService#archiveProject æ¹æ³ */ ARCHIVE(MesPdStatusConstants.ARCHIVE, "已彿¡£"); ARCHIVE(MesPdStatusConstants.ARCHIVE, "已彿¡£"), /** * 审æ¹ä¸ * * å¯¹åº MesPdProjectService#submitProjectApproval æ¹æ³ */ APPROVING(MesPdStatusConstants.APPROVING, "审æ¹ä¸"); public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesPdProjectStatusEnum::getStatus).toArray(Integer[]::new); yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pd/project/MesPdProjectService.java
@@ -81,11 +81,29 @@ void uploadProject(Long id, Long userId); /** * å®¡æ ¸è®¾è®¡é¡¹ç®ï¼å¾ å®¡æ ¸âå¾ å½æ¡£ï¼ * æäº¤è®¾è®¡é¡¹ç®å®¡æ¹ï¼å¾ å®¡æ ¸â审æ¹ä¸ï¼ * <p> * å建 BPM æµç¨å®ä¾ï¼å®¡æ¹éè¿åç±çå¬å¨åè°æ´æ°ä¸ºå¾ 彿¡£ * * @param id ç¼å· * @param id ç¼å· * @param processDefinitionKey æµç¨å®ä¹ Key */ void auditProject(Long id); void submitProjectApproval(Long id, String processDefinitionKey); /** * è·å¾è®¾è®¡é¡¹ç®å®¡æ¹æµç¨å表 * * @return æµç¨å表ï¼id/name/version/keyï¼ */ List<Map<String, Object>> getProjectApproveProcessDefinitionList(); /** * æ´æ°è®¾è®¡é¡¹ç®å®¡æ¹ç¶æï¼BPM çå¬å¨åè°ï¼ * * @param id ç¼å· * @param bpmResult BPM 审æ¹ç»æ */ void updateProjectAuditStatus(Long id, Integer bpmResult); /** * 彿¡£è®¾è®¡é¡¹ç®ï¼å¾ 彿¡£â已彿¡£ï¼ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pd/project/MesPdProjectServiceImpl.java
@@ -1,6 +1,14 @@ package cn.iocoder.yudao.module.mes.service.pd.project; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.mes.controller.admin.pd.project.vo.MesPdProjectPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pd.project.vo.MesPdProjectSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pd.document.MesPdDocumentDO; @@ -16,18 +24,24 @@ import cn.iocoder.yudao.module.mes.service.pd.document.MesPdDocumentService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.repository.ProcessDefinition; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** @@ -37,7 +51,13 @@ */ @Service @Validated @Slf4j public class MesPdProjectServiceImpl implements MesPdProjectService { /** * BPM 产å项ç®å®¡æ¹åç±»ç¼ç */ private static final String BPM_PROCESS_DEFINITION_CATEGORY_CODE = "mes_pd_project_approve"; @Resource private MesPdProjectMapper projectMapper; @@ -55,6 +75,15 @@ @Resource @Lazy private MesMdAutoCodeRecordService autoCodeRecordService; @Resource private BpmProcessInstanceApi processInstanceApi; @Resource private BpmCategoryService bpmCategoryService; @Resource private BpmProcessDefinitionService bpmProcessDefinitionService; @Override @Transactional(rollbackFor = Exception.class) @@ -180,27 +209,105 @@ } @Override public void auditProject(Long id) { // æ ¡éªåå¨ @Transactional(rollbackFor = Exception.class) public void submitProjectApproval(Long id, String processDefinitionKey) { // 1. æ ¡éªåå¨ + å¾ å®¡æ ¸ç¶æ MesPdProjectDO project = validateProjectExists(id); // æ ¡éªç¶æä¸ºå¾ å®¡æ ¸ if (!MesPdProjectStatusEnum.UPLOAD.getStatus().equals(project.getStatus())) { throw exception(PD_PROJECT_NOT_UPLOAD_FOR_AUDIT); throw exception(PD_PROJECT_NOT_UPLOAD_FOR_APPROVAL); } // æ ¡éªè¯¥é¡¹ç®ä¸ææèµæå®¡æ ¸è®°å½åå·²å®¡æ ¸ï¼ä¸åå¨å¾ å®¡æ ¸çè®°å½ï¼ // 2. æ ¡éªè¯¥é¡¹ç®ä¸ææèµæå®¡æ ¸è®°å½åå·²å®¡æ ¸ï¼ä¸åå¨å¾ å®¡æ ¸çè®°å½ï¼ List<MesPdDocumentDO> documents = documentService.getDocumentListByProjectId(id); List<Long> documentIds = documents.stream().map(MesPdDocumentDO::getId).toList(); if (documentAuditMapper.existsPendingAuditByDocumentIds(documentIds)) { throw exception(PD_PROJECT_AUDIT_NOT_FINISHED); } // æ´æ°ç¶æ // 3. å建 BPM æµç¨å®ä¾ String processInstanceId = processInstanceApi.createProcessInstance(getLoginUserId(), new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(processDefinitionKey) .setBusinessKey(String.valueOf(id))); // 4. æ´æ°é¡¹ç®ç¶æä¸ºå®¡æ¹ä¸ projectMapper.updateById(MesPdProjectDO.builder() .id(id) .status(MesPdProjectStatusEnum.AUDIT.getStatus()) .status(MesPdProjectStatusEnum.APPROVING.getStatus()) .processInstanceId(processInstanceId) .processDefinitionKey(processDefinitionKey) .build()); } @Override public List<Map<String, Object>> getProjectApproveProcessDefinitionList() { // 1. æ ¡éªåç±»æ¯å¦åå¨ List<BpmCategoryDO> categories = bpmCategoryService.getCategoryListByCode( Collections.singletonList(BPM_PROCESS_DEFINITION_CATEGORY_CODE)); if (CollUtil.isEmpty(categories)) { throw exception(PD_PROJECT_BPM_CATEGORY_NOT_EXISTS); } // 2. è·ååç±»ä¸çæµç¨å®ä¹ä¿¡æ¯ List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService .getProcessDefinitionInfoListByCategory(BPM_PROCESS_DEFINITION_CATEGORY_CODE); if (CollUtil.isEmpty(definitionInfoList)) { return Collections.emptyList(); } // 3. è¿æ»¤æ¿æ´»ç¶æï¼ä¿çææ°çæ¬ Map<String, ProcessDefinition> latestVersionMap = new HashMap<>(); for (BpmProcessDefinitionInfoDO info : definitionInfoList) { ProcessDefinition pd = bpmProcessDefinitionService.getProcessDefinition(info.getProcessDefinitionId()); if (pd == null || pd.isSuspended()) { continue; } ProcessDefinition existing = latestVersionMap.get(pd.getKey()); if (existing == null || pd.getVersion() > existing.getVersion()) { latestVersionMap.put(pd.getKey(), pd); } } // 4. è¿åæµç¨å®ä¹å表 List<Map<String, Object>> result = new ArrayList<>(); for (ProcessDefinition pd : latestVersionMap.values()) { Map<String, Object> item = new HashMap<>(); item.put("id", pd.getId()); item.put("key", pd.getKey()); item.put("name", pd.getName()); result.add(item); } return result; } @Override @Transactional(rollbackFor = Exception.class) public void updateProjectAuditStatus(Long id, Integer bpmResult) { // 1. æ ¡éªåå¨ MesPdProjectDO project = validateProjectExists(id); if (!MesPdProjectStatusEnum.APPROVING.getStatus().equals(project.getStatus())) { log.warn("[updateProjectAuditStatus] 设计项ç®({}) ä¸å¤äºå®¡æ¹ä¸ç¶æï¼å½åç¶æï¼{}", id, project.getStatus()); return; } // 2. æ ¹æ®å®¡æ¹ç»ææ´æ°ç¶æ Integer newStatus = convertBpmResultToProjectStatus(bpmResult); if (newStatus != null) { projectMapper.updateById(MesPdProjectDO.builder() .id(id) .status(newStatus) .build()); } } /** * è½¬æ¢ BPM 审æ¹ç»æä¸ºè®¾è®¡é¡¹ç®ç¶æ */ private Integer convertBpmResultToProjectStatus(Integer bpmResult) { if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) { return MesPdProjectStatusEnum.AUDIT.getStatus(); } else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) { return MesPdProjectStatusEnum.UPLOAD.getStatus(); } else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) { return MesPdProjectStatusEnum.UPLOAD.getStatus(); } return null; } @Override @Transactional(rollbackFor = Exception.class) public void archiveProject(Long id, Long userId) { // æ ¡éªåå¨ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pd/project/listener/MesPdProjectStatusListener.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,47 @@ package cn.iocoder.yudao.module.mes.service.pd.project.listener; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener; import cn.iocoder.yudao.module.mes.service.pd.project.MesPdProjectService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * 设计项ç®å®¡æ¹ç¶æçå¬å¨ * * çå¬ BPM æµç¨å®ä¾ç¶æåæ´äºä»¶ï¼æ´æ°è®¾è®¡é¡¹ç®ç审æ¹ç¶æ * * @author è¶ çº§ç®¡çå */ @Component @Slf4j public class MesPdProjectStatusListener extends BpmProcessInstanceStatusEventListener { /** * BPM 设计项ç®å®¡æ¹æµç¨å®ä¹ key */ private static final String BPM_PROCESS_DEFINITION_KEY = "mes-pd-project-audit"; @Resource private MesPdProjectService projectService; @Override protected String getProcessDefinitionKey() { return BPM_PROCESS_DEFINITION_KEY; } @Override protected void onEvent(BpmProcessInstanceStatusEvent event) { Long projectId; try { projectId = Long.parseLong(event.getBusinessKey()); } catch (NumberFormatException e) { log.warn("[onEvent] businessKey({}) 䏿¯ææç设计项ç®ç¼å·", event.getBusinessKey()); return; } log.info("[onEvent] æ¶å°BPM审æ¹äºä»¶ï¼projectId={}, status={}", projectId, event.getStatus()); projectService.updateProjectAuditStatus(projectId, event.getStatus()); } } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java
@@ -3,6 +3,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; import java.util.List; @@ -96,4 +99,36 @@ */ Long getBatchCountByToolId(Long toolId); /** * è·å¾æ¹æ¬¡éè´æ¥æºï¼éè´å ¥åºå + IQCï¼ * * @param code æ¹æ¬¡å· * @return éè´æ¥æºå表 */ List<MesWmBatchPurchaseSourceRespVO> getPurchaseSourceList(String code); /** * è·å¾æ¹æ¬¡éå®å»åï¼éå®åºåºå + OQCï¼ * * @param code æ¹æ¬¡å· * @return éå®å»åå表 */ List<MesWmBatchSalesTargetRespVO> getSalesTargetList(String code); /** * è·å¾æ¹æ¬¡å·¥åºæµè½¬ï¼äº§åº/æå ¥äºä»¶ï¼ * * @param code æ¹æ¬¡å· * @return å·¥åºæµè½¬å表 */ List<MesWmBatchProcessTraceRespVO> getProcessTraceList(String code); /** * æ ¹æ® SN ç è·å¾æ¹æ¬¡ * * @param sn SN ç * @return æ¹æ¬¡è®°å½ï¼æªå½ä¸è¿å nullï¼ */ MesWmBatchDO getBatchBySn(String sn); } yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java
@@ -6,9 +6,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO; import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.batch.MesWmBatchMapper; import cn.iocoder.yudao.module.mes.dal.mysql.wm.sn.MesWmSnMapper; import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; @@ -24,6 +29,7 @@ import org.springframework.validation.annotation.Validated; import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -51,6 +57,8 @@ @Resource private MesMdmItemService mdmItemService; @Resource private MesWmSnMapper snMapper; @Resource private MdmItemBatchConfigApi itemBatchConfigApi; @Resource @@ -372,4 +380,39 @@ return batchMapper.selectCountByToolId(toolId); } @Override public List<MesWmBatchPurchaseSourceRespVO> getPurchaseSourceList(String code) { return batchMapper.selectPurchaseSourceList(code); } @Override public List<MesWmBatchSalesTargetRespVO> getSalesTargetList(String code) { return batchMapper.selectSalesTargetList(code); } @Override public List<MesWmBatchProcessTraceRespVO> getProcessTraceList(String code) { List<MesWmBatchProcessTraceRespVO> list = batchMapper.selectProcessTraceList(code); if (CollUtil.isEmpty(list)) { return list; } // æå·¥åãå·¥åºåºå·ãäºä»¶æ¶é´æåºï¼sort å¯è½ä¸ºç©ºï¼ç©ºå¼å åºï¼ list.sort(Comparator.comparing(MesWmBatchProcessTraceRespVO::getWorkOrderId, Comparator.nullsLast(Comparator.naturalOrder())) .thenComparing(MesWmBatchProcessTraceRespVO::getProcessSort, Comparator.nullsLast(Comparator.naturalOrder())) .thenComparing(MesWmBatchProcessTraceRespVO::getEventTime, Comparator.nullsLast(Comparator.naturalOrder()))); return list; } @Override public MesWmBatchDO getBatchBySn(String sn) { MesWmSnDO snDO = snMapper.selectOne(MesWmSnDO::getCode, sn); if (snDO == null || StrUtil.isBlank(snDO.getBatchCode())) { return null; } return batchMapper.selectByCode(snDO.getBatchCode()); } } yudao-module-mes/src/main/resources/mapper/wm/batch/MesWmBatchMapper.xml
@@ -11,14 +11,15 @@ <!-- åå追溯ï¼ä»æä¸ªåæææ¹æ¬¡åºåï¼æ¥æ¾å®è¢«åªäºå·¥åæ¶èåï¼äº§åºäºåªäºæåæ¹æ¬¡ SQL è·¯å¾ï¼åºåäºå¡(æ¶è OUT) â æ¶èå â æ¥å·¥è®°å½ â åºåäºå¡(äº§åº IN) â æ¹æ¬¡ é¾è·¯ï¼åºåäºå¡(æ¶è OUT, biz=123, biz_id=æ¶èåid) â æ¶èå â æ¥å·¥ â 产åºå(feedback_id) â åºåäºå¡(äº§åº IN, biz=124, biz_id=产åºåid) â æ¹æ¬¡ --> <select id="selectListByForward" parameterType="String" resultMap="BatchTraceResult"> SELECT DISTINCT pf.work_order_id, pf.item_id, tx_produce.batch_id, tx_produce.batch_code FROM mes_wm_transaction tx_consume LEFT JOIN mes_wm_item_consume ic ON tx_consume.biz_id = ic.id AND tx_consume.biz_type = 123 AND ic.deleted = 0 LEFT JOIN mes_pro_feedback pf ON pf.id = ic.feedback_id AND pf.deleted = 0 LEFT JOIN mes_wm_transaction tx_produce ON tx_produce.biz_id = pf.id AND tx_produce.biz_type = 124 AND tx_produce.deleted = 0 JOIN mes_wm_item_consume ic ON tx_consume.biz_id = ic.id AND tx_consume.biz_type = 123 AND ic.deleted = 0 JOIN mes_pro_feedback pf ON pf.id = ic.feedback_id AND pf.deleted = 0 JOIN mes_wm_product_produce pp ON pp.feedback_id = pf.id AND pp.deleted = 0 JOIN mes_wm_transaction tx_produce ON tx_produce.biz_id = pp.id AND tx_produce.biz_type = 124 AND tx_produce.deleted = 0 WHERE tx_consume.batch_code = #{batchCode} AND tx_consume.biz_type = 123 AND tx_consume.deleted = 0 @@ -27,19 +28,65 @@ <!-- åå追溯ï¼ä»æä¸ªæåæ¹æ¬¡åºåï¼æ¥æ¾çäº§å®æ¶æ¶èäºåªäºåæææ¹æ¬¡ SQL è·¯å¾ï¼åºåäºå¡(äº§åº IN) â 产åºå â æ¥å·¥è®°å½ â åºåäºå¡(æ¶è OUT) â æ¹æ¬¡ é¾è·¯ï¼åºåäºå¡(äº§åº IN, biz=124, biz_id=产åºåid) â 产åºå â æ¥å·¥ â æ¶èå(feedback_id) â åºåäºå¡(æ¶è OUT, biz=123, biz_id=æ¶èåid) â æ¹æ¬¡ --> <select id="selectListByBackward" parameterType="String" resultMap="BatchTraceResult"> SELECT DISTINCT ic.work_order_id, tx_consume.item_id, tx_consume.batch_id, tx_consume.batch_code FROM mes_wm_transaction tx_produce LEFT JOIN mes_wm_product_produce pp ON tx_produce.biz_id = pp.id AND tx_produce.biz_type = 124 AND pp.deleted = 0 LEFT JOIN mes_pro_feedback pf ON pf.id = pp.feedback_id AND pf.deleted = 0 LEFT JOIN mes_wm_transaction tx_consume ON tx_consume.biz_id = pf.id AND tx_consume.biz_type = 123 AND tx_consume.deleted = 0 LEFT JOIN mes_wm_item_consume ic ON ic.id = tx_consume.biz_id AND ic.deleted = 0 JOIN mes_wm_product_produce pp ON tx_produce.biz_id = pp.id AND tx_produce.biz_type = 124 AND pp.deleted = 0 JOIN mes_pro_feedback pf ON pf.id = pp.feedback_id AND pf.deleted = 0 JOIN mes_wm_item_consume ic ON ic.feedback_id = pf.id AND ic.deleted = 0 JOIN mes_wm_transaction tx_consume ON tx_consume.biz_id = ic.id AND tx_consume.biz_type = 123 AND tx_consume.deleted = 0 WHERE tx_produce.batch_code = #{batchCode} AND tx_produce.biz_type = 124 AND tx_produce.deleted = 0 AND tx_consume.batch_id IS NOT NULL </select> <!-- æ¹æ¬¡éè´æ¥æºï¼æ¹æ¬¡ â éè´å ¥åºè¡ â éè´å ¥åºå â IQC --> <select id="selectPurchaseSourceList" parameterType="String" resultType="cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO"> SELECT r.code AS receipt_code, r.receipt_date, r.purchase_order_code, r.vendor_id, iqc.code AS iqc_code, iqc.check_result AS check_result, rl.batch_code, rl.item_id, rl.received_quantity FROM mes_wm_item_receipt_line rl JOIN mes_wm_item_receipt r ON r.id = rl.receipt_id AND r.deleted = 0 LEFT JOIN mes_qc_iqc iqc ON iqc.id = r.iqc_id AND iqc.deleted = 0 WHERE rl.batch_code = #{batchCode} AND rl.deleted = 0 </select> <!-- æ¹æ¬¡éå®å»åï¼æ¹æ¬¡ â éå®åºåºè¡ â éå®åºåºå â OQC --> <select id="selectSalesTargetList" parameterType="String" resultType="cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO"> SELECT s.code AS sales_code, s.sales_date, s.sales_order_code, s.client_id, oqc.code AS oqc_code, oqc.check_result AS check_result, sl.batch_code, sl.item_id, sl.quantity, sl.quality_status FROM mes_wm_product_sales_line sl JOIN mes_wm_product_sales s ON s.id = sl.sales_id AND s.deleted = 0 LEFT JOIN mes_qc_oqc oqc ON oqc.id = sl.oqc_id AND oqc.deleted = 0 WHERE sl.batch_code = #{batchCode} AND sl.deleted = 0 </select> <!-- æ¹æ¬¡å·¥åºæµè½¬ï¼äº§åº(OUT)/æå ¥(IN) äºä»¶èåï¼æ é建表 --> <select id="selectProcessTraceList" parameterType="String" resultType="cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO"> SELECT 'OUT' AS event_type, pp.work_order_id, pp.process_id, ppl.batch_code, ppl.quantity, ppl.quality_status, pp.produce_date AS event_time, wop.sort AS process_sort FROM mes_wm_product_produce_line ppl JOIN mes_wm_product_produce pp ON pp.id = ppl.produce_id AND pp.deleted = 0 LEFT JOIN mes_pro_work_order_process wop ON wop.work_order_id = pp.work_order_id AND wop.process_id = pp.process_id AND wop.deleted = 0 WHERE ppl.batch_code = #{batchCode} AND ppl.deleted = 0 UNION ALL SELECT 'IN' AS event_type, ic.work_order_id, ic.process_id, icd.batch_code, icd.quantity, NULL AS quality_status, ic.consume_date AS event_time, wop.sort AS process_sort FROM mes_wm_item_consume_detail icd JOIN mes_wm_item_consume ic ON ic.id = icd.consume_id AND ic.deleted = 0 LEFT JOIN mes_pro_work_order_process wop ON wop.work_order_id = ic.work_order_id AND wop.process_id = ic.process_id AND wop.deleted = 0 WHERE icd.batch_code = #{batchCode} AND icd.deleted = 0 </select> </mapper> yudao-server/src/main/resources/application-yzfx.yaml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,324 @@ server: port: 48080 --- #################### æ°æ®åºç¸å ³é ç½® #################### spring: autoconfigure: # noinspection SpringBootApplicationYaml exclude: - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # é»è®¤ local ç¯å¢ï¼ä¸å¼å¯ Quartz çèªå¨é ç½® - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # ç¦ç¨ AI 模åç Qdrantï¼æå¨å建 - org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration # ç¦ç¨ AI 模åç Redisï¼æå¨å建 - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # ç¦ç¨ AI 模åç Milvusï¼æå¨å建 - org.dromara.trans.config.TransServiceConfig # TODO èè¿ï¼easy-trans å ¼å®¹ Spring Boot 4 åç§»é¤ï¼TransServiceConfig å¼ç¨äºå·²ç§»é¤ç RestTemplateBuilderï¼ # ç¦ç¨æªé ç½® API Key çæ¨¡åèªå¨é ç½®ï¼åªä¿çéä¹åé® Embedding çæå¨é ç½®ï¼ - org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration - org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration - org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration - org.springframework.ai.model.openai.autoconfigure.OpenAiAudioSpeechAutoConfiguration - org.springframework.ai.model.openai.autoconfigure.OpenAiAudioTranscriptionAutoConfiguration - org.springframework.ai.model.openai.autoconfigure.OpenAiModerationAutoConfiguration - org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration - org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration - org.springframework.ai.model.google.genai.autoconfigure.chat.GoogleGenAiChatAutoConfiguration - org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiEmbeddingConnectionAutoConfiguration - org.springframework.ai.model.google.genai.autoconfigure.embedding.GoogleGenAiTextEmbeddingAutoConfiguration - org.springframework.ai.model.ollama.autoconfigure.OllamaApiAutoConfiguration - org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration - org.springframework.ai.model.ollama.autoconfigure.OllamaEmbeddingAutoConfiguration - org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration # æ°æ®æºé 置项 datasource: druid: # Druid ãçæ§ãç¸å ³çå ¨å±é ç½® web-stat-filter: enabled: true stat-view-servlet: enabled: true allow: # 设置ç½ååï¼ä¸å¡«åå 许ææè®¿é® url-pattern: /druid/* login-username: # æ§å¶å°ç®¡çç¨æ·ååå¯ç login-password: filter: stat: enabled: true log-slow-sql: true # æ ¢ SQL è®°å½ slow-sql-millis: 100 merge-sql: true wall: config: multi-statement-allow: true dynamic: # 夿°æ®æºé ç½® druid: # Druid ãè¿æ¥æ± ãç¸å ³çå ¨å±é ç½® initial-size: 1 # åå§è¿æ¥æ° min-idle: 1 # æå°è¿æ¥æ± æ°é max-active: 20 # æå¤§è¿æ¥æ± æ°é max-wait: 60000 # é ç½®è·åè¿æ¥çå¾ è¶ æ¶çæ¶é´ï¼åä½ï¼æ¯«ç§ï¼1 åéï¼ time-between-eviction-runs-millis: 60000 # é ç½®é´éå¤ä¹ æè¿è¡ä¸æ¬¡æ£æµï¼æ£æµéè¦å ³éç空é²è¿æ¥ï¼åä½ï¼æ¯«ç§ï¼1 åéï¼ min-evictable-idle-time-millis: 600000 # é ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿å°çåçæ¶é´ï¼åä½ï¼æ¯«ç§ï¼10 åéï¼ max-evictable-idle-time-millis: 1800000 # é ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿大çåçæ¶é´ï¼åä½ï¼æ¯«ç§ï¼30 åéï¼ validation-query: SELECT 1 FROM DUAL # é ç½®æ£æµè¿æ¥æ¯å¦ææ test-while-idle: true test-on-borrow: false test-on-return: false pool-prepared-statements: true # æ¯å¦å¼å¯ PreparedStatement ç¼å max-pool-prepared-statement-per-connection-size: 20 # æ¯ä¸ªè¿æ¥ç¼åç PreparedStatement æ°é primary: master datasource: master: url: jdbc:mysql://172.17.0.1:9002/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X è¿æ¥çç¤ºä¾ # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X è¿æ¥çç¤ºä¾ # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL è¿æ¥çç¤ºä¾ # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle è¿æ¥çç¤ºä¾ # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer è¿æ¥çç¤ºä¾ # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM è¿æ¥çç¤ºä¾ # url: jdbc:kingbase8://127.0.0.1:54321/test # 人大éä» KingbaseES è¿æ¥çç¤ºä¾ # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss è¿æ¥çç¤ºä¾ # url: jdbc:postgresql://127.0.0.1:5866/ruoyi-vue-pro # çé« HighGo è¿æ¥çç¤ºä¾ username: root password: yzfx@123456.. # username: sa # SQL Server è¿æ¥çç¤ºä¾ # password: Yudao@2024 # SQL Server è¿æ¥çç¤ºä¾ # username: SYSDBA # DM è¿æ¥çç¤ºä¾ # password: SYSDBA001 # DM è¿æ¥çç¤ºä¾ # username: root # OpenGauss è¿æ¥çç¤ºä¾ # password: Yudao@2024 # OpenGauss è¿æ¥çç¤ºä¾ # username: root # çé« HighGo è¿æ¥çç¤ºä¾ # password: 123456 # çé« HighGo è¿æ¥çç¤ºä¾ slave: # 模æä»åºï¼å¯æ ¹æ®èªå·±éè¦ä¿®æ¹ lazy: true # å¼å¯æå è½½ï¼ä¿è¯å¯å¨é度 url: jdbc:mysql://172.17.0.1:9002/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true username: root password: yzfx@123456 # tdengine: # IoT æ°æ®åºï¼éè¦ IoT ç©èç½åå¼å¯å¢ï¼ï¼ # lazy: true # å¼å¯æå è½½ï¼ä¿è¯å¯å¨é度 # url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro?varcharAsString=true&enableAutoReconnect=true # åè§ï¼https://t.zsxq.com/qaX9cï¼å¼å¯ TDengine WebSocket èªå¨éè¿ # driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver # username: root # password: taosdata # druid: # validation-query: SELECT SERVER_STATUS() # TDengine æ°æ®æºçæææ§æ£æ¥ SQL # Redis é ç½®ãRedisson é»è®¤çé 置足å¤ä½¿ç¨ï¼ä¸è¬ä¸éè¦è¿è¡è°ä¼ data: redis: host: 172.17.0.1 # å°å port: 6379 # ç«¯å£ database: 1 # æ°æ®åºç´¢å¼ # password: dev # å¯ç ï¼å»ºè®®ç产ç¯å¢å¼å¯ --- #################### 宿¶ä»»å¡ç¸å ³é ç½® #################### # Quartz é 置项ï¼å¯¹åº QuartzProperties é 置类 spring: quartz: auto-startup: true # æ¬å°å¼åç¯å¢ï¼å°½éä¸è¦å¼å¯ Job scheduler-name: schedulerName # Scheduler ååãé»è®¤ä¸º schedulerName job-store-type: jdbc # Job åå¨å¨ç±»åãé»è®¤ä¸º memory 表示å åï¼å¯é jdbc ä½¿ç¨æ°æ®åºã wait-for-jobs-to-complete-on-shutdown: true # åºç¨å ³éæ¶ï¼æ¯å¦çå¾ å®æ¶ä»»å¡æ§è¡å®æãé»è®¤ä¸º false ï¼å»ºè®®è®¾ç½®ä¸º true properties: # æ·»å Quartz Scheduler éå 屿§ï¼æ´å¤å¯ä»¥ç http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html ææ¡£ org: quartz: # Scheduler ç¸å ³é ç½® scheduler: instanceName: schedulerName instanceId: AUTO # èªå¨çæ instance ID # JobStore ç¸å ³é ç½® jobStore: # JobStore å®ç°ç±»ãå¯è§å客ï¼https://blog.csdn.net/weixin_42458219/article/details/122247162 class: org.springframework.scheduling.quartz.LocalDataSourceJobStore isClustered: true # æ¯éç¾¤æ¨¡å¼ clusterCheckinInterval: 15000 # éç¾¤æ£æ¥é¢çï¼åä½ï¼æ¯«ç§ãé»è®¤ä¸º 15000ï¼å³ 15 ç§ misfireThreshold: 60000 # misfire éå¼ï¼åä½ï¼æ¯«ç§ã # çº¿ç¨æ± ç¸å ³é ç½® threadPool: threadCount: 25 # çº¿ç¨æ± 大å°ãé»è®¤ä¸º 10 ã threadPriority: 5 # 线ç¨ä¼å 级 class: org.quartz.simpl.SimpleThreadPool # çº¿ç¨æ± ç±»å jdbc: # ä½¿ç¨ JDBC ç JobStore çæ¶åï¼JDBC çé ç½® initialize-schema: NEVER # æ¯å¦èªå¨ä½¿ç¨ SQL åå§å Quartz è¡¨ç»æãè¿é设置æ never ï¼æä»¬æå¨åå»ºè¡¨ç»æã --- #################### æ¶æ¯éåç¸å ³ #################### # rocketmq é 置项ï¼å¯¹åº RocketMQProperties é 置类 rocketmq: name-server: 127.0.0.1:9876 # RocketMQ Namesrv spring: # RabbitMQ é 置项ï¼å¯¹åº RabbitProperties é 置类 rabbitmq: host: 127.0.0.1 # RabbitMQ æå¡çå°å port: 5672 # RabbitMQ æå¡çç«¯å£ username: rabbit # RabbitMQ æå¡çè´¦å· password: rabbit # RabbitMQ æå¡çå¯ç # Kafka é 置项ï¼å¯¹åº KafkaProperties é 置类 kafka: bootstrap-servers: 127.0.0.1:9092 # æå® Kafka Broker å°åï¼å¯ä»¥è®¾ç½®å¤ä¸ªï¼ä»¥éå·åé --- #################### æå¡ä¿éç¸å ³é ç½® #################### # Lock4j é 置项 lock4j: acquire-timeout: 3000 # è·ååå¸å¼éè¶ æ¶æ¶é´ï¼é»è®¤ä¸º 3000 æ¯«ç§ expire: 30000 # åå¸å¼éçè¶ æ¶æ¶é´ï¼é»è®¤ä¸º 30000 æ¯«ç§ --- #################### çæ§ç¸å ³é ç½® #################### # Actuator çæ§ç«¯ç¹çé 置项 management: endpoints: web: base-path: /actuator # Actuator æä¾ç API æ¥å£çæ ¹ç®å½ãé»è®¤ä¸º /actuator exposure: include: '*' # éè¦å¼æ¾ç端ç¹ãé»è®¤å¼åªæå¼ health å info 两个端ç¹ãéè¿è®¾ç½® * ï¼å¯ä»¥å¼æ¾ææç«¯ç¹ã # Spring Boot Admin é 置项 spring: boot: admin: # Spring Boot Admin Client 客æ·ç«¯çç¸å ³é ç½® client: url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server å°å instance: service-host-type: IP # 注åå®ä¾æ¶ï¼ä¼å ä½¿ç¨ IP [IP, HOST_NAME, CANONICAL_HOST_NAME] username: admin password: admin # Spring Boot Admin Server æå¡ç«¯çç¸å ³é ç½® context-path: /admin # é ç½® Spring # å 许åµå ¥ iframe çååï¼æ¯æéé 符ï¼ï¼å®é é¨ç½²æ¶ï¼å¯ä»¥æ¹ä¸º "'self' [ä½ çå ¬ç½åå]" frame-ancestors: "'self' localhost localhost:48080 127.0.0.1 127.0.0.1:48080" # æ¥å¿æä»¶é ç½® logging: file: name: logs/${spring.application.name}.log # æ¥å¿æä»¶åï¼ç¸å¯¹äºé¡¹ç®æ ¹ç®å½ level: # é ç½®èªå·±åç MyBatis Mapper æå°æ¥å¿ cn.iocoder.yudao.module.bpm.dal.mysql: debug cn.iocoder.yudao.module.infra.dal.mysql: debug cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # é ç½® ApiErrorLogMapper çæ¥å¿çº§å«ä¸º infoï¼é¿å å GlobalExceptionHandler éå¤æå° cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # é ç½® JobLogMapper çæ¥å¿çº§å«ä¸º info cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # é ç½® FileConfigMapper çæ¥å¿çº§å«ä¸º info cn.iocoder.yudao.module.pay.dal.mysql: debug cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # é ç½® PayNotifyTaskMapper çæ¥å¿çº§å«ä¸º info cn.iocoder.yudao.module.system.dal.mysql: debug cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # é ç½® SmsChannelMapper çæ¥å¿çº§å«ä¸º info cn.iocoder.yudao.module.tool.dal.mysql: debug cn.iocoder.yudao.module.member.dal.mysql: debug cn.iocoder.yudao.module.trade.dal.mysql: debug cn.iocoder.yudao.module.promotion.dal.mysql: debug cn.iocoder.yudao.module.statistics.dal.mysql: debug cn.iocoder.yudao.module.crm.dal.mysql: debug cn.iocoder.yudao.module.erp.dal.mysql: debug cn.iocoder.yudao.module.mes.dal.mysql: debug cn.iocoder.yudao.module.wms.dal.mysql: debug cn.iocoder.yudao.module.iot.dal.mysql: debug cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG cn.iocoder.yudao.module.iot.service.rule: debug cn.iocoder.yudao.module.ai.dal.mysql: debug cn.iocoder.yudao.module.im.dal.mysql: debug org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO èè¿ï¼å ç¦ç¨ï¼Spring Boot 3.X åå¨é¨åé误ç WARN æç¤º debug: false yudao: ai: vector-store: type: milvus # åéåºç±»åï¼milvus milvus: initialize-schema: true database-name: test collection-name: knowledge_segment_yzfx host: 36.213.180.217 port: 19530 --- #################### å¾®ä¿¡å ¬ä¼å·ãå°ç¨åºç¸å ³é ç½® #################### wx: mp: # å ¬ä¼å·é ç½®ï¼å¿ å¡«ï¼ï¼åè§ https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md ææ¡£ # app-id: wx041349c6f39b268b # æµè¯å·ï¼çå¸å°§æä¾çï¼ # secret: 5abee519483bc9f8cb37ce280e814bd0 # app-id: wx5b23ba7a5589ecbb # æµè¯å·ï¼èªå·±çï¼ # secret: 2a7b3b20c537e52e74afd395eb85f61f app-id: wxf56b1542b9e85f8a # æµè¯å·ï¼Kongdy æä¾çï¼ secret: 496379dcef1ba869e9234de8d598cfd3 # åå¨é ç½®ï¼è§£å³ AccessToken çè·¨èç¹çå ±äº« config-storage: type: RedisTemplate # éç¨ RedisTemplate æä½ Redisï¼ä¼èªå¨ä» Spring ä¸è·å key-prefix: wx # Redis Key çåç¼ http-client-type: HttpComponents # éç¨ HttpComponentsï¼HttpClient 5ï¼è¯·æ±å¾®ä¿¡å ¬ä¼å·å¹³å° miniapp: # å°ç¨åºé ç½®ï¼å¿ å¡«ï¼ï¼åè§ https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md ææ¡£ # appid: wx62056c0d5e8db250 # æµè¯å·ï¼çå¸å°§æä¾çï¼ # secret: 333ae72f41552af1e998fe1f54e1584a # appid: wx63c280fe3248a3e7 # wenhualiançæ¥å£æµè¯å· # secret: 6f270509224a7ae1296bbf1c8cb97aed appid: wxc4598c446f8a9cb3 # æµè¯å·ï¼Kongdy æä¾çï¼ secret: 4a1a04e07f6a4a0751b39c3064a92c8b # appid: wx66186af0759f47c9 # æµè¯å·ï¼puhui æä¾çï¼ # secret: 3218bcbd112cbc614c7264ceb20144ac config-storage: type: RedisTemplate # éç¨ RedisTemplate æä½ Redisï¼ä¼èªå¨ä» Spring ä¸è·å key-prefix: wa # Redis Key çåç¼ http-client-type: HttpComponents # éç¨ HttpComponentsï¼HttpClient 5ï¼è¯·æ±å¾®ä¿¡å°ç¨åºå¹³å° --- #################### è¶ çº§ç®¡çåç¸å ³é ç½® #################### # è¶ çº§ç®¡çåé 置项ï¼è®¾ç½®å½åé¡¹ç®ææèªå®ä¹çé ç½® yudao: captcha: enable: false # æ¬å°ç¯å¢ï¼ææ¶å ³éå¾çéªè¯ç ï¼æ¹ä¾¿ç»å½çæ¥å£çæµè¯ï¼ security: mock-enable: true pay: order-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/order # æ¯ä»æ¸ éçãæ¯ä»ãåè°å°å refund-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/refund # æ¯ä»æ¸ éçã鿬¾ãåè°å°å transfer-notify-url: https://yutou.mynatapp.cc/admin-api/pay/notify/transfer # æ¯ä»æ¸ éçã转账ãåè°å°å access-log: # è®¿é®æ¥å¿çé 置项 enable: false demo: false # å ³éæ¼ç¤ºæ¨¡å¼ wxa-code: env-version: develop # å°ç¨åºçæ¬: æ£å¼ç为 "release"ï¼ä½éªç为 "trial"ï¼å¼åç为 "develop" wxa-subscribe-message: miniprogram-state: developer # 跳转å°ç¨åºç±»åï¼å¼åç为 âdeveloperâï¼ä½éªç为 âtrialâä¸ºï¼æ£å¼ç为 âformalâ tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ å°å¾çå¯é¥ https://lbs.qq.com/service/staticV2/staticGuide/staticDoc storage: # æä»¶ä¸ä¼ é ç½® path: /data/javaWork/mom/file # æä»¶å卿 ¹ç®å½ url-prefix: /admin-api/system/storage-blob # URLè·¯å¾åç¼ domain: http://42.63.70.231:9001 # åååç¼ï¼æå®é ååé ç½®ï¼ï¼å端é 置好åä¸å¤ªå¯¹ç°å¨æ¯ç´è¿åç«¯ï¼ææè¦åç«¯ç«¯å£ expired: 120 # tokenè¿ææ¶é´ï¼åéï¼ use-limit: 10 # tokenä½¿ç¨æ¬¡æ°ä¸é jwt-secret: abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG # JWTå¯é¥ compress: true # æ¯å¦å缩å¾ç need-compress-size: 10MB # 触åå缩çæä»¶å¤§å°éå¼ compress-quality: 0.5 # å缩质é(0.0-1.0) justauth: enabled: true type: DINGTALK: # éé client-id: dingvrnreaje3yqvzhxg client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI ignore-check-redirect-uri: true WECHAT_ENTERPRISE: # ä¼ä¸å¾®ä¿¡ client-id: wwd411c69a39ad2e54 client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw agent-id: 1000004 ignore-check-redirect-uri: true # noinspection SpringBootApplicationYaml WECHAT_MINI_PROGRAM: # 微信å°ç¨åº client-id: ${wx.miniapp.appid} client-secret: ${wx.miniapp.secret} ignore-check-redirect-uri: true ignore-check-state: true # 微信å°ç¨åºï¼ä¸ä¼ä½¿ç¨å° stateï¼æä»¥ä¸è¿è¡æ ¡éª WECHAT_MP: # å¾®ä¿¡å ¬ä¼å· client-id: ${wx.mp.app-id} client-secret: ${wx.mp.secret} ignore-check-redirect-uri: true ALIPAY: # æ¯ä»å®å°ç¨åº client-id: xx client-secret: xx alipay-public-key: xx ignore-check-redirect-uri: true ignore-check-state: true cache: type: REDIS prefix: 'social_auth_state:' # ç¼ååç¼ï¼ç®ååªå¯¹ Redis ç¼åçæï¼é»è®¤ JUSTAUTH::STATE:: timeout: 24h # è¶ æ¶æ¶é¿ï¼ç®ååªå¯¹ Redis ç¼åçæï¼é»è®¤ 3 åé