| docs/生产工单接口变更文档.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/生产工单模块前端联调文档.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/mapper/production/ProductionOperationTaskMapper.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
docs/Éú²ú¹¤µ¥½Ó¿Ú±ä¸üÎĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,264 @@ # çäº§å·¥åæ¥å£åæ´ææ¡£ > ææ¡£çææ¥æï¼2026-06-11 > éç¨åæ¯ï¼dev_天津_ä¸å ´å®å¼º --- ## åæ´è®°å½ | æ¥æ | åæ´å 容 | åæ´äºº | |------|----------|--------| | 2026-06-11 | ä¼å/pageæ¥å£ä¸ºæè®¢ååç»ï¼æ°å¢/byOrder/{orderId}æ¥å£ | - | --- ## ä¸ãæ¥å£æ¦è§ | æ¥å£è·¯å¾ | è¯·æ±æ¹å¼ | 说æ | |----------|----------|------| | `/productionOperationTask/page` | GET | ç产工åå页æ¥è¯¢ï¼æç产订å维度åç»ï¼ | | `/productionOperationTask/byOrder/{orderId}` | GET | æ ¹æ®ç产订åIDæ¥è¯¢å·¥åå表 | --- ## äºãæ¥å£è¯¦æ ### 2.1 ç产工åå页æ¥è¯¢ `/page` #### 请æ±åæ° | åæ°å | ç±»å | å¿ å¡« | 说æ | |--------|------|------|------| | current | Long | å¦ | å½å页ç | | size | Long | å¦ | æ¯é¡µæ¡æ° | | npsNo | String | å¦ | ç产订åå·ï¼æ¨¡ç³æ¥è¯¢ï¼ | | productionOrderId | Long | å¦ | ç产订åIDï¼ç²¾ç¡®å¹é ï¼ | #### ååºå段 | åæ®µå | ç±»å | 说æ | |--------|------|------| | productionOrderId | Long | ç产订åID | | npsNo | String | ç产订åå· | | endOrder | Boolean | æ¯å¦ç»æ | | productName | String | 产ååç§° | | model | String | è§æ ¼åå· | | unit | String | åä½ | | operationName | String | å·¥åºåç§°ï¼å¤ä¸ªéå·åéï¼ | | productionTaskCount | Long | çäº§ä»»å¡æ°é | | planQuantity | BigDecimal | è®¡åæ°éï¼è®¢å级å«ï¼ | | completeQuantity | BigDecimal | 宿æ°éï¼è®¢å级å«ï¼ | | goodQuantity | BigDecimal | è¯åæ°é | | scrapQty | BigDecimal | æ¥åºæ°é | | completionStatus | BigDecimal | 宿è¿åº¦ï¼ç¾åæ¯ï¼ | | type | Integer | å·¥åºç±»åï¼0计æ¶/1è®¡ä»¶ï¼ | | workOrderType | String | å·¥åç±»åï¼æ£å¸¸/è¿å·¥è¿ä¿®ï¼ | | workOrderNo | String | å·¥åç¼å·ï¼å¤ä¸ªéå·åéï¼ | | planStartTime | LocalDate | 计åå¼å§æ¶é´ | | planEndTime | LocalDate | 计åç»ææ¶é´ | | actualStartTime | LocalDate | å®é å¼å§æ¶é´ | | actualEndTime | LocalDate | å®é ç»ææ¶é´ | | status | Integer | ç¶æ | #### æ ¸å¿SQL ```sql SELECT po.id AS productionOrderId, po.nps_no AS npsNo, po.is_end_order AS endOrder, p.product_name AS productName, pm.model AS model, pm.unit AS unit, GROUP_CONCAT(DISTINCT poro.operation_name ORDER BY poro.drag_sort, poro.operation_name SEPARATOR ',') AS operationName, COUNT(DISTINCT pot.id) AS productionTaskCount, po.quantity AS planQuantity, po.complete_quantity AS completeQuantity, po.complete_quantity AS goodQuantity, SUM(IFNULL(scrapStat.scrapQty, 0)) AS scrapQty, ROUND(IFNULL(po.complete_quantity, 0) / NULLIF(po.quantity, 0) * 100, 2) AS completionStatus, MAX(poro.type) AS type, CASE WHEN SUM(CASE WHEN pot.work_order_no LIKE 'FG%' THEN 1 ELSE 0 END) > 0 THEN 'è¿å·¥è¿ä¿®' ELSE 'æ£å¸¸' END AS workOrderType, GROUP_CONCAT(DISTINCT pot.work_order_no ORDER BY pot.work_order_no SEPARATOR ',') AS workOrderNo, MIN(pot.plan_start_time) AS planStartTime, MAX(pot.plan_end_time) AS planEndTime, MIN(pot.actual_start_time) AS actualStartTime, MAX(pot.actual_end_time) AS actualEndTime, MAX(pot.status) AS status FROM production_operation_task pot LEFT JOIN production_order po ON pot.production_order_id = po.id LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id LEFT JOIN product_model pm ON pm.id = po.product_model_id LEFT JOIN product p ON pm.product_id = p.id LEFT JOIN ( SELECT ppm.production_operation_task_id AS taskId, SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty FROM production_product_main ppm LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id GROUP BY ppm.production_operation_task_id ) scrapStat ON scrapStat.taskId = pot.id WHERE ... GROUP BY po.id ORDER BY po.id DESC ``` --- ### 2.2 æ ¹æ®è®¢åIDæ¥è¯¢å·¥åå表 `/byOrder/{orderId}` #### 请æ±åæ° | åæ°å | ç±»å | å¿ å¡« | 说æ | |--------|------|------|------| | orderId | Long | æ¯ | ç产订åIDï¼è·¯å¾åæ°ï¼ | #### ååºå段 | åæ®µå | ç±»å | 说æ | |--------|------|------| | id | Long | å·¥åID | | workOrderNo | String | å·¥åç¼å· | | planStartTime | LocalDate | 计åå¼å§æ¶é´ | | planEndTime | LocalDate | 计åç»ææ¶é´ | | actualStartTime | LocalDate | å®é å¼å§æ¶é´ | | actualEndTime | LocalDate | å®é ç»ææ¶é´ | | status | Integer | ç¶æ | | productionOrderId | Long | ç产订åID | | planQuantity | BigDecimal | è®¡åæ°é | | completeQuantity | BigDecimal | 宿æ°é | | npsNo | String | ç产订åå· | | endOrder | Boolean | æ¯å¦ç»æ | | productName | String | 产ååç§° | | model | String | è§æ ¼åå· | | unit | String | åä½ | | operationName | String | å·¥åºåç§° | | type | Integer | å·¥åºç±»åï¼0计æ¶/1è®¡ä»¶ï¼ | | workOrderType | String | å·¥åç±»åï¼æ£å¸¸/è¿å·¥è¿ä¿®ï¼ | | scrapQty | BigDecimal | æ¥åºæ°é | | completionStatus | BigDecimal | 宿è¿åº¦ï¼ç¾åæ¯ï¼ | | userNames | String | æ¥å·¥äººååç§°ï¼å¤ä¸ªéå·åéï¼ | #### æ ¸å¿SQL ```sql SELECT pot.id, pot.work_order_no, pot.plan_start_time AS planStartTime, pot.plan_end_time AS planEndTime, pot.actual_start_time AS actualStartTime, pot.actual_end_time AS actualEndTime, pot.status, pot.production_order_id AS productionOrderId, pot.plan_quantity AS planQuantity, pot.complete_quantity AS completeQuantity, po.nps_no AS npsNo, po.is_end_order AS endOrder, p.product_name AS productName, pm.model AS model, pm.unit AS unit, poro.operation_name AS operationName, poro.type AS type, CASE WHEN pot.work_order_no LIKE 'FG%' THEN 'è¿å·¥è¿ä¿®' ELSE 'æ£å¸¸' END AS workOrderType, IFNULL(scrapStat.scrapQty, 0) AS scrapQty, ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus FROM production_operation_task pot LEFT JOIN production_order po ON pot.production_order_id = po.id LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id LEFT JOIN product_model pm ON pm.id = IFNULL(poro.product_model_id, po.product_model_id) LEFT JOIN product p ON pm.product_id = p.id LEFT JOIN ( SELECT ppm.production_operation_task_id AS taskId, SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty FROM production_product_main ppm LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id GROUP BY ppm.production_operation_task_id ) scrapStat ON scrapStat.taskId = pot.id WHERE pot.production_order_id = #{orderId} ORDER BY pot.id DESC ``` --- ## ä¸ã两个æ¥å£å¯¹æ¯ | 对æ¯é¡¹ | /page | /byOrder/{orderId} | |--------|-------|---------------------| | æ¥è¯¢ç»´åº¦ | æç产订ååç» | æå·¥åæç» | | åç»ä¾æ® | GROUP BY po.id | æ åç» | | è®¡åæ°éæ¥æº | 订å级å«ï¼po.quantityï¼ | å·¥å级å«ï¼pot.plan_quantityï¼ | | 宿æ°éæ¥æº | 订å级å«ï¼po.complete_quantityï¼ | å·¥å级å«ï¼pot.complete_quantityï¼ | | 宿è¿åº¦è®¡ç® | 订å宿æ°/订åè®¡åæ° | å·¥å宿æ°/å·¥åè®¡åæ° | | å·¥åºå表å±ç¤º | GROUP_CONCATèå | åä¸ªå·¥åº | | ç¨é | å·¥ååè¡¨é¡µï¼æ±æ»è§å¾ï¼ | 订å详æ 页ï¼å·¥åæç»ï¼ | --- ## åãå ³è表说æ | 表å | å«å | 说æ | |------|------|------| | production_operation_task | pot | ç产工å表 | | production_order | po | ç产订å表 | | production_order_routing_operation | poro | ç产订åå·¥èºè·¯çº¿å·¥åºè¡¨ | | product_model | pm | 产åè§æ ¼è¡¨ | | product | p | 产å表 | | production_product_main | ppm | æ¥å·¥ä¸»è¡¨ | | production_product_output | ppo | æ¥å·¥äº§åºè¡¨ | --- ## äºãæä¸¾å¼è¯´æ ### 5.1 å·¥åç¶æ | ç¶æå¼ | 说æ | |--------|------| | 1 | å¾ ç¡®è®¤ | | 2 | å¾ ç产 | | 3 | çäº§ä¸ | | 4 | å·²ç产 | ### 5.2 å·¥åºç±»å | ç±»åå¼ | 说æ | |--------|------| | 0 | è®¡æ¶ | | 1 | 计件 | ### 5.3 å·¥åç±»å夿 - å·¥åå·ä»¥ `FG` å¼å¤´ â è¿å·¥è¿ä¿® - å ¶ä» â æ£å¸¸ --- ## å ãåå¤çé»è¾ ### 6.1 å¡«å å·¥åºç±»å `fillOperationTypes` - ä» `production_order_routing_operation` 表æ¹éæ¥è¯¢å·¥åºç±»å - æ ¹æ® `productionOrderRoutingOperationId` å ³èåå¡« ### 6.2 å¡«å æ¥å·¥äººååç§° `fillUserNames` - è§£æå·¥åç `userIds` åæ®µï¼JSONæ°ç»æ ¼å¼ï¼ - ä» `sys_user` 表æ¹éæ¥è¯¢ç¨æ·æµç§° - æ¼æ¥ä¸ºéå·åéçå符串 --- ## ä¸ãæ¶åæä»¶ | æä»¶è·¯å¾ | 说æ | |----------|------| | `controller/ProductionOperationTaskController.java` | æ§å¶å¨ | | `service/ProductionOperationTaskService.java` | æå¡æ¥å£ | | `service/impl/ProductionOperationTaskServiceImpl.java` | æå¡å®ç° | | `mapper/ProductionOperationTaskMapper.java` | Mapperæ¥å£ | | `mapper/production/ProductionOperationTaskMapper.xml` | Mapper XML | | `pojo/ProductionOperationTask.java` | å·¥åå®ä½ | | `bean/dto/ProductionOperationTaskDto.java` | æ¥è¯¢DTO | | `bean/vo/ProductionOperationTaskVo.java` | ååºVO | docs/Éú²ú¹¤µ¥Ä£¿éǰ¶ËÁªµ÷Îĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,505 @@ # çäº§å·¥åæ¨¡åå端èè°ææ¡£ > ææ¡£çææ¥æï¼2026-06-11 > éç¨åæ¯ï¼dev_天津_ä¸å ´å®å¼º --- ## åæ´è®°å½ | æ¥æ | åæ´å 容 | å½±åèå´ | |------|----------|----------| | 2026-06-11 | /pageæ¥å£æ¹ä¸ºæè®¢ååç»èå | å表页å±ç¤ºé»è¾è°æ´ | | 2026-06-11 | æ°å¢/byOrder/{orderId}æ¥å£ | 订å详æ 页工åå表 | --- ## ä¸ãæ¥å£å表 | æ¥å£åç§° | æ¥å£è·¯å¾ | è¯·æ±æ¹å¼ | 说æ | |----------|----------|----------|------| | å·¥åå页æ¥è¯¢ | `/productionOperationTask/page` | GET | æç产订å维度åç»å±ç¤º | | 订åå·¥åå表 | `/productionOperationTask/byOrder/{orderId}` | GET | æ ¹æ®è®¢åIDæ¥è¯¢å·¥åæç» | --- ## äºãæ¥å£è¯¦æ ### 2.1 å·¥åå页æ¥è¯¢ #### åºæ¬ä¿¡æ¯ ``` GET /productionOperationTask/page ``` #### 请æ±åæ°ï¼Queryï¼ | åæ°å | ç±»å | å¿ å¡« | 说æ | |--------|------|------|------| | current | Number | å¦ | å½å页ç ï¼é»è®¤1 | | size | Number | å¦ | æ¯é¡µæ¡æ°ï¼é»è®¤10 | | npsNo | String | å¦ | ç产订åå·ï¼æ¨¡ç³æ¥è¯¢ | | productionOrderId | Number | å¦ | ç产订åIDï¼ç²¾ç¡®å¹é | #### 请æ±ç¤ºä¾ ```javascript // åºç¡å页æ¥è¯¢ axios.get('/productionOperationTask/page', { params: { current: 1, size: 10 } }) // æè®¢åå·çé axios.get('/productionOperationTask/page', { params: { current: 1, size: 10, npsNo: 'SC202606' } }) ``` #### ååºç»æ ```json { "code": 200, "msg": "æä½æå", "data": { "records": [ { "productionOrderId": 123, "npsNo": "SC20260611001", "endOrder": false, "productName": "çµçº¿çµç¼", "model": "RVV 3*2.5", "unit": "ç±³", "operationName": "ç»çº¿,ç»ç¼,æç¼", "productionTaskCount": 3, "planQuantity": 1000.00, "completeQuantity": 500.00, "goodQuantity": 500.00, "scrapQty": 10.00, "completionStatus": 50.00, "type": 1, "workOrderType": "æ£å¸¸", "workOrderNo": "GD20260611001,GD20260611002,GD20260611003", "planStartTime": "2026-06-10", "planEndTime": "2026-06-15", "actualStartTime": "2026-06-11", "actualEndTime": null, "status": 3 } ], "total": 100, "current": 1, "size": 10 } } ``` #### ååºå段说æ | åæ®µå | ç±»å | 说æ | å端å±ç¤ºå»ºè®® | |--------|------|------|--------------| | productionOrderId | Number | ç产订åID | ç¨äºè·³è½¬è®¢å详æ | | npsNo | String | ç产订åå· | å表主æ é¢ | | endOrder | Boolean | æ¯å¦ç»æ | å·²ç»ææ¶æ¾ç¤º"å·²ç»æ"æ ç¾ | | productName | String | 产ååç§° | åè¡¨å¯æ é¢ | | model | String | è§æ ¼åå· | 产åè§æ ¼å±ç¤º | | unit | String | åä½ | æ°éåä½ | | operationName | String | å·¥åºåç§°ï¼éå·åéï¼ | å·¥åºå表å±ç¤º | | productionTaskCount | Number | å·¥å任塿°é | æ¾ç¤º"å ±X个工å" | | planQuantity | Number | è®¡åæ°éï¼è®¢åçº§ï¼ | è¿åº¦æ¡æ»æ° | | completeQuantity | Number | 宿æ°éï¼è®¢åçº§ï¼ | è¿åº¦æ¡å·²å®æ | | goodQuantity | Number | è¯åæ°é | è¯åç»è®¡ | | scrapQty | Number | æ¥åºæ°é | æ¥åºç»è®¡ï¼çº¢è²æ è®°ï¼ | | completionStatus | Number | 宿è¿åº¦ç¾åæ¯ | è¿åº¦æ¡æ°å¼ | | type | Number | å·¥åºç±»å | 0=计æ¶ï¼1=计件 | | workOrderType | String | å·¥åç±»å | "æ£å¸¸"æ"è¿å·¥è¿ä¿®" | | workOrderNo | String | å·¥åç¼å·ï¼éå·åéï¼ | ç¹å»å¯å±å¼æ¥ç | | planStartTime | String | 计åå¼å§æ¶é´ | æ ¼å¼ï¼YYYY-MM-DD | | planEndTime | String | 计åç»ææ¶é´ | æ ¼å¼ï¼YYYY-MM-DD | | actualStartTime | String | å®é å¼å§æ¶é´ | æ ¼å¼ï¼YYYY-MM-DD | | actualEndTime | String | å®é ç»ææ¶é´ | æ ¼å¼ï¼YYYY-MM-DD | | status | Number | ç¶æ | è§ç¶ææä¸¾è¡¨ | --- ### 2.2 订åå·¥åå表 #### åºæ¬ä¿¡æ¯ ``` GET /productionOperationTask/byOrder/{orderId} ``` #### 请æ±åæ°ï¼Pathï¼ | åæ°å | ç±»å | å¿ å¡« | 说æ | |--------|------|------|------| | orderId | Number | æ¯ | ç产订åID | #### 请æ±ç¤ºä¾ ```javascript // æ¥è¯¢è®¢åID为123çææå·¥å axios.get('/productionOperationTask/byOrder/123') ``` #### ååºç»æ ```json { "code": 200, "msg": "æä½æå", "data": [ { "id": 1, "workOrderNo": "GD20260611001", "planStartTime": "2026-06-10", "planEndTime": "2026-06-12", "actualStartTime": "2026-06-11", "actualEndTime": null, "status": 3, "productionOrderId": 123, "planQuantity": 500.00, "completeQuantity": 300.00, "npsNo": "SC20260611001", "endOrder": false, "productName": "çµçº¿çµç¼", "model": "RVV 3*2.5", "unit": "ç±³", "operationName": "ç»çº¿", "type": 1, "workOrderType": "æ£å¸¸", "scrapQty": 5.00, "completionStatus": 60.00, "userNames": "å¼ ä¸,æå" }, { "id": 2, "workOrderNo": "FG20260611001", "planStartTime": "2026-06-12", "planEndTime": "2026-06-15", "actualStartTime": "2026-06-13", "actualEndTime": null, "status": 3, "productionOrderId": 123, "planQuantity": 100.00, "completeQuantity": 50.00, "npsNo": "SC20260611001", "endOrder": false, "productName": "çµçº¿çµç¼", "model": "RVV 3*2.5", "unit": "ç±³", "operationName": "ç»ç¼", "type": 0, "workOrderType": "è¿å·¥è¿ä¿®", "scrapQty": 2.00, "completionStatus": 50.00, "userNames": "çäº" } ] } ``` #### ååºå段说æ | åæ®µå | ç±»å | 说æ | å端å±ç¤ºå»ºè®® | |--------|------|------|--------------| | id | Number | å·¥åID | ç¨äºæ¥å·¥ã详æ 跳转 | | workOrderNo | String | å·¥åç¼å· | å表主æ é¢ | | planStartTime | String | 计åå¼å§æ¶é´ | æ¶é´èå´å±ç¤º | | planEndTime | String | 计åç»ææ¶é´ | æ¶é´èå´å±ç¤º | | actualStartTime | String | å®é å¼å§æ¶é´ | å®é æ¶é´å±ç¤º | | actualEndTime | String | å®é ç»ææ¶é´ | å®é æ¶é´å±ç¤º | | status | Number | å·¥åç¶æ | ç¶ææ ç¾ | | productionOrderId | Number | ç产订åID | å ³è订å | | planQuantity | Number | è®¡åæ°éï¼å·¥åçº§ï¼ | è¿åº¦æ¡æ»æ° | | completeQuantity | Number | 宿æ°éï¼å·¥åçº§ï¼ | è¿åº¦æ¡å·²å®æ | | npsNo | String | ç产订åå· | 订åå·å±ç¤º | | endOrder | Boolean | æ¯å¦ç»æ | ç»ææ ç¾ | | productName | String | 产ååç§° | 产åä¿¡æ¯ | | model | String | è§æ ¼åå· | è§æ ¼å±ç¤º | | unit | String | åä½ | æ°éåä½ | | operationName | String | å·¥åºåç§° | åä¸ªå·¥åº | | type | Number | å·¥åºç±»å | 0=计æ¶ï¼1=计件 | | workOrderType | String | å·¥åç±»å | è¿å·¥è¿ä¿®ç¨çº¢è²æ è®° | | scrapQty | Number | æ¥åºæ°é | æ¥åºç»è®¡ | | completionStatus | Number | 宿è¿åº¦ç¾åæ¯ | è¿åº¦æ¡æ°å¼ | | userNames | String | æ¥å·¥äººåï¼éå·åéï¼ | 人åå表 | --- ## ä¸ãæä¸¾å¼æ å° ### 3.1 å·¥åç¶æ | ç¶æå¼ | ææ¡ | æ ç¾é¢è²å»ºè®® | |--------|------|--------------| | 1 | å¾ ç¡®è®¤ | ç°è²/é»è®¤ | | 2 | å¾ ç产 | èè²/info | | 3 | çäº§ä¸ | 绿è²/success | | 4 | å·²ç产 | 深绿è²/success-dark | #### åç«¯ç¶ææ å°ç¤ºä¾ ```javascript const statusMap = { 1: { text: 'å¾ ç¡®è®¤', color: 'default' }, 2: { text: 'å¾ ç产', color: 'info' }, 3: { text: 'ç产ä¸', color: 'success' }, 4: { text: 'å·²ç产', color: 'success-dark' } } function getStatusTag(status) { return statusMap[status] || { text: 'æªç¥', color: 'default' } } ``` ### 3.2 å·¥åºç±»å | ç±»åå¼ | ææ¡ | 说æ | |--------|------|------| | 0 | è®¡æ¶ | æå·¥æ¶è®¡ç®å·¥èµ | | 1 | 计件 | æäº§é计ç®å·¥èµ | ```javascript const typeMap = { 0: '计æ¶', 1: '计件' } ``` ### 3.3 å·¥åç±»å夿 | ç±»å | 夿è§å | æ ç¾é¢è²å»ºè®® | |------|----------|--------------| | æ£å¸¸ | workOrderNo ä¸ä»¥ 'FG' å¼å¤´ | é»è®¤è² | | è¿å·¥è¿ä¿® | workOrderNo 以 'FG' å¼å¤´ | 红è²/error | ```javascript function getWorkOrderType(workOrderNo) { return workOrderNo?.startsWith('FG') ? 'è¿å·¥è¿ä¿®' : 'æ£å¸¸' } ``` --- ## åã页é¢è®¾è®¡å»ºè®® ### 4.1 å·¥åå表页ï¼ä½¿ç¨ /page æ¥å£ï¼ #### è¡¨æ ¼å设计 | åå | åæ®µ | 宽度 | 说æ | |------|------|------|------| | ç产订åå· | npsNo | 150px | å¯ç¹å»è·³è½¬è¯¦æ | | 产ååç§° | productName | 120px | - | | è§æ ¼åå· | model | 150px | - | | å·¥åº | operationName | 200px | å¤ä¸ªå·¥åºéå·åé | | å·¥åç±»å | workOrderType | 100px | æ£å¸¸/è¿å·¥è¿ä¿® | | è®¡åæ°é | planQuantity | 100px | 订åçº§å« | | 宿æ°é | completeQuantity | 100px | 订åçº§å« | | 宿è¿åº¦ | completionStatus | 120px | è¿åº¦æ¡+ç¾åæ¯ | | æ¥åºæ°é | scrapQty | 80px | çº¢è²æ è®° | | 工忰 | productionTaskCount | 80px | å ±X个工å | | ç¶æ | status | 80px | ç¶ææ ç¾ | | æä½ | - | 150px | æ¥ç详æ ãæ¥å·¥ç | #### è¿åº¦æ¡å±ç¤º ```javascript // 使ç¨è¿åº¦æ¡ç»ä»¶ <Progress percent={item.completionStatus} strokeColor="#52c41a" format={percent => `${percent}%`} /> ``` ### 4.2 订å详æ 页工åå表ï¼ä½¿ç¨ /byOrder/{orderId} æ¥å£ï¼ #### è¡¨æ ¼å设计 | åå | åæ®µ | 宽度 | 说æ | |------|------|------|------| | å·¥åç¼å· | workOrderNo | 150px | 主æ è¯ | | å·¥åºåç§° | operationName | 120px | åä¸ªå·¥åº | | å·¥åç±»å | workOrderType | 100px | æ£å¸¸/è¿å·¥è¿ä¿® | | å·¥åºç±»å | type | 80px | 计æ¶/计件 | | è®¡åæ°é | planQuantity | 100px | å·¥åçº§å« | | 宿æ°é | completeQuantity | 100px | å·¥åçº§å« | | 宿è¿åº¦ | completionStatus | 120px | è¿åº¦æ¡ | | æ¥åºæ°é | scrapQty | 80px | çº¢è²æ è®° | | æ¥å·¥äººå | userNames | 150px | å¤äººéå·åé | | è®¡åæ¶é´ | planStartTime ~ planEndTime | 180px | æ¶é´èå´ | | å®é æ¶é´ | actualStartTime ~ actualEndTime | 180px | æ¶é´èå´ | | ç¶æ | status | 80px | ç¶ææ ç¾ | | æä½ | - | 150px | æ¥å·¥ãæµè½¬å¡ç | --- ## äºã两个æ¥å£æ°æ®å·®å¼å¯¹æ¯ | 对æ¯é¡¹ | /page æ¥å£ | /byOrder/{orderId} æ¥å£ | |--------|------------|-------------------------| | æ°æ®ç»´åº¦ | è®¢åæ±æ» | å·¥åæç» | | planQuantity | 订åè®¡åæ° | å·¥åè®¡åæ° | | completeQuantity | 订åå®ææ° | å·¥åå®ææ° | | completionStatus | 订åè¿åº¦ | å·¥åè¿åº¦ | | operationName | å¤å·¥åºèå | åä¸ªå·¥åº | | workOrderNo | å¤å·¥åèå | å个工å | | userNames | æ | ææ¥å·¥äººå | | ç¨é | åè¡¨æ±æ»é¡µ | è¯¦æ æç»é¡µ | --- ## å ãå端è°ç¨æ³¨æäºé¡¹ ### 6.1 å页忰 - `/page` æ¥å£æ¯æå页ï¼éä¼ `current` å `size` - `/byOrder/{orderId}` æ¥å£ä¸å页ï¼è¿åå ¨é¨å·¥åå表 ### 6.2 æ°éåæ®µç²¾åº¦ - æææ°éåæ®µä¸º `BigDecimal` ç±»åï¼å端å±ç¤ºæ¶ä¿ç2ä½å°æ° - 宿è¿åº¦ `completionStatus` 已为ç¾åæ¯æ°å¼ï¼å¦50.00表示50%ï¼ ### 6.3 æ¶é´åæ®µæ ¼å¼ - æææ¶é´å段为 `LocalDate` æ ¼å¼ï¼`YYYY-MM-DD` - æ æ¶é´å¼æ¶è¿å `null`ï¼å端éå空å¼å¤ç ### 6.4 å·¥åç±»å夿 - æ¥å£å·²è¿å `workOrderType` åæ®µï¼æ éåç«¯å¤æ - è¿å·¥è¿ä¿®å·¥å建议使ç¨çº¢è²æ ç¾çªåºæ¾ç¤º ### 6.5 æ¥å·¥äººååæ®µ - `userNames` 为éå·åéå符串ï¼å¯è½ä¸ºç©º - å¤äººæ¶å»ºè®®ä½¿ç¨æ ç¾æå¤´åå表å±ç¤º --- ## ä¸ã常è§é®é¢å¤ç ### 7.1 è¿åº¦ä¸ºç©ºæé¤é¶ - `completionStatus` å·²å¨SQLä¸å¤çé¤é¶æ åµ - è¥è®¡åæ°é为0ï¼è¿åº¦æ¾ç¤ºä¸º0 ### 7.2 å·¥åå·ä¸ºç©º - `workOrderNo` ä¸ºå¿ å¡«åæ®µï¼ä¸ä¼ä¸ºç©º - è¥èåå±ç¤ºæ¶å¤ä¸ªå·¥åå·ç¨éå·åé ### 7.3 æ¥åºæ°éå±ç¤º - `scrapQty` 为累计æ¥åºæ°é - 建议使ç¨çº¢è²å使è¦å徿 æ è¯ --- ## å «ãMockæ°æ®ç¤ºä¾ ### 8.1 /page æ¥å£Mock ```json { "code": 200, "data": { "records": [ { "productionOrderId": 1, "npsNo": "SC20260611001", "endOrder": false, "productName": "çµçº¿çµç¼", "model": "RVV 3*2.5", "unit": "ç±³", "operationName": "ç»çº¿,ç»ç¼,æç¼", "productionTaskCount": 3, "planQuantity": 1000.00, "completeQuantity": 500.00, "goodQuantity": 500.00, "scrapQty": 10.00, "completionStatus": 50.00, "type": 1, "workOrderType": "æ£å¸¸", "workOrderNo": "GD20260611001,GD20260611002,GD20260611003", "planStartTime": "2026-06-10", "planEndTime": "2026-06-15", "actualStartTime": "2026-06-11", "actualEndTime": null, "status": 3 } ], "total": 1, "current": 1, "size": 10 } } ``` ### 8.2 /byOrder/{orderId} æ¥å£Mock ```json { "code": 200, "data": [ { "id": 1, "workOrderNo": "GD20260611001", "planStartTime": "2026-06-10", "planEndTime": "2026-06-12", "actualStartTime": "2026-06-11", "actualEndTime": null, "status": 3, "productionOrderId": 1, "planQuantity": 500.00, "completeQuantity": 300.00, "npsNo": "SC20260611001", "endOrder": false, "productName": "çµçº¿çµç¼", "model": "RVV 3*2.5", "unit": "ç±³", "operationName": "ç»çº¿", "type": 1, "workOrderType": "æ£å¸¸", "scrapQty": 5.00, "completionStatus": 60.00, "userNames": "å¼ ä¸,æå" }, { "id": 2, "workOrderNo": "FG20260611001", "planStartTime": "2026-06-12", "planEndTime": "2026-06-15", "actualStartTime": "2026-06-13", "actualEndTime": null, "status": 3, "productionOrderId": 1, "planQuantity": 100.00, "completeQuantity": 50.00, "npsNo": "SC20260611001", "endOrder": false, "productName": "çµçº¿çµç¼", "model": "RVV 3*2.5", "unit": "ç±³", "operationName": "ç»ç¼", "type": 0, "workOrderType": "è¿å·¥è¿ä¿®", "scrapQty": 2.00, "completionStatus": 50.00, "userNames": "çäº" } ] } ``` src/main/java/com/ruoyi/production/bean/dto/ProductionOperationTaskDto.java
@@ -47,4 +47,16 @@ @Schema(description = "æ¯å¦ç产") private Integer isProduction; @Schema(description = "è¯åæ°é") private BigDecimal goodQuantity; @Schema(description = "å·¥å任塿°é") private Long productionTaskCount; @Schema(description = "å·¥åç±»åï¼æ£å¸¸/è¿å·¥è¿ä¿®ï¼") private String workOrderType; @Schema(description = "æ¥å·¥äººååç§°") private String userNames; } src/main/java/com/ruoyi/production/controller/ProductionOperationTaskController.java
@@ -1,5 +1,6 @@ package com.ruoyi.production.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.bean.dto.ProductionOperationTaskDto; @@ -23,11 +24,17 @@ private final ProductionOperationTaskService productionOperationTaskService; @GetMapping("/page") @Operation(summary = "å页æ¥è¯¢") public R page(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) { @Operation(summary = "å·¥åå页æ¥è¯¢", description = "æç产订å维度åç»å±ç¤ºï¼è¿å订å级å«çæ±æ»æ°æ®") public R<IPage<ProductionOperationTaskVo>> page(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) { return R.ok(productionOperationTaskService.pageProductionOperationTask(page, dto)); } @GetMapping("/byOrder/{orderId}") @Operation(summary = "æ ¹æ®è®¢åIDæ¥è¯¢å·¥åå表", description = "æ¥è¯¢æå®ç产订åä¸çææå·¥åæç»") public R<List<ProductionOperationTaskVo>> byOrder(@PathVariable Long orderId) { return R.ok(productionOperationTaskService.listByOrderId(orderId)); } @GetMapping("/list") @Operation(summary = "å·¥åå表") public R<List<ProductionOperationTaskVo>> list(ProductionOperationTaskDto dto) { src/main/java/com/ruoyi/production/mapper/ProductionOperationTaskMapper.java
@@ -26,9 +26,17 @@ @Mapper public interface ProductionOperationTaskMapper extends BaseMapper<ProductionOperationTask> { /** * å·¥åå页æ¥è¯¢ï¼æç产订å维度åç»ï¼ */ IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskVo> page, @Param("c") ProductionOperationTaskDto dto); /** * æ ¹æ®ç产订åIDæ¥è¯¢å·¥åå表 */ List<ProductionOperationTaskVo> listByOrderId(@Param("orderId") Long orderId); List<ProductionTaskStatisticsDto> selectTaskStatisticsByDate(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); src/main/java/com/ruoyi/production/service/ProductionOperationTaskService.java
@@ -12,9 +12,17 @@ public interface ProductionOperationTaskService extends IService<ProductionOperationTask> { /** * å·¥åå页æ¥è¯¢ï¼æç产订å维度åç»ï¼ */ IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto productionOperationTaskDto); /** * æ ¹æ®ç产订åIDæ¥è¯¢å·¥åå表ï¼å·¥åæç»ï¼ */ List<ProductionOperationTaskVo> listByOrderId(Long orderId); List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto productionOperationTaskDto); ProductionOperationTaskVo getProductionOperationTaskInfo(Long id); src/main/java/com/ruoyi/production/service/impl/ProductionOperationTaskServiceImpl.java
@@ -61,7 +61,7 @@ @Override public IPage<ProductionOperationTaskVo> pageProductionOperationTask(Page<ProductionOperationTaskDto> page, ProductionOperationTaskDto dto) { // å页æ¥è¯¢ç产工åºä»»å¡ // å页æ¥è¯¢ï¼æç产订å维度åç»ï¼ Page<ProductionOperationTaskVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); IPage<ProductionOperationTaskVo> result = baseMapper.pageProductionOperationTask(voPage, dto); fillOperationTypes(result.getRecords()); @@ -70,6 +70,17 @@ } @Override public List<ProductionOperationTaskVo> listByOrderId(Long orderId) { // æ ¹æ®ç产订åIDæ¥è¯¢å·¥åå表 if (orderId == null) { return Collections.emptyList(); } List<ProductionOperationTaskVo> result = baseMapper.listByOrderId(orderId); fillUserNames(result); return result; } @Override public List<ProductionOperationTaskVo> listProductionOperationTask(ProductionOperationTaskDto dto) { // æ¥è¯¢å·¥åºä»»å¡å表 List<ProductionOperationTaskVo> result = BeanUtil.copyToList(this.list(buildQueryWrapper(dto)), ProductionOperationTaskVo.class); src/main/resources/mapper/production/ProductionOperationTaskMapper.xml
@@ -21,57 +21,92 @@ <result column="dept_id" property="deptId" /> </resultMap> <!-- æç产订ååç»çå·¥åå页æ¥è¯¢ --> <select id="pageProductionOperationTask" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo"> select pot.*, po.nps_no as npsNo, po.is_end_order as endOrder, p.product_name as productName, pm.model as model, pm.unit as unit, poro.operation_name as operationName, poro.type as type, IFNULL(scrapStat.scrapQty, 0) AS scrapQty, ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus, CASE WHEN pot.work_order_no LIKE 'FG%' THEN 'è¿å·¥è¿ä¿®' ELSE 'æ£å¸¸' END AS work_order_type from production_operation_task pot left join production_order po on pot.production_order_id = po.id left join production_order_routing_operation poro on pot.production_order_routing_operation_id = poro.id left join product_model pm on pm.id = ifnull(poro.product_model_id, po.product_model_id) left join product p on pm.product_id = p.id left join ( select ppm.production_operation_task_id as taskId, sum(ifnull(ppo.scrap_qty, 0)) as scrapQty from production_product_main ppm left join production_product_output ppo on ppo.production_product_main_id = ppm.id group by ppm.production_operation_task_id ) scrapStat on scrapStat.taskId = pot.id SELECT po.id AS productionOrderId, po.nps_no AS npsNo, po.is_end_order AS endOrder, p.product_name AS productName, pm.model AS model, pm.unit AS unit, GROUP_CONCAT(DISTINCT poro.operation_name ORDER BY poro.drag_sort, poro.operation_name SEPARATOR ',') AS operationName, COUNT(DISTINCT pot.id) AS productionTaskCount, po.quantity AS planQuantity, po.complete_quantity AS completeQuantity, po.complete_quantity AS goodQuantity, SUM(IFNULL(scrapStat.scrapQty, 0)) AS scrapQty, ROUND(IFNULL(po.complete_quantity, 0) / NULLIF(po.quantity, 0) * 100, 2) AS completionStatus, MAX(poro.type) AS type, CASE WHEN SUM(CASE WHEN pot.work_order_no LIKE 'FG%' THEN 1 ELSE 0 END) > 0 THEN 'è¿å·¥è¿ä¿®' ELSE 'æ£å¸¸' END AS workOrderType, GROUP_CONCAT(DISTINCT pot.work_order_no ORDER BY pot.work_order_no SEPARATOR ',') AS workOrderNo, MIN(pot.plan_start_time) AS planStartTime, MAX(pot.plan_end_time) AS planEndTime, MIN(pot.actual_start_time) AS actualStartTime, MAX(pot.actual_end_time) AS actualEndTime, MAX(pot.status) AS status FROM production_operation_task pot LEFT JOIN production_order po ON pot.production_order_id = po.id LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id LEFT JOIN product_model pm ON pm.id = po.product_model_id LEFT JOIN product p ON pm.product_id = p.id LEFT JOIN ( SELECT ppm.production_operation_task_id AS taskId, SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty FROM production_product_main ppm LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id GROUP BY ppm.production_operation_task_id ) scrapStat ON scrapStat.taskId = pot.id <where> <if test="c != null and c.id != null"> and pot.id = #{c.id} </if> <if test="c != null and c.npsNo != null"> and po.nps_no like concat('%', #{c.npsNo}, '%') <if test="c != null and c.npsNo != null and c.npsNo != ''"> AND po.nps_no LIKE CONCAT('%', #{c.npsNo}, '%') </if> <if test="c != null and c.productionOrderId != null"> and pot.production_order_id = #{c.productionOrderId} </if> <if test="c != null and c.productionOrderRoutingOperationId != null"> and pot.production_order_routing_operation_id = #{c.productionOrderRoutingOperationId} </if> <if test="c != null and c.status != null"> and pot.status = #{c.status} </if> <if test="c != null and c.isProduction != null"> and poro.is_production = #{c.isProduction} </if> <if test="c != null and c.workOrderNo != null and c.workOrderNo != ''"> and pot.work_order_no like concat('%', #{c.workOrderNo}, '%') AND pot.production_order_id = #{c.productionOrderId} </if> </where> order by pot.id desc GROUP BY po.id ORDER BY po.id DESC </select> <!-- æ ¹æ®è®¢åIDæ¥è¯¢å·¥åå表 --> <select id="listByOrderId" resultType="com.ruoyi.production.bean.vo.ProductionOperationTaskVo"> SELECT pot.id, pot.work_order_no AS workOrderNo, pot.plan_start_time AS planStartTime, pot.plan_end_time AS planEndTime, pot.actual_start_time AS actualStartTime, pot.actual_end_time AS actualEndTime, pot.status, pot.production_order_id AS productionOrderId, pot.plan_quantity AS planQuantity, pot.complete_quantity AS completeQuantity, po.nps_no AS npsNo, po.is_end_order AS endOrder, p.product_name AS productName, pm.model AS model, pm.unit AS unit, poro.operation_name AS operationName, poro.type AS type, CASE WHEN pot.work_order_no LIKE 'FG%' THEN 'è¿å·¥è¿ä¿®' ELSE 'æ£å¸¸' END AS workOrderType, IFNULL(scrapStat.scrapQty, 0) AS scrapQty, ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus FROM production_operation_task pot LEFT JOIN production_order po ON pot.production_order_id = po.id LEFT JOIN production_order_routing_operation poro ON pot.production_order_routing_operation_id = poro.id LEFT JOIN product_model pm ON pm.id = IFNULL(poro.product_model_id, po.product_model_id) LEFT JOIN product p ON pm.product_id = p.id LEFT JOIN ( SELECT ppm.production_operation_task_id AS taskId, SUM(IFNULL(ppo.scrap_qty, 0)) AS scrapQty FROM production_product_main ppm LEFT JOIN production_product_output ppo ON ppo.production_product_main_id = ppm.id GROUP BY ppm.production_operation_task_id ) scrapStat ON scrapStat.taskId = pot.id WHERE pot.production_order_id = #{orderId} ORDER BY pot.id DESC </select> <select id="selectTaskStatisticsByDate" resultType="com.ruoyi.home.dto.ProductionTaskStatisticsDto">