zlwu 5 月之前
父节点
当前提交
87dbbf1247
共有 25 个文件被更改,包括 3016 次插入 和 2386 次删除
  1. 1 1
      backend/app.pid
  2. 0 0
      backend/app/graphify-out/cache/ast/2d6b5257b87b8fca53569768ea8998f4b03fc934a5ec5270a5562da5a001386c.json
  3. 0 0
      backend/app/graphify-out/cache/ast/315b764a28716a51e93168931553987bc347c2285c1c504f3031d9e6c9d74146.json
  4. 0 0
      backend/app/graphify-out/cache/ast/92e51a2383ec6fcceaf9878101280ca5ccdb76826238a9d457e6b8b7ea127cba.json
  5. 0 0
      backend/app/graphify-out/cache/ast/ff12bcdb64e44ff49b0ac0b7b072aed83434517e3d42b2187ced789123e5ad2c.json
  6. 2 0
      backend/app/schemas/production_task.py
  7. 1242 1406
      backend/graphify-out/.graphify_analysis.json
  8. 137 130
      backend/graphify-out/.graphify_extract.json
  9. 123 88
      backend/graphify-out/GRAPH_REPORT.md
  10. 1 1
      backend/graphify-out/graph.html
  11. 112 112
      backend/graphify-out/graph.json
  12. 4 4
      backend/graphify-out/manifest.json
  13. 493 470
      web-admin/graphify-out/.graphify_analysis.json
  14. 777 88
      web-admin/graphify-out/.graphify_extract.json
  15. 61 54
      web-admin/graphify-out/GRAPH_REPORT.md
  16. 1 1
      web-admin/graphify-out/graph.html
  17. 7 7
      web-admin/graphify-out/manifest.json
  18. 0 0
      web-admin/src/graphify-out/cache/ast/13b280c56260b23c5f5019313e397f18d32123034f825439d28c47ab9d56e87e.json
  19. 0 0
      web-admin/src/graphify-out/cache/ast/30a4dc3504ebc5f26cd1e91e7bbe3f20f0353e34bcba5b80e45cbf1135b9877f.json
  20. 0 0
      web-admin/src/graphify-out/cache/ast/39ea3a02c254cea29029f8613c104395266e5ddb2d70825ef398ea37999c3922.json
  21. 1 0
      web-admin/src/graphify-out/cache/ast/ab7ada5af3697d125c1e952c09a82a170c633200708c6435b41dcb917193c7f8.json
  22. 1 0
      web-admin/src/graphify-out/cache/ast/df4a50457577371e356844f3ee5be9d61ee4f3c4ea83c8ce010f59c0f86b00bc.json
  23. 1 0
      web-admin/src/graphify-out/cache/ast/df92ca9d807c40f21dbd3c36c4c8526973367447e23d4dc5ec78e25dec1a219b.json
  24. 14 12
      web-admin/src/views/production/production-work-order/StepDetailPanel.vue
  25. 38 12
      web-admin/src/views/production/production-work-order/useTaskStepEditor.ts

+ 1 - 1
backend/app.pid

@@ -1 +1 @@
-28319
+71550

文件差异内容过多而无法显示
+ 0 - 0
backend/app/graphify-out/cache/ast/2d6b5257b87b8fca53569768ea8998f4b03fc934a5ec5270a5562da5a001386c.json


文件差异内容过多而无法显示
+ 0 - 0
backend/app/graphify-out/cache/ast/315b764a28716a51e93168931553987bc347c2285c1c504f3031d9e6c9d74146.json


文件差异内容过多而无法显示
+ 0 - 0
backend/app/graphify-out/cache/ast/92e51a2383ec6fcceaf9878101280ca5ccdb76826238a9d457e6b8b7ea127cba.json


文件差异内容过多而无法显示
+ 0 - 0
backend/app/graphify-out/cache/ast/ff12bcdb64e44ff49b0ac0b7b072aed83434517e3d42b2187ced789123e5ad2c.json


+ 2 - 0
backend/app/schemas/production_task.py

@@ -67,12 +67,14 @@ class TaskStepOutputItem(BaseModel):
     output_type_id: Optional[str] = None
     output_name: Optional[str] = None
     output_barcode: Optional[str] = None
+    remark: Optional[str] = None
 
 
 class TaskStepDataCollectionItem(BaseModel):
     collection_name: Optional[str] = None
     unit: Optional[str] = None
     collection_value: Optional[str] = None
+    remark: Optional[str] = None
 
 
 class TaskInputItem(BaseModel):

文件差异内容过多而无法显示
+ 1242 - 1406
backend/graphify-out/.graphify_analysis.json


文件差异内容过多而无法显示
+ 137 - 130
backend/graphify-out/.graphify_extract.json


+ 123 - 88
backend/graphify-out/GRAPH_REPORT.md

@@ -1,12 +1,12 @@
 # Graph Report - app  (2026-05-21)
 
 ## Corpus Check
-- 135 files · ~119,855 words
+- 135 files · ~119,965 words
 - Verdict: corpus is large enough that graph structure adds value.
 
 ## Summary
-- 2410 nodes · 9421 edges · 50 communities detected
-- Extraction: 42% EXTRACTED · 58% INFERRED · 0% AMBIGUOUS · INFERRED: 5467 edges (avg confidence: 0.63)
+- 2411 nodes · 9448 edges · 57 communities detected
+- Extraction: 42% EXTRACTED · 58% INFERRED · 0% AMBIGUOUS · INFERRED: 5492 edges (avg confidence: 0.63)
 - Token cost: 0 input · 0 output
 
 ## Community Hubs (Navigation)
@@ -54,16 +54,23 @@
 - [[_COMMUNITY_Community 41|Community 41]]
 - [[_COMMUNITY_Community 42|Community 42]]
 - [[_COMMUNITY_Community 43|Community 43]]
+- [[_COMMUNITY_Community 44|Community 44]]
+- [[_COMMUNITY_Community 45|Community 45]]
 - [[_COMMUNITY_Community 46|Community 46]]
 - [[_COMMUNITY_Community 47|Community 47]]
 - [[_COMMUNITY_Community 48|Community 48]]
 - [[_COMMUNITY_Community 49|Community 49]]
 - [[_COMMUNITY_Community 50|Community 50]]
-- [[_COMMUNITY_Community 51|Community 51]]
+- [[_COMMUNITY_Community 53|Community 53]]
+- [[_COMMUNITY_Community 54|Community 54]]
+- [[_COMMUNITY_Community 55|Community 55]]
+- [[_COMMUNITY_Community 56|Community 56]]
+- [[_COMMUNITY_Community 57|Community 57]]
+- [[_COMMUNITY_Community 58|Community 58]]
 
 ## God Nodes (most connected - your core abstractions)
-1. `success_response()` - 379 edges
-2. `error_response()` - 304 edges
+1. `success_response()` - 380 edges
+2. `error_response()` - 305 edges
 3. `SysUser` - 217 edges
 4. `BizQcMaterialUsage` - 197 edges
 5. `BizMaterialStockLog` - 193 edges
@@ -88,60 +95,60 @@
 ## Communities
 
 ### Community 0 - "Community 0"
-Cohesion: 0.01
-Nodes (378): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+370 more)
+Cohesion: 0.02
+Nodes (387): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+379 more)
 
 ### Community 1 - "Community 1"
 Cohesion: 0.02
-Nodes (387): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+379 more)
+Nodes (369): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+361 more)
 
 ### Community 2 - "Community 2"
-Cohesion: 0.06
-Nodes (216): InsuranceCompanyCreateBody, InsuranceCompanyInvoiceCreateBody, InsuranceCompanyInvoiceUpdateBody, InsuranceCompanyUpdateBody, InsuranceProjectPriceCreateBody, InsuranceProjectPriceUpdateBody, 保险公司及险种价格管理 API(保险公司 + 开票信息 + 险种价格), ProcessDefCreateBody (+208 more)
+Cohesion: 0.05
+Nodes (229): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约), StorageFacilityCreateBody (+221 more)
 
 ### Community 3 - "Community 3"
 Cohesion: 0.02
-Nodes (181): generate_uuid(), create_consumable_pack(), get_consumable_pack(), get_pack_detail(), _item_row_to_dict(), list_all_packs(), list_consumable_packs(), pack_code_exists() (+173 more)
+Nodes (192): generate_uuid(), _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), options_list() (+184 more)
 
 ### Community 4 - "Community 4"
-Cohesion: 0.06
-Nodes (170): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+162 more)
+Cohesion: 0.03
+Nodes (138): create_collection_protocol(), delete_collection_protocol(), _ensure_customer_for_mother(), get_collection_protocol_detail(), _get_current_user_id(), _get_tenant_no(), list_collection_protocol_audits(), list_collection_protocols() (+130 more)
 
 ### Community 5 - "Community 5"
