zlwu 4 ヶ月 前
親
コミット
e7d080c9d3
27 ファイル変更、1251 行追加、1124 行削除
  1. 1 1
      backend/app.pid
  2. 36 3
      backend/app/crud/qc_work_order.py
  3. 0 0
      backend/app/graphify-out/cache/ast/877a8ace49c84bd7c995f0a2ef0cbb1733c4fa089290fc8ee7d8d5377b0d0eb2.json
  4. 0 0
      backend/app/graphify-out/cache/ast/a98cd4ef4c2935f3597891a9c89537f94d6e5ca11762892c45807dcb9a54c4a0.json
  5. 22 22
      backend/graphify-out/.graphify_analysis.json
  6. 141 141
      backend/graphify-out/.graphify_extract.json
  7. 1 1
      backend/graphify-out/GRAPH_REPORT.md
  8. 0 0
      backend/graphify-out/graph.html
  9. 182 182
      backend/graphify-out/graph.json
  10. 1 1
      backend/graphify-out/manifest.json
  11. 413 444
      web-admin/graphify-out/.graphify_analysis.json
  12. 116 80
      web-admin/graphify-out/.graphify_extract.json
  13. 88 78
      web-admin/graphify-out/GRAPH_REPORT.md
  14. 1 1
      web-admin/graphify-out/graph.html
  15. 112 112
      web-admin/graphify-out/graph.json
  16. 4 4
      web-admin/graphify-out/manifest.json
  17. 0 0
      web-admin/src/graphify-out/cache/ast/6d5161fd864604c6ee197990fa9124e2d48eb7e79a553a9318e1c78971b5498d.json
  18. 0 0
      web-admin/src/graphify-out/cache/ast/8ea71580bbb5347bd447471bc268544140cc38a4bb131e63317fc1e4ce446e2c.json
  19. 3 3
      web-admin/src/utils/production-work-order-card-meta.ts
  20. 8 4
      web-admin/src/utils/qc-mine-task-groups.ts
  21. 8 8
      web-admin/src/utils/qc-work-order-card-meta.ts
  22. 20 0
      web-admin/src/utils/qc-work-order-groups.ts
  23. 9 2
      web-admin/src/views/production/production-work-order/DispatchQcWorkOrderDialog.vue
  24. 17 3
      web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderSingleCard.vue
  25. 45 26
      web-admin/src/views/quality-inspection/qc-work-order/composables/inbound-view-sections.ts
  26. 6 2
      web-admin/src/views/quality-inspection/qc-work-order/composables/useQcWorkOrderTabPage.ts
  27. 17 6
      web-admin/src/views/quality-inspection/qc-work-order/tabs/QcWorkOrderTabPanel.vue

+ 1 - 1
backend/app.pid

@@ -1 +1 @@
-55086
+22388

+ 36 - 3
backend/app/crud/qc_work_order.py

@@ -60,6 +60,7 @@ _TRIGGER_SOURCE_LABELS = {
     "reception": "样本接收",
     "schedule": "计划质检",
     "production": "生产过程",
+    "manual": "手动创建",
 }
 _ACCEPT_CONCLUSION_LABELS = {"js": "接收", "bj": "拒收"}
 _WORK_ORDER_STATUS_LABELS = {"dpz": "待配置", "ypz": "已配置", "ywc": "已完成", "yzf": "已作废"}
