This commit is contained in:
zlwu committed 2026-05-23 14:49:50 +08:00
1 parent fb85230d25
commit 05684ba2a4
56 files changed
+26110 -13601

No files matched your search

+1
View File
@@ -68,6 +68,7 @@ Full specs: `openspec/changes/zkxw-engineering-standards/specs/*/spec.md`. Below
- **Backend**: Python 3.9, FastAPI + SQLAlchemy + Pydantic v2. Routes stay thin; business logic goes in `app/services/` and `app/crud/`. Config via `pydantic-settings` + `.env` files.
- **DB changes**: SHALL maintain SQL in `docs/sql/`. Schema changes SHALL align with `database-conventions` public field rules.
- **Commit messages**: SHALL be complete sentences describing "what changed and why". Follow Conventional Commits (`feat|fix|docs|…`).
- **Field consistency (CRUD ↔ Schema ↔ Frontend)**: When implementing CRUD for any entity, the `_row_to_dict` function is the **single source of truth** for all readable fields. The CreateBody/UpdateBody Pydantic schemas and the frontend `formData` initialization SHALL include every writable field present in `_row_to_dict` (excluding computed/read-only fields like `id`, `createTime`, `updateTime`, `stockQty`). Run `python scripts/check_field_consistency.py` after implementation to verify. See `docs/dev-field-consistency.md` for details.
### Permission Conventions
+1 -1
View File
@@ -1 +1 @@
55545
65187
+16
View File
@@ -74,6 +74,8 @@ class ConsumableCreateBody(BaseModel):
standard_usage: Optional[str] = Field(None, alias="standardUsage")
unit: Optional[str] = None
description: Optional[str] = None
warning_qty: Optional[float] = Field(0, alias="warningQty")
status: Optional[str] = Field("1", alias="status")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -86,6 +88,8 @@ class ConsumableUpdateBody(BaseModel):
standard_usage: Optional[str] = Field(None, alias="standardUsage")
unit: Optional[str] = None
description: Optional[str] = None
warning_qty: Optional[float] = Field(None, alias="warningQty")
status: Optional[str] = Field(None, alias="status")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -131,6 +135,8 @@ async def create_consumable(
unit=body.unit,
description=body.description,
tenant_no=tenant_no,
warning_qty=body.warning_qty,
status=body.status,
order_num=body.order_num,
remark=body.remark,
user_id=user.get("user_id"),
@@ -158,6 +164,8 @@ async def update_consumable(
standard_usage=payload.get("standard_usage"),
unit=payload.get("unit"),
description=payload.get("description"),
warning_qty=payload.get("warning_qty"),
status=payload.get("status"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
user_id=user.get("user_id"),
@@ -358,6 +366,8 @@ class ReagentCreateBody(BaseModel):
standard_usage: Optional[str] = Field(None, alias="standardUsage")
unit: Optional[str] = None
description: Optional[str] = None
warning_qty: Optional[float] = Field(0, alias="warningQty")
status: Optional[str] = Field("1", alias="status")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -370,6 +380,8 @@ class ReagentUpdateBody(BaseModel):
standard_usage: Optional[str] = Field(None, alias="standardUsage")
unit: Optional[str] = None
description: Optional[str] = None
warning_qty: Optional[float] = Field(None, alias="warningQty")
status: Optional[str] = Field(None, alias="status")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -415,6 +427,8 @@ async def create_reagent(
unit=body.unit,
description=body.description,
tenant_no=tenant_no,
warning_qty=body.warning_qty,
status=body.status,
order_num=body.order_num,
remark=body.remark,
user_id=user.get("user_id"),
@@ -442,6 +456,8 @@ async def update_reagent(
standard_usage=payload.get("standard_usage"),
unit=payload.get("unit"),
description=payload.get("description"),
warning_qty=payload.get("warning_qty"),
status=payload.get("status"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
user_id=user.get("user_id"),
+10
View File
@@ -126,6 +126,8 @@ def create_consumable(
unit: Optional[str] = None,
description: Optional[str] = None,
tenant_no: str = "zkxw",
warning_qty: Optional[float] = None,
status: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -144,6 +146,8 @@ def create_consumable(
unit=(unit or "").strip() or None,
description=(description or "").strip() or None,
tenant_no=tenant_no,
warning_qty=warning_qty if warning_qty is not None else 0,
status=_norm_status(status),
order_num=order_num if order_num is not None else 0,
remark=(remark or "").strip() or None,
create_by=user_id,
@@ -169,6 +173,8 @@ def update_consumable(
standard_usage: Optional[str] = None,
unit: Optional[str] = None,
description: Optional[str] = None,
warning_qty: Optional[float] = None,
status: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -193,6 +199,10 @@ def update_consumable(
obj.unit = (unit or "").strip() or None
if description is not None:
obj.description = (description or "").strip() or None
if warning_qty is not None:
obj.warning_qty = warning_qty
if status is not None:
obj.status = _norm_status(status)
if order_num is not None:
obj.order_num = order_num
if remark is not None:
+3
View File
@@ -72,6 +72,7 @@ def _row_to_dict(r: BizConsumableStockLog, *, create_by_name: str = "") -> Dict[
"stockBefore": float(r.stock_before) if r.stock_before is not None else 0,
"stockAfter": float(r.stock_after) if r.stock_after is not None else 0,
"stepId": r.step_id or "",
"stepName": r.step_name or "",
"taskId": r.task_id or "",
"taskNo": r.task_no or "",
"receiver": receiver,
@@ -204,6 +205,7 @@ def revert_step_stock_changes(
def deduct_for_step(
db: Session,
step_id: str,
step_name: str,
task_id: str,
task_no: str,
consumable_items: List[Dict[str, Any]],
@@ -265,6 +267,7 @@ def deduct_for_step(
stock_after=new_stock,
source_type="step_save",
step_id=step_id,
step_name=(step_name or "").strip() or None,
task_id=task_id,
task_no=task_no,
tenant_no=tenant_no,
+6 -2
View File
@@ -839,7 +839,9 @@ def replace_step_reagents(
).first()
task_id = ""
task_no = ""
step_name = ""
if step_row:
step_name = step_row.process_name or ""
task_row = db.query(BizProductionTask).filter(
and_(BizProductionTask.id == step_row.task_id, BizProductionTask.del_flag == 0)
).first()
@@ -871,7 +873,7 @@ def replace_step_reagents(
# Deduct stock based on actual_usage
reagent_stock_log_crud.deduct_for_step(
db, step_id, task_id, task_no, items, tenant_no, user_id, "",
db, step_id, step_name, task_id, task_no, items, tenant_no, user_id, "",
)
db.commit()
@@ -891,7 +893,9 @@ def replace_step_consumables(
).first()
task_id = ""
task_no = ""
step_name = ""
if step_row:
step_name = step_row.process_name or ""
task_row = db.query(BizProductionTask).filter(
and_(BizProductionTask.id == step_row.task_id, BizProductionTask.del_flag == 0)
).first()
@@ -923,7 +927,7 @@ def replace_step_consumables(
# Deduct stock based on actual_usage
consumable_stock_log_crud.deduct_for_step(
db, step_id, task_id, task_no, items, tenant_no, user_id, "",
db, step_id, step_name, task_id, task_no, items, tenant_no, user_id, "",
)
db.commit()
+10
View File
@@ -126,6 +126,8 @@ def create_reagent(
unit: Optional[str] = None,
description: Optional[str] = None,
tenant_no: str = "zkxw",
warning_qty: Optional[float] = None,
status: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -144,6 +146,8 @@ def create_reagent(
unit=(unit or "").strip() or None,
description=(description or "").strip() or None,
tenant_no=tenant_no,
warning_qty=warning_qty if warning_qty is not None else 0,
status=_norm_status(status),
order_num=order_num if order_num is not None else 0,
remark=(remark or "").strip() or None,
create_by=user_id,
@@ -169,6 +173,8 @@ def update_reagent(
standard_usage: Optional[str] = None,
unit: Optional[str] = None,
description: Optional[str] = None,
warning_qty: Optional[float] = None,
status: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -193,6 +199,10 @@ def update_reagent(
obj.unit = (unit or "").strip() or None
if description is not None:
obj.description = (description or "").strip() or None
if warning_qty is not None:
obj.warning_qty = warning_qty
if status is not None:
obj.status = _norm_status(status)
if order_num is not None:
obj.order_num = order_num
if remark is not None:
+3
View File
@@ -72,6 +72,7 @@ def _row_to_dict(r: BizReagentStockLog, *, create_by_name: str = "") -> Dict[str
"stockBefore": float(r.stock_before) if r.stock_before is not None else 0,
"stockAfter": float(r.stock_after) if r.stock_after is not None else 0,
"stepId": r.step_id or "",
"stepName": r.step_name or "",
"taskId": r.task_id or "",
"taskNo": r.task_no or "",
"receiver": receiver,
@@ -204,6 +205,7 @@ def revert_step_stock_changes(
def deduct_for_step(
db: Session,
step_id: str,
step_name: str,
task_id: str,
task_no: str,
reagent_items: List[Dict[str, Any]],
@@ -264,6 +266,7 @@ def deduct_for_step(
stock_after=new_stock,
source_type="step_save",
step_id=step_id,
step_name=(step_name or "").strip() or None,
task_id=task_id,
task_no=task_no,
tenant_no=tenant_no,
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "label": "consumable_stock_log.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L1"}, {"id": "crud_consumable_stock_log_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L16"}, {"id": "crud_consumable_stock_log_parse_receiver_purpose_from_remark", "label": "_parse_receiver_purpose_from_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L24"}, {"id": "crud_consumable_stock_log_resolve_receiver_purpose", "label": "_resolve_receiver_purpose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L35"}, {"id": "crud_consumable_stock_log_display_remark", "label": "_display_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L45"}, {"id": "crud_consumable_stock_log_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L60"}, {"id": "crud_consumable_stock_log_list_stock_logs", "label": "list_stock_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L89"}, {"id": "crud_consumable_stock_log_revert_step_stock_changes", "label": "revert_step_stock_changes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L157"}, {"id": "crud_consumable_stock_log_deduct_for_step", "label": "deduct_for_step()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L204"}, {"id": "crud_consumable_stock_log_rationale_1", "label": "\u8017\u6750\u53d8\u52a8\u8bb0\u5f55 CRUD\uff08biz_consumable_stock_log\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L1"}, {"id": "crud_consumable_stock_log_rationale_163", "label": "\u64a4\u9500\u6b65\u9aa4\u6b64\u524d step_save \u6263\u51cf\uff0c\u4fbf\u4e8e\u91cd\u65b0\u586b\u62a5\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L163"}, {"id": "crud_consumable_stock_log_rationale_214", "label": "\u6263\u51cf\u8017\u6750\u5e93\u5b58\u5e76\u751f\u6210\u53d8\u52a8\u8bb0\u5f55\u3002\u8c03\u7528\u65b9\u63a7\u5236\u4e8b\u52a1\uff0c\u672c\u51fd\u6570\u4e0d commit\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L214"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "decimal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_stock_log_py", "target": "appLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_production_task_py", "label": "production_task.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L1"}, {"id": "crud_production_task_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L43"}, {"id": "crud_production_task_generate_task_no", "label": "_generate_task_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L47"}, {"id": "crud_production_task_task_to_dict", "label": "_task_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L61"}, {"id": "crud_production_task_step_to_dict", "label": "_step_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L83"}, {"id": "crud_production_task_step_reagent_to_dict", "label": "_step_reagent_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L103"}, {"id": "crud_production_task_step_consumable_to_dict", "label": "_step_consumable_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L118"}, {"id": "crud_production_task_step_output_to_dict", "label": "_step_output_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L133"}, {"id": "crud_production_task_step_data_collection_to_dict", "label": "_step_data_collection_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L144"}, {"id": "crud_production_task_task_input_to_dict", "label": "_task_input_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L155"}, {"id": "crud_production_task_task_output_to_dict", "label": "_task_output_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L177"}, {"id": "crud_production_task_soft_delete_sub", "label": "_soft_delete_sub()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L202"}, {"id": "crud_production_task_clone_step_reagents", "label": "_clone_step_reagents()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L215"}, {"id": "crud_production_task_clone_step_consumables", "label": "_clone_step_consumables()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L233"}, {"id": "crud_production_task_clone_step_outputs", "label": "_clone_step_outputs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L251"}, {"id": "crud_production_task_clone_step_data_collections", "label": "_clone_step_data_collections()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L268"}, {"id": "crud_production_task_clone_route_to_task", "label": "_clone_route_to_task()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L284"}, {"id": "crud_production_task_create_production_task", "label": "create_production_task()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L317"}, {"id": "crud_production_task_list_production_tasks", "label": "list_production_tasks()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L359"}, {"id": "crud_production_task_get_production_task_detail", "label": "get_production_task_detail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L479"}, {"id": "crud_production_task_update_production_task", "label": "update_production_task()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L569"}, {"id": "crud_production_task_update_task_status", "label": "update_task_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L594"}, {"id": "crud_production_task_add_task_step", "label": "add_task_step()", "file_type": Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "label": "reagent.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L1"}, {"id": "crud_reagent_dec", "label": "_dec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L16"}, {"id": "crud_reagent_norm_status", "label": "_norm_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L22"}, {"id": "crud_reagent_is_enabled_status", "label": "_is_enabled_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L38"}, {"id": "crud_reagent_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L42"}, {"id": "crud_reagent_list_reagents", "label": "list_reagents()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L62"}, {"id": "crud_reagent_get_reagent", "label": "get_reagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L102"}, {"id": "crud_reagent_reagent_code_exists", "label": "reagent_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L110"}, {"id": "crud_reagent_create_reagent", "label": "create_reagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L119"}, {"id": "crud_reagent_update_reagent", "label": "update_reagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L162"}, {"id": "crud_reagent_soft_delete_reagent", "label": "soft_delete_reagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L208"}, {"id": "crud_reagent_stock_in", "label": "stock_in()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L220"}, {"id": "crud_reagent_batch_stock_in", "label": "batch_stock_in()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L276"}, {"id": "crud_reagent_stock_out", "label": "stock_out()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L351"}, {"id": "crud_reagent_batch_stock_out", "label": "batch_stock_out()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L422"}, {"id": "crud_reagent_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L510"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "decimal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "label": "reagent_stock_log.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L1"}, {"id": "crud_reagent_stock_log_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L16"}, {"id": "crud_reagent_stock_log_parse_receiver_purpose_from_remark", "label": "_parse_receiver_purpose_from_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L24"}, {"id": "crud_reagent_stock_log_resolve_receiver_purpose", "label": "_resolve_receiver_purpose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L35"}, {"id": "crud_reagent_stock_log_display_remark", "label": "_display_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L45"}, {"id": "crud_reagent_stock_log_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L60"}, {"id": "crud_reagent_stock_log_list_stock_logs", "label": "list_stock_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L89"}, {"id": "crud_reagent_stock_log_revert_step_stock_changes", "label": "revert_step_stock_changes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L157"}, {"id": "crud_reagent_stock_log_deduct_for_step", "label": "deduct_for_step()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L204"}, {"id": "crud_reagent_stock_log_rationale_1", "label": "\u8bd5\u5242\u53d8\u52a8\u8bb0\u5f55 CRUD\uff08biz_reagent_stock_log\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L1"}, {"id": "crud_reagent_stock_log_rationale_163", "label": "\u64a4\u9500\u6b65\u9aa4\u6b64\u524d step_save \u6263\u51cf\uff0c\u4fbf\u4e8e\u91cd\u65b0\u586b\u62a5\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L163"}, {"id": "crud_reagent_stock_log_rationale_214", "label": "\u6263\u51cf\u8bd5\u5242\u5e93\u5b58\u5e76\u751f\u6210\u53d8\u52a8\u8bb0\u5f55\u3002\u8c03\u7528\u65b9\u63a7\u5236\u4e8b\u52a1\uff0c\u672c\u51fd\u6570\u4e0d commit\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L214"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "decimal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_reagent_stock_log_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxwLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_production_py", "label": "production.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L1"}, {"id": "api_production_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L56"}, {"id": "api_production_consumablecreatebody", "label": "ConsumableCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L69"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_production_consumableupdatebody", "label": "ConsumableUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L81"}, {"id": "api_production_list_consumables", "label": "list_consumables()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L94"}, {"id": "api_production_list_all_consumables", "label": "list_all_consumables()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L108"}, {"id": "api_production_create_consumable", "label": "create_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L118"}, {"id": "api_production_update_consumable", "label": "update_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L144"}, {"id": "api_production_delete_consumable", "label": "delete_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L171"}, {"id": "api_production_stockinbody", "label": "StockInBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L183"}, {"id": "api_production_stockoutbody", "label": "StockOutBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L189"}, {"id": "api_production_batchstockinitem", "label": "BatchStockInItem", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L197"}, {"id": "api_production_batchstockinbody", "label": "BatchStockInBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L204"}, {"id": "api_production_batchstockoutitem", "label": "BatchStockOutItem", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L210"}, {"id": "api_production_batchstockoutbody", "label": "BatchStockOutBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L216"}, {"id": "api_production_consumable_stock_in", "label": "consumable_stock_in()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L225"}, {"id": "api_production_consumable_stock_out", "label": "consumable_stock_out()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L247"}, {"id": "api_production_consumable_batch_stock_in", "label": "consumable_batch_stock_in()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L271"}, {"id": "api_production_consumable_batch_stock_out", "label": "consumable_batch_stock_out()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L289"}, {"id": "api_production_list_consumable_stock_logs", "label": "list_consumable_stock_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L308"}, {"id": "api_production_list_all_consumable_stock_logs", "label": "list_all_consumable_stock_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L327"}, {"id": "api_production_reagentcreatebody", "label": "ReagentCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L353"}, {"id": "api_production_reagentupdatebody", "label": "ReagentUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L365"}, {"id": "api_production_list_reagents", "label": "list_reagents()", "file_type": "code", "source_filLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L220"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L240"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L259"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L278"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L297"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L320"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L341"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L359"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L378"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L400"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L428"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L447"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L466"}, {"id": "models_models_sysapirequestlog", "label": "SysApiRequestLog", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_py", "label": "consumable.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L1"}, {"id": "crud_consumable_dec", "label": "_dec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L16"}, {"id": "crud_consumable_norm_status", "label": "_norm_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L22"}, {"id": "crud_consumable_is_enabled_status", "label": "_is_enabled_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L38"}, {"id": "crud_consumable_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L42"}, {"id": "crud_consumable_list_consumables", "label": "list_consumables()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L62"}, {"id": "crud_consumable_get_consumable", "label": "get_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L102"}, {"id": "crud_consumable_consumable_code_exists", "label": "consumable_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L110"}, {"id": "crud_consumable_create_consumable", "label": "create_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L119"}, {"id": "crud_consumable_update_consumable", "label": "update_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L162"}, {"id": "crud_consumable_soft_delete_consumable", "label": "soft_delete_consumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L208"}, {"id": "crud_consumable_build_manual_out_remark", "label": "_build_manual_out_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L220"}, {"id": "crud_consumable_stock_in", "label": "stock_in()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L240"}, {"id": "crud_consumable_batch_stock_in", "label": "batch_stock_in()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L296"}, {"id": "crud_consumable_stock_out", "label": "stock_out()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L371"}, {"id": "crud_consumable_batch_stock_out", "label": "batch_stock_out()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L442"}, {"id": "crud_consumable_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L530"}, {"id": "crud_consumable_rationale_1", "label": "\u8017\u6750 CRUD\uff08biz_consumable\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_py", "target": "decimal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_consumable_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00coLine truncated
+2
View File
@@ -2556,6 +2556,7 @@ class BizConsumableStockLog(Base):
stock_after = Column(Numeric(18, 4), nullable=False, comment="变动后库存")
source_type = Column(String(16), nullable=False, comment="来源:manual_in/manual_out/step_save")
step_id = Column(String(64), nullable=True, comment="生产任务步骤ID")
step_name = Column(String(200), nullable=True, comment="步骤名称快照")
task_id = Column(String(64), nullable=True, comment="生产任务ID")
task_no = Column(String(32), nullable=True, comment="生产任务编号快照")
receiver = Column(String(64), nullable=True, comment="领用人")
@@ -2585,6 +2586,7 @@ class BizReagentStockLog(Base):
stock_after = Column(Numeric(18, 4), nullable=False, comment="变动后库存")
source_type = Column(String(16), nullable=False, comment="来源:manual_in/manual_out/step_save")
step_id = Column(String(64), nullable=True, comment="生产任务步骤ID")
step_name = Column(String(200), nullable=True, comment="步骤名称快照")
task_id = Column(String(64), nullable=True, comment="生产任务ID")
task_no = Column(String(32), nullable=True, comment="生产任务编号快照")
receiver = Column(String(64), nullable=True, comment="领用人")
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+104 -109
View File
@@ -1,12 +1,12 @@
# Graph Report - app (2026-05-23)
## Corpus Check
- 140 files · ~125,737 words
- 142 files · ~130,208 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 2481 nodes · 9810 edges · 52 communities detected
- Extraction: 42% EXTRACTED · 58% INFERRED · 0% AMBIGUOUS · INFERRED: 5728 edges (avg confidence: 0.63)
- 2542 nodes · 10216 edges · 51 communities detected
- Extraction: 41% EXTRACTED · 59% INFERRED · 0% AMBIGUOUS · INFERRED: 6029 edges (avg confidence: 0.63)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
@@ -55,25 +55,24 @@
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_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 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
## God Nodes (most connected - your core abstractions)
1. `success_response()` - 391 edges
2. `error_response()` - 314 edges
3. `SysUser` - 218 edges
4. `BizQcMaterialUsage` - 201 edges
5. `BizMaterialStockLog` - 197 edges
6. `BizQcTaskResult` - 197 edges
7. `BizQcMaterial` - 197 edges
8. `BizMaterial` - 194 edges
9. `BizQcItemParam` - 192 edges
10. `generate_uuid()` - 136 edges
1. `success_response()` - 403 edges
2. `error_response()` - 322 edges
3. `SysUser` - 230 edges
4. `BizQcMaterialUsage` - 205 edges
5. `BizMaterialStockLog` - 201 edges
6. `BizQcTaskResult` - 201 edges
7. `BizQcMaterial` - 201 edges
8. `BizMaterial` - 198 edges
9. `BizQcItemParam` - 196 edges
10. `generate_uuid()` - 146 edges
## Surprising Connections (you probably didn't know these)
- `统一记录 API 请求/响应出入参的中间件` --uses--> `SysApiRequestLog` [INFERRED]
@@ -90,48 +89,48 @@
## Communities
### Community 0 - "Community 0"
Cohesion: 0.01
Nodes (427): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+419 more)
Cohesion: 0.02
Nodes (429): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+421 more)
### Community 1 - "Community 1"
Cohesion: 0.02
Nodes (416): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+408 more)
Nodes (402): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+394 more)
### Community 2 - "Community 2"
Cohesion: 0.06
Nodes (272): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+264 more)
Cohesion: 0.01
Nodes (258): apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), _resolve_user_role_scopes(), generate_uuid(), batch_stock_in(), batch_stock_out(), consumable_code_exists() (+250 more)
### Community 3 - "Community 3"
Cohesion: 0.02
Nodes (190): generate_uuid(), appointment_no_exists(), create_exhibition_appointment(), _format_visit_date(), _generate_appointment_no(), get_exhibition_appointment(), list_exhibition_appointments(), 展览预约 CRUD(biz_exhibition_appointment) (+182 more)
Cohesion: 0.06
Nodes (221): InsuranceCompanyCreateBody, InsuranceCompanyInvoiceCreateBody, InsuranceCompanyInvoiceUpdateBody, InsuranceCompanyUpdateBody, InsuranceProjectPriceCreateBody, InsuranceProjectPriceUpdateBody, 保险公司及险种价格管理 API(保险公司 + 开票信息 + 险种价格), Base (+213 more)
### Community 4 - "Community 4"
Cohesion: 0.03
Nodes (147): list_collection_regions(), _persist_protocol_sub_resources(), list_ethnics_for_select(), InsuranceCompanyCreateBody, InsuranceCompanyInvoiceCreateBody, InsuranceCompanyInvoiceUpdateBody, InsuranceCompanyUpdateBody, InsuranceProjectPriceCreateBody (+139 more)
Cohesion: 0.06
Nodes (164): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+156 more)
### Community 5 - "Community 5"
Cohesion: 0.03
Nodes (99): list_roles_for_select(), _avatar_url_field(), _build_user_info_payload(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线), 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。, 与 web-admin `userInfo` 字段约定一致。 (+91 more)
Nodes (100): 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)。 (+92 more)
### Community 6 - "Community 6"
Cohesion: 0.05
Nodes (96): _accept_conclusion_label(), _attach_reception_detail(), complete_production_work_order(), create_production_work_order_from_reception(), _enrich_wo_items(), _fmt_dt(), _generate_work_order_no(), get_production_work_order() (+88 more)
Cohesion: 0.04
Nodes (104): 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() (+96 more)
### Community 7 - "Community 7"
Cohesion: 0.05
Nodes (26): BusinessException, InvalidStatusTransitionException, log_delivery_operation(), log_operation(), log_order_operation(), log_settlement_operation(), log_user_operation(), OrderLockedException (+18 more)
Cohesion: 0.04
Nodes (99): _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() (+91 more)
### Community 8 - "Community 8"
Cohesion: 0.06
Nodes (54): get_designer_data(), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, 审批意见:前端传 commentText,兼容 comment。, StartInstanceBody, TaskActionBody, list_results_by_task() (+46 more)
Nodes (60): _business_type_label(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields(), get_designer_data(), get_instance_detail(), list_completed_tasks(), list_my_instances() (+52 more)
### Community 9 - "Community 9"
Cohesion: 0.27
Nodes (58): ConsumableCreateBody, ConsumablePackCreateBody, ConsumablePackUpdateBody, ConsumableUpdateBody, OutputTypeCreateBody, OutputTypeUpdateBody, PackItemInput, ProcessCategoryCreateBody (+50 more)
Cohesion: 0.07
Nodes (67): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+59 more)
### Community 10 - "Community 10"
Cohesion: 0.09
Nodes (58): batch_delete_research_donations(), change_donation_status(), convert_from_storage(), convert_to_storage(), create_research_donation(), delete_research_donation(), _get_current_user_id(), get_research_donation_detail() (+50 more)
Cohesion: 0.05
Nodes (26): BusinessException, InvalidStatusTransitionException, log_delivery_operation(), log_operation(), log_order_operation(), log_settlement_operation(), log_user_operation(), OrderLockedException (+18 more)
### Community 11 - "Community 11"
Cohesion: 0.06
@@ -142,24 +141,24 @@ 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.11
Nodes (28): get_next_cell_product_code(), _build_facility_path_label(), build_split_product_codes(), create_cell_product(), create_cell_products_batch(), create_cell_products_by_quantity(), delete_cell_product(), _enrich_product_dicts() (+20 more)
### Community 14 - "Community 14"
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)
### Community 15 - "Community 15"
Cohesion: 0.18
Nodes (18): company_code_exists(), create_company(), get_company(), list_companies(), list_company_options(), _row_to_dict(), soft_delete_company(), update_company() (+10 more)
### Community 16 - "Community 16"
### Community 14 - "Community 14"
Cohesion: 0.2
Nodes (16): get_next_cell_product_code(), _build_facility_path_label(), build_split_product_codes(), create_cell_products_batch(), create_cell_products_by_quantity(), delete_cell_product(), _enrich_product_dicts(), get_cell_product() (+8 more)
### Community 15 - "Community 15"
Cohesion: 0.17
Nodes (18): create_storage_slot(), update_storage_slot(), batch_create_slots(), collect_descendant_ids(), create_facility(), create_slot(), get_children(), get_facility() (+10 more)
Nodes (15): Config, QuotationBase, QuotationCreate, QuotationDetailResponse, QuotationItemBase, QuotationItemCreate, QuotationItemResponse, QuotationItemUpdate (+7 more)
### Community 16 - "Community 16"
Cohesion: 0.25
Nodes (13): code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), _norm_status(), options_list() (+5 more)
### Community 17 - "Community 17"
Cohesion: 0.2
Nodes (14): deduct_for_task(), _display_remark(), list_usages(), list_usages_by_task(), _parse_receiver_purpose_from_remark(), 查询质检任务关联的物料使用记录(task_complete)。, 撤销任务此前 task_complete 扣减,便于重新填报物料使用。, 兼容旧数据:领用人/用途曾拼接在 remark 中。 (+6 more)
Cohesion: 0.21
Nodes (13): create_collection_region(), create_hospital(), get_collection_region(), get_hospital(), _hospital_names_by_region_ids(), _hospital_to_dict(), list_collection_regions(), list_hospitals() (+5 more)
### Community 18 - "Community 18"
Cohesion: 0.25
@@ -170,20 +169,20 @@ 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 20 - "Community 20"
Cohesion: 0.22
Nodes (12): create_access_log(), create_clean_room(), get_access_log(), get_clean_room(), list_access_logs(), list_clean_rooms(), room_code_exists(), _row_to_dict() (+4 more)
### Community 21 - "Community 21"
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 21 - "Community 21"
Cohesion: 0.22
Nodes (12): Config, InquiryBase, InquiryCreate, InquiryDetailResponse, InquiryItemBase, InquiryItemCreate, InquiryItemResponse, InquiryListResponse (+4 more)
### Community 22 - "Community 22"
Cohesion: 0.23
Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
### Community 23 - "Community 23"
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)
Cohesion: 0.31
Nodes (12): _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), options_list(), _row_to_dict() (+4 more)
### Community 24 - "Community 24"
Cohesion: 0.27
@@ -194,8 +193,8 @@ 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 26 - "Community 26"
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()
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 27 - "Community 27"
Cohesion: 0.31
@@ -219,124 +218,120 @@ Nodes (8): create_item_unit(), get_item_unit(), list_item_units(), 物品单位
### Community 32 - "Community 32"
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()
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 33 - "Community 33"
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 34 - "Community 34"
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 35 - "Community 35"
Cohesion: 0.36
Nodes (7): create_post(), get_post(), list_posts(), post_code_exists(), _row_to_dict(), soft_delete_post(), update_post()
### Community 36 - "Community 36"
### Community 34 - "Community 34"
Cohesion: 0.36
Nodes (7): create_tenant(), get_tenant(), list_tenants(), _row_to_dict(), soft_delete_tenant(), tenant_no_exists(), update_tenant()
### Community 37 - "Community 37"
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"
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 38 - "Community 38"
Cohesion: 0.36
Nodes (7): create_site(), get_site(), list_sites(), _row_to_dict(), site_code_exists(), soft_delete_site(), update_site()
### Community 39 - "Community 39"
### Community 36 - "Community 36"
Cohesion: 0.29
Nodes (2): BaseModel, SoftDeleteModel
### Community 40 - "Community 40"
### Community 37 - "Community 37"
Cohesion: 0.43
Nodes (7): _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), _resolve_receiver_purpose(), revert_step_stock_changes(), _row_to_dict(), _user_nick_name_map()
### Community 38 - "Community 38"
Cohesion: 0.38
Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 41 - "Community 41"
### Community 39 - "Community 39"
Cohesion: 0.4
Nodes (4): list_ethnics_for_select(), list_ethnics(), 民族码表 CRUD(全局 sys_ethnic), _row_to_dict()
### Community 40 - "Community 40"
Cohesion: 0.5
Nodes (3): BaseSettings, Config, Settings
### Community 42 - "Community 42"
### Community 41 - "Community 41"
Cohesion: 0.5
Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
### Community 43 - "Community 43"
### Community 42 - "Community 42"
Cohesion: 0.67
Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)
### Community 44 - "Community 44"
### Community 43 - "Community 43"
Cohesion: 1.0
Nodes (1): 请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
### Community 45 - "Community 45"
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
### Community 48 - "Community 48"
### Community 47 - "Community 47"
Cohesion: 1.0
Nodes (1): 发送订单状态通知 Args: openid: 用户openid ord
### Community 49 - "Community 49"
### Community 48 - "Community 48"
Cohesion: 1.0
Nodes (1): 发送支付成功通知 Args: openid: 用户openid ord
### Community 50 - "Community 50"
### Community 49 - "Community 49"
Cohesion: 1.0
Nodes (1): 发送配送通知 Args: openid: 配送员openid task
### Community 51 - "Community 51"
### Community 50 - "Community 50"
Cohesion: 1.0
Nodes (1): 发送配送时效预警 Args: openid: 配送员openid ta
### Community 52 - "Community 52"
### Community 51 - "Community 51"
Cohesion: 1.0
Nodes (1): 发送退款结果通知 Args: openid: 用户openid ord
### Community 53 - "Community 53"
### Community 52 - "Community 52"
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 39`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
- **Thin community `Community 36`** (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 42`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
- **Thin community `Community 41`** (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 43`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)`
- **Thin community `Community 42`** (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 44`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
- **Thin community `Community 43`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 45`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
- **Thin community `Community 44`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 48`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
- **Thin community `Community 47`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 49`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
- **Thin community `Community 48`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 50`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
- **Thin community `Community 49`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 51`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
- **Thin community `Community 50`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 52`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
- **Thin community `Community 51`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 53`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
- **Thin community `Community 52`** (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 0`, `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 8`, `Community 10`, `Community 11`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `Community 20`, `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`, `Community 37`, `Community 38`?**
_High betweenness centrality (0.104) - this node is a cross-community bridge._
- **Why does `SysUser` connect `Community 0` to `Community 2`, `Community 4`, `Community 5`, `Community 8`, `Community 9`, `Community 10`, `Community 17`, `Community 18`, `Community 19`?**
_High betweenness centrality (0.086) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 1` to `Community 0`, `Community 4`, `Community 5`, `Community 8`, `Community 10`, `Community 43`, `Community 13`, `Community 16`?**
_High betweenness centrality (0.064) - this node is a cross-community bridge._
- **Are the 390 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 390 INFERRED edges - model-reasoned connections that need verification._
- **Are the 363 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
_`str` has 363 INFERRED edges - model-reasoned connections that need verification._
- **Are the 313 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
_`error_response()` has 313 INFERRED edges - model-reasoned connections that need verification._
- **Are the 216 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
_`SysUser` has 216 INFERRED edges - model-reasoned connections that need verification._
- **Why does `generate_uuid()` connect `Community 2` to `Community 0`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 11`, `Community 13`, `Community 14`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `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`?**
_High betweenness centrality (0.118) - this node is a cross-community bridge._
- **Why does `SysUser` connect `Community 1` to `Community 3`, `Community 4`, `Community 5`, `Community 8`, `Community 9`, `Community 18`, `Community 19`?**
_High betweenness centrality (0.098) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 5`, `Community 6`, `Community 39`, `Community 8`, `Community 42`, `Community 14`?**
_High betweenness centrality (0.074) - this node is a cross-community bridge._
- **Are the 402 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 402 INFERRED edges - model-reasoned connections that need verification._
- **Are the 381 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
_`str` has 381 INFERRED edges - model-reasoned connections that need verification._
- **Are the 321 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
_`error_response()` has 321 INFERRED edges - model-reasoned connections that need verification._
- **Are the 228 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
_`SysUser` has 228 INFERRED edges - model-reasoned connections that need verification._
+4 -4
View File
@@ -57,12 +57,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">2481 nodes &middot; 9810 edges &middot; 58 communities</div>
<div id="stats">2542 nodes &middot; 10216 edges &middot; 57 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 46, "community_name": "Community 46", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 5, "community_name": "Community 5", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_init_scheduled_tasks", "label": "init_scheduled_tasks()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "init_scheduled_tasks()", "community": 5, "community_name": "Community 5", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_shutdown_scheduler", "label": "shutdown_scheduler()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "shutdown_scheduler()", "community": 5, "community_name": "Community 5", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "core_auth_py", "label": "auth.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 11.4, "font": {"size": 0, "color": "#ffffff"}, "title": "auth.py", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 18}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "_redis_session_enabled()", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 2}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "_get_redis_client()", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 9}, {"id": "core_auth_session_key", "label": "_session_key()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "_session_key()", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 5}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "boLine truncated
const RAW_EDGES = [{"from": "main_py", "to": "app_main_lifespan", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_mask_secret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_root", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_health_check", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_lifespan", "to": "core_login_crypto_ensure_initialized", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_init_scheduled_tasks", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_shutdown_scheduler", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "tasks_init_py", "to": "tasks_init_init_scheduled_tasks", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "tasks_init_py", "to": "tasks_init_shutdown_scheduler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_redis_session_enabled", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_redis_client", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_session_key", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_refresh_key", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_store_session", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_revoke_session", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_extend_session", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_is_session_valid", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_store_refresh_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_is_refresh_token_valid", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_revoke_refresh_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_create_access_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_create_refresh_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_decode_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_current_user_by_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_current_user", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "Line truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 454}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 428}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 277}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 207}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 165}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 128}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 102}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 68}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 68}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 65}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 61}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 49}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 31}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 31}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 21}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 20}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 19}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 15}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 15}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 14}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 14}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 13}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 12}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 12}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 11}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 10}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 10}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 10}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 10}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 10}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 10}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 10}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 10}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 9}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 9}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 9}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 9}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 8}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 7}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 4}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 4}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 3}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 2}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 2}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 1}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 1}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 1}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 1}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 1}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 1}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 1}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 1}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 1}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 1}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 0}];
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 45, "community_name": "Community 45", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 5, "community_name": "Community 5", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 5, "community_name": "Community 5", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_init_scheduled_tasks", "label": "init_scheduled_tasks()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "init_scheduled_tasks()", "community": 5, "community_name": "Community 5", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_shutdown_scheduler", "label": "shutdown_scheduler()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "shutdown_scheduler()", "community": 5, "community_name": "Community 5", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "core_auth_py", "label": "auth.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 11.3, "font": {"size": 0, "color": "#ffffff"}, "title": "auth.py", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 18}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_redis_session_enabled()", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 2}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "_get_redis_client()", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 9}, {"id": "core_auth_session_key", "label": "_session_key()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "_session_key()", "community": 5, "community_name": "Community 5", "source_file": "core/auth.py", "file_type": "code", "degree": 5}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "boLine truncated
const RAW_EDGES = [{"from": "main_py", "to": "app_main_lifespan", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_mask_secret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_root", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_health_check", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_lifespan", "to": "core_login_crypto_ensure_initialized", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_init_scheduled_tasks", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_shutdown_scheduler", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "tasks_init_py", "to": "tasks_init_init_scheduled_tasks", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "tasks_init_py", "to": "tasks_init_shutdown_scheduler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_redis_session_enabled", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_redis_client", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_session_key", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_refresh_key", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_store_session", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_revoke_session", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_extend_session", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_is_session_valid", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_store_refresh_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_is_refresh_token_valid", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_revoke_refresh_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_create_access_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_create_refresh_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_decode_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_current_user_by_token", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_current_user", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "Line truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 441}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 433}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 293}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 227}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 168}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 129}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 109}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 107}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 75}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 71}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 67}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 49}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 31}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 20}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 18}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 16}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 15}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 15}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 15}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 14}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 13}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 13}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 13}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 12}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 11}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 10}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 10}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 10}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 10}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 10}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 10}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 10}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 10}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 9}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 9}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 8}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 8}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 7}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 6}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 4}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 4}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 3}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 2}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 2}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 1}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 1}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 1}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 1}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 1}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 1}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 1}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 1}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 1}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 1}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 0}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 0}];
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
+10668 -5247
View File
File diff suppressed because it is too large. Load diff
+7 -5
View File
@@ -25,7 +25,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/core/wechat_message.py": 1778578258.0458734,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/material.py": 1779283385.245847,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_param.py": 1779022399.0175831,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1779491653.3192608,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1779509954.4854348,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/__init__.py": 1779418058.876012,
"/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,
@@ -76,13 +76,14 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py": 1779265648.2051165,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/material_stock_log.py": 1779281903.0942652,
"/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/consumable.py": 1779510193.3188746,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sop_document.py": 1779265721.9928973,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779506354.67238,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779510450.6769412,
"/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/reagent.py": 1779510328.552785,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1779329214.3583212,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py": 1779332036.2049248,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py": 1779510275.0678422,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py": 1778775238.2993922,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/__init__.py": 1778605691.3816392,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py": 1779265659.3453207,
@@ -110,6 +111,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol_no.py": 1779279043.1571646,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_facility.py": 1779270989.9713993,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py": 1778733001.8375483,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py": 1779510237.5108597,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/dept.py": 1779265637.7914758,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/base.py": 1778578258.062207,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/protocol_donation_convert.py": 1779161468.6582925,
@@ -133,7 +135,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": 1779435531.0507855,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py": 1779510401.9179235,
"/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,
@@ -1,17 +0,0 @@
-- /api/web/admin/api-request-logs 列表性能索引补强
-- 典型查询:
-- WHERE is_del=0 [AND http_method=?] [AND status_code=?]
-- [AND create_at between ? and ?]
-- ORDER BY create_at DESC
-- 默认列表 + 时间倒序分页
ALTER TABLE sys_api_request_log
ADD INDEX idx_arl_isdel_createat (is_del, create_at);
-- 按方法过滤
ALTER TABLE sys_api_request_log
ADD INDEX idx_arl_isdel_method_createat (is_del, http_method, create_at);
-- 按状态码过滤
ALTER TABLE sys_api_request_log
ADD INDEX idx_arl_isdel_status_createat (is_del, status_code, create_at);
@@ -1,12 +0,0 @@
-- 给 /api/web/admin/products 列表(GET,前端加密传输时为 POST + X-HTTP-Method-Override: GET)做索引补强
-- 典型 SQL:WHERE is_del = 0 [AND category_id = ?] [AND (name LIKE ... OR description LIKE ...)] ORDER BY create_at DESC
-- LIKE '%keyword%' 无法有效走 name/description 索引;无关键词时下面索引可帮助 COUNT + 分页排序。
-- 执行前请先 SHOW INDEX FROM bas_product; 若索引已存在可跳过对应语句。
-- 1) 全量列表 / 仅启用筛选:is_del + 排序字段
ALTER TABLE bas_product
ADD INDEX idx_product_isdel_createat (is_del, create_at);
-- 2) 按分类筛选 + 排序(与 1 并存;分类列表走此索引更省扫描)
ALTER TABLE bas_product
ADD INDEX idx_product_isdel_category_createat (is_del, category_id, create_at);
@@ -1,26 +0,0 @@
-- /api/web/delivery-tasks 列表性能索引补强
-- 目标查询特征:
-- 1) WHERE is_del=0 ORDER BY create_at DESC(默认列表)
-- 2) WHERE is_del=0 AND region_id=? AND status=? ORDER BY create_at DESC
-- 3) WHERE is_del=0 AND deliver_id=? ORDER BY create_at DESC
-- 4) 列表中按 task_id 聚合明细数量(biz_delivery_task_item)
-- 1) 默认列表与时间倒序分页
ALTER TABLE biz_delivery_task
ADD INDEX idx_dt_isdel_createat (is_del, create_at);
-- 2) 区域 + 状态过滤场景
ALTER TABLE biz_delivery_task
ADD INDEX idx_dt_isdel_region_status_createat (is_del, region_id, status, create_at);
-- 3) 配送员维度过滤场景
ALTER TABLE biz_delivery_task
ADD INDEX idx_dt_isdel_deliver_createat (is_del, deliver_id, create_at);
-- 4) 供应商维度过滤场景(供应商端任务列表)
ALTER TABLE biz_delivery_task
ADD INDEX idx_dt_isdel_supplier_createat (is_del, supplier_id, create_at);
-- 5) 列表 itemCount 聚合:WHERE task_id IN (...) AND is_del=0 GROUP BY task_id
ALTER TABLE biz_delivery_task_item
ADD INDEX idx_dti_task_isdel (task_id, is_del);
@@ -1,21 +0,0 @@
-- 给 /api/web/admin/orders 列表接口做性能索引补强(幂等尽量实现)
-- 注意:不同 MySQL 版本对 IF NOT EXISTS 支持不同;若执行失败,请先 SHOW INDEX 再手动判断是否已存在。
-- 1) 覆盖最常见列表:WHERE is_del=0 ORDER BY create_at DESC
-- 目标:减少 Using filesort / 全表扫描风险
ALTER TABLE biz_order
ADD INDEX idx_order_isdel_createat (is_del, create_at);
-- 2) 常用筛选:区域 + 订单主状态 + 时间排序
ALTER TABLE biz_order
ADD INDEX idx_order_isdel_region_orderstatus_createat (is_del, region_id, order_status, create_at);
-- 3) 常用筛选:区域 + 创建时间范围(startDate/endDate)
ALTER TABLE biz_order
ADD INDEX idx_order_isdel_region_createat (is_del, region_id, create_at);
-- 4) 单号查询建议:
-- 当前实现是 order_no LIKE '%xxx%',该写法通常无法走索引。
-- 若业务可改为前缀匹配(LIKE 'xxx%')或精确匹配(=),将显著提升性能。
-- 订单号已有唯一索引 uk_order_no(可用于 '=' 或前缀匹配)。
@@ -1,20 +0,0 @@
-- /api/web/admin/price-versions 列表性能索引补强
-- 典型查询:
-- WHERE is_del=0 [AND region_id=?] [AND supplier_id=?] [AND status=?]
-- ORDER BY create_at DESC
-- 默认列表 + 时间倒序分页
ALTER TABLE biz_price_list
ADD INDEX idx_pl_isdel_createat (is_del, create_at);
-- 区域维度过滤
ALTER TABLE biz_price_list
ADD INDEX idx_pl_isdel_region_createat (is_del, region_id, create_at);
-- 供应商维度过滤
ALTER TABLE biz_price_list
ADD INDEX idx_pl_isdel_supplier_createat (is_del, supplier_id, create_at);
-- 状态维度过滤
ALTER TABLE biz_price_list
ADD INDEX idx_pl_isdel_status_createat (is_del, status, create_at);
@@ -1,7 +0,0 @@
-- 询价报价界面“区域”下拉/Tab:启用区域列表索引补强
-- 对应接口:GET /api/web/admin/regions/active
-- 查询:WHERE is_del=0 AND is_active=1 ORDER BY sort_order
ALTER TABLE sys_region
ADD INDEX idx_region_isdel_active_sort (is_del, is_active, sort_order);
+573
View File
@@ -0,0 +1,573 @@
#!/usr/bin/env python3
"""字段一致性检查器 — 检测 CRUD → API Schema → 前端 formData 字段缺失问题。
用法:
python backend/scripts/check_field_consistency.py
python backend/scripts/check_field_consistency.py --entity consumable
python backend/scripts/check_field_consistency.py --json
退出码:
0 — 全部通过
1 — 存在警告(字段缺失)
2 — 存在错误(文件/类找不到等)
"""
from __future__ import annotations
import argparse
import json
import os
import re
import sys
from typing import Any, Dict, List, Optional, Set, Tuple
# ---------------------------------------------------------------------------
# 项目根目录(从脚本位置推断)
# ---------------------------------------------------------------------------
_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
_PROJECT_ROOT = os.path.abspath(os.path.join(_SCRIPT_DIR, "..", ".."))
# ---------------------------------------------------------------------------
# 只读字段 — 这些字段出现在 _row_to_dict 但不应出现在 CreateBody/UpdateBody/formData
# ---------------------------------------------------------------------------
READ_ONLY_FIELDS: Set[str] = {
"id",
"createTime",
"updateTime",
"stockQty",
"tenantNo",
"attachmentFiles", # 计算字段,由后端从 URLs 生成
}
# ---------------------------------------------------------------------------
# 实体注册表
# ---------------------------------------------------------------------------
ENTITIES: List[Dict[str, str]] = [
{
"name": "consumable",
"crud_file": "backend/app/crud/consumable.py",
"schema_file": "backend/app/api/production.py",
"create_body": "ConsumableCreateBody",
"update_body": "ConsumableUpdateBody",
"frontend_file": "web-admin/src/views/production/consumable/index.vue",
},
{
"name": "reagent",
"crud_file": "backend/app/crud/reagent.py",
"schema_file": "backend/app/api/production.py",
"create_body": "ReagentCreateBody",
"update_body": "ReagentUpdateBody",
"frontend_file": "web-admin/src/views/production/reagent/index.vue",
},
{
"name": "material (market)",
"crud_file": "backend/app/crud/material.py",
"schema_file": "backend/app/api/material.py",
"create_body": "MaterialBody",
"update_body": "MaterialUpdateBody",
"frontend_file": "web-admin/src/views/market/material/index.vue",
},
{
"name": "qc_material",
"crud_file": "backend/app/crud/qc_material.py",
"schema_file": "backend/app/api/qc.py",
"create_body": "QcMaterialBody",
"update_body": "QcMaterialUpdateBody",
"frontend_file": "web-admin/src/views/quality/material/index.vue",
},
{
"name": "sop_document",
"crud_file": "backend/app/crud/sop_document.py",
"schema_file": "backend/app/api/production.py",
"create_body": "SopDocumentCreateBody",
"update_body": "SopDocumentUpdateBody",
"frontend_file": "web-admin/src/views/production/sop/index.vue",
},
]
# ===================================================================
# 终端颜色辅助
# ===================================================================
class _C:
"""ANSI 颜色常量"""
RESET = "\033[0m"
GREEN = "\033[32m"
YELLOW = "\033[33m"
RED = "\033[31m"
CYAN = "\033[36m"
BOLD = "\033[1m"
DIM = "\033[2m"
def _supports_color() -> bool:
"""检测终端是否支持颜色"""
if os.environ.get("NO_COLOR"):
return False
if not hasattr(sys.stdout, "isatty"):
return False
return sys.stdout.isatty()
_COLOR = _supports_color()
def cprint(text: str, color: str = "") -> None:
if _COLOR and color:
print("{}{}{}".format(color, text, _C.RESET))
else:
print(text)
# ===================================================================
# 工具函数
# ===================================================================
def _read_file(rel_path: str) -> Optional[str]:
"""读取项目根目录下的相对路径文件"""
full = os.path.join(_PROJECT_ROOT, rel_path)
if not os.path.isfile(full):
return None
with open(full, "r", encoding="utf-8", errors="replace") as f:
return f.read()
def _snake_to_camel(name: str) -> str:
"""snake_case → camelCase: warning_qty → warningQty"""
parts = name.split("_")
return parts[0] + "".join(p.capitalize() for p in parts[1:])
# ===================================================================
# 提取逻辑 — _row_to_dict
# ===================================================================
_RE_DICT_KEY = re.compile(r'"([a-zA-Z][a-zA-Z0-9]*)"\s*:')
def extract_row_to_dict_fields(source: str) -> List[str]:
"""从 CRUD 文件提取 _row_to_dict 函数的字典键(camelCase)。
支持一个文件中有多个 _row_to_dict 的情况 — 只取第一个。
"""
# 定位函数起始
func_match = re.search(
r"def\s+_row_to_dict\s*\([^)]*\)\s*->\s*[^:]+:", source
)
if not func_match:
return []
# 从函数开始往后找到第一个 return { ... } 块
start = func_match.end()
# 找到 return {
ret_match = re.search(r"return\s*\{", source[start:])
if not ret_match:
return []
brace_start = start + ret_match.end() - 1 # 指向 {
# 匹配大括号
depth = 0
end = brace_start
for i in range(brace_start, len(source)):
ch = source[i]
if ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
end = i
break
block = source[brace_start : end + 1]
keys = _RE_DICT_KEY.findall(block)
# 去重但保持顺序
seen = set()
result = []
for k in keys:
if k not in seen:
seen.add(k)
result.append(k)
return result
# ===================================================================
# 提取逻辑 — Pydantic Schema 类
# ===================================================================
_RE_FIELD_ALIAS = re.compile(r'alias\s*=\s*"([^"]+)"')
_RE_FIELD_LINE = re.compile(
r"^\s+([a-z_][a-z0-9_]*)\s*:\s*"
)
def extract_schema_fields(source: str, class_name: str) -> Optional[List[str]]:
"""从 Pydantic 类提取字段名(返回 camelCase 列表)。
优先使用 alias,否则 snake_case 转 camelCase。
返回 None 表示类未找到。
"""
# 找到类定义
class_match = re.search(
r"class\s+{}\s*\([^)]*\)\s*:".format(re.escape(class_name)),
source,
)
if not class_match:
return None
class_start = class_match.end()
# 收集类体 — 到下一个顶层 class 或 def(不缩进)或文件末尾
body_lines = []
for line in source[class_start:].split("\n"):
stripped = line.lstrip()
if stripped and not stripped.startswith("#") and not line[0].isspace():
# 到达下一个顶层定义
break
if stripped.startswith("class ") or (stripped.startswith("def ") and not line.startswith(" ")):
break
body_lines.append(line)
body = "\n".join(body_lines)
fields = []
# 按行解析
for line in body.split("\n"):
field_match = _RE_FIELD_LINE.match(line)
if not field_match:
continue
field_name = field_match.group(1)
if field_name == "model_config":
continue
# 检查是否有 alias
alias_match = _RE_FIELD_ALIAS.search(line)
if alias_match:
fields.append(alias_match.group(1))
else:
fields.append(_snake_to_camel(field_name))
return fields
# ===================================================================
# 提取逻辑 — 前端 formData
# ===================================================================
_RE_FORMDATA_KEY = re.compile(r"^\s+([a-zA-Z][a-zA-Z0-9]*)\s*:")
def extract_frontend_formdata(source: str) -> List[str]:
"""从 Vue 文件提取 formData 的键名(camelCase)。"""
# 匹配多种写法: reactive({ ... }), reactive<SomeType>({ ... })
match = re.search(
r"(?:const|let|var)\s+formData\s*=\s*reactive(?:<[^>]*>)?\s*\(\s*\{",
source,
)
if not match:
return []
start = match.end() - 1 # 指向 {
depth = 0
end = start
for i in range(start, len(source)):
ch = source[i]
if ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
end = i
break
block = source[start : end + 1]
fields = []
for line in block.split("\n"):
m = _RE_FORMDATA_KEY.match(line)
if m:
fields.append(m.group(1))
return fields
# ===================================================================
# 单个实体检查
# ===================================================================
def check_entity(entity: Dict[str, str]) -> Dict[str, Any]:
"""检查单个实体的字段一致性,返回报告字典。"""
name = entity["name"]
report: Dict[str, Any] = {
"entity": name,
"status": "ok",
"crud_fields": [],
"create_body_fields": None,
"update_body_fields": None,
"frontend_fields": [],
"warnings": [],
"errors": [],
}
# 1. 读取 CRUD 文件
crud_src = _read_file(entity["crud_file"])
if crud_src is None:
report["status"] = "error"
report["errors"].append("CRUD file not found: {}".format(entity["crud_file"]))
return report
crud_fields = extract_row_to_dict_fields(crud_src)
report["crud_fields"] = crud_fields
if not crud_fields:
report["status"] = "error"
report["errors"].append(
"No _row_to_dict fields found in {}".format(entity["crud_file"])
)
return report
writable_fields = [f for f in crud_fields if f not in READ_ONLY_FIELDS]
# 2. 读取 Schema 文件
schema_src = _read_file(entity["schema_file"])
if schema_src is None:
report["status"] = "error"
report["errors"].append(
"Schema file not found: {}".format(entity["schema_file"])
)
return report
# 3. 提取 CreateBody
create_fields = extract_schema_fields(schema_src, entity["create_body"])
report["create_body_fields"] = create_fields
if create_fields is None:
report["status"] = "warning"
report["warnings"].append(
"Create body class '{}' not found in {}".format(
entity["create_body"], entity["schema_file"]
)
)
else:
missing = [f for f in writable_fields if f not in create_fields]
if missing:
report["status"] = "warning"
report["warnings"].append(
"CreateBody missing fields: {}".format(", ".join(sorted(missing)))
)
# 4. 提取 UpdateBody
update_fields = extract_schema_fields(schema_src, entity["update_body"])
report["update_body_fields"] = update_fields
if update_fields is None:
report["status"] = "warning"
report["warnings"].append(
"Update body class '{}' not found in {}".format(
entity["update_body"], entity["schema_file"]
)
)
else:
missing = [f for f in writable_fields if f not in update_fields]
if missing:
report["status"] = "warning"
report["warnings"].append(
"UpdateBody missing fields: {}".format(", ".join(sorted(missing)))
)
# 5. 读取前端文件
fe_src = _read_file(entity["frontend_file"])
if fe_src is None:
report["status"] = "warning"
report["warnings"].append(
"Frontend file not found: {}".format(entity["frontend_file"])
)
return report
fe_fields = extract_frontend_formdata(fe_src)
report["frontend_fields"] = fe_fields
if not fe_fields:
report["status"] = "warning"
report["warnings"].append(
"No formData found in {}".format(entity["frontend_file"])
)
return report
missing_fe = [f for f in writable_fields if f not in fe_fields]
if missing_fe:
report["status"] = "warning"
report["warnings"].append(
"Frontend formData missing fields: {}".format(
", ".join(sorted(missing_fe))
)
)
# 6. 反向检查: Schema 有但 _row_to_dict 没有的字段
if create_fields is not None:
extra_create = [f for f in create_fields if f not in crud_fields]
if extra_create:
report.setdefault("info", []).append(
"CreateBody has extra fields (not in _row_to_dict): {}".format(
", ".join(sorted(extra_create))
)
)
# 7. 反向检查: formData 有但 _row_to_dict 没有的字段
extra_fe = [f for f in fe_fields if f not in crud_fields]
if extra_fe:
report.setdefault("info", []).append(
"Frontend formData has extra fields (not in _row_to_dict): {}".format(
", ".join(sorted(extra_fe))
)
)
return report
# ===================================================================
# 报告输出
# ===================================================================
def print_report(report: Dict[str, Any]) -> None:
"""打印单个实体的检查报告(终端彩色输出)"""
name = report["entity"]
status = report["status"]
if status == "ok":
cprint(" [OK] {}".format(name), _C.GREEN)
elif status == "warning":
cprint(" [!!] {} — warnings".format(name), _C.YELLOW)
else:
cprint(" [XX] {} — errors".format(name), _C.RED)
# CRUD fields
crud_fields = report.get("crud_fields", [])
if crud_fields:
writable = [f for f in crud_fields if f not in READ_ONLY_FIELDS]
read_only = [f for f in crud_fields if f in READ_ONLY_FIELDS]
cprint(
" _row_to_dict ({} total, {} writable): {}".format(
len(crud_fields),
len(writable),
", ".join(writable),
),
_C.DIM,
)
if read_only:
cprint(
" read-only: {}".format(", ".join(sorted(read_only))),
_C.DIM,
)
# Schema fields
for body_label, body_key in [
("CreateBody", "create_body_fields"),
("UpdateBody", "update_body_fields"),
]:
fields = report.get(body_key)
if fields is not None:
cprint(
" {}: {}".format(body_label, ", ".join(fields)),
_C.DIM,
)
# Frontend fields
fe_fields = report.get("frontend_fields", [])
if fe_fields:
cprint(
" formData: {}".format(", ".join(fe_fields)),
_C.DIM,
)
# Warnings
for w in report.get("warnings", []):
cprint(" WARN: {}".format(w), _C.YELLOW)
# Errors
for e in report.get("errors", []):
cprint(" ERR: {}".format(e), _C.RED)
# Info
for info in report.get("info", []):
cprint(" INFO: {}".format(info), _C.CYAN)
print()
def print_json_report(reports: List[Dict[str, Any]]) -> None:
"""输出 JSON 格式报告"""
print(json.dumps(reports, indent=2, ensure_ascii=False))
# ===================================================================
# 主入口
# ===================================================================
def main() -> int:
parser = argparse.ArgumentParser(
description="字段一致性检查器 — CRUD ↔ Schema ↔ 前端 formData"
)
parser.add_argument(
"--entity",
type=str,
default=None,
help="只检查指定实体名称(如 consumable)",
)
parser.add_argument(
"--json",
action="store_true",
dest="json_output",
help="输出 JSON 格式",
)
args = parser.parse_args()
# 筛选实体
entities = ENTITIES
if args.entity:
entities = [e for e in ENTITIES if e["name"] == args.entity]
if not entities:
cprint(
"Entity '{}' not found. Available: {}".format(
args.entity, ", ".join(e["name"] for e in ENTITIES)
),
_C.RED,
)
return 2
if not args.json_output:
cprint(
"Field Consistency Checker — checking {} entities".format(
len(entities)
),
_C.BOLD,
)
cprint("Project root: {}".format(_PROJECT_ROOT), _C.DIM)
print()
reports = []
has_warnings = False
has_errors = False
for entity in entities:
report = check_entity(entity)
reports.append(report)
if report["status"] == "warning":
has_warnings = True
elif report["status"] == "error":
has_errors = True
if args.json_output:
print_json_report(reports)
else:
for report in reports:
print_report(report)
# 汇总
ok_count = sum(1 for r in reports if r["status"] == "ok")
warn_count = sum(1 for r in reports if r["status"] == "warning")
err_count = sum(1 for r in reports if r["status"] == "error")
cprint(
"Summary: {} OK, {} warnings, {} errors (total {})".format(
ok_count, warn_count, err_count, len(reports)
),
_C.BOLD,
)
if has_errors:
return 2
if has_warnings:
return 1
return 0
if __name__ == "__main__":
sys.exit(main())
@@ -1,68 +0,0 @@
-- 运营端权限改造:super_admin + 多区域 + 菜单 code 授权
-- 1) 角色迁移:admin -> super_admin
UPDATE sys_user
SET role = 'super_admin',
update_at = NOW()
WHERE is_del = 0
AND role = 'admin';
-- 2) 用户-区域权限表
CREATE TABLE IF NOT EXISTS sys_user_region_scope (
id VARCHAR(32) NOT NULL COMMENT '主键ID',
user_id VARCHAR(32) NOT NULL COMMENT '用户ID',
region_id VARCHAR(32) NOT NULL COMMENT '区域ID',
is_del TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除',
create_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_by VARCHAR(32) DEFAULT NULL COMMENT '创建人ID',
create_name VARCHAR(100) DEFAULT NULL COMMENT '创建人姓名',
update_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
update_by VARCHAR(32) DEFAULT NULL COMMENT '修改人ID',
PRIMARY KEY (id),
UNIQUE KEY uk_user_region_scope (user_id, region_id, is_del),
KEY idx_user_region_scope_user (user_id, is_del),
KEY idx_user_region_scope_region (region_id, is_del)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户区域权限';
-- 3) 用户-区域权限历史表(无索引、无 is_del)
CREATE TABLE IF NOT EXISTS sys_user_region_scope_his (
id VARCHAR(32) NOT NULL COMMENT '主键ID',
user_id VARCHAR(32) NOT NULL COMMENT '用户ID',
region_id VARCHAR(32) NOT NULL COMMENT '区域ID',
create_at DATETIME DEFAULT NULL COMMENT '创建时间',
create_by VARCHAR(32) DEFAULT NULL COMMENT '创建人ID',
create_name VARCHAR(100) DEFAULT NULL COMMENT '创建人姓名',
update_at DATETIME DEFAULT NULL COMMENT '修改时间',
update_by VARCHAR(32) DEFAULT NULL COMMENT '修改人ID',
his_create_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '历史记录创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户区域权限历史';
-- 4) 用户-菜单 code 权限表
CREATE TABLE IF NOT EXISTS sys_user_menu_scope (
id VARCHAR(32) NOT NULL COMMENT '主键ID',
user_id VARCHAR(32) NOT NULL COMMENT '用户ID',
menu_code VARCHAR(100) NOT NULL COMMENT '菜单编码',
is_del TINYINT NOT NULL DEFAULT 0 COMMENT '是否删除',
create_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
create_by VARCHAR(32) DEFAULT NULL COMMENT '创建人ID',
create_name VARCHAR(100) DEFAULT NULL COMMENT '创建人姓名',
update_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
update_by VARCHAR(32) DEFAULT NULL COMMENT '修改人ID',
PRIMARY KEY (id),
UNIQUE KEY uk_user_menu_scope (user_id, menu_code, is_del),
KEY idx_user_menu_scope_user (user_id, is_del),
KEY idx_user_menu_scope_code (menu_code, is_del)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户菜单权限';
-- 5) 用户-菜单 code 权限历史表(无索引、无 is_del)
CREATE TABLE IF NOT EXISTS sys_user_menu_scope_his (
id VARCHAR(32) NOT NULL COMMENT '主键ID',
user_id VARCHAR(32) NOT NULL COMMENT '用户ID',
menu_code VARCHAR(100) NOT NULL COMMENT '菜单编码',
create_at DATETIME DEFAULT NULL COMMENT '创建时间',
create_by VARCHAR(32) DEFAULT NULL COMMENT '创建人ID',
create_name VARCHAR(100) DEFAULT NULL COMMENT '创建人姓名',
update_at DATETIME DEFAULT NULL COMMENT '修改时间',
update_by VARCHAR(32) DEFAULT NULL COMMENT '修改人ID',
his_create_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '历史记录创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户菜单权限历史';
+100
View File
@@ -0,0 +1,100 @@
# 字段一致性开发指南
## 问题背景
在前后端全链路开发中,一个字段需要同时出现在 **5 个位置** 才能完整打通:
```
前端 formData → API Schema (Pydantic) → API Handler 传参 → CRUD 函数签名 → ORM 赋值
```
任何一层遗漏都会导致字段**静默丢失**(Pydantic 默认忽略未定义字段,不报错),产生难以发现的 bug。
## 历史问题
| 时间 | 问题 | 根因 |
|------|------|------|
| 2026-05 | 耗材/试剂新增时 `warning_qty` 未保存 | Schema 缺字段 → Handler 没传 → CRUD 没接 |
| 2026-05 | 耗材/试剂新增时 `status` 未保存 | 同上 |
| 2026-05 | 变动记录筛选"出库"无效 | 前端 value 与后端期望值不匹配 |
## 开发纪律(MUST)
### 1. `_row_to_dict` 是单一真相源
CRUD 文件中的 `_row_to_dict` 函数定义了实体返回给前端的**所有可读字段**。它是字段一致性的基准。
### 2. 先写 `_row_to_dict`,再写 create/update
新增实体时:
1. 先定义 `_row_to_dict`,列出所有字段的读取逻辑
2. 根据 `_row_to_dict` 的字段列表,逐字段编写 CreateBody/UpdateBody
3. 根据 Schema 字段,逐字段编写 create/update 函数签名和 ORM 赋值
4. 根据后端字段列表,编写前端 formData
### 3. 排除只读字段
以下字段出现在 `_row_to_dict` 中但**不需要**出现在 CreateBody/UpdateBody 或 formData 中:
- `id` — 自动生成
- `createTime` / `updateTime` — 自动维护
- `stockQty` — 通过出入库操作维护,不可直接设置
- `tenantNo` — 从认证上下文获取
### 4. 每个字段必须检查的 5 个位置
以 `warningQty` 为例:
| 位置 | 代码 | 必须 |
|------|------|------|
| `_row_to_dict` | `"warningQty": _dec(c.warning_qty)` | ✅ 读取 |
| CreateBody | `warning_qty: Optional[float] = Field(0, alias="warningQty")` | ✅ 接收 |
| Handler | `warning_qty=body.warning_qty` | ✅ 传递 |
| create 函数签名 | `warning_qty: Optional[float] = None` | ✅ 接收 |
| create ORM 赋值 | `warning_qty=warning_qty if warning_qty is not None else 0` | ✅ 写入 |
### 5. 实现后验证
每个实体完成后运行:
```bash
python backend/scripts/check_field_consistency.py
```
检查项:
- `_row_to_dict` 中的可写字段是否都在 CreateBody/UpdateBody 中
- `_row_to_dict` 中的可写字段是否都在前端 formData 中
- 前后端字段值映射是否一致(如筛选条件 value 对应关系)
## 校验脚本
`backend/scripts/check_field_consistency.py` 自动扫描以下三层,输出 diff 报告:
1. **CRUD 层**:提取 `_row_to_dict` 的所有 camelCase key
2. **API 层**:提取 CreateBody/UpdateBody 的所有字段(含 alias)
3. **前端层**:提取 `formData` 的所有 key
### 使用方式
```bash
# 检查所有注册实体
python backend/scripts/check_field_consistency.py
# 检查单个实体
python backend/scripts/check_field_consistency.py --entity consumable
# JSON 格式输出
python backend/scripts/check_field_consistency.py --json
```
### 退出码
- `0`:所有检查通过
- `1`:发现字段不一致
## 常见陷阱
1. **alias 遗漏**:Schema 字段有 `alias="warningQty"` 但忘记写,Pydantic 只接受 snake_case 键名
2. **Handler 传参遗漏**:Schema 有字段但 Handler 没传给 CRUD,字段在 Schema 层就被丢弃
3. **CRUD 签名遗漏**:Handler 传了但 CRUD 函数签名没接收,Python 会报 unexpected keyword argument(运行时错误)
4. **前端 value 与后端不匹配**:如筛选条件下拉框的 value 是 `"use"` 但后端期望 `"out"`
@@ -1,19 +0,0 @@
-- 细胞产品库字段重设计迁移
-- 日期: 2026-05-21
-- 设计文档: docs/superpowers/specs/2026-05-21-cell-product-library-design.md
-- 1. 新增 4 个业务字段(放在 storage_slot_id 之后,product_status 之前)
ALTER TABLE biz_cell_product
ADD COLUMN `passage` VARCHAR(8) DEFAULT NULL COMMENT '代次(P1~P8)' AFTER `storage_slot_id`,
ADD COLUMN `freeze_date` DATETIME DEFAULT NULL COMMENT '冻存日期' AFTER `passage`,
ADD COLUMN `expected_cell_count` DECIMAL(18,4) DEFAULT NULL COMMENT '预计细胞数量(单位:亿)' AFTER `freeze_date`,
ADD COLUMN `viability` DECIMAL(5,2) DEFAULT NULL COMMENT '活性(百分比,0~100)' AFTER `expected_cell_count`;
-- 2. 更新 product_status 默认值和注释
ALTER TABLE biz_cell_product
MODIFY COLUMN `product_status` VARCHAR(16) DEFAULT 'frozen' COMMENT '状态: frozen已冻存/sold已售卖/used已使用';
-- 3. 迁移旧状态数据(如有)
UPDATE biz_cell_product SET product_status = 'frozen' WHERE product_status = 'zk';
UPDATE biz_cell_product SET product_status = 'sold' WHERE product_status = 'yc';
UPDATE biz_cell_product SET product_status = 'used' WHERE product_status = 'ysy';
-168
View File
@@ -1,168 +0,0 @@
-- 细胞产品库初始化测试数据(20 条,覆盖各种场景)
-- 日期: 2026-05-21
-- 前提: 已执行 2026-05-21-cell-product-alter.sql 迁移
-- 场景覆盖:
-- 状态: frozen(12条) / sold(5条) / used(3条)
-- 代次: P1~P8 均有覆盖
-- 活性: 70.0 ~ 99.5,含 NULL
-- 预计细胞数量: 0.5 ~ 50.0 亿,含 NULL
-- 冻存日期: 有值 / NULL / 未来日期
-- 有效期: 已过期 / 未过期 / NULL
-- 产品图片: 有值 / NULL
-- 备注: 有值 / NULL
-- 数量/单位: 1~100 份
INSERT INTO biz_cell_product
(id, product_code, product_name, product_type_id, spec_id, batch_no, storage_slot_id,
passage, freeze_date, expected_cell_count, viability,
product_status, source_type, production_task_id,
quantity, unit, expiry_date, product_images,
tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag)
VALUES
-- ==================== 已冻存 frozen (12条) ====================
-- 1. 典型冻存产品:高活性、P2代次、有图片有备注
('60eaac11fceb4fd6b62e58e8be2c51cc', 'CP20260501000001', '间充质干细胞-MSC-P2-001', NULL, NULL, 'B20260501-001', NULL,
'P2', '2026-05-01 10:30:00', 5.0000, 95.50,
'frozen', 'manual', NULL,
10, '份', '2027-05-01 00:00:00', 'https://minio.example.com/cell-product/msc-p2-001.jpg',
'zkxw', 1, '高活性批次,来源于健康供体', 'admin', '', '2026-05-01 10:30:00', 'admin', '2026-05-01 10:30:00', 0),
-- 2. P1初代产品:数量大、高活性
('5ea198fede454198be443211d2687ab3', 'CP20260502000001', '脐带血造血干细胞-HSC-P1-002', NULL, NULL, 'B20260502-002', NULL,
'P1', '2026-05-02 14:20:00', 10.0000, 98.00,
'frozen', 'manual', NULL,
20, '份', '2027-11-02 00:00:00', NULL,
'zkxw', 2, NULL, 'admin', '', '2026-05-02 14:20:00', 'admin', '2026-05-02 14:20:00', 0),
-- 3. P3代次、低活性、无冻存日期
('661bcbadd41c4f478b16f3b9dd577914', 'CP20260503000001', '脂肪干细胞-ADSC-P3-003', NULL, NULL, 'B20260503-003', NULL,
'P3', NULL, 3.0000, 72.00,
'frozen', 'manual', NULL,
5, '份', '2026-08-03 00:00:00', NULL,
'zkxw', 3, '活性偏低,需进一步检测', 'admin', '', '2026-05-03 09:00:00', 'admin', '2026-05-03 09:00:00', 0),
-- 4. P4、中等活性、无预计细胞数量
('dd8d414f36a244bca611a51a96581a85', 'CP20260505000001', '神经干细胞-NSC-P4-004', NULL, NULL, 'B20260505-004', NULL,
'P4', '2026-05-05 08:15:00', NULL, 88.00,
'frozen', 'manual', NULL,
8, '份', '2027-05-05 00:00:00', 'https://minio.example.com/cell-product/nsc-p4-004.jpg',
'zkxw', 4, NULL, 'admin', '', '2026-05-05 08:15:00', 'admin', '2026-05-05 08:15:00', 0),
-- 5. P5、活性为NULL(未检测)
('815d5312900140c99e453c685c6d81a6', 'CP20260506000001', '诱导多能干细胞-iPSC-P5-005', NULL, NULL, 'B20260506-005', NULL,
'P5', '2026-05-06 16:45:00', 2.5000, NULL,
'frozen', 'manual', NULL,
3, '份', '2027-02-06 00:00:00', NULL,
'zkxw', 5, '待活性检测', 'admin', '', '2026-05-06 16:45:00', 'admin', '2026-05-06 16:45:00', 0),
-- 6. P6、大数量、有效期已过期(异常数据)
('da9b6201f2a74921b475c234e0d72841', 'CP20260507000001', '软骨细胞-CC-P6-006', NULL, NULL, 'B20260507-006', NULL,
'P6', '2026-05-07 11:00:00', 1.2000, 85.00,
'frozen', 'manual', NULL,
15, '份', '2025-05-07 00:00:00', NULL,
'zkxw', 6, '有效期已过,需处理', 'admin', '', '2026-05-07 11:00:00', 'admin', '2026-05-07 11:00:00', 0),
-- 7. P7、极小数量、极高活性
('e26ac18706b84c3da114f24eb50ec7e9', 'CP20260508000001', '心肌细胞-CM-P7-007', NULL, NULL, 'B20260508-007', NULL,
'P7', '2026-05-08 09:30:00', 0.5000, 99.50,
'frozen', 'manual', NULL,
1, '份', '2027-11-08 00:00:00', NULL,
'zkxw', 7, NULL, 'admin', '', '2026-05-08 09:30:00', 'admin', '2026-05-08 09:30:00', 0),
-- 8. P8、最大代次、多张图片
('177e808ce4b8454cb074e5965ed94bb1', 'CP20260509000001', '肝细胞-HC-P8-008', NULL, NULL, 'B20260509-008', NULL,
'P8', '2026-05-09 13:00:00', 8.0000, 80.00,
'frozen', 'manual', NULL,
12, '份', '2027-05-09 00:00:00', 'https://minio.example.com/cell-product/hc-p8-008a.jpg,https://minio.example.com/cell-product/hc-p8-008b.jpg',
'zkxw', 8, '代次较高,建议尽快使用', 'admin', '', '2026-05-09 13:00:00', 'admin', '2026-05-09 13:00:00', 0),
-- 9. P1、大预计细胞数量50亿
('0fe62984ef6c4d3eafa8bcff70c6e151', 'CP20260510000001', 'NK细胞-NK-P1-009', NULL, NULL, 'B20260510-009', NULL,
'P1', '2026-05-10 07:00:00', 50.0000, 96.00,
'frozen', 'manual', NULL,
30, '份', '2027-11-10 00:00:00', 'https://minio.example.com/cell-product/nk-p1-009.jpg',
'zkxw', 9, '大批次生产', 'admin', '', '2026-05-10 07:00:00', 'admin', '2026-05-10 07:00:00', 0),
-- 10. P3、无有效期
('cb8e8ea1581348f18c119e1611fba39f', 'CP20260511000001', 'T细胞-TC-P3-010', NULL, NULL, 'B20260511-010', NULL,
'P3', '2026-05-11 15:30:00', 15.0000, 91.00,
'frozen', 'manual', NULL,
25, '份', NULL, NULL,
'zkxw', 10, NULL, 'admin', '', '2026-05-11 15:30:00', 'admin', '2026-05-11 15:30:00', 0),
-- 11. P2、活性偏低70%
('28c6b50ccd3d4cf8ae9bbbbffef96418', 'CP20260512000001', '树突状细胞-DC-P2-011', NULL, NULL, 'B20260512-011', NULL,
'P2', '2026-05-12 10:00:00', 4.0000, 70.00,
'frozen', 'manual', NULL,
6, '份', '2026-11-12 00:00:00', NULL,
'zkxw', 11, '活性偏低,需复检', 'admin', '', '2026-05-12 10:00:00', 'admin', '2026-05-12 10:00:00', 0),
-- 12. P4、未来冻存日期(计划冻存)
('940c82c006954865adb09e31fae36038', 'CP20260513000001', '表皮细胞-EC-P4-012', NULL, NULL, 'B20260513-012', NULL,
'P4', '2026-06-15 00:00:00', 6.0000, 92.50,
'frozen', 'manual', NULL,
4, '份', '2027-06-15 00:00:00', NULL,
'zkxw', 12, '计划冻存,待入库', 'admin', '', '2026-05-13 08:00:00', 'admin', '2026-05-13 08:00:00', 0),
-- ==================== 已售卖 sold (5条) ====================
-- 13. P2、已售卖、高活性
('338ae843fb4a4914a1eb672fd7a5ee38', 'CP20260420000001', '间充质干细胞-MSC-P2-S01', NULL, NULL, 'B20260420-S01', NULL,
'P2', '2026-04-20 09:00:00', 5.0000, 97.00,
'sold', 'manual', NULL,
10, '份', '2027-04-20 00:00:00', 'https://minio.example.com/cell-product/msc-p2-s01.jpg',
'zkxw', 13, '已出售给合作医院', 'admin', '', '2026-04-20 09:00:00', 'admin', '2026-05-15 14:00:00', 0),
-- 14. P1、已售卖、最大批次
('237d80589852465180706d1f7a3d3586', 'CP20260418000001', '脐带血造血干细胞-HSC-P1-S02', NULL, NULL, 'B20260418-S02', NULL,
'P1', '2026-04-18 11:30:00', 20.0000, 99.00,
'sold', 'manual', NULL,
50, '份', '2027-10-18 00:00:00', NULL,
'zkxw', 14, NULL, 'admin', '', '2026-04-18 11:30:00', 'admin', '2026-05-16 09:30:00', 0),
-- 15. P3、已售卖、中活性
('a6380097234e4c15b04349f27348a9dd', 'CP20260415000001', '脂肪干细胞-ADSC-P3-S03', NULL, NULL, 'B20260415-S03', NULL,
'P3', '2026-04-15 08:00:00', 8.0000, 88.50,
'sold', 'manual', NULL,
15, '份', '2027-04-15 00:00:00', 'https://minio.example.com/cell-product/adsc-p3-s03a.jpg,https://minio.example.com/cell-product/adsc-p3-s03b.jpg',
'zkxw', 15, '科研合作项目使用', 'admin', '', '2026-04-15 08:00:00', 'admin', '2026-05-17 10:00:00', 0),
-- 16. P5、已售卖、低活性
('853e0e67632c4291bf9d111a43a17b71', 'CP20260410000001', '神经干细胞-NSC-P5-S04', NULL, NULL, 'B20260410-S04', NULL,
'P5', '2026-04-10 14:00:00', 2.0000, 75.00,
'sold', 'manual', NULL,
5, '份', '2026-10-10 00:00:00', NULL,
'zkxw', 16, '低价出售,活性一般', 'admin', '', '2026-04-10 14:00:00', 'admin', '2026-05-18 11:00:00', 0),
-- 17. P1、已售卖、未填活性
('ec5309d6870f486695cf5b5f63fd91d1', 'CP20260405000001', 'NK细胞-NK-P1-S05', NULL, NULL, 'B20260405-S05', NULL,
'P1', '2026-04-05 10:00:00', 30.0000, NULL,
'sold', 'manual', NULL,
20, '份', '2027-10-05 00:00:00', NULL,
'zkxw', 17, NULL, 'admin', '', '2026-04-05 10:00:00', 'admin', '2026-05-19 16:00:00', 0),
-- ==================== 已使用 used (3条) ====================
-- 18. P3、已使用(用于生产分化)
('5e1f8cf0bab14e3f964d5a7aafb09d0d', 'CP20260301000001', '间充质干细胞-MSC-P3-U01', NULL, NULL, 'B20260301-U01', NULL,
'P3', '2026-03-01 08:30:00', 10.0000, 93.00,
'used', 'manual', NULL,
8, '份', '2027-03-01 00:00:00', 'https://minio.example.com/cell-product/msc-p3-u01.jpg',
'zkxw', 18, '用于生产分化为软骨细胞', 'admin', '', '2026-03-01 08:30:00', 'admin', '2026-05-10 09:00:00', 0),
-- 19. P4、已使用、来源生产任务
('292c2ec830084ba08daf151845043dba', 'CP20260215000001', '诱导多能干细胞-iPSC-P4-U02', NULL, NULL, 'B20260215-U02', NULL,
'P4', '2026-02-15 12:00:00', 12.0000, 90.00,
'used', 'production', 'task-uuid-placeholder-001',
6, '份', '2027-02-15 00:00:00', NULL,
'zkxw', 19, '生产任务产出的细胞被用于后续分化实验', 'admin', '', '2026-02-15 12:00:00', 'admin', '2026-04-20 15:00:00', 0),
-- 20. P6、已使用、高代次低活性(极限场景)
('e1cb9f8cbe6a40998686a8bb8fb76c9a', 'CP20260201000001', '肝细胞-HC-P6-U03', NULL, NULL, 'B20260201-U03', NULL,
'P6', '2026-02-01 09:00:00', 1.5000, 78.50,
'used', 'manual', NULL,
2, '份', '2026-08-01 00:00:00', 'https://minio.example.com/cell-product/hc-p6-u03.jpg,https://minio.example.com/cell-product/hc-p6-u03-report.pdf',
'zkxw', 20, '高代次细胞,已用于药物毒性测试', 'admin', '', '2026-02-01 09:00:00', 'admin', '2026-03-15 10:00:00', 0);
@@ -1,37 +0,0 @@
-- ============================================================
-- 库位占用记录功能迁移
-- 日期: 2026-05-22
-- ============================================================
-- 1. 新增:库位占用记录表
CREATE TABLE biz_storage_slot_occupancy (
id VARCHAR(64) NOT NULL COMMENT '主键ID',
slot_id VARCHAR(64) NOT NULL COMMENT '储物格ID (FK → biz_storage_facility_slot)',
item_type VARCHAR(32) NOT NULL COMMENT '物品类型: cell_product=细胞产品, other=其他',
item_id VARCHAR(64) NOT NULL COMMENT '物品ID (指向对应业务表主键)',
item_code VARCHAR(64) NULL COMMENT '物品编码 (冗余展示)',
item_name VARCHAR(200) NULL COMMENT '物品名称 (冗余展示)',
item_source VARCHAR(32) NULL COMMENT '来源: production=生产入库, manual=手动入库, transfer=转移',
stored_at DATETIME NULL COMMENT '入库时间',
removed_at DATETIME NULL COMMENT '出库时间 (NULL=当前在库)',
occupancy_status VARCHAR(16) NOT NULL DEFAULT 'stored' COMMENT 'stored=在库, removed=已出库',
tenant_no VARCHAR(64) NULL COMMENT '租户编号',
order_num INT DEFAULT 0 COMMENT '排序',
remark VARCHAR(500) NULL COMMENT '备注',
create_by VARCHAR(64) NULL COMMENT '创建者',
create_dept_id VARCHAR(64) NULL COMMENT '创建部门',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by VARCHAR(64) NULL COMMENT '更新者',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
del_flag CHAR(1) DEFAULT '0' COMMENT '删除标志(0存在 1删除)',
PRIMARY KEY (id),
INDEX idx_sso_slot (slot_id, occupancy_status, del_flag),
INDEX idx_sso_item (item_type, item_id, del_flag),
INDEX idx_sso_tenant (tenant_no, del_flag)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库位占用记录表';
-- 2. 增强:biz_storage_facility_slot 增加缓存字段
ALTER TABLE biz_storage_facility_slot
ADD COLUMN occupied_count INT DEFAULT 0 COMMENT '当前占用数量',
ADD COLUMN last_item_type VARCHAR(32) NULL COMMENT '最近存储物品类型',
ADD COLUMN last_stored_at DATETIME NULL COMMENT '最近入库时间';
-51
View File
@@ -1,51 +0,0 @@
-- ============================================================
-- 入库放行审核 biz_storage_release_review
-- Date: 2026-05-23
-- ============================================================
SET NAMES utf8mb4;
-- ----------------------------
-- Table structure for biz_storage_release_review
-- ----------------------------
DROP TABLE IF EXISTS `biz_storage_release_review`;
CREATE TABLE `biz_storage_release_review` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`sample_code` VARCHAR(64) NOT NULL COMMENT '样本编码(关联键)',
`reception_source` VARCHAR(32) NOT NULL COMMENT '来源:cell_storage=采集/research_donation=捐赠',
`protocol_id` VARCHAR(64) DEFAULT NULL COMMENT '协议单ID',
`reception_id` VARCHAR(64) DEFAULT NULL COMMENT '样本接收记录ID',
`protocol_no` VARCHAR(64) DEFAULT NULL COMMENT '协议编号',
`sample_name` VARCHAR(128) DEFAULT NULL COMMENT '样本名称',
`review_conclusion` VARCHAR(16) DEFAULT NULL COMMENT '审核结论:tg=通过/btg=不通过/NULL=待审核',
`review_remark` VARCHAR(512) DEFAULT NULL COMMENT '审核备注',
`review_attachments` VARCHAR(4000) DEFAULT NULL COMMENT '审核附件(逗号分隔URL)',
`review_by` VARCHAR(64) DEFAULT NULL COMMENT '审核人ID',
`review_by_name` VARCHAR(64) DEFAULT NULL COMMENT '审核人姓名',
`review_time` DATETIME DEFAULT NULL COMMENT '审核时间',
`storage_status` VARCHAR(16) NOT NULL DEFAULT 'drk' COMMENT '入库状态:drk=待入库/yrk=已入库',
`storage_by` VARCHAR(64) DEFAULT NULL COMMENT '入库操作人ID',
`storage_by_name` VARCHAR(64) DEFAULT NULL COMMENT '入库操作人姓名',
`storage_time` DATETIME DEFAULT NULL COMMENT '入库时间',
`tenant_no` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '租户编号',
`order_num` INT(11) DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人ID',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人ID',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_srr_sample` (`tenant_no`, `sample_code`, `del_flag`),
KEY `idx_srr_protocol` (`tenant_no`, `protocol_id`, `del_flag`),
KEY `idx_srr_status` (`tenant_no`, `review_conclusion`, `storage_status`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='入库放行审核';
-- ----------------------------
-- Menu entry: 入库放行审核 (under 质量检测)
-- ----------------------------
-- 父菜单: 质量检测 id=70000000000000000000000000000001
-- 新菜单 ID: 70000000000000000000000000000011 (递增)
INSERT INTO `sys_menu` (`id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`, `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
VALUES ('70000000000000000000000000000011', '入库放行审核', '70000000000000000000000000000001', 'C', 'storage-release-review', '/quality-inspection/storage-release-review/index', 'biz:storageReleaseReview:list', 1, '1', '1', 'zkxw', 10, NULL, NULL, '', NOW(), NULL, NOW(), 0);
-91
View File
@@ -1,91 +0,0 @@
-- 快递公司初始化(仅国内)
-- 用法:
-- 1) 默认租户为 zkxw,如需其他租户请修改 @tenant_no
-- 2) 可重复执行:按 tenant_no + express_code + del_flag=0 去重插入
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
SET @tenant_no = 'zkxw';
SET @operator_id = 'd3000000000000000000000000000001';
START TRANSACTION;
DROP TEMPORARY TABLE IF EXISTS tmp_express_company_seed;
CREATE TEMPORARY TABLE tmp_express_company_seed (
express_code varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
express_name varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
order_num int(11) DEFAULT NULL,
remark varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=Memory DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO tmp_express_company_seed (express_code, express_name, order_num, remark) VALUES
('sf', '顺丰速运', 1, '国内主流快递'),
('jd', '京东快递', 2, '国内主流快递'),
('zt', '中通快递', 3, '国内主流快递'),
('yt', '圆通速递', 4, '国内主流快递'),
('sto', '申通快递', 5, '国内主流快递'),
('yunda', '韵达速递', 6, '国内主流快递'),
('deppon', '德邦快递', 7, '国内主流快递'),
('ems', 'EMS中国邮政速递物流', 8, '国家邮政体系'),
('youzheng', '中国邮政', 9, '邮政包裹/普邮'),
('jtexpress', '极兔速递', 10, '国内主流快递'),
('zjs', '宅急送', 11, '国内常见快递'),
('anneng', '安能物流', 12, '零担/大件常见'),
('suning', '苏宁物流', 13, '电商体系物流'),
('best', '百世快递', 14, '原百世快递体系'),
('tiantian', '天天快递', 15, '历史常见渠道'),
('guotong', '国通快递', 16, '历史常见渠道'),
('quanfen', '全峰快递', 17, '历史常见渠道'),
('rufengda', '如风达', 18, '历史常见渠道'),
('kuaijie', '快捷快递', 19, '历史常见渠道'),
('huitong', '汇通快运', 20, '区域快运常见'),
('yousu', '优速快递', 21, '国内常见快递'),
('suer', '速尔快递', 22, '国内常见快递'),
('ky', '跨越速运', 23, '企业件/时效件常见'),
('ymdd', '壹米滴答', 24, '零担快运常见'),
('longbang', '龙邦快递', 25, '国内常见快递');
INSERT INTO biz_express_company (
id,
express_code,
express_name,
tenant_no,
order_num,
remark,
create_by,
create_dept_id,
create_time,
update_by,
update_time,
del_flag
)
SELECT
CONCAT(
REPLACE(UUID(), '-', ''),
LPAD(CONV(CRC32(t.express_code), 10, 16), 8, '0')
),
t.express_code,
t.express_name,
@tenant_no,
t.order_num,
t.remark,
@operator_id,
'',
NOW(),
@operator_id,
NOW(),
0
FROM tmp_express_company_seed t
WHERE NOT EXISTS (
SELECT 1
FROM biz_express_company e
WHERE e.tenant_no COLLATE utf8mb4_unicode_ci = @tenant_no COLLATE utf8mb4_unicode_ci
AND e.express_code COLLATE utf8mb4_unicode_ci = t.express_code COLLATE utf8mb4_unicode_ci
AND e.del_flag = 0
);
DROP TEMPORARY TABLE IF EXISTS tmp_express_company_seed;
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
-3
View File
@@ -1,3 +0,0 @@
-- 市场物料库:增加预警库存字段(与质检物料库 biz_qc_material.warning_qty 对齐)
ALTER TABLE `biz_material`
ADD COLUMN `warning_qty` decimal(18, 4) NOT NULL DEFAULT 0 COMMENT '预警库存量' AFTER `stock_qty`;
@@ -1,80 +0,0 @@
-- ============================================================
-- 生产物料库存管理 - 数据库迁移脚本
-- 变更: production-material-inventory
-- ============================================================
-- 1. biz_consumable 新增库存字段
ALTER TABLE `biz_consumable`
ADD COLUMN `stock_qty` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '当前库存量' AFTER `description`,
ADD COLUMN `warning_qty` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '预警库存量' AFTER `stock_qty`,
ADD COLUMN `status` CHAR(1) NOT NULL DEFAULT '1' COMMENT '1-启用 0-停用' AFTER `warning_qty`;
-- 2. biz_reagent 新增库存字段
ALTER TABLE `biz_reagent`
ADD COLUMN `stock_qty` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '当前库存量' AFTER `description`,
ADD COLUMN `warning_qty` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '预警库存量' AFTER `stock_qty`,
ADD COLUMN `status` CHAR(1) NOT NULL DEFAULT '1' COMMENT '1-启用 0-停用' AFTER `warning_qty`;
-- 3. 耗材变动记录表
CREATE TABLE `biz_consumable_stock_log` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`material_id` VARCHAR(64) NOT NULL COMMENT '耗材ID',
`material_code` VARCHAR(64) DEFAULT NULL COMMENT '耗材编码快照',
`material_name` VARCHAR(200) DEFAULT NULL COMMENT '耗材名称快照',
`change_type` VARCHAR(16) NOT NULL COMMENT '变动类型:in入库 / use使用出库',
`change_qty` DECIMAL(18,4) NOT NULL COMMENT '变动数量(入库正数,出库负数)',
`stock_before` DECIMAL(18,4) NOT NULL COMMENT '变动前库存',
`stock_after` DECIMAL(18,4) NOT NULL COMMENT '变动后库存',
`source_type` VARCHAR(16) NOT NULL COMMENT '来源:manual_in / manual_out / step_save',
`step_id` VARCHAR(64) DEFAULT NULL COMMENT '生产任务步骤ID(step_save时有值)',
`task_id` VARCHAR(64) DEFAULT NULL COMMENT '生产任务ID(step_save时有值)',
`task_no` VARCHAR(32) DEFAULT NULL COMMENT '生产任务编号快照',
`receiver` VARCHAR(64) DEFAULT NULL COMMENT '领用人(手动出库时)',
`purpose` VARCHAR(512) DEFAULT NULL COMMENT '用途/事由(手动出库时)',
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
INDEX `idx_csl_material` (`material_id`, `del_flag`),
INDEX `idx_csl_step` (`step_id`, `del_flag`),
INDEX `idx_csl_task` (`task_id`, `del_flag`),
INDEX `idx_csl_tenant_time` (`tenant_no`, `change_type`, `create_time`),
INDEX `idx_csl_source` (`source_type`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='耗材变动记录';
-- 4. 试剂变动记录表
CREATE TABLE `biz_reagent_stock_log` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`material_id` VARCHAR(64) NOT NULL COMMENT '试剂ID',
`material_code` VARCHAR(64) DEFAULT NULL COMMENT '试剂编码快照',
`material_name` VARCHAR(200) DEFAULT NULL COMMENT '试剂名称快照',
`change_type` VARCHAR(16) NOT NULL COMMENT '变动类型:in入库 / use使用出库',
`change_qty` DECIMAL(18,4) NOT NULL COMMENT '变动数量(入库正数,出库负数)',
`stock_before` DECIMAL(18,4) NOT NULL COMMENT '变动前库存',
`stock_after` DECIMAL(18,4) NOT NULL COMMENT '变动后库存',
`source_type` VARCHAR(16) NOT NULL COMMENT '来源:manual_in / manual_out / step_save',
`step_id` VARCHAR(64) DEFAULT NULL COMMENT '生产任务步骤ID(step_save时有值)',
`task_id` VARCHAR(64) DEFAULT NULL COMMENT '生产任务ID(step_save时有值)',
`task_no` VARCHAR(32) DEFAULT NULL COMMENT '生产任务编号快照',
`receiver` VARCHAR(64) DEFAULT NULL COMMENT '领用人(手动出库时)',
`purpose` VARCHAR(512) DEFAULT NULL COMMENT '用途/事由(手动出库时)',
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
INDEX `idx_rsl_material` (`material_id`, `del_flag`),
INDEX `idx_rsl_step` (`step_id`, `del_flag`),
INDEX `idx_rsl_task` (`task_id`, `del_flag`),
INDEX `idx_rsl_tenant_time` (`tenant_no`, `change_type`, `create_time`),
INDEX `idx_rsl_source` (`source_type`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='试剂变动记录';
@@ -1,5 +0,0 @@
-- 生产任务表增加任务类型字段
-- 区分入库生产单 (cell_storage) / 出库生产单 (outbound)
ALTER TABLE biz_production_task
ADD COLUMN task_type VARCHAR(20) NOT NULL DEFAULT 'cell_storage' COMMENT '任务类型 cell_storage入库生产单 outbound出库生产单'
AFTER work_order_id;
-109
View File
@@ -1,109 +0,0 @@
-- 质检物料库测试数据(biz_qc_material / biz_qc_material_usage)
--
-- 用法:
-- 1) 默认租户 zkxw,默认操作人 d3000000000000000000000000000001(与 zkxw.sql 演示账号一致)
-- 2) 可重复执行:按物料编码前缀 QC-MAT-DEMO- 清理后重新插入
-- 3) 执行前请确认已建表(见 docs/superpowers/plans/2026-05-20-qc-material-library.md 中 DDL)
--
-- 示例:
-- mysql -u root -p zkxw < docs/sql/qc_material_demo_seed.sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
SET @tenant_no = 'zkxw';
SET @operator_id = 'd3000000000000000000000000000001';
SET @now = NOW();
START TRANSACTION;
-- 清理旧测试数据(先删变动记录,再删物料)
DELETE u
FROM `biz_qc_material_usage` u
INNER JOIN `biz_qc_material` m ON m.`id` = u.`material_id`
WHERE m.`tenant_no` = @tenant_no
AND m.`material_code` LIKE 'QC-MAT-DEMO-%';
DELETE FROM `biz_qc_material`
WHERE `tenant_no` = @tenant_no
AND `material_code` LIKE 'QC-MAT-DEMO-%';
-- ----------------------------
-- 质检物料主数据(10 条)
-- 覆盖:正常库存 / 库存预警 / 零库存 / 停用
-- ----------------------------
INSERT INTO `biz_qc_material` (
`id`,
`material_code`,
`material_name`,
`spec_model`,
`unit`,
`stock_qty`,
`warning_qty`,
`status`,
`tenant_no`,
`order_num`,
`remark`,
`create_by`,
`create_dept_id`,
`create_time`,
`update_by`,
`update_time`,
`del_flag`
) VALUES
('q1000000000000000000000000000001', 'QC-MAT-DEMO-001', 'PCR 扩增引物 Mix', '20× 预混', '支', 120.0000, 50.0000, '1', @tenant_no, 1, '常温避光', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000002', 'QC-MAT-DEMO-002', '核酸提取试剂盒', '96 孔板适用', '盒', 35.0000, 40.0000, '1', @tenant_no, 2, '库存低于预警线', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000003', 'QC-MAT-DEMO-003', '琼脂糖', 'Bio-Rad 常规型', 'g', 8.0000, 10.0000, '1', @tenant_no, 3, '粉末,干燥保存', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000004', 'QC-MAT-DEMO-004', 'TAE 电泳缓冲液', '50× 浓缩', '瓶', 200.0000, 30.0000, '1', @tenant_no, 4, NULL, @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000005', 'QC-MAT-DEMO-005', '无菌吸头', '200μL 滤芯', '盒', 5000.0000, 500.0000, '1', @tenant_no, 5, '每盒 96 支', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000006', 'QC-MAT-DEMO-006', 'EP 离心管', '1.5mL 锥底', '包', 3000.0000, 200.0000, '1', @tenant_no, 6, '每包 500 支', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000007', 'QC-MAT-DEMO-007', '医用丁腈手套', 'M 码 无粉', '盒', 150.0000, 50.0000, '1', @tenant_no, 7, '每盒 100 只', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000008', 'QC-MAT-DEMO-008', '75% 乙醇消毒液', '500ml 喷雾', '瓶', 0.0000, 20.0000, '1', @tenant_no, 8, '零库存,可测入库', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000009', 'QC-MAT-DEMO-009', '质检标准品', '冻干粉 1mg', '支', 25.0000, 10.0000, '1', @tenant_no, 9, '-20℃ 保存', @operator_id, '', @now, @operator_id, @now, 0),
('q1000000000000000000000000000010', 'QC-MAT-DEMO-010', '细胞培养基(旧批次)', '500ml', '瓶', 15.0000, 5.0000, '0', @tenant_no, 10, '停用批次,仅保留档案', @operator_id, '', @now, @operator_id, @now, 0);
-- ----------------------------
-- 物料变动记录(3 条,便于「物料变动记录」页联调)
-- change_type: in=入库 / use=使用;source_type: manual_in / task_complete
-- ----------------------------
INSERT INTO `biz_qc_material_usage` (
`id`,
`material_id`,
`material_code`,
`material_name`,
`change_type`,
`change_qty`,
`stock_after`,
`qc_task_id`,
`qc_task_no`,
`source_type`,
`tenant_no`,
`remark`,
`create_by`,
`create_dept_id`,
`create_time`,
`update_by`,
`update_time`,
`del_flag`
) VALUES
('qu100000000000000000000000000001', 'q1000000000000000000000000000001', 'QC-MAT-DEMO-001', 'PCR 扩增引物 Mix', 'in', 50.0000, 70.0000, NULL, NULL, 'manual_in', @tenant_no, '期初入库', @operator_id, '', DATE_SUB(@now, INTERVAL 7 DAY), @operator_id, DATE_SUB(@now, INTERVAL 7 DAY), 0),
('qu100000000000000000000000000002', 'q1000000000000000000000000000001', 'QC-MAT-DEMO-001', 'PCR 扩增引物 Mix', 'in', 50.0000, 120.0000, NULL, NULL, 'manual_in', @tenant_no, '补货入库', @operator_id, '', DATE_SUB(@now, INTERVAL 2 DAY), @operator_id, DATE_SUB(@now, INTERVAL 2 DAY), 0),
('qu100000000000000000000000000003', 'q1000000000000000000000000000002', 'QC-MAT-DEMO-002', '核酸提取试剂盒', 'use', -5.0000, 35.0000, NULL, 'QC-DEMO-TASK-001', 'task_complete', @tenant_no, '演示任务消耗', @operator_id, '', DATE_SUB(@now, INTERVAL 1 DAY), @operator_id, DATE_SUB(@now, INTERVAL 1 DAY), 0);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
-- 插入结果速览
SELECT
material_code AS `物料编码`,
material_name AS `物料名称`,
stock_qty AS `当前库存`,
warning_qty AS `预警库存`,
CASE WHEN status = '1' THEN '正常' ELSE '停用' END AS `状态`,
CASE WHEN stock_qty <= warning_qty THEN '库存预警' ELSE '正常' END AS `库存状态`
FROM `biz_qc_material`
WHERE `tenant_no` = @tenant_no
AND `material_code` LIKE 'QC-MAT-DEMO-%'
AND `del_flag` = 0
ORDER BY `order_num`;
@@ -1,33 +0,0 @@
-- 质检物料变动记录:出库领用人/用途独立字段,来源类型补充 manual_out
-- 用法:mysql -u root -p zkxw < docs/sql/qc_material_usage_out_fields_alter.sql
SET NAMES utf8mb4;
ALTER TABLE `biz_qc_material_usage`
ADD COLUMN `receiver` varchar(64) DEFAULT NULL COMMENT '领用人(手动出库)' AFTER `qc_task_no`,
ADD COLUMN `purpose` varchar(512) DEFAULT NULL COMMENT '用途/事由(手动出库)' AFTER `receiver`;
ALTER TABLE `biz_qc_material_usage`
MODIFY COLUMN `source_type` varchar(16) NOT NULL COMMENT '来源:task_complete任务完成 / manual_in手动入库 / manual_out手动出库';
-- 历史数据:从备注中回填领用人、用途(格式:领用人:xxx;用途:yyy)
UPDATE `biz_qc_material_usage`
SET
`receiver` = TRIM(
SUBSTRING_INDEX(
SUBSTRING_INDEX(`remark`, '领用人:', -1),
';',
1
)
),
`purpose` = TRIM(
SUBSTRING_INDEX(
SUBSTRING_INDEX(`remark`, '用途:', -1),
';',
1
)
)
WHERE `source_type` = 'manual_out'
AND `del_flag` = 0
AND (`receiver` IS NULL OR `receiver` = '')
AND `remark` LIKE '%领用人:%';
@@ -1,25 +0,0 @@
-- 回填手动出库记录的领用人、用途(从 remark 解析,可重复执行)
SET NAMES utf8mb4;
UPDATE `biz_qc_material_usage`
SET
`receiver` = TRIM(
SUBSTRING_INDEX(
SUBSTRING_INDEX(`remark`, '领用人:', -1),
';',
1
)
),
`purpose` = TRIM(
SUBSTRING_INDEX(
SUBSTRING_INDEX(`remark`, '用途:', -1),
';',
1
)
)
WHERE `source_type` = 'manual_out'
AND `del_flag` = 0
AND `remark` LIKE '%领用人:%'
AND (
`receiver` IS NULL OR `receiver` = '' OR `purpose` IS NULL OR `purpose` = ''
);
@@ -1,18 +0,0 @@
-- 细胞存储管理:菜单更名
-- 物料库 → 市场物料库(id=50000000000000000000000000000009)
-- 物料变动记录 → 市场物料变动记录(id=50000000000000000000000000000010)
-- 用法:mysql -u root -p zkxw < docs/sql/sys_menu_cell_storage_material_rename.sql
SET NAMES utf8mb4;
UPDATE `sys_menu`
SET `menu_name` = '市场物料库',
`update_time` = NOW()
WHERE `id` = '50000000000000000000000000000009'
AND `del_flag` = 0;
UPDATE `sys_menu`
SET `menu_name` = '市场物料变动记录',
`update_time` = NOW()
WHERE `id` = '50000000000000000000000000000010'
AND `del_flag` = 0;
@@ -1,10 +0,0 @@
-- 质量检测:菜单「物料变动记录」更名为「质检物料变动记录」
-- 用法:mysql -u root -p zkxw < docs/sql/sys_menu_qc_material_usage_rename.sql
SET NAMES utf8mb4;
UPDATE `sys_menu`
SET `menu_name` = '质检物料变动记录',
`update_time` = NOW()
WHERE `id` = '70000000000000000000000000000010'
AND `del_flag` = 0;
+3664 -1161
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -4130,6 +4130,90 @@
"source_file": "api/production.ts",
"source_location": "L303"
},
{
"id": "api_production_fetchreagentstockin",
"label": "fetchReagentStockIn()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L311"
},
{
"id": "api_production_fetchreagentstockout",
"label": "fetchReagentStockOut()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L315"
},
{
"id": "api_production_fetchreagentbatchstockin",
"label": "fetchReagentBatchStockIn()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L322"
},
{
"id": "api_production_fetchreagentbatchstockout",
"label": "fetchReagentBatchStockOut()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L329"
},
{
"id": "api_production_fetchreagentstocklogs",
"label": "fetchReagentStockLogs()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L338"
},
{
"id": "api_production_fetchallreagentstocklogs",
"label": "fetchAllReagentStockLogs()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L350"
},
{
"id": "api_production_fetchconsumablestockin",
"label": "fetchConsumableStockIn()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L370"
},
{
"id": "api_production_fetchconsumablestockout",
"label": "fetchConsumableStockOut()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L374"
},
{
"id": "api_production_fetchconsumablebatchstockin",
"label": "fetchConsumableBatchStockIn()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L381"
},
{
"id": "api_production_fetchconsumablebatchstockout",
"label": "fetchConsumableBatchStockOut()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L388"
},
{
"id": "api_production_fetchconsumablestocklogs",
"label": "fetchConsumableStockLogs()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L397"
},
{
"id": "api_production_fetchallconsumablestocklogs",
"label": "fetchAllConsumableStockLogs()",
"file_type": "code",
"source_file": "api/production.ts",
"source_location": "L409"
},
{
"id": "api_qc_third_party_item_ts",
"label": "qc-third-party-item.ts",
@@ -17987,6 +18071,114 @@
"source_location": "L303",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchreagentstockin",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L311",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchreagentstockout",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L315",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchreagentbatchstockin",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L322",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchreagentbatchstockout",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L329",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchreagentstocklogs",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L338",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchallreagentstocklogs",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L350",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchconsumablestockin",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L370",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchconsumablestockout",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L374",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchconsumablebatchstockin",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L381",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchconsumablebatchstockout",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L388",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchconsumablestocklogs",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L397",
"weight": 1.0
},
{
"source": "api_production_ts",
"target": "api_production_fetchallconsumablestocklogs",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/production.ts",
"source_location": "L409",
"weight": 1.0
},
{
"source": "api_qc_third_party_item_ts",
"target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_http",
@@ -29017,6 +29209,46 @@
"source_location": "L250",
"weight": 1.0
},
{
"source": "api_production_fetchreagentstocklogs",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/production.ts",
"source_location": "L342",
"weight": 1.0
},
{
"source": "api_production_fetchallreagentstocklogs",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/production.ts",
"source_location": "L358",
"weight": 1.0
},
{
"source": "api_production_fetchconsumablestocklogs",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/production.ts",
"source_location": "L401",
"weight": 1.0
},
{
"source": "api_production_fetchallconsumablestocklogs",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/production.ts",
"source_location": "L417",
"weight": 1.0
},
{
"source": "api_qc_third_party_item_fetchqcthirdpartyitemlist",
"target": "process_route_index_get",
+74 -79
View File
@@ -1,11 +1,11 @@
# Graph Report - src (2026-05-23)
## Corpus Check
- Large corpus: 588 files · ~312,880 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
- Large corpus: 588 files · ~319,039 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
## Summary
- 1461 nodes · 1826 edges · 42 communities detected
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 406 edges (avg confidence: 0.8)
- 1473 nodes · 1842 edges · 41 communities detected
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 410 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
@@ -32,7 +32,7 @@
- [[_COMMUNITY_Community 20|Community 20]]
- [[_COMMUNITY_Community 21|Community 21]]
- [[_COMMUNITY_Community 22|Community 22]]
- [[_COMMUNITY_Community 24|Community 24]]
- [[_COMMUNITY_Community 23|Community 23]]
- [[_COMMUNITY_Community 25|Community 25]]
- [[_COMMUNITY_Community 26|Community 26]]
- [[_COMMUNITY_Community 27|Community 27]]
@@ -45,15 +45,14 @@
- [[_COMMUNITY_Community 35|Community 35]]
- [[_COMMUNITY_Community 36|Community 36]]
- [[_COMMUNITY_Community 37|Community 37]]
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 40|Community 40]]
- [[_COMMUNITY_Community 41|Community 41]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 44|Community 44]]
## God Nodes (most connected - your core abstractions)
1. `get()` - 157 edges
1. `get()` - 161 edges
2. `WebSocketClient` - 26 edges
3. `push()` - 19 edges
4. `withFullscreenLoading()` - 17 edges
@@ -67,116 +66,116 @@
## Surprising Connections (you probably didn't know these)
- `handleBatchDelete()` --calls--> `withFullscreenLoading()` [INFERRED]
views/system/site/index.vue → utils/fullscreen-loading.ts
- `handleBatchDeleteHospital()` --calls--> `withFullscreenLoading()` [INFERRED]
views/basic-info/collection-region/index.vue → utils/fullscreen-loading.ts
- `handleBatchDelete()` --calls--> `withFullscreenLoading()` [INFERRED]
views/basic-info/customer/index.vue → utils/fullscreen-loading.ts
- `handleUnauthorizedResponse()` --calls--> `fetchRefreshToken()` [INFERRED]
utils/http/index.ts → api/auth.ts
- `fetchLeaveList()` --calls--> `get()` [INFERRED]
api/leave.ts → views/production/process-route/index.vue
- `fetchLeaveDetail()` --calls--> `get()` [INFERRED]
api/leave.ts → views/production/process-route/index.vue
- `fetchSampleReceptionCheckItemList()` --calls--> `get()` [INFERRED]
api/sample-reception-check-item.ts → views/production/process-route/index.vue
- `fetchSampleReceptionCheckItemsActive()` --calls--> `get()` [INFERRED]
api/sample-reception-check-item.ts → views/production/process-route/index.vue
## Communities
### Community 0 - "Community 0"
Cohesion: 0.01
Nodes (78): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+70 more)
Nodes (80): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+72 more)
### Community 1 - "Community 1"
Cohesion: 0.03
Nodes (56): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+48 more)
Nodes (60): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+52 more)
### Community 2 - "Community 2"
Cohesion: 0.04
Nodes (20): clickTab(), handleTouchEnd(), setTransition(), ComponentLoader, IframeRouteManager, RoutePermissionValidator, RouteTransformer, useCommon() (+12 more)
Nodes (31): fetchGetUserInfo(), clickTab(), handleTouchEnd(), setTransition(), IframeRouteManager, RouteRegistry, useCommon(), setupAfterEachGuard() (+23 more)
### Community 3 - "Community 3"
Cohesion: 0.04
Nodes (25): fetchGetMenuList(), fetchGetMenuCodes(), fetchGetUserInfo(), fetchLogin(), fetchRefreshToken(), MenuProcessor, RouteRegistry, useAppMode() (+17 more)
Cohesion: 0.03
Nodes (22): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllConsumableStockLogs(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllReagentStockLogs() (+14 more)
### Community 4 - "Community 4"
Cohesion: 0.05
Nodes (33): fetchDeptTree(), fetchPostBoundUserIds(), FireworkSystem, reload(), formatUserLabel(), loadDeptData(), onPersonSelectChange(), subscribeTokenRefresh() (+25 more)
Cohesion: 0.04
Nodes (33): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+25 more)
### Community 5 - "Community 5"
Cohesion: 0.04
Nodes (18): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllSopDocuments(), fetchConsumableList() (+10 more)
Cohesion: 0.05
Nodes (33): fetchDeptTree(), fetchPostBoundUserIds(), FireworkSystem, reload(), formatUserLabel(), loadDeptData(), onPersonSelectChange(), subscribeTokenRefresh() (+25 more)
### Community 6 - "Community 6"
Cohesion: 0.05
Nodes (40): fetchAccessLogList(), fetchCleanRoomList(), fetchCreateAccessLog(), fetchCreateCleanRoom(), fetchCreateSite(), fetchDeleteAccessLog(), fetchDeleteCleanRoom(), fetchDeleteSite() (+32 more)
### Community 7 - "Community 7"
Cohesion: 0.07
Nodes (35): disableDevTools(), handleLock(), handleUnlock(), isMobile(), toLogin(), base64ToBytes(), bytesToBase64(), decryptJson() (+27 more)
Cohesion: 0.05
Nodes (18): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+10 more)
### Community 8 - "Community 8"
Cohesion: 0.09
Nodes (5): handleReset(), handleSearch(), WebSocketClient, TableCache, emit()
Nodes (31): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+23 more)
### Community 9 - "Community 9"
Cohesion: 0.05
Nodes (18): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+10 more)
Cohesion: 0.06
Nodes (10): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), RoutePermissionValidator, useCeremony(), useTheme(), TableCache, themeAnimation() (+2 more)
### Community 10 - "Community 10"
Cohesion: 0.09
Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
### Community 11 - "Community 11"
Cohesion: 0.07
Nodes (15): fetchDeleteProductionTask(), fetchProductionTaskDetail(), fetchProductionTaskList(), fetchUpdateProductionTask(), fetchCompleteProductionWorkOrder(), fetchProductionWorkOrderDetail(), fetchProductionWorkOrderList(), handleClose() (+7 more)
Cohesion: 0.13
Nodes (4): handleReset(), handleSearch(), WebSocketClient, emit()
### Community 12 - "Community 12"
Cohesion: 0.08
Nodes (17): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), collectIds(), postorder(), preorder(), applyTreeExpand() (+9 more)
### Community 13 - "Community 13"
Cohesion: 0.09
Nodes (9): fetchGetAllUpgradeLogs(), fetchGetChinaMapData(), fetchGetComments(), fetchGetCurrentVersion(), fetchGetLatestUpgradeLog(), fetchGetSystemConfig(), fetchGetUpgradeLogs(), systemUpgrade() (+1 more)
### Community 13 - "Community 13"
Cohesion: 0.1
Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
### Community 14 - "Community 14"
Cohesion: 0.1
Nodes (19): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+11 more)
Nodes (8): fetchGetMenuList(), fetchGetMenuCodes(), fetchLogin(), fetchRefreshToken(), MenuProcessor, useAppMode(), useAuth(), buildWebEncryptedLoginBody()
### Community 15 - "Community 15"
Cohesion: 0.1
Nodes (12): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), collectIds(), handleAdd(), handleDelete(), handleReset() (+4 more)
Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
### Community 16 - "Community 16"
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 (9): auditorDisplay(), dash(), expressName(), formatYm(), formatYmd(), sampleTypeName(), siteName(), unitName() (+1 more)
### Community 19 - "Community 19"
### Community 18 - "Community 18"
Cohesion: 0.14
Nodes (17): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd(), handleDelete() (+9 more)
### Community 20 - "Community 20"
### Community 19 - "Community 19"
Cohesion: 0.12
Nodes (12): fetchApproveTask(), fetchBusinessAllTasks(), fetchCompletedTasks(), fetchDesignerData(), fetchInstanceDetail(), fetchMyInstances(), fetchPendingTasks(), fetchProcessDefList() (+4 more)
### Community 21 - "Community 21"
### Community 20 - "Community 20"
Cohesion: 0.16
Nodes (10): useTable(), useTableImpl(), getColumnChecks(), useTableColumns(), createErrorHandler(), createSmartDebounce(), defaultResponseAdapter(), extractPagination() (+2 more)
### Community 21 - "Community 21"
Cohesion: 0.2
Nodes (2): ComponentLoader, RouteTransformer
### Community 22 - "Community 22"
Cohesion: 0.27
Nodes (14): useChart(), useChartComponent(), useChartOps(), colourBlend(), getCssVar(), getDarkColor(), getLightColor(), handleElementThemeColor() (+6 more)
### Community 24 - "Community 24"
### Community 23 - "Community 23"
Cohesion: 0.17
Nodes (3): fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList()
Nodes (12): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), handleAdd(), handleBatchDelete(), handleDelete(), handleReset() (+4 more)
### Community 25 - "Community 25"
Cohesion: 0.18
Nodes (5): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), useCeremony(), useTheme()
Cohesion: 0.17
Nodes (3): fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList()
### Community 26 - "Community 26"
Cohesion: 0.18
@@ -199,92 +198,88 @@ Cohesion: 0.33
Nodes (2): logApiCryptoBootInfo(), maskSecret()
### Community 32 - "Community 32"
Cohesion: 0.29
Nodes (2): fetchLeaveDetail(), fetchLeaveList()
### Community 33 - "Community 33"
Cohesion: 0.47
Nodes (3): isPaymentDueWithinWarnWindow(), parsePaymentDueYmd(), startOfLocalDay()
### Community 34 - "Community 34"
### Community 33 - "Community 33"
Cohesion: 0.33
Nodes (2): fetchSampleReceptionCheckItemList(), fetchSampleReceptionCheckItemsActive()
### Community 35 - "Community 35"
### Community 34 - "Community 34"
Cohesion: 0.33
Nodes (2): fetchQcThirdPartyItemList(), fetchQcThirdPartyItemsActive()
### Community 36 - "Community 36"
### Community 35 - "Community 35"
Cohesion: 0.33
Nodes (2): fetchQcThirdPartyCompanyList(), fetchQcThirdPartyCompanyOptions()
### Community 37 - "Community 37"
### Community 36 - "Community 36"
Cohesion: 0.33
Nodes (2): fetchQcLabTestItemList(), fetchQcLabTestItemsActive()
### Community 38 - "Community 38"
### Community 37 - "Community 37"
Cohesion: 0.33
Nodes (2): fetchQcTaskDetail(), fetchQcTaskList()
### Community 40 - "Community 40"
### Community 39 - "Community 39"
Cohesion: 0.53
Nodes (4): isEtaTodayOrEarlier(), parseEtaLocalDate(), sampleReceptionRowClassName(), startOfLocalDay()
### Community 41 - "Community 41"
### Community 40 - "Community 40"
Cohesion: 0.5
Nodes (2): focusInput(), handleKeydown()
### Community 42 - "Community 42"
### Community 41 - "Community 41"
Cohesion: 0.67
Nodes (2): if(), logSidebarMenu()
### Community 43 - "Community 43"
### Community 42 - "Community 42"
Cohesion: 1.0
Nodes (2): getSettingDefaults(), resetToDefaults()
### Community 45 - "Community 45"
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (2): defaultAvatarPathByRole(), resolveUserAvatarUrl()
## Knowledge Gaps
- **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 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 30`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 31`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 32`** (7 nodes): `fetchCreateLeave()`, `fetchDeleteLeave()`, `fetchLeaveDetail()`, `fetchLeaveList()`, `fetchSubmitLeave()`, `fetchUpdateLeave()`, `leave.ts`
- **Thin community `Community 33`** (6 nodes): `fetchCreateSampleReceptionCheckItem()`, `fetchDeleteSampleReceptionCheckItem()`, `fetchSampleReceptionCheckItemList()`, `fetchSampleReceptionCheckItemsActive()`, `fetchUpdateSampleReceptionCheckItem()`, `sample-reception-check-item.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 34`** (6 nodes): `fetchCreateSampleReceptionCheckItem()`, `fetchDeleteSampleReceptionCheckItem()`, `fetchSampleReceptionCheckItemList()`, `fetchSampleReceptionCheckItemsActive()`, `fetchUpdateSampleReceptionCheckItem()`, `sample-reception-check-item.ts`
- **Thin community `Community 34`** (6 nodes): `fetchCreateQcThirdPartyItem()`, `fetchDeleteQcThirdPartyItem()`, `fetchQcThirdPartyItemList()`, `fetchQcThirdPartyItemsActive()`, `fetchUpdateQcThirdPartyItem()`, `qc-third-party-item.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 35`** (6 nodes): `fetchCreateQcThirdPartyItem()`, `fetchDeleteQcThirdPartyItem()`, `fetchQcThirdPartyItemList()`, `fetchQcThirdPartyItemsActive()`, `fetchUpdateQcThirdPartyItem()`, `qc-third-party-item.ts`
- **Thin community `Community 35`** (6 nodes): `fetchCreateQcThirdPartyCompany()`, `fetchDeleteQcThirdPartyCompany()`, `fetchQcThirdPartyCompanyList()`, `fetchQcThirdPartyCompanyOptions()`, `fetchUpdateQcThirdPartyCompany()`, `qc-third-party-company.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 36`** (6 nodes): `fetchCreateQcThirdPartyCompany()`, `fetchDeleteQcThirdPartyCompany()`, `fetchQcThirdPartyCompanyList()`, `fetchQcThirdPartyCompanyOptions()`, `fetchUpdateQcThirdPartyCompany()`, `qc-third-party-company.ts`
- **Thin community `Community 36`** (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 37`** (6 nodes): `fetchCreateQcLabTestItem()`, `fetchDeleteQcLabTestItem()`, `fetchQcLabTestItemList()`, `fetchQcLabTestItemsActive()`, `fetchUpdateQcLabTestItem()`, `qc-lab-test-item.ts`
- **Thin community `Community 37`** (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 38`** (6 nodes): `fetchCompleteQcTask()`, `fetchQcTaskDetail()`, `fetchQcTaskList()`, `fetchStartQcTask()`, `fetchUpdateQcTaskAttachments()`, `qc-task.ts`
- **Thin community `Community 40`** (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 41`** (5 nodes): `focusInput()`, `handleKeydown()`, `if()`, `search()`, `index.vue`
- **Thin community `Community 41`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 42`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
- **Thin community `Community 42`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 43`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 45`** (3 nodes): `defaultAvatarPathByRole()`, `resolveUserAvatarUrl()`, `user-avatar.ts`
- **Thin community `Community 44`** (3 nodes): `defaultAvatarPathByRole()`, `resolveUserAvatarUrl()`, `user-avatar.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 9`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 17`, `Community 18`, `Community 19`, `Community 20`, `Community 24`, `Community 26`, `Community 27`, `Community 32`, `Community 34`, `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 4` to `Community 0`, `Community 2`, `Community 8`, `Community 9`, `Community 12`, `Community 13`?**
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 17`, `Community 18`, `Community 19`, `Community 23`, `Community 25`, `Community 26`, `Community 27`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`?**
_High betweenness centrality (0.279) - this node is a cross-community bridge._
- **Why does `push()` connect `Community 5` to `Community 0`, `Community 7`, `Community 9`, `Community 11`, `Community 13`, `Community 15`?**
_High betweenness centrality (0.085) - this node is a cross-community bridge._
- **Why does `fetchGetLatestUpgradeLog()` connect `Community 12` to `Community 0`?**
_High betweenness centrality (0.043) - this node is a cross-community bridge._
- **Are the 156 inferred relationships involving `get()` (e.g. with `buildTreePathLabelFromFlat()` and `alignFqPaymentDetailsForDisplay()`) actually correct?**
_`get()` has 156 INFERRED edges - model-reasoned connections that need verification._
- **Why does `buildTreePathLabelFromFlat()` connect `Community 5` to `Community 0`, `Community 9`?**
_High betweenness centrality (0.045) - this node is a cross-community bridge._
- **Are the 160 inferred relationships involving `get()` (e.g. with `buildTreePathLabelFromFlat()` and `alignFqPaymentDetailsForDisplay()`) actually correct?**
_`get()` has 160 INFERRED edges - model-reasoned connections that need verification._
- **Are the 18 inferred relationships involving `push()` (e.g. with `fetchAllPagedRecords()` and `calcInstallmentDueAmounts()`) actually correct?**
_`push()` has 18 INFERRED edges - model-reasoned connections that need verification._
- **Are the 16 inferred relationships involving `withFullscreenLoading()` (e.g. with `.close()` and `handleSubmit()`) actually correct?**
+4 -4
View File
@@ -57,12 +57,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">1461 nodes &middot; 1826 edges &middot; 245 communities</div>
<div id="stats">1473 nodes &middot; 1842 edges &middot; 244 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 31, "community_name": "Community 31", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 31, "community_name": "Community 31", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 31, "community_name": "Community 31", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 31, "community_name": "Community 31", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 31, "community_name": "Community 31", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 31, "community_name": "Community 31", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 79, "community_name": "Community 79", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 80, "community_name": "Community 80", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 16, "community_name": "Community 16", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 16, "community_name": "Community 16", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 16, "community_name": "Community 16", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 16, "community_name": "Community 16", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 16, "community_name": "Community 16", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_setuprolesdirective", "laLine truncated
const RAW_EDGES = [{"from": "app_vue", "to": "src_app_refreshbuttonautoicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "src_app_refreshpaneltitleicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "main_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "utils_sys_console_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_masksecret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_logapicryptobootinfo", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "src_main_masksecret", "to": "src_main_logapicryptobootinfo", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_ts", "to": "directives_index_setupglobdirectives", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_setupglobdirectives", "to": "core_auth_setupauthdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "core_roles_setuprolesdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_highlight_setuphighlightdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_ripple_setuprippledirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_core_roles_ts", "to": "core_roles_checkrolepermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_setuprolesdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_roles_checkrolepermission", "to": "core_roles_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_checkauthpermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_setupauthdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_checkauthpermission", "to": "core_auth_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_ripple_ts", "to": "business_ripple_setuprippledirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_highlightcode", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_insertlinenumbers", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_addcopybutton", "label": "contains", "title": "contains [EXTRACTED]", "dLine truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 226}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 94}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 65}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 62}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 53}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 53}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 51}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 48}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 48}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 44}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 36}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 35}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 31}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 27}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 27}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 25}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 22}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 21}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 20}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 20}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 19}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 17}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 16}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 13}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 12}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 11}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 11}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 10}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 9}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 8}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 8}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 7}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 7}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 6}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 6}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 6}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 6}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 6}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 6}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 6}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 6}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 5}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 4}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 3}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 3}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 3}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 3}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 3}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 3}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 3}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 3}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 3}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 3}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 2}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 2}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 2}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 2}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 2}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 2}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 2}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 2}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 2}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 2}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 2}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 2}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 2}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 2}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 2}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 2}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 2}, {"cid": 70, "color": "#4E79A7", "label": "Community 70", "count": 2}, {"ciLine truncated
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 31, "community_name": "Community 31", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 31, "community_name": "Community 31", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 31, "community_name": "Community 31", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 31, "community_name": "Community 31", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 31, "community_name": "Community 31", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 31, "community_name": "Community 31", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 78, "community_name": "Community 78", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 79, "community_name": "Community 79", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 16, "community_name": "Community 16", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 16, "community_name": "Community 16", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 16, "community_name": "Community 16", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 16, "community_name": "Community 16", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 16, "community_name": "Community 16", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_setuprolesdirective", "laLine truncated
const RAW_EDGES = [{"from": "app_vue", "to": "src_app_refreshbuttonautoicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "src_app_refreshpaneltitleicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "main_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "utils_sys_console_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_masksecret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_logapicryptobootinfo", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "src_main_masksecret", "to": "src_main_logapicryptobootinfo", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_ts", "to": "directives_index_setupglobdirectives", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_setupglobdirectives", "to": "core_auth_setupauthdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "core_roles_setuprolesdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_highlight_setuphighlightdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_ripple_setuprippledirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_core_roles_ts", "to": "core_roles_checkrolepermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_setuprolesdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_roles_checkrolepermission", "to": "core_roles_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_checkauthpermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_setupauthdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_checkauthpermission", "to": "core_auth_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_ripple_ts", "to": "business_ripple_setuprippledirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_highlightcode", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_insertlinenumbers", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_addcopybutton", "label": "contains", "title": "contains [EXTRACTED]", "dLine truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 233}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 101}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 69}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 65}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 61}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 53}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 51}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 44}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 39}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 39}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 36}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 34}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 33}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 31}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 27}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 27}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 22}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 20}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 20}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 19}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 17}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 17}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 16}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 16}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 13}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 12}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 11}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 10}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 9}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 8}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 8}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 7}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 6}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 6}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 6}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 6}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 6}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 6}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 6}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 6}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 5}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 4}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 3}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 3}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 3}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 3}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 3}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 3}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 3}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 3}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 3}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 3}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 2}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 2}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 2}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 2}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 2}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 2}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 2}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 2}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 2}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 2}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 2}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 2}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 2}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 2}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 2}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 2}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 2}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 2}, {"cid": 70, "color": "#4E79A7", "label": "Community 70", "count": 2}, {"cLine truncated
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
+5 -5
View File
@@ -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": 1779506249.5668056,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779502098.7595692,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1779511864.5113068,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779511519.245795,
"/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,
@@ -192,7 +192,7 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/hooks/core/useAppMode.ts": 1778582067.999649,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/leave.ts": 1778666177.2933538,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/sample-reception-check-item.ts": 1779007909.2933023,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts": 1779171206.8677726,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts": 1779510739.079313,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-third-party-item.ts": 1779017836.101254,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts": 1779492302.440177,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/workflow.ts": 1778729873.096252,
@@ -273,7 +273,7 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/process-route/index.vue": 1779435878.9581294,
"/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": 1779414898.4036016,
"/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/reagent/index.vue": 1779511836.8888884,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue": 1779504046.6918495,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts": 1779506613.3205173,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/StepDetailPanel.vue": 1779507602.4356499,
@@ -284,7 +284,7 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/DispatchTaskDialog.vue": 1779432481.6736288,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskOutputProductDialog.vue": 1779505558.2585275,
"/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,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/consumable/index.vue": 1779511015.0429022,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/process/index.vue": 1779436610.457994,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/process-category/index.vue": 1779307716.2724373,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/index/index.vue": 1778582068.070888,
@@ -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": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_consumable_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/consumable/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_api_production_ts", "label": "production.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L1"}, {"id": "api_production_fetchconsumablelist", "label": "fetchConsumableList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L7"}, {"id": "api_production_fetchallconsumables", "label": "fetchAllConsumables()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L17"}, {"id": "api_production_fetchcreateconsumable", "label": "fetchCreateConsumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L21"}, {"id": "api_production_fetchupdateconsumable", "label": "fetchUpdateConsumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L25"}, {"id": "api_production_fetchdeleteconsumable", "label": "fetchDeleteConsumable()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L29"}, {"id": "api_production_fetchreagentlist", "label": "fetchReagentList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L37"}, {"id": "api_production_fetchallreagents", "label": "fetchAllReagents()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L47"}, {"id": "api_production_fetchcreatereagent", "label": "fetchCreateReagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L51"}, {"id": "api_production_fetchupdatereagent", "label": "fetchUpdateReagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L55"}, {"id": "api_production_fetchdeletereagent", "label": "fetchDeleteReagent()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L59"}, {"id": "api_production_fetchsoplist", "label": "fetchSopList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L67"}, {"id": "api_production_fetchallsopdocuments", "label": "fetchAllSopDocuments()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L77"}, {"id": "api_production_fetchcreatesop", "label": "fetchCreateSop()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L81"}, {"id": "api_production_fetchupdatesop", "label": "fetchUpdateSop()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L85"}, {"id": "api_production_fetchdeletesop", "label": "fetchDeleteSop()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L89"}, {"id": "api_production_fetchprocesscategorylist", "label": "fetchProcessCategoryList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L97"}, {"id": "api_production_fetchallprocesscategories", "label": "fetchAllProcessCategories()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L111"}, {"id": "api_production_fetchcreateprocesscategory", "label": "fetchCreateProcessCategory()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L115"}, {"id": "api_production_fetchupdateprocesscategory", "label": "fetchUpdateProcessCategory()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L119"}, {"id": "api_production_fetchdeleteprocesscategory", "label": "fetchDeleteProcessCategory()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L123"}, {"id": "api_production_fetchoutputtypelist", "label": "fetchOutputTypeList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L131"}, {"id": "api_production_fetchalloutputtypes", "label": "fetchAllOutputTypes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production.ts", "source_location": "L141"}, {"id": "api_production_fetchcreateoutputtype", "label": "fetchCreateOutputType()", "file_type": "code", "source_file"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_reagent_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/reagent/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -145,7 +145,7 @@
<el-form-item label="变动类型">
<el-select v-model="logSearchForm.changeType" placeholder="全部" clearable>
<el-option label="入库" value="in" />
<el-option label="出库" value="use" />
<el-option label="出库" value="out" />
</el-select>
</el-form-item>
<el-form-item label="时间范围">
@@ -212,6 +212,12 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column label="领用人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ row.receiver || '-' }}</template>
</el-table-column>
@@ -785,6 +791,12 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column label="领用人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ row.receiver || '-' }}</template>
</el-table-column>
@@ -1020,7 +1032,7 @@
function getSourceLabel(sourceType: string) {
if (sourceType === 'manual_in') return '手动入库'
if (sourceType === 'manual_out') return '手动出库'
if (sourceType === 'step_save') return '步骤扣减'
if (sourceType === 'step_save') return '生产扣减'
return sourceType || '-'
}
@@ -219,8 +219,8 @@
</el-form-item>
<el-form-item label="变动类型">
<el-select v-model="allLogFilter.changeType" placeholder="全部" clearable>
<el-option label="入库" value="in" />
<el-option label="出库" value="use" />
<el-option label="入库" value="in" />
<el-option label="出库" value="out" />
</el-select>
</el-form-item>
<el-form-item label="时间范围">
@@ -319,6 +319,12 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column
prop="receiver"
label="领用人"
@@ -928,7 +934,7 @@
<el-form-item label="变动类型">
<el-select v-model="stockLogFilter.changeType" placeholder="全部" clearable @change="loadStockLogs">
<el-option label="入库" value="in" />
<el-option label="出库" value="use" />
<el-option label="出库" value="out" />
</el-select>
</el-form-item>
</el-form>
@@ -985,6 +991,12 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="工单号" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.taskNo || '-' }}</template>
</el-table-column>
<el-table-column label="步骤名称" min-width="140" align="center" header-align="center">
<template #default="{ row }">{{ row.stepName || '-' }}</template>
</el-table-column>
<el-table-column
prop="receiver"
label="领用人"
@@ -1099,7 +1111,7 @@
const map: Record<string, string> = {
manual_in: '手动入库',
manual_out: '手动出库',
step_save: '步骤扣减'
step_save: '生产扣减'
}
return map[sourceType] || sourceType || '-'
}