-Cohesion: 0.03
-Nodes (131): list_cell_sample_types(), list_collection_regions(), list_customers(), list_protocol_nos(), list_sample_codes(), _get_tenant_no(), list_collection_protocol_audits(), list_collection_protocols() (+123 more)
+Cohesion: 0.08
+Nodes (136): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+128 more)
 
 ### Community 6 - "Community 6"
-Cohesion: 0.03
-Nodes (97): list_roles_for_select(), _avatar_url_field(), _build_user_info_payload(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线), 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。 (+89 more)
+Cohesion: 0.04
+Nodes (105): _format_attachment_file_size(), get_protocol_nos_used_in_protocols(), urls_to_attachment_list(), _accept_conclusion_label(), _attach_reception_detail(), complete_production_work_order(), create_production_work_order_from_reception(), _enrich_wo_items() (+97 more)
 
 ### Community 7 - "Community 7"
 Cohesion: 0.03
-Nodes (54): get_designer_data(), BaseStorage, convert_heic_to_jpeg(), get_storage(), LocalStorage, MinIOStorage, OSSStorage, process_image_content() (+46 more)
+Nodes (55): get_designer_data(), BaseStorage, convert_heic_to_jpeg(), get_storage(), LocalStorage, MinIOStorage, OSSStorage, process_image_content() (+47 more)
 
 ### Community 8 - "Community 8"
-Cohesion: 0.05
-Nodes (91): _format_attachment_file_size(), urls_to_attachment_list(), _accept_conclusion_label(), _attach_reception_detail(), complete_production_work_order(), create_production_work_order_from_reception(), _enrich_wo_items(), _fmt_dt() (+83 more)
+Cohesion: 0.04
+Nodes (65): list_roles_for_select(), _avatar_url_field(), _build_user_info_payload(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线), 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。 (+57 more)
 
 ### Community 9 - "Community 9"
-Cohesion: 0.07
-Nodes (67): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, list_storage_slots(), 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+59 more)
+Cohesion: 0.08
+Nodes (36): BaseHTTPMiddleware, parse_admin_request_json(), 运营 Web(/web/admin)JSON 请求体解析。  与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。      Returns:, ApiCryptoError, _b64url_decode(), _b64url_encode(), decrypt_json() (+28 more)
 
 ### Community 10 - "Community 10"
-Cohesion: 0.32
-Nodes (51): ConsumableCreateBody, ConsumablePackCreateBody, ConsumablePackUpdateBody, ConsumableUpdateBody, OutputTypeCreateBody, OutputTypeUpdateBody, PackItemInput, ProcessCategoryCreateBody (+43 more)
+Cohesion: 0.16
+Nodes (32): _create_insurance_company(), _create_insurance_company_invoice(), _create_insurance_project_price(), delete_insurance_company(), delete_insurance_company_invoice(), delete_insurance_project_price(), _fmt_dt(), _generate_uuid() (+24 more)
 
 ### Community 11 - "Community 11"
-Cohesion: 0.08
-Nodes (36): BaseHTTPMiddleware, parse_admin_request_json(), 运营 Web(/web/admin)JSON 请求体解析。  与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。      Returns:, ApiCryptoError, _b64url_decode(), _b64url_encode(), decrypt_json() (+28 more)
+Cohesion: 0.15
+Nodes (31): _audit_to_dict(), batch_delete_donations(), _collection_to_dict(), _create_collection(), create_donation(), _create_party(), _create_samples(), _create_transport() (+23 more)
 
 ### Community 12 - "Community 12"
 Cohesion: 0.12
 Nodes (11): get_wechat_pay_client(), get_wechat_pay_v2(), 微信支付工具模块  支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.ht, 统一下单接口 (V3)          Args:             out_trade_no: 商户订单号             total, 申请退款          Args:             out_trade_no: 商户订单号             total_amount, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API)          Args:             out_trade_no: 商户订单号             tot, 生成签名 V3 (SHA256 with RSA) (+3 more)
 
 ### Community 13 - "Community 13"
-Cohesion: 0.21
-Nodes (19): _consumable_row_to_dict(), create_process(), _create_sub_consumable(), _create_sub_data_collection(), _create_sub_output(), _create_sub_reagent(), _data_collection_row_to_dict(), get_process() (+11 more)
+Cohesion: 0.15
+Nodes (22): Config, Config, ProductReviewMediaBase, ProductReviewMediaCreate, ProductReviewMediaCreateBatch, ProductReviewMediaListResponse, ProductReviewMediaResponse, ProductReviewMediaUpdate (+14 more)
 
 ### Community 14 - "Community 14"
 Cohesion: 0.17
@@ -160,173 +167,201 @@ Cohesion: 0.21
 Nodes (15): batch_issue_protocol_nos(), batch_revoke_protocol_nos(), create_protocol_no(), enrich_issued_user_names(), get_protocol_no(), list_protocol_nos(), _parse_issued_time(), protocol_no_exists() (+7 more)
 
 ### Community 18 - "Community 18"
+Cohesion: 0.17
+Nodes (15): Config, QuotationBase, QuotationCreate, QuotationDetailResponse, QuotationItemBase, QuotationItemCreate, QuotationItemResponse, QuotationItemUpdate (+7 more)
+
+### Community 19 - "Community 19"
+Cohesion: 0.21
+Nodes (13): _access_log_to_dict(), create_access_log(), create_clean_room(), get_access_log(), get_clean_room(), list_access_logs(), list_clean_rooms(), room_code_exists() (+5 more)
+
+### Community 20 - "Community 20"
+Cohesion: 0.25
+Nodes (13): code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), _norm_status(), options_list() (+5 more)
+
+### Community 21 - "Community 21"
 Cohesion: 0.26
 Nodes (12): batch_issue_sample_codes(), batch_revoke_sample_codes(), create_sample_code(), get_sample_code(), list_sample_codes(), _parse_issued_time(), 样本编码池 CRUD(biz_sample_code), _resolve_issued_user_display_name() (+4 more)
 
-### Community 19 - "Community 19"
+### Community 22 - "Community 22"
 Cohesion: 0.24
 Nodes (9): 微信消息通知服务  支持微信小程序模板消息推送  使用方式:     from app.core.wechat_message import Wech, 发送模板消息                  Args:             openid: 用户openid             templ, send_delivery_notice(), send_delivery_warning(), send_order_status(), send_payment_success(), send_refund_result(), send_urge_notification() (+1 more)
 
-### Community 20 - "Community 20"
+### Community 23 - "Community 23"
+Cohesion: 0.22
+Nodes (12): Config, InquiryBase, InquiryCreate, InquiryDetailResponse, InquiryItemBase, InquiryItemCreate, InquiryItemResponse, InquiryListResponse (+4 more)
+
+### Community 24 - "Community 24"
+Cohesion: 0.23
+Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
+
+### Community 25 - "Community 25"
+Cohesion: 0.3
+Nodes (10): create_consumable_pack(), get_consumable_pack(), get_pack_detail(), _item_row_to_dict(), list_all_packs(), list_consumable_packs(), pack_code_exists(), _row_to_dict() (+2 more)
+
+### Community 26 - "Community 26"
 Cohesion: 0.27
 Nodes (11): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), 保留匹配节点及其全部上级,供关键词检索后仍能正确组树。 (+3 more)
 
-### Community 21 - "Community 21"
+### Community 27 - "Community 27"
 Cohesion: 0.29
 Nodes (9): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), _row_to_dict(), soft_delete_menu() (+1 more)
 
-### Community 22 - "Community 22"
-Cohesion: 0.36
-Nodes (9): deduct_for_task(), _display_remark(), list_usages(), list_usages_by_task(), _parse_receiver_purpose_from_remark(), _resolve_receiver_purpose(), revert_task_material_usages(), _row_to_dict() (+1 more)
-
-### Community 23 - "Community 23"
+### Community 28 - "Community 28"
 Cohesion: 0.31
 Nodes (8): consumable_code_exists(), create_consumable(), get_consumable(), list_consumables(), 耗材 CRUD(biz_consumable), _row_to_dict(), soft_delete_consumable(), update_consumable()
 
-### Community 24 - "Community 24"
+### Community 29 - "Community 29"
+Cohesion: 0.31
+Nodes (8): create_sop_document(), get_sop_document(), list_sop_documents(), SOP文档 CRUD(biz_sop_document), _row_to_dict(), soft_delete_sop_document(), sop_code_exists(), update_sop_document()
+
+### Community 30 - "Community 30"
 Cohesion: 0.31
 Nodes (8): create_express_company(), express_code_exists(), get_express_company(), list_express_companies(), 快递公司 CRUD(biz_express_company), _row_to_dict(), soft_delete_express_company(), update_express_company()
 
-### Community 25 - "Community 25"
+### Community 31 - "Community 31"
 Cohesion: 0.38
 Nodes (9): create_check_item(), get_check_item(), item_code_exists(), list_active_check_items(), list_check_items(), _order_query(), _row_to_dict(), soft_delete_check_item() (+1 more)
 
-### Community 26 - "Community 26"
+### Community 32 - "Community 32"
 Cohesion: 0.27
 Nodes (8): create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options(), 字典数据 CRUD(sys_dict_data), _row_to_dict(), soft_delete_dict_data(), update_dict_data()
 
-### Community 27 - "Community 27"
+### Community 33 - "Community 33"
 Cohesion: 0.31
 Nodes (8): category_code_exists(), create_process_category(), get_process_category(), list_process_categories(), 工艺工序分类 CRUD(biz_process_category), _row_to_dict(), soft_delete_process_category(), update_process_category()
 
-### Community 28 - "Community 28"
+### Community 34 - "Community 34"
 Cohesion: 0.31
 Nodes (8): create_item_unit(), get_item_unit(), list_item_units(), 物品单位 CRUD(biz_item_unit), _row_to_dict(), soft_delete_item_unit(), unit_code_exists(), update_item_unit()
 
-### Community 29 - "Community 29"
-Cohesion: 0.31
-Nodes (8): create_customer(), get_customer(), id_card_taken(), list_customers(), 客户 CRUD(biz_customer), _row_to_dict(), soft_delete_customer(), update_customer()
-
-### Community 30 - "Community 30"
+### Community 35 - "Community 35"
 Cohesion: 0.31
 Nodes (8): create_cell_sample_type(), get_cell_sample_type(), list_cell_sample_types(), 细胞样本类型 CRUD(biz_cell_sample_type), _row_to_dict(), soft_delete_cell_sample_type(), type_code_exists(), update_cell_sample_type()
 
-### Community 31 - "Community 31"
+### Community 36 - "Community 36"
 Cohesion: 0.31
 Nodes (8): create_output_type(), get_output_type(), list_output_types(), 工艺产出物类型 CRUD(biz_output_type), _row_to_dict(), soft_delete_output_type(), type_code_exists(), update_output_type()
 
-### Community 32 - "Community 32"
+### Community 37 - "Community 37"
+Cohesion: 0.31
+Nodes (9): appointment_no_exists(), create_exhibition_appointment(), _generate_appointment_no(), get_exhibition_appointment(), list_exhibition_appointments(), 展览预约 CRUD(biz_exhibition_appointment), 生成预约编号:YYYYMMDD + 6位序号(如 20260515000001), soft_delete_exhibition_appointment() (+1 more)
+
+### Community 38 - "Community 38"
 Cohesion: 0.36
 Nodes (7): create_post(), get_post(), list_posts(), post_code_exists(), _row_to_dict(), soft_delete_post(), update_post()
 
-### Community 33 - "Community 33"
+### Community 39 - "Community 39"
+Cohesion: 0.36
+Nodes (7): create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), _row_to_dict(), soft_delete_dict_type(), update_dict_type()
+
+### Community 40 - "Community 40"
 Cohesion: 0.36
 Nodes (7): create_tenant(), get_tenant(), list_tenants(), _row_to_dict(), soft_delete_tenant(), tenant_no_exists(), update_tenant()
 
-### Community 34 - "Community 34"
+### Community 41 - "Community 41"
 Cohesion: 0.36
 Nodes (7): create_reagent(), get_reagent(), list_reagents(), reagent_code_exists(), _row_to_dict(), soft_delete_reagent(), update_reagent()
 
-### Community 35 - "Community 35"
+### Community 42 - "Community 42"
 Cohesion: 0.39
 Nodes (8): create_lab_item(), get_lab_item(), item_code_exists(), list_active_lab_items(), list_lab_items(), _row_to_dict(), soft_delete_lab_item(), update_lab_item()
 
-### Community 36 - "Community 36"
+### Community 43 - "Community 43"
 Cohesion: 0.36
 Nodes (7): create_site(), get_site(), list_sites(), _row_to_dict(), site_code_exists(), soft_delete_site(), update_site()
 
-### Community 37 - "Community 37"
+### Community 44 - "Community 44"
 Cohesion: 0.29
 Nodes (2): BaseModel, SoftDeleteModel
 
-### Community 38 - "Community 38"
+### Community 45 - "Community 45"
 Cohesion: 0.38
 Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。     约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断;     若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
 
-### Community 39 - "Community 39"
+### Community 46 - "Community 46"
 Cohesion: 0.5
 Nodes (3): BaseSettings, Config, Settings
 
-### Community 40 - "Community 40"
+### Community 47 - "Community 47"
 Cohesion: 0.5
 Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
 
-### Community 41 - "Community 41"
+### Community 48 - "Community 48"
 Cohesion: 0.67
 Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)
 
-### Community 42 - "Community 42"
+### Community 49 - "Community 49"
 Cohesion: 1.0
 Nodes (1): 请求级别的用户上下文变量  通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
 
-### Community 43 - "Community 43"
+### Community 50 - "Community 50"
 Cohesion: 1.0
 Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
 
-### Community 46 - "Community 46"
+### Community 53 - "Community 53"
 Cohesion: 1.0
 Nodes (1): 发送订单状态通知                  Args:             openid: 用户openid             ord
 
-### Community 47 - "Community 47"
+### Community 54 - "Community 54"
 Cohesion: 1.0
 Nodes (1): 发送支付成功通知                  Args:             openid: 用户openid             ord
 
-### Community 48 - "Community 48"
+### Community 55 - "Community 55"
 Cohesion: 1.0
 Nodes (1): 发送配送通知                  Args:             openid: 配送员openid             task
 
-### Community 49 - "Community 49"
+### Community 56 - "Community 56"
 Cohesion: 1.0
 Nodes (1): 发送配送时效预警                  Args:             openid: 配送员openid             ta
 
-### Community 50 - "Community 50"
+### Community 57 - "Community 57"
 Cohesion: 1.0
 Nodes (1): 发送退款结果通知                  Args:             openid: 用户openid             ord
 
-### Community 51 - "Community 51"
+### Community 58 - "Community 58"
 Cohesion: 1.0
 Nodes (1): 发送催单通知给配送员                  Args:             deliver_openid: 配送员openid
 
 ## Knowledge Gaps
 - **90 isolated node(s):** `刷新会话 TTL(refreshToken 续期;已登录用户每次 API 校验通过后滑动续期)`, `写入 refreshToken(用于 one-time 使用/吊销)`, `根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期)`, `登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。`, `Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。` (+85 more)
   These have ≤1 connection - possible missing edges or undocumented components.
-- **Thin community `Community 37`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
+- **Thin community `Community 44`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 40`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
+- **Thin community `Community 47`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 41`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)`
+- **Thin community `Community 48`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 42`** (2 nodes): `context.py`, `请求级别的用户上下文变量  通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
+- **Thin community `Community 49`** (2 nodes): `context.py`, `请求级别的用户上下文变量  通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 43`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
+- **Thin community `Community 50`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 46`** (1 nodes): `发送订单状态通知                  Args:             openid: 用户openid             ord`
+- **Thin community `Community 53`** (1 nodes): `发送订单状态通知                  Args:             openid: 用户openid             ord`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 47`** (1 nodes): `发送支付成功通知                  Args:             openid: 用户openid             ord`
+- **Thin community `Community 54`** (1 nodes): `发送支付成功通知                  Args:             openid: 用户openid             ord`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 48`** (1 nodes): `发送配送通知                  Args:             openid: 配送员openid             task`
+- **Thin community `Community 55`** (1 nodes): `发送配送通知                  Args:             openid: 配送员openid             task`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 49`** (1 nodes): `发送配送时效预警                  Args:             openid: 配送员openid             ta`
+- **Thin community `Community 56`** (1 nodes): `发送配送时效预警                  Args:             openid: 配送员openid             ta`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 50`** (1 nodes): `发送退款结果通知                  Args:             openid: 用户openid             ord`
+- **Thin community `Community 57`** (1 nodes): `发送退款结果通知                  Args:             openid: 用户openid             ord`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 51`** (1 nodes): `发送催单通知给配送员                  Args:             deliver_openid: 配送员openid`
+- **Thin community `Community 58`** (1 nodes): `发送催单通知给配送员                  Args:             deliver_openid: 配送员openid`
   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 `generate_uuid()` connect `Community 3` to `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 11`, `Community 13`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 20`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`?**
+- **Why does `generate_uuid()` connect `Community 3` to `Community 0`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 11`, `Community 15`, `Community 16`, `Community 17`, `Community 19`, `Community 20`, `Community 21`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`, `Community 38`, `Community 39`, `Community 40`, `Community 41`, `Community 42`, `Community 43`?**
   _High betweenness centrality (0.124) - this node is a cross-community bridge._
-- **Why does `SysUser` connect `Community 0` to `Community 2`, `Community 4`, `Community 6`, `Community 9`, `Community 10`, `Community 17`, `Community 18`?**
-  _High betweenness centrality (0.084) - this node is a cross-community bridge._
-- **Why does `success_response()` connect `Community 1` to `Community 0`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 9`, `Community 41`, `Community 16`?**
-  _High betweenness centrality (0.066) - this node is a cross-community bridge._
-- **Are the 378 inferred relationships involving `success_response()` (e.g. with `web_login_rsa_public_key()` and `web_login()`) actually correct?**
-  _`success_response()` has 378 INFERRED edges - model-reasoned connections that need verification._
-- **Are the 350 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
-  _`str` has 350 INFERRED edges - model-reasoned connections that need verification._
-- **Are the 303 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `web_login()`) actually correct?**
-  _`error_response()` has 303 INFERRED edges - model-reasoned connections that need verification._
+- **Why does `SysUser` connect `Community 1` to `Community 2`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 10`, `Community 17`, `Community 21`?**
+  _High betweenness centrality (0.083) - this node is a cross-community bridge._
+- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 4`, `Community 5`, `Community 7`, `Community 8`, `Community 10`, `Community 48`, `Community 16`?**
+  _High betweenness centrality (0.067) - this node is a cross-community bridge._
+- **Are the 379 inferred relationships involving `success_response()` (e.g. with `web_login_rsa_public_key()` and `web_login()`) actually correct?**
+  _`success_response()` has 379 INFERRED edges - model-reasoned connections that need verification._
+- **Are the 351 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
+  _`str` has 351 INFERRED edges - model-reasoned connections that need verification._
+- **Are the 304 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `web_login()`) actually correct?**
+  _`error_response()` has 304 INFERRED edges - model-reasoned connections that need verification._
 - **Are the 215 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤)  data_scope 值:   1 = 全部数据   2 = 本部门数据   3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
   _`SysUser` has 215 INFERRED edges - model-reasoned connections that need verification._

文件差异内容过多而无法显示
+ 1 - 1
backend/graphify-out/graph.html


文件差异内容过多而无法显示
+ 112 - 112
backend/graphify-out/graph.json


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

@@ -30,7 +30,7 @@
   "/Users/wuzilong/work/00code/zkxw/backend/app/models/research_donation.py": 1779177348.5945773,
   "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py": 1779284411.5179992,
   "/Users/wuzilong/work/00code/zkxw/backend/app/models/base.py": 1778578258.0821667,
-  "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/process_route.py": 1779171106.9178398,
+  "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/process_route.py": 1779367496.1718137,
   "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py": 1778578258.0939043,
   "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/delivery.py": 1778578258.0949655,
   "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/price_list.py": 1778578258.096609,
@@ -60,7 +60,7 @@
   "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/category.py": 1778578258.0941947,
   "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/leave.py": 1778666088.7680702,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_task.py": 1779332373.211639,
-  "/Users/wuzilong/work/00code/zkxw/backend/app/crud/process_route.py": 1779265696.2771301,
+  "/Users/wuzilong/work/00code/zkxw/backend/app/crud/process_route.py": 1779367598.0383394,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_code.py": 1779279460.690872,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_task_result.py": 1779331731.6720955,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/post.py": 1779265648.38155,
@@ -74,7 +74,7 @@
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/tenant.py": 1779265611.0532296,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py": 1779265707.1662717,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sop_document.py": 1779265721.9928973,
-  "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779352518.519091,
+  "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779363964.0353281,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_item.py": 1779265661.482352,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py": 1779265718.524432,
   "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1779329214.3583212,
@@ -128,7 +128,7 @@
   "/Users/wuzilong/work/00code/zkxw/backend/app/api/workflow.py": 1779266232.4568832,
   "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py": 1779304425.1104686,
   "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py": 1779281097.279193,
-  "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py": 1779343860.3325307,
+  "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py": 1779363804.634908,
   "/Users/wuzilong/work/00code/zkxw/backend/app/api/leave.py": 1779266168.8693042,
   "/Users/wuzilong/work/00code/zkxw/backend/app/services/workflow_callback.py": 1778727966.7277644,
   "/Users/wuzilong/work/00code/zkxw/backend/app/services/workflow_engine.py": 1778634664.6293883,

文件差异内容过多而无法显示
+ 493 - 470
web-admin/graphify-out/.graphify_analysis.json


+ 777 - 88
web-admin/graphify-out/.graphify_extract.json

@@ -8300,21 +8300,21 @@
       "label": "if()",
       "file_type": "code",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1049"
+      "source_location": "L1055"
     },
     {
       "id": "process_route_index_get",
       "label": "get()",
       "file_type": "code",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1203"
+      "source_location": "L1255"
     },
     {
       "id": "process_route_index_set",
       "label": "set()",
       "file_type": "code",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1213"
+      "source_location": "L1265"
     },
     {
       "id": "views_production_sop_index_vue",
@@ -8386,6 +8386,181 @@
       "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
       "source_location": "L53"
     },
+    {
+      "id": "production_work_order_usetaskstepeditor_ensureallstepunitoptions",
+      "label": "ensureAllStepUnitOptions()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L253"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
+      "label": "loadConfigReferenceData()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L294"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "label": "loadTaskDetail()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L318"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_ondragstart",
+      "label": "onDragStart()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L333"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_ondroptocenter",
+      "label": "onDropToCenter()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L337"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_onstepdragend",
+      "label": "onStepDragEnd()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L351"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_selectstep",
+      "label": "selectStep()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L360"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_handlecopystep",
+      "label": "handleCopyStep()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L361"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_handledeletestep",
+      "label": "handleDeleteStep()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L372"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_savestepbasic",
+      "label": "saveStepBasic()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L386"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_onsopidschange",
+      "label": "onSopIdsChange()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L399"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_addreagentrow",
+      "label": "addReagentRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L404"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_removereagentrow",
+      "label": "removeReagentRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L412"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_savereagents",
+      "label": "saveReagents()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L413"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_addconsumablerow",
+      "label": "addConsumableRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L425"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_removeconsumablerow",
+      "label": "removeConsumableRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L433"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_saveconsumables",
+      "label": "saveConsumables()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L434"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_addoutputrow",
+      "label": "addOutputRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L447"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_removeoutputrow",
+      "label": "removeOutputRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L452"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_saveoutputs",
+      "label": "saveOutputs()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L453"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_adddatacollectionrow",
+      "label": "addDataCollectionRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L464"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_removedatacollectionrow",
+      "label": "removeDataCollectionRow()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L469"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_savedatacollections",
+      "label": "saveDataCollections()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L470"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "label": "handleManualSave()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L482"
+    },
+    {
+      "id": "production_work_order_usetaskstepeditor_initeditor",
+      "label": "initEditor()",
+      "file_type": "code",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L501"
+    },
     {
       "id": "views_production_production_work_order_stepdetailpanel_vue",
       "label": "StepDetailPanel.vue",
@@ -23899,7 +24074,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1049",
+      "source_location": "L1055",
       "weight": 1.0
     },
     {
@@ -23908,7 +24083,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1138",
+      "source_location": "L1172",
       "weight": 1.0
     },
     {
@@ -23917,7 +24092,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1203",
+      "source_location": "L1255",
       "weight": 1.0
     },
     {
@@ -23926,7 +24101,7 @@
       "relation": "contains",
       "confidence": "EXTRACTED",
       "source_file": "views/production/process-route/index.vue",
-      "source_location": "L1213",
+      "source_location": "L1265",
       "weight": 1.0
     },
     {
@@ -24002,164 +24177,488 @@
       "weight": 1.0
     },
     {
-      "source": "views_production_production_work_order_stepdetailpanel_vue",
-      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_ensureallstepunitoptions",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/production/production-work-order/StepDetailPanel.vue",
-      "source_location": "L265",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L253",
       "weight": 1.0
     },
     {
-      "source": "views_production_production_work_order_dispatchtaskdialog_vue",
-      "target": "production_work_order_dispatchtaskdialog_if",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/production/production-work-order/DispatchTaskDialog.vue",
-      "source_location": "L205",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L294",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "element_plus",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L722",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L318",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "icons_vue",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_ondragstart",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L723",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L333",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "components_business_system_view_dialog_index_vue",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_ondroptocenter",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L724",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L337",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_onstepdragend",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L725",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L351",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_material",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_selectstep",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L726",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L360",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_material",
-      "relation": "imports_from",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_handlecopystep",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L736",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L361",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_material_index_vue",
-      "target": "qc_material_index_pad",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_handledeletestep",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-material/index.vue",
-      "source_location": "L924",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L372",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_sample_reception_index_vue",
-      "target": "sample_reception_index_parseetalocaldate",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_savestepbasic",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L683",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L386",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_sample_reception_index_vue",
-      "target": "sample_reception_index_startoflocalday",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_onsopidschange",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L697",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L399",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_sample_reception_index_vue",
-      "target": "sample_reception_index_isetatodayorearlier",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_addreagentrow",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L701",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L404",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_sample_reception_index_vue",
-      "target": "sample_reception_index_samplereceptionrowclassname",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_removereagentrow",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L707",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L412",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_sample_reception_index_vue",
-      "target": "sample_reception_index_pad",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_savereagents",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L832",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L413",
       "weight": 1.0
     },
     {
-      "source": "sample_reception_index_isetatodayorearlier",
-      "target": "sample_reception_index_parseetalocaldate",
-      "relation": "calls",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_addconsumablerow",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L702",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L425",
       "weight": 1.0
     },
     {
-      "source": "sample_reception_index_isetatodayorearlier",
-      "target": "sample_reception_index_startoflocalday",
-      "relation": "calls",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_removeconsumablerow",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L704",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L433",
       "weight": 1.0
     },
     {
-      "source": "sample_reception_index_samplereceptionrowclassname",
-      "target": "sample_reception_index_isetatodayorearlier",
-      "relation": "calls",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_saveconsumables",
+      "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/sample-reception/index.vue",
-      "source_location": "L709",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L434",
       "weight": 1.0
     },
     {
-      "source": "views_quality_inspection_qc_task_index_vue",
-      "target": "qc_task_index_canfillresult",
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_addoutputrow",
       "relation": "contains",
       "confidence": "EXTRACTED",
-      "source_file": "views/quality-inspection/qc-task/index.vue",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L447",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_removeoutputrow",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L452",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_saveoutputs",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L453",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_adddatacollectionrow",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L464",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_removedatacollectionrow",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L469",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_savedatacollections",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L470",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L482",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_usetaskstepeditor_ts",
+      "target": "production_work_order_usetaskstepeditor_initeditor",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L501",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_usetaskstepeditor",
+      "target": "production_work_order_usetaskstepeditor_saveconsumables",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L242",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "target": "production_work_order_usetaskstepeditor_ensureallstepunitoptions",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L325",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_ondroptocenter",
+      "target": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L343",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlecopystep",
+      "target": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L365",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handledeletestep",
+      "target": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L377",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "target": "production_work_order_usetaskstepeditor_savestepbasic",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L487",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "target": "production_work_order_usetaskstepeditor_savereagents",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L488",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "target": "production_work_order_usetaskstepeditor_saveconsumables",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L489",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "target": "production_work_order_usetaskstepeditor_saveoutputs",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L490",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlemanualsave",
+      "target": "production_work_order_usetaskstepeditor_savedatacollections",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L491",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_initeditor",
+      "target": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L508",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_initeditor",
+      "target": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L509",
+      "weight": 1.0
+    },
+    {
+      "source": "views_production_production_work_order_dispatchtaskdialog_vue",
+      "target": "production_work_order_dispatchtaskdialog_if",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/production/production-work-order/DispatchTaskDialog.vue",
+      "source_location": "L205",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "element_plus",
+      "relation": "imports_from",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L722",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "icons_vue",
+      "relation": "imports_from",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L723",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "components_business_system_view_dialog_index_vue",
+      "relation": "imports_from",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L724",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin",
+      "relation": "imports_from",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L725",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_material",
+      "relation": "imports_from",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L726",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_material",
+      "relation": "imports_from",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L736",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_material_index_vue",
+      "target": "qc_material_index_pad",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-material/index.vue",
+      "source_location": "L924",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_sample_reception_index_vue",
+      "target": "sample_reception_index_parseetalocaldate",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L683",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_sample_reception_index_vue",
+      "target": "sample_reception_index_startoflocalday",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L697",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_sample_reception_index_vue",
+      "target": "sample_reception_index_isetatodayorearlier",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L701",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_sample_reception_index_vue",
+      "target": "sample_reception_index_samplereceptionrowclassname",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L707",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_sample_reception_index_vue",
+      "target": "sample_reception_index_pad",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L832",
+      "weight": 1.0
+    },
+    {
+      "source": "sample_reception_index_isetatodayorearlier",
+      "target": "sample_reception_index_parseetalocaldate",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L702",
+      "weight": 1.0
+    },
+    {
+      "source": "sample_reception_index_isetatodayorearlier",
+      "target": "sample_reception_index_startoflocalday",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L704",
+      "weight": 1.0
+    },
+    {
+      "source": "sample_reception_index_samplereceptionrowclassname",
+      "target": "sample_reception_index_isetatodayorearlier",
+      "relation": "calls",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/sample-reception/index.vue",
+      "source_location": "L709",
+      "weight": 1.0
+    },
+    {
+      "source": "views_quality_inspection_qc_task_index_vue",
+      "target": "qc_task_index_canfillresult",
+      "relation": "contains",
+      "confidence": "EXTRACTED",
+      "source_file": "views/quality-inspection/qc-task/index.vue",
       "source_location": "L460",
       "weight": 1.0
     },
@@ -30327,6 +30826,196 @@
       "source_location": "L571",
       "weight": 1.0
     },
+    {
+      "source": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
+      "target": "api_production_fetchallprocesses",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L296",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
+      "target": "api_production_fetchallprocesscategories",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L296",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
+      "target": "api_production_fetchallsopdocuments",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L297",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_loadconfigreferencedata",
+      "target": "api_production_fetchalloutputtypes",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L297",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_loadtaskdetail",
+      "target": "api_production_task_fetchproductiontaskdetail",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L321",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_ondroptocenter",
+      "target": "api_production_task_fetchaddtaskstep",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L342",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_onstepdragend",
+      "target": "api_production_task_fetchreordertasksteps",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L355",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handlecopystep",
+      "target": "api_production_task_fetchcopytaskstep",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L364",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_handledeletestep",
+      "target": "api_production_task_fetchdeletetaskstep",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L376",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_savestepbasic",
+      "target": "api_production_task_fetchupdatetaskstep",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L389",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_addreagentrow",
+      "target": "storage_facility_index_push",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L407",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_savereagents",
+      "target": "api_production_task_fetchreplacestepreagents",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L421",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_addconsumablerow",
+      "target": "storage_facility_index_push",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L428",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_saveconsumables",
+      "target": "api_production_task_fetchreplacestepconsumables",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L443",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_addoutputrow",
+      "target": "storage_facility_index_push",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L450",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_saveoutputs",
+      "target": "api_production_task_fetchreplacestepoutputs",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L460",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_adddatacollectionrow",
+      "target": "storage_facility_index_push",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L467",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_usetaskstepeditor_savedatacollections",
+      "target": "api_production_task_fetchreplacestepdatacollection",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/useTaskStepEditor.ts",
+      "source_location": "L477",
+      "weight": 1.0
+    },
+    {
+      "source": "production_work_order_dispatchtaskdialog_if",
+      "target": "production_work_order_usetaskstepeditor_initeditor",
+      "relation": "calls",
+      "confidence": "INFERRED",
+      "confidence_score": 0.8,
+      "source_file": "views/production/production-work-order/DispatchTaskDialog.vue",
+      "source_location": "L209",
+      "weight": 1.0
+    },
     {
       "source": "qc_task_index_handlereceptionattachmentdownload",
       "target": "utils_download_attachment_downloadattachmentfile",

+ 61 - 54
web-admin/graphify-out/GRAPH_REPORT.md

@@ -1,11 +1,11 @@
 # Graph Report - src  (2026-05-21)
 
 ## Corpus Check
-- Large corpus: 580 files · ~302,856 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
+- Large corpus: 580 files · ~303,367 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
 
 ## Summary
-- 1415 nodes · 1763 edges · 42 communities detected
-- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 384 edges (avg confidence: 0.8)
+- 1440 nodes · 1819 edges · 43 communities detected
+- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 403 edges (avg confidence: 0.8)
 - Token cost: 0 input · 0 output
 
 ## Community Hubs (Navigation)
@@ -33,8 +33,8 @@
 - [[_COMMUNITY_Community 21|Community 21]]
 - [[_COMMUNITY_Community 22|Community 22]]
 - [[_COMMUNITY_Community 23|Community 23]]
-- [[_COMMUNITY_Community 24|Community 24]]
 - [[_COMMUNITY_Community 25|Community 25]]
+- [[_COMMUNITY_Community 26|Community 26]]
 - [[_COMMUNITY_Community 27|Community 27]]
 - [[_COMMUNITY_Community 28|Community 28]]
 - [[_COMMUNITY_Community 30|Community 30]]
@@ -46,6 +46,7 @@
 - [[_COMMUNITY_Community 36|Community 36]]
 - [[_COMMUNITY_Community 37|Community 37]]
 - [[_COMMUNITY_Community 38|Community 38]]
+- [[_COMMUNITY_Community 39|Community 39]]
 - [[_COMMUNITY_Community 40|Community 40]]
 - [[_COMMUNITY_Community 41|Community 41]]
 - [[_COMMUNITY_Community 42|Community 42]]
@@ -55,7 +56,7 @@
 ## God Nodes (most connected - your core abstractions)
 1. `get()` - 153 edges
 2. `WebSocketClient` - 26 edges
-3. `push()` - 18 edges
+3. `push()` - 22 edges
 4. `withFullscreenLoading()` - 16 edges
 5. `MenuProcessor` - 16 edges
 6. `VersionManager` - 15 edges
@@ -67,8 +68,8 @@
 ## Surprising Connections (you probably didn't know these)
 - `handleBatchDelete()` --calls--> `withFullscreenLoading()`  [INFERRED]
   views/system/site/index.vue → utils/fullscreen-loading.ts
-- `handleBatchDelete()` --calls--> `withFullscreenLoading()`  [INFERRED]
-  views/basic-info/customer/index.vue → utils/fullscreen-loading.ts
+- `handleBatchDeleteHospital()` --calls--> `withFullscreenLoading()`  [INFERRED]
+  views/basic-info/collection-region/index.vue → utils/fullscreen-loading.ts
 - `handleUnauthorizedResponse()` --calls--> `fetchRefreshToken()`  [INFERRED]
   utils/http/index.ts → api/auth.ts
 - `fetchLeaveList()` --calls--> `get()`  [INFERRED]
@@ -80,31 +81,31 @@
 
 ### Community 0 - "Community 0"
 Cohesion: 0.01
-Nodes (75): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+67 more)
+Nodes (82): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+74 more)
 
 ### Community 1 - "Community 1"
 Cohesion: 0.03
-Nodes (57): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+49 more)
+Nodes (56): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+48 more)
 
 ### Community 2 - "Community 2"
-Cohesion: 0.04
-Nodes (31): fetchGetUserInfo(), clickTab(), handleTouchEnd(), setTransition(), IframeRouteManager, RouteRegistry, useCommon(), setupAfterEachGuard() (+23 more)
+Cohesion: 0.03
+Nodes (54): fetchAddTaskStep(), fetchCopyTaskStep(), fetchDeleteTaskStep(), fetchProductionTaskDetail(), fetchProductionTaskList(), fetchReorderTaskSteps(), fetchReplaceStepConsumables(), fetchReplaceStepDataCollection() (+46 more)
 
 ### Community 3 - "Community 3"
-Cohesion: 0.05
-Nodes (32): fetchDeptTree(), fetchPostBoundUserIds(), FireworkSystem, reload(), formatUserLabel(), loadDeptData(), onPersonSelectChange(), subscribeTokenRefresh() (+24 more)
+Cohesion: 0.04
+Nodes (31): fetchGetUserInfo(), clickTab(), handleTouchEnd(), setTransition(), IframeRouteManager, RouteRegistry, useCommon(), setupAfterEachGuard() (+23 more)
 
 ### Community 4 - "Community 4"
-Cohesion: 0.04
-Nodes (18): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllSopDocuments(), fetchConsumableList() (+10 more)
+Cohesion: 0.06
+Nodes (33): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+25 more)
 
 ### Community 5 - "Community 5"
-Cohesion: 0.05
-Nodes (40): fetchAccessLogList(), fetchCleanRoomList(), fetchCreateAccessLog(), fetchCreateCleanRoom(), fetchCreateSite(), fetchDeleteAccessLog(), fetchDeleteCleanRoom(), fetchDeleteSite() (+32 more)
+Cohesion: 0.04
+Nodes (19): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllSopDocuments(), fetchConsumableList() (+11 more)
 
 ### Community 6 - "Community 6"
-Cohesion: 0.09
-Nodes (31): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+23 more)
+Cohesion: 0.05
+Nodes (42): fetchAccessLogList(), fetchCleanRoomList(), fetchCreateAccessLog(), fetchCreateCleanRoom(), fetchCreateSite(), fetchDeleteAccessLog(), fetchDeleteCleanRoom(), fetchDeleteSite() (+34 more)
 
 ### Community 7 - "Community 7"
 Cohesion: 0.06
@@ -119,24 +120,24 @@ Cohesion: 0.13
 Nodes (4): handleReset(), handleSearch(), WebSocketClient, emit()
 
 ### Community 10 - "Community 10"
-Cohesion: 0.07
-Nodes (13): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+5 more)
+Cohesion: 0.08
+Nodes (17): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), collectIds(), postorder(), preorder(), applyTreeExpand() (+9 more)
 
 ### Community 11 - "Community 11"
-Cohesion: 0.09
-Nodes (9): fetchGetAllUpgradeLogs(), fetchGetChinaMapData(), fetchGetComments(), fetchGetCurrentVersion(), fetchGetLatestUpgradeLog(), fetchGetSystemConfig(), fetchGetUpgradeLogs(), systemUpgrade() (+1 more)
+Cohesion: 0.07
+Nodes (13): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+5 more)
 
 ### Community 12 - "Community 12"
 Cohesion: 0.1
-Nodes (8): fetchGetMenuList(), fetchGetMenuCodes(), fetchLogin(), fetchRefreshToken(), MenuProcessor, useAppMode(), useAuth(), buildWebEncryptedLoginBody()
+Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
 
 ### Community 13 - "Community 13"
 Cohesion: 0.1
-Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
+Nodes (19): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+11 more)
 
 ### Community 14 - "Community 14"
 Cohesion: 0.1
-Nodes (18): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+10 more)
+Nodes (8): fetchGetMenuList(), fetchGetMenuCodes(), fetchLogin(), fetchRefreshToken(), MenuProcessor, useAppMode(), useAuth(), buildWebEncryptedLoginBody()
 
 ### Community 15 - "Community 15"
 Cohesion: 0.11
@@ -147,49 +148,49 @@ Cohesion: 0.12
 Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
 
 ### Community 17 - "Community 17"
-Cohesion: 0.13
-Nodes (16): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), postorder(), preorder(), applyTreeExpand(), handleAdd() (+8 more)
-
-### Community 18 - "Community 18"
 Cohesion: 0.14
 Nodes (17): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd(), handleDelete() (+9 more)
 
+### Community 18 - "Community 18"
+Cohesion: 0.12
+Nodes (12): fetchApproveTask(), fetchBusinessAllTasks(), fetchCompletedTasks(), fetchDesignerData(), fetchInstanceDetail(), fetchMyInstances(), fetchPendingTasks(), fetchProcessDefList() (+4 more)
+
 ### Community 19 - "Community 19"
 Cohesion: 0.11
 Nodes (8): fetchCollectionProtocolAuditList(), fetchCollectionProtocolDetail(), fetchCollectionProtocolList(), fetchPaymentDetailList(), fetchReceiptConfirmedList(), fetchReceiptConfirmList(), fetchRefundConfirmedList(), fetchRefundConfirmList()
 
 ### Community 20 - "Community 20"
-Cohesion: 0.12
-Nodes (12): fetchApproveTask(), fetchBusinessAllTasks(), fetchCompletedTasks(), fetchDesignerData(), fetchInstanceDetail(), fetchMyInstances(), fetchPendingTasks(), fetchProcessDefList() (+4 more)
-
-### Community 21 - "Community 21"
 Cohesion: 0.16
 Nodes (10): useTable(), useTableImpl(), getColumnChecks(), useTableColumns(), createErrorHandler(), createSmartDebounce(), defaultResponseAdapter(), extractPagination() (+2 more)
 
-### Community 22 - "Community 22"
-Cohesion: 0.12
-Nodes (2): fetchProductionTaskDetail(), fetchProductionTaskList()
-
-### Community 23 - "Community 23"
+### Community 21 - "Community 21"
 Cohesion: 0.2
 Nodes (2): ComponentLoader, RouteTransformer
 
-### Community 24 - "Community 24"
+### Community 22 - "Community 22"
 Cohesion: 0.27
 Nodes (14): useChart(), useChartComponent(), useChartOps(), colourBlend(), getCssVar(), getDarkColor(), getLightColor(), handleElementThemeColor() (+6 more)
 
+### Community 23 - "Community 23"
+Cohesion: 0.18
+Nodes (11): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), handleAdd(), handleDelete(), handleReset(), handleSearch() (+3 more)
+
 ### Community 25 - "Community 25"
 Cohesion: 0.17
-Nodes (12): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), handleAdd(), handleBatchDelete(), handleDelete(), handleReset() (+4 more)
+Nodes (3): fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList()
 
-### Community 27 - "Community 27"
+### Community 26 - "Community 26"
 Cohesion: 0.18
 Nodes (3): fetchMaterialList(), fetchMaterialOptions(), fetchMaterialStockLogList()
 
-### Community 28 - "Community 28"
+### Community 27 - "Community 27"
 Cohesion: 0.2
 Nodes (2): fetchQcMaterialList(), fetchQcMaterialOptions()
 
+### Community 28 - "Community 28"
+Cohesion: 0.28
+Nodes (1): FireworkSystem
+
 ### Community 30 - "Community 30"
 Cohesion: 0.39
 Nodes (6): isIgnorableScriptError(), normalizeErrorMessage(), registerPromiseErrorHandler(), registerResourceErrorHandler(), scriptErrorHandler(), setupErrorHandle()
@@ -226,6 +227,10 @@ Nodes (2): fetchQcThirdPartyCompanyList(), fetchQcThirdPartyCompanyOptions()
 Cohesion: 0.33
 Nodes (2): fetchQcLabTestItemList(), fetchQcLabTestItemsActive()
 
+### Community 39 - "Community 39"
+Cohesion: 0.33
+Nodes (2): fetchQcTaskDetail(), fetchQcTaskList()
+
 ### Community 40 - "Community 40"
 Cohesion: 0.53
 Nodes (4): isEtaTodayOrEarlier(), parseEtaLocalDate(), sampleReceptionRowClassName(), startOfLocalDay()
@@ -247,11 +252,11 @@ Cohesion: 1.0
 Nodes (2): defaultAvatarPathByRole(), resolveUserAvatarUrl()
 
 ## Knowledge Gaps
-- **Thin community `Community 22`** (17 nodes): `fetchAddTaskStep()`, `fetchCopyTaskStep()`, `fetchCreateProductionTask()`, `fetchDeleteTaskStep()`, `fetchProductionTaskDetail()`, `fetchProductionTaskList()`, `fetchReorderTaskSteps()`, `fetchReplaceStepConsumables()`, `fetchReplaceStepDataCollection()`, `fetchReplaceStepOutputs()`, `fetchReplaceStepReagents()`, `fetchSetTaskInputs()`, `fetchSetTaskOutputs()`, `fetchUpdateProductionTask()`, `fetchUpdateProductionTaskStatus()`, `fetchUpdateTaskStep()`, `production-task.ts`
+- **Thin community `Community 21`** (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 23`** (17 nodes): `ComponentLoader`, `.constructor()`, `.createEmptyComponent()`, `.createErrorComponent()`, `.load()`, `.loadIframe()`, `.loadLayout()`, `.load()`, `RouteTransformer`, `.extractFirstSegment()`, `.handleFirstLevelRoute()`, `.handleIframeRoute()`, `.handleNormalRoute()`, `.isFirstLevelRoute()`, `.transform()`, `ComponentLoader.ts`, `RouteTransformer.ts`
+- **Thin community `Community 27`** (10 nodes): `fetchBatchStockInQcMaterial()`, `fetchBatchStockOutQcMaterial()`, `fetchCreateQcMaterial()`, `fetchDeleteQcMaterial()`, `fetchQcMaterialList()`, `fetchQcMaterialOptions()`, `fetchStockInQcMaterial()`, `fetchStockOutQcMaterial()`, `fetchUpdateQcMaterial()`, `qc-material.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
-- **Thin community `Community 28`** (10 nodes): `fetchBatchStockInQcMaterial()`, `fetchBatchStockOutQcMaterial()`, `fetchCreateQcMaterial()`, `fetchDeleteQcMaterial()`, `fetchQcMaterialList()`, `fetchQcMaterialOptions()`, `fetchStockInQcMaterial()`, `fetchStockOutQcMaterial()`, `fetchUpdateQcMaterial()`, `qc-material.ts`
+- **Thin community `Community 28`** (9 nodes): `FireworkSystem`, `.constructor()`, `.createFirework()`, `.createParticle()`, `.getAvailableParticle()`, `.initializePool()`, `.preloadAllImages()`, `.preloadImage()`, `index.vue`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
 - **Thin community `Community 31`** (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.
@@ -267,6 +272,8 @@ Nodes (2): defaultAvatarPathByRole(), resolveUserAvatarUrl()
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
 - **Thin community `Community 38`** (6 nodes): `fetchCreateQcLabTestItem()`, `fetchDeleteQcLabTestItem()`, `fetchQcLabTestItemList()`, `fetchQcLabTestItemsActive()`, `fetchUpdateQcLabTestItem()`, `qc-lab-test-item.ts`
   Too small to be a meaningful cluster - may be noise or needs more connections extracted.
+- **Thin community `Community 39`** (6 nodes): `fetchCompleteQcTask()`, `fetchQcTaskDetail()`, `fetchQcTaskList()`, `fetchStartQcTask()`, `fetchUpdateQcTaskAttachments()`, `qc-task.ts`
+  Too small to be a meaningful cluster - may be noise or needs more connections extracted.
 - **Thin community `Community 41`** (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 42`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
@@ -279,16 +286,16 @@ Nodes (2): defaultAvatarPathByRole(), resolveUserAvatarUrl()
 ## 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 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 17`, `Community 18`, `Community 19`, `Community 20`, `Community 22`, `Community 25`, `Community 27`, `Community 28`, `Community 33`, `Community 35`, `Community 36`, `Community 37`, `Community 38`?**
-  _High betweenness centrality (0.266) - this node is a cross-community bridge._
-- **Why does `push()` connect `Community 3` to `Community 0`, `Community 2`, `Community 7`, `Community 9`, `Community 11`, `Community 13`?**
-  _High betweenness centrality (0.077) - this node is a cross-community bridge._
-- **Why does `fetchGetLatestUpgradeLog()` connect `Community 11` to `Community 0`?**
-  _High betweenness centrality (0.043) - this node is a cross-community bridge._
+- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 5`, `Community 6`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 17`, `Community 18`, `Community 19`, `Community 23`, `Community 25`, `Community 26`, `Community 27`, `Community 33`, `Community 35`, `Community 36`, `Community 37`, `Community 38`, `Community 39`?**
+  _High betweenness centrality (0.263) - this node is a cross-community bridge._
+- **Why does `push()` connect `Community 2` to `Community 0`, `Community 3`, `Community 4`, `Community 6`, `Community 7`, `Community 9`, `Community 12`, `Community 28`?**
+  _High betweenness centrality (0.097) - this node is a cross-community bridge._
+- **Why does `buildTreePathLabelFromFlat()` connect `Community 2` to `Community 0`, `Community 7`?**
+  _High betweenness centrality (0.044) - this node is a cross-community bridge._
 - **Are the 152 inferred relationships involving `get()` (e.g. with `buildTreePathLabelFromFlat()` and `alignFqPaymentDetailsForDisplay()`) actually correct?**
   _`get()` has 152 INFERRED edges - model-reasoned connections that need verification._
-- **Are the 17 inferred relationships involving `push()` (e.g. with `fetchAllPagedRecords()` and `calcInstallmentDueAmounts()`) actually correct?**
-  _`push()` has 17 INFERRED edges - model-reasoned connections that need verification._
+- **Are the 21 inferred relationships involving `push()` (e.g. with `fetchAllPagedRecords()` and `calcInstallmentDueAmounts()`) actually correct?**
+  _`push()` has 21 INFERRED edges - model-reasoned connections that need verification._
 - **Are the 15 inferred relationships involving `withFullscreenLoading()` (e.g. with `.close()` and `handleSubmit()`) actually correct?**
   _`withFullscreenLoading()` has 15 INFERRED edges - model-reasoned connections that need verification._
 - **Should `Community 0` be split into smaller, more focused modules?**

文件差异内容过多而无法显示
+ 1 - 1
web-admin/graphify-out/graph.html


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

@@ -17,8 +17,8 @@
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/index.ts": 1778582068.0254738,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/directive/directive.d.ts": 1778582068.026978,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api/api.d.ts": 1778582068.0246184,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1779352117.4443235,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779352105.3240538,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1779367818.9493446,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779367815.3312664,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/store/index.ts": 1778582068.0293276,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/router/index.ts": 1778775532.895603,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/locales/index.ts": 1778582068.004279,
@@ -209,7 +209,7 @@
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/research-donation.ts": 1779160004.1431847,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-task.ts": 1779182848.881475,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-item-param.ts": 1779022632.5658252,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production-task.ts": 1779343665.7247121,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production-task.ts": 1779362887.1562896,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-material-usage.ts": 1779284726.00147,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-material.ts": 1779283280.0705447,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/system.ts": 1778582067.862994,
@@ -270,13 +270,13 @@
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/leave/index.vue": 1779257191.2768743,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/output-type/index.vue": 1779307917.5932443,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/cell-product/index.vue": 1779341967.5417912,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/process-route/index.vue": 1779337462.617501,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/process-route/index.vue": 1779368158.8972282,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/sop/index.vue": 1779309609.6630545,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-task/index.vue": 1779341706.1749396,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/reagent/index.vue": 1779307562.93293,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue": 1779352577.0334256,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts": 1779348972.995939,
-  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/StepDetailPanel.vue": 1779360359.145311,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue": 1779361308.0826523,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts": 1779365205.5601952,
+  "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/StepDetailPanel.vue": 1779365306.261633,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/DispatchTaskDialog.vue": 1779352611.1311061,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/consumable-pack/index.vue": 1779307488.018346,
   "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/consumable/index.vue": 1779307921.9798808,

文件差异内容过多而无法显示
+ 0 - 0
web-admin/src/graphify-out/cache/ast/13b280c56260b23c5f5019313e397f18d32123034f825439d28c47ab9d56e87e.json


文件差异内容过多而无法显示
+ 0 - 0
web-admin/src/graphify-out/cache/ast/30a4dc3504ebc5f26cd1e91e7bbe3f20f0353e34bcba5b80e45cbf1135b9877f.json


文件差异内容过多而无法显示
+ 0 - 0
web-admin/src/graphify-out/cache/ast/39ea3a02c254cea29029f8613c104395266e5ddb2d70825ef398ea37999c3922.json


+ 1 - 0
web-admin/src/graphify-out/cache/ast/ab7ada5af3697d125c1e952c09a82a170c633200708c6435b41dcb917193c7f8.json

@@ -0,0 +1 @@
+{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_stepdetailpanel_vue", "label": "StepDetailPanel.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/StepDetailPanel.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}

+ 1 - 0
web-admin/src/graphify-out/cache/ast/df4a50457577371e356844f3ee5be9d61ee4f3c4ea83c8ce010f59c0f86b00bc.json

@@ -0,0 +1 @@
+{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}

+ 1 - 0
web-admin/src/graphify-out/cache/ast/df92ca9d807c40f21dbd3c36c4c8526973367447e23d4dc5ec78e25dec1a219b.json

@@ -0,0 +1 @@
+{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}

+ 14 - 12
web-admin/src/views/production/production-work-order/StepDetailPanel.vue

@@ -172,7 +172,8 @@
               <el-table-column type="index" label="序号" width="56" align="center" :index="(i: number) => i + 1" />
               <el-table-column label="产出类型" min-width="150" align="center">
                 <template #default="{ row }">
-                  <el-select v-model="row.outputTypeId" placeholder="选择类型" filterable class="inner-cell-select">
+                  <el-select v-model="row.outputTypeId" placeholder="选择类型" filterable class="inner-cell-select"
+                    @change="editor.saveOutputs">
                     <el-option v-for="ot in editor.outputTypeOptions.value" :key="ot.id"
                       :label="ot.typeName || ot.name" :value="ot.id" />
                   </el-select>
@@ -180,17 +181,20 @@
               </el-table-column>
               <el-table-column label="名称" min-width="150" align="center">
                 <template #default="{ row }">
-                  <el-input v-model="row.outputName" placeholder="名称" class="inner-cell-input" />
+                  <el-input v-model="row.outputName" placeholder="名称" class="inner-cell-input"
+                    @change="editor.saveOutputs" />
                 </template>
               </el-table-column>
               <el-table-column label="条码" min-width="150" align="center">
                 <template #default="{ row }">
-                  <el-input v-model="row.outputBarcode" placeholder="条码" class="inner-cell-input" />
+                  <el-input v-model="row.outputBarcode" placeholder="条码" class="inner-cell-input"
+                    @change="editor.saveOutputs" />
                 </template>
               </el-table-column>
               <el-table-column label="备注" min-width="120" align="center">
                 <template #default="{ row }">
-                  <el-input v-model="row.remark" placeholder="备注" class="inner-cell-input" />
+                  <el-input v-model="row.remark" placeholder="备注" class="inner-cell-input"
+                    @change="editor.saveOutputs" />
                 </template>
               </el-table-column>
               <el-table-column label="操作" width="80" align="center">
@@ -212,7 +216,8 @@
               <el-table-column type="index" label="序号" width="56" align="center" :index="(i: number) => i + 1" />
               <el-table-column label="采集名称" min-width="180" align="center">
                 <template #default="{ row }">
-                  <el-input v-model="row.collectionName" placeholder="采集项名称" class="inner-cell-input" />
+                  <el-input v-model="row.collectionName" placeholder="采集项名称" class="inner-cell-input"
+                    @change="editor.saveDataCollections" />
                 </template>
               </el-table-column>
               <el-table-column label="单位" min-width="120" align="center">
@@ -220,19 +225,16 @@
                   <el-select v-model="row.unit" placeholder="请选择单位" clearable filterable remote
                     reserve-keyword class="inner-cell-select" :loading="editor.itemUnitOptionsLoading.value"
                     :remote-method="editor.searchItemUnitOptions"
-                    @visible-change="(vis: boolean) => vis && editor.searchItemUnitOptions('')">
+                    @visible-change="(vis: boolean) => vis && editor.searchItemUnitOptions('')"
+                    @change="editor.saveDataCollections">
                     <el-option v-for="item in editor.itemUnitOptions.value" :key="item.value" :label="item.label" :value="item.value" />
                   </el-select>
                 </template>
               </el-table-column>
-              <el-table-column label="排序号" min-width="100" align="center">
-                <template #default="{ row }">
-                  <el-input v-model="row.orderNum" placeholder="排序号" class="inner-cell-input" />
-                </template>
-              </el-table-column>
               <el-table-column label="备注" min-width="120" align="center">
                 <template #default="{ row }">
-                  <el-input v-model="row.remark" placeholder="备注" class="inner-cell-input" />
+                  <el-input v-model="row.remark" placeholder="备注" class="inner-cell-input"
+                    @change="editor.saveDataCollections" />
                 </template>
               </el-table-column>
               <el-table-column label="操作" width="80" align="center">

+ 38 - 12
web-admin/src/views/production/production-work-order/useTaskStepEditor.ts

@@ -109,6 +109,17 @@ export function useTaskStepEditor() {
     for (const r of list) if (r?.id) next[r.id] = r
     reagentMasterById.value = next
   }
+
+  /** 通过 reagentCode 在已缓存的主表数据中反查 masterId */
+  function resolveReagentMasterId(row: Record<string, any>): string | null {
+    const code = (row.reagentCode || '').trim()
+    if (!code) return null
+    for (const master of Object.values(reagentMasterById.value)) {
+      if ((master.reagentCode || '').trim() === code) return master.id
+    }
+    return null
+  }
+
   async function searchReagentOptions(query: string) {
     reagentOptionsLoading.value = true
     try {
@@ -132,6 +143,14 @@ export function useTaskStepEditor() {
         reagentOptions.value = [{ id: row.reagentId, label: mapReagentOptionLabel(row) }, ...reagentOptions.value]
       return
     }
+    // reagentId 为空(后端不存储该字段)— 通过 reagentCode 反查主表真实 ID
+    const masterId = resolveReagentMasterId(row)
+    if (masterId) {
+      row.reagentId = masterId
+      // 主表选项已在 searchReagentOptions 中加载,无需重复添加
+      return
+    }
+    // 实在找不到主表记录才走 legacy 兜底
     const code = (row.reagentCode || '').trim()
     const name = (row.reagentName || '').trim()
     if (!code && !name) return
@@ -179,6 +198,17 @@ export function useTaskStepEditor() {
     for (const c of list) if (c?.id) next[c.id] = c
     consumableMasterById.value = next
   }
+
+  /** 通过 consumableCode 在已缓存的主表数据中反查 masterId */
+  function resolveConsumableMasterId(row: Record<string, any>): string | null {
+    const code = (row.consumableCode || '').trim()
+    if (!code) return null
+    for (const master of Object.values(consumableMasterById.value)) {
+      if ((master.consumableCode || '').trim() === code) return master.id
+    }
+    return null
+  }
+
   async function searchConsumableOptions(query: string) {
     consumableOptionsLoading.value = true
     try {
@@ -202,6 +232,14 @@ export function useTaskStepEditor() {
         consumableOptions.value = [{ id: row.consumableId, label: mapConsumableOptionLabel(row) }, ...consumableOptions.value]
       return
     }
+    // consumableId 为空(后端不存储该字段)— 通过 consumableCode 反查主表真实 ID
+    const masterId = resolveConsumableMasterId(row)
+    if (masterId) {
+      row.consumableId = masterId
+      // 主表选项已在 searchConsumableOptions 中加载,无需重复添加
+      return
+    }
+    // 实在找不到主表记录才走 legacy 兜底
     const code = (row.consumableCode || '').trim()
     const name = (row.consumableName || '').trim()
     if (!code && !name) return
@@ -237,18 +275,6 @@ export function useTaskStepEditor() {
     })
     ensureItemUnitOption(row.unit)
     ensureConsumableOption(row)
-  }
-    const master = consumableMasterById.value[consumableId]
-    if (!master) { saveConsumables(); return }
-    Object.assign(row, {
-      consumableId: master.id, consumableCode: master.consumableCode || '',
-      consumableName: master.consumableName || '', specModel: master.specModel || '',
-      standardUsage: master.standardUsage ?? '', unit: master.unit || '',
-      remark: master.remark ?? master.description ?? ''
-    })
-    ensureItemUnitOption(row.unit)
-    ensureConsumableOption(row)
-    saveConsumables()
   }
   function ensureAllStepUnitOptions() {
     for (const step of stepList.value) {

部分文件因为文件数量过多而无法显示