From 3ce57820e618b704ce61487b7cdb38fdd6b0f44a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 22 九月 2026 14:06:10 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_银川_九鸿化工' into dev_银川_九鸿化工

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java                     |    4 
 yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java                           |  411 +++++++---------------
 docs/project-business/mermaid/05-quality-flow.mmd                                                                                  |   11 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java                                            |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java                       |   12 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcOqcCheckResultEnum.java                                   |   51 ++
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java |    2 
 docs/project-business/data/modules.json                                                                                            |    2 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java                                 |   28 -
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java           |    6 
 docs/sql/config_export_all_20260904.sql                                                                                            |    9 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java                     |   21 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java                       |   30 -
 docs/project-business/index.html                                                                                                   |   32 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java                   |   45 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java                                  |    2 
 docs/qc_chemical_report_integration.md                                                                                             |    6 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java                            |   31 +
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java                          |    2 
 yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml                                         |    6 
 docs/project-business/data/flows.json                                                                                              |    6 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java                                           |    1 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java                     |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcReportServiceImpl.java                  |   15 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java                                    |    7 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java                               |  145 -------
 yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilderTest.java       |    7 
 yudao-module-mes/src/test/resources/sql/create_tables.sql                                                                          |   10 
 docs/project-business/data/business.json                                                                                           |    2 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/ai/MesProAiServiceImpl.java                                 |   37 -
 docs/project-business/mermaid/11-ai-business-flow.mmd                                                                              |    2 
 docs/project-business/data/objects.json                                                                                            |    8 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcQcReportRespVO.java         |    5 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java                         |    2 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java                       |   14 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilder.java           |   14 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java    |    3 
 .playwright-mcp/产品检验单-1.docx                                                                                                       |    0 
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java         |    6 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java                        |   31 -
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ai/MesQcAiServiceImpl.java                                   |    3 
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java                                   |    4 
 42 files changed, 393 insertions(+), 646 deletions(-)

diff --git "a/.playwright-mcp/\344\272\247\345\223\201\346\243\200\351\252\214\345\215\225-1.docx" "b/.playwright-mcp/\344\272\247\345\223\201\346\243\200\351\252\214\345\215\225-1.docx"
new file mode 100644
index 0000000..e6e47f5
--- /dev/null
+++ "b/.playwright-mcp/\344\272\247\345\223\201\346\243\200\351\252\214\345\215\225-1.docx"
Binary files differ
diff --git a/docs/project-business/data/business.json b/docs/project-business/data/business.json
index 7aec6dc..8546e4f 100644
--- a/docs/project-business/data/business.json
+++ b/docs/project-business/data/business.json
@@ -110,7 +110,7 @@
     },
     {
       "name": "鐢熶骇椋庨櫓棰勬祴",
-      "flow": "IPQC 缂洪櫡鐜�+璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�<20%+鍏抽敭宸ュ簭 鈫� chat 鈫� 缁煎悎椋庨櫓+鍥犵礌",
+      "flow": "璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�<20%+鍏抽敭宸ュ簭 鈫� chat 鈫� 缁煎悎椋庨櫓+鍥犵礌",
       "callsApis": [
         "MdmItemApi"
       ]
diff --git a/docs/project-business/data/flows.json b/docs/project-business/data/flows.json
index aef97e3..55797d2 100644
--- a/docs/project-business/data/flows.json
+++ b/docs/project-business/data/flows.json
@@ -29,13 +29,13 @@
        {"stage": "鑱斿姩", "action": "瀹℃壒閫氳繃鎸夊伐搴忔爣璁�: 鍊掑啿鈫掕嚜鍔ㄧ墿鏂欐秷鑰楁墸绾胯竟搴�(鍏佽璐熷簱瀛�)锛涜川妫�鈫掍骇鍑哄緟妫�琛岀瓑 IPQC锛涘叧閿潪妫�鈫掔洿鎺ヤ骇鍑哄叆搴�", "roles": ["绯荤粺鑷姩"]},
        {"stage": "瀹屽伐", "action": "浠呮湯閬撳伐搴忓洖鍐欏伐鍗曞凡鐢熶骇鏁伴噺锛岃揪鏍囪嚜鍔ㄥ畬鎴愶紱MPS 绱鍒ゆ柇瀹屾垚骞跺彂浜嬩欢缁欓攢鍞鍗�", "roles": ["绯荤粺鑷姩"]}]},
     {"id": "quality", "name": "璐ㄩ噺娴佺▼", "mermaid": "mermaid/05-quality-flow.mmd", "color": "#e06c6c",
-     "summary": "鍥涢亾妫�楠岄椄鍙�(IQC/IPQC/OQC/RQC锛屼簩鎬� 0鈫�4) + 鍒ゅ畾鍥涙灉(鍚堟牸/鐗归噰/閫�璐�/鎶ュ簾) + NCR 璇勫澶勭疆鍏抽棴锛汚I 鎻愪緵鍒ゅ畾寤鸿锛汵CR 褰撳墠浠呭彴璐︿笉瑙﹀彂杩斿伐鍗曘�傛敮鎸佸寲宸ユ姤鍛婅寖寮忥細鍒嗙粍鎸囨爣鏍�+鍏紡鏂囨湰+骞宠娴嬮噺鎵规+閲囨牱琛ㄥご+绛惧瓧鍖猴紝娴忚鍣ㄦ墦鍗版楠屾姤鍛婏紱骞跺彲瀵煎嚭浜у搧妫�楠屽崟 Word锛堢焊璐ㄦ楠屽崟鐗堝紡锛屽垽瀹氱粨璁�/璐ㄦ绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉紝Word 鎵撳嵃锛夈��",
+     "summary": "鍥涢亾妫�楠岄椄鍙�(IQC/IPQC/OQC/RQC锛屼簩鎬� 0鈫�4) + 鍒ゅ畾鍥涙灉(鍚堟牸/鐗归噰/閫�璐�/鎶ュ簾锛汷QC 鏀规寜浜у搧绛夌骇 1鍨�/2鍨�/搴熷搧锛屼粎搴熷搧鍒や笉鍚堟牸) + NCR 璇勫澶勭疆鍏抽棴锛汚I 鎻愪緵鍒ゅ畾寤鸿锛汵CR 褰撳墠浠呭彴璐︿笉瑙﹀彂杩斿伐鍗曘�傛敮鎸佸寲宸ユ姤鍛婅寖寮忥細鍒嗙粍鎸囨爣鏍�+鍏紡鏂囨湰+骞宠娴嬮噺鎵规+閲囨牱琛ㄥご+绛惧瓧鍖猴紝娴忚鍣ㄦ墦鍗版楠屾姤鍛婏紱骞跺彲瀵煎嚭浜у搧妫�楠屽崟 Word锛堢焊璐ㄦ楠屽崟鐗堝紡锛屽垽瀹氱粨璁�/璐ㄦ绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉紝Word 鎵撳嵃锛夈��",
      "steps": [
        {"stage": "鏉ユ枡", "action": "鍒拌揣閫氱煡/澶栧崗鍏ュ簱鈫扞QC锛岀粨璁哄洖鍐欐帹杩涘緟鍏ュ簱鎴栬Е鍙戦��璐�", "roles": ["IQC 璐ㄦ鍛�"]},
        {"stage": "杩囩▼", "action": "鎶ュ伐璐ㄦ宸ュ簭浜у嚭琛屸啋IPQC锛屽悎鏍兼媶琛屽叆搴撱�佷笉鍚堟牸鐢熸垚 NCR", "roles": ["IPQC 璐ㄦ鍛�"]},
-       {"stage": "鍑鸿揣", "action": "閿�鍞嚭搴撴彁浜も啋OQC锛屽畬鎴愬悗鍑哄簱鍗曡繘鍏ュ緟鎷h揣", "roles": ["OQC 璐ㄦ鍛�"]},
+       {"stage": "鍑鸿揣", "action": "閿�鍞嚭搴撴彁浜も啋OQC(妫�娴嬬粨鏋滄寜浜у搧绛夌骇 1鍨�/2鍨�/搴熷搧蹇呭~锛�1鍨�/2鍨嬪垽琛屽悎鏍硷紝搴熷搧鍒よ涓嶅悎鏍�)锛屽叏閮ㄥ悎鏍煎悗鍑哄簱鍗曡繘鍏ュ緟鎷h揣锛屽嚭鐜板簾鍝佸垯鏁村崟鍙栨秷", "roles": ["OQC 璐ㄦ鍛�"]},
        {"stage": "閫�璐�", "action": "閫�鏂�/閿�鍞��璐�/鍞悗閫�璐р啋RQC锛岀粨璁哄洖璋冨崟鎹笌鍞悗", "roles": ["RQC 璐ㄦ鍛�"]},
-       {"stage": "鎶ュ憡", "action": "妫�楠岀粨鏋滄寜鍒嗙粍鏍�+娴嬮噺鎵规褰曞叆锛�/indicator-result/report 鑱氬悎鍚庡墠绔墦鍗版楠屾姤鍛�(鍚噰鏍峰湴鐐�/璇佷功缂栧彿/鎵ц鏍囧噯/澶嶆牳路瀹℃牳绛惧瓧鍖�)锛�/indicator-result/export-product-word 瀵煎嚭浜у搧妫�楠屽崟Word(鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹/璐ㄦ涓撶敤绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉峰钩琛屾祴閲忛】鍙峰悎骞堵蜂笅杞藉悗Word鎵撳嵃锛涜川妫�鍗曡鎯呮娴嬬粨鏋淭ab鍙寜鏍峰搧鏌ョ湅鍙妫�娴嬪�兼槑缁�)", "roles": ["璐ㄦ鍛�", "澶嶆牳浜�", "瀹℃牳浜�"]},
+       {"stage": "鎶ュ憡", "action": "妫�楠岀粨鏋滄寜鍒嗙粍鏍�+娴嬮噺鎵规褰曞叆锛�/indicator-result/report 鑱氬悎鍚庡墠绔墦鍗版楠屾姤鍛�(鍚噰鏍峰湴鐐�/璇佷功缂栧彿/鎵ц鏍囧噯/鍒ゅ畾缁撹路璐ㄦ涓撶敤绔�/澶嶆牳路瀹℃牳绛惧瓧鍖猴紱鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋溌疯川妫�绔犵暀绌虹洊绔犅锋棤骞宠娴嬮噺鏃跺垪澶寸О娴嬮噺鍊�)锛�/indicator-result/export-product-word 瀵煎嚭浜у搧妫�楠屽崟Word(鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋溌疯川妫�绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉峰钩琛屾祴閲忛】鍙峰悎骞堵蜂笅杞藉悗Word鎵撳嵃锛涜川妫�鍗曡鎯呮娴嬬粨鏋淭ab鍙寜鏍峰搧鏌ョ湅鍙妫�娴嬪�兼槑缁�)", "roles": ["璐ㄦ鍛�", "澶嶆牳浜�", "瀹℃牳浜�"]},
        {"stage": "涓嶅悎鏍�", "action": "NCR: 寰呰瘎瀹♀啋璇勫鈫掑缃�(閫�璐�/鎶ュ簾/杩斿伐/璁╂鎺ユ敹/闄嶇骇)鈫掑叧闂�", "roles": ["璐ㄩ噺宸ョ▼甯�"]}]},
     {"id": "warehouse", "name": "浠撳偍娴佺▼", "mermaid": "mermaid/06-warehouse-flow.mmd", "color": "#7e6bd6",
      "summary": "15 绫诲崟鎹┍鍔ㄥ簱瀛樺彴璐�(鍏厓缁勩�佸洓閲�)鍙樺姩锛屽叏閮ㄧ粡浜嬪姟娴佹按鐣欑棔锛涙敮鎸佽皟鎷ㄥ湪閫斻�佺洏鐐硅皟鏁淬�佹壒娆�/SN 杩芥函銆佸簱瀛樺崰鐢ㄤ笌鍥涚骇鍐荤粨銆佺嚎杈硅櫄鎷熷簱璐熷簱瀛橈紱瀵瑰 WmsStockApi 渚� ERP 鏀跺彂銆�",
diff --git a/docs/project-business/data/modules.json b/docs/project-business/data/modules.json
index 09137e1..dd2e10b 100644
--- a/docs/project-business/data/modules.json
+++ b/docs/project-business/data/modules.json
@@ -51,7 +51,7 @@
     {"key": "qc", "name": "璐ㄩ噺绠$悊", "color": "#e06c6c", "tag": "MES-QC", "flow": "quality",
      "positioning": "鍥涢亾妫�楠岄椄鍙� + 涓嶅悎鏍煎搧闂幆澶勭疆",
      "problem": "鏉ユ枡/杩囩▼/鍑鸿揣/閫�璐ф楠屾爣鍑嗗寲锛屼笉鍚堟牸鍙拷婧缃�",
-     "features": ["IQC 鏉ユ枡(鍒拌揣/澶栧崗)", "IPQC 杩囩▼(鑱斿姩鎶ュ伐)", "OQC 鍑鸿揣(鑱斿姩閿�鍞嚭搴�)", "RQC 閫�璐�(鑱斿姩閫�鏂�/鍞悗)", "璐ㄦ鏂规路鎸囨爣路缂洪櫡搴�", "妫�娴嬬粨鏋�:鍚堟牸/鐗归噰/閫�璐�/鎶ュ簾", "NCR:璇勫鈫掑缃�(閫�璐�/鎶ュ簾/杩斿伐/璁╂/闄嶇骇)鈫掑叧闂�", "AI 鍒ゅ畾寤鸿"],
+     "features": ["IQC 鏉ユ枡(鍒拌揣/澶栧崗)", "IPQC 杩囩▼(鑱斿姩鎶ュ伐)", "OQC 鍑鸿揣(鑱斿姩閿�鍞嚭搴�)", "RQC 閫�璐�(鑱斿姩閫�鏂�/鍞悗)", "璐ㄦ鏂规路鎸囨爣路缂洪櫡搴�", "妫�娴嬬粨鏋�:IQC/IPQC/RQC 鍚堟牸路鐗归噰路閫�璐锋姤搴� / OQC 1鍨嬄�2鍨嬄峰簾鍝�", "NCR:璇勫鈫掑缃�(閫�璐�/鎶ュ簾/杩斿伐/璁╂/闄嶇骇)鈫掑叧闂�", "AI 鍒ゅ畾寤鸿"],
      "objects": ["IQC", "IPQC", "OQC", "RQC", "璐ㄦ鏂规", "NCR", "缂洪櫡璁板綍"],
      "roles": ["璐ㄦ鍛�(IQC/IPQC/OQC)", "璐ㄩ噺宸ョ▼甯�"],
      "upstream": ["浠撳偍(鍒拌揣)", "鐢熶骇(鎶ュ伐)", "閿�鍞�(鍑哄簱)", "鍞悗(閫�璐�)"], "downstream": ["浠撳偍(鍚堟牸鍏ュ簱/鎶ュ簾鍑哄簱)", "鐢熶骇(NCR杩斿伐)"],
diff --git a/docs/project-business/data/objects.json b/docs/project-business/data/objects.json
index adaa873..8cc8a93 100644
--- a/docs/project-business/data/objects.json
+++ b/docs/project-business/data/objects.json
@@ -7,7 +7,7 @@
     {"name": "鑱旂郴浜�", "module": "閿�鍞鐞�", "table": "crm_contact", "doc": "瀹㈡埛涓嬭仈绯讳汉锛屼笌鍟嗘満澶氬澶�", "upstream": ["瀹㈡埛"], "downstream": ["鍟嗘満"], "keywords": "鑱旂郴浜� contact"},
     {"name": "鍟嗘満", "module": "閿�鍞鐞�", "table": "crm_business", "doc": "閿�鍞満浼氾紝DB 閰嶇疆寮忛樁娈垫帹杩涳紝缁撴潫鎬�: 璧�/杈�/鏃犳晥", "upstream": ["瀹㈡埛"], "downstream": ["鎶ヤ环鍗�", "鍚堝悓"], "keywords": "鍟嗘満 business 璧㈠崟 杈撳崟 闃舵"},
     {"name": "鎶ヤ环鍗�", "module": "閿�鍞鐞�", "table": "crm_sale_quotation", "doc": "QT缂栧彿锛岄�� MDM 鐗╂枡鎶ヤ环锛孉I OCR 褰曞叆锛岃崏绋库啋宸茶浆鍚堝悓", "upstream": ["鍟嗘満"], "downstream": ["鍚堝悓"], "keywords": "鎶ヤ环 quotation QT"},
-    {"name": "鍚堝悓", "module": "閿�鍞鐞�", "table": "crm_contract", "doc": "HT缂栧彿锛孊PM 瀹℃壒(0鑽夌/10瀹℃壒涓�/20閫氳繃/30椹冲洖/40鍙栨秷/50浣滃簾)锛岄�氳繃鍚庡彲鐢熸垚閿�鍞鍗�", "upstream": ["鎶ヤ环鍗�"], "downstream": ["閿�鍞鍗�", "鍥炴璁″垝", "寮�绁�"], "keywords": "鍚堝悓 contract 瀹℃壒"},
+    {"name": "鍚堝悓", "module": "閿�鍞鐞�", "table": "crm_contract", "doc": "HT缂栧彿(鏂板/缂栬緫鍧囧彲鑷畾涔夛紝鐣欑┖鍒欐柊澧炶嚜鍔ㄧ敓鎴愩�佺紪杈戜繚鎸佸師缂栧彿)锛孊PM 瀹℃壒(0鑽夌/10瀹℃壒涓�/20閫氳繃/30椹冲洖/40鍙栨秷/50浣滃簾)锛岄�氳繃鍚庡彲鐢熸垚閿�鍞鍗�", "upstream": ["鎶ヤ环鍗�"], "downstream": ["閿�鍞鍗�", "鍥炴璁″垝", "寮�绁�"], "keywords": "鍚堝悓 contract 瀹℃壒"},
     {"name": "鍙戠エ", "module": "閿�鍞鐞�", "table": "crm_invoice", "doc": "KP缂栧彿锛孊PM 瀹℃壒锛岀疮璁″紑绁ㄢ墹鍚堝悓棰濓紝闄勪欢蹇呬紶", "upstream": ["鍚堝悓"], "downstream": ["鍥炴"], "keywords": "寮�绁� 鍙戠エ invoice"},
     {"name": "鍥炴", "module": "閿�鍞鐞�", "table": "crm_receivable", "doc": "HK缂栧彿锛屽垱寤哄嵆瀹℃壒涓�(鎵嬪姩瀹℃牳)锛屽己鍒跺厛寮�绁紝閲戦鍙屾牎楠�", "upstream": ["鍚堝悓", "鍙戠エ"], "downstream": ["鏀舵鍗�(鍏宠仈)"], "keywords": "鍥炴 鏀舵璁″垝 receivable"},
     {"name": "閿�鍞洰鏍�", "module": "閿�鍞鐞�", "table": "crm_sales_target", "doc": "骞�/瀛�/鏈埫椾釜浜�/閮ㄩ棬/浜у搧缁村害鐨勫悎鍚屽洖娆剧瓑鐩爣", "upstream": [], "downstream": ["涓氱哗缁熻"], "keywords": "鐩爣 target 涓氱哗"},
@@ -28,7 +28,7 @@
     {"name": "鍒拌揣閫氱煡鍗�", "module": "浠撳偍", "table": "mes_wm_arrival_notice", "doc": "閲囪喘璁㈠崟纭鏀惰揣鐢熸垚锛岃崏绋�0鈫掑緟璐ㄦ2鈫掑緟鍏ュ簱3鈫掑畬鎴�4", "upstream": ["閲囪喘璁㈠崟"], "downstream": ["IQC", "閲囪喘鍏ュ簱"], "keywords": "鍒拌揣 鏀惰揣 arrival"},
     {"name": "閲囪喘鍏ュ簱鍗�", "module": "浠撳偍", "table": "mes_wm_item_receipt", "doc": "鑽夌0鈫掑緟涓婃灦2鈫掑緟鎵ц3鈫掑畬鎴�4锛屽畬鎴愬悗搴撳瓨+骞跺洖鍐� ERP inCount/inStatus", "upstream": ["鍒拌揣閫氱煡"], "downstream": ["搴撳瓨鍙拌处", "閲囪喘璁㈠崟(鍥炲啓)"], "keywords": "閲囪喘鍏ュ簱 鏀惰揣鍏ュ簱 receipt"},
     {"name": "鐢熶骇棰嗘枡鍗�", "module": "浠撳偍", "table": "mes_wm_product_issue", "doc": "鑽夌0鈫掑緟鎷h揣2鈫掑緟鎵ц3鈫掑畬鎴�4锛屽簱瀛�-", "upstream": ["鐢熶骇宸ュ崟"], "downstream": ["搴撳瓨鍙拌处"], "keywords": "棰嗘枡 issue"},
-    {"name": "閿�鍞嚭搴撳崟", "module": "浠撳偍", "table": "mes_wm_product_sales", "doc": "鍙戣揣閫氱煡瀹℃牳鍚庣敓鎴愶紝鎻愪氦鈫扥QC妫�娴嬧啋鎷h揣鈫掑彂杩�10鈫掑緟鎵ц3鈫掑畬鎴�4锛屽洖鍐欓攢鍞鍗曞嚭搴撴暟涓庣姸鎬�", "upstream": ["鍙戣揣閫氱煡", "閿�鍞鍗�"], "downstream": ["搴撳瓨鍙拌处", "OQC"], "keywords": "閿�鍞嚭搴� 鍙戣揣 鍑哄簱鍗� sales"},
+    {"name": "閿�鍞嚭搴撳崟", "module": "浠撳偍", "table": "mes_wm_product_sales", "doc": "鍙戣揣閫氱煡瀹℃牳鍚庣敓鎴愶紝鎻愪氦鈫扥QC妫�娴嬧啋鎷h揣鈫掑彂杩�10鈫掑緟鎵ц3鈫掑畬鎴�4锛屽洖鍐欓攢鍞鍗曞嚭搴撴暟涓庣姸鎬侊紱浠讳竴 OQC 琛屽垽搴熷搧鍒欐暣鍗曞彇娑�", "upstream": ["鍙戣揣閫氱煡", "閿�鍞鍗�"], "downstream": ["搴撳瓨鍙拌处", "OQC"], "keywords": "閿�鍞嚭搴� 鍙戣揣 鍑哄簱鍗� sales"},
     {"name": "閿�鍞��璐у崟", "module": "浠撳偍", "table": "mes_wm_return_sales", "doc": "鑽夌鈫掑緟妫�楠�(RQC)鈫掑緟涓婃灦鈫掑緟鍏ュ簱鈫掑畬鎴愶紝鍞悗涓庢墜宸ヤ袱鏉ユ簮", "upstream": ["鍞悗閫�璐х敵璇�"], "downstream": ["搴撳瓨鍙拌处", "RQC"], "keywords": "閿�鍞��璐� 閫�璐у叆搴�"},
     {"name": "渚涘簲鍟嗛��璐у崟", "module": "浠撳偍", "table": "mes_wm_return_vendor", "doc": "IQC 涓嶅悎鏍奸��璐у彂璧凤紝寰呮嫞璐р啋寰呮墽琛屸啋瀹屾垚锛屽簱瀛�-", "upstream": ["IQC"], "downstream": ["搴撳瓨鍙拌处", "閲囪喘璁㈠崟(returnCount)"], "keywords": "渚涘簲鍟嗛��璐� 閫�鏂� 閫�璐� vendor"},
     {"name": "璋冩嫧鍗�", "module": "浠撳偍", "table": "mes_wm_transfer", "doc": "鍐呴儴/澶栭儴璋冩嫧锛屾垚瀵� MOVE_OUT+MOVE_IN 浜嬪姟锛屽湪閫旀暟閲�", "upstream": [], "downstream": ["搴撳瓨鍙拌处"], "keywords": "璋冩嫧 绉诲簱 transfer"},
@@ -36,8 +36,8 @@
     {"name": "搴撳瓨鍙拌处", "module": "浠撳偍", "table": "mes_wm_material_stock", "doc": "鐗╂枡脳浠撳簱脳搴撳尯脳搴撲綅脳鎵规脳渚涘簲鍟嗗叚鍏冪粍锛屾暟閲�/鍐荤粨/鍗犵敤/鍦ㄩ�斿洓閲�", "upstream": ["鍏ㄩ儴鍏ュ簱鍗�"], "downstream": ["鍏ㄩ儴鍑哄簱鍗�", "浜嬪姟娴佹按"], "keywords": "搴撳瓨 鍙拌处 stock 鍙敤閲�"},
     {"name": "鎵规", "module": "浠撳偍", "table": "mes_wm_batch", "doc": "鍏宠仈鐗╂枡/宸ュ崟/渚涘簲鍟�/瀹㈡埛/璐ㄩ噺鐘舵�侊紱SN 鐮佸惈鎵规 uuid锛涙潯鐮佹敮鎸�18绉嶄笟鍔″璞�", "upstream": ["鍏ュ簱鍗曟嵁"], "downstream": ["搴撳瓨鍙拌处"], "keywords": "鎵规 batch SN 鏉$爜 杩芥函"},
     {"name": "IQC鏉ユ枡妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_iqc", "doc": "鍒拌揣閫氱煡/澶栧崗鍏ュ簱瑙﹀彂锛岃崏绋�0鈫掑畬鎴�4锛岀粨璁哄洖鍐欐潵婧愬崟鎹�", "upstream": ["鍒拌揣閫氱煡", "澶栧崗鍏ュ簱"], "downstream": ["閲囪喘鍏ュ簱", "渚涘簲鍟嗛��璐�", "NCR"], "keywords": "IQC 鏉ユ枡妫�楠�"},
-    {"name": "IPQC杩囩▼妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_ipqc", "doc": "鎶ュ伐璐ㄦ宸ュ簭浜у嚭琛岃Е鍙戯紝瀹屾垚鍥炶皟鎺ㄨ繘鎶ュ伐涓庝骇鍑哄叆搴�", "upstream": ["鎶ュ伐"], "downstream": ["浜у嚭鍏ュ簱", "NCR"], "keywords": "IPQC 杩囩▼妫�楠� 宸℃"},
-    {"name": "OQC鍑鸿揣妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_oqc", "doc": "閿�鍞嚭搴撴彁浜よЕ鍙戯紝瀹屾垚鎺ㄨ繘鍑哄簱鍗曞緟鎷h揣", "upstream": ["閿�鍞嚭搴撳崟"], "downstream": ["閿�鍞嚭搴撳崟(鎺ㄨ繘)"], "keywords": "OQC 鍑鸿揣妫�楠� 鍑哄巶妫�楠�"},
+    {"name": "IPQC杩囩▼妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_ipqc", "doc": "鎶ュ伐璐ㄦ宸ュ簭浜у嚭琛岃Е鍙戯紝瀹屾垚鍥炶皟鎺ㄨ繘鎶ュ伐涓庝骇鍑哄叆搴擄紱琛ㄥご=鏉ユ簮鍗曟嵁(鍙)+浜у搧鐗╂枡(MDM,蹇呭~)+鎵瑰彿(蹇呭~)+鏁伴噺+妫�楠屼俊鎭紝宸插幓鎺夌敓浜ц鍗�/宸ヤ綅/鐢熶骇浠诲姟/宸ュ簭", "upstream": ["鎶ュ伐"], "downstream": ["浜у嚭鍏ュ簱", "NCR"], "keywords": "IPQC 杩囩▼妫�楠� 宸℃ 鎵瑰彿"},
+    {"name": "OQC鍑鸿揣妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_oqc", "doc": "閿�鍞嚭搴撴彁浜よЕ鍙戯紝鑽夌0鈫掑畬鎴�4锛涙娴嬬粨鏋滄寜浜у搧绛夌骇鍒ゅ畾(1鍨�/2鍨�/搴熷搧锛屽繀濉�)锛�1鍨�/2鍨嬪垽琛屽悎鏍煎苟鎺ㄨ繘鍑哄簱鍗曞緟鎷h揣锛屽簾鍝佸垽琛屼笉鍚堟牸骞跺彇娑堥攢鍞嚭搴撳崟锛涘彂璐ф暟閲�/鍑鸿揣鏃ユ湡鍙┖", "upstream": ["閿�鍞嚭搴撳崟"], "downstream": ["閿�鍞嚭搴撳崟(鎺ㄨ繘鎴栧彇娑�)"], "keywords": "OQC 鍑鸿揣妫�楠� 鍑哄巶妫�楠� 1鍨� 2鍨� 搴熷搧"},
     {"name": "RQC閫�璐ф楠�", "module": "璐ㄩ噺", "table": "mes_qc_rqc", "doc": "鐢熶骇閫�鏂�/閿�鍞��璐�/鍞悗閫�璐цЕ鍙戯紝缁撹鍥炶皟鍞悗锛涘洓绫绘楠屽崟鍧囨敮鎸侀噰鏍峰湴鐐�/璇佷功缂栧彿/鎵ц鏍囧噯琛ㄥご涓庡鏍嘎峰鏍镐汉锛屽苟鍙墦鍗版楠屾姤鍛�", "upstream": ["閫�鏂�", "閫�璐�"], "downstream": ["閫�璐у叆搴�", "鍞悗鍥炶皟", "妫�楠屾姤鍛婃墦鍗�"], "keywords": "RQC 閫�璐ф楠�"},
     {"name": "妫�楠屾寚鏍�", "module": "璐ㄩ噺", "table": "mes_qc_indicator", "doc": "鏀寔涓ょ骇鍒嗙粍鏍�(itemType褰曞叆/鍒嗙粍+parentId)銆佸叕寮忔枃鏈睍绀恒�佸崟浣嶆枃鏈�佸悓绾ф帓搴忥紱鍒嗙粍椤逛笉褰曞�硷紱鏈夊瓙椤圭鍒狅紱鍚屽眰绾у悕绉板彲閲嶅", "upstream": [], "downstream": ["璐ㄦ鏂规", "妫�楠屾姤鍛婃墦鍗�"], "keywords": "妫�楠屾寚鏍� indicator 鍒嗙粍 鍏紡 鍖栧伐"},
     {"name": "妫�楠屾姤鍛婃墦鍗�", "module": "璐ㄩ噺", "table": "mes_qc_indicator_result_detail", "doc": "鍖栧伐鎶ュ憡鑼冨紡锛氬钩琛屾祴閲忔壒娆�(measure_no)+鍒嗙粍鐭╅樀+鍏紡鍒�+绛惧瓧鍖猴紱/mes/qc/indicator-result/report 鑱氬悎锛屽墠绔祻瑙堝櫒鎵撳嵃", "upstream": ["IQC鏉ユ枡妫�楠�", "IPQC杩囩▼妫�楠�", "OQC鍑鸿揣妫�楠�", "RQC閫�璐ф楠�", "妫�楠屾寚鏍�"], "downstream": [], "keywords": "鎵撳嵃 鎶ュ憡 娴嬮噺鎵规 绛惧瓧 姝d竵閱� GB/T6027"},
diff --git a/docs/project-business/index.html b/docs/project-business/index.html
index 2cf6913..6ba4d3c 100644
--- a/docs/project-business/index.html
+++ b/docs/project-business/index.html
@@ -290,7 +290,7 @@
     },
     {
       "name": "鐢熶骇椋庨櫓棰勬祴",
-      "flow": "IPQC 缂洪櫡鐜�+璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�<20%+鍏抽敭宸ュ簭 鈫� chat 鈫� 缁煎悎椋庨櫓+鍥犵礌",
+      "flow": "璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�<20%+鍏抽敭宸ュ簭 鈫� chat 鈫� 缁煎悎椋庨櫓+鍥犵礌",
       "callsApis": [
         "MdmItemApi"
       ]
@@ -381,7 +381,7 @@
     {"key": "qc", "name": "璐ㄩ噺绠$悊", "color": "#e06c6c", "tag": "MES-QC", "flow": "quality",
      "positioning": "鍥涢亾妫�楠岄椄鍙� + 涓嶅悎鏍煎搧闂幆澶勭疆",
      "problem": "鏉ユ枡/杩囩▼/鍑鸿揣/閫�璐ф楠屾爣鍑嗗寲锛屼笉鍚堟牸鍙拷婧缃�",
-     "features": ["IQC 鏉ユ枡(鍒拌揣/澶栧崗)", "IPQC 杩囩▼(鑱斿姩鎶ュ伐)", "OQC 鍑鸿揣(鑱斿姩閿�鍞嚭搴�)", "RQC 閫�璐�(鑱斿姩閫�鏂�/鍞悗)", "璐ㄦ鏂规路鎸囨爣路缂洪櫡搴�", "妫�娴嬬粨鏋�:鍚堟牸/鐗归噰/閫�璐�/鎶ュ簾", "NCR:璇勫鈫掑缃�(閫�璐�/鎶ュ簾/杩斿伐/璁╂/闄嶇骇)鈫掑叧闂�", "AI 鍒ゅ畾寤鸿"],
+     "features": ["IQC 鏉ユ枡(鍒拌揣/澶栧崗)", "IPQC 杩囩▼(鑱斿姩鎶ュ伐)", "OQC 鍑鸿揣(鑱斿姩閿�鍞嚭搴�)", "RQC 閫�璐�(鑱斿姩閫�鏂�/鍞悗)", "璐ㄦ鏂规路鎸囨爣路缂洪櫡搴�", "妫�娴嬬粨鏋�:IQC/IPQC/RQC 鍚堟牸路鐗归噰路閫�璐锋姤搴� / OQC 1鍨嬄�2鍨嬄峰簾鍝�", "NCR:璇勫鈫掑缃�(閫�璐�/鎶ュ簾/杩斿伐/璁╂/闄嶇骇)鈫掑叧闂�", "AI 鍒ゅ畾寤鸿"],
      "objects": ["IQC", "IPQC", "OQC", "RQC", "璐ㄦ鏂规", "NCR", "缂洪櫡璁板綍"],
      "roles": ["璐ㄦ鍛�(IQC/IPQC/OQC)", "璐ㄩ噺宸ョ▼甯�"],
      "upstream": ["浠撳偍(鍒拌揣)", "鐢熶骇(鎶ュ伐)", "閿�鍞�(鍑哄簱)", "鍞悗(閫�璐�)"], "downstream": ["浠撳偍(鍚堟牸鍏ュ簱/鎶ュ簾鍑哄簱)", "鐢熶骇(NCR杩斿伐)"],
@@ -442,7 +442,7 @@
     {"name": "鑱旂郴浜�", "module": "閿�鍞鐞�", "table": "crm_contact", "doc": "瀹㈡埛涓嬭仈绯讳汉锛屼笌鍟嗘満澶氬澶�", "upstream": ["瀹㈡埛"], "downstream": ["鍟嗘満"], "keywords": "鑱旂郴浜� contact"},
     {"name": "鍟嗘満", "module": "閿�鍞鐞�", "table": "crm_business", "doc": "閿�鍞満浼氾紝DB 閰嶇疆寮忛樁娈垫帹杩涳紝缁撴潫鎬�: 璧�/杈�/鏃犳晥", "upstream": ["瀹㈡埛"], "downstream": ["鎶ヤ环鍗�", "鍚堝悓"], "keywords": "鍟嗘満 business 璧㈠崟 杈撳崟 闃舵"},
     {"name": "鎶ヤ环鍗�", "module": "閿�鍞鐞�", "table": "crm_sale_quotation", "doc": "QT缂栧彿锛岄�� MDM 鐗╂枡鎶ヤ环锛孉I OCR 褰曞叆锛岃崏绋库啋宸茶浆鍚堝悓", "upstream": ["鍟嗘満"], "downstream": ["鍚堝悓"], "keywords": "鎶ヤ环 quotation QT"},
-    {"name": "鍚堝悓", "module": "閿�鍞鐞�", "table": "crm_contract", "doc": "HT缂栧彿锛孊PM 瀹℃壒(0鑽夌/10瀹℃壒涓�/20閫氳繃/30椹冲洖/40鍙栨秷/50浣滃簾)锛岄�氳繃鍚庡彲鐢熸垚閿�鍞鍗�", "upstream": ["鎶ヤ环鍗�"], "downstream": ["閿�鍞鍗�", "鍥炴璁″垝", "寮�绁�"], "keywords": "鍚堝悓 contract 瀹℃壒"},
+    {"name": "鍚堝悓", "module": "閿�鍞鐞�", "table": "crm_contract", "doc": "HT缂栧彿(鏂板/缂栬緫鍧囧彲鑷畾涔夛紝鐣欑┖鍒欐柊澧炶嚜鍔ㄧ敓鎴愩�佺紪杈戜繚鎸佸師缂栧彿)锛孊PM 瀹℃壒(0鑽夌/10瀹℃壒涓�/20閫氳繃/30椹冲洖/40鍙栨秷/50浣滃簾)锛岄�氳繃鍚庡彲鐢熸垚閿�鍞鍗�", "upstream": ["鎶ヤ环鍗�"], "downstream": ["閿�鍞鍗�", "鍥炴璁″垝", "寮�绁�"], "keywords": "鍚堝悓 contract 瀹℃壒"},
     {"name": "鍙戠エ", "module": "閿�鍞鐞�", "table": "crm_invoice", "doc": "KP缂栧彿锛孊PM 瀹℃壒锛岀疮璁″紑绁ㄢ墹鍚堝悓棰濓紝闄勪欢蹇呬紶", "upstream": ["鍚堝悓"], "downstream": ["鍥炴"], "keywords": "寮�绁� 鍙戠エ invoice"},
     {"name": "鍥炴", "module": "閿�鍞鐞�", "table": "crm_receivable", "doc": "HK缂栧彿锛屽垱寤哄嵆瀹℃壒涓�(鎵嬪姩瀹℃牳)锛屽己鍒跺厛寮�绁紝閲戦鍙屾牎楠�", "upstream": ["鍚堝悓", "鍙戠エ"], "downstream": ["鏀舵鍗�(鍏宠仈)"], "keywords": "鍥炴 鏀舵璁″垝 receivable"},
     {"name": "閿�鍞洰鏍�", "module": "閿�鍞鐞�", "table": "crm_sales_target", "doc": "骞�/瀛�/鏈埫椾釜浜�/閮ㄩ棬/浜у搧缁村害鐨勫悎鍚屽洖娆剧瓑鐩爣", "upstream": [], "downstream": ["涓氱哗缁熻"], "keywords": "鐩爣 target 涓氱哗"},
@@ -463,7 +463,7 @@
     {"name": "鍒拌揣閫氱煡鍗�", "module": "浠撳偍", "table": "mes_wm_arrival_notice", "doc": "閲囪喘璁㈠崟纭鏀惰揣鐢熸垚锛岃崏绋�0鈫掑緟璐ㄦ2鈫掑緟鍏ュ簱3鈫掑畬鎴�4", "upstream": ["閲囪喘璁㈠崟"], "downstream": ["IQC", "閲囪喘鍏ュ簱"], "keywords": "鍒拌揣 鏀惰揣 arrival"},
     {"name": "閲囪喘鍏ュ簱鍗�", "module": "浠撳偍", "table": "mes_wm_item_receipt", "doc": "鑽夌0鈫掑緟涓婃灦2鈫掑緟鎵ц3鈫掑畬鎴�4锛屽畬鎴愬悗搴撳瓨+骞跺洖鍐� ERP inCount/inStatus", "upstream": ["鍒拌揣閫氱煡"], "downstream": ["搴撳瓨鍙拌处", "閲囪喘璁㈠崟(鍥炲啓)"], "keywords": "閲囪喘鍏ュ簱 鏀惰揣鍏ュ簱 receipt"},
     {"name": "鐢熶骇棰嗘枡鍗�", "module": "浠撳偍", "table": "mes_wm_product_issue", "doc": "鑽夌0鈫掑緟鎷h揣2鈫掑緟鎵ц3鈫掑畬鎴�4锛屽簱瀛�-", "upstream": ["鐢熶骇宸ュ崟"], "downstream": ["搴撳瓨鍙拌处"], "keywords": "棰嗘枡 issue"},
-    {"name": "閿�鍞嚭搴撳崟", "module": "浠撳偍", "table": "mes_wm_product_sales", "doc": "鍙戣揣閫氱煡瀹℃牳鍚庣敓鎴愶紝鎻愪氦鈫扥QC妫�娴嬧啋鎷h揣鈫掑彂杩�10鈫掑緟鎵ц3鈫掑畬鎴�4锛屽洖鍐欓攢鍞鍗曞嚭搴撴暟涓庣姸鎬�", "upstream": ["鍙戣揣閫氱煡", "閿�鍞鍗�"], "downstream": ["搴撳瓨鍙拌处", "OQC"], "keywords": "閿�鍞嚭搴� 鍙戣揣 鍑哄簱鍗� sales"},
+    {"name": "閿�鍞嚭搴撳崟", "module": "浠撳偍", "table": "mes_wm_product_sales", "doc": "鍙戣揣閫氱煡瀹℃牳鍚庣敓鎴愶紝鎻愪氦鈫扥QC妫�娴嬧啋鎷h揣鈫掑彂杩�10鈫掑緟鎵ц3鈫掑畬鎴�4锛屽洖鍐欓攢鍞鍗曞嚭搴撴暟涓庣姸鎬侊紱浠讳竴 OQC 琛屽垽搴熷搧鍒欐暣鍗曞彇娑�", "upstream": ["鍙戣揣閫氱煡", "閿�鍞鍗�"], "downstream": ["搴撳瓨鍙拌处", "OQC"], "keywords": "閿�鍞嚭搴� 鍙戣揣 鍑哄簱鍗� sales"},
     {"name": "閿�鍞��璐у崟", "module": "浠撳偍", "table": "mes_wm_return_sales", "doc": "鑽夌鈫掑緟妫�楠�(RQC)鈫掑緟涓婃灦鈫掑緟鍏ュ簱鈫掑畬鎴愶紝鍞悗涓庢墜宸ヤ袱鏉ユ簮", "upstream": ["鍞悗閫�璐х敵璇�"], "downstream": ["搴撳瓨鍙拌处", "RQC"], "keywords": "閿�鍞��璐� 閫�璐у叆搴�"},
     {"name": "渚涘簲鍟嗛��璐у崟", "module": "浠撳偍", "table": "mes_wm_return_vendor", "doc": "IQC 涓嶅悎鏍奸��璐у彂璧凤紝寰呮嫞璐р啋寰呮墽琛屸啋瀹屾垚锛屽簱瀛�-", "upstream": ["IQC"], "downstream": ["搴撳瓨鍙拌处", "閲囪喘璁㈠崟(returnCount)"], "keywords": "渚涘簲鍟嗛��璐� 閫�鏂� 閫�璐� vendor"},
     {"name": "璋冩嫧鍗�", "module": "浠撳偍", "table": "mes_wm_transfer", "doc": "鍐呴儴/澶栭儴璋冩嫧锛屾垚瀵� MOVE_OUT+MOVE_IN 浜嬪姟锛屽湪閫旀暟閲�", "upstream": [], "downstream": ["搴撳瓨鍙拌处"], "keywords": "璋冩嫧 绉诲簱 transfer"},
@@ -471,11 +471,11 @@
     {"name": "搴撳瓨鍙拌处", "module": "浠撳偍", "table": "mes_wm_material_stock", "doc": "鐗╂枡脳浠撳簱脳搴撳尯脳搴撲綅脳鎵规脳渚涘簲鍟嗗叚鍏冪粍锛屾暟閲�/鍐荤粨/鍗犵敤/鍦ㄩ�斿洓閲�", "upstream": ["鍏ㄩ儴鍏ュ簱鍗�"], "downstream": ["鍏ㄩ儴鍑哄簱鍗�", "浜嬪姟娴佹按"], "keywords": "搴撳瓨 鍙拌处 stock 鍙敤閲�"},
     {"name": "鎵规", "module": "浠撳偍", "table": "mes_wm_batch", "doc": "鍏宠仈鐗╂枡/宸ュ崟/渚涘簲鍟�/瀹㈡埛/璐ㄩ噺鐘舵�侊紱SN 鐮佸惈鎵规 uuid锛涙潯鐮佹敮鎸�18绉嶄笟鍔″璞�", "upstream": ["鍏ュ簱鍗曟嵁"], "downstream": ["搴撳瓨鍙拌处"], "keywords": "鎵规 batch SN 鏉$爜 杩芥函"},
     {"name": "IQC鏉ユ枡妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_iqc", "doc": "鍒拌揣閫氱煡/澶栧崗鍏ュ簱瑙﹀彂锛岃崏绋�0鈫掑畬鎴�4锛岀粨璁哄洖鍐欐潵婧愬崟鎹�", "upstream": ["鍒拌揣閫氱煡", "澶栧崗鍏ュ簱"], "downstream": ["閲囪喘鍏ュ簱", "渚涘簲鍟嗛��璐�", "NCR"], "keywords": "IQC 鏉ユ枡妫�楠�"},
-    {"name": "IPQC杩囩▼妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_ipqc", "doc": "鎶ュ伐璐ㄦ宸ュ簭浜у嚭琛岃Е鍙戯紝瀹屾垚鍥炶皟鎺ㄨ繘鎶ュ伐涓庝骇鍑哄叆搴�", "upstream": ["鎶ュ伐"], "downstream": ["浜у嚭鍏ュ簱", "NCR"], "keywords": "IPQC 杩囩▼妫�楠� 宸℃"},
-    {"name": "OQC鍑鸿揣妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_oqc", "doc": "閿�鍞嚭搴撴彁浜よЕ鍙戯紝瀹屾垚鎺ㄨ繘鍑哄簱鍗曞緟鎷h揣", "upstream": ["閿�鍞嚭搴撳崟"], "downstream": ["閿�鍞嚭搴撳崟(鎺ㄨ繘)"], "keywords": "OQC 鍑鸿揣妫�楠� 鍑哄巶妫�楠�"},
+    {"name": "IPQC杩囩▼妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_ipqc", "doc": "鎶ュ伐璐ㄦ宸ュ簭浜у嚭琛岃Е鍙戯紝瀹屾垚鍥炶皟鎺ㄨ繘鎶ュ伐涓庝骇鍑哄叆搴擄紱琛ㄥご=鏉ユ簮鍗曟嵁(鍙)+浜у搧鐗╂枡(MDM,蹇呭~)+鎵瑰彿(蹇呭~)+鏁伴噺+妫�楠屼俊鎭紝宸插幓鎺夌敓浜ц鍗�/宸ヤ綅/鐢熶骇浠诲姟/宸ュ簭", "upstream": ["鎶ュ伐"], "downstream": ["浜у嚭鍏ュ簱", "NCR"], "keywords": "IPQC 杩囩▼妫�楠� 宸℃ 鎵瑰彿"},
+    {"name": "OQC鍑鸿揣妫�楠�", "module": "璐ㄩ噺", "table": "mes_qc_oqc", "doc": "閿�鍞嚭搴撴彁浜よЕ鍙戯紝鑽夌0鈫掑畬鎴�4锛涙娴嬬粨鏋滄寜浜у搧绛夌骇鍒ゅ畾(1鍨�/2鍨�/搴熷搧锛屽繀濉�)锛�1鍨�/2鍨嬪垽琛屽悎鏍煎苟鎺ㄨ繘鍑哄簱鍗曞緟鎷h揣锛屽簾鍝佸垽琛屼笉鍚堟牸骞跺彇娑堥攢鍞嚭搴撳崟锛涘彂璐ф暟閲�/鍑鸿揣鏃ユ湡鍙┖", "upstream": ["閿�鍞嚭搴撳崟"], "downstream": ["閿�鍞嚭搴撳崟(鎺ㄨ繘鎴栧彇娑�)"], "keywords": "OQC 鍑鸿揣妫�楠� 鍑哄巶妫�楠� 1鍨� 2鍨� 搴熷搧"},
     {"name": "RQC閫�璐ф楠�", "module": "璐ㄩ噺", "table": "mes_qc_rqc", "doc": "鐢熶骇閫�鏂�/閿�鍞��璐�/鍞悗閫�璐цЕ鍙戯紝缁撹鍥炶皟鍞悗锛涘洓绫绘楠屽崟鍧囨敮鎸侀噰鏍峰湴鐐�/璇佷功缂栧彿/鎵ц鏍囧噯琛ㄥご涓庡鏍嘎峰鏍镐汉锛屽苟鍙墦鍗版楠屾姤鍛�", "upstream": ["閫�鏂�", "閫�璐�"], "downstream": ["閫�璐у叆搴�", "鍞悗鍥炶皟", "妫�楠屾姤鍛婃墦鍗�"], "keywords": "RQC 閫�璐ф楠�"},
     {"name": "妫�楠屾寚鏍�", "module": "璐ㄩ噺", "table": "mes_qc_indicator", "doc": "鏀寔涓ょ骇鍒嗙粍鏍�(itemType褰曞叆/鍒嗙粍+parentId)銆佸叕寮忔枃鏈睍绀恒�佸崟浣嶆枃鏈�佸悓绾ф帓搴忥紱鍒嗙粍椤逛笉褰曞�硷紱鏈夊瓙椤圭鍒狅紱鍚屽眰绾у悕绉板彲閲嶅", "upstream": [], "downstream": ["璐ㄦ鏂规", "妫�楠屾姤鍛婃墦鍗�"], "keywords": "妫�楠屾寚鏍� indicator 鍒嗙粍 鍏紡 鍖栧伐"},
-    {"name": "妫�楠屾姤鍛婃墦鍗�", "module": "璐ㄩ噺", "table": "mes_qc_indicator_result_detail", "doc": "鍖栧伐鎶ュ憡鑼冨紡锛氬钩琛屾祴閲忔壒娆�(measure_no)+鍒嗙粍鐭╅樀+鍏紡鍒�+绛惧瓧鍖猴紱/mes/qc/indicator-result/report 鑱氬悎锛屽墠绔祻瑙堝櫒鎵撳嵃锛涘彟鏈変骇鍝佹楠屽崟Word瀵煎嚭 /mes/qc/indicator-result/export-product-word锛堢焊璐ㄦ楠屽崟鐗堝紡锛氭棤鎶�鏈寚鏍囧垪锛屽垽瀹氱粨璁�/璐ㄦ涓撶敤绔犵暀绌烘墜濉紝骞宠娴嬮噺椤垮彿鍚堝苟锛岀敓浜у崟浣嶅啓姝汇�佺敓浜ф椂闂�=鍗曟嵁鍒涘缓鏃堕棿锛屼笅杞藉悗Word鎵撳嵃锛�", "upstream": ["IQC鏉ユ枡妫�楠�", "IPQC杩囩▼妫�楠�", "OQC鍑鸿揣妫�楠�", "RQC閫�璐ф楠�", "妫�楠屾寚鏍�"], "downstream": [], "keywords": "鎵撳嵃 鎶ュ憡 娴嬮噺鎵规 绛惧瓧 姝d竵閱� GB/T6027 Word 浜у搧妫�楠屽崟"},
+    {"name": "妫�楠屾姤鍛婃墦鍗�", "module": "璐ㄩ噺", "table": "mes_qc_indicator_result_detail", "doc": "鍖栧伐鎶ュ憡鑼冨紡锛氬钩琛屾祴閲忔壒娆�(measure_no)+鍒嗙粍鐭╅樀+鍏紡鍒�+绛惧瓧鍖猴紱/mes/qc/indicator-result/report 鑱氬悎锛屽墠绔祻瑙堝櫒鎵撳嵃", "upstream": ["IQC鏉ユ枡妫�楠�", "IPQC杩囩▼妫�楠�", "OQC鍑鸿揣妫�楠�", "RQC閫�璐ф楠�", "妫�楠屾寚鏍�"], "downstream": [], "keywords": "鎵撳嵃 鎶ュ憡 娴嬮噺鎵规 绛惧瓧 姝d竵閱� GB/T6027"},
     {"name": "NCR涓嶅悎鏍煎搧", "module": "璐ㄩ噺", "table": "mes_qc_ncr", "doc": "寰呰瘎瀹�0鈫掑凡璇勫6鈫掑凡澶勭疆7鈫掑凡鍏抽棴8锛屽缃�:閫�璐�/鎶ュ簾/杩斿伐/璁╂鎺ユ敹/闄嶇骇", "upstream": ["IQC/IPQC/OQC/RQC"], "downstream": ["閫�璐�/鎶ュ簾/杩斿伐(鍙拌处)"], "keywords": "NCR 涓嶅悎鏍� 澶勭疆 鐗归噰 鎶ュ簾"},
     {"name": "璁惧", "module": "璁惧", "table": "mes_dv_machinery", "doc": "鍙拌处鐘舵��:鍋滄満/鐢熶骇涓�/淇濆吇涓紱鐐规路淇濆吇路缁翠慨宸ュ崟锛汚I 椋庨櫓棰勬祴娑堣垂鍏舵暟鎹�", "upstream": [], "downstream": ["鐐规", "缁翠慨", "鐢熶骇椋庨櫓棰勬祴"], "keywords": "璁惧 鐐规 淇濆吇 缁翠慨 machinery"},
     {"name": "鍞悗宸ュ崟", "module": "鍞悗", "table": "after_sale_ticket", "doc": "鑽夌0鈫掑鐞嗕腑10鈫掑緟鍏ュ簱30鈫掑緟閫�娆�40鈫掑畬缁�50鈫掑叧闂�60/鍙栨秷99锛屽垽瀹�:涓�鑸�/缁翠慨/閫�璐�", "upstream": ["瀹㈡埛鍙嶉(浜哄伐褰曞叆)"], "downstream": ["缁翠慨璁板綍", "閫�璐х敵璇�"], "keywords": "鍞悗 宸ュ崟 ticket 缁翠慨"},
@@ -516,13 +516,13 @@
        {"stage": "鑱斿姩", "action": "瀹℃壒閫氳繃鎸夊伐搴忔爣璁�: 鍊掑啿鈫掕嚜鍔ㄧ墿鏂欐秷鑰楁墸绾胯竟搴�(鍏佽璐熷簱瀛�)锛涜川妫�鈫掍骇鍑哄緟妫�琛岀瓑 IPQC锛涘叧閿潪妫�鈫掔洿鎺ヤ骇鍑哄叆搴�", "roles": ["绯荤粺鑷姩"]},
        {"stage": "瀹屽伐", "action": "浠呮湯閬撳伐搴忓洖鍐欏伐鍗曞凡鐢熶骇鏁伴噺锛岃揪鏍囪嚜鍔ㄥ畬鎴愶紱MPS 绱鍒ゆ柇瀹屾垚骞跺彂浜嬩欢缁欓攢鍞鍗�", "roles": ["绯荤粺鑷姩"]}]},
     {"id": "quality", "name": "璐ㄩ噺娴佺▼", "mermaid": "mermaid/05-quality-flow.mmd", "color": "#e06c6c",
-     "summary": "鍥涢亾妫�楠岄椄鍙�(IQC/IPQC/OQC/RQC锛屼簩鎬� 0鈫�4) + 鍒ゅ畾鍥涙灉(鍚堟牸/鐗归噰/閫�璐�/鎶ュ簾) + NCR 璇勫澶勭疆鍏抽棴锛汚I 鎻愪緵鍒ゅ畾寤鸿锛汵CR 褰撳墠浠呭彴璐︿笉瑙﹀彂杩斿伐鍗曘�傛敮鎸佸寲宸ユ姤鍛婅寖寮忥細鍒嗙粍鎸囨爣鏍�+鍏紡鏂囨湰+骞宠娴嬮噺鎵规+閲囨牱琛ㄥご+绛惧瓧鍖猴紝娴忚鍣ㄦ墦鍗版楠屾姤鍛婏紱骞跺彲瀵煎嚭浜у搧妫�楠屽崟 Word锛堢焊璐ㄧ増寮忥紝鍒ゅ畾缁撹/璐ㄦ绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉紝Word 鎵撳嵃锛夈��",
+     "summary": "鍥涢亾妫�楠岄椄鍙�(IQC/IPQC/OQC/RQC锛屼簩鎬� 0鈫�4) + 鍒ゅ畾鍥涙灉(鍚堟牸/鐗归噰/閫�璐�/鎶ュ簾锛汷QC 鏀规寜浜у搧绛夌骇 1鍨�/2鍨�/搴熷搧锛屼粎搴熷搧鍒や笉鍚堟牸) + NCR 璇勫澶勭疆鍏抽棴锛汚I 鎻愪緵鍒ゅ畾寤鸿锛汵CR 褰撳墠浠呭彴璐︿笉瑙﹀彂杩斿伐鍗曘�傛敮鎸佸寲宸ユ姤鍛婅寖寮忥細鍒嗙粍鎸囨爣鏍�+鍏紡鏂囨湰+骞宠娴嬮噺鎵规+閲囨牱琛ㄥご+绛惧瓧鍖猴紝娴忚鍣ㄦ墦鍗版楠屾姤鍛婏紱骞跺彲瀵煎嚭浜у搧妫�楠屽崟 Word锛堢焊璐ㄦ楠屽崟鐗堝紡锛屽垽瀹氱粨璁�/璐ㄦ绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉紝Word 鎵撳嵃锛夈��",
      "steps": [
        {"stage": "鏉ユ枡", "action": "鍒拌揣閫氱煡/澶栧崗鍏ュ簱鈫扞QC锛岀粨璁哄洖鍐欐帹杩涘緟鍏ュ簱鎴栬Е鍙戦��璐�", "roles": ["IQC 璐ㄦ鍛�"]},
        {"stage": "杩囩▼", "action": "鎶ュ伐璐ㄦ宸ュ簭浜у嚭琛屸啋IPQC锛屽悎鏍兼媶琛屽叆搴撱�佷笉鍚堟牸鐢熸垚 NCR", "roles": ["IPQC 璐ㄦ鍛�"]},
-       {"stage": "鍑鸿揣", "action": "閿�鍞嚭搴撴彁浜も啋OQC锛屽畬鎴愬悗鍑哄簱鍗曡繘鍏ュ緟鎷h揣", "roles": ["OQC 璐ㄦ鍛�"]},
+       {"stage": "鍑鸿揣", "action": "閿�鍞嚭搴撴彁浜も啋OQC(妫�娴嬬粨鏋滄寜浜у搧绛夌骇 1鍨�/2鍨�/搴熷搧蹇呭~锛�1鍨�/2鍨嬪垽琛屽悎鏍硷紝搴熷搧鍒よ涓嶅悎鏍�)锛屽叏閮ㄥ悎鏍煎悗鍑哄簱鍗曡繘鍏ュ緟鎷h揣锛屽嚭鐜板簾鍝佸垯鏁村崟鍙栨秷", "roles": ["OQC 璐ㄦ鍛�"]},
        {"stage": "閫�璐�", "action": "閫�鏂�/閿�鍞��璐�/鍞悗閫�璐р啋RQC锛岀粨璁哄洖璋冨崟鎹笌鍞悗", "roles": ["RQC 璐ㄦ鍛�"]},
-       {"stage": "鎶ュ憡", "action": "妫�楠岀粨鏋滄寜鍒嗙粍鏍�+娴嬮噺鎵规褰曞叆锛�/indicator-result/report 鑱氬悎鍚庡墠绔墦鍗版楠屾姤鍛�(鍚噰鏍峰湴鐐�/璇佷功缂栧彿/鎵ц鏍囧噯/澶嶆牳路瀹℃牳绛惧瓧鍖�)锛�/indicator-result/export-product-word 瀵煎嚭浜у搧妫�楠屽崟Word(鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹/璐ㄦ绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉稺ord鎵撳嵃锛涜鎯呮娴嬬粨鏋淭ab鍙寜鏍峰搧鏌ョ湅鍙鏄庣粏)", "roles": ["璐ㄦ鍛�", "澶嶆牳浜�", "瀹℃牳浜�"]},
+       {"stage": "鎶ュ憡", "action": "妫�楠岀粨鏋滄寜鍒嗙粍鏍�+娴嬮噺鎵规褰曞叆锛�/indicator-result/report 鑱氬悎鍚庡墠绔墦鍗版楠屾姤鍛�(鍚噰鏍峰湴鐐�/璇佷功缂栧彿/鎵ц鏍囧噯/鍒ゅ畾缁撹路璐ㄦ涓撶敤绔�/澶嶆牳路瀹℃牳绛惧瓧鍖猴紱鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋溌疯川妫�绔犵暀绌虹洊绔犅锋棤骞宠娴嬮噺鏃跺垪澶寸О娴嬮噺鍊�)锛�/indicator-result/export-product-word 瀵煎嚭浜у搧妫�楠屽崟Word(鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋溌疯川妫�绔�/妫�楠屄峰鏍嘎锋壒鍑嗙瀛楃暀绌烘墜濉峰钩琛屾祴閲忛】鍙峰悎骞堵蜂笅杞藉悗Word鎵撳嵃锛涜川妫�鍗曡鎯呮娴嬬粨鏋淭ab鍙寜鏍峰搧鏌ョ湅鍙妫�娴嬪�兼槑缁�)", "roles": ["璐ㄦ鍛�", "澶嶆牳浜�", "瀹℃牳浜�"]},
        {"stage": "涓嶅悎鏍�", "action": "NCR: 寰呰瘎瀹♀啋璇勫鈫掑缃�(閫�璐�/鎶ュ簾/杩斿伐/璁╂鎺ユ敹/闄嶇骇)鈫掑叧闂�", "roles": ["璐ㄩ噺宸ョ▼甯�"]}]},
     {"id": "warehouse", "name": "浠撳偍娴佺▼", "mermaid": "mermaid/06-warehouse-flow.mmd", "color": "#7e6bd6",
      "summary": "15 绫诲崟鎹┍鍔ㄥ簱瀛樺彴璐�(鍏厓缁勩�佸洓閲�)鍙樺姩锛屽叏閮ㄧ粡浜嬪姟娴佹按鐣欑棔锛涙敮鎸佽皟鎷ㄥ湪閫斻�佺洏鐐硅皟鏁淬�佹壒娆�/SN 杩芥函銆佸簱瀛樺崰鐢ㄤ笌鍥涚骇鍐荤粨銆佺嚎杈硅櫄鎷熷簱璐熷簱瀛橈紱瀵瑰 WmsStockApi 渚� ERP 鏀跺彂銆�",
@@ -739,19 +739,25 @@
   T4[鐢熶骇閫�鏂欏崟 鎴� 閿�鍞��璐у崟 鎴� 鍞悗閫�璐 --> A4[RQC 閫�璐ф楠屄疯崏绋�0鈫掑畬鎴�4]
   A1 --> R{妫�楠屽垽瀹� MesQcCheckResultEnum}
   A2 --> R
-  A3 --> R
   A4 --> R
   R -->|1 鍚堟牸| Q1[鍏佽鍏ュ簱路鍥炲啓鏉ユ簮鍗曟嵁鎺ㄨ繘鐘舵�乚
   R -->|2 鐗归噰| Q2[鍏佽鍏ュ簱路骞剁敓鎴怤CR鐣欑棔]
   R -->|3 涓嶅悎鏍奸��璐 Q3[鐢熸垚NCR路璧颁緵搴斿晢閫�璐ф垨閿�鍞��璐
   R -->|4 涓嶅悎鏍兼姤搴焲 Q4[鐢熸垚NCR路璧版姤搴熷嚭搴揮
+  A3 --> R2{鍑鸿揣鍒ゅ畾 MesQcOqcCheckResultEnum路蹇呭~}
+  R2 -->|1鍨�/2鍨媩 S1[鍑哄簱琛屽垽鍚堟牸路鎺ㄨ繘鍑哄簱鍗曞緟鎷h揣]
+  R2 -->|搴熷搧| S2[鍑哄簱琛屽垽涓嶅悎鏍悸峰彇娑堥攢鍞嚭搴撳崟]
+  A3 -.-> N5[琛ㄥご:鍙戣揣鏁伴噺/鍑鸿揣鏃ユ湡闈炲繀濉锋娴嬬粨鏋滃繀濉玗
+  A2 -.-> N6[琛ㄥご:鏉ユ簮鍗曟嵁鍙路浜у搧鐗╂枡(MDM)蹇呭~路鎵瑰彿蹇呭~路宸插幓鎺夌敓浜ц鍗�/宸ヤ綅/鐢熶骇浠诲姟/宸ュ簭]
   A2 -->|鍚堟牸鏁伴噺| Q5[鎶ュ伐杞畬鎴惵蜂骇鍑烘媶琛屽叆搴揮
-  A3 -->|瀹屾垚| Q6[閿�鍞嚭搴撳崟鎺ㄨ繘寰呮嫞璐
   A4 -->|瀹屾垚| Q7[閫�璐у崟鎺ㄨ繘涓婃灦鎴栧叆搴撀峰敭鍚庡洖璋冪粨璁篯
   N1[NCR 寰呰瘎瀹�0] -->|璇勫| N2[宸茶瘎瀹�6]
   N2 -->|澶勭疆鏂瑰紡:閫�璐�1鎶ュ簾2杩斿伐3璁╂鎺ユ敹4闄嶇骇浣跨敤5| N3[宸插缃�7]
   N3 -->|鍏抽棴| N4[宸插叧闂�8]
   Q8[鏀拺鏁版嵁:璐ㄦ鏂规路妫�楠屾寚鏍嚶风己闄峰簱路鎸囨爣缁撴灉] --- A1
+  Q9[鍖栧伐鎶ュ憡澧炲己:鎸囨爣鍒嗙粍鏍�+鍏紡鏂囨湰路骞宠娴嬮噺鎵规路閲囨牱鍦扮偣/璇佷功缂栧彿/鎵ц鏍囧噯琛ㄥご路澶嶆牳浜�/瀹℃牳浜篯 --- Q8
+  A1 & A2 & A3 & A4 --> P1[妫�楠屾姤鍛婂崟鎵撳嵃路鍓嶇娴忚鍣ㄦ墦鍗奥峰垽瀹氱粨璁哄甫鍑烘楠岀粨鏋�+璐ㄦ涓撶敤绔犵暀绌虹洊绔�+绛惧瓧鍖郝锋棤骞宠娴嬮噺鏃跺垪澶寸О娴嬮噺鍊糫
+  A1 & A2 & A3 & A4 --> P2[浜у搧妫�楠屽崟Word瀵煎嚭路export-product-word路鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋�/璐ㄦ绔犵暀绌虹洊绔犅稺ord鎵撳嵃]
 </pre>
 <pre style="display:none" class="mmd-src" data-mmd="06-warehouse-flow">
 flowchart LR
@@ -932,7 +938,7 @@
   J4 --> J5[璐ㄦ鍛樺弬鑰冨垽瀹毬稟I涓嶅彲鐢ㄦ椂鎻愮ず浜哄伐鍒ゅ畾]
   R1[宸ュ崟BOM+搴撳瓨鍙敤閲�+宸叉姇鏂橾 --> R2[鐗╂枡鐭己棰勬祴路椋庨櫓绛夌骇涓庣己鍙f竻鍗昡
   R3[宸ュ簭鏍囧噯宸ユ椂+璁惧姣忓皬鏃朵骇閲�+浼犻�佸�嶇巼] --> R4[鐢熶骇鏃堕暱棰勬祴]
-  R5[IPQC缂洪櫡鐜�+璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�+鍏抽敭宸ュ簭] --> R6[鐢熶骇椋庨櫓棰勬祴]
+  R5[璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�+鍏抽敭宸ュ簭] --> R6[鐢熶骇椋庨櫓棰勬祴]
   R7[杩涘害+鍓╀綑澶╂暟+浠诲姟瀹屾垚鐘舵��+瀹㈡埛浜ゆ湡] --> R8[浜や粯棰勬祴路鑳藉惁鎸夋椂+缃俊搴�+寤惰鍥犵礌]
   KB1[鐭ヨ瘑搴撴枃妗d笂浼燯RL] --> KB2[POI/Tika鎻愬彇鏂囨湰] --> KB3[鍒囩墖绾�800tokens鈫掑悜閲忓寲鈫扢ilvus]
   KB3 --> KB4[鍒嗘妫�绱㈡帴鍙� topK+鐩镐技搴﹂槇鍊糫
diff --git a/docs/project-business/mermaid/05-quality-flow.mmd b/docs/project-business/mermaid/05-quality-flow.mmd
index af16dd4..3b21b28 100644
--- a/docs/project-business/mermaid/05-quality-flow.mmd
+++ b/docs/project-business/mermaid/05-quality-flow.mmd
@@ -5,19 +5,22 @@
   T4[鐢熶骇閫�鏂欏崟 鎴� 閿�鍞��璐у崟 鎴� 鍞悗閫�璐 --> A4[RQC 閫�璐ф楠屄疯崏绋�0鈫掑畬鎴�4]
   A1 --> R{妫�楠屽垽瀹� MesQcCheckResultEnum}
   A2 --> R
-  A3 --> R
   A4 --> R
   R -->|1 鍚堟牸| Q1[鍏佽鍏ュ簱路鍥炲啓鏉ユ簮鍗曟嵁鎺ㄨ繘鐘舵�乚
   R -->|2 鐗归噰| Q2[鍏佽鍏ュ簱路骞剁敓鎴怤CR鐣欑棔]
   R -->|3 涓嶅悎鏍奸��璐 Q3[鐢熸垚NCR路璧颁緵搴斿晢閫�璐ф垨閿�鍞��璐
   R -->|4 涓嶅悎鏍兼姤搴焲 Q4[鐢熸垚NCR路璧版姤搴熷嚭搴揮
+  A3 --> R2{鍑鸿揣鍒ゅ畾 MesQcOqcCheckResultEnum路蹇呭~}
+  R2 -->|1鍨�/2鍨媩 S1[鍑哄簱琛屽垽鍚堟牸路鎺ㄨ繘鍑哄簱鍗曞緟鎷h揣]
+  R2 -->|搴熷搧| S2[鍑哄簱琛屽垽涓嶅悎鏍悸峰彇娑堥攢鍞嚭搴撳崟]
+  A3 -.-> N5[琛ㄥご:鍙戣揣鏁伴噺/鍑鸿揣鏃ユ湡闈炲繀濉锋娴嬬粨鏋滃繀濉玗
+  A2 -.-> N6[琛ㄥご:鏉ユ簮鍗曟嵁鍙路浜у搧鐗╂枡(MDM)蹇呭~路鎵瑰彿蹇呭~路宸插幓鎺夌敓浜ц鍗�/宸ヤ綅/鐢熶骇浠诲姟/宸ュ簭]
   A2 -->|鍚堟牸鏁伴噺| Q5[鎶ュ伐杞畬鎴惵蜂骇鍑烘媶琛屽叆搴揮
-  A3 -->|瀹屾垚| Q6[閿�鍞嚭搴撳崟鎺ㄨ繘寰呮嫞璐
   A4 -->|瀹屾垚| Q7[閫�璐у崟鎺ㄨ繘涓婃灦鎴栧叆搴撀峰敭鍚庡洖璋冪粨璁篯
   N1[NCR 寰呰瘎瀹�0] -->|璇勫| N2[宸茶瘎瀹�6]
   N2 -->|澶勭疆鏂瑰紡:閫�璐�1鎶ュ簾2杩斿伐3璁╂鎺ユ敹4闄嶇骇浣跨敤5| N3[宸插缃�7]
   N3 -->|鍏抽棴| N4[宸插叧闂�8]
   Q8[鏀拺鏁版嵁:璐ㄦ鏂规路妫�楠屾寚鏍嚶风己闄峰簱路鎸囨爣缁撴灉] --- A1
   Q9[鍖栧伐鎶ュ憡澧炲己:鎸囨爣鍒嗙粍鏍�+鍏紡鏂囨湰路骞宠娴嬮噺鎵规路閲囨牱鍦扮偣/璇佷功缂栧彿/鎵ц鏍囧噯琛ㄥご路澶嶆牳浜�/瀹℃牳浜篯 --- Q8
-  A1 & A2 & A3 & A4 --> P1[妫�楠屾姤鍛婂崟鎵撳嵃路鍓嶇娴忚鍣ㄦ墦鍗奥峰惈绛惧瓧鍖篯
-  A1 & A2 & A3 & A4 --> P2[浜у搧妫�楠屽崟Word瀵煎嚭路export-product-word路鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹/璐ㄦ绔犵暀绌烘墜濉稺ord鎵撳嵃]
+  A1 & A2 & A3 & A4 --> P1[妫�楠屾姤鍛婂崟鎵撳嵃路鍓嶇娴忚鍣ㄦ墦鍗奥峰垽瀹氱粨璁哄甫鍑烘楠岀粨鏋�+璐ㄦ涓撶敤绔犵暀绌虹洊绔�+绛惧瓧鍖郝锋棤骞宠娴嬮噺鏃跺垪澶寸О娴嬮噺鍊糫
+  A1 & A2 & A3 & A4 --> P2[浜у搧妫�楠屽崟Word瀵煎嚭路export-product-word路鏃犳妧鏈寚鏍囧垪路鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋�/璐ㄦ绔犵暀绌虹洊绔犅稺ord鎵撳嵃]
diff --git a/docs/project-business/mermaid/11-ai-business-flow.mmd b/docs/project-business/mermaid/11-ai-business-flow.mmd
index 947d2eb..94f13cf 100644
--- a/docs/project-business/mermaid/11-ai-business-flow.mmd
+++ b/docs/project-business/mermaid/11-ai-business-flow.mmd
@@ -15,7 +15,7 @@
   J4 --> J5[璐ㄦ鍛樺弬鑰冨垽瀹毬稟I涓嶅彲鐢ㄦ椂鎻愮ず浜哄伐鍒ゅ畾]
   R1[宸ュ崟BOM+搴撳瓨鍙敤閲�+宸叉姇鏂橾 --> R2[鐗╂枡鐭己棰勬祴路椋庨櫓绛夌骇涓庣己鍙f竻鍗昡
   R3[宸ュ簭鏍囧噯宸ユ椂+璁惧姣忓皬鏃朵骇閲�+浼犻�佸�嶇巼] --> R4[鐢熶骇鏃堕暱棰勬祴]
-  R5[IPQC缂洪櫡鐜�+璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�+鍏抽敭宸ュ簭] --> R6[鐢熶骇椋庨櫓棰勬祴]
+  R5[璁惧淇濆吇鐐规+鐗╂枡鍙敤鐜�+鍏抽敭宸ュ簭] --> R6[鐢熶骇椋庨櫓棰勬祴]
   R7[杩涘害+鍓╀綑澶╂暟+浠诲姟瀹屾垚鐘舵��+瀹㈡埛浜ゆ湡] --> R8[浜や粯棰勬祴路鑳藉惁鎸夋椂+缃俊搴�+寤惰鍥犵礌]
   KB1[鐭ヨ瘑搴撴枃妗d笂浼燯RL] --> KB2[POI/Tika鎻愬彇鏂囨湰] --> KB3[鍒囩墖绾�800tokens鈫掑悜閲忓寲鈫扢ilvus]
   KB3 --> KB4[鍒嗘妫�绱㈡帴鍙� topK+鐩镐技搴﹂槇鍊糫
diff --git a/docs/qc_chemical_report_integration.md b/docs/qc_chemical_report_integration.md
index c0ca1d2..0a2b546 100644
--- a/docs/qc_chemical_report_integration.md
+++ b/docs/qc_chemical_report_integration.md
@@ -50,6 +50,7 @@
   "samplingTime": "2026-08-30T01:00:00",
   "batchQuantity": 30,
   "checkResult": 1,
+  "checkResultText": "鏍¢獙閫氳繃",
   "inspectorName": "鏂拌壋",
   "auditName": "娴蜂附",
   "approveName": "鐜嬩簲",
@@ -83,8 +84,10 @@
 | 璇佷功缂栧彿 / 閲囨牱鍦扮偣 / 鎵归噺 / 閲囨牱鏃堕棿 / 鎵ц鏍囧噯 | report 鍚屽悕瀛楁 |
 | 鍒嗙粍琛岋紙姘村垎/閰稿惈閲忊�︼級 | itemType=2 鑺傜偣锛氬悕绉拌 + 鍏紡鏂囨湰(formulaText) |
 | 鍙傛暟琛�/缁撴灉琛� | 鍒嗙粍 children 褰曞叆椤癸紝鎸� sortOrder 鎺掑簭 |
-| 骞宠娴嬮噺涓ゅ垪 | measureNos 鏁扮粍椹卞姩鍒楀ご锛屾瘡 measureNo 涓�鍒� |
+| 骞宠娴嬮噺鍒楀ご | measureNos 鏁扮粍椹卞姩锛涗粎涓�鍒楁椂鍒楀ご鏄剧ず銆屾祴閲忓�笺�嶏紝澶氬垪鏃舵樉绀恒�屾祴閲�1銆嶃�屾祴閲�2銆嶁�� |
 | 澶栬绛夊畾鎬ч」 | resultType=鏂囨湰/瀛楀吀 鐨勫綍鍏ラ」鐩存帴鏄剧ず value |
+| 鍒ゅ畾缁撹 | `checkResultText`锛堝悗绔寜 qcType 瀵瑰簲瀛楀吀瑙f瀽锛� |
+| 璐ㄦ涓撶敤绔� | 鏃犳暟鎹潵婧愶紝鐣欏嚭绌虹櫧鍗曞厓鏍间緵鎵撳嵃鍚庝汉宸ョ洊绔� |
 | 鍒嗘瀽鑰�/澶嶆牳浜�/瀹℃牳浜� | inspectorName / auditName / approveName |
 
 ## 涓氬姟瑙勫垯
@@ -101,6 +104,7 @@
 
 - 鎵撳嵃涓烘祻瑙堝櫒 `window.print()`锛屽缓璁湪 Chrome 涓嬮瑙堬紱闅愯棌鎵撳嵃澶栧叾浠栧厓绱犵敱缁勪欢鍐� `@media print` 鎺у埗銆�
 - `/report` 鐨� `qcType`锛�1=IQC銆�2=IPQC銆�3=OQC銆�4=RQC锛屼笌 `MesQcTypeEnum` 涓�鑷淬��
+- 鍒ゅ畾缁撹鏂囨鐢卞悗绔寜 `qcType` 閫夊瓧鍏歌В鏋愶細OQC 璧� `mes_oqc_check_result`锛�1鍨�/2鍨�/搴熷搧锛夛紝IQC/IPQC/RQC 璧� `mes_qc_check_result`锛堟牎楠岄�氳繃/鏍¢獙涓嶉�氳繃锛夈�傛湭鍒ゅ畾锛坄checkResult` 涓虹┖锛夋椂鎵撳嵃涓恒��-銆嶏紝鍓嶇鍙洖閫�鎸� `checkResult` 鑷鍙栧瓧鍏告爣绛俱��
 - 澶嶆牳浜�/瀹℃牳浜轰粎浣滀负璁板綍涓庢墦鍗扮瀛楀尯锛屼笉寮曞叆瀹℃壒娴佽浆銆�
 - 鏂囦欢闄勪欢绫绘寚鏍囷紙resultType=鏂囦欢锛夋部鐢ㄥ師鏈哄埗锛屾湭鍦ㄦ湰娆¤寖鍥淬��
 - 鍥炲綊鐐癸細鏃㈡湁鎵佸钩鎸囨爣鐨勮�佹楠屽崟锛堝綍鍏�/瀹屾垚/Excel 瀵煎嚭锛夎涓轰笉鍙橈紱`measure_no` 榛樿 1 瀵硅�佹暟鎹�忔槑銆�
diff --git a/docs/sql/config_export_all_20260904.sql b/docs/sql/config_export_all_20260904.sql
index d91386f..754c734 100644
--- a/docs/sql/config_export_all_20260904.sql
+++ b/docs/sql/config_export_all_20260904.sql
@@ -988,6 +988,7 @@
 ('2046', 'MES 缁翠慨宸ュ崟鐘舵��', 'mes_dv_repair_status', '0', 'MES 璁惧绠$悊 - 缁翠慨宸ュ崟鐘舵�侊紙10=寰呯淮淇紝20=缁翠慨涓紝30=宸插畬鎴愶紝40=宸查獙鏀讹級', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', X'00', NULL),
 ('2047', 'MES 缁翠慨缁撴灉', 'mes_dv_repair_result', '0', 'MES 璁惧绠$悊 - 缁翠慨缁撴灉锛�1=淇鎴愬姛锛�2=鎶ュ簾锛�', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', X'00', NULL),
 ('2049', 'MES 妫�娴嬬粨鏋�', 'mes_qc_check_result', '0', '鏉ユ枡妫�楠岀殑鏈�缁堢粨鏋滃垽瀹�', '1', '2026-02-20 11:23:35', '1', '2026-02-20 11:23:35', X'00', NULL),
+('1065400', 'MES 鍑鸿揣妫�楠屾娴嬬粨鏋�', 'mes_oqc_check_result', '0', '鍑鸿揣妫�楠屽崟(OQC)鍒ゅ畾缁撴灉锛�1鍨�/2鍨嬩负鍙彂璐х瓑绾э紝搴熷搧涓嶆斁琛�', '1', '2026-09-22 00:00:00', '1', '2026-09-22 00:00:00', X'00', NULL),
 ('2050', 'MES 鏉ユ簮鍗曟嵁绫诲瀷', 'mes_qc_source_doc_type', '0', 'IQC 鏉ユ枡妫�楠岀殑鏉ユ簮鍗曟嵁绫诲瀷', '1', '2026-02-20 11:23:35', '1', '2026-02-20 11:23:35', X'00', NULL),
 ('2051', 'MES 瀹夌伅澶勭疆鐘舵��', 'mes_pro_andon_status', '0', 'MES 鐢熶骇绠$悊 - 瀹夌伅澶勭疆鐘舵�侊紙0=鏈缃紝1=宸插缃級', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', X'00', NULL),
 ('2052', 'MES 瀹夌伅绾у埆', 'mes_pro_andon_level', '0', 'MES 鐢熶骇绠$悊 - 瀹夌伅绾у埆锛�1=涓�绾э紝2=浜岀骇锛�3=涓夌骇锛�', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', X'00', NULL),
@@ -1822,6 +1823,9 @@
 ('3158', '2', '鎶ュ簾', '2', 'mes_dv_repair_result', '0', 'danger', '', '', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', X'00'),
 ('3161', '1', '鏍¢獙閫氳繃', '1', 'mes_qc_check_result', '0', 'success', '', '', '1', '2026-02-20 11:23:35', '1', '2026-02-20 16:15:54', X'00'),
 ('3162', '2', '鏍¢獙涓嶉�氳繃', '2', 'mes_qc_check_result', '0', 'danger', '', '', '1', '2026-02-20 11:23:35', '1', '2026-02-20 16:15:52', X'00'),
+('1065401', '1', '1鍨�', '1', 'mes_oqc_check_result', '0', 'success', '', '', '1', '2026-09-22 00:00:00', '1', '2026-09-22 00:00:00', X'00'),
+('1065402', '2', '2鍨�', '2', 'mes_oqc_check_result', '0', 'primary', '', '', '1', '2026-09-22 00:00:00', '1', '2026-09-22 00:00:00', X'00'),
+('1065403', '3', '搴熷搧', '3', 'mes_oqc_check_result', '0', 'danger', '', '', '1', '2026-09-22 00:00:00', '1', '2026-09-22 00:00:00', X'00'),
 ('3166', '0', '鏈缃�', '0', 'mes_pro_andon_status', '0', 'danger', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', X'00'),
 ('3167', '1', '宸插缃�', '1', 'mes_pro_andon_status', '0', 'success', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', X'00'),
 ('3168', '1', '涓�绾�', '1', 'mes_pro_andon_level', '0', 'danger', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', X'00'),
@@ -7995,10 +7999,7 @@
   `source_doc_id` bigint DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁缂栧彿',
   `source_line_id` bigint DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁琛岀紪鍙�',
   `source_doc_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '鏉ユ簮鍗曟嵁缂栧彿',
-  `work_order_id` bigint DEFAULT NULL COMMENT '鐢熶骇宸ュ崟缂栧彿',
-  `task_id` bigint DEFAULT NULL COMMENT '鐢熶骇浠诲姟缂栧彿',
-  `workstation_id` bigint DEFAULT NULL COMMENT '宸ヤ綅缂栧彿',
-  `process_id` bigint DEFAULT NULL COMMENT '宸ュ簭缂栧彿',
+  `batch_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '鎵瑰彿',
   `item_id` bigint DEFAULT NULL COMMENT '浜у搧鐗╂枡缂栧彿',
   `check_quantity` decimal(24,6) DEFAULT NULL COMMENT '妫�娴嬫暟閲�',
   `qualified_quantity` decimal(24,6) DEFAULT NULL COMMENT '鍚堟牸鍝佹暟閲�',
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java
index 5e7b2c0..169b1e1 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractSaveReqVO.java
@@ -7,6 +7,7 @@
 import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -30,6 +31,11 @@
     @NotNull(message = "鍚堝悓鍚嶇О涓嶈兘涓虹┖")
     private String name;
 
+    @Schema(description = "鍚堝悓缂栧彿锛岀暀绌哄垯鑷姩鐢熸垚锛涙柊澧炲拰鏇存柊鍧囧彲鑷畾涔夛紝鏇存柊鏃剁暀绌哄垯淇濇寔鍘熺紪鍙�", example = "HT20260921001")
+    @DiffLogField(name = "鍚堝悓缂栧彿")
+    @Size(max = 100, message = "鍚堝悓缂栧彿闀垮害涓嶈兘瓒呰繃 100 涓瓧绗�")
+    private String no;
+
     @Schema(description = "瀹㈡埛缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "18336")
     @DiffLogField(name = "瀹㈡埛", function = CrmCustomerParseFunction.NAME)
     @NotNull(message = "瀹㈡埛缂栧彿涓嶈兘涓虹┖")
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
index ffcdf9c..c133f54 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -20,6 +20,7 @@
     ErrorCode CONTRACT_GENERATE_ORDER_FAIL_EXISTS_ORDER = new ErrorCode(1_020_000_007, "鐢熸垚閿�鍞鍗曞け璐ワ紝鍘熷洜锛氬凡鍏宠仈閿�鍞鍗曘�恵}銆�");
     ErrorCode CONTRACT_GENERATE_ORDER_FAIL_NO_PRODUCT = new ErrorCode(1_020_000_008, "鐢熸垚閿�鍞鍗曞け璐ワ紝鍘熷洜锛氬悎鍚屾病鏈変骇鍝佷俊鎭�");
     ErrorCode CONTRACT_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_020_000_009, "鍚堝悓瀹℃壒娴佺▼涓嶅瓨鍦ㄦ垨鏈縺娲伙紝璇锋鏌� BPM 閰嶇疆");
+    ErrorCode CONTRACT_NO_DUPLICATE = new ErrorCode(1_020_000_010, "鍚堝悓缂栧彿銆恵}銆戝凡瀛樺湪锛岃鏇存崲鍚庨噸璇�");
 
     // ========== 绾跨储绠$悊 1-020-001-000 ==========
     ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "绾跨储涓嶅瓨鍦�");
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
index 448dae2..91138a8 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -150,10 +150,15 @@
         List<CrmContractProductDO> contractProducts = validateContractProducts(createReqVO.getProducts());
         // 1.2 鏍¢獙鍏宠仈瀛楁
         validateRelationDataExists(createReqVO);
-        // 1.3 鐢熸垚搴忓彿
-        String no = noRedisDAO.generate(CrmNoRedisDAO.CONTRACT_NO_PREFIX);
-        if (contractMapper.selectByNo(no) != null) {
-            throw exception(CONTRACT_NO_EXISTS);
+        // 1.3 鐢熸垚鎴栨牎楠屽悎鍚岀紪鍙凤細鏀寔鑷畾涔夌紪鍙凤紝鏈~鍐欐椂鑷姩鐢熸垚
+        String no = StrUtil.trimToNull(createReqVO.getNo());
+        if (no == null) {
+            no = noRedisDAO.generate(CrmNoRedisDAO.CONTRACT_NO_PREFIX);
+            if (contractMapper.selectByNo(no) != null) {
+                throw exception(CONTRACT_NO_EXISTS);
+            }
+        } else if (contractMapper.selectByNo(no) != null) {
+            throw exception(CONTRACT_NO_DUPLICATE, no);
         }
 
         // 2.1 鎻掑叆鍚堝悓
@@ -188,14 +193,26 @@
         updateReqVO.setOwnerUserId(null); // 涓嶅厑璁告洿鏂扮殑瀛楁
         // 1.1 鏍¢獙瀛樺湪
         CrmContractDO oldContract = validateContractExists(updateReqVO.getId());
-        // 1.2 鍙湁鑽夌銆佸鎵逛腑锛屽彲浠ョ紪杈戯紱
+        // 1.2 鍚堝悓缂栧彿锛氱暀绌哄垯淇濇寔鍘熺紪鍙凤紝濉啓鍒欐牎楠屽敮涓�鎬э紙鎺掗櫎鑷韩锛�
+        //     鐣欑┖鏃跺洖濉師缂栧彿鑰岄潪缃┖锛岄伩鍏嶆搷浣滄棩蹇� diff 鍑虹幇鈥滅紪鍙疯娓呯┖鈥�
+        String no = StrUtil.trimToNull(updateReqVO.getNo());
+        if (no == null) {
+            no = oldContract.getNo();
+        } else {
+            CrmContractDO noContract = contractMapper.selectByNo(no);
+            if (noContract != null && !ObjUtil.equal(noContract.getId(), updateReqVO.getId())) {
+                throw exception(CONTRACT_NO_DUPLICATE, no);
+            }
+        }
+        updateReqVO.setNo(no);
+        // 1.3 鍙湁鑽夌銆佸鎵逛腑锛屽彲浠ョ紪杈戯紱
         if (!ObjectUtils.equalsAny(oldContract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(),
                 CrmAuditStatusEnum.PROCESS.getStatus())) {
             throw exception(CONTRACT_UPDATE_FAIL_NOT_DRAFT);
         }
-        // 1.3 鏍¢獙浜у搧椤圭殑鏈夋晥鎬�
+        // 1.4 鏍¢獙浜у搧椤圭殑鏈夋晥鎬�
         List<CrmContractProductDO> contractProducts = validateContractProducts(updateReqVO.getProducts());
-        // 1.4 鏍¢獙鍏宠仈瀛楁
+        // 1.5 鏍¢獙鍏宠仈瀛楁
         validateRelationDataExists(updateReqVO);
 
         // 2.1 鏇存柊鍚堝悓
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java
index 6a8021e..831586b 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java
@@ -143,7 +143,7 @@
     }
 
     @GetMapping("/export-product-word")
-    @Operation(summary = "瀵煎嚭浜у搧妫�楠屽崟 Word锛堢焊璐ㄦ楠屽崟鐗堝紡锛氭棤鎶�鏈寚鏍囧垪锛屽垽瀹氱粨璁�/璐ㄦ涓撶敤绔犵暀绌烘墜濉紝鎵撳嵃鐢� Word 鎵撳紑锛�")
+    @Operation(summary = "瀵煎嚭浜у搧妫�楠屽崟 Word锛堢焊璐ㄦ楠屽崟鐗堝紡锛氭棤鎶�鏈寚鏍囧垪锛屽垽瀹氱粨璁鸿嚜鍔ㄥ甫鍑烘楠岀粨鏋溿�佽川妫�涓撶敤绔犵暀绌虹洊绔狅紝鎵撳嵃鐢� Word 鎵撳紑锛�")
     @Parameters({
             @Parameter(name = "qcId", description = "璐ㄦ鍗旾D", required = true, example = "1"),
             @Parameter(name = "qcType", description = "璐ㄦ绫诲瀷", required = true, example = "1"),
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcQcReportRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcQcReportRespVO.java
index 9ca3a6f..c957b5d 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcQcReportRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcQcReportRespVO.java
@@ -49,9 +49,12 @@
     @Schema(description = "鎵归噺锛堟潵鏂�=鎺ユ敹鏁伴噺锛岃繃绋�/閫�璐�=妫�娴嬫暟閲忥紝鍑鸿揣=鍑鸿揣鏁伴噺锛�", example = "30")
     private BigDecimal batchQuantity;
 
-    @Schema(description = "妫�娴嬬粨鏋滐紙瀛楀吀 mes_qc_check_result锛�", example = "1")
+    @Schema(description = "妫�娴嬬粨鏋滐紙IQC/IPQC/RQC=瀛楀吀 mes_qc_check_result锛汷QC=瀛楀吀 mes_oqc_check_result锛�", example = "1")
     private Integer checkResult;
 
+    @Schema(description = "妫�娴嬬粨鏋滄枃妗堬紙鎸夎川妫�绫诲瀷瀵瑰簲瀛楀吀瑙f瀽锛屼緵鍒ゅ畾缁撹灞曠ず锛涙湭鍒ゅ畾鏃朵负绌猴級", example = "鏍¢獙閫氳繃")
+    private String checkResultText;
+
     @Schema(description = "妫�楠屾棩鏈�", example = "2026-08-30T01:00:00")
     private LocalDateTime inspectDate;
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java
index 39682ab..2030742 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java
@@ -15,9 +15,6 @@
 import cn.iocoder.yudao.module.mes.controller.admin.qc.vo.MesQcQualityExportVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
-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.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO;
@@ -28,9 +25,6 @@
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
-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.workorder.MesProWorkOrderService;
 import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService;
 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
 import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService;
@@ -69,12 +63,6 @@
 
     @Resource
     private MesQcIpqcService ipqcService;
-    @Resource
-    private MesProWorkOrderService workOrderService;
-    @Resource
-    private MesMdWorkstationService workstationService;
-    @Resource
-    private MesProProcessService processService;
     @Resource
     private MesMdItemService itemService;
     @Resource
@@ -157,15 +145,6 @@
         if (CollUtil.isEmpty(list)) {
             return Collections.emptyList();
         }
-        // 鎵归噺鏌ヨ宸ュ崟
-        Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap(
-                convertSet(list, MesQcIpqcDO::getWorkOrderId));
-        // 鎵归噺鏌ヨ宸ヤ綅
-        Map<Long, MesMdWorkstationDO> workstationMap = workstationService.getWorkstationMap(
-                convertSet(list, MesQcIpqcDO::getWorkstationId));
-        // 鎵归噺鏌ヨ宸ュ簭
-        Map<Long, MesProProcessDO> processMap = processService.getProcessMap(
-                convertSet(list, MesQcIpqcDO::getProcessId));
         // 鎵归噺鏌ヨ鐗╂枡
         Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
                 convertSet(list, MesQcIpqcDO::getItemId));
@@ -182,12 +161,6 @@
         Map<Long, String> indicatorSummaryMap = buildIndicatorSummaryMap(list);
         // 鎷艰 VO
         return BeanUtils.toBean(list, MesQcIpqcRespVO.class, vo -> {
-            findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> vo
-                    .setWorkOrderCode(workOrder.getCode()).setWorkOrderName(workOrder.getName()));
-            findAndThen(workstationMap, vo.getWorkstationId(),
-                    ws -> vo.setWorkstationName(ws.getName()));
-            findAndThen(processMap, vo.getProcessId(),
-                    process -> vo.setProcessName(process.getName()));
             findAndThen(itemMap, vo.getItemId(), item -> {
                 vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification());
                 findAndThen(unitMeasureMap, item.getUnitMeasureId(),
@@ -289,8 +262,7 @@
             vo.setDocName(ipqc.getName());
             MesMdItemDO item = itemMap.get(ipqc.getItemId());
             vo.setItemName(item != null ? item.getName() : "");
-            // IPQC 鏃犳壒娆″彿瀛楁锛屾殏鐢ㄦ潵婧愬崟鎹紪鍙凤紙涓�鑸负鐢熶骇宸ュ崟鍙凤級浣滀负鎵瑰彿
-            vo.setBatchNo(ipqc.getSourceDocCode());
+            vo.setBatchNo(ipqc.getBatchCode());
             vo.setInspectDate(MesQcQualityExportVO.formatDateTime(ipqc.getInspectDate()));
             List<String> indicatorNames = new ArrayList<>();
             List<String> judgementSegments = new ArrayList<>();
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java
index 8221b17..488603f 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java
@@ -23,8 +23,8 @@
     @Schema(description = "IPQC 妫�楠岀被鍨�", example = "1")
     private Integer type;
 
-    @Schema(description = "鐢熶骇宸ュ崟 ID", example = "10")
-    private Long workOrderId;
+    @Schema(description = "鎵瑰彿", example = "BC20250101")
+    private String batchCode;
 
     @Schema(description = "浜у搧鐗╂枡 ID", example = "50")
     private Long itemId;
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java
index 3df24d5..b91a0b2 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java
@@ -50,34 +50,9 @@
     @Schema(description = "鏉ユ簮鍗曟嵁缂栧彿", example = "FB20250101001")
     private String sourceDocCode;
 
-    // ========== 鐢熶骇鍏宠仈 ==========
-
-    @Schema(description = "鐢熶骇宸ュ崟 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    private Long workOrderId;
-
-    @Schema(description = "宸ュ崟缂栧彿", example = "WO20250101001")
-    @ExcelProperty("宸ュ崟缂栧彿")
-    private String workOrderCode;
-
-    @Schema(description = "宸ュ崟鍚嶇О", example = "鐢熶骇宸ュ崟A")
-    private String workOrderName;
-
-    @Schema(description = "鐢熶骇浠诲姟 ID", example = "20")
-    private Long taskId;
-
-    @Schema(description = "宸ヤ綅 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
-    private Long workstationId;
-
-    @Schema(description = "宸ヤ綅鍚嶇О", example = "宸ヤ綅A")
-    @ExcelProperty("宸ヤ綅鍚嶇О")
-    private String workstationName;
-
-    @Schema(description = "宸ュ簭 ID", example = "40")
-    private Long processId;
-
-    @Schema(description = "宸ュ簭鍚嶇О", example = "缁勮")
-    @ExcelProperty("宸ュ簭鍚嶇О")
-    private String processName;
+    @Schema(description = "鎵瑰彿", example = "BC20250101")
+    @ExcelProperty("鎵瑰彿")
+    private String batchCode;
 
     // ========== 鐗╂枡 ==========
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java
index ba73cf7..8214c1d 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java
@@ -42,25 +42,14 @@
     @Schema(description = "鏉ユ簮鍗曟嵁琛� ID", example = "300")
     private Long sourceLineId;
 
-    // ========== 鐢熶骇鍏宠仈 ==========
-
-    @Schema(description = "鐢熶骇宸ュ崟 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @NotNull(message = "鐢熶骇宸ュ崟涓嶈兘涓虹┖")
-    private Long workOrderId;
-
-    @Schema(description = "鐢熶骇浠诲姟 ID", example = "20")
-    private Long taskId;
-
-    @Schema(description = "宸ヤ綅 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
-    @NotNull(message = "宸ヤ綅涓嶈兘涓虹┖")
-    private Long workstationId;
-
-    @Schema(description = "宸ュ簭 ID", example = "40")
-    private Long processId;
+    @Schema(description = "鎵瑰彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "BC20250101")
+    @NotEmpty(message = "鎵瑰彿涓嶈兘涓虹┖")
+    private String batchCode;
 
     // ========== 鐗╂枡 ==========
 
-    @Schema(description = "浜у搧鐗╂枡 ID", example = "50")
+    @Schema(description = "浜у搧鐗╂枡 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
+    @NotNull(message = "浜у搧鐗╂枡涓嶈兘涓虹┖")
     private Long itemId;
 
     @Schema(description = "璐ㄦ鏂规 ID", example = "5")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java
index a8cfea2..40d7285 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java
@@ -285,7 +285,7 @@
             return "";
         }
         return DictFrameworkUtils.parseDictDataLabel(
-                DictTypeConstants.MES_QC_CHECK_RESULT, String.valueOf(checkResult));
+                DictTypeConstants.MES_OQC_CHECK_RESULT, String.valueOf(checkResult));
     }
 
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java
index fab9c40..4d1bec6 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java
@@ -127,7 +127,7 @@
 
     @Schema(description = "妫�娴嬬粨鏋�", example = "1")
     @ExcelProperty(value = "妫�娴嬬粨鏋�", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.MES_QC_CHECK_RESULT)
+    @DictFormat(DictTypeConstants.MES_OQC_CHECK_RESULT)
     private Integer checkResult;
 
     // ========== 妫�楠岄」鎸囨爣 ==========
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java
index 718e434..0738fee 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java
@@ -37,8 +37,7 @@
 
     // ========== 瀹㈡埛 ==========
 
-    @Schema(description = "瀹㈡埛 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @NotNull(message = "瀹㈡埛涓嶈兘涓虹┖")
+    @Schema(description = "瀹㈡埛 ID锛屽彲涓虹┖", example = "10")
     private Long clientId;
 
     // ========== 鐗╂枡 ==========
@@ -55,8 +54,7 @@
 
     // ========== 鏁伴噺 ==========
 
-    @Schema(description = "鏈鍑鸿揣鏁伴噺", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
-    @NotNull(message = "鏈鍑鸿揣鏁伴噺涓嶈兘涓虹┖")
+    @Schema(description = "鏈鍑鸿揣鏁伴噺", example = "100")
     @DecimalMin(value = "0", message = "鏈鍑鸿揣鏁伴噺涓嶈兘灏忎簬 0")
     private BigDecimal outQuantity;
 
@@ -77,11 +75,11 @@
 
     // ========== 妫�楠� ==========
 
-    @Schema(description = "妫�娴嬬粨鏋�", example = "1")
+    @Schema(description = "妫�娴嬬粨鏋�", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "妫�娴嬬粨鏋滀笉鑳戒负绌�")
     private Integer checkResult;
 
-    @Schema(description = "鍑鸿揣鏃ユ湡", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "鍑鸿揣鏃ユ湡涓嶈兘涓虹┖")
+    @Schema(description = "鍑鸿揣鏃ユ湡")
     private LocalDateTime outDate;
 
     @Schema(description = "妫�娴嬫棩鏈�", requiredMode = Schema.RequiredMode.REQUIRED)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java
index effe2a5..fd8a276 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java
@@ -41,6 +41,9 @@
     @Schema(description = "鍗曚綅鍚嶇О", example = "涓�")
     private String unitName;
 
+    @Schema(description = "鎵瑰彿锛堝綋鍓嶄粎 IPQC 鏉ユ簮鎻愪緵锛�", example = "BC20250101")
+    private String batchCode;
+
     // ========== 鏁伴噺 ==========
 
     @Schema(description = "寰呮鏁伴噺", example = "100.00")
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java
index f06c921..c309810 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java
@@ -2,9 +2,7 @@
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
@@ -86,32 +84,10 @@
      */
     private String sourceDocCode;
 
-    // ========== 鐢熶骇鍏宠仈 ==========
-
     /**
-     * 鐢熶骇宸ュ崟 ID
-     *
-     * 鍏宠仈 {@link MesProWorkOrderDO#getId()}
+     * 鎵瑰彿
      */
-    private Long workOrderId;
-    /**
-     * 鐢熶骇浠诲姟 ID
-     *
-     * 鍏宠仈 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO#getId()}
-     */
-    private Long taskId;
-    /**
-     * 宸ヤ綅 ID
-     *
-     * 鍏宠仈 {@link MesMdWorkstationDO#getId()}
-     */
-    private Long workstationId;
-    /**
-     * 宸ュ簭 ID
-     *
-     * 鍏宠仈 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO#getId()}
-     */
-    private Long processId;
+    private String batchCode;
 
     // ========== 鐗╂枡 ==========
 
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
index c66a438..724be95 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java
@@ -156,8 +156,8 @@
     /**
      * 妫�娴嬬粨鏋�
      *
-     * 瀛楀吀 {@link DictTypeConstants#MES_QC_CHECK_RESULT}
-     * 鏋氫妇 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum}
+     * 瀛楀吀 {@link DictTypeConstants#MES_OQC_CHECK_RESULT}
+     * 鏋氫妇 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcOqcCheckResultEnum}
      */
     private Integer checkResult;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java
index ef0b02b..163f3ed 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java
@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.mes.dal.dataobject.qc.template;
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -38,7 +37,7 @@
     /**
      * 浜у搧鐗╂枡缂栧彿
      *
-     * 鍏宠仈 {@link MesMdItemDO#getId()}
+     * 鍏宠仈 MDM 鐗╂枡缂栧彿锛坢dm_item.id锛夛紝闈� MES 鐗╂枡
      */
     private Long itemId;
     /**
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java
index 105c503..24185c1 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java
@@ -21,7 +21,7 @@
         return selectPage(reqVO, new LambdaQueryWrapperX<MesQcIpqcDO>()
                 .likeIfPresent(MesQcIpqcDO::getCode, reqVO.getCode())
                 .eqIfPresent(MesQcIpqcDO::getType, reqVO.getType())
-                .eqIfPresent(MesQcIpqcDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .likeIfPresent(MesQcIpqcDO::getBatchCode, reqVO.getBatchCode())
                 .eqIfPresent(MesQcIpqcDO::getItemId, reqVO.getItemId())
                 .eqIfPresent(MesQcIpqcDO::getCheckResult, reqVO.getCheckResult())
                 .eqIfPresent(MesQcIpqcDO::getStatus, reqVO.getStatus())
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java
index 7c175d3..5e562f3 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java
@@ -43,9 +43,12 @@
                 .orderByDesc(MesQcOqcDO::getId);
         if (permittedClientIds != null) {
             if (CollUtil.isEmpty(permittedClientIds)) {
-                return PageResult.empty();
+                wrapper.isNull(MesQcOqcDO::getClientId);
+            } else {
+                // 鍏佽 client_id 涓虹┖鐨勮褰曪紙鏈~瀹㈡埛鐨勬楠屽崟瀵规墍鏈夋湁鏉冮檺鐢ㄦ埛鍙锛�
+                wrapper.and(w -> w.in(MesQcOqcDO::getClientId, permittedClientIds)
+                        .or().isNull(MesQcOqcDO::getClientId));
             }
-            wrapper.in(MesQcOqcDO::getClientId, permittedClientIds);
         }
         return selectPage(reqVO, wrapper);
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
index 71b6607..147f33f 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
@@ -78,7 +78,8 @@
     String MES_IPQC_TYPE = "mes_ipqc_type"; // MES IPQC 妫�楠岀被鍨�
     String MES_RQC_TYPE = "mes_rqc_type"; // MES 閫�璐ф楠岀被鍨�
     String MES_ORDER_STATUS = "mes_order_status"; // MES 鍗曟嵁鐘舵�侊紙IQC/IPQC/OQC/RQC 閫氱敤锛�
-    String MES_QC_CHECK_RESULT = "mes_qc_check_result"; // MES 妫�娴嬬粨鏋�
+    String MES_QC_CHECK_RESULT = "mes_qc_check_result"; // MES 妫�娴嬬粨鏋滐紙IQC/IPQC/RQC 鍏辩敤锛�
+    String MES_OQC_CHECK_RESULT = "mes_oqc_check_result"; // MES 鍑鸿揣妫�楠屾娴嬬粨鏋滐紙OQC 涓撶敤锛�
     String MES_QC_SOURCE_DOC_TYPE = "mes_qc_source_doc_type"; // MES 鏉ユ簮鍗曟嵁绫诲瀷
     String MES_NCR_STATUS = "mes_ncr_status"; // MES NCR 鐘舵��
     String MES_NCR_DISPOSITION = "mes_ncr_disposition"; // MES NCR 澶勭疆鏂瑰紡
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcOqcCheckResultEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcOqcCheckResultEnum.java
new file mode 100644
index 0000000..19b45b2
--- /dev/null
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcOqcCheckResultEnum.java
@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.mes.enums.qc;
+
+import cn.iocoder.yudao.framework.common.core.ArrayValuable;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Arrays;
+
+/**
+ * MES 鍑鸿揣妫�楠屽崟妫�娴嬬粨鏋滄灇涓撅紙OQC 涓撶敤锛�
+ *
+ * <p>涓� IQC/IPQC/RQC 鍏辩敤鐨� {@link MesQcCheckResultEnum} 涓嶅悓锛屽嚭璐ф楠屾寜浜у搧绛夌骇鍒ゅ畾锛�
+ * 瀛楀吀 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_OQC_CHECK_RESULT}</p>
+ */
+@Getter
+@AllArgsConstructor
+public enum MesQcOqcCheckResultEnum implements ArrayValuable<Integer> {
+
+    TYPE_1(1, "1鍨�"),
+    TYPE_2(2, "2鍨�"),
+    SCRAP(3, "搴熷搧");
+
+    public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcOqcCheckResultEnum::getType).toArray(Integer[]::new);
+
+    /**
+     * 缁撴灉鍊�
+     */
+    private final Integer type;
+    /**
+     * 缁撴灉鍚�
+     */
+    private final String name;
+
+    @Override
+    public Integer[] array() {
+        return ARRAYS;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鍙互鏀捐鍙戣揣
+     *
+     * <p>1 鍨嬨��2 鍨嬪潎涓哄彲鍙戣揣绛夌骇锛屼粎搴熷搧涓嶆斁琛�</p>
+     *
+     * @param type 妫�娴嬬粨鏋�
+     * @return true 鍙互鏀捐
+     */
+    public static boolean canShip(Integer type) {
+        return type != null && !SCRAP.getType().equals(type);
+    }
+
+}
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/ai/MesProAiServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/ai/MesProAiServiceImpl.java
index 208b2d9..00591b4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/ai/MesProAiServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/ai/MesProAiServiceImpl.java
@@ -19,7 +19,6 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.dv.machinery.MesDvMachineryMapper;
 import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMachineMapper;
@@ -28,7 +27,6 @@
 import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskIssueMapper;
 import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper;
 import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderBomMapper;
-import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper;
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper;
 import cn.iocoder.yudao.module.mes.service.pro.mps.MesProMpsService;
 import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
@@ -101,14 +99,13 @@
             浣犻渶瑕佺患鍚堝垎鏋愪互涓嬩俊鎭紝缁欏嚭涓撲笟鐨勯闄╄瘎浼帮細
 
             ## 鍒嗘瀽缁村害
-            1. 璐ㄩ噺椋庨櫓锛氳繃绋嬫楠�(IPQC)鐨勭己闄风巼鏁版嵁锛堣嚧鍛�/涓ラ噸/杞诲井缂洪櫡鐜囷級
-            2. 璁惧椋庨櫓锛氳澶囩姸鎬併�佷笂娆′繚鍏绘椂闂淬�佷笂娆$偣妫�鏃堕棿銆佺敓浜ф晥鐜�
-            3. 鐗╂枡椋庨櫓锛氱墿鏂欏簱瀛樺彲鐢ㄩ噺涓庨渶姹傞噺鐨勫姣�
-            4. 宸ヨ壓鐡堕锛氬叧閿伐搴忕殑璁惧浜ц兘銆佷换鍔℃帓闃熸儏鍐�
+            1. 璁惧椋庨櫓锛氳澶囩姸鎬併�佷笂娆′繚鍏绘椂闂淬�佷笂娆$偣妫�鏃堕棿銆佺敓浜ф晥鐜�
+            2. 鐗╂枡椋庨櫓锛氱墿鏂欏簱瀛樺彲鐢ㄩ噺涓庨渶姹傞噺鐨勫姣�
+            3. 宸ヨ壓鐡堕锛氬叧閿伐搴忕殑璁惧浜ц兘銆佷换鍔℃帓闃熸儏鍐�
 
             ## 椋庨櫓绛夌骇瀹氫箟
-            - 楂橈細瀛樺湪鑷村懡缂洪櫡鐜�>5% 鎴� 璁惧鏁呴殰 鎴� 鍏抽敭鐗╂枡鐭己>50% 鎴� 鍏抽敭宸ュ簭涓ラ噸绉帇
-            - 涓細瀛樺湪涓ラ噸缂洪櫡鐜�>10% 鎴� 璁惧闀挎湡鏈繚鍏� 鎴� 鐗╂枡绱у紶
+            - 楂橈細瀛樺湪璁惧鏁呴殰 鎴� 鍏抽敭鐗╂枡鐭己>50% 鎴� 鍏抽敭宸ュ簭涓ラ噸绉帇
+            - 涓細瀛樺湪璁惧闀挎湡鏈繚鍏� 鎴� 鐗╂枡绱у紶
             - 浣庯細鍚勯」鎸囨爣姝e父
 
             ## 杈撳嚭鏍煎紡
@@ -118,7 +115,7 @@
             overallRiskLevel 鍙栧�硷細1=浣庨闄� 2=涓闄� 3=楂橀闄�
             riskLevel 鍙栧�硷細鍏呰冻/绱у紶/鐭己
             severity 鍙栧�硷細楂�/涓�/浣�
-            category 鍙栧�硷細璐ㄩ噺/璁惧/鐗╂枡/宸ヨ壓鐡堕
+            category 鍙栧�硷細璁惧/鐗╂枡/宸ヨ壓鐡堕
             """;
 
     private static final String SYSTEM_PROMPT_DELIVERY = """
@@ -159,8 +156,6 @@
     private MesProTaskIssueMapper taskIssueMapper;
     @Resource
     private MesProFeedbackMapper feedbackMapper;
-    @Resource
-    private MesQcIpqcMapper ipqcMapper;
     @Resource
     private MesWmMaterialStockMapper materialStockMapper;
     @Resource
@@ -523,26 +518,6 @@
         data.put("璁″垝鏁伴噺", workOrder.getQuantity());
         data.put("宸茬敓浜ф暟閲�", workOrder.getQuantityProduced());
         fillItemInfo(data, workOrder.getProductId());
-
-        // 璐ㄩ噺椋庨櫓 - IPQC
-        List<MesQcIpqcDO> ipqcList = ipqcMapper.selectList(
-                new LambdaQueryWrapper<MesQcIpqcDO>()
-                        .eq(MesQcIpqcDO::getWorkOrderId, workOrderId));
-        if (CollUtil.isNotEmpty(ipqcList)) {
-            List<Map<String, Object>> qcData = ipqcList.stream().map(ipqc -> {
-                Map<String, Object> item = new LinkedHashMap<>();
-                item.put("妫�楠屽崟缂栧彿", ipqc.getCode());
-                item.put("鑷村懡缂洪櫡鐜�", ipqc.getCriticalRate() != null ? ipqc.getCriticalRate() + "%" : "0%");
-                item.put("涓ラ噸缂洪櫡鐜�", ipqc.getMajorRate() != null ? ipqc.getMajorRate() + "%" : "0%");
-                item.put("杞诲井缂洪櫡鐜�", ipqc.getMinorRate() != null ? ipqc.getMinorRate() + "%" : "0%");
-                item.put("鑷村懡缂洪櫡鏁�", ipqc.getCriticalQuantity() != null ? ipqc.getCriticalQuantity() : 0);
-                item.put("涓ラ噸缂洪櫡鏁�", ipqc.getMajorQuantity() != null ? ipqc.getMajorQuantity() : 0);
-                item.put("杞诲井缂洪櫡鏁�", ipqc.getMinorQuantity() != null ? ipqc.getMinorQuantity() : 0);
-                item.put("妫�楠岀粨鏋�", ipqc.getCheckResult());
-                return item;
-            }).collect(Collectors.toList());
-            data.put("杩囩▼妫�楠�(IPQC)璁板綍", qcData);
-        }
 
         // 璁惧椋庨櫓
         List<MesProTaskDO> tasks = taskMapper.selectListByWorkOrderId(workOrderId);
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ai/MesQcAiServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ai/MesQcAiServiceImpl.java
index 2005d29..907a1ea 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ai/MesQcAiServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ai/MesQcAiServiceImpl.java
@@ -141,8 +141,7 @@
             data.put("妫�娴嬫暟閲�", ipqc.getCheckQuantity());
             data.put("鍚堟牸鏁伴噺", ipqc.getQualifiedQuantity());
             data.put("涓嶅悎鏍兼暟閲�", ipqc.getUnqualifiedQuantity());
-            data.put("宸ュ崟ID", ipqc.getWorkOrderId());
-            data.put("宸ュ簭ID", ipqc.getProcessId());
+            data.put("鎵瑰彿", ipqc.getBatchCode());
             fillItemInfo(data, ipqc.getItemId());
         } else if (MesBizTypeConstants.QC_OQC == qcType) {
             data.put("璐ㄦ绫诲瀷", "鍑鸿揣妫�楠�");
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilder.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilder.java
index bee442a..1fca7f8 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilder.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilder.java
@@ -18,7 +18,7 @@
  * 浜у搧妫�楠屽崟锛堢焊璐�"脳脳浜у搧璐ㄩ噺妫�楠屽崟"鐗堝紡锛塛ord 鏋勫缓鍣�
  *
  * 鐗堝紡锛氭爣棰橈紙鍏徃 + 浜у搧妫�楠屽崟锛夆啋 琛ㄥご淇℃伅 5 琛� 鈫� 妫�楠岄」鐩�/妫�楠岀粨鏋� 涓ゅ垪鐭╅樀 鈫�
- * 鍒ゅ畾缁撹/璐ㄦ涓撶敤绔狅紙鐣欑┖锛屾墦鍗板悗鎵嬪~锛夆啋 澶囨敞 鈫� 妫�楠�/澶嶆牳/鎵瑰噯绛惧瓧琛屻��
+ * 鍒ゅ畾缁撹锛堣嚜鍔ㄥ甫鍑烘楠岀粨鏋滐級/璐ㄦ涓撶敤绔狅紙鐣欑┖鐩栫珷锛夆啋 澶囨敞 鈫� 妫�楠�/澶嶆牳/鎵瑰噯绛惧瓧琛屻��
  * 涓嶅惈鎶�鏈寚鏍囧垪锛涘垎缁勯」涓嶅睍绀猴紝褰曞叆椤瑰钩閾猴紱骞宠娴嬮噺澶氬�奸】鍙峰悎骞躲��
  */
 public class MesQcProductReportWordBuilder {
@@ -51,7 +51,7 @@
             writeTitle(doc, report);
             writeHeaderTable(doc, report);
             writeItemTable(doc, report);
-            writeConclusionTable(doc);
+            writeConclusionTable(doc, report);
             writeRemarkTable(doc, report);
             writeSignLine(doc);
             doc.write(out);
@@ -150,12 +150,14 @@
                 .orElse(EMPTY);
     }
 
-    // ========== 鍒ゅ畾缁撹 / 璐ㄦ涓撶敤绔狅紙鐣欑┖鍚庡~锛� ==========
+    // ========== 鍒ゅ畾缁撹 / 璐ㄦ涓撶敤绔� ==========
 
-    private static XWPFTable writeConclusionTable(XWPFDocument doc) {
+    /** 鍒ゅ畾缁撹鑷姩甯﹀嚭妫�楠岀粨鏋滄枃妗堬紱璐ㄦ涓撶敤绔犵暀绌猴紝鎵撳嵃鍚庝汉宸ョ洊绔� */
+    private static XWPFTable writeConclusionTable(XWPFDocument doc, MesQcQcReportRespVO report) {
         XWPFTable table = createTable(doc);
-        XWPFTableRow row = addRow(table, valueLeftSpan("鍒ゅ畾缁撹锛�", 2), valueLeftSpan("璐ㄦ涓撶敤绔狅細", 2));
-        // 棰勭暀鎵嬪啓/鐩栫珷楂樺害
+        String conclusion = notBlank(report.getCheckResultText()) ? report.getCheckResultText() : "";
+        XWPFTableRow row = addRow(table, valueLeftSpan("鍒ゅ畾缁撹锛�" + conclusion, 2), valueLeftSpan("璐ㄦ涓撶敤绔狅細", 2));
+        // 棰勭暀鐩栫珷楂樺害
         setRowHeight(row, 2550);
         return table;
     }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcReportServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcReportServiceImpl.java
index e6245ab..5280cde 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcReportServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcReportServiceImpl.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.mes.service.qc.indicatorresult;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcQcReportRespVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
@@ -14,6 +15,7 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO;
+import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcIndicatorItemTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
@@ -231,10 +233,23 @@
                 report.setApproveName(userMap.get(report.getApproveUserId()).getNickname());
             }
         }
+        report.setCheckResultText(resolveCheckResultText(qcType, report.getCheckResult()));
         return report;
     }
 
     /**
+     * 妫�娴嬬粨鏋滄枃妗堬細OQC 鎸変骇鍝佺瓑绾у垽瀹氾紙mes_oqc_check_result锛夛紝鍏朵綑璧伴�氱敤妫�娴嬬粨鏋滃瓧鍏革紙mes_qc_check_result锛�
+     */
+    private String resolveCheckResultText(Integer qcType, Integer checkResult) {
+        if (checkResult == null) {
+            return null;
+        }
+        String dictType = Objects.equals(qcType, MesQcTypeEnum.OQC.getType())
+                ? DictTypeConstants.MES_OQC_CHECK_RESULT : DictTypeConstants.MES_QC_CHECK_RESULT;
+        return DictFrameworkUtils.parseDictDataLabel(dictType, String.valueOf(checkResult));
+    }
+
+    /**
      * 缁勮鎶ュ憡妫�楠岄」鏍戯紱椤哄甫鏀堕泦鍏ㄥ眬 measureNos 鍒楀ご
      */
     private List<MesQcQcReportRespVO.ReportItem> buildReportItems(
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
index 47e9ed3..1096ea4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -10,10 +10,6 @@
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
-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.pro.feedback.MesProFeedbackDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO;
@@ -23,15 +19,8 @@
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
-import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
-import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
-import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
 import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService;
-import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
-import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService;
-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.qc.defectrecord.MesQcDefectRecordService;
 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
@@ -39,6 +28,7 @@
 import cn.iocoder.yudao.module.mes.controller.admin.qc.ncr.vo.MesQcNcrSaveReqVO;
 import cn.iocoder.yudao.module.mes.service.qc.ncr.MesQcNcrService;
 import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
@@ -65,14 +55,6 @@
 @Slf4j
 public class MesQcIpqcServiceImpl implements MesQcIpqcService {
 
-    /**
-     * IPQC 淇濆瓨鏁版嵁鏍¢獙涓婁笅鏂�
-     *
-     * @param workstation 宸ヤ綅
-     * @param task        鐢熶骇浠诲姟锛堝彲閫夛紝鎸囧畾 taskId 鏃堕潪绌猴級
-     */
-    private record SaveDataContext(MesMdWorkstationDO workstation, MesProTaskDO task) {}
-
     @Resource
     private MesQcIpqcMapper ipqcMapper;
 
@@ -85,25 +67,7 @@
     private MesQcIpqcLineService ipqcLineService;
     @Resource
     @Lazy
-    private MesProWorkOrderService workOrderService;
-    @Resource
-    @Lazy
-    private MesMdWorkstationService workstationService;
-    @Resource
-    @Lazy
-    private MesMdItemService itemService;
-    @Resource
-    @Lazy
     private MesQcDefectRecordService defectRecordService;
-    @Resource
-    @Lazy
-    private MesProRouteProductService routeProductService;
-    @Resource
-    @Lazy
-    private MesProRouteProcessService routeProcessService;
-    @Resource
-    @Lazy
-    private MesProTaskService taskService;
     @Resource
     @Lazy
     private MesProFeedbackService feedbackService;
@@ -121,18 +85,18 @@
     @Resource
     private AdminUserApi adminUserApi;
 
+    @Resource
+    private MdmItemApi mdmItemApi;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createIpqc(MesQcIpqcSaveReqVO createReqVO) {
         // 1.1 鏍¢獙鏁版嵁
-        SaveDataContext ctx = validateIpqcSaveData(createReqVO);
-        // 1.2 鏍¢獙宸ュ崟瀛樺湪
-        MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId());
-        // 1.3 纭畾妫�楠岀墿鏂欙細鏈変换鍔℃椂鍙栦换鍔$殑鐗╂枡锛屾棤浠诲姟鏃跺彇宸ュ崟鐨勪骇鍝�
-        Long itemId = (ctx.task() != null) ? ctx.task().getItemId() : workOrder.getProductId();
-        // 1.4 鏍规嵁鐗╂枡 + IPQC 绫诲瀷鏌ユ壘鍙敤璐ㄦ鏂规锛堟敮鎸佸墠绔樉寮忔寚瀹氾級
+        validateIpqcSaveData(createReqVO);
+        // 1.2 鏍规嵁浜у搧鐗╂枡 + IPQC 绫诲瀷鏌ユ壘鍙敤璐ㄦ鏂规锛堟敮鎸佸墠绔樉寮忔寚瀹氾級
+        // 鐗╂枡 ID 鏉ヨ嚜 MDM锛屾ā鏉挎湇鍔$洿鎺ユ寜 MDM 鐗╂枡鍖归厤
         List<MesQcTemplateItemDO> templateItems = templateItemService.getTemplateItemList(
-                itemId, MesQcTypeEnum.IPQC.getType(), null, null);
+                createReqVO.getItemId(), MesQcTypeEnum.IPQC.getType(), null, null);
         if (CollUtil.isEmpty(templateItems)) {
             throw exception(QC_NO_TEMPLATE);
         }
@@ -146,14 +110,12 @@
             }
         }
         Long templateId = templateItem.getTemplateId();
-        // 1.5 鑾峰彇鏉ユ簮鍗曟嵁缂栧彿
+        // 1.3 鑾峰彇鏉ユ簮鍗曟嵁缂栧彿
         String sourceDocCode = validateAndGetSourceDocCode(
                 createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId());
 
         // 2. 鎻掑叆涓昏〃
         MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class)
-                .setItemId(itemId)
-                .setProcessId(getProcessId(itemId, ctx.workstation().getProcessId()))
                 .setTemplateId(templateId)
                 .setSourceDocCode(sourceDocCode)
                 .setStatus(MesQcStatusEnum.DRAFT.getStatus());
@@ -176,60 +138,23 @@
         // 1.1 鏍¢獙瀛樺湪 + 鑽夌鐘舵��
         validateIpqcStatusPrepare(updateReqVO.getId());
         // 1.2 鏍¢獙鏁版嵁
-        SaveDataContext ctx = validateIpqcSaveData(updateReqVO);
+        validateIpqcSaveData(updateReqVO);
 
         // 2. 鏇存柊涓昏〃
-        MesQcIpqcDO existIpqc = validateIpqcExists(updateReqVO.getId());
         MesQcIpqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIpqcDO.class);
         updateObj.setSourceDocType(null).setSourceDocId(null).setSourceLineId(null); // 涓嶅厑璁镐慨鏀规潵婧愬崟鎹�
         updateObj.setTemplateId(null); // 涓嶅厑璁镐慨鏀规ā鏉�
         updateObj.setItemId(null); // 涓嶅厑璁镐慨鏀圭墿鏂�
-        updateObj.setWorkOrderId(null); // 涓嶅厑璁镐慨鏀瑰伐鍗�
-        updateObj.setProcessId(getProcessId(existIpqc.getItemId(), ctx.workstation().getProcessId()));
         ipqcMapper.updateById(updateObj);
     }
 
-    private SaveDataContext validateIpqcSaveData(MesQcIpqcSaveReqVO reqVO) {
+    private void validateIpqcSaveData(MesQcIpqcSaveReqVO reqVO) {
         // 鏍¢獙缂栧彿鍞竴
         validateIpqcCodeUnique(reqVO.getId(), reqVO.getCode());
-        // 鏍¢獙宸ヤ綅銆佹娴嬩汉鍛樺瓨鍦�
-        MesMdWorkstationDO workstation = workstationService.validateWorkstationExists(reqVO.getWorkstationId());
+        // 鏍¢獙鐗╂枡銆佹娴嬩汉鍛樺瓨鍦�
+        // 娉細鐗╂枡 ID 鏉ヨ嚜 MDM
+        mdmItemApi.validateItemExists(reqVO.getItemId());
         adminUserApi.validateUser(reqVO.getInspectorUserId());
-        // 鏍¢獙宸ュ崟瀛樺湪
-        MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
-        if (reqVO.getProcessId() != null && ObjUtil.notEqual(workstation.getProcessId(), reqVO.getProcessId())) {
-            throw exception(PRO_WORKSTATION_PROCESS_MISMATCH);
-        }
-        // 鏍¢獙浠诲姟鍏崇郴锛堝鏋滄寚瀹氫簡浠诲姟锛�
-        MesProTaskDO task = null;
-        if (reqVO.getTaskId() != null) {
-            task = taskService.validateTaskNotFinished(reqVO.getTaskId());
-            validateTaskRelation(task, workstation, workOrder, reqVO);
-        } else {
-            // 鏃犱换鍔℃椂锛宨temId 浠嶉渶涓庡伐鍗曚骇鍝佷竴鑷�
-            if (reqVO.getItemId() != null && ObjUtil.notEqual(reqVO.getItemId(), workOrder.getProductId())) {
-                throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH);
-            }
-        }
-        return new SaveDataContext(workstation, task);
-    }
-
-    private void validateTaskRelation(MesProTaskDO task, MesMdWorkstationDO workstation,
-                                      MesProWorkOrderDO workOrder, MesQcIpqcSaveReqVO reqVO) {
-        if (ObjUtil.notEqual(task.getWorkOrderId(), workOrder.getId())) {
-            throw exception(PRO_TASK_WORK_ORDER_MISMATCH);
-        }
-        if (ObjUtil.notEqual(task.getWorkstationId(), workstation.getId())) {
-            throw exception(PRO_TASK_WORKSTATION_MISMATCH);
-        }
-        Long expectedProcessId = reqVO.getProcessId() != null ? reqVO.getProcessId() : workstation.getProcessId();
-        if (expectedProcessId != null && ObjUtil.notEqual(task.getProcessId(), expectedProcessId)) {
-            throw exception(PRO_TASK_ROUTE_PROCESS_MISMATCH);
-        }
-        // 鏍¢獙妫�楠岀墿鏂欎笌浠诲姟鐗╂枡涓�鑷达紙鏈変换鍔℃椂锛孖PQC 妫�楠岀殑鐗╂枡搴斾笌浠诲姟鍔犲伐鐨勭墿鏂欎竴鑷达級
-        if (reqVO.getItemId() != null && ObjUtil.notEqual(reqVO.getItemId(), task.getItemId())) {
-            throw exception(PRO_TASK_ITEM_MISMATCH);
-        }
     }
 
     @Override
@@ -290,21 +215,8 @@
         // 1. 纭畾 sourceDocType/sourceDocId
         Long sourceDocId = ipqc.getSourceDocId();
         Long sourceLineId = ipqc.getSourceLineId();
-
-        // 濡傛灉 IPQC 鍗曟病鏈夎缃潵婧愶紝灏濊瘯閫氳繃 taskId 鏌ユ壘鍏宠仈鐨勫緟妫�楠屾姤宸�
-        if (sourceDocId == null && ipqc.getTaskId() != null) {
-            MesProFeedbackDO feedback = feedbackService.getFeedbackListByTaskId(ipqc.getTaskId()).stream()
-                    .filter(f -> MesProFeedbackStatusEnum.UNCHECK.getStatus().equals(f.getStatus()))
-                    .findFirst().orElse(null);
-            if (feedback != null) {
-                sourceDocId = feedback.getId();
-                log.info("[writeBackSourceDoc] IPQC({}) 鏈缃潵婧愬崟鎹紝閫氳繃 taskId({}) 鎵惧埌寰呮楠屾姤宸�({})",
-                        ipqc.getId(), ipqc.getTaskId(), feedback.getId());
-            }
-        }
-
         if (sourceDocId == null) {
-            log.warn("[writeBackSourceDoc] IPQC({}) 鏃犳硶纭畾鏉ユ簮鎶ュ伐锛岃烦杩囧洖鍐�", ipqc.getId());
+            log.warn("[writeBackSourceDoc] IPQC({}) 鏈缃潵婧愭姤宸ワ紝璺宠繃鍥炲啓", ipqc.getId());
             return;
         }
 
@@ -388,33 +300,6 @@
         }
         // 鏈煡鏉ユ簮绫诲瀷搴旀姤閿欙紝鑰屼笉鏄潤榛樺拷鐣�
         throw exception(QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN);
-    }
-
-    /**
-     * 鎺ㄥ宸ュ簭 ID
-     *
-     * <p>閫氳繃浜у搧 鈫� 宸ヨ壓璺嚎浜у搧 鈫� 宸ヨ壓璺嚎 鈫� 鏍¢獙宸ヤ綅宸ュ簭鏄惁鍦ㄨ璺嚎涓�
-     * <p>濡傛灉宸ヤ綅鐨勫伐搴忓湪璺嚎涓紝鍒欒繑鍥炶 processId锛涘惁鍒欒繑鍥� null
-     *
-     * @param productId 浜у搧 ID锛堝伐鍗曚骇鍝侊級
-     * @param workstationProcessId 宸ヤ綅鍏宠仈鐨勫伐搴� ID
-     * @return 鎺ㄥ鍑虹殑宸ュ簭 ID锛屾棤娉曟帹瀵兼椂杩斿洖 null
-     */
-    private Long getProcessId(Long productId, Long workstationProcessId) {
-        if (productId == null || workstationProcessId == null) {
-            return null;
-        }
-        // 1. 浜у搧 鈫� 宸ヨ壓璺嚎
-        MesProRouteProductDO routeProduct = routeProductService.getRouteProductByItemId(productId);
-        if (routeProduct == null) {
-            return null;
-        }
-        // 2. 鏍¢獙宸ヤ綅鐨勫伐搴忔槸鍚﹀湪璇ヨ矾绾夸腑
-        if (routeProcessService.getRouteProcessByRouteIdAndProcessId(
-                routeProduct.getRouteId(), workstationProcessId) == null) {
-            return null;
-        }
-        return workstationProcessId;
     }
 
     @Override
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java
index 4a6ab79..1dba9d4 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java
@@ -64,21 +64,21 @@
     /**
      * 鏍规嵁浜у搧鐗╂枡 ID 鍜� QC 绫诲瀷鏌ユ壘妫�楠屾ā鏉跨殑浜у搧鍏宠仈锛堝繀椤诲瓨鍦紝鍚﹀垯鎶涘紓甯革級
      *
-     * @param itemId 浜у搧鐗╂枡 ID
-     * @param qcType 妫�娴嬬绫伙紙鏋氫妇 {@link MesQcTypeEnum}锛�
+     * @param mdmItemId MDM 浜у搧鐗╂枡 ID锛坢dm_item.id锛�
+     * @param qcType    妫�娴嬬绫伙紙鏋氫妇 {@link MesQcTypeEnum}锛�
      * @return 鍖归厤鐨勪骇鍝佸叧鑱�
      */
-    MesQcTemplateItemDO getRequiredTemplateByItemIdAndType(Long itemId, Integer qcType);
+    MesQcTemplateItemDO getRequiredTemplateByItemIdAndType(Long mdmItemId, Integer qcType);
 
     /**
      * 鏍规嵁浜у搧鐗╂枡锛堟垨宸ュ崟/浠诲姟锛夊拰 QC 绫诲瀷锛岃幏鍙栨墍鏈夊彲鐢ㄧ殑璐ㄦ鏂规浜у搧鍏宠仈鍒楄〃
      *
-     * @param itemId      浜у搧鐗╂枡 ID锛坢es_md_item.id锛夛紱涓� workOrderId/taskId 鑷冲皯鍏朵竴
+     * @param mdmItemId   MDM 浜у搧鐗╂枡 ID锛坢dm_item.id锛夛紱涓� workOrderId/taskId 鑷冲皯鍏朵竴
      * @param qcType      妫�娴嬬绫伙紙鏋氫妇 {@link MesQcTypeEnum}锛�
-     * @param workOrderId 鐢熶骇宸ュ崟 ID锛堝彲閫夛紝IPQC 鍦烘櫙鐢ㄤ簬瑙f瀽浜у搧鐗╂枡锛�
-     * @param taskId      鐢熶骇浠诲姟 ID锛堝彲閫夛紝浼樺厛鐢ㄤ簬瑙f瀽浜у搧鐗╂枡锛�
+     * @param workOrderId 鐢熶骇宸ュ崟 ID锛堝彲閫夛紝IPQC 鍦烘櫙鐢ㄤ簬瑙f瀽浜у搧鐗╂枡锛涘伐鍗曚骇鍝佷负 MES 鐗╂枡锛屽唴閮ㄨ浆鎹负 MDM 鐗╂枡锛�
+     * @param taskId      鐢熶骇浠诲姟 ID锛堝彲閫夛紝浼樺厛鐢ㄤ簬瑙f瀽浜у搧鐗╂枡锛涗换鍔$墿鏂欎负 MES 鐗╂枡锛屽唴閮ㄨ浆鎹负 MDM 鐗╂枡锛�
      * @return 鍖归厤鐨勪骇鍝佸叧鑱斿垪琛紙淇濇寔鍘熼『搴忥級锛屾棤鍖归厤杩斿洖绌哄垪琛�
      */
-    List<MesQcTemplateItemDO> getTemplateItemList(Long itemId, Integer qcType, Long workOrderId, Long taskId);
+    List<MesQcTemplateItemDO> getTemplateItemList(Long mdmItemId, Integer qcType, Long workOrderId, Long taskId);
 
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java
index 712c693..8ff8e40 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java
@@ -126,8 +126,8 @@
     }
 
     @Override
-    public MesQcTemplateItemDO getRequiredTemplateByItemIdAndType(Long itemId, Integer qcType) {
-        List<MesQcTemplateItemDO> templateItems = getTemplateItemList(itemId, qcType, null, null);
+    public MesQcTemplateItemDO getRequiredTemplateByItemIdAndType(Long mdmItemId, Integer qcType) {
+        List<MesQcTemplateItemDO> templateItems = getTemplateItemList(mdmItemId, qcType, null, null);
         if (CollUtil.isEmpty(templateItems)) {
             throw exception(QC_NO_TEMPLATE);
         }
@@ -135,28 +135,27 @@
     }
 
     @Override
-    public List<MesQcTemplateItemDO> getTemplateItemList(Long itemId, Integer qcType, Long workOrderId, Long taskId) {
-        // 1. 瑙f瀽鐪熷疄浜у搧鐗╂枡 ID锛氫换鍔′紭鍏堬紝鍏舵宸ュ崟锛屾渶鍚庣洿鎺ョ敤鍏ュ弬
-        Long resolvedItemId = itemId;
+    public List<MesQcTemplateItemDO> getTemplateItemList(Long mdmItemId, Integer qcType, Long workOrderId, Long taskId) {
+        // 1. 瑙f瀽 MDM 浜у搧鐗╂枡 ID锛氫换鍔′紭鍏堬紝鍏舵宸ュ崟锛涗袱鑰呭瓨鐨勬槸 MES 鐗╂枡 ID锛岄渶杞崲涓� MDM 鐗╂枡 ID銆�
+        //    鏈紶宸ュ崟/浠诲姟鏃讹紝鍏ュ弬鏈韩鍗� MDM 鐗╂枡 ID锛堣川妫�鍗曞墠绔�夋嫨鐨勫氨鏄� MDM 鐗╂枡锛�
+        Long resolvedMdmItemId;
         if (taskId != null) {
-            resolvedItemId = proTaskService.validateTaskExists(taskId).getItemId();
+            resolvedMdmItemId = convertMesItemIdToMdmItemId(proTaskService.validateTaskExists(taskId).getItemId());
         } else if (workOrderId != null) {
-            resolvedItemId = proWorkOrderService.validateWorkOrderExists(workOrderId).getProductId();
+            resolvedMdmItemId = convertMesItemIdToMdmItemId(
+                    proWorkOrderService.validateWorkOrderExists(workOrderId).getProductId());
+        } else {
+            resolvedMdmItemId = mdmItemId;
         }
-        if (resolvedItemId == null) {
+        if (resolvedMdmItemId == null) {
             return Collections.emptyList();
         }
-        // 2. mes_md_item.id 杞� mdm_item.id锛堜骇鍝佸叧鑱旇〃瀛樼殑鏄� mdm 鐗╂枡锛�
-        MesMdItemDO item = mesMdItemService.getItem(resolvedItemId);
-        if (item == null || item.getMdmItemId() == null) {
-            return Collections.emptyList();
-        }
-        // 3. 鏌ュ嚭璇ョ墿鏂欏叧鑱旂殑鎵�鏈変骇鍝佸叧鑱�
-        List<MesQcTemplateItemDO> templateItems = templateItemMapper.selectListByItemId(item.getMdmItemId());
+        // 2. 鏌ュ嚭璇ョ墿鏂欏叧鑱旂殑鎵�鏈変骇鍝佸叧鑱�
+        List<MesQcTemplateItemDO> templateItems = templateItemMapper.selectListByItemId(resolvedMdmItemId);
         if (CollUtil.isEmpty(templateItems)) {
             return Collections.emptyList();
         }
-        // 4. 杩囨护锛氭柟妗堝惎鐢ㄤ笖妫�娴嬬绫诲寘鍚� qcType锛岃繑鍥炲叏閮ㄥ尮閰嶉」
+        // 3. 杩囨护锛氭柟妗堝惎鐢ㄤ笖妫�娴嬬绫诲寘鍚� qcType锛岃繑鍥炲叏閮ㄥ尮閰嶉」
         List<MesQcTemplateDO> templates = templateService.getTemplateList(
                 convertSet(templateItems, MesQcTemplateItemDO::getTemplateId));
         Set<Long> matchedTemplateIds = templates.stream()
@@ -169,4 +168,18 @@
                 .collect(Collectors.toList());
     }
 
+    /**
+     * MES 鐗╂枡 ID 杞� MDM 鐗╂枡 ID
+     *
+     * @param mesItemId MES 鐗╂枡 ID锛坢es_md_item.id锛�
+     * @return MDM 鐗╂枡 ID锛坢dm_item.id锛夛紱MES 鐗╂枡涓嶅瓨鍦ㄦ垨鏈叧鑱� MDM 鐗╂枡鏃惰繑鍥� null
+     */
+    private Long convertMesItemIdToMdmItemId(Long mesItemId) {
+        if (mesItemId == null) {
+            return null;
+        }
+        MesMdItemDO item = mesMdItemService.getItem(mesItemId);
+        return item != null ? item.getMdmItemId() : null;
+    }
+
 }
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
index 30303e7..247a487 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
@@ -10,7 +10,7 @@
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper;
-import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum;
+import cn.iocoder.yudao.module.mes.enums.qc.MesQcOqcCheckResultEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
 import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
 import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService;
@@ -232,8 +232,8 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void updateProductSalesLineWhenOqcFinish(Long id, Long oqcId, Integer checkResult) {
-        // 1. 鏇存柊琛岀殑 oqcId + qualityStatus
-        Integer qualityStatus = Objects.equals(checkResult, MesQcCheckResultEnum.QUALIFIED.getType())
+        // 1. 鏇存柊琛岀殑 oqcId + qualityStatus锛�1鍨�/2鍨嬫斁琛岋紝搴熷搧鍒や笉鍚堟牸锛�
+        Integer qualityStatus = MesQcOqcCheckResultEnum.canShip(checkResult)
                 ? MesWmQualityStatusEnum.PASS.getStatus() : MesWmQualityStatusEnum.FAIL.getStatus();
         productSalesLineMapper.updateById(new MesWmProductSalesLineDO()
                 .setId(id).setOqcId(oqcId).setQualityStatus(qualityStatus));
diff --git a/yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml b/yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml
index ab88c74..7928816 100644
--- a/yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml
+++ b/yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml
@@ -22,6 +22,7 @@
                 n.arrival_date AS recordTime,
                 ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@IQC.type} AS qcType,
                 l.item_id AS itemId,
+                NULL AS batchCode,
                 l.arrival_quantity AS quantity,
                 n.vendor_id AS vendorId,
                 NULL AS workOrderId,
@@ -47,6 +48,7 @@
                 r.receipt_date AS recordTime,
                 ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@IQC.type} AS qcType,
                 rl.item_id AS itemId,
+                NULL AS batchCode,
                 rl.quantity AS quantity,
                 r.vendor_id AS vendorId,
                 NULL AS workOrderId,
@@ -72,6 +74,7 @@
                 pf.feedback_time AS recordTime,
                 ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@IPQC.type} AS qcType,
                 ppl.item_id AS itemId,
+                ppl.batch_code AS batchCode,
                 ppl.quantity AS quantity,
                 NULL AS vendorId,
                 pf.work_order_id AS workOrderId,
@@ -97,6 +100,7 @@
                 s.sales_date AS recordTime,
                 ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@OQC.type} AS qcType,
                 sl.item_id AS itemId,
+                NULL AS batchCode,
                 sl.quantity AS quantity,
                 NULL AS vendorId,
                 NULL AS workOrderId,
@@ -122,6 +126,7 @@
                 ri.return_date AS recordTime,
                 ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@RQC.type} AS qcType,
                 ril.item_id AS itemId,
+                NULL AS batchCode,
                 ril.quantity AS quantity,
                 NULL AS vendorId,
                 ri.work_order_id AS workOrderId,
@@ -148,6 +153,7 @@
                 r.return_date AS recordTime,
                 ${@cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum@RQC.type} AS qcType,
                 rl.item_id AS itemId,
+                NULL AS batchCode,
                 rl.quantity AS quantity,
                 NULL AS vendorId,
                 NULL AS workOrderId,
diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilderTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilderTest.java
index 9de4db1..f41d159 100644
--- a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilderTest.java
+++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcProductReportWordBuilderTest.java
@@ -54,9 +54,9 @@
             assertEquals("10.023銆�10.115", itemTable.getRow(2).getCell(1).getText().trim());
             assertEquals("/", itemTable.getRow(3).getCell(1).getText().trim());
 
-            // 鍒ゅ畾缁撹/璐ㄦ涓撶敤绔犵暀绌�
+            // 鍒ゅ畾缁撹甯﹀嚭妫�楠岀粨鏋滐紱璐ㄦ涓撶敤绔犵暀绌哄緟鐩栫珷
             assertTrue(itemTable.getRow(2).getCell(0).getText().contains("璇曟牱璐ㄩ噺 m /g"));
-            assertEquals("鍒ゅ畾缁撹锛�", tables.get(2).getRow(0).getCell(0).getText().trim());
+            assertEquals("鍒ゅ畾缁撹锛�1鍨�", tables.get(2).getRow(0).getCell(0).getText().trim());
             assertEquals("璐ㄦ涓撶敤绔狅細", tables.get(2).getRow(0).getCell(1).getText().trim());
 
             // 澶囨敞榛樿鏂囨
@@ -80,7 +80,8 @@
                 .setSamplingTime(LocalDateTime.of(2026, 1, 6, 9, 0))
                 .setInspectDate(LocalDateTime.of(2026, 1, 6, 15, 0))
                 .setDocCreateTime(LocalDateTime.of(2026, 1, 6, 8, 0))
-                .setInspectorName("鏉庡崥").setAuditName("鍛ㄤ簹娲�").setApproveName("鍖呯繝钀�");
+                .setInspectorName("鏉庡崥").setAuditName("鍛ㄤ簹娲�").setApproveName("鍖呯繝钀�")
+                .setCheckResult(1).setCheckResultText("1鍨�");
 
         MesQcQcReportRespVO.ReportItem appearance = new MesQcQcReportRespVO.ReportItem();
         appearance.setIndicatorName("澶栬").setItemType(1).setSortOrder(10);
diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java
index 7207edb..85bf379 100644
--- a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java
+++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java
@@ -3,30 +3,23 @@
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
-import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
-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.qc.ipqc.MesQcIpqcDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO;
 import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
+import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
 import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
-import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
-import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
 import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService;
-import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
-import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService;
-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.qc.defectrecord.MesQcDefectRecordService;
 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
+import cn.iocoder.yudao.module.mes.service.qc.ncr.MesQcNcrService;
 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
+import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateService;
 import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import jakarta.annotation.Resource;
 import org.junit.jupiter.api.Test;
@@ -34,11 +27,16 @@
 import org.springframework.test.context.bean.override.mockito.MockitoBean;
 
 import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.*;
 
 /**
@@ -58,13 +56,9 @@
     @MockitoBean
     private MesQcTemplateItemService templateItemService;
     @MockitoBean
+    private MesQcTemplateService templateService;
+    @MockitoBean
     private MesQcIpqcLineService ipqcLineService;
-    @MockitoBean
-    private MesProWorkOrderService workOrderService;
-    @MockitoBean
-    private MesMdWorkstationService workstationService;
-    @MockitoBean
-    private MesMdItemService itemService;
     @MockitoBean
     private MesQcDefectRecordService defectRecordService;
     @MockitoBean
@@ -72,15 +66,15 @@
     @MockitoBean
     private MesProFeedbackService feedbackService;
     @MockitoBean
-    private MesProRouteProductService routeProductService;
-    @MockitoBean
-    private MesProRouteProcessService routeProcessService;
-    @MockitoBean
-    private MesProTaskService taskService;
-    @MockitoBean
     private MesQcIndicatorResultService indicatorResultService;
     @MockitoBean
     private MesWmProductProduceLineService productProduceLineService;
+    @MockitoBean
+    private MesQcNcrService ncrService;
+    @MockitoBean
+    private MdmItemApi mdmItemApi;
+
+    // ==================== finishIpqc 鍥炲啓鏉ユ簮鍗曟嵁 ====================
 
     @Test
     public void testFinishIpqc_writeBack_feedback() {
@@ -89,9 +83,6 @@
         Long sourceLineId = randomLongId();
         BigDecimal qualifiedQty = BigDecimal.valueOf(80);
         BigDecimal unqualifiedQty = BigDecimal.valueOf(20);
-        BigDecimal laborScrapQty = BigDecimal.valueOf(5);
-        BigDecimal materialScrapQty = BigDecimal.valueOf(10);
-        BigDecimal otherScrapQty = BigDecimal.valueOf(5);
 
         MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> {
             o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
@@ -101,9 +92,9 @@
             o.setSourceLineId(sourceLineId);
             o.setQualifiedQuantity(qualifiedQty);
             o.setUnqualifiedQuantity(unqualifiedQty);
-            o.setLaborScrapQuantity(laborScrapQty);
-            o.setMaterialScrapQuantity(materialScrapQty);
-            o.setOtherScrapQuantity(otherScrapQty);
+            o.setLaborScrapQuantity(BigDecimal.valueOf(5));
+            o.setMaterialScrapQuantity(BigDecimal.valueOf(10));
+            o.setOtherScrapQuantity(BigDecimal.valueOf(5));
         });
         ipqcMapper.insert(ipqc);
 
@@ -124,6 +115,8 @@
                 any(BigDecimal.class),
                 any(BigDecimal.class),
                 any(BigDecimal.class));
+        // 鏂█ 3锛氫笉鍚堟牸鏁伴噺 > 0锛岃嚜鍔ㄥ垱寤� NCR
+        verify(ncrService).createNcr(any());
     }
 
     @Test
@@ -161,13 +154,14 @@
 
     @Test
     public void testFinishIpqc_writeBack_noSourceDoc() {
-        // 鍑嗗鏁版嵁锛歴ourceDocType 涓虹┖锛屼笉闇�瑕佸洖鍐�
+        // 鍑嗗鏁版嵁锛氭棤鏉ユ簮鍗曟嵁锛堟墜宸ュ垱寤虹殑 IPQC锛夛紝鐩存帴瀹屾垚锛屼笉鍥炲啓
         MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> {
             o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
             o.setCheckResult(1);
             o.setSourceDocType(null);
             o.setSourceDocId(null);
             o.setSourceLineId(null);
+            o.setUnqualifiedQuantity(BigDecimal.ZERO);
         });
         ipqcMapper.insert(ipqc);
 
@@ -181,38 +175,6 @@
         // 鏂█ 2锛氫笉搴旇璋冪敤 feedbackService
         verify(feedbackService, never()).updateProFeedbackWhenIpqcFinish(
                 anyLong(), anyLong(), any(), any(), any(), any(), any());
-    }
-
-    @Test
-    public void testFinishIpqc_writeBack_sourceDocTypeDirtyData() {
-        // 鍑嗗鏁版嵁锛歴ourceDocType 闈炵┖浣� sourceDocId 涓虹┖锛屽簲璇ユ姏寮傚父
-        MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> {
-            o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
-            o.setCheckResult(1);
-            o.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK);
-            o.setSourceDocId(null); // 鑴忔暟鎹�
-            o.setSourceLineId(null);
-        });
-        ipqcMapper.insert(ipqc);
-
-        // 璋冪敤锛屽苟鏂█寮傚父
-        assertThrows(IllegalArgumentException.class, () -> ipqcService.finishIpqc(ipqc.getId()));
-    }
-
-    @Test
-    public void testFinishIpqc_writeBack_unknownSourceDocType() {
-        // 鍑嗗鏁版嵁锛歴ourceDocType 鏃犳硶璇嗗埆
-        MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> {
-            o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
-            o.setCheckResult(1);
-            o.setSourceDocType(99999); // 鏃犳硶璇嗗埆鐨勭被鍨�
-            o.setSourceDocId(randomLongId());
-            o.setSourceLineId(null);
-        });
-        ipqcMapper.insert(ipqc);
-
-        // 璋冪敤锛屽苟鏂█寮傚父
-        assertThrows(IllegalArgumentException.class, () -> ipqcService.finishIpqc(ipqc.getId()));
     }
 
     @Test
@@ -242,162 +204,61 @@
         assertThrows(Exception.class, () -> ipqcService.finishIpqc(ipqc.getId()));
     }
 
-    // ==================== processId 鎺ㄥ琛屼负娴嬭瘯 ====================
+    // ==================== createIpqc 鐗╂枡 / 鎵瑰彿 / 妯℃澘鍖归厤 ====================
 
     /**
-     * 宸ヤ綅鏈夊伐搴� + 璇ュ伐搴忓湪浜у搧宸ヨ壓璺嚎涓� 鈫� processId 搴旇琚缃负宸ヤ綅宸ュ簭
+     * 鎵嬪伐鍒涘缓锛氱墿鏂欐潵鑷� MDM锛屾ā鏉挎寜 MDM 鐗╂枡 ID 鍖归厤锛涙壒鍙枫�佺墿鏂欏潎钀藉簱
      */
     @Test
-    public void testCreateIpqc_processId_workstationHasProcess() {
+    public void testCreateIpqc_success() {
         // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
-        Long processId = randomLongId();
-        Long routeId = randomLongId();
+        Long itemId = randomLongId();
         Long templateId = randomLongId();
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-TEST-001");
+        reqVO.setItemId(itemId);
+        reqVO.setBatchCode("BC20250101");
 
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-TEST-001");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setInspectorUserId(randomLongId());
-
-        // mock 宸ヤ綅杩斿洖鏈夊伐搴�
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(processId);
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        // mock 宸ュ崟
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        // mock 妯℃澘鍖归厤
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
-        // mock 宸ヨ壓璺嚎
-        MesProRouteProductDO routeProduct = new MesProRouteProductDO();
-        routeProduct.setRouteId(routeId);
-        when(routeProductService.getRouteProductByItemId(productId)).thenReturn(routeProduct);
-        // mock 宸ュ簭鍦ㄨ矾绾夸腑
-        when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId))
-                .thenReturn(new MesProRouteProcessDO());
+        // mock锛氭寜 MDM 鐗╂枡 ID 鍖归厤鍒拌川妫�鏂规
+        mockTemplate(templateId);
 
         // 璋冪敤
         Long ipqcId = ipqcService.createIpqc(reqVO);
 
-        // 鏂█锛歱rocessId 搴旇鏄伐浣嶅伐搴�
+        // 鏂█ 1锛氭壒鍙枫�佺墿鏂欍�佹柟妗堝潎钀藉簱
         MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId);
-        assertEquals(processId, ipqc.getProcessId());
+        assertNotNull(ipqc);
+        assertEquals("BC20250101", ipqc.getBatchCode());
+        assertEquals(itemId, ipqc.getItemId());
+        assertEquals(templateId, ipqc.getTemplateId());
+        assertEquals(MesQcStatusEnum.DRAFT.getStatus(), ipqc.getStatus());
+        assertNull(ipqc.getSourceDocCode());
+
+        // 鏂█ 2锛氭ā鏉挎寜 MDM 鐗╂枡 ID 鍖归厤锛屼笉鍐嶄緷璧栧伐鍗�/浠诲姟
+        verify(templateItemService).getTemplateItemList(
+                eq(itemId), eq(MesQcTypeEnum.IPQC.getType()), isNull(), isNull());
+        // 鏂█ 3锛氱墿鏂欏瓨鍦ㄦ�ф牎楠岃蛋 MDM
+        verify(mdmItemApi).validateItemExists(itemId);
     }
 
     /**
-     * 宸ヤ綅娌℃湁宸ュ簭锛坧rocessId=null锛夆啋 processId 搴旇鐣� null锛堜笉鍥為��鍒颁换鍔″伐搴忥級
+     * 鐗╂枡鏈尮閰嶅埌浠讳綍璐ㄦ鏂规 鈫� 鍒涘缓澶辫触
      */
     @Test
-    public void testCreateIpqc_processId_workstationNoProcess_shouldBeNull() {
+    public void testCreateIpqc_noTemplate() {
         // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
-        Long taskId = randomLongId();
-        Long templateId = randomLongId();
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-TEST-002");
+        reqVO.setItemId(randomLongId());
 
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-TEST-002");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setTaskId(taskId); // 鏁呮剰浼犲叆 taskId锛岄獙璇佷笉浼氬洖閫�
-        reqVO.setInspectorUserId(randomLongId());
+        // mock锛氭棤鍖归厤鏂规
+        when(templateItemService.getTemplateItemList(any(), any(), any(), any()))
+                .thenReturn(Collections.emptyList());
 
-        // mock 宸ヤ綅娌℃湁宸ュ簭
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(null); // 鏃犲伐搴�
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        // mock 宸ュ崟
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        // mock 浠诲姟
-        MesProTaskDO task = new MesProTaskDO();
-        task.setId(taskId);
-        task.setWorkOrderId(workOrderId);
-        task.setWorkstationId(workstationId);
-        task.setItemId(productId);
-        when(taskService.validateTaskNotFinished(taskId)).thenReturn(task);
-        // mock 妯℃澘鍖归厤
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
-
-        // 璋冪敤
-        Long ipqcId = ipqcService.createIpqc(reqVO);
-
-        // 鏂█锛歱rocessId 搴旇鏄� null锛屽嵆浣夸紶鍏ヤ簡 taskId 涔熶笉搴旇鍥為��
-        MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId);
-        assertNull(ipqc.getProcessId(),
-                "宸ヤ綅鏃犲伐搴忔椂 processId 搴斾负 null锛屼笉搴斿洖閫�鍒颁换鍔″伐搴�");
-        // 鏂█锛氫笉搴旇璇诲彇浠诲姟鐨� processId
-        verify(routeProductService, never()).getRouteProductByItemId(any());
+        // 璋冪敤锛屾柇瑷�寮傚父
+        ServiceException ex = assertThrows(ServiceException.class, () -> ipqcService.createIpqc(reqVO));
+        assertEquals(QC_NO_TEMPLATE.getCode(), ex.getCode());
     }
 
-    /**
-     * 宸ヤ綅鏈夊伐搴忎絾璇ュ伐搴忎笉鍦ㄤ骇鍝佸伐鑹鸿矾绾夸腑 鈫� processId 搴旇鐣� null
-     */
-    @Test
-    public void testCreateIpqc_processId_processNotInRoute() {
-        // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
-        Long processId = randomLongId();
-        Long routeId = randomLongId();
-        Long templateId = randomLongId();
-
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-TEST-003");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setInspectorUserId(randomLongId());
-
-        // mock 宸ヤ綅鏈夊伐搴�
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(processId);
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        // mock 宸ュ崟
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        // mock 妯℃澘鍖归厤
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
-        // mock 宸ヨ壓璺嚎瀛樺湪
-        MesProRouteProductDO routeProduct = new MesProRouteProductDO();
-        routeProduct.setRouteId(routeId);
-        when(routeProductService.getRouteProductByItemId(productId)).thenReturn(routeProduct);
-        // mock 宸ュ簭涓嶅湪璺嚎涓�
-        when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId))
-                .thenReturn(null);
-
-        // 璋冪敤
-        Long ipqcId = ipqcService.createIpqc(reqVO);
-
-        // 鏂█锛歱rocessId 搴旇鏄� null
-        MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId);
-        assertNull(ipqc.getProcessId());
-    }
-
-    // ==================== sourceLineId 鏍¢獙娴嬭瘯 ====================
+    // ==================== createIpqc sourceLineId 鏍¢獙 ====================
 
     /**
      * sourceDocType=PRO_FEEDBACK 鏃� sourceLineId 涓虹┖ 鈫� 鍒涘缓澶辫触
@@ -405,34 +266,15 @@
     @Test
     public void testCreateIpqc_sourceLineId_required() {
         // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
         Long feedbackId = randomLongId();
-        Long templateId = randomLongId();
-
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-SL-001");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setInspectorUserId(randomLongId());
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-SL-001");
+        reqVO.setItemId(randomLongId());
         reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK);
         reqVO.setSourceDocId(feedbackId);
         reqVO.setSourceLineId(null); // 涓嶄紶 sourceLineId
 
         // mock
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(null);
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
+        mockTemplate(randomLongId());
         when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(new MesProFeedbackDO());
 
         // 璋冪敤锛屾柇瑷�寮傚父
@@ -446,35 +288,16 @@
     @Test
     public void testCreateIpqc_sourceLineId_notBelong() {
         // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
         Long feedbackId = randomLongId();
         Long sourceLineId = randomLongId();
-        Long templateId = randomLongId();
-
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-SL-002");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setInspectorUserId(randomLongId());
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-SL-002");
+        reqVO.setItemId(randomLongId());
         reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK);
         reqVO.setSourceDocId(feedbackId);
         reqVO.setSourceLineId(sourceLineId);
 
         // mock
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(null);
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
+        mockTemplate(randomLongId());
         when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(new MesProFeedbackDO());
         // mock锛氫骇鍑鸿瀛樺湪浣� feedbackId 涓嶅尮閰�
         MesWmProductProduceLineDO line = new MesWmProductProduceLineDO();
@@ -494,35 +317,16 @@
     @Test
     public void testCreateIpqc_sourceLineId_notPending() {
         // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
         Long feedbackId = randomLongId();
         Long sourceLineId = randomLongId();
-        Long templateId = randomLongId();
-
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-SL-003");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setInspectorUserId(randomLongId());
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-SL-003");
+        reqVO.setItemId(randomLongId());
         reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK);
         reqVO.setSourceDocId(feedbackId);
         reqVO.setSourceLineId(sourceLineId);
 
         // mock
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(null);
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
+        mockTemplate(randomLongId());
         when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(new MesProFeedbackDO());
         // mock锛氫骇鍑鸿瀛樺湪涓斿綊灞炴纭紝浣嗕笉鏄� PENDING 鐘舵��
         MesWmProductProduceLineDO line = new MesWmProductProduceLineDO();
@@ -537,40 +341,24 @@
     }
 
     /**
-     * sourceLineId 鏍¢獙鍏ㄩ儴閫氳繃 鈫� 鍒涘缓鎴愬姛
+     * sourceLineId 鏍¢獙鍏ㄩ儴閫氳繃 鈫� 鍒涘缓鎴愬姛锛屾潵婧愬崟鎹紪鍙峰洖鍐�
      */
     @Test
     public void testCreateIpqc_sourceLineId_success() {
         // 鍑嗗鍙傛暟
-        Long workstationId = randomLongId();
-        Long workOrderId = randomLongId();
-        Long productId = randomLongId();
+        Long itemId = randomLongId();
         Long feedbackId = randomLongId();
         Long sourceLineId = randomLongId();
         Long templateId = randomLongId();
-
-        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
-        reqVO.setCode("IPQC-SL-004");
-        reqVO.setWorkstationId(workstationId);
-        reqVO.setWorkOrderId(workOrderId);
-        reqVO.setInspectorUserId(randomLongId());
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-SL-004");
+        reqVO.setItemId(itemId);
+        reqVO.setBatchCode("BC20250101");
         reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK);
         reqVO.setSourceDocId(feedbackId);
         reqVO.setSourceLineId(sourceLineId);
 
         // mock
-        MesMdWorkstationDO workstation = new MesMdWorkstationDO();
-        workstation.setId(workstationId);
-        workstation.setProcessId(null);
-        when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation);
-        MesProWorkOrderDO workOrder = new MesProWorkOrderDO();
-        workOrder.setId(workOrderId);
-        workOrder.setProductId(productId);
-        when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder);
-        when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder);
-        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
-        templateItem.setTemplateId(templateId);
-        when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem);
+        mockTemplate(templateId);
         MesProFeedbackDO feedback = new MesProFeedbackDO();
         feedback.setId(feedbackId);
         feedback.setCode("FB-001");
@@ -585,12 +373,65 @@
         // 璋冪敤
         Long ipqcId = ipqcService.createIpqc(reqVO);
 
-        // 鏂█锛氬垱寤烘垚鍔燂紝sourceDocCode 鍥炲啓
+        // 鏂█锛氬垱寤烘垚鍔燂紝鏉ユ簮鍗曟嵁瀛楁钀藉簱
         MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId);
         assertNotNull(ipqc);
         assertEquals(feedbackId, ipqc.getSourceDocId());
         assertEquals(sourceLineId, ipqc.getSourceLineId());
         assertEquals("FB-001", ipqc.getSourceDocCode());
+        assertEquals("BC20250101", ipqc.getBatchCode());
+        assertEquals(itemId, ipqc.getItemId());
+    }
+
+    /**
+     * 鏈煡鏉ユ簮鍗曟嵁绫诲瀷 鈫� 鍒涘缓澶辫触
+     */
+    @Test
+    public void testCreateIpqc_sourceDocTypeUnknown() {
+        // 鍑嗗鍙傛暟
+        MesQcIpqcSaveReqVO reqVO = buildReqVO("IPQC-SL-005");
+        reqVO.setItemId(randomLongId());
+        reqVO.setSourceDocType(99999); // 鏃犳硶璇嗗埆鐨勭被鍨�
+        reqVO.setSourceDocId(randomLongId());
+
+        // mock
+        mockTemplate(randomLongId());
+
+        // 璋冪敤锛屾柇瑷�寮傚父
+        ServiceException ex = assertThrows(ServiceException.class, () -> ipqcService.createIpqc(reqVO));
+        assertEquals(QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN.getCode(), ex.getCode());
+    }
+
+    // ==================== 杈呭姪鏂规硶 ====================
+
+    /**
+     * 鏋勯�犱竴涓弧瓒冲繀濉」鐨勮繃绋嬫楠屽崟璇锋眰锛堜笉鍚潵婧愬崟鎹級
+     */
+    private MesQcIpqcSaveReqVO buildReqVO(String code) {
+        MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO();
+        reqVO.setCode(code);
+        reqVO.setName(code + "-鍚嶇О");
+        reqVO.setType(1);
+        reqVO.setBatchCode("BC-" + code);
+        reqVO.setCheckQuantity(BigDecimal.valueOf(100));
+        reqVO.setQualifiedQuantity(BigDecimal.valueOf(95));
+        reqVO.setUnqualifiedQuantity(BigDecimal.valueOf(5));
+        reqVO.setLaborScrapQuantity(BigDecimal.ZERO);
+        reqVO.setMaterialScrapQuantity(BigDecimal.ZERO);
+        reqVO.setOtherScrapQuantity(BigDecimal.ZERO);
+        reqVO.setInspectorUserId(randomLongId());
+        return reqVO;
+    }
+
+    /**
+     * mock锛氭寜 MDM 鐗╂枡 ID + IPQC 绫诲瀷鍖归厤鍒版寚瀹氳川妫�鏂规
+     */
+    private void mockTemplate(Long templateId) {
+        MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO();
+        templateItem.setTemplateId(templateId);
+        List<MesQcTemplateItemDO> templateItems = Collections.singletonList(templateItem);
+        when(templateItemService.getTemplateItemList(any(), eq(MesQcTypeEnum.IPQC.getType()), isNull(), isNull()))
+                .thenReturn(templateItems);
     }
 
 }
diff --git a/yudao-module-mes/src/test/resources/sql/create_tables.sql b/yudao-module-mes/src/test/resources/sql/create_tables.sql
index fd73613..716210e 100644
--- a/yudao-module-mes/src/test/resources/sql/create_tables.sql
+++ b/yudao-module-mes/src/test/resources/sql/create_tables.sql
@@ -242,10 +242,7 @@
     "source_doc_id" bigint DEFAULT NULL,
     "source_line_id" bigint DEFAULT NULL,
     "source_doc_code" varchar(64) DEFAULT NULL,
-    "work_order_id" bigint DEFAULT NULL,
-    "task_id" bigint DEFAULT NULL,
-    "workstation_id" bigint DEFAULT NULL,
-    "process_id" bigint DEFAULT NULL,
+    "batch_code" varchar(100) DEFAULT NULL,
     "item_id" bigint DEFAULT NULL,
     "check_quantity" decimal(14,2) DEFAULT NULL,
     "qualified_quantity" decimal(14,2) DEFAULT NULL,
@@ -263,6 +260,11 @@
     "inspect_date" timestamp DEFAULT NULL,
     "inspector_user_id" bigint DEFAULT NULL,
     "status" tinyint DEFAULT NULL,
+    "sampling_location" varchar(255) DEFAULT NULL,
+    "certificate_no" varchar(100) DEFAULT NULL,
+    "execute_standard" varchar(100) DEFAULT NULL,
+    "audit_user_id" bigint DEFAULT NULL,
+    "approve_user_id" bigint DEFAULT NULL,
     "remark" varchar(500) DEFAULT NULL,
     "creator" varchar(64) DEFAULT '',
     "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

--
Gitblit v1.9.3