@@ -840,8 +841,8 @@ def create_qc_work_order_from_production(
     if not pwo:
         raise ValueError("生产工单不存在")
     wo_type = (getattr(pwo, "work_order_type", None) or "inbound").strip()
-    if wo_type not in ("inbound", "outbound"):
-        raise ValueError("仅入库或出库生产工单可派发质检")
+    if wo_type not in ("inbound", "outbound", "temporary"):
+        raise ValueError("仅入库、出库或临时生产工单可派发质检")
     status = (pwo.work_order_status or "").strip()
     if status == "yzf":
         raise ValueError("已作废的生产工单不可派发质检")
@@ -907,6 +908,34 @@ def create_qc_work_order_from_production(
             update_time=datetime.now(),
             del_flag=0,
         )
+    elif wo_type == "temporary":
+        wo = BizQcWorkOrder(
+            id=generate_uuid(),
+            work_order_no=_gen_daily_no(db, tenant_no, "LSZJ"),
+            work_order_type="temporary",
+            reception_id=None,
+            protocol_sample_id=None,
+            collection_protocol_id=None,
+            protocol_no=None,
+            sample_code=None,
+            reception_source=None,
+            qc_biz_type="temporary",
+            trigger_source="production",
+            cell_product_id=cp_id,
+            production_work_order_id=pwo.id,
+            production_task_id=task_id,
+            work_order_status="dpz",
+            has_lab="0",
+            has_third_party="0",
+            tenant_no=tenant_no,
+            remark=(remark or "").strip() or None,
+            create_by=user_id,
+            create_dept_id=create_dept_id or "",
+            update_by=user_id,
+            create_time=datetime.now(),
+            update_time=datetime.now(),
+            del_flag=0,
+        )
     else:
         wo = BizQcWorkOrder(
             id=generate_uuid(),
@@ -1062,7 +1091,10 @@ def list_work_orders(
             q0 = q0.filter(BizQcWorkOrder.reception_source == rs)
         ts = (trigger_source or "").strip()
         if ts:
-            q0 = q0.filter(BizQcWorkOrder.trigger_source == ts)
+            if ts == "manual" and wt == "temporary":
+                q0 = q0.filter(BizQcWorkOrder.trigger_source != "production")
+            else:
+                q0 = q0.filter(BizQcWorkOrder.trigger_source == ts)
         kw = (keyword or "").strip()
         if kw:
             like = f"%{kw}%"
@@ -2075,6 +2107,7 @@ def create_temp_qc_work_order(
         sample_code=None,
         reception_source=None,
         qc_biz_type="temporary",
+        trigger_source="manual",
         cell_product_id=cp_id,
         work_order_status="dpz",
         has_lab="0",

ファイルの差分が大きいため隠しています
+ 0 - 0
backend/app/graphify-out/cache/ast/877a8ace49c84bd7c995f0a2ef0cbb1733c4fa089290fc8ee7d8d5377b0d0eb2.json


ファイルの差分が大きいため隠しています
+ 0 - 0
backend/app/graphify-out/cache/ast/a98cd4ef4c2935f3597891a9c89537f94d6e5ca11762892c45807dcb9a54c4a0.json


+ 22 - 22
backend/graphify-out/.graphify_analysis.json

@@ -1506,28 +1506,28 @@
       "crud_qc_material_usage_rationale_957",
       "crud_qc_task_result_rationale_43",
       "crud_qc_task_result_rationale_96",
-      "crud_qc_work_order_rationale_1232",
-      "crud_qc_work_order_rationale_1309",
-      "crud_qc_work_order_rationale_1375",
-      "crud_qc_work_order_rationale_1400",
-      "crud_qc_work_order_rationale_1427",
-      "crud_qc_work_order_rationale_1449",
-      "crud_qc_work_order_rationale_1547",
-      "crud_qc_work_order_rationale_1630",
-      "crud_qc_work_order_rationale_1754",
-      "crud_qc_work_order_rationale_203",
-      "crud_qc_work_order_rationale_2065",
-      "crud_qc_work_order_rationale_2106",
-      "crud_qc_work_order_rationale_2386",
-      "crud_qc_work_order_rationale_2649",
-      "crud_qc_work_order_rationale_296",
-      "crud_qc_work_order_rationale_358",
-      "crud_qc_work_order_rationale_367",
-      "crud_qc_work_order_rationale_410",
-      "crud_qc_work_order_rationale_710",
-      "crud_qc_work_order_rationale_830",
-      "crud_qc_work_order_rationale_87",
-      "crud_qc_work_order_rationale_951",
+      "crud_qc_work_order_rationale_1264",
+      "crud_qc_work_order_rationale_1341",
+      "crud_qc_work_order_rationale_1407",
+      "crud_qc_work_order_rationale_1432",
+      "crud_qc_work_order_rationale_1459",
+      "crud_qc_work_order_rationale_1481",
+      "crud_qc_work_order_rationale_1579",
+      "crud_qc_work_order_rationale_1662",
+      "crud_qc_work_order_rationale_1786",
+      "crud_qc_work_order_rationale_204",
+      "crud_qc_work_order_rationale_2097",
+      "crud_qc_work_order_rationale_2139",
+      "crud_qc_work_order_rationale_2419",
+      "crud_qc_work_order_rationale_2682",
+      "crud_qc_work_order_rationale_297",
+      "crud_qc_work_order_rationale_359",
+      "crud_qc_work_order_rationale_368",
+      "crud_qc_work_order_rationale_411",
+      "crud_qc_work_order_rationale_711",
+      "crud_qc_work_order_rationale_831",
+      "crud_qc_work_order_rationale_88",
+      "crud_qc_work_order_rationale_980",
       "crud_storage_facility_rationale_298",
       "crud_storage_occupancy_rationale_1",
       "crud_storage_occupancy_rationale_174",

ファイルの差分が大きいため隠しています
+ 141 - 141
backend/graphify-out/.graphify_extract.json


+ 1 - 1
backend/graphify-out/GRAPH_REPORT.md

@@ -1,7 +1,7 @@
 # Graph Report - app  (2026-06-16)
 
 ## Corpus Check
-- Large corpus: 208 files · ~242,541 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
+- Large corpus: 208 files · ~242,600 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
 
 ## Summary
 - 4163 nodes · 21838 edges · 57 communities detected

ファイルの差分が大きいため隠しています
+ 0 - 0
backend/graphify-out/graph.html


ファイルの差分が大きいため隠しています
+ 182 - 182
backend/graphify-out/graph.json


+ 1 - 1
backend/graphify-out/manifest.json

@@ -136,7 +136,7 @@
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/env_detect_item.py": 1781145689.9525824,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/process_category.py": 1779265700.0606413,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/item_unit.py": 1779265653.7504313,
-  "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_work_order.py": 1781603212.996301,
+  "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_work_order.py": 1781607961.140553,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_handover_inventory.py": 1781598316.476379,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/env_detect_record.py": 1781145773.959546,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_release_material.py": 1781598316.369666,

ファイルの差分が大きいため隠しています
+ 413 - 444
web-admin/graphify-out/.graphify_analysis.json


+ 116 - 80
web-admin/graphify-out/.graphify_extract.json

@@ -9779,12 +9779,19 @@
       "source_file": "api/cell-product.ts",
       "source_location": "L36"
     },
+    {
+      "id": "api_cell_product_fetchmaxpassageproductseq",
+      "label": "fetchMaxPassageProductSeq()",
+      "file_type": "code",
+      "source_file": "api/cell-product.ts",
+      "source_location": "L43"
+    },
     {
       "id": "api_cell_product_fetchcellproductchain",
       "label": "fetchCellProductChain()",
       "file_type": "code",
       "source_file": "api/cell-product.ts",
-      "source_location": "L43"
+      "source_location": "L59"
     },
     {
       "id": "api_sample_sms_notification_ts",
@@ -13165,175 +13172,175 @@
       "label": "remoteSearchProductTypes()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L370"
+      "source_location": "L371"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_ensureproducttypeinoptions",
       "label": "ensureProductTypeInOptions()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L386"
+      "source_location": "L387"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_remotesearchspecs",
       "label": "remoteSearchSpecs()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L392"
+      "source_location": "L393"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_ensurespecinoptions",
       "label": "ensureSpecInOptions()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L408"
+      "source_location": "L409"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_remotesearchstorageslots",
       "label": "remoteSearchStorageSlots()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L414"
+      "source_location": "L415"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_onstorageslotselectvisible",
       "label": "onStorageSlotSelectVisible()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L428"
+      "source_location": "L429"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_onproducttypeselectvisible",
       "label": "onProductTypeSelectVisible()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L432"
+      "source_location": "L433"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_onspecselectvisible",
       "label": "onSpecSelectVisible()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L436"
+      "source_location": "L437"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_getotherlinestorageslotids",
       "label": "getOtherLineStorageSlotIds()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L459"
+      "source_location": "L460"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_getlinestorageslotoptions",
       "label": "getLineStorageSlotOptions()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L465"
+      "source_location": "L466"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_normalizedatevalue",
       "label": "normalizeDateValue()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L501"
+      "source_location": "L503"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_calcexpiryfromfreeze",
       "label": "calcExpiryFromFreeze()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L507"
+      "source_location": "L509"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_onfreezedatechange",
       "label": "onFreezeDateChange()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L518"
+      "source_location": "L520"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_createemptyproductline",
       "label": "createEmptyProductLine()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L522"
+      "source_location": "L524"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_resolvespecname",
       "label": "resolveSpecName()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L533"
+      "source_location": "L535"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_populateformfromedititem",
       "label": "populateFormFromEditItem()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L537"
+      "source_location": "L539"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_initaddform",
       "label": "initAddForm()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L556"
+      "source_location": "L558"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_applyproductcodetolines",
       "label": "applyProductCodeToLines()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L571"
+      "source_location": "L573"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_ondialogopened",
       "label": "onDialogOpened()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L576"
+      "source_location": "L578"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_createquantityvalue",
       "label": "createQuantityValue()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L586"
+      "source_location": "L588"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_synclinecodesfrombase",
       "label": "syncLineCodesFromBase()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L592"
+      "source_location": "L594"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_syncproductlines",
       "label": "syncProductLines()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L607"
+      "source_location": "L626"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_oncreatecountchange",
       "label": "onCreateCountChange()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L624"
+      "source_location": "L643"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_onbaseproductcodeinput",
       "label": "onBaseProductCodeInput()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L630"
+      "source_location": "L649"
     },
     {
       "id": "production_work_order_taskoutputproductdialog_handlesubmit",
       "label": "handleSubmit()",
       "file_type": "code",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L764"
+      "source_location": "L783"
     },
     {
       "id": "views_production_production_work_order_productionworkordercardlist_vue",
@@ -34379,13 +34386,22 @@
     },
     {
       "source": "api_cell_product_ts",
-      "target": "api_cell_product_fetchcellproductchain",
+      "target": "api_cell_product_fetchmaxpassageproductseq",
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "api/cell-product.ts",
       "source_location": "L43",
       "weight": 1.0
     },
+    {
+      "source": "api_cell_product_ts",
+      "target": "api_cell_product_fetchcellproductchain",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "api/cell-product.ts",
+      "source_location": "L59",
+      "weight": 1.0
+    },
     {
       "source": "api_sample_sms_notification_ts",
       "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_http",
@@ -40359,7 +40375,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L370",
+      "source_location": "L371",
       "weight": 1.0
     },
     {
@@ -40368,7 +40384,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L386",
+      "source_location": "L387",
       "weight": 1.0
     },
     {
@@ -40377,7 +40393,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L392",
+      "source_location": "L393",
       "weight": 1.0
     },
     {
@@ -40386,7 +40402,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L408",
+      "source_location": "L409",
       "weight": 1.0
     },
     {
@@ -40395,7 +40411,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L414",
+      "source_location": "L415",
       "weight": 1.0
     },
     {
@@ -40404,7 +40420,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L428",
+      "source_location": "L429",
       "weight": 1.0
     },
     {
@@ -40413,7 +40429,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L432",
+      "source_location": "L433",
       "weight": 1.0
     },
     {
@@ -40422,7 +40438,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L436",
+      "source_location": "L437",
       "weight": 1.0
     },
     {
@@ -40431,7 +40447,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L459",
+      "source_location": "L460",
       "weight": 1.0
     },
     {
@@ -40440,7 +40456,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L465",
+      "source_location": "L466",
       "weight": 1.0
     },
     {
@@ -40449,7 +40465,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L501",
+      "source_location": "L503",
       "weight": 1.0
     },
     {
@@ -40458,7 +40474,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L507",
+      "source_location": "L509",
       "weight": 1.0
     },
     {
@@ -40467,7 +40483,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L518",
+      "source_location": "L520",
       "weight": 1.0
     },
     {
@@ -40476,7 +40492,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L522",
+      "source_location": "L524",
       "weight": 1.0
     },
     {
@@ -40485,7 +40501,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L533",
+      "source_location": "L535",
       "weight": 1.0
     },
     {
@@ -40494,7 +40510,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L537",
+      "source_location": "L539",
       "weight": 1.0
     },
     {
@@ -40503,7 +40519,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L556",
+      "source_location": "L558",
       "weight": 1.0
     },
     {
@@ -40512,7 +40528,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L571",
+      "source_location": "L573",
       "weight": 1.0
     },
     {
@@ -40521,7 +40537,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L576",
+      "source_location": "L578",
       "weight": 1.0
     },
     {
@@ -40530,7 +40546,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L586",
+      "source_location": "L588",
       "weight": 1.0
     },
     {
@@ -40539,7 +40555,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L592",
+      "source_location": "L594",
       "weight": 1.0
     },
     {
@@ -40548,7 +40564,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L607",
+      "source_location": "L626",
       "weight": 1.0
     },
     {
@@ -40557,7 +40573,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L624",
+      "source_location": "L643",
       "weight": 1.0
     },
     {
@@ -40566,7 +40582,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L630",
+      "source_location": "L649",
       "weight": 1.0
     },
     {
@@ -40575,7 +40591,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L764",
+      "source_location": "L783",
       "weight": 1.0
     },
     {
@@ -40584,7 +40600,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L429",
+      "source_location": "L430",
       "weight": 1.0
     },
     {
@@ -40593,7 +40609,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L433",
+      "source_location": "L434",
       "weight": 1.0
     },
     {
@@ -40602,7 +40618,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L437",
+      "source_location": "L438",
       "weight": 1.0
     },
     {
@@ -40611,7 +40627,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L468",
+      "source_location": "L469",
       "weight": 1.0
     },
     {
@@ -40620,7 +40636,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L519",
+      "source_location": "L521",
       "weight": 1.0
     },
     {
@@ -40629,7 +40645,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L548",
+      "source_location": "L550",
       "weight": 1.0
     },
     {
@@ -40638,7 +40654,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L551",
+      "source_location": "L553",
       "weight": 1.0
     },
     {
@@ -40647,7 +40663,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L561",
+      "source_location": "L563",
       "weight": 1.0
     },
     {
@@ -40656,7 +40672,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L562",
+      "source_location": "L564",
       "weight": 1.0
     },
     {
@@ -40665,7 +40681,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L563",
+      "source_location": "L565",
       "weight": 1.0
     },
     {
@@ -40674,7 +40690,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L567",
+      "source_location": "L569",
       "weight": 1.0
     },
     {
@@ -40683,7 +40699,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L572",
+      "source_location": "L574",
       "weight": 1.0
     },
     {
@@ -40692,7 +40708,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L573",
+      "source_location": "L575",
       "weight": 1.0
     },
     {
@@ -40701,7 +40717,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L578",
+      "source_location": "L580",
       "weight": 1.0
     },
     {
@@ -40710,7 +40726,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L582",
+      "source_location": "L584",
       "weight": 1.0
     },
     {
@@ -40719,7 +40735,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L608",
+      "source_location": "L627",
       "weight": 1.0
     },
     {
@@ -40728,7 +40744,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L621",
+      "source_location": "L640",
       "weight": 1.0
     },
     {
@@ -40737,7 +40753,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L626",
+      "source_location": "L645",
       "weight": 1.0
     },
     {
@@ -40746,7 +40762,7 @@
       "relation": "calls",
       "confidence": "EXTRACTED",
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L632",
+      "source_location": "L651",
       "weight": 1.0
     },
     {
@@ -54485,6 +54501,16 @@
       "source_location": "L37",
       "weight": 1.0
     },
+    {
+      "source": "api_cell_product_fetchmaxpassageproductseq",
+      "target": "process_processroutetab_get",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "api/cell-product.ts",
+      "source_location": "L45",
+      "weight": 1.0
+    },
     {
       "source": "api_cell_product_fetchcellproductchain",
       "target": "process_processroutetab_get",
@@ -54492,7 +54518,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "api/cell-product.ts",
-      "source_location": "L44",
+      "source_location": "L60",
       "weight": 1.0
     },
     {
@@ -56102,7 +56128,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L373",
+      "source_location": "L374",
       "weight": 1.0
     },
     {
@@ -56112,7 +56138,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L395",
+      "source_location": "L396",
       "weight": 1.0
     },
     {
@@ -56122,7 +56148,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L417",
+      "source_location": "L418",
       "weight": 1.0
     },
     {
@@ -56132,7 +56158,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L466",
+      "source_location": "L467",
       "weight": 1.0
     },
     {
@@ -56142,7 +56168,17 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L557",
+      "source_location": "L559",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_taskoutputproductdialog_synclinecodesfrombase",
+      "target": "api_cell_product_fetchmaxpassageproductseq",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
+      "source_location": "L605",
       "weight": 1.0
     },
     {
@@ -56152,7 +56188,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L612",
+      "source_location": "L631",
       "weight": 1.0
     },
     {
@@ -56162,7 +56198,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L766",
+      "source_location": "L785",
       "weight": 1.0
     },
     {
@@ -56172,7 +56208,7 @@
       "confidence": "INFERRED",
       "confidence_score": 0.8,
       "source_file": "views/production/production-work-order/TaskOutputProductDialog.vue",
-      "source_location": "L771",
+      "source_location": "L790",
       "weight": 1.0
     },
     {

+ 88 - 78
web-admin/graphify-out/GRAPH_REPORT.md

@@ -1,11 +1,11 @@
 # Graph Report - src  (2026-06-16)
 
 ## Corpus Check
-- Large corpus: 782 files · ~514,925 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
+- Large corpus: 782 files · ~515,044 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
 
 ## Summary
-- 2581 nodes · 3576 edges · 49 communities detected
-- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 778 edges (avg confidence: 0.8)
+- 2582 nodes · 3579 edges · 51 communities detected
+- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 780 edges (avg confidence: 0.8)
 - Token cost: 0 input · 0 output
 
 ## Community Hubs (Navigation)
@@ -41,26 +41,28 @@
 - [[_COMMUNITY_Community 29|Community 29]]
 - [[_COMMUNITY_Community 30|Community 30]]
 - [[_COMMUNITY_Community 31|Community 31]]
+- [[_COMMUNITY_Community 32|Community 32]]
 - [[_COMMUNITY_Community 33|Community 33]]
-- [[_COMMUNITY_Community 34|Community 34]]
 - [[_COMMUNITY_Community 35|Community 35]]
 - [[_COMMUNITY_Community 36|Community 36]]
 - [[_COMMUNITY_Community 37|Community 37]]
 - [[_COMMUNITY_Community 38|Community 38]]
 - [[_COMMUNITY_Community 39|Community 39]]
-- [[_COMMUNITY_Community 42|Community 42]]
-- [[_COMMUNITY_Community 43|Community 43]]
+- [[_COMMUNITY_Community 40|Community 40]]
+- [[_COMMUNITY_Community 41|Community 41]]
 - [[_COMMUNITY_Community 44|Community 44]]
-- [[_COMMUNITY_Community 47|Community 47]]
-- [[_COMMUNITY_Community 48|Community 48]]
+- [[_COMMUNITY_Community 45|Community 45]]
+- [[_COMMUNITY_Community 46|Community 46]]
+- [[_COMMUNITY_Community 49|Community 49]]
 - [[_COMMUNITY_Community 50|Community 50]]
-- [[_COMMUNITY_Community 51|Community 51]]
+- [[_COMMUNITY_Community 52|Community 52]]
 - [[_COMMUNITY_Community 53|Community 53]]
-- [[_COMMUNITY_Community 58|Community 58]]
+- [[_COMMUNITY_Community 55|Community 55]]
 - [[_COMMUNITY_Community 60|Community 60]]
+- [[_COMMUNITY_Community 62|Community 62]]
 
 ## God Nodes (most connected - your core abstractions)
-1. `get()` - 260 edges
+1. `get()` - 261 edges
 2. `push()` - 63 edges
 3. `emit()` - 27 edges
 4. `WebSocketClient` - 26 edges
@@ -78,10 +80,10 @@
   components/business/clinical-schedule-payment-detail/index.vue → utils/money-format.ts
 - `subscribeTokenRefresh()` --calls--> `push()`  [INFERRED]
   utils/http/index.ts → views/operations/storage-facility/index.vue
-- `fetchSampleReceptionCheckItemList()` --calls--> `get()`  [INFERRED]
-  api/sample-reception-check-item.ts → views/production/process/ProcessRouteTab.vue
-- `fetchStorageReleaseReviewList()` --calls--> `get()`  [INFERRED]
-  api/storage-release-review.ts → views/production/process/ProcessRouteTab.vue
+- `handleUnauthorizedResponse()` --calls--> `fetchRefreshToken()`  [INFERRED]
+  utils/http/index.ts → api/auth.ts
+- `handleCardSelect()` --calls--> `emit()`  [INFERRED]
+  views/production/production-work-order/ProductionWorkOrderCardList.vue → components/core/layouts/art-settings-panel/widget/SettingItem.vue
 
 ## Communities
 
@@ -95,23 +97,23 @@ Nodes (11): fetchCreateCheckupInstitution(), fetchCreateCheckupInstitutionInvoic
 
 ### Community 2 - "Community 2"
 Cohesion: 0.03
-Nodes (50): fetchGetMenuList(), fetchGetMenuCodes(), fetchGetUserInfo(), fetchLogin(), fetchUpdateProfile(), fetchUploadProfileAvatar(), IframeRouteManager, MenuProcessor (+42 more)
+Nodes (51): fetchGetMenuList(), fetchGetMenuCodes(), fetchGetUserInfo(), fetchLogin(), fetchRefreshToken(), fetchUpdateProfile(), fetchUploadProfileAvatar(), IframeRouteManager (+43 more)
 
 ### Community 3 - "Community 3"
 Cohesion: 0.03
 Nodes (62): fetchCheckupInstitutionInvoices(), fetchCheckupInstitutionList(), fetchCheckupInstitutionProjects(), fetchCreateCheckupInstitutionProject(), fetchUpdateCheckupInstitutionProject(), submitOutboundReleaseReview(), fetchConsumablePackDetail(), fetchConsumablePackList() (+54 more)
 
 ### Community 4 - "Community 4"
-Cohesion: 0.03
-Nodes (59): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), updateInfusionScheduleStatus(), fetchProductionTaskList(), handleAdd(), handleDelete() (+51 more)
+Cohesion: 0.04
+Nodes (74): batchSavePilotCheckup(), deletePilotCheckupActualItem(), fetchCheckupInstitutionPackageDetail(), fetchCheckupInstitutionPackages(), fetchPilotCheckupActualItems(), fetchPilotCheckupDetail(), fetchPilotCheckupReserveItems(), markPilotCheckupChecked() (+66 more)
 
 ### Community 5 - "Community 5"
 Cohesion: 0.04
-Nodes (66): fetchUploadAttachment(), FireworkSystem, reload(), handleReportUpload(), handleReportUpload(), walk(), formatTodayDate(), handleMenuJump() (+58 more)
+Nodes (61): fetchUploadAttachment(), FireworkSystem, reload(), handleReportUpload(), handleReportUpload(), walk(), handleMenuJump(), openExternalLink() (+53 more)
 
 ### Community 6 - "Community 6"
 Cohesion: 0.04
-Nodes (75): batchSavePilotCheckup(), deletePilotCheckupActualItem(), fetchCheckupInstitutionPackageDetail(), fetchCheckupInstitutionPackages(), fetchPilotCheckupActualItems(), fetchPilotCheckupDetail(), fetchPilotCheckupReserveItems(), markPilotCheckupChecked() (+67 more)
+Nodes (51): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), updateInfusionScheduleStatus(), fetchProductionTaskList(), handleDelete(), handleDropdownCommand() (+43 more)
 
 ### Community 7 - "Community 7"
 Cohesion: 0.03
@@ -119,31 +121,31 @@ Nodes (43): fetchMyProductionTasks(), fetchMyQcTaskList(), fetchQcTaskDetail(),
 
 ### Community 8 - "Community 8"
 Cohesion: 0.04
-Nodes (51): fetchCellProductSpecList(), fetchCellProductTypeList(), fetchStorageSlotSelectOptions(), useSettingsHandlers(), useSettingsPanel(), useSettingsState(), RoutePermissionValidator, useCeremony() (+43 more)
+Nodes (48): fetchCellSampleTypeList(), fetchCreateCellSampleType(), fetchCreateMenu(), fetchDeleteCellSampleType(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateCellSampleType(), fetchUpdateMenu() (+40 more)
 
 ### Community 9 - "Community 9"
-Cohesion: 0.04
-Nodes (48): fetchCellSampleTypeList(), fetchCreateCellSampleType(), fetchCreateMenu(), fetchDeleteCellSampleType(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateCellSampleType(), fetchUpdateMenu() (+40 more)
+Cohesion: 0.05
+Nodes (47): fetchCellProductSpecList(), fetchCellProductTypeList(), fetchStorageSlotSelectOptions(), fetchMaxPassageProductSeq(), RoutePermissionValidator, handleAdd(), resetForm(), applyProductCodeToLines() (+39 more)
 
 ### Community 10 - "Community 10"
+Cohesion: 0.05
+Nodes (49): completePilotApplication(), deletePilotApplication(), fetchFullmoonTodoList(), fetchPilotApplicationList(), fetchUpdateFullmoonTodoInsurance(), startPilotApplication(), voidPilotApplication(), fetchCollectionProtocolDetail() (+41 more)
+
+### Community 11 - "Community 11"
 Cohesion: 0.04
 Nodes (37): fetchInfusionScheduleMgmtDetail(), fetchAttachmentDownloadUrl(), qcAttachmentFullUrl(), qcDownloadAttachment(), qcPreviewAttachment(), handleDownloadAttachment(), attachmentFullUrl(), handleAttachmentDownload() (+29 more)
 
-### Community 11 - "Community 11"
+### Community 12 - "Community 12"
 Cohesion: 0.05
 Nodes (34): fetchClinicalPaymentDetail(), fetchClinicalPayments(), fetchClinicalReceiptConfirmed(), fetchClinicalReceiptPending(), fetchClinicalRefundConfirmed(), fetchClinicalRefundPending(), fetchOrderAdjusts(), fetchOrderDetail() (+26 more)
 
-### Community 12 - "Community 12"
-Cohesion: 0.06
-Nodes (35): fetchRefreshToken(), toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url() (+27 more)
-
 ### Community 13 - "Community 13"
 Cohesion: 0.06
-Nodes (37): buildBaseFields(), buildInboundBasicSection(), buildInboundCellStorageProductionViewSections(), buildInboundResearchDonationProductionViewSections(), buildOutboundBasicExperimentProductionViewSections(), buildOutboundClinicalProductionViewSections(), buildOutboundDetail(), buildOutboundPilotProductionViewSections() (+29 more)
+Nodes (34): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+26 more)
 
 ### Community 14 - "Community 14"
 Cohesion: 0.05
-Nodes (28): handleBlur(), handleFocus(), handleInput(), fetchEthnicList(), formatAmount(), formatAmount(), formatProtocolAmount(), buildFeeSection() (+20 more)
+Nodes (27): fetchEthnicList(), formatNowDatetime(), formatHandoverUserLabel(), formatNowDatetime(), fullFileUrl(), handlePreviewAttachment(), isVideoFile(), resetHandoverForm() (+19 more)
 
 ### Community 15 - "Community 15"
 Cohesion: 0.05
@@ -151,31 +153,31 @@ Nodes (13): fmtMoney(), auditorDisplay(), dash(), ensureUnitsInOptions(), expres
 
 ### Community 16 - "Community 16"
 Cohesion: 0.07
-Nodes (33): fetchUserList(), fetchAddTaskStep(), fetchCopyTaskStep(), fetchDeleteTaskStep(), fetchForwardProductionTask(), fetchProductionTaskDetail(), fetchReassignProductionTask(), fetchReorderTaskSteps() (+25 more)
-
-### Community 17 - "Community 17"
-Cohesion: 0.07
 Nodes (24): fetchDeleteQcMaterialBatch(), fetchQcMaterialBatchList(), fetchQcMaterialBatchOptions(), fetchQcMaterialList(), fetchQcMaterialOptions(), fetchUpdateQcMaterialBatch(), fetchMarkQcMaterialUsageFullyUsed(), ensureTabMounted() (+16 more)
 
-### Community 18 - "Community 18"
+### Community 17 - "Community 17"
 Cohesion: 0.1
 Nodes (2): WebSocketClient, TableCache
 
-### Community 19 - "Community 19"
+### Community 18 - "Community 18"
 Cohesion: 0.08
 Nodes (28): fetchUserOptions(), fetchSampleReceptionCheckItemList(), fetchSampleReceptionCheckItemsActive(), fetchAllocateLabStorageCodes(), fetchSampleReceptionBySampleCode(), fetchSampleReceptionDetail(), fetchSampleReceptionPendingList(), fetchSampleReceptionReceivedList() (+20 more)
 
+### Community 19 - "Community 19"
+Cohesion: 0.08
+Nodes (20): maskIdCard(), buildBasicExperimentApplicationFields(), buildDefaultApplicationFields(), buildOutboundPilotContextSections(), applicationStatusLabel(), applicationStatusTagType(), cellProductStatusLabel(), cellProductStatusTagType() (+12 more)
+
 ### Community 20 - "Community 20"
 Cohesion: 0.09
 Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
 
 ### Community 21 - "Community 21"
-Cohesion: 0.08
-Nodes (29): fetchCreateUser(), fetchDeleteUser(), fetchDeptTree(), fetchPostBoundUserIds(), fetchResetPassword(), fetchRoleOptions(), fetchUpdateUser(), fetchUserDetail() (+21 more)
+Cohesion: 0.09
+Nodes (30): handleBlur(), handleFocus(), handleInput(), formatAmount(), formatAmount(), formatProtocolAmount(), buildBaseFields(), buildFeeSection() (+22 more)
 
 ### Community 22 - "Community 22"
-Cohesion: 0.09
-Nodes (28): completePilotApplication(), deletePilotApplication(), fetchPilotApplicationList(), startPilotApplication(), voidPilotApplication(), clearTableSelection(), handleBatchComplete(), handleBatchStart() (+20 more)
+Cohesion: 0.08
+Nodes (29): fetchCreateUser(), fetchDeleteUser(), fetchDeptTree(), fetchPostBoundUserIds(), fetchResetPassword(), fetchRoleOptions(), fetchUpdateUser(), fetchUserDetail() (+21 more)
 
 ### Community 23 - "Community 23"
 Cohesion: 0.07
@@ -183,7 +185,7 @@ Nodes (18): fetchDictDataOptions(), fetchDeleteMaterialBatch(), fetchMaterialBat
 
 ### Community 24 - "Community 24"
 Cohesion: 0.1
-Nodes (21): fetchFullmoonTodoList(), fetchUpdateFullmoonTodoInsurance(), fetchCollectionProtocolDetail(), buildInsuranceAttachmentsValue(), buildInsurancePayload(), formatYmdFromAny(), fullFileUrl(), handleBatchEdit() (+13 more)
+Nodes (27): fetchUserList(), fetchAddTaskStep(), fetchCopyTaskStep(), fetchDeleteTaskStep(), fetchForwardProductionTask(), fetchProductionTaskDetail(), fetchReassignProductionTask(), fetchReorderTaskSteps() (+19 more)
 
 ### Community 25 - "Community 25"
 Cohesion: 0.12
@@ -206,114 +208,122 @@ Cohesion: 0.27
 Nodes (14): useChart(), useChartComponent(), useChartOps(), colourBlend(), getCssVar(), getDarkColor(), getLightColor(), handleElementThemeColor() (+6 more)
 
 ### Community 30 - "Community 30"
+Cohesion: 0.14
+Nodes (8): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), useCeremony(), useTheme(), themeAnimation(), toggleTheme(), toggleTransition()
+
+### Community 31 - "Community 31"
+Cohesion: 0.16
+Nodes (5): canDeleteWorkOrder(), canDispatchTask(), canEditWorkOrder(), handleCardSelect(), hasMoreActions()
+
+### Community 32 - "Community 32"
 Cohesion: 0.33
 Nodes (13): buildProtocolPaymentFlowSteps(), dash(), financeReceiptTime(), formatAmount(), hasFinanceReceipt(), hasFinanceRefund(), hasReceiptSubmit(), hasRefundSubmit() (+5 more)
 
-### Community 31 - "Community 31"
+### Community 33 - "Community 33"
 Cohesion: 0.19
 Nodes (6): fetchServiceOrderTxnList(), handleReset(), handleSearch(), handleTabChange(), loadData(), switchTab()
 
-### Community 33 - "Community 33"
+### Community 35 - "Community 35"
 Cohesion: 0.21
 Nodes (7): handleReset(), handleSearch(), handleToggleSelect(), loadData(), onReviewSubmitted(), rowId(), isSelected()
 
-### Community 34 - "Community 34"
-Cohesion: 0.18
-Nodes (3): normalizeStepSubTables(), parseEquipmentIds(), syncEquipmentNamesFromOptions()
-
-### Community 35 - "Community 35"
+### Community 36 - "Community 36"
 Cohesion: 0.17
 Nodes (3): fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList()
 
-### Community 36 - "Community 36"
+### Community 37 - "Community 37"
+Cohesion: 0.18
+Nodes (3): normalizeStepSubTables(), parseEquipmentIds(), syncEquipmentNamesFromOptions()
+
+### Community 38 - "Community 38"
 Cohesion: 0.24
 Nodes (6): buildInboundMetaFields(), getCardMetaConfig(), getCardMetaConfigForLegacyTab(), parseReceptionTime(), receptionOver24HoursLabel(), receptionOver24HoursTagType()
 
-### Community 37 - "Community 37"
+### Community 39 - "Community 39"
 Cohesion: 0.42
 Nodes (9): buildPaymentFlowSteps(), dash(), formatAmount(), hasFinanceReceipt(), hasFinanceRefund(), hasReceiptSubmit(), hasRefundSubmit(), receiptSubmitTime() (+1 more)
 
-### Community 38 - "Community 38"
+### Community 40 - "Community 40"
 Cohesion: 0.29
 Nodes (5): canConfigureWorkOrder(), canDeleteWorkOrder(), canEditRemarkWorkOrder(), canEditTemporaryWorkOrder(), hasMoreWorkOrderActions()
 
-### Community 39 - "Community 39"
+### Community 41 - "Community 41"
 Cohesion: 0.25
 Nodes (2): handleTouchEnd(), setTransition()
 
-### Community 42 - "Community 42"
+### Community 44 - "Community 44"
 Cohesion: 0.28
 Nodes (4): fetchMyProductionMaterialConsumptions(), handleReset(), handleSearch(), loadData()
 
-### Community 43 - "Community 43"
+### Community 45 - "Community 45"
 Cohesion: 0.39
 Nodes (6): isIgnorableScriptError(), normalizeErrorMessage(), registerPromiseErrorHandler(), registerResourceErrorHandler(), scriptErrorHandler(), setupErrorHandle()
 
-### Community 44 - "Community 44"
+### Community 46 - "Community 46"
 Cohesion: 0.36
 Nodes (1): TableHeightCalculator
 
-### Community 47 - "Community 47"
+### Community 49 - "Community 49"
 Cohesion: 0.33
 Nodes (2): logApiCryptoBootInfo(), maskSecret()
 
-### Community 48 - "Community 48"
+### Community 50 - "Community 50"
 Cohesion: 0.47
 Nodes (3): isPaymentDueWithinWarnWindow(), parsePaymentDueYmd(), startOfLocalDay()
 
-### Community 50 - "Community 50"
+### Community 52 - "Community 52"
 Cohesion: 0.5
 Nodes (2): formatProtocolDocDeleteConfirm(), formatProtocolDocSubject()
 
-### Community 51 - "Community 51"
+### Community 53 - "Community 53"
 Cohesion: 0.5
 Nodes (2): focusInput(), handleKeydown()
 
-### Community 53 - "Community 53"
+### Community 55 - "Community 55"
 Cohesion: 0.67
 Nodes (2): if(), logSidebarMenu()
 
-### Community 58 - "Community 58"
+### Community 60 - "Community 60"
 Cohesion: 1.0
 Nodes (2): getSettingDefaults(), resetToDefaults()
 
-### Community 60 - "Community 60"
+### Community 62 - "Community 62"
 Cohesion: 1.0
 Nodes (2): copyTextToClipboard(), copyTextWithFallback()
 
 ## Knowledge Gaps
-- **Thin community `Community 18`** (42 nodes): `WebSocketClient`, `.calculateReconnectDelay()`, `.clearAllTimers()`, `.clearConnectionTimers()`, `.clearTimer()`, `.close()`, `.closeCurrentSocketForReconnect()`, `.connect()`, `.connectionStatusText()`, `.constructor()`, `.destroyInstance()`, `.flushMessageQueue()`, `.getInstance()`, `.getReadyStateText()`, `.handleClose()`, `.handleConnectionTimeout()`, `.handleError()`, `.handleMessage()`, `.handleOpen()`, `.init()`, `.isWebSocketConnected()`, `.reconnect()`, `.resetHeartbeat()`, `.send()`, `.startHeartbeat()`, `.startPing()`, `TableCache`, `.cleanupExpired()`, `.clear()`, `.clearByTags()`, `.clearCurrentSearch()`, `.clearPagination()`, `.constructor()`, `.evictLRU()`, `.generateKey()`, `.generateTags()`, `.get()`, `.getStats()`, `.log()`, `.set()`, `index.ts`, `tableCache.ts`
+- **Thin community `Community 17`** (42 nodes): `WebSocketClient`, `.calculateReconnectDelay()`, `.clearAllTimers()`, `.clearConnectionTimers()`, `.clearTimer()`, `.close()`, `.closeCurrentSocketForReconnect()`, `.connect()`, `.connectionStatusText()`, `.constructor()`, `.destroyInstance()`, `.flushMessageQueue()`, `.getInstance()`, `.getReadyStateText()`, `.handleClose()`, `.handleConnectionTimeout()`, `.handleError()`, `.handleMessage()`, `.handleOpen()`, `.init()`, `.isWebSocketConnected()`, `.reconnect()`, `.resetHeartbeat()`, `.send()`, `.startHeartbeat()`, `.startPing()`, `TableCache`, `.cleanupExpired()`, `.clear()`, `.clearByTags()`, `.clearCurrentSearch()`, `.clearPagination()`, `.constructor()`, `.evictLRU()`, `.generateKey()`, `.generateTags()`, `.get()`, `.getStats()`, `.log()`, `.set()`, `index.ts`, `tableCache.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
 - **Thin community `Community 28`** (17 nodes): `ComponentLoader`, `.constructor()`, `.createEmptyComponent()`, `.createErrorComponent()`, `.load()`, `.loadIframe()`, `.loadLayout()`, `.load()`, `RouteTransformer`, `.extractFirstSegment()`, `.handleFirstLevelRoute()`, `.handleIframeRoute()`, `.handleNormalRoute()`, `.isFirstLevelRoute()`, `.transform()`, `ComponentLoader.ts`, `RouteTransformer.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 39`** (9 nodes): `cleanupEventListeners()`, `handleTouchEnd()`, `handleTouchMove()`, `handleTouchStart()`, `handleWheelScroll()`, `if()`, `setTransition()`, `setupEventListeners()`, `index.vue`
+- **Thin community `Community 41`** (9 nodes): `cleanupEventListeners()`, `handleTouchEnd()`, `handleTouchMove()`, `handleTouchStart()`, `handleWheelScroll()`, `if()`, `setTransition()`, `setupEventListeners()`, `index.vue`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 44`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
+- **Thin community `Community 46`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 47`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
+- **Thin community `Community 49`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 50`** (5 nodes): `formatProtocolDocBatchDeleteConfirm()`, `formatProtocolDocDeleteConfirm()`, `formatProtocolDocSubject()`, `getProtocolDocTypeLabel()`, `protocol-doc-label.ts`
+- **Thin community `Community 52`** (5 nodes): `formatProtocolDocBatchDeleteConfirm()`, `formatProtocolDocDeleteConfirm()`, `formatProtocolDocSubject()`, `getProtocolDocTypeLabel()`, `protocol-doc-label.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 51`** (5 nodes): `focusInput()`, `handleKeydown()`, `if()`, `search()`, `index.vue`
+- **Thin community `Community 53`** (5 nodes): `focusInput()`, `handleKeydown()`, `if()`, `search()`, `index.vue`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 53`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
+- **Thin community `Community 55`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 58`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
+- **Thin community `Community 60`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 60`** (3 nodes): `copyTextToClipboard()`, `copyTextWithFallback()`, `copy-text.ts`
+- **Thin community `Community 62`** (3 nodes): `copyTextToClipboard()`, `copyTextWithFallback()`, `copy-text.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
 
 ## Suggested Questions
 _Questions this graph is uniquely positioned to answer:_
 
-- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 14`, `Community 16`, `Community 17`, `Community 19`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 26`, `Community 31`, `Community 35`, `Community 42`?**
-  _High betweenness centrality (0.365) - this node is a cross-community bridge._
-- **Why does `push()` connect `Community 5` to `Community 1`, `Community 3`, `Community 36`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `Community 21`, `Community 22`, `Community 24`?**
-  _High betweenness centrality (0.184) - this node is a cross-community bridge._
-- **Why does `emit()` connect `Community 4` to `Community 0`, `Community 3`, `Community 6`, `Community 14`, `Community 16`, `Community 19`?**
+- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 14`, `Community 16`, `Community 18`, `Community 22`, `Community 23`, `Community 24`, `Community 26`, `Community 33`, `Community 36`, `Community 44`?**
+  _High betweenness centrality (0.364) - this node is a cross-community bridge._
+- **Why does `push()` connect `Community 5` to `Community 1`, `Community 3`, `Community 4`, `Community 38`, `Community 7`, `Community 6`, `Community 9`, `Community 10`, `Community 8`, `Community 13`, `Community 14`, `Community 15`, `Community 17`, `Community 19`, `Community 21`, `Community 22`?**
+  _High betweenness centrality (0.180) - this node is a cross-community bridge._
+- **Why does `fetchNotDeletedRegions()` connect `Community 1` to `Community 5`?**
   _High betweenness centrality (0.032) - this node is a cross-community bridge._
-- **Are the 259 inferred relationships involving `get()` (e.g. with `buildNodeCodePathFromFlat()` and `collectLeafFacilityNodesInTreeOrder()`) actually correct?**
-  _`get()` has 259 INFERRED edges - model-reasoned connections that need verification._
+- **Are the 260 inferred relationships involving `get()` (e.g. with `buildNodeCodePathFromFlat()` and `collectLeafFacilityNodesInTreeOrder()`) actually correct?**
+  _`get()` has 260 INFERRED edges - model-reasoned connections that need verification._
 - **Are the 62 inferred relationships involving `push()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `formatDetectMethods()`) actually correct?**
   _`push()` has 62 INFERRED edges - model-reasoned connections that need verification._
 - **Are the 26 inferred relationships involving `emit()` (e.g. with `handleSubmit()` and `handleBlur()`) actually correct?**

ファイルの差分が大きいため隠しています
+ 1 - 1
web-admin/graphify-out/graph.html


ファイルの差分が大きいため隠しています
+ 112 - 112
web-admin/graphify-out/graph.json


+ 4 - 4
web-admin/graphify-out/manifest.json

@@ -17,8 +17,8 @@
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/index.ts": 1781272556.3597305,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/directive/directive.d.ts": 1781272556.3601494,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api/api.d.ts": 1781272556.3606477,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1781604188.41692,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1781603268.522488,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1781605758.34215,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1781605412.0921795,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/store/index.ts": 1781272556.364766,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/router/index.ts": 1781272556.3652694,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/locales/index.ts": 1781272556.3657222,
@@ -250,7 +250,7 @@
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/ethnic.ts": 1781272556.6658764,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/research-donation-sample-collection.ts": 1781272556.6660974,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-lab-test-item.ts": 1781272556.666375,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/cell-product.ts": 1781272556.6666105,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/cell-product.ts": 1781605170.2572234,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/sample-sms-notification.ts": 1781272556.666838,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/material-stock-check.ts": 1781427280.4992144,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/research-donation.ts": 1781592190.7764218,
@@ -363,7 +363,7 @@
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/DispatchTaskDialog.vue": 1781593091.2341514,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskPaperAttachmentsPanel.vue": 1781530960.805927,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/WorkOrderTaskSubList.vue": 1781585388.7005522,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskOutputProductDialog.vue": 1781563767.357495,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskOutputProductDialog.vue": 1781605192.0421948,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/ProductionWorkOrderCardList.vue": 1781601931.1752002,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/ForwardTaskDialog.vue": 1781563767.3550124,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/tabs/OutboundPilotTab.vue": 1781583381.1088736,

ファイルの差分が大きいため隠しています
+ 0 - 0
web-admin/src/graphify-out/cache/ast/6d5161fd864604c6ee197990fa9124e2d48eb7e79a553a9318e1c78971b5498d.json


ファイルの差分が大きいため隠しています
+ 0 - 0
web-admin/src/graphify-out/cache/ast/8ea71580bbb5347bd447471bc268544140cc38a4bb131e63317fc1e4ce446e2c.json


+ 3 - 3
web-admin/src/utils/production-work-order-card-meta.ts

@@ -237,10 +237,10 @@ const CARD_META_BY_TAB: Record<ProductionWorkOrderTabKey, ProductionWorkOrderCar
     showProtocolFeeSummary: false,
     showOutboundFeeSummary: false,
     metaFields: temporaryFields,
-    allowDispatchQc: false,
+    allowDispatchQc: true,
     allowSampleReception: false,
-    allowDispatchComplete: false,
-    allowEditRemark: false,
+    allowDispatchComplete: true,
+    allowEditRemark: true,
     allowDelete: true
   }
 }

+ 8 - 4
web-admin/src/utils/qc-mine-task-groups.ts

@@ -1,7 +1,7 @@
 import type { QcWorkOrder } from '@/api/qc-work-order'
 import { fetchQcWorkOrderDetail } from '@/api/qc-work-order'
 import { fetchMyQcTaskList, type QcTask } from '@/api/qc-task'
-import { groupInboundQcWorkOrders } from '@/utils/qc-work-order-groups'
+import { groupInboundQcWorkOrders, matchesTemporaryQcSourceFilter } from '@/utils/qc-work-order-groups'
 import type { QcWorkOrderTabKey } from '@/utils/qc-work-order-tabs'
 import {
   resolveTabKeyFromWorkOrder,
@@ -51,7 +51,7 @@ function keywordMatchesWorkOrder(row: QcWorkOrder, keyword: string, tabKey: QcWo
   const tab = getQcWorkOrderTab(tabKey)!
   const fields =
     tabKey === 'temporary'
-      ? [row.workOrderNo]
+      ? [row.workOrderNo, row.productionWorkOrderNo]
       : tabKey === 'outbound_basic_experiment'
         ? [row.workOrderNo, row.applicationNo, row.projectTitle, row.customerName, row.applicationName]
         : tab.group === 'outbound'
@@ -70,8 +70,12 @@ export function filterMineEntriesByWorkOrderSearch(
     const row = entry.workOrder
     if (resolveTabKeyFromWorkOrder(row) !== tabKey) return false
     if (filters.workOrderStatus && row.workOrderStatus !== filters.workOrderStatus) return false
-    if (tab.listLayout !== 'standalone' && filters.triggerSource && row.triggerSource !== filters.triggerSource) {
-      return false
+    if (filters.triggerSource) {
+      if (tabKey === 'temporary') {
+        if (!matchesTemporaryQcSourceFilter(row, filters.triggerSource)) return false
+      } else if (tab.listLayout !== 'standalone' && row.triggerSource !== filters.triggerSource) {
+        return false
+      }
     }
     if (!keywordMatchesWorkOrder(row, filters.keyword || '', tabKey)) return false
     if (tabUsesInfusionTimeFilter(tab)) {

+ 8 - 8
web-admin/src/utils/qc-work-order-card-meta.ts

@@ -1,16 +1,17 @@
 import type { QcWorkOrder } from '@/api/qc-work-order'
-import { qcBizTypeLabel } from '@/utils/qc-labels'
 import {
   donationStatusLabel,
   donationStatusTagType,
   protocolStatusLabel,
-  protocolStatusTagType,
-  qcBizTypeTagType
+  protocolStatusTagType
 } from '@/utils/status-tag-registry'
 import type { TagType } from '@/utils/status-tag-registry'
 import type { QcWorkOrderTabKey } from '@/utils/qc-work-order-tabs'
 import { getQcWorkOrderTab } from '@/utils/qc-work-order-tabs'
 import { formatMoneyDisplay } from '@/utils/money-format'
+import {
+  isTemporaryQcFromProduction
+} from '@/utils/qc-work-order-groups'
 
 export type CardMetaFieldKind = 'text' | 'tag'
 
@@ -130,10 +131,9 @@ const outboundBasicExperimentFields: CardMetaField[] = [
 
 const temporaryFields: CardMetaField[] = [
   {
-    label: '业务类型',
-    kind: 'tag',
-    getValue: (row) => row.qcBizTypeLabel || qcBizTypeLabel('temporary'),
-    getTagType: () => qcBizTypeTagType('temporary')
+    label: '关联生产工单',
+    getValue: (row) => row.productionWorkOrderNo || '—',
+    visible: (row) => isTemporaryQcFromProduction(row)
   },
   {
     label: '产品编码',
@@ -266,7 +266,7 @@ const CARD_META_BY_TAB: Record<QcWorkOrderTabKey, QcWorkOrderCardMetaConfig> = {
   temporary: {
     tabKey: 'temporary',
     listLayout: 'standalone',
-    showTriggerTag: false,
+    showTriggerTag: true,
     showProtocolFeeSummary: false,
     showOutboundFeeSummary: false,
     metaFields: temporaryFields,

+ 20 - 0
web-admin/src/utils/qc-work-order-groups.ts

@@ -75,3 +75,23 @@ export function isGateTriggerSource(source?: string | null) {
   const ts = (source || 'reception').trim()
   return ts === 'reception' || ts === 'schedule'
 }
+
+/** 临时质检:是否由生产工单派发 */
+export function isTemporaryQcFromProduction(row: QcWorkOrder) {
+  return (row.triggerSource || '') === 'production' || !!(row.productionWorkOrderId || '').trim()
+}
+
+export function temporaryQcSourceLabel(row: QcWorkOrder) {
+  return isTemporaryQcFromProduction(row) ? '生产派发' : '手动创建'
+}
+
+export function temporaryQcSourceTagType(row: QcWorkOrder): 'warning' | 'info' {
+  return isTemporaryQcFromProduction(row) ? 'warning' : 'info'
+}
+
+export function matchesTemporaryQcSourceFilter(row: QcWorkOrder, filterValue?: string) {
+  if (!filterValue) return true
+  if (filterValue === 'production') return isTemporaryQcFromProduction(row)
+  if (filterValue === 'manual') return !isTemporaryQcFromProduction(row)
+  return (row.triggerSource || '') === filterValue
+}

+ 9 - 2
web-admin/src/views/production/production-work-order/DispatchQcWorkOrderDialog.vue

@@ -16,7 +16,10 @@
       <span
         >工单号:<b>{{ workOrderRow?.workOrderNo || '—' }}</b></span
       >
-      <span>样本编码:{{ workOrderRow?.sampleCode || '—' }}</span>
+      <span v-if="workOrderRow?.workOrderType !== 'temporary'">
+        样本编码:{{ workOrderRow?.sampleCode || '—' }}
+      </span>
+      <span v-else>工单类型:临时生产</span>
     </div>
     <el-form
       ref="formRef"
@@ -160,7 +163,11 @@
         productionTaskId: selected?.taskId,
         remark: form.remark || undefined
       })
-      ElMessage.success('质检工单派发成功')
+      ElMessage.success(
+        props.workOrderRow?.workOrderType === 'temporary'
+          ? '临时质检工单派发成功'
+          : '质检工单派发成功'
+      )
       emit('success', { sampleCode: props.workOrderRow.sampleCode })
       handleClose()
     } finally {

+ 17 - 3
web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderSingleCard.vue

@@ -12,10 +12,10 @@
             </el-tag>
             <el-tag
               v-if="cardMetaConfig.showTriggerTag"
-              :type="triggerSourceTagType(row.triggerSource)"
+              :type="resolveTriggerTagType(row)"
               size="small"
             >
-              {{ row.triggerSourceLabel || triggerSourceTabLabel(row) }}
+              {{ resolveTriggerTagLabel(row) }}
             </el-tag>
           </div>
           <dl class="qc-work-order-card__meta">
@@ -127,7 +127,7 @@
   import { workOrderStatusLabel } from '@/utils/qc-labels'
   import type { TagType } from '@/utils/status-tag-registry'
   import type { QcWorkOrderCardMetaConfig } from '@/utils/qc-work-order-card-meta'
-  import { triggerSourceTabLabel } from '@/utils/qc-work-order-groups'
+  import { triggerSourceTabLabel, temporaryQcSourceLabel, temporaryQcSourceTagType } from '@/utils/qc-work-order-groups'
   import QcWorkOrderTaskSubList from './QcWorkOrderTaskSubList.vue'
   import QcWorkOrderFeeSummaryBar from './QcWorkOrderFeeSummaryBar.vue'
   import QcWorkOrderProtocolPaymentPanel from './QcWorkOrderProtocolPaymentPanel.vue'
@@ -181,6 +181,20 @@
     return 'success'
   }
 
+  function resolveTriggerTagLabel(row: QcWorkOrder) {
+    if (props.cardMetaConfig.tabKey === 'temporary') {
+      return temporaryQcSourceLabel(row)
+    }
+    return row.triggerSourceLabel || triggerSourceTabLabel(row)
+  }
+
+  function resolveTriggerTagType(row: QcWorkOrder): TagType {
+    if (props.cardMetaConfig.tabKey === 'temporary') {
+      return temporaryQcSourceTagType(row)
+    }
+    return triggerSourceTagType(row.triggerSource)
+  }
+
   function workOrderStatusTagType(status: string): TagType {
     if (status === 'ywc') return 'success'
     if (status === 'ypz') return 'warning'

+ 45 - 26
web-admin/src/views/quality-inspection/qc-work-order/composables/inbound-view-sections.ts

@@ -17,6 +17,11 @@ import {
   appendTaskResultSections,
   type QcWorkOrderTaskView
 } from './useQcWorkOrderTaskViewSections'
+import {
+  isTemporaryQcFromProduction,
+  temporaryQcSourceLabel,
+  temporaryQcSourceTagType
+} from '@/utils/qc-work-order-groups'
 
 function formatMetric(v: unknown) {
   if (v === null || v === undefined || v === '') return '—'
@@ -159,35 +164,49 @@ export function buildTemporaryViewSections(
   detail: QcWorkOrderDetail,
   tasks: QcWorkOrderTaskView[]
 ): ViewSection[] {
+  const basicFields: ViewSection['fields'] = [
+    { label: '工单号', value: detail.workOrderNo },
+    { label: '工单类型', value: '临时', tagType: 'warning' },
+    {
+      label: '业务类型',
+      value: detail.qcBizTypeLabel || qcBizTypeLabel('temporary'),
+      tagType: 'warning'
+    },
+    {
+      label: '工单来源',
+      value: temporaryQcSourceLabel(detail),
+      tagType: temporaryQcSourceTagType(detail)
+    }
+  ]
+  if (isTemporaryQcFromProduction(detail)) {
+    basicFields.push({
+      label: '关联生产工单',
+      value: detail.productionWorkOrderNo || '—'
+    })
+  }
+  basicFields.push(
+    { label: '产品编码', value: detail.cellProductCode || '—' },
+    { label: '产品名称', value: detail.cellProductName || '—' },
+    { label: '产品类型', value: detail.cellProductTypeName || '—' },
+    { label: '代次', value: detail.cellProductPassage || '—' },
+    { label: '规格', value: detail.cellProductSpecName || '—' },
+    {
+      label: '状态',
+      value: workOrderStatusLabel(detail.workOrderStatus),
+      tagType:
+        detail.workOrderStatus === 'ywc'
+          ? 'success'
+          : detail.workOrderStatus === 'ypz'
+            ? 'warning'
+            : 'info'
+    },
+    { label: '备注', value: detail.remark || '—', span: true },
+    { label: '创建时间', value: detail.createTime || '—' }
+  )
   return [
     {
       title: '基本信息',
-      fields: [
-        { label: '工单号', value: detail.workOrderNo },
-        { label: '工单类型', value: '临时', tagType: 'warning' },
-        {
-          label: '业务类型',
-          value: detail.qcBizTypeLabel || qcBizTypeLabel('temporary'),
-          tagType: 'warning'
-        },
-        { label: '产品编码', value: detail.cellProductCode || '—' },
-        { label: '产品名称', value: detail.cellProductName || '—' },
-        { label: '产品类型', value: detail.cellProductTypeName || '—' },
-        { label: '代次', value: detail.cellProductPassage || '—' },
-        { label: '规格', value: detail.cellProductSpecName || '—' },
-        {
-          label: '状态',
-          value: workOrderStatusLabel(detail.workOrderStatus),
-          tagType:
-            detail.workOrderStatus === 'ywc'
-              ? 'success'
-              : detail.workOrderStatus === 'ypz'
-                ? 'warning'
-                : 'info'
-        },
-        { label: '备注', value: detail.remark || '—', span: true },
-        { label: '创建时间', value: detail.createTime || '—' }
-      ]
+      fields: basicFields
     },
     ...appendTaskResultSections(detail, tasks)
   ]

+ 6 - 2
web-admin/src/views/quality-inspection/qc-work-order/composables/useQcWorkOrderTabPage.ts

@@ -20,6 +20,10 @@ import {
 } from '@/utils/qc-work-order-tabs'
 import { getCardMetaConfig } from '@/utils/qc-work-order-card-meta'
 
+function shouldApplyTriggerSourceFilter(tabKey: QcWorkOrderTabKey, tabLayout: string) {
+  return tabLayout !== 'standalone' || tabKey === 'temporary'
+}
+
 export type QcWorkOrderTabPageMode = 'manage' | 'mine'
 
 export function useQcWorkOrderTabPage(
@@ -71,7 +75,7 @@ export function useQcWorkOrderTabPage(
       keyword: searchForm.keyword || undefined,
       workOrderStatus: searchForm.workOrderStatus || undefined,
       triggerSource:
-        tab.listLayout !== 'standalone' && searchForm.triggerSource
+        shouldApplyTriggerSourceFilter(tabKey.value, tab.listLayout) && searchForm.triggerSource
           ? searchForm.triggerSource
           : undefined,
       tabKey: tabKey.value,
@@ -116,7 +120,7 @@ export function useQcWorkOrderTabPage(
         keyword: searchForm.keyword || undefined,
         workOrderStatus: searchForm.workOrderStatus || undefined,
         triggerSource:
-          tab.listLayout !== 'standalone' && searchForm.triggerSource
+          shouldApplyTriggerSourceFilter(tabKey.value, tab.listLayout) && searchForm.triggerSource
             ? searchForm.triggerSource
             : undefined,
         ...toWorkOrderListQuery(tab),

+ 17 - 6
web-admin/src/views/quality-inspection/qc-work-order/tabs/QcWorkOrderTabPanel.vue

@@ -21,20 +21,24 @@
               <el-option label="已作废" value="yzf" />
             </el-select>
           </el-form-item>
-          <el-form-item v-if="tabConfig.listLayout !== 'standalone'" label="触发来源">
+          <el-form-item v-if="tabConfig.listLayout !== 'standalone' || tabKey === 'temporary'" label="工单来源">
             <el-select
               v-model="searchForm.triggerSource"
               placeholder="全部"
               clearable
               style="width: 100%"
             >
-              <template v-if="tabConfig.group === 'inbound'">
+              <template v-if="tabKey === 'temporary'">
+                <el-option label="生产派发" value="production" />
+                <el-option label="手动创建" value="manual" />
+              </template>
+              <template v-else-if="tabConfig.group === 'inbound'">
                 <el-option label="样本接收" value="reception" />
               </template>
               <template v-else-if="tabConfig.listLayout === 'outbound-grouped'">
                 <el-option label="计划质检" value="schedule" />
               </template>
-              <el-option label="生产过程" value="production" />
+              <el-option v-if="tabKey !== 'temporary'" label="生产过程" value="production" />
             </el-select>
           </el-form-item>
           <el-form-item :label="filterTimeLabel">
@@ -115,20 +119,27 @@
 
         <div v-show="filterExpanded" id="my-qc-task-filter-extra" class="filter-extra">
           <div class="filter-grid my-qc-task-filter-extra-grid">
-            <el-form-item v-if="tabConfig.listLayout !== 'standalone'" label="触发来源">
+            <el-form-item
+              v-if="tabConfig.listLayout !== 'standalone' || tabKey === 'temporary'"
+              label="工单来源"
+            >
               <el-select
                 v-model="searchForm.triggerSource"
                 placeholder="全部"
                 clearable
                 style="width: 100%"
               >
-                <template v-if="tabConfig.group === 'inbound'">
+                <template v-if="tabKey === 'temporary'">
+                  <el-option label="生产派发" value="production" />
+                  <el-option label="手动创建" value="manual" />
+                </template>
+                <template v-else-if="tabConfig.group === 'inbound'">
                   <el-option label="样本接收" value="reception" />
                 </template>
                 <template v-else-if="tabConfig.listLayout === 'outbound-grouped'">
                   <el-option label="计划质检" value="schedule" />
                 </template>
-                <el-option label="生产过程" value="production" />
+                <el-option v-if="tabKey !== 'temporary'" label="生产过程" value="production" />
               </el-select>
             </el-form-item>
             <el-form-item label="任务类型">

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません