提交
This commit is contained in:
1 parent
05684ba2a4
commit
7fbf71b6e1
150 files changed
+19268
-12045
No files matched your search
@@ -213,5 +213,6 @@ pnpm clean:dev # strip demo data for fresh start
|
||||
- **No backdrop blur on modals**: `backdrop-filter: none`.
|
||||
- **Dialog forms**: `label-position="top"`.
|
||||
- **Table action column**: `fixed="right"`, min-width ≥ 260px.
|
||||
- **Table column widths**: All `el-table-column` SHALL use `min-width` (not `width`) for proportional scaling when viewport resizes.
|
||||
- **Toolbar**: "已选 N 项" first, then primary action button (only one `type="primary"` per toolbar row), no `space-between` push.
|
||||
- **Database changes**: always pair with schema SQL in `docs/sql/` and evaluate API/TypeScript type impact.
|
||||
+1
-1
@@ -1 +1 @@
|
||||
65187
|
||||
43673
|
||||
@@ -16,6 +16,8 @@ from app.api.pilot_service import router as pilot_service_router
|
||||
from app.api.insurance_company import router as insurance_company_router
|
||||
from app.api.material import router as material_router
|
||||
from app.api.storage_release_review import router as storage_release_review_router
|
||||
from app.api.sample_sms_notification import router as sample_sms_notification_router
|
||||
from app.api.storage_entry_sms_notification import router as storage_entry_sms_notification_router
|
||||
|
||||
__all__ = [
|
||||
"public_router",
|
||||
@@ -35,4 +37,6 @@ __all__ = [
|
||||
"insurance_company_router",
|
||||
"material_router",
|
||||
"storage_release_review_router",
|
||||
"sample_sms_notification_router",
|
||||
"storage_entry_sms_notification_router",
|
||||
]
|
||||
+23
-23
@@ -115,9 +115,9 @@ async def list_materials(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/materials/options")
|
||||
@@ -129,7 +129,7 @@ async def material_options(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(mat_svc.options_list(db, tenant_no=tenant_no))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/materials")
|
||||
@@ -147,9 +147,9 @@ async def create_material(
|
||||
)
|
||||
return success_response(obj, message="创建成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/materials/{material_id}")
|
||||
@@ -168,9 +168,9 @@ async def update_material(
|
||||
)
|
||||
return success_response(obj, message="更新成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.delete("/materials/{material_id}")
|
||||
@@ -185,9 +185,9 @@ async def delete_material(
|
||||
mat_svc.soft_delete_material(db, material_id, tenant_no=tenant_no, user_id=user_id)
|
||||
return success_response(None, message="删除成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/materials/batch-stock-in")
|
||||
@@ -203,7 +203,7 @@ async def batch_stock_in_material(
|
||||
if body.stock_in_time:
|
||||
rt = parse_datetime(body.stock_in_time)
|
||||
if not rt:
|
||||
return error_response("入库时间格式无效")
|
||||
return error_response(400, "入库时间格式无效")
|
||||
operate_time = rt
|
||||
items = [
|
||||
{"material_id": x.material_id, "qty": x.qty, "remark": x.remark}
|
||||
@@ -219,9 +219,9 @@ async def batch_stock_in_material(
|
||||
)
|
||||
return success_response({"count": count}, message=f"批量入库成功,共 {count} 项")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/materials/batch-stock-out")
|
||||
@@ -237,7 +237,7 @@ async def batch_stock_out_material(
|
||||
if body.stock_out_time:
|
||||
rt = parse_datetime(body.stock_out_time)
|
||||
if not rt:
|
||||
return error_response("出库时间格式无效")
|
||||
return error_response(400, "出库时间格式无效")
|
||||
operate_time = rt
|
||||
items = [
|
||||
{"material_id": x.material_id, "qty": x.qty, "remark": x.remark}
|
||||
@@ -255,9 +255,9 @@ async def batch_stock_out_material(
|
||||
)
|
||||
return success_response({"count": count}, message=f"批量出库成功,共 {count} 项")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/materials/{material_id}/stock-in")
|
||||
@@ -274,7 +274,7 @@ async def stock_in_material(
|
||||
if body.stock_in_time:
|
||||
rt = parse_datetime(body.stock_in_time)
|
||||
if not rt:
|
||||
return error_response("入库时间格式无效")
|
||||
return error_response(400, "入库时间格式无效")
|
||||
operate_time = rt
|
||||
obj = mat_svc.stock_in(
|
||||
db, material_id, qty=body.qty, remark=body.remark,
|
||||
@@ -282,9 +282,9 @@ async def stock_in_material(
|
||||
)
|
||||
return success_response(obj, message="入库成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/materials/{material_id}/stock-out")
|
||||
@@ -301,7 +301,7 @@ async def stock_out_material(
|
||||
if body.stock_out_time:
|
||||
rt = parse_datetime(body.stock_out_time)
|
||||
if not rt:
|
||||
return error_response("出库时间格式无效")
|
||||
return error_response(400, "出库时间格式无效")
|
||||
operate_time = rt
|
||||
obj = mat_svc.stock_out(
|
||||
db, material_id, qty=body.qty, receiver=body.receiver,
|
||||
@@ -310,9 +310,9 @@ async def stock_out_material(
|
||||
)
|
||||
return success_response(obj, message="出库成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 库存变动记录 ----------
|
||||
@@ -339,6 +339,6 @@ async def list_stock_logs(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
+99
-99
@@ -81,9 +81,9 @@ async def list_qc_third_party_companies(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-third-party-companies/options")
|
||||
@@ -95,9 +95,9 @@ async def list_qc_third_party_company_options(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(tpc_svc.list_company_options(db, tenant_no))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-third-party-companies")
|
||||
@@ -127,11 +127,11 @@ async def create_qc_third_party_company(
|
||||
)
|
||||
return success_response(tpc_svc._row_to_dict(obj), message="创建成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/qc-third-party-companies/{company_id}")
|
||||
@@ -163,11 +163,11 @@ async def update_qc_third_party_company(
|
||||
)
|
||||
return success_response(tpc_svc._row_to_dict(obj), message="更新成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.delete("/qc-third-party-companies/{company_id}")
|
||||
@@ -181,11 +181,11 @@ async def delete_qc_third_party_company(
|
||||
tpc_svc.soft_delete_company(db, company_id, tenant_no=tenant_no)
|
||||
return success_response(None, message="删除成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 第三方检测项目 ----------
|
||||
@@ -239,9 +239,9 @@ async def list_qc_third_party_items(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-third-party-items/active")
|
||||
@@ -254,9 +254,9 @@ async def list_qc_third_party_items_active(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(tpi_svc.list_active_items(db, tenant_no, company_id=companyId, user_info=user))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-third-party-items")
|
||||
@@ -281,11 +281,11 @@ async def create_qc_third_party_item(
|
||||
)
|
||||
return success_response(tpi_svc._row_to_dict(obj, ""), message="创建成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/qc-third-party-items/{item_id}")
|
||||
@@ -312,11 +312,11 @@ async def update_qc_third_party_item(
|
||||
)
|
||||
return success_response(tpi_svc._row_to_dict(obj, ""), message="更新成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.delete("/qc-third-party-items/{item_id}")
|
||||
@@ -330,11 +330,11 @@ async def delete_qc_third_party_item(
|
||||
tpi_svc.soft_delete_item(db, item_id, tenant_no=tenant_no)
|
||||
return success_response(None, message="删除成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 实验室自检项目 ----------
|
||||
@@ -401,9 +401,9 @@ async def list_qc_lab_test_items(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-lab-test-items/active")
|
||||
@@ -415,9 +415,9 @@ async def list_qc_lab_test_items_active(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(lab_svc.list_active_lab_items(db, tenant_no, user_info=user))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-lab-test-items")
|
||||
@@ -441,11 +441,11 @@ async def create_qc_lab_test_item(
|
||||
)
|
||||
return success_response(lab_svc._row_to_dict(obj), message="创建成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/qc-lab-test-items/{item_id}")
|
||||
@@ -471,11 +471,11 @@ async def update_qc_lab_test_item(
|
||||
)
|
||||
return success_response(lab_svc._row_to_dict(obj), message="更新成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.delete("/qc-lab-test-items/{item_id}")
|
||||
@@ -489,11 +489,11 @@ async def delete_qc_lab_test_item(
|
||||
lab_svc.soft_delete_lab_item(db, item_id, tenant_no=tenant_no)
|
||||
return success_response(None, message="删除成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 检测项目参数模板 ----------
|
||||
@@ -510,9 +510,9 @@ async def list_item_params(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(param_svc.list_params_by_item(db, itemSource, itemId, tenant_no, user_info=user))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/qc-item-params")
|
||||
@@ -530,9 +530,9 @@ async def save_item_params(
|
||||
message="保存成功",
|
||||
)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 质检工单 ----------
|
||||
@@ -569,9 +569,9 @@ async def list_qc_work_orders(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-work-orders/{work_order_id}")
|
||||
@@ -585,11 +585,11 @@ async def get_qc_work_order_detail(
|
||||
data = wo_svc.get_work_order_detail(db, work_order_id, tenant_no)
|
||||
return success_response(data)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-work-orders/{work_order_id}/configure")
|
||||
@@ -613,11 +613,11 @@ async def configure_qc_work_order(
|
||||
)
|
||||
return success_response(wo_svc._wo_to_dict(obj), message="配置成功")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 质检任务 ----------
|
||||
@@ -657,9 +657,9 @@ async def list_qc_tasks(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-tasks/{task_id}")
|
||||
@@ -673,11 +673,11 @@ async def get_qc_task_detail(
|
||||
data = task_svc.get_task_detail(db, task_id, tenant_no)
|
||||
return success_response(data)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-tasks/{task_id}/start")
|
||||
@@ -691,11 +691,11 @@ async def start_qc_task(
|
||||
obj = task_svc.start_task(db, task_id, tenant_no=tenant_no, user_id=_get_current_user_id(user))
|
||||
return success_response(task_svc._task_to_dict(obj), message="已开始")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-tasks/{task_id}/complete")
|
||||
@@ -711,11 +711,11 @@ async def complete_qc_task(
|
||||
)
|
||||
return success_response(task_svc._task_to_dict(obj), message="已完成")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-tasks/{task_id}/results")
|
||||
@@ -728,9 +728,9 @@ async def get_task_results(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(result_svc.list_results_by_task(db, task_id, tenant_no, user_info=user))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-tasks/{task_id}/material-usages")
|
||||
@@ -743,14 +743,14 @@ async def get_task_material_usages(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
t = task_svc.get_task(db, task_id, tenant_no=tenant_no)
|
||||
if not t:
|
||||
return error_response("任务不存在")
|
||||
return error_response(404, "任务不存在")
|
||||
return success_response(
|
||||
mu_svc.list_usages_by_task(db, task_id, tenant_no, user_info=user)
|
||||
)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-tasks/{task_id}/complete-with-result")
|
||||
@@ -765,7 +765,7 @@ async def complete_task_with_result(
|
||||
user_id = _get_current_user_id(user)
|
||||
t = task_svc.get_task(db, task_id, tenant_no=tenant_no)
|
||||
if not t:
|
||||
return error_response("任务不存在")
|
||||
return error_response(404, "任务不存在")
|
||||
was_done = (t.task_status or "").strip() == "ywc"
|
||||
if body.results:
|
||||
result_svc.save_results_for_task(
|
||||
@@ -773,7 +773,7 @@ async def complete_task_with_result(
|
||||
)
|
||||
concl = (body.conclusion or "").strip()
|
||||
if concl not in ("tg", "btg"):
|
||||
return error_response("请选择检测结论(通过/不通过)")
|
||||
return error_response(400, "请选择检测结论(通过/不通过)")
|
||||
if body.third_party_attachments is not None:
|
||||
task_svc.update_task_attachments(
|
||||
db, task_id, attachments=body.third_party_attachments,
|
||||
@@ -801,16 +801,16 @@ async def complete_task_with_result(
|
||||
db.rollback()
|
||||
detail = e.detail
|
||||
msg = detail if isinstance(detail, str) else str(detail)
|
||||
return error_response(msg, code=e.status_code)
|
||||
return error_response(e.status_code, msg)
|
||||
except PermissionError as e:
|
||||
db.rollback()
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
db.rollback()
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/qc-tasks/{task_id}/attachments")
|
||||
@@ -831,11 +831,11 @@ async def update_qc_task_attachments(
|
||||
)
|
||||
return success_response(task_svc._task_to_dict(obj), message="已保存")
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 质检物料库 ----------
|
||||
@@ -926,9 +926,9 @@ async def list_qc_materials(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/qc-materials/options")
|
||||
@@ -940,7 +940,7 @@ async def qc_material_options(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
return success_response(mat_svc.options_list(db, tenant_no=tenant_no))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-materials")
|
||||
@@ -968,9 +968,9 @@ async def create_qc_material(
|
||||
)
|
||||
return success_response(mat_svc._row_to_dict(obj), message="创建成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/qc-materials/{material_id}")
|
||||
@@ -997,9 +997,9 @@ async def update_qc_material(
|
||||
)
|
||||
return success_response(mat_svc._row_to_dict(obj), message="更新成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.delete("/qc-materials/{material_id}")
|
||||
@@ -1014,9 +1014,9 @@ async def delete_qc_material(
|
||||
mat_svc.soft_delete_material(db, material_id, tenant_no=tenant_no)
|
||||
return success_response(None, message="删除成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-materials/batch-stock-in")
|
||||
@@ -1032,7 +1032,7 @@ async def batch_stock_in_qc_material(
|
||||
if body.stock_in_time:
|
||||
rt = parse_datetime(body.stock_in_time)
|
||||
if not rt:
|
||||
return error_response("入库时间格式无效")
|
||||
return error_response(400, "入库时间格式无效")
|
||||
operate_time = rt
|
||||
items = [
|
||||
{"material_id": x.material_id, "qty": x.qty, "remark": x.remark}
|
||||
@@ -1048,9 +1048,9 @@ async def batch_stock_in_qc_material(
|
||||
)
|
||||
return success_response({"count": count}, message=f"批量入库成功,共 {count} 项")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-materials/batch-stock-out")
|
||||
@@ -1066,7 +1066,7 @@ async def batch_stock_out_qc_material(
|
||||
if body.stock_out_time:
|
||||
rt = parse_datetime(body.stock_out_time)
|
||||
if not rt:
|
||||
return error_response("出库时间格式无效")
|
||||
return error_response(400, "出库时间格式无效")
|
||||
operate_time = rt
|
||||
items = [
|
||||
{"material_id": x.material_id, "qty": x.qty, "remark": x.remark}
|
||||
@@ -1084,9 +1084,9 @@ async def batch_stock_out_qc_material(
|
||||
)
|
||||
return success_response({"count": count}, message=f"批量出库成功,共 {count} 项")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-materials/{material_id}/stock-in")
|
||||
@@ -1103,7 +1103,7 @@ async def stock_in_qc_material(
|
||||
if body.stock_in_time:
|
||||
rt = parse_datetime(body.stock_in_time)
|
||||
if not rt:
|
||||
return error_response("入库时间格式无效")
|
||||
return error_response(400, "入库时间格式无效")
|
||||
operate_time = rt
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -1118,9 +1118,9 @@ async def stock_in_qc_material(
|
||||
)
|
||||
return success_response(mat_svc._row_to_dict(obj), message="入库成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/qc-materials/{material_id}/stock-out")
|
||||
@@ -1137,7 +1137,7 @@ async def stock_out_qc_material(
|
||||
if body.stock_out_time:
|
||||
rt = parse_datetime(body.stock_out_time)
|
||||
if not rt:
|
||||
return error_response("出库时间格式无效")
|
||||
return error_response(400, "出库时间格式无效")
|
||||
operate_time = rt
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -1154,9 +1154,9 @@ async def stock_out_qc_material(
|
||||
)
|
||||
return success_response(mat_svc._row_to_dict(obj), message="出库成功")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 物料变动记录 ----------
|
||||
@@ -1183,6 +1183,6 @@ async def list_qc_material_usages(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
@@ -101,9 +101,9 @@ async def list_check_items(
|
||||
result_list = [check_item_svc._row_to_dict(r) for r in items]
|
||||
return success_response(_page_payload(result_list, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/sample-reception-check-items/active")
|
||||
@@ -116,9 +116,9 @@ async def list_active_check_items(
|
||||
items = check_item_svc.list_active_check_items(db, tenant_no)
|
||||
return success_response(items)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/sample-reception-check-items")
|
||||
@@ -145,11 +145,11 @@ async def create_check_item(
|
||||
)
|
||||
return success_response(check_item_svc._row_to_dict(obj))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/sample-reception-check-items/{row_id}")
|
||||
@@ -175,11 +175,11 @@ async def update_check_item(
|
||||
)
|
||||
return success_response(check_item_svc._row_to_dict(obj))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.delete("/sample-reception-check-items/{row_id}")
|
||||
@@ -193,11 +193,11 @@ async def delete_check_item(
|
||||
check_item_svc.soft_delete_check_item(db, row_id, tenant_no=tenant_no)
|
||||
return success_response(None)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
# ---------- 样本接收 ----------
|
||||
@@ -220,9 +220,9 @@ async def list_pending_samples(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/sample-receptions/received")
|
||||
@@ -242,9 +242,9 @@ async def list_received_samples(
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/sample-receptions/{reception_id}")
|
||||
@@ -257,12 +257,12 @@ async def get_sample_reception_detail(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
item = sr_svc.get_reception_by_id(db, reception_id, tenant_no)
|
||||
if not item:
|
||||
return error_response("接收记录不存在", code=404)
|
||||
return error_response(404, "接收记录不存在")
|
||||
return success_response(item)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
class ReceptionCheckSubmit(BaseModel):
|
||||
@@ -318,7 +318,7 @@ async def post_sample_reception(
|
||||
dept_id = (sys_user.dept_id or "") if sys_user else ""
|
||||
rt = parse_datetime(body.reception_time)
|
||||
if not rt:
|
||||
return error_response("样本接收时间格式无效")
|
||||
return error_response(400, "样本接收时间格式无效")
|
||||
checks_payload = [
|
||||
{"checkItemId": c.check_item_id, "checked": c.checked} for c in body.checks
|
||||
]
|
||||
@@ -344,11 +344,11 @@ async def post_sample_reception(
|
||||
detail = sr_svc.get_reception_by_id(db, obj.id, tenant_no)
|
||||
return success_response(detail or {"id": obj.id})
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/sample-receptions/{reception_id}")
|
||||
@@ -363,7 +363,7 @@ async def put_sample_reception(
|
||||
user_id = _get_current_user_id(user)
|
||||
rt = parse_datetime(body.reception_time)
|
||||
if not rt:
|
||||
return error_response("样本接收时间格式无效")
|
||||
return error_response(400, "样本接收时间格式无效")
|
||||
checks_payload = [
|
||||
{"checkItemId": c.check_item_id, "checked": c.checked} for c in body.checks
|
||||
]
|
||||
@@ -386,11 +386,11 @@ async def put_sample_reception(
|
||||
detail = sr_svc.get_reception_by_id(db, obj.id, tenant_no)
|
||||
return success_response(detail or {"id": obj.id})
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/sample-receptions/{reception_id}")
|
||||
@@ -405,7 +405,7 @@ async def put_sample_reception(
|
||||
user_id = _get_current_user_id(user)
|
||||
rt = parse_datetime(body.reception_time)
|
||||
if not rt:
|
||||
return error_response("样本接收时间格式无效")
|
||||
return error_response(400, "样本接收时间格式无效")
|
||||
checks_payload = [
|
||||
{"checkItemId": c.check_item_id, "checked": c.checked} for c in body.checks
|
||||
]
|
||||
@@ -428,8 +428,8 @@ async def put_sample_reception(
|
||||
detail = sr_svc.get_reception_by_id(db, obj.id, tenant_no)
|
||||
return success_response(detail or {"id": obj.id})
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
@@ -0,0 +1,131 @@
|
||||
"""样本接收短信通知 API"""
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.menu_guard import require_menu_code
|
||||
from app.core.response import error_response, success_response
|
||||
from app.crud import sample_sms_notification as svc
|
||||
from app.crud.collection_protocol import total_pages
|
||||
from app.models.models import SysUser
|
||||
|
||||
router = APIRouter(prefix="/web/admin", tags=["样本接收短信通知"])
|
||||
|
||||
|
||||
def _get_tenant_no(db: Session, user: dict) -> str:
|
||||
user_id = user.get("user_id")
|
||||
if not user_id:
|
||||
raise PermissionError("用户身份信息缺失,无法确定租户")
|
||||
sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
|
||||
if not sys_user or not sys_user.tenant_no:
|
||||
raise PermissionError("用户租户信息缺失")
|
||||
return sys_user.tenant_no
|
||||
|
||||
|
||||
def _get_current_user_id(user: dict) -> str:
|
||||
user_id = user.get("user_id")
|
||||
if not user_id:
|
||||
raise PermissionError("用户身份信息缺失")
|
||||
return str(user_id)
|
||||
|
||||
|
||||
def _page_payload(items: list, total: int, page: int, page_size: int) -> dict:
|
||||
return {
|
||||
"list": items,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"pageSize": page_size,
|
||||
"totalPages": total_pages(total, page_size),
|
||||
}
|
||||
|
||||
|
||||
class ToggleStatusBody(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
sms_notified: int = Field(..., alias="smsNotified")
|
||||
sample_reception_id: Optional[str] = Field(None, alias="sampleReceptionId")
|
||||
|
||||
|
||||
@router.get("/sample-sms-notifications/list")
|
||||
async def list_notifications(
|
||||
page: int = Query(1, ge=1),
|
||||
pageSize: int = Query(10, ge=1, le=100),
|
||||
keyword: Optional[str] = None,
|
||||
acceptConclusion: Optional[str] = None,
|
||||
smsNotified: Optional[int] = None,
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("cell-storage:sample-reception-info:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, total = svc.list_notifications(
|
||||
db,
|
||||
page=page,
|
||||
page_size=pageSize,
|
||||
tenant_no=tenant_no,
|
||||
keyword=keyword,
|
||||
accept_conclusion=acceptConclusion,
|
||||
sms_notified=smsNotified,
|
||||
user_info=user,
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/sample-sms-notifications/{notification_id}/toggle-status")
|
||||
async def toggle_status(
|
||||
notification_id: str,
|
||||
body: ToggleStatusBody,
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("cell-storage:sample-reception-info:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
result = svc.toggle_notification_status(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
sms_notified=body.sms_notified,
|
||||
user_id=user_id,
|
||||
sample_reception_id=body.sample_reception_id,
|
||||
)
|
||||
if not result:
|
||||
return error_response(404, "通知记录不存在")
|
||||
return success_response(None)
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/sample-sms-notifications/{notification_id}/generate-sms")
|
||||
async def generate_sms(
|
||||
notification_id: str,
|
||||
sampleReceptionId: Optional[str] = Query(None),
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("cell-storage:sample-reception-info:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
content = svc.generate_sms_content(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
sample_reception_id=sampleReceptionId,
|
||||
user_id=user_id,
|
||||
)
|
||||
if content is None:
|
||||
return error_response(404, "通知记录不存在")
|
||||
return success_response({"smsContent": content})
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(400, str(e))
|
||||
@@ -0,0 +1,131 @@
|
||||
"""样本入库短信通知 API"""
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.menu_guard import require_menu_code
|
||||
from app.core.response import error_response, success_response
|
||||
from app.crud import storage_entry_sms_notification as svc
|
||||
from app.crud.collection_protocol import total_pages
|
||||
from app.models.models import SysUser
|
||||
|
||||
router = APIRouter(prefix="/web/admin", tags=["样本入库短信通知"])
|
||||
|
||||
|
||||
def _get_tenant_no(db: Session, user: dict) -> str:
|
||||
user_id = user.get("user_id")
|
||||
if not user_id:
|
||||
raise PermissionError("用户身份信息缺失,无法确定租户")
|
||||
sys_user = db.query(SysUser).filter(SysUser.id == user_id).first()
|
||||
if not sys_user or not sys_user.tenant_no:
|
||||
raise PermissionError("用户租户信息缺失")
|
||||
return sys_user.tenant_no
|
||||
|
||||
|
||||
def _get_current_user_id(user: dict) -> str:
|
||||
user_id = user.get("user_id")
|
||||
if not user_id:
|
||||
raise PermissionError("用户身份信息缺失")
|
||||
return str(user_id)
|
||||
|
||||
|
||||
def _page_payload(items: list, total: int, page: int, page_size: int) -> dict:
|
||||
return {
|
||||
"list": items,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"pageSize": page_size,
|
||||
"totalPages": total_pages(total, page_size),
|
||||
}
|
||||
|
||||
|
||||
class ToggleStatusBody(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
sms_notified: int = Field(..., alias="smsNotified")
|
||||
storage_review_id: Optional[str] = Field(None, alias="storageReviewId")
|
||||
|
||||
|
||||
@router.get("/storage-entry-sms-notifications/list")
|
||||
async def list_notifications(
|
||||
page: int = Query(1, ge=1),
|
||||
pageSize: int = Query(10, ge=1, le=100),
|
||||
keyword: Optional[str] = None,
|
||||
storageStatus: Optional[str] = None,
|
||||
smsNotified: Optional[int] = None,
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("cell-storage:storage-entry-info:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, total = svc.list_notifications(
|
||||
db,
|
||||
page=page,
|
||||
page_size=pageSize,
|
||||
tenant_no=tenant_no,
|
||||
keyword=keyword,
|
||||
storage_status=storageStatus,
|
||||
sms_notified=smsNotified,
|
||||
user_info=user,
|
||||
)
|
||||
return success_response(_page_payload(items, total, page, pageSize))
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/storage-entry-sms-notifications/{notification_id}/toggle-status")
|
||||
async def toggle_status(
|
||||
notification_id: str,
|
||||
body: ToggleStatusBody,
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("cell-storage:storage-entry-info:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
result = svc.toggle_notification_status(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
sms_notified=body.sms_notified,
|
||||
user_id=user_id,
|
||||
storage_review_id=body.storage_review_id,
|
||||
)
|
||||
if not result:
|
||||
return error_response(404, "通知记录不存在")
|
||||
return success_response(None)
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.post("/storage-entry-sms-notifications/{notification_id}/generate-sms")
|
||||
async def generate_sms(
|
||||
notification_id: str,
|
||||
storageReviewId: Optional[str] = Query(None),
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("cell-storage:storage-entry-info:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
content = svc.generate_sms_content(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
storage_review_id=storageReviewId,
|
||||
user_id=user_id,
|
||||
)
|
||||
if content is None:
|
||||
return error_response(404, "通知记录不存在")
|
||||
return success_response({"smsContent": content})
|
||||
except PermissionError as e:
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(400, str(e))
|
||||
@@ -60,9 +60,9 @@ async def list_storage_release_reviews(
|
||||
)
|
||||
return success_response(result)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.get("/storage-release-reviews/{review_id}")
|
||||
@@ -75,12 +75,12 @@ async def get_storage_release_review_detail(
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
detail = srr_svc.get_review_detail(db, review_id, tenant_no)
|
||||
if not detail:
|
||||
return error_response("审核记录不存在", code=404)
|
||||
return error_response(404, "审核记录不存在")
|
||||
return success_response(detail)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/storage-release-reviews/{review_id}/review")
|
||||
@@ -105,11 +105,11 @@ async def submit_single_review(
|
||||
db.commit()
|
||||
return success_response(srr_svc._row_to_dict(rev))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/storage-release-reviews/batch-review")
|
||||
@@ -133,11 +133,11 @@ async def batch_review(
|
||||
db.commit()
|
||||
return success_response(result)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/storage-release-reviews/{review_id}/store")
|
||||
@@ -158,11 +158,11 @@ async def store_single_sample(
|
||||
db.commit()
|
||||
return success_response(srr_svc._row_to_dict(rev))
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
|
||||
|
||||
@router.put("/storage-release-reviews/batch-store")
|
||||
@@ -183,8 +183,8 @@ async def batch_store_samples(
|
||||
db.commit()
|
||||
return success_response(result)
|
||||
except PermissionError as e:
|
||||
return error_response(str(e), code=403)
|
||||
return error_response(403, str(e))
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
return error_response(400, str(e))
|
||||
@@ -954,6 +954,8 @@ def get_protocol_detail_bundle(
|
||||
sample_code_by_id=sample_code_by_id,
|
||||
)
|
||||
from app.crud import qc_work_order as qc_work_order_svc
|
||||
from app.crud import production_work_order as production_work_order_svc
|
||||
from app.crud import storage_release_review as storage_release_review_svc
|
||||
|
||||
qc_by_sample = qc_work_order_svc.get_qc_info_map_for_samples(
|
||||
db,
|
||||
@@ -961,12 +963,26 @@ def get_protocol_detail_bundle(
|
||||
tenant_no,
|
||||
sample_code_by_id=sample_code_by_id,
|
||||
)
|
||||
production_by_sample = production_work_order_svc.get_production_info_map_for_samples(
|
||||
db,
|
||||
[s.id for s in s_rows],
|
||||
tenant_no,
|
||||
sample_code_by_id=sample_code_by_id,
|
||||
)
|
||||
storage_release_by_sample = storage_release_review_svc.get_storage_release_map_for_samples(
|
||||
db,
|
||||
[s.id for s in s_rows],
|
||||
tenant_no,
|
||||
sample_code_by_id=sample_code_by_id,
|
||||
)
|
||||
samples_out: List[Dict[str, Any]] = []
|
||||
for s in s_rows:
|
||||
item = _sample_to_dict(s)
|
||||
item["transport"] = transport_by_sample.get(s.id)
|
||||
item["sampleReception"] = reception_by_sample.get(s.id)
|
||||
item["qcInfo"] = qc_by_sample.get(s.id)
|
||||
item["productionInfo"] = production_by_sample.get(s.id)
|
||||
item["storageReleaseInfo"] = storage_release_by_sample.get(s.id)
|
||||
samples_out.append(item)
|
||||
out["samples"] = samples_out
|
||||
out["storageCert"] = _storage_cert_to_dict(sc) if sc else None
|
||||
|
||||
@@ -12,6 +12,7 @@ from app.core.utils import generate_uuid, parse_datetime
|
||||
from app.models.models import (
|
||||
BizCellProduct,
|
||||
BizCellSampleType,
|
||||
BizCollectionProtocol,
|
||||
BizProcess,
|
||||
BizProcessConsumable,
|
||||
BizProcessDataCollection,
|
||||
@@ -38,6 +39,15 @@ from app.models.models import (
|
||||
)
|
||||
from app.crud import storage_occupancy as occupancy_svc
|
||||
from app.crud.cell_product import _row_to_dict as _cp_row_to_dict, _enrich_product_dicts as _cp_enrich
|
||||
from app.models.research_donation import BizResearchDonation
|
||||
|
||||
|
||||
_PROTOCOL_STATUS_LABELS = {
|
||||
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zky": "转科研"
|
||||
}
|
||||
_DONATION_STATUS_LABELS = {
|
||||
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zckc": "转细胞存储"
|
||||
}
|
||||
|
||||
|
||||
def _fmt_dt(t: Optional[datetime]) -> str:
|
||||
@@ -414,18 +424,47 @@ def list_production_tasks(
|
||||
BizProductionWorkOrder.sample_code,
|
||||
BizProductionWorkOrder.reception_id,
|
||||
BizProductionWorkOrder.protocol_sample_id,
|
||||
BizProductionWorkOrder.collection_protocol_id,
|
||||
BizProductionWorkOrder.reception_source,
|
||||
)
|
||||
.filter(BizProductionWorkOrder.id.in_(wo_ids))
|
||||
.all()
|
||||
)
|
||||
for w in wo_rows:
|
||||
wo_map[w.id] = w
|
||||
cell_wo_ids = [w.collection_protocol_id for w in wo_rows if (w.reception_source or "cell_storage") != "research_donation" and w.collection_protocol_id]
|
||||
donation_wo_ids = [w.collection_protocol_id for w in wo_rows if (w.reception_source or "") == "research_donation" and w.collection_protocol_id]
|
||||
proto_status_map: Dict[str, str] = {}
|
||||
if cell_wo_ids:
|
||||
for p in (
|
||||
db.query(BizCollectionProtocol.id, BizCollectionProtocol.protocol_status)
|
||||
.filter(BizCollectionProtocol.id.in_(cell_wo_ids), BizCollectionProtocol.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
proto_status_map[p.id] = p.protocol_status or ""
|
||||
donation_status_map: Dict[str, str] = {}
|
||||
if donation_wo_ids:
|
||||
for d in (
|
||||
db.query(BizResearchDonation.id, BizResearchDonation.donation_status)
|
||||
.filter(BizResearchDonation.id.in_(donation_wo_ids), BizResearchDonation.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
donation_status_map[d.id] = d.donation_status or ""
|
||||
for item, row in zip(items, rows):
|
||||
wo = wo_map.get(row.work_order_id)
|
||||
if wo:
|
||||
item["workOrderNo"] = wo.work_order_no or ""
|
||||
item["protocolNo"] = wo.protocol_no or ""
|
||||
item["sampleCode"] = wo.sample_code or ""
|
||||
_source = wo.reception_source or "cell_storage"
|
||||
if _source == "research_donation":
|
||||
_st = donation_status_map.get(wo.collection_protocol_id, "")
|
||||
item["protocolStatus"] = _st
|
||||
item["protocolStatusLabel"] = _DONATION_STATUS_LABELS.get(_st, _st)
|
||||
else:
|
||||
_st = proto_status_map.get(wo.collection_protocol_id, "")
|
||||
item["protocolStatus"] = _st
|
||||
item["protocolStatusLabel"] = _PROTOCOL_STATUS_LABELS.get(_st, _st)
|
||||
# 批量补充接收人、接收时间
|
||||
reception_ids = [wo.reception_id for wo in wo_map.values() if getattr(wo, "reception_id", None)]
|
||||
reception_map: Dict[str, Any] = {}
|
||||
@@ -492,6 +531,25 @@ def get_production_task_detail(db: Session, task_id: str, tenant_no: str) -> Opt
|
||||
if wo:
|
||||
result["sampleCode"] = wo.sample_code or ""
|
||||
result["protocolNo"] = wo.protocol_no or ""
|
||||
_src = getattr(wo, "reception_source", "cell_storage") or "cell_storage"
|
||||
_cpid = wo.collection_protocol_id or ""
|
||||
if _src == "research_donation" and _cpid:
|
||||
d = db.query(BizResearchDonation.donation_status).filter(
|
||||
BizResearchDonation.id == _cpid, BizResearchDonation.del_flag == 0
|
||||
).first()
|
||||
_st = d.donation_status or "" if d else ""
|
||||
result["protocolStatus"] = _st
|
||||
result["protocolStatusLabel"] = _DONATION_STATUS_LABELS.get(_st, _st)
|
||||
elif _cpid:
|
||||
p = db.query(BizCollectionProtocol.protocol_status).filter(
|
||||
BizCollectionProtocol.id == _cpid, BizCollectionProtocol.del_flag == 0
|
||||
).first()
|
||||
_st = p.protocol_status or "" if p else ""
|
||||
result["protocolStatus"] = _st
|
||||
result["protocolStatusLabel"] = _PROTOCOL_STATUS_LABELS.get(_st, _st)
|
||||
else:
|
||||
result["protocolStatus"] = ""
|
||||
result["protocolStatusLabel"] = ""
|
||||
|
||||
steps = (
|
||||
db.query(BizProductionTaskStep)
|
||||
|
||||
@@ -14,6 +14,8 @@ from app.crud import sample_reception_check_result as check_result_svc
|
||||
from app.models.models import (
|
||||
BizCollectionProtocol,
|
||||
BizProductionTask,
|
||||
BizProductionTaskInput,
|
||||
BizProductionTaskOutput,
|
||||
BizProductionWorkOrder,
|
||||
BizProtocolSample,
|
||||
BizSampleReception,
|
||||
@@ -367,3 +369,140 @@ def complete_production_work_order(
|
||||
db.commit()
|
||||
db.refresh(wo)
|
||||
return wo
|
||||
|
||||
|
||||
_TASK_STATUS_LABELS = {
|
||||
"dpz": "待配置",
|
||||
"dzx": "待执行",
|
||||
"jxz": "执行中",
|
||||
"ywc": "已完成",
|
||||
}
|
||||
|
||||
|
||||
def _production_task_info(db: Session, task: BizProductionTask) -> Dict[str, Any]:
|
||||
"""将单条生产任务(含投入物、产出物)转为摘要字典。"""
|
||||
inputs = (
|
||||
db.query(BizProductionTaskInput)
|
||||
.filter(
|
||||
BizProductionTaskInput.task_id == task.id,
|
||||
BizProductionTaskInput.del_flag == 0,
|
||||
)
|
||||
.order_by(BizProductionTaskInput.order_num)
|
||||
.all()
|
||||
)
|
||||
outputs = (
|
||||
db.query(BizProductionTaskOutput)
|
||||
.filter(
|
||||
BizProductionTaskOutput.task_id == task.id,
|
||||
BizProductionTaskOutput.del_flag == 0,
|
||||
)
|
||||
.order_by(BizProductionTaskOutput.order_num)
|
||||
.all()
|
||||
)
|
||||
return {
|
||||
"id": task.id,
|
||||
"taskNo": task.task_no,
|
||||
"taskName": task.task_name or "",
|
||||
"taskStatus": task.task_status or "",
|
||||
"taskStatusLabel": _TASK_STATUS_LABELS.get(task.task_status, task.task_status or ""),
|
||||
"startedTime": _fmt_dt(task.started_time),
|
||||
"completedTime": _fmt_dt(task.completed_time),
|
||||
"inputs": [
|
||||
{
|
||||
"inputType": (inp.input_type or ""),
|
||||
"inputCode": (inp.input_code or ""),
|
||||
"inputName": (inp.input_name or ""),
|
||||
}
|
||||
for inp in inputs
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"outputType": "product",
|
||||
"outputCode": (out.output_barcode or ""),
|
||||
"outputName": (out.output_name or ""),
|
||||
}
|
||||
for out in outputs
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _production_info_item(db: Session, wo: BizProductionWorkOrder) -> Dict[str, Any]:
|
||||
"""将单条生产工单(含任务列表)转为摘要字典。"""
|
||||
tasks = (
|
||||
db.query(BizProductionTask)
|
||||
.filter(
|
||||
BizProductionTask.work_order_id == wo.id,
|
||||
BizProductionTask.tenant_no == wo.tenant_no,
|
||||
BizProductionTask.del_flag == 0,
|
||||
)
|
||||
.order_by(BizProductionTask.order_num, BizProductionTask.create_time)
|
||||
.all()
|
||||
)
|
||||
return {
|
||||
"workOrderNo": wo.work_order_no or "",
|
||||
"workOrderStatus": wo.work_order_status or "",
|
||||
"workOrderStatusLabel": _WORK_ORDER_STATUS_LABELS.get(wo.work_order_status, wo.work_order_status or ""),
|
||||
"tasks": [_production_task_info(db, t) for t in tasks],
|
||||
}
|
||||
|
||||
|
||||
def get_production_info_map_for_samples(
|
||||
db: Session,
|
||||
sample_ids: List[str],
|
||||
tenant_no: str,
|
||||
*,
|
||||
sample_code_by_id: Optional[Dict[str, str]] = None,
|
||||
) -> Dict[str, Dict[str, Any]]:
|
||||
"""按样本批量返回生产工单摘要(含任务、投入物、产出物),供协议查看弹窗使用。
|
||||
|
||||
细胞存储:传入 sample_code_by_id 时,按租户 + 样本编码关联。
|
||||
科研捐赠等:仅传 sample_ids 时,按 protocol_sample_id 关联。
|
||||
"""
|
||||
if not tenant_no:
|
||||
return {}
|
||||
|
||||
if sample_code_by_id:
|
||||
codes = list({(c or "").strip() for c in sample_code_by_id.values() if (c or "").strip()})
|
||||
if not codes:
|
||||
return {}
|
||||
wos = (
|
||||
db.query(BizProductionWorkOrder)
|
||||
.filter(
|
||||
BizProductionWorkOrder.tenant_no == tenant_no,
|
||||
BizProductionWorkOrder.del_flag == 0,
|
||||
BizProductionWorkOrder.sample_code.in_(codes),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
code_to_wo: Dict[str, BizProductionWorkOrder] = {}
|
||||
for wo in wos:
|
||||
code = (wo.sample_code or "").strip()
|
||||
if code and code not in code_to_wo:
|
||||
code_to_wo[code] = wo
|
||||
out: Dict[str, Dict[str, Any]] = {}
|
||||
for sid, raw_code in sample_code_by_id.items():
|
||||
code = (raw_code or "").strip()
|
||||
if not code:
|
||||
continue
|
||||
wo = code_to_wo.get(code)
|
||||
if wo:
|
||||
out[sid] = _production_info_item(db, wo)
|
||||
return out
|
||||
|
||||
if not sample_ids:
|
||||
return {}
|
||||
wos = (
|
||||
db.query(BizProductionWorkOrder)
|
||||
.filter(
|
||||
BizProductionWorkOrder.protocol_sample_id.in_(sample_ids),
|
||||
BizProductionWorkOrder.tenant_no == tenant_no,
|
||||
BizProductionWorkOrder.del_flag == 0,
|
||||
)
|
||||
.all()
|
||||
)
|
||||
out = {}
|
||||
for wo in wos:
|
||||
sid = (wo.protocol_sample_id or "").strip()
|
||||
if sid:
|
||||
out[sid] = _production_info_item(db, wo)
|
||||
return out
|
||||
@@ -19,12 +19,13 @@ from app.crud.qc_work_order import (
|
||||
_work_order_qc_biz_type,
|
||||
)
|
||||
from app.models.models import (
|
||||
BizCollectionProtocol,
|
||||
BizProtocolSample,
|
||||
BizQcTask,
|
||||
BizQcWorkOrder,
|
||||
BizSampleReception,
|
||||
)
|
||||
from app.models.research_donation import BizResearchDonationSample
|
||||
from app.models.research_donation import BizResearchDonation, BizResearchDonationSample
|
||||
|
||||
|
||||
def _dec(v: Any) -> Optional[float]:
|
||||
@@ -42,6 +43,12 @@ def _gen_task_no(db: Session, work_order: BizQcWorkOrder, seq: int) -> str:
|
||||
|
||||
|
||||
_CONCLUSION_LABELS = {"tg": "通过", "btg": "不通过"}
|
||||
_PROTOCOL_STATUS_LABELS = {
|
||||
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zky": "转科研"
|
||||
}
|
||||
_DONATION_STATUS_LABELS = {
|
||||
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zckc": "转细胞存储"
|
||||
}
|
||||
|
||||
|
||||
def _conclusion_label(v: Optional[str]) -> str:
|
||||
@@ -150,6 +157,32 @@ def _enrich_tasks_reception_fields(
|
||||
}
|
||||
)
|
||||
type_map = _load_sample_type_name_map(db, type_ids)
|
||||
cell_proto_ids = [
|
||||
rec.collection_protocol_id
|
||||
for rec in rec_map.values()
|
||||
if (rec.reception_source or "cell_storage") != "research_donation" and rec.collection_protocol_id
|
||||
]
|
||||
donation_ids = [
|
||||
rec.research_donation_id
|
||||
for rec in rec_map.values()
|
||||
if (rec.reception_source or "") == "research_donation" and rec.research_donation_id
|
||||
]
|
||||
proto_status_map: Dict[str, str] = {}
|
||||
if cell_proto_ids:
|
||||
for p in (
|
||||
db.query(BizCollectionProtocol.id, BizCollectionProtocol.protocol_status)
|
||||
.filter(BizCollectionProtocol.id.in_(cell_proto_ids), BizCollectionProtocol.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
proto_status_map[p.id] = p.protocol_status or ""
|
||||
donation_status_map: Dict[str, str] = {}
|
||||
if donation_ids:
|
||||
for d in (
|
||||
db.query(BizResearchDonation.id, BizResearchDonation.donation_status)
|
||||
.filter(BizResearchDonation.id.in_(donation_ids), BizResearchDonation.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
donation_status_map[d.id] = d.donation_status or ""
|
||||
for item in items:
|
||||
rec = rec_map.get(item.get("receptionId") or "")
|
||||
if not rec:
|
||||
@@ -163,6 +196,17 @@ def _enrich_tasks_reception_fields(
|
||||
protocol_samples=protocol_samples,
|
||||
donation_samples=donation_samples,
|
||||
)
|
||||
source = item.get("receptionSource") or (rec.reception_source if rec else "cell_storage")
|
||||
if source == "research_donation":
|
||||
_did = rec.research_donation_id if rec else ""
|
||||
_st = donation_status_map.get(_did or "", "")
|
||||
item["protocolStatus"] = _st
|
||||
item["protocolStatusLabel"] = _DONATION_STATUS_LABELS.get(_st, _st)
|
||||
else:
|
||||
_pid = rec.collection_protocol_id if rec else ""
|
||||
_st = proto_status_map.get(_pid or "", "")
|
||||
item["protocolStatus"] = _st
|
||||
item["protocolStatusLabel"] = _PROTOCOL_STATUS_LABELS.get(_st, _st)
|
||||
return items
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@ _ACCEPT_CONCLUSION_LABELS = {"js": "接收", "bj": "拒收"}
|
||||
_WORK_ORDER_STATUS_LABELS = {"dpz": "待配置", "ypz": "已配置", "ywc": "已完成"}
|
||||
_TASK_TYPE_LABELS = {"sysz": "实验室自检", "dsfjc": "第三方检测"}
|
||||
_TASK_STATUS_LABELS = {"dzx": "待执行", "jxz": "进行中", "ywc": "已完成"}
|
||||
_PROTOCOL_STATUS_LABELS = {
|
||||
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zky": "转科研"
|
||||
}
|
||||
_DONATION_STATUS_LABELS = {
|
||||
"dsx": "待生效", "sxz": "生效中", "ygq": "已过期", "yzf": "已作废", "zckc": "转细胞存储"
|
||||
}
|
||||
_CONCLUSION_LABELS = {"tg": "通过", "btg": "不通过"}
|
||||
|
||||
|
||||
@@ -155,6 +161,32 @@ def _enrich_work_order_list_items(
|
||||
}
|
||||
)
|
||||
type_map = _load_sample_type_name_map(db, type_ids)
|
||||
cell_proto_ids = [
|
||||
rec.collection_protocol_id
|
||||
for rec in rec_map.values()
|
||||
if (rec.reception_source or "cell_storage") != "research_donation" and rec.collection_protocol_id
|
||||
]
|
||||
donation_ids = [
|
||||
rec.research_donation_id
|
||||
for rec in rec_map.values()
|
||||
if (rec.reception_source or "") == "research_donation" and rec.research_donation_id
|
||||
]
|
||||
proto_status_map: Dict[str, str] = {}
|
||||
if cell_proto_ids:
|
||||
for p in (
|
||||
db.query(BizCollectionProtocol.id, BizCollectionProtocol.protocol_status)
|
||||
.filter(BizCollectionProtocol.id.in_(cell_proto_ids), BizCollectionProtocol.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
proto_status_map[p.id] = p.protocol_status or ""
|
||||
donation_status_map: Dict[str, str] = {}
|
||||
if donation_ids:
|
||||
for d in (
|
||||
db.query(BizResearchDonation.id, BizResearchDonation.donation_status)
|
||||
.filter(BizResearchDonation.id.in_(donation_ids), BizResearchDonation.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
donation_status_map[d.id] = d.donation_status or ""
|
||||
for item in items:
|
||||
rec = rec_map.get(item.get("receptionId") or "")
|
||||
source = item.get("receptionSource") or (rec.reception_source if rec else "cell_storage")
|
||||
@@ -173,6 +205,16 @@ def _enrich_work_order_list_items(
|
||||
protocol_samples=protocol_samples,
|
||||
donation_samples=donation_samples,
|
||||
)
|
||||
if source == "research_donation":
|
||||
_did = rec.research_donation_id if rec else ""
|
||||
_st = donation_status_map.get(_did or "", "")
|
||||
item["protocolStatus"] = _st
|
||||
item["protocolStatusLabel"] = _DONATION_STATUS_LABELS.get(_st, _st)
|
||||
else:
|
||||
_pid = rec.collection_protocol_id if rec else ""
|
||||
_st = proto_status_map.get(_pid or "", "")
|
||||
item["protocolStatus"] = _st
|
||||
item["protocolStatusLabel"] = _PROTOCOL_STATUS_LABELS.get(_st, _st)
|
||||
return items
|
||||
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ def _donation_rows_to_sample_list_items(
|
||||
"protocolSampleId": sample.id,
|
||||
"collectionProtocolId": donation.id,
|
||||
"protocolNo": donation.donation_no or "",
|
||||
"protocolStatus": donation.donation_status or "",
|
||||
"sampleCode": sample.sample_code or "",
|
||||
"sampleTypeId": sample.sample_type_id or "",
|
||||
"sampleTypeName": type_map.get(sample.sample_type_id or "", ""),
|
||||
@@ -801,8 +802,6 @@ def create_sample_reception(
|
||||
create_dept_id=create_dept_id or "",
|
||||
)
|
||||
from app.crud import storage_release_review as srr_svc
|
||||
from app.models.models import BizCollectionProtocol, BizProtocolSample
|
||||
from app.models.research_donation import BizResearchDonation, BizResearchDonationSample
|
||||
|
||||
_srr_protocol_no = ""
|
||||
_srr_sample_name = ""
|
||||
|
||||
@@ -0,0 +1,447 @@
|
||||
"""样本接收短信通知 CRUD"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from sqlalchemy import and_, func, or_, select as sa_select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.utils import generate_uuid
|
||||
from app.models.models import (
|
||||
BizCellSampleType,
|
||||
BizCollectionProtocol,
|
||||
BizProtocolPartyCustomer,
|
||||
BizProtocolSample,
|
||||
BizSampleReception,
|
||||
BizSampleSmsNotification,
|
||||
)
|
||||
|
||||
# biz_sample_sms_notification may use general_ci; align with unicode_ci tables on JOIN
|
||||
_UNICODE_CI = "utf8mb4_unicode_ci"
|
||||
|
||||
|
||||
def _unicode_ci(col):
|
||||
return col.collate(_UNICODE_CI)
|
||||
|
||||
|
||||
def total_pages(total: int, page_size: int) -> int:
|
||||
if total <= 0:
|
||||
return 0
|
||||
return int(math.ceil(total / float(page_size)))
|
||||
|
||||
|
||||
def _fmt_dt(t: Optional[datetime]) -> str:
|
||||
return t.strftime("%Y-%m-%d %H:%M:%S") if t else ""
|
||||
|
||||
|
||||
def _accept_conclusion_label(v: str) -> str:
|
||||
return {"js": "接收", "bj": "拒收"}.get(v, "待接收确认")
|
||||
|
||||
|
||||
def _row_to_dict(
|
||||
*,
|
||||
notification_id: str = "",
|
||||
sample_reception_id: str = "",
|
||||
protocol_id: str = "",
|
||||
sms_notified: int = 0,
|
||||
sms_content: str = "",
|
||||
protocol_no: str = "",
|
||||
mother_name: str = "",
|
||||
newborn_name: str = "",
|
||||
sample_code: str = "",
|
||||
sample_type_name: str = "",
|
||||
reception_time: str = "",
|
||||
accept_conclusion: str = "",
|
||||
collection_protocol_id: str = "",
|
||||
protocol_status: str = "",
|
||||
) -> Dict[str, Any]:
|
||||
return {
|
||||
"id": notification_id,
|
||||
"sampleReceptionId": sample_reception_id,
|
||||
"protocolId": protocol_id,
|
||||
"protocolNo": protocol_no,
|
||||
"protocolStatus": protocol_status,
|
||||
"motherName": mother_name,
|
||||
"newbornName": newborn_name,
|
||||
"sampleCode": sample_code,
|
||||
"sampleTypeName": sample_type_name,
|
||||
"receptionTime": reception_time,
|
||||
"acceptConclusion": accept_conclusion,
|
||||
"acceptConclusionLabel": _accept_conclusion_label(accept_conclusion),
|
||||
"smsNotified": sms_notified,
|
||||
"smsContent": sms_content,
|
||||
"collectionProtocolId": collection_protocol_id,
|
||||
}
|
||||
|
||||
|
||||
def _base_query(db: Session, tenant_no: str):
|
||||
# Subquery: protocol IDs that have at least one cell_storage reception
|
||||
cell_storage_protocol_ids = (
|
||||
db.query(BizSampleReception.collection_protocol_id)
|
||||
.filter(
|
||||
BizSampleReception.reception_source == "cell_storage",
|
||||
BizSampleReception.del_flag == 0,
|
||||
)
|
||||
.distinct()
|
||||
.subquery()
|
||||
)
|
||||
|
||||
return (
|
||||
db.query(
|
||||
BizProtocolSample,
|
||||
BizSampleReception,
|
||||
BizSampleSmsNotification,
|
||||
BizCollectionProtocol,
|
||||
BizProtocolPartyCustomer,
|
||||
)
|
||||
.outerjoin(
|
||||
BizSampleReception,
|
||||
and_(
|
||||
_unicode_ci(BizSampleReception.sample_code)
|
||||
== _unicode_ci(BizProtocolSample.sample_code),
|
||||
BizSampleReception.tenant_no == tenant_no,
|
||||
BizSampleReception.reception_source == "cell_storage",
|
||||
BizSampleReception.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizSampleSmsNotification,
|
||||
and_(
|
||||
BizSampleSmsNotification.sample_reception_id == BizSampleReception.id,
|
||||
BizSampleSmsNotification.tenant_no == tenant_no,
|
||||
BizSampleSmsNotification.del_flag == "0",
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizCollectionProtocol,
|
||||
and_(
|
||||
BizCollectionProtocol.id == BizProtocolSample.collection_protocol_id,
|
||||
BizCollectionProtocol.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizProtocolPartyCustomer,
|
||||
and_(
|
||||
BizProtocolPartyCustomer.collection_protocol_id == BizCollectionProtocol.id,
|
||||
BizProtocolPartyCustomer.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.filter(
|
||||
BizProtocolSample.tenant_no == tenant_no,
|
||||
BizProtocolSample.del_flag == 0,
|
||||
BizProtocolSample.collection_protocol_id.in_(sa_select(cell_storage_protocol_ids)),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _ensure_notification(
|
||||
db: Session,
|
||||
reception: Optional[BizSampleReception],
|
||||
tenant_no: str,
|
||||
user_id: Optional[str] = None,
|
||||
*,
|
||||
psample: Optional[BizProtocolSample] = None,
|
||||
) -> BizSampleSmsNotification:
|
||||
lookup_id = reception.id if reception else (psample.id if psample else None)
|
||||
if not lookup_id:
|
||||
raise ValueError("reception or psample required")
|
||||
|
||||
existing = (
|
||||
db.query(BizSampleSmsNotification)
|
||||
.filter(
|
||||
BizSampleSmsNotification.sample_reception_id == lookup_id,
|
||||
BizSampleSmsNotification.tenant_no == tenant_no,
|
||||
BizSampleSmsNotification.del_flag == "0",
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if existing:
|
||||
return existing
|
||||
|
||||
obj = BizSampleSmsNotification(
|
||||
id=generate_uuid(),
|
||||
sample_reception_id=lookup_id,
|
||||
protocol_id=(reception.collection_protocol_id if reception else psample.collection_protocol_id) or "",
|
||||
sms_notified=0,
|
||||
tenant_no=tenant_no,
|
||||
create_by=user_id,
|
||||
update_by=user_id,
|
||||
)
|
||||
db.add(obj)
|
||||
db.flush()
|
||||
db.commit()
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
def resolve_notification(
|
||||
db: Session,
|
||||
*,
|
||||
notification_id: str,
|
||||
tenant_no: str,
|
||||
sample_reception_id: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
) -> Optional[BizSampleSmsNotification]:
|
||||
notif = (
|
||||
db.query(BizSampleSmsNotification)
|
||||
.filter(
|
||||
BizSampleSmsNotification.id == notification_id,
|
||||
BizSampleSmsNotification.tenant_no == tenant_no,
|
||||
BizSampleSmsNotification.del_flag == "0",
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if notif:
|
||||
return notif
|
||||
|
||||
if not sample_reception_id:
|
||||
return None
|
||||
|
||||
rec = (
|
||||
db.query(BizSampleReception)
|
||||
.filter(
|
||||
BizSampleReception.id == sample_reception_id,
|
||||
BizSampleReception.tenant_no == tenant_no,
|
||||
BizSampleReception.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if rec:
|
||||
return _ensure_notification(db, rec, tenant_no=tenant_no, user_id=user_id)
|
||||
|
||||
psample = (
|
||||
db.query(BizProtocolSample)
|
||||
.filter(
|
||||
BizProtocolSample.id == sample_reception_id,
|
||||
BizProtocolSample.tenant_no == tenant_no,
|
||||
BizProtocolSample.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if psample:
|
||||
return _ensure_notification(db, None, tenant_no=tenant_no, user_id=user_id, psample=psample)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _fetch_sample_type_name(db: Session, sample_type_id: Optional[str], tenant_no: str) -> str:
|
||||
if not sample_type_id:
|
||||
return ""
|
||||
t = (
|
||||
db.query(BizCellSampleType)
|
||||
.filter(
|
||||
BizCellSampleType.id == sample_type_id,
|
||||
BizCellSampleType.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
return (t.type_name or "") if t else ""
|
||||
|
||||
|
||||
def list_notifications(
|
||||
db: Session,
|
||||
*,
|
||||
page: int = 1,
|
||||
page_size: int = 10,
|
||||
tenant_no: str,
|
||||
keyword: Optional[str] = None,
|
||||
accept_conclusion: Optional[str] = None,
|
||||
sms_notified: Optional[int] = None,
|
||||
user_info=None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
if not tenant_no:
|
||||
return [], 0
|
||||
|
||||
q = _base_query(db, tenant_no)
|
||||
|
||||
if keyword and keyword.strip():
|
||||
kw = f"%{keyword.strip()}%"
|
||||
q = q.filter(
|
||||
or_(
|
||||
BizCollectionProtocol.protocol_no.like(kw),
|
||||
BizProtocolPartyCustomer.mother_name.like(kw),
|
||||
BizProtocolSample.sample_code.like(kw),
|
||||
)
|
||||
)
|
||||
|
||||
if accept_conclusion:
|
||||
if accept_conclusion == "dqr":
|
||||
q = q.filter(BizSampleReception.id.is_(None))
|
||||
else:
|
||||
q = q.filter(BizSampleReception.accept_conclusion == accept_conclusion)
|
||||
|
||||
if sms_notified is not None:
|
||||
if sms_notified == 0:
|
||||
q = q.filter(
|
||||
or_(
|
||||
BizSampleSmsNotification.sms_notified == 0,
|
||||
BizSampleSmsNotification.id.is_(None),
|
||||
)
|
||||
)
|
||||
else:
|
||||
q = q.filter(BizSampleSmsNotification.sms_notified == sms_notified)
|
||||
|
||||
if user_info:
|
||||
from app.core.data_scope import apply_data_scope
|
||||
q = apply_data_scope(q, BizProtocolSample, user_info, db, tenant_no)
|
||||
|
||||
total = q.count()
|
||||
page = max(1, page)
|
||||
page_size = min(max(1, page_size), 100)
|
||||
|
||||
# MySQL 5.7 不支持 NULLS LAST;用 IS NULL 升序把空接收时间排到最后
|
||||
rows = (
|
||||
q.order_by(
|
||||
BizSampleReception.reception_time.is_(None),
|
||||
BizSampleReception.reception_time.desc(),
|
||||
BizProtocolSample.create_time.desc(),
|
||||
)
|
||||
.offset((page - 1) * page_size)
|
||||
.limit(page_size)
|
||||
.all()
|
||||
)
|
||||
|
||||
sample_type_ids = list({
|
||||
ps.sample_type_id
|
||||
for ps, _, _, _, _ in rows
|
||||
if ps and ps.sample_type_id
|
||||
})
|
||||
type_map: Dict[str, str] = {}
|
||||
if sample_type_ids:
|
||||
for t in (
|
||||
db.query(BizCellSampleType)
|
||||
.filter(BizCellSampleType.id.in_(sample_type_ids), BizCellSampleType.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
type_map[t.id] = t.type_name or ""
|
||||
|
||||
items: List[Dict[str, Any]] = []
|
||||
for psample, rec, notif, proto, party in rows:
|
||||
if notif is None:
|
||||
notif = _ensure_notification(db, rec, tenant_no=tenant_no, psample=psample)
|
||||
|
||||
sample_type_name = ""
|
||||
if psample and psample.sample_type_id:
|
||||
sample_type_name = type_map.get(psample.sample_type_id, "")
|
||||
items.append(
|
||||
_row_to_dict(
|
||||
notification_id=notif.id,
|
||||
sample_reception_id=rec.id if rec else psample.id,
|
||||
protocol_id=notif.protocol_id or "",
|
||||
sms_notified=notif.sms_notified or 0,
|
||||
sms_content=notif.sms_content or "",
|
||||
protocol_no=(proto.protocol_no or "") if proto else "",
|
||||
mother_name=(party.mother_name or "") if party else "",
|
||||
newborn_name=(party.newborn_name or "") if party else "",
|
||||
sample_code=psample.sample_code or (rec.sample_code if rec else "") or "",
|
||||
sample_type_name=sample_type_name,
|
||||
reception_time=_fmt_dt(rec.reception_time) if rec else "",
|
||||
accept_conclusion=rec.accept_conclusion if rec else "",
|
||||
collection_protocol_id=(proto.id or "") if proto else "",
|
||||
protocol_status=(proto.protocol_status or "") if proto else "",
|
||||
)
|
||||
)
|
||||
return items, int(total)
|
||||
|
||||
|
||||
def toggle_notification_status(
|
||||
db: Session,
|
||||
*,
|
||||
notification_id: str,
|
||||
tenant_no: str,
|
||||
sms_notified: int,
|
||||
user_id: Optional[str] = None,
|
||||
sample_reception_id: Optional[str] = None,
|
||||
) -> Optional[BizSampleSmsNotification]:
|
||||
notif = resolve_notification(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
sample_reception_id=sample_reception_id,
|
||||
user_id=user_id,
|
||||
)
|
||||
if not notif:
|
||||
return None
|
||||
|
||||
notif.sms_notified = sms_notified
|
||||
notif.notified_by = user_id if sms_notified == 1 else None
|
||||
notif.notified_time = datetime.now() if sms_notified == 1 else None
|
||||
notif.update_by = user_id
|
||||
notif.update_time = datetime.now()
|
||||
db.commit()
|
||||
db.refresh(notif)
|
||||
return notif
|
||||
|
||||
|
||||
def generate_sms_content(
|
||||
db: Session,
|
||||
*,
|
||||
notification_id: str,
|
||||
tenant_no: str,
|
||||
sample_reception_id: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
) -> Optional[str]:
|
||||
notif = resolve_notification(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
sample_reception_id=sample_reception_id,
|
||||
user_id=user_id,
|
||||
)
|
||||
if not notif:
|
||||
return None
|
||||
|
||||
rec = (
|
||||
db.query(BizSampleReception)
|
||||
.filter(
|
||||
BizSampleReception.id == notif.sample_reception_id,
|
||||
BizSampleReception.tenant_no == tenant_no,
|
||||
BizSampleReception.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not rec:
|
||||
notif.sms_content = "暂无短信内容,样本尚未完成接收确认"
|
||||
notif.update_time = datetime.now()
|
||||
db.commit()
|
||||
db.refresh(notif)
|
||||
return notif.sms_content
|
||||
|
||||
mother_name = ""
|
||||
proto = (
|
||||
db.query(BizCollectionProtocol)
|
||||
.filter(
|
||||
BizCollectionProtocol.id == rec.collection_protocol_id,
|
||||
BizCollectionProtocol.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if proto:
|
||||
party = (
|
||||
db.query(BizProtocolPartyCustomer)
|
||||
.filter(
|
||||
BizProtocolPartyCustomer.collection_protocol_id == proto.id,
|
||||
BizProtocolPartyCustomer.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if party:
|
||||
mother_name = party.mother_name or ""
|
||||
|
||||
sample_code = rec.sample_code or ""
|
||||
reception_date = _fmt_dt(rec.reception_time)[:10] if rec.reception_time else ""
|
||||
conclusion_label = _accept_conclusion_label(rec.accept_conclusion or "")
|
||||
|
||||
content = (
|
||||
f"尊敬的{mother_name}女士,您的样本(编码:{sample_code})"
|
||||
f"已于{reception_date}完成接收处理,结论:{conclusion_label}。"
|
||||
f"如有疑问请联系客服。"
|
||||
)
|
||||
|
||||
notif.sms_content = content
|
||||
notif.update_time = datetime.now()
|
||||
db.commit()
|
||||
db.refresh(notif)
|
||||
return content
|
||||
@@ -0,0 +1,457 @@
|
||||
"""样本入库短信通知 CRUD"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from sqlalchemy import and_, func, or_, select as sa_select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.utils import generate_uuid
|
||||
from app.models.models import (
|
||||
BizCellSampleType,
|
||||
BizCollectionProtocol,
|
||||
BizProtocolPartyCustomer,
|
||||
BizProtocolSample,
|
||||
BizSampleReception,
|
||||
BizStorageEntrySmsNotification,
|
||||
BizStorageReleaseReview,
|
||||
SysUser,
|
||||
)
|
||||
|
||||
_UNICODE_CI = "utf8mb4_unicode_ci"
|
||||
|
||||
|
||||
def _unicode_ci(col):
|
||||
return col.collate(_UNICODE_CI)
|
||||
|
||||
|
||||
def total_pages(total: int, page_size: int) -> int:
|
||||
if total <= 0:
|
||||
return 0
|
||||
return int(math.ceil(total / float(page_size)))
|
||||
|
||||
|
||||
def _fmt_dt(t: Optional[datetime]) -> str:
|
||||
return t.strftime("%Y-%m-%d %H:%M:%S") if t else ""
|
||||
|
||||
|
||||
def _storage_status_label(review: Optional[BizStorageReleaseReview]) -> str:
|
||||
if not review:
|
||||
return "待入库确认"
|
||||
if review.storage_status == "yrk":
|
||||
return "已入库"
|
||||
if review.review_conclusion == "btg":
|
||||
return "拒绝入库"
|
||||
return "待入库确认"
|
||||
|
||||
|
||||
def _row_to_dict(
|
||||
*,
|
||||
notification_id: str = "",
|
||||
storage_review_id: str = "",
|
||||
protocol_id: str = "",
|
||||
sms_notified: int = 0,
|
||||
sms_content: str = "",
|
||||
protocol_no: str = "",
|
||||
mother_name: str = "",
|
||||
newborn_name: str = "",
|
||||
sample_code: str = "",
|
||||
sample_type_name: str = "",
|
||||
storage_time: str = "",
|
||||
storage_status_label: str = "",
|
||||
collection_protocol_id: str = "",
|
||||
protocol_status: str = "",
|
||||
) -> Dict[str, Any]:
|
||||
return {
|
||||
"id": notification_id,
|
||||
"storageReviewId": storage_review_id,
|
||||
"protocolId": protocol_id,
|
||||
"protocolNo": protocol_no,
|
||||
"protocolStatus": protocol_status,
|
||||
"motherName": mother_name,
|
||||
"newbornName": newborn_name,
|
||||
"sampleCode": sample_code,
|
||||
"sampleTypeName": sample_type_name,
|
||||
"storageTime": storage_time,
|
||||
"storageStatusLabel": storage_status_label,
|
||||
"smsNotified": sms_notified,
|
||||
"smsContent": sms_content,
|
||||
"collectionProtocolId": collection_protocol_id,
|
||||
}
|
||||
|
||||
|
||||
def _base_query(db: Session, tenant_no: str):
|
||||
# Subquery: protocol IDs that have at least one cell_storage reception
|
||||
cell_storage_protocol_ids = (
|
||||
db.query(BizSampleReception.collection_protocol_id)
|
||||
.filter(
|
||||
BizSampleReception.reception_source == "cell_storage",
|
||||
BizSampleReception.del_flag == 0,
|
||||
)
|
||||
.distinct()
|
||||
.subquery()
|
||||
)
|
||||
|
||||
return (
|
||||
db.query(
|
||||
BizProtocolSample,
|
||||
BizStorageReleaseReview,
|
||||
BizStorageEntrySmsNotification,
|
||||
BizCollectionProtocol,
|
||||
BizProtocolPartyCustomer,
|
||||
)
|
||||
.outerjoin(
|
||||
BizStorageReleaseReview,
|
||||
and_(
|
||||
_unicode_ci(BizStorageReleaseReview.sample_code)
|
||||
== _unicode_ci(BizProtocolSample.sample_code),
|
||||
BizStorageReleaseReview.tenant_no == tenant_no,
|
||||
BizStorageReleaseReview.reception_source == "cell_storage",
|
||||
BizStorageReleaseReview.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizStorageEntrySmsNotification,
|
||||
and_(
|
||||
BizStorageEntrySmsNotification.storage_review_id == BizStorageReleaseReview.id,
|
||||
BizStorageEntrySmsNotification.tenant_no == tenant_no,
|
||||
BizStorageEntrySmsNotification.del_flag == "0",
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizCollectionProtocol,
|
||||
and_(
|
||||
BizCollectionProtocol.id == BizProtocolSample.collection_protocol_id,
|
||||
BizCollectionProtocol.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.outerjoin(
|
||||
BizProtocolPartyCustomer,
|
||||
and_(
|
||||
BizProtocolPartyCustomer.collection_protocol_id == BizCollectionProtocol.id,
|
||||
BizProtocolPartyCustomer.del_flag == 0,
|
||||
),
|
||||
)
|
||||
.filter(
|
||||
BizProtocolSample.tenant_no == tenant_no,
|
||||
BizProtocolSample.del_flag == 0,
|
||||
BizProtocolSample.collection_protocol_id.in_(sa_select(cell_storage_protocol_ids)),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _ensure_notification(
|
||||
db: Session,
|
||||
review: Optional[BizStorageReleaseReview],
|
||||
tenant_no: str,
|
||||
user_id: Optional[str] = None,
|
||||
) -> Optional[BizStorageEntrySmsNotification]:
|
||||
if not review:
|
||||
return None
|
||||
existing = (
|
||||
db.query(BizStorageEntrySmsNotification)
|
||||
.filter(
|
||||
BizStorageEntrySmsNotification.storage_review_id == review.id,
|
||||
BizStorageEntrySmsNotification.tenant_no == tenant_no,
|
||||
BizStorageEntrySmsNotification.del_flag == "0",
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if existing:
|
||||
return existing
|
||||
|
||||
obj = BizStorageEntrySmsNotification(
|
||||
id=generate_uuid(),
|
||||
storage_review_id=review.id,
|
||||
protocol_id=review.protocol_id or "",
|
||||
sms_notified=0,
|
||||
tenant_no=tenant_no,
|
||||
create_by=user_id,
|
||||
update_by=user_id,
|
||||
)
|
||||
db.add(obj)
|
||||
db.flush()
|
||||
db.commit()
|
||||
db.refresh(obj)
|
||||
return obj
|
||||
|
||||
|
||||
def resolve_notification(
|
||||
db: Session,
|
||||
*,
|
||||
notification_id: str,
|
||||
tenant_no: str,
|
||||
storage_review_id: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
) -> Optional[BizStorageEntrySmsNotification]:
|
||||
"""Find notification by id; fallback to storage_review_id and ensure row exists."""
|
||||
notif = (
|
||||
db.query(BizStorageEntrySmsNotification)
|
||||
.filter(
|
||||
BizStorageEntrySmsNotification.id == notification_id,
|
||||
BizStorageEntrySmsNotification.tenant_no == tenant_no,
|
||||
BizStorageEntrySmsNotification.del_flag == "0",
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if notif:
|
||||
return notif
|
||||
|
||||
if not storage_review_id:
|
||||
return None
|
||||
|
||||
review = (
|
||||
db.query(BizStorageReleaseReview)
|
||||
.filter(
|
||||
BizStorageReleaseReview.id == storage_review_id,
|
||||
BizStorageReleaseReview.tenant_no == tenant_no,
|
||||
BizStorageReleaseReview.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not review:
|
||||
return None
|
||||
return _ensure_notification(db, review, tenant_no=tenant_no, user_id=user_id)
|
||||
|
||||
|
||||
def _fetch_sample_type_name(db: Session, sample_type_id: Optional[str], tenant_no: str) -> str:
|
||||
if not sample_type_id:
|
||||
return ""
|
||||
t = (
|
||||
db.query(BizCellSampleType)
|
||||
.filter(
|
||||
BizCellSampleType.id == sample_type_id,
|
||||
BizCellSampleType.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
return (t.type_name or "") if t else ""
|
||||
|
||||
|
||||
def list_notifications(
|
||||
db: Session,
|
||||
*,
|
||||
page: int = 1,
|
||||
page_size: int = 10,
|
||||
tenant_no: str,
|
||||
keyword: Optional[str] = None,
|
||||
storage_status: Optional[str] = None,
|
||||
sms_notified: Optional[int] = None,
|
||||
user_info=None,
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
if not tenant_no:
|
||||
return [], 0
|
||||
|
||||
q = _base_query(db, tenant_no)
|
||||
|
||||
if keyword and keyword.strip():
|
||||
kw = f"%{keyword.strip()}%"
|
||||
q = q.filter(
|
||||
or_(
|
||||
BizCollectionProtocol.protocol_no.like(kw),
|
||||
BizProtocolPartyCustomer.mother_name.like(kw),
|
||||
BizProtocolSample.sample_code.like(kw),
|
||||
)
|
||||
)
|
||||
|
||||
if storage_status:
|
||||
if storage_status == "yrk":
|
||||
q = q.filter(BizStorageReleaseReview.storage_status == "yrk")
|
||||
elif storage_status == "btg":
|
||||
q = q.filter(BizStorageReleaseReview.review_conclusion == "btg")
|
||||
elif storage_status == "drk":
|
||||
q = q.filter(
|
||||
or_(
|
||||
BizStorageReleaseReview.storage_status == "drk",
|
||||
BizStorageReleaseReview.id.is_(None),
|
||||
)
|
||||
)
|
||||
|
||||
if sms_notified is not None:
|
||||
if sms_notified == 0:
|
||||
q = q.filter(
|
||||
or_(
|
||||
BizStorageEntrySmsNotification.sms_notified == 0,
|
||||
BizStorageEntrySmsNotification.id.is_(None),
|
||||
)
|
||||
)
|
||||
else:
|
||||
q = q.filter(BizStorageEntrySmsNotification.sms_notified == sms_notified)
|
||||
|
||||
if user_info:
|
||||
from app.core.data_scope import apply_data_scope
|
||||
q = apply_data_scope(q, BizProtocolSample, user_info, db, tenant_no)
|
||||
|
||||
total = q.count()
|
||||
page = max(1, page)
|
||||
page_size = min(max(1, page_size), 100)
|
||||
|
||||
rows = (
|
||||
q.order_by(BizProtocolSample.create_time.desc())
|
||||
.offset((page - 1) * page_size)
|
||||
.limit(page_size)
|
||||
.all()
|
||||
)
|
||||
|
||||
sample_type_ids = list({
|
||||
psample.sample_type_id
|
||||
for psample, _, _, _, _ in rows
|
||||
if psample and psample.sample_type_id
|
||||
})
|
||||
type_map: Dict[str, str] = {}
|
||||
if sample_type_ids:
|
||||
for t in (
|
||||
db.query(BizCellSampleType)
|
||||
.filter(BizCellSampleType.id.in_(sample_type_ids), BizCellSampleType.del_flag == 0)
|
||||
.all()
|
||||
):
|
||||
type_map[t.id] = t.type_name or ""
|
||||
|
||||
items: List[Dict[str, Any]] = []
|
||||
for psample, review, notif, proto, party in rows:
|
||||
if notif is None and review is not None:
|
||||
notif = _ensure_notification(db, review, tenant_no=tenant_no)
|
||||
|
||||
sample_type_name = ""
|
||||
if psample and psample.sample_type_id:
|
||||
sample_type_name = type_map.get(psample.sample_type_id, "")
|
||||
|
||||
display_time = ""
|
||||
if review:
|
||||
if review.storage_status == "yrk" and review.storage_time:
|
||||
display_time = _fmt_dt(review.storage_time)
|
||||
elif review.review_time:
|
||||
display_time = _fmt_dt(review.review_time)
|
||||
|
||||
items.append(
|
||||
_row_to_dict(
|
||||
notification_id=(notif.id if notif else ""),
|
||||
storage_review_id=(review.id if review else ""),
|
||||
protocol_id=(notif.protocol_id or "") if notif else "",
|
||||
sms_notified=(notif.sms_notified or 0) if notif else 0,
|
||||
sms_content=(notif.sms_content or "") if notif else "",
|
||||
protocol_no=(proto.protocol_no or "") if proto else "",
|
||||
mother_name=(party.mother_name or "") if party else "",
|
||||
newborn_name=(party.newborn_name or "") if party else "",
|
||||
sample_code=psample.sample_code or "",
|
||||
sample_type_name=sample_type_name,
|
||||
storage_time=display_time,
|
||||
storage_status_label=_storage_status_label(review),
|
||||
collection_protocol_id=(proto.id or "") if proto else "",
|
||||
protocol_status=(proto.protocol_status or "") if proto else "",
|
||||
)
|
||||
)
|
||||
return items, int(total)
|
||||
|
||||
|
||||
def toggle_notification_status(
|
||||
db: Session,
|
||||
*,
|
||||
notification_id: str,
|
||||
tenant_no: str,
|
||||
sms_notified: int,
|
||||
user_id: Optional[str] = None,
|
||||
storage_review_id: Optional[str] = None,
|
||||
) -> Optional[BizStorageEntrySmsNotification]:
|
||||
notif = resolve_notification(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
storage_review_id=storage_review_id,
|
||||
user_id=user_id,
|
||||
)
|
||||
if not notif:
|
||||
return None
|
||||
|
||||
notif.sms_notified = sms_notified
|
||||
if sms_notified == 1:
|
||||
notif.notified_by = user_id
|
||||
notif.notified_time = datetime.now()
|
||||
_user = db.query(SysUser.nick_name).filter(SysUser.id == user_id).first()
|
||||
notif.notified_by_name = _user.nick_name if _user else None
|
||||
else:
|
||||
notif.notified_by = None
|
||||
notif.notified_by_name = None
|
||||
notif.notified_time = None
|
||||
notif.update_by = user_id
|
||||
notif.update_time = datetime.now()
|
||||
db.commit()
|
||||
db.refresh(notif)
|
||||
return notif
|
||||
|
||||
|
||||
def generate_sms_content(
|
||||
db: Session,
|
||||
*,
|
||||
notification_id: str,
|
||||
tenant_no: str,
|
||||
storage_review_id: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
) -> Optional[str]:
|
||||
notif = resolve_notification(
|
||||
db,
|
||||
notification_id=notification_id,
|
||||
tenant_no=tenant_no,
|
||||
storage_review_id=storage_review_id,
|
||||
user_id=user_id,
|
||||
)
|
||||
if not notif:
|
||||
return None
|
||||
|
||||
review = (
|
||||
db.query(BizStorageReleaseReview)
|
||||
.filter(
|
||||
BizStorageReleaseReview.id == notif.storage_review_id,
|
||||
BizStorageReleaseReview.tenant_no == tenant_no,
|
||||
BizStorageReleaseReview.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if not review:
|
||||
return None
|
||||
|
||||
mother_name = ""
|
||||
proto = (
|
||||
db.query(BizCollectionProtocol)
|
||||
.filter(
|
||||
BizCollectionProtocol.id == review.protocol_id,
|
||||
BizCollectionProtocol.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if proto:
|
||||
party = (
|
||||
db.query(BizProtocolPartyCustomer)
|
||||
.filter(
|
||||
BizProtocolPartyCustomer.collection_protocol_id == proto.id,
|
||||
BizProtocolPartyCustomer.del_flag == 0,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if party:
|
||||
mother_name = party.mother_name or ""
|
||||
|
||||
sample_code = review.sample_code or ""
|
||||
|
||||
# 短信模板:区分已入库、拒绝入库、待入库确认
|
||||
if review.storage_status == "yrk":
|
||||
storage_date = _fmt_dt(review.storage_time)[:10] if review.storage_time else ""
|
||||
content = (
|
||||
f"尊敬的{mother_name}女士,您的样本(编码:{sample_code})"
|
||||
f"已于{storage_date}完成入库处理。如有疑问请联系客服。"
|
||||
)
|
||||
elif review.review_conclusion == "btg":
|
||||
content = (
|
||||
f"尊敬的{mother_name}女士,您的样本(编码:{sample_code})"
|
||||
f"入库审核未通过。如有疑问请联系客服。"
|
||||
)
|
||||
else:
|
||||
return "暂无短信内容,样本尚未完成入库确认"
|
||||
|
||||
notif.sms_content = content
|
||||
notif.update_time = datetime.now()
|
||||
db.commit()
|
||||
db.refresh(notif)
|
||||
return content
|
||||
@@ -34,6 +34,22 @@ _RECEPTION_SOURCE_LABELS = {
|
||||
}
|
||||
_REVIEW_CONCLUSION_LABELS = {"tg": "通过", "btg": "不通过"}
|
||||
_STORAGE_STATUS_LABELS = {"drk": "待入库", "yrk": "已入库"}
|
||||
_PROTOCOL_STATUS_LABELS = {
|
||||
"dsx": "待生效",
|
||||
"sxz": "生效中",
|
||||
"ygq": "已过期",
|
||||
"yzf": "已作废",
|
||||
"zky": "转科研",
|
||||
}
|
||||
_DONATION_STATUS_LABELS = {
|
||||
"dsx": "待生效",
|
||||
"sxz": "生效中",
|
||||
"ygq": "已过期",
|
||||
"yzf": "已作废",
|
||||
"zckc": "转细胞存储",
|
||||
}
|
||||
_QC_WORK_ORDER_STATUS_LABELS = {"dpz": "待配置", "ypz": "已配置", "ywc": "已完成"}
|
||||
_PRODUCTION_WORK_ORDER_STATUS_LABELS = {"dpz": "待配置", "jxz": "进行中", "ywc": "已完成"}
|
||||
|
||||
|
||||
def _fmt_dt(t: Optional[datetime]) -> str:
|
||||
@@ -159,7 +175,7 @@ def list_reviews(
|
||||
.limit(page_size)
|
||||
.all()
|
||||
)
|
||||
items = [_row_to_dict(r) for r in rows]
|
||||
items = _enrich_review_list_items(db, [_row_to_dict(r) for r in rows])
|
||||
return {
|
||||
"list": items,
|
||||
"total": int(total),
|
||||
@@ -169,6 +185,87 @@ def list_reviews(
|
||||
}
|
||||
|
||||
|
||||
def _enrich_review_list_items(db: Session, items: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
||||
if not items:
|
||||
return items
|
||||
from app.crud.qc_work_order import _enrich_work_order_list_items
|
||||
|
||||
items = _enrich_work_order_list_items(db, items)
|
||||
|
||||
cell_pids = [
|
||||
x["protocolId"]
|
||||
for x in items
|
||||
if (x.get("receptionSource") or "cell_storage") != "research_donation" and x.get("protocolId")
|
||||
]
|
||||
donation_pids = [
|
||||
x["protocolId"]
|
||||
for x in items
|
||||
if (x.get("receptionSource") or "") == "research_donation" and x.get("protocolId")
|
||||
]
|
||||
|
||||
proto_map: Dict[str, BizCollectionProtocol] = {}
|
||||
if cell_pids:
|
||||
proto_map = {
|
||||
p.id: p
|
||||
for p in db.query(BizCollectionProtocol)
|
||||
.filter(BizCollectionProtocol.id.in_(cell_pids), BizCollectionProtocol.del_flag == 0)
|
||||
.all()
|
||||
}
|
||||
party_map: Dict[str, str] = {}
|
||||
if cell_pids:
|
||||
for party in (
|
||||
db.query(BizProtocolPartyCustomer)
|
||||
.filter(
|
||||
BizProtocolPartyCustomer.collection_protocol_id.in_(cell_pids),
|
||||
BizProtocolPartyCustomer.del_flag == 0,
|
||||
)
|
||||
.all()
|
||||
):
|
||||
party_map[party.collection_protocol_id] = party.mother_name or ""
|
||||
|
||||
donation_map: Dict[str, BizResearchDonation] = {}
|
||||
if donation_pids:
|
||||
donation_map = {
|
||||
d.id: d
|
||||
for d in db.query(BizResearchDonation)
|
||||
.filter(BizResearchDonation.id.in_(donation_pids), BizResearchDonation.del_flag == 0)
|
||||
.all()
|
||||
}
|
||||
dparty_map: Dict[str, str] = {}
|
||||
if donation_pids:
|
||||
for party in (
|
||||
db.query(BizResearchDonationParty)
|
||||
.filter(
|
||||
BizResearchDonationParty.research_donation_id.in_(donation_pids),
|
||||
BizResearchDonationParty.del_flag == 0,
|
||||
)
|
||||
.all()
|
||||
):
|
||||
dparty_map[party.research_donation_id] = party.mother_name or ""
|
||||
|
||||
for item in items:
|
||||
source = item.get("receptionSource") or "cell_storage"
|
||||
pid = item.get("protocolId") or ""
|
||||
item.setdefault("motherName", "")
|
||||
item.setdefault("protocolStatus", "")
|
||||
item.setdefault("protocolStatusLabel", "")
|
||||
if source == "research_donation":
|
||||
donation = donation_map.get(pid)
|
||||
if donation:
|
||||
st = donation.donation_status or ""
|
||||
item["protocolStatus"] = st
|
||||
item["protocolStatusLabel"] = _DONATION_STATUS_LABELS.get(st, st)
|
||||
item["motherName"] = dparty_map.get(pid, "")
|
||||
else:
|
||||
proto = proto_map.get(pid)
|
||||
if proto:
|
||||
st = getattr(proto, "protocol_status", "") or ""
|
||||
item["protocolStatus"] = st
|
||||
item["protocolStatusLabel"] = _PROTOCOL_STATUS_LABELS.get(st, st)
|
||||
item["motherName"] = party_map.get(pid, "")
|
||||
return items
|
||||
|
||||
|
||||
def _get_user_name(db: Session, user_id: str) -> str:
|
||||
u = db.query(SysUser).filter(SysUser.id == user_id).first()
|
||||
return (u.nick_name or "") if u else ""
|
||||
@@ -201,8 +298,34 @@ def get_review_detail(db: Session, review_id: str, tenant_no: str) -> Optional[D
|
||||
transport_info = _build_research_donation_transport_info(db, rev)
|
||||
result["transportInfo"] = transport_info
|
||||
|
||||
reception_info = _build_reception_info(db, rev)
|
||||
result["receptionInfo"] = reception_info
|
||||
from app.crud import sample_reception as sample_reception_svc
|
||||
|
||||
reception_detail = sample_reception_svc.get_reception_by_id(
|
||||
db, rev.reception_id or "", tenant_no
|
||||
)
|
||||
if reception_detail:
|
||||
result["reception"] = reception_detail
|
||||
result["receptionInfo"] = {
|
||||
"receptionTime": reception_detail.get("receptionTime") or "",
|
||||
"handlerName": reception_detail.get("handlerName") or "",
|
||||
"receiveTemperature": reception_detail.get("receiveTemperature") or "",
|
||||
"volumeMl": reception_detail.get("volumeMl"),
|
||||
"netWeightG": reception_detail.get("netWeightG"),
|
||||
"acceptConclusion": reception_detail.get("acceptConclusion") or "",
|
||||
"acceptConclusionLabel": reception_detail.get("acceptConclusionLabel") or "",
|
||||
"remark": reception_detail.get("remark") or "",
|
||||
"checkResults": reception_detail.get("checkResults") or [],
|
||||
"receiveAttachments": reception_detail.get("receiveAttachments") or "",
|
||||
"receiveAttachmentFiles": reception_detail.get("receiveAttachmentFiles") or [],
|
||||
"transportType": reception_detail.get("transportType") or "",
|
||||
"expressCompanyName": reception_detail.get("expressCompanyName") or "",
|
||||
"waybillNo": reception_detail.get("waybillNo") or "",
|
||||
"carrierName": reception_detail.get("carrierName") or "",
|
||||
"carrierPhone": reception_detail.get("carrierPhone") or "",
|
||||
"etaTime": reception_detail.get("etaTime") or "",
|
||||
}
|
||||
else:
|
||||
result["receptionInfo"] = _build_reception_info(db, rev)
|
||||
|
||||
qc_info = _build_qc_info(db, rev, tenant_no)
|
||||
result["qcInfo"] = qc_info
|
||||
@@ -452,9 +575,11 @@ def _build_qc_info(db: Session, rev: BizStorageReleaseReview, tenant_no: str) ->
|
||||
"conclusion": getattr(t, "conclusion", "") or "",
|
||||
"conclusionLabel": _conclusion_labels.get(getattr(t, "conclusion", "") or "", getattr(t, "conclusion", "") or ""),
|
||||
})
|
||||
wo_status = wo.work_order_status or ""
|
||||
return {
|
||||
"workOrderNo": wo.work_order_no or "",
|
||||
"workOrderStatus": wo.work_order_status or "",
|
||||
"workOrderStatus": wo_status,
|
||||
"workOrderStatusLabel": _QC_WORK_ORDER_STATUS_LABELS.get(wo_status, wo_status),
|
||||
"tasks": task_list,
|
||||
}
|
||||
|
||||
@@ -492,9 +617,11 @@ def _build_production_info(db: Session, rev: BizStorageReleaseReview, tenant_no:
|
||||
"startedTime": _fmt_dt(t.started_time),
|
||||
"completedTime": _fmt_dt(t.completed_time),
|
||||
})
|
||||
pwo_status = pwo.work_order_status or ""
|
||||
return {
|
||||
"workOrderNo": pwo.work_order_no or "",
|
||||
"workOrderStatus": pwo.work_order_status or "",
|
||||
"workOrderStatus": pwo_status,
|
||||
"workOrderStatusLabel": _PRODUCTION_WORK_ORDER_STATUS_LABELS.get(pwo_status, pwo_status),
|
||||
"tasks": task_list,
|
||||
}
|
||||
|
||||
@@ -631,3 +758,57 @@ def batch_store_samples(
|
||||
except Exception:
|
||||
fail += 1
|
||||
return {"success": success, "fail": fail}
|
||||
|
||||
|
||||
def get_storage_release_map_for_samples(
|
||||
db: Session,
|
||||
sample_ids: List[str],
|
||||
tenant_no: str,
|
||||
*,
|
||||
sample_code_by_id: Optional[Dict[str, str]] = None,
|
||||
) -> Dict[str, Dict[str, Any]]:
|
||||
"""按样本批量返回存储放行审核摘要。
|
||||
|
||||
当传入 sample_code_by_id 时,按租户 + 样本编码关联存储放行审核记录,
|
||||
返回以 sample_id 为 key 的审核信息映射。
|
||||
"""
|
||||
if not tenant_no or not sample_code_by_id:
|
||||
return {}
|
||||
|
||||
codes = list({(c or "").strip() for c in sample_code_by_id.values() if (c or "").strip()})
|
||||
if not codes:
|
||||
return {}
|
||||
|
||||
rows = (
|
||||
db.query(BizStorageReleaseReview)
|
||||
.filter(
|
||||
BizStorageReleaseReview.tenant_no == tenant_no,
|
||||
BizStorageReleaseReview.del_flag == 0,
|
||||
BizStorageReleaseReview.sample_code.in_(codes),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
code_to_review: Dict[str, BizStorageReleaseReview] = {}
|
||||
for r in rows:
|
||||
code = (r.sample_code or "").strip()
|
||||
if code and code not in code_to_review:
|
||||
code_to_review[code] = r
|
||||
|
||||
out: Dict[str, Dict[str, Any]] = {}
|
||||
for sid, raw_code in sample_code_by_id.items():
|
||||
code = (raw_code or "").strip()
|
||||
if not code:
|
||||
continue
|
||||
rev = code_to_review.get(code)
|
||||
if not rev or not (rev.review_conclusion or "").strip():
|
||||
continue
|
||||
rc = rev.review_conclusion or ""
|
||||
out[sid] = {
|
||||
"reviewConclusion": rc,
|
||||
"reviewConclusionLabel": _REVIEW_CONCLUSION_LABELS.get(rc, rc),
|
||||
"reviewByName": rev.review_by_name or "",
|
||||
"reviewTime": _fmt_dt(rev.review_time),
|
||||
"reviewRemark": rev.review_remark or "",
|
||||
"reviewAttachments": rev.review_attachments or "",
|
||||
}
|
||||
return out
|
||||
+1
@@ -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
|
||||
+1
@@ -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": "L90"}, {"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": "L158"}, {"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": "L205"}, {"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_164", "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": "L164"}, {"id": "crud_consumable_stock_log_rationale_216", "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": "L216"}], "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
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_storage_release_review_py", "label": "storage_release_review.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L1"}, {"id": "crud_storage_release_review_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L55"}, {"id": "crud_storage_release_review_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L59"}, {"id": "crud_storage_release_review_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L65"}, {"id": "crud_storage_release_review_create_review_from_reception", "label": "create_review_from_reception()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L93"}, {"id": "crud_storage_release_review_list_reviews", "label": "list_reviews()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L131"}, {"id": "crud_storage_release_review_enrich_review_list_items", "label": "_enrich_review_list_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L188"}, {"id": "crud_storage_release_review_get_user_name", "label": "_get_user_name()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L269"}, {"id": "crud_storage_release_review_get_review_detail", "label": "get_review_detail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L274"}, {"id": "crud_storage_release_review_build_cell_storage_protocol_info", "label": "_build_cell_storage_protocol_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L339"}, {"id": "crud_storage_release_review_build_research_donation_protocol_info", "label": "_build_research_donation_protocol_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L396"}, {"id": "crud_storage_release_review_build_cell_storage_transport_info", "label": "_build_cell_storage_transport_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L453"}, {"id": "crud_storage_release_review_build_research_donation_transport_info", "label": "_build_research_donation_transport_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L487"}, {"id": "crud_storage_release_review_build_reception_info", "label": "_build_reception_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L521"}, {"id": "crud_storage_release_review_build_qc_info", "label": "_build_qc_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L543"}, {"id": "crud_storage_release_review_build_production_info", "label": "_build_production_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L587"}, {"id": "crud_storage_release_review_submit_review", "label": "submit_review()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L629"}, {"id": "crud_storage_release_review_batch_submit_review", "label": "batch_submit_review()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L664"}, {"id": "crud_storage_release_review_store_sample", "label": "store_sample()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L693"}, {"id": "crud_storage_release_review_batch_store_samples", "label": "batch_store_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py", "source_location": "L745"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_storage_release_review_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxwLine truncated
|
||||
+1
@@ -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": "L166"}, {"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": "L218"}, {"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": "L230"}, {"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": "L286"}, {"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": "L361"}, {"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": "L432"}, {"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": "L520"}], "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
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_material_py", "label": "material.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L1"}, {"id": "api_material_materialbody", "label": "MaterialBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L23"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_material_materialupdatebody", "label": "MaterialUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L37"}, {"id": "api_material_stockinbody", "label": "StockInBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L51"}, {"id": "api_material_stockoutbody", "label": "StockOutBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L58"}, {"id": "api_material_batchstockinitem", "label": "BatchStockInItem", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L67"}, {"id": "api_material_batchstockinbody", "label": "BatchStockInBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L74"}, {"id": "api_material_batchstockoutitem", "label": "BatchStockOutItem", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L81"}, {"id": "api_material_batchstockoutbody", "label": "BatchStockOutBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L88"}, {"id": "api_material_list_materials", "label": "list_materials()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L101"}, {"id": "api_material_material_options", "label": "material_options()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L124"}, {"id": "api_material_create_material", "label": "create_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L136"}, {"id": "api_material_update_material", "label": "update_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L156"}, {"id": "api_material_delete_material", "label": "delete_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L177"}, {"id": "api_material_batch_stock_in_material", "label": "batch_stock_in_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L194"}, {"id": "api_material_batch_stock_out_material", "label": "batch_stock_out_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L228"}, {"id": "api_material_stock_in_material", "label": "stock_in_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L264"}, {"id": "api_material_stock_out_material", "label": "stock_out_material()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L291"}, {"id": "api_material_list_stock_logs", "label": "list_stock_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L322"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_api_material_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_material_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_material_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_material_py", "target": "pydantic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py", "source_location": "L6", "weight": 1.0}, {"sourLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "label": "storage_release_review.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L1"}, {"id": "api_storage_release_review_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L20"}, {"id": "api_storage_release_review_get_current_user_id", "label": "_get_current_user_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L30"}, {"id": "api_storage_release_review_list_storage_release_reviews", "label": "list_storage_release_reviews()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L38"}, {"id": "api_storage_release_review_get_storage_release_review_detail", "label": "get_storage_release_review_detail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L69"}, {"id": "api_storage_release_review_submit_single_review", "label": "submit_single_review()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L87"}, {"id": "api_storage_release_review_batch_review", "label": "batch_review()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L116"}, {"id": "api_storage_release_review_store_single_sample", "label": "store_single_sample()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L144"}, {"id": "api_storage_release_review_batch_store_samples", "label": "batch_store_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L169"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "app_core_database", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "app_core_menu_guard", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "app_core_response", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "app_crud", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_release_review_py", "target": "app_schemas_storage_release_review", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_storage_releLine truncated
|
||||
+1
@@ -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": "L83"}, {"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": "L98"}, {"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": "L112"}, {"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": "L122"}, {"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": "L150"}, {"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": "L179"}, {"id": "api_production_stockinbody", "label": "StockInBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L191"}, {"id": "api_production_stockoutbody", "label": "StockOutBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L197"}, {"id": "api_production_batchstockinitem", "label": "BatchStockInItem", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L205"}, {"id": "api_production_batchstockinbody", "label": "BatchStockInBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L212"}, {"id": "api_production_batchstockoutitem", "label": "BatchStockOutItem", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L218"}, {"id": "api_production_batchstockoutbody", "label": "BatchStockOutBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L224"}, {"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": "L233"}, {"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": "L255"}, {"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": "L279"}, {"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": "L297"}, {"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": "L316"}, {"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": "L335"}, {"id": "api_production_reagentcreatebody", "label": "ReagentCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L361"}, {"id": "api_production_reagentupdatebody", "label": "ReagentUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py", "source_location": "L375"}, {"id": "api_production_list_reagents", "label": "list_reagents()", "file_type": "code", "source_filLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_qc_py", "label": "qc.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L1"}, {"id": "api_qc_thirdpartycompanybody", "label": "ThirdPartyCompanyBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L33"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_qc_thirdpartycompanyupdatebody", "label": "ThirdPartyCompanyUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L50"}, {"id": "api_qc_list_qc_third_party_companies", "label": "list_qc_third_party_companies()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L68"}, {"id": "api_qc_list_qc_third_party_company_options", "label": "list_qc_third_party_company_options()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L90"}, {"id": "api_qc_create_qc_third_party_company", "label": "create_qc_third_party_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L104"}, {"id": "api_qc_update_qc_third_party_company", "label": "update_qc_third_party_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L138"}, {"id": "api_qc_delete_qc_third_party_company", "label": "delete_qc_third_party_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L174"}, {"id": "api_qc_thirdpartyitembody", "label": "ThirdPartyItemBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L194"}, {"id": "api_qc_thirdpartyitemupdatebody", "label": "ThirdPartyItemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L206"}, {"id": "api_qc_list_qc_third_party_items", "label": "list_qc_third_party_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L219"}, {"id": "api_qc_list_qc_third_party_items_active", "label": "list_qc_third_party_items_active()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L248"}, {"id": "api_qc_create_qc_third_party_item", "label": "create_qc_third_party_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L263"}, {"id": "api_qc_update_qc_third_party_item", "label": "update_qc_third_party_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L292"}, {"id": "api_qc_delete_qc_third_party_item", "label": "delete_qc_third_party_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L323"}, {"id": "api_qc_labtestitembody", "label": "LabTestItemBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L343"}, {"id": "api_qc_labtestitemupdatebody", "label": "LabTestItemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L354"}, {"id": "api_qc_itemparambody", "label": "ItemParamBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L368"}, {"id": "api_qc_taskresultbody", "label": "TaskResultBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L373"}, {"id": "api_qc_taskcompletewithresultbody", "label": "TaskCompleteWithResultBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L378"}, {"id": "api_qc_list_qc_lab_test_items", "label": "list_qc_lab_test_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L388"}, {"id": "api_qc_list_qc_lab_test_items_active", "label": "list_qc_lab_test_items_active()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L410"}, {"id": "api_qc_create_qc_lab_test_item", "label": "create_qc_lab_test_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L424"}, {"id": "api_qc_update_qc_lab_test_item", "label": "update_qc_lab_test_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L452"}, {"id": "api_qLine truncated
|
||||
+1
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_reception_py", "label": "sample_reception.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L1"}, {"id": "api_sample_reception_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L22"}, {"id": "api_sample_reception_get_current_user_id", "label": "_get_current_user_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L32"}, {"id": "api_sample_reception_page_payload", "label": "_page_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L39"}, {"id": "api_sample_reception_checkitembody", "label": "CheckItemBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L52"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_sample_reception_checkitemupdatebody", "label": "CheckItemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L62"}, {"id": "api_sample_reception_list_check_items", "label": "list_check_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L73"}, {"id": "api_sample_reception_list_active_check_items", "label": "list_active_check_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L110"}, {"id": "api_sample_reception_create_check_item", "label": "create_check_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L125"}, {"id": "api_sample_reception_update_check_item", "label": "update_check_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L156"}, {"id": "api_sample_reception_delete_check_item", "label": "delete_check_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L186"}, {"id": "api_sample_reception_list_pending_samples", "label": "list_pending_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L207"}, {"id": "api_sample_reception_list_received_samples", "label": "list_received_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L229"}, {"id": "api_sample_reception_get_sample_reception_detail", "label": "get_sample_reception_detail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L251"}, {"id": "api_sample_reception_receptionchecksubmit", "label": "ReceptionCheckSubmit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L268"}, {"id": "api_sample_reception_samplereceptionupdatebody", "label": "SampleReceptionUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L275"}, {"id": "api_sample_reception_samplereceptioncreatebody", "label": "SampleReceptionCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L290"}, {"id": "api_sample_reception_post_sample_reception", "label": "post_sample_reception()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L309"}, {"id": "api_sample_reception_put_sample_reception", "label": "put_sample_reception()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L355"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_reception_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_reception_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_reception_py", "taLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "label": "main.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L1"}, {"id": "app_main_lifespan", "label": "lifespan()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L17"}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L83"}, {"id": "app_main_root", "label": "root()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L105"}, {"id": "app_main_health_check", "label": "health_check()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L110"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "contextlib", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "logging", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "fastapi_middleware_cors", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_core_config", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_core_database", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_core_api_request_log_middleware", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_core_api_crypto_middleware", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_api", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_main_lifespan", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L17", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_main_mask_secret", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L83", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_main_root", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L105", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_main_py", "target": "app_main_health_check", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L110", "weight": 1.0}], "raw_calls": [{"caller_nid": "app_main_lifespan", "callee": "ensure_initialized", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L21"}, {"caller_nid": "app_main_lifespan", "callee": "init_scheduled_tasks", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/main.py", "source_location": "L26"}, {"caller_nid": "app_main_lifespan", "callee": "warning", "soLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "label": "sample_sms_notification.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L1"}, {"id": "crud_sample_sms_notification_unicode_ci", "label": "_unicode_ci()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L25"}, {"id": "crud_sample_sms_notification_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L29"}, {"id": "crud_sample_sms_notification_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L35"}, {"id": "crud_sample_sms_notification_accept_conclusion_label", "label": "_accept_conclusion_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L39"}, {"id": "crud_sample_sms_notification_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L43"}, {"id": "crud_sample_sms_notification_base_query", "label": "_base_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L77"}, {"id": "crud_sample_sms_notification_ensure_notification", "label": "_ensure_notification()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L126"}, {"id": "crud_sample_sms_notification_fetch_sample_type_name", "label": "_fetch_sample_type_name()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L160"}, {"id": "crud_sample_sms_notification_list_notifications", "label": "list_notifications()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L174"}, {"id": "crud_sample_sms_notification_toggle_notification_status", "label": "toggle_notification_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L272"}, {"id": "crud_sample_sms_notification_generate_sms_content", "label": "generate_sms_content()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L302"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_0Line truncated
|
||||
+1
@@ -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": "L90"}, {"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": "L158"}, {"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": "L205"}, {"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_164", "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": "L164"}, {"id": "crud_reagent_stock_log_rationale_216", "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": "L216"}], "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
|
||||
+1
@@ -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": "L166"}, {"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": "L218"}, {"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": "L230"}, {"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": "L250"}, {"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": "L306"}, {"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": "L381"}, {"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": "L452"}, {"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": "L540"}, {"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
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "label": "sample_sms_notification.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L1"}, {"id": "crud_sample_sms_notification_unicode_ci", "label": "_unicode_ci()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L25"}, {"id": "crud_sample_sms_notification_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L29"}, {"id": "crud_sample_sms_notification_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L35"}, {"id": "crud_sample_sms_notification_accept_conclusion_label", "label": "_accept_conclusion_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L39"}, {"id": "crud_sample_sms_notification_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L43"}, {"id": "crud_sample_sms_notification_base_query", "label": "_base_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L77"}, {"id": "crud_sample_sms_notification_ensure_notification", "label": "_ensure_notification()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L126"}, {"id": "crud_sample_sms_notification_resolve_notification", "label": "resolve_notification()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L160"}, {"id": "crud_sample_sms_notification_fetch_sample_type_name", "label": "_fetch_sample_type_name()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L198"}, {"id": "crud_sample_sms_notification_list_notifications", "label": "list_notifications()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L212"}, {"id": "crud_sample_sms_notification_toggle_notification_status", "label": "toggle_notification_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L310"}, {"id": "crud_sample_sms_notification_generate_sms_content", "label": "generate_sms_content()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L339"}, {"id": "crud_sample_sms_notification_rationale_168", "label": "Find notification by id; fallback to sample_reception_id and ensure row exists.", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L168"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_sms_notification_py", "target": "app_core_utils", "relaLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "label": "__init__.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L1"}, {"id": "api_init_rationale_1", "label": "API \u8def\u7531\u5305\uff08\u9aa8\u67b6\uff1a\u516c\u5171\u9274\u6743 + \u9759\u6001\u83dc\u5355 + \u8fd0\u8425\u7aef\u5360\u4f4d\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_public", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_menu", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_admin", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_workflow", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_basic_info", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_collection_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_leave", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_operations", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_ethnic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_sample_reception", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_qc", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_research_donation", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_production", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L14", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_pilot_service", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L15", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_insurance_company", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L16", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_init_py", "target": "app_api_material", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py", "source_location": "L17", "weight": 1.0}, {"source": "usLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_sample_reception_py", "label": "sample_reception.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L1"}, {"id": "crud_sample_reception_donation_sample_id_col", "label": "_donation_sample_id_col()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L34"}, {"id": "crud_sample_reception_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L39"}, {"id": "crud_sample_reception_dec", "label": "_dec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L43"}, {"id": "crud_sample_reception_reception_to_dict", "label": "_reception_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L49"}, {"id": "crud_sample_reception_sample_detail_rows_query", "label": "_sample_detail_rows_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L73"}, {"id": "crud_sample_reception_donation_sample_detail_rows_query", "label": "_donation_sample_detail_rows_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L107"}, {"id": "crud_sample_reception_donation_sample_pending_query", "label": "_donation_sample_pending_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L141"}, {"id": "crud_sample_reception_donation_rows_to_sample_list_items", "label": "_donation_rows_to_sample_list_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L172"}, {"id": "crud_sample_reception_sample_pending_query", "label": "_sample_pending_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L253"}, {"id": "crud_sample_reception_rows_to_sample_list_items", "label": "_rows_to_sample_list_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L287"}, {"id": "crud_sample_reception_list_pending_protocol_samples", "label": "list_pending_protocol_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L374"}, {"id": "crud_sample_reception_list_received_protocol_samples", "label": "list_received_protocol_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L436"}, {"id": "crud_sample_reception_get_reception_by_id", "label": "get_reception_by_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L564"}, {"id": "crud_sample_reception_create_sample_reception", "label": "create_sample_reception()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L632"}, {"id": "crud_sample_reception_update_sample_reception", "label": "update_sample_reception()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L864"}, {"id": "crud_sample_reception_reception_detail_item", "label": "_reception_detail_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L947"}, {"id": "crud_sample_reception_reception_sample_code", "label": "_reception_sample_code()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L964"}, {"id": "crud_sample_reception_get_receptions_map_for_samples", "label": "get_receptions_map_for_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L979"}, {"id": "crud_sample_reception_get_receptions_map_for_donation_samples", "label": "get_receptions_map_for_donation_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_location": "L1024"}, {"id": "crud_sample_reception_rationale_35", "label": "\u6350\u8d60\u6837\u672c ID \u4e0e biz_sample_reception.donation_sample_id \u6bd4\u8f83\u65f6\u7edf\u4e00\u6392\u5e8f\u89c4\u5219\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py", "source_locationLine truncated
|
||||
+1
@@ -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
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "label": "sample_sms_notification.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L1"}, {"id": "api_sample_sms_notification_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L18"}, {"id": "api_sample_sms_notification_get_current_user_id", "label": "_get_current_user_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L28"}, {"id": "api_sample_sms_notification_page_payload", "label": "_page_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L35"}, {"id": "api_sample_sms_notification_togglestatusbody", "label": "ToggleStatusBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L45"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_sample_sms_notification_list_notifications", "label": "list_notifications()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L52"}, {"id": "api_sample_sms_notification_toggle_status", "label": "toggle_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L81"}, {"id": "api_sample_sms_notification_generate_sms", "label": "generate_sms()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L107"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "pydantic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_core_database", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_core_menu_guard", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_core_response", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_crud", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_crud_collection_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notificatioLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "label": "sample_sms_notification.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L1"}, {"id": "api_sample_sms_notification_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L18"}, {"id": "api_sample_sms_notification_get_current_user_id", "label": "_get_current_user_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L28"}, {"id": "api_sample_sms_notification_page_payload", "label": "_page_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L35"}, {"id": "api_sample_sms_notification_togglestatusbody", "label": "ToggleStatusBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L45"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_sample_sms_notification_list_notifications", "label": "list_notifications()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L53"}, {"id": "api_sample_sms_notification_toggle_status", "label": "toggle_status()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L82"}, {"id": "api_sample_sms_notification_generate_sms", "label": "generate_sms()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L109"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "fastapi", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "pydantic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_core_database", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_core_menu_guard", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_core_response", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_crud", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_crud_collection_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_api_sample_sms_notification_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notificatioLine truncated
|
||||
+3
-1
@@ -10,7 +10,7 @@ from app.core.database import SessionLocal
|
||||
from app.core.api_request_log_middleware import ApiRequestLogMiddleware
|
||||
from app.core.api_crypto_middleware import ApiCryptoMiddleware
|
||||
from app.models import models # noqa: F401
|
||||
from app.api import public_router, menu_router, admin_router, workflow_router, basic_info_router, collection_protocol_router, leave_router, operations_router, ethnic_router, sample_reception_router, qc_router, research_donation_router, production_router, pilot_service_router, insurance_company_router, material_router, storage_release_review_router
|
||||
from app.api import public_router, menu_router, admin_router, workflow_router, basic_info_router, collection_protocol_router, leave_router, operations_router, ethnic_router, sample_reception_router, qc_router, research_donation_router, production_router, pilot_service_router, insurance_company_router, material_router, storage_release_review_router, sample_sms_notification_router, storage_entry_sms_notification_router
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
@@ -75,6 +75,8 @@ app.include_router(pilot_service_router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(insurance_company_router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(material_router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(storage_release_review_router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(sample_sms_notification_router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(storage_entry_sms_notification_router, prefix=settings.API_V1_PREFIX)
|
||||
|
||||
logger = logging.getLogger("sqxp")
|
||||
|
||||
|
||||
@@ -1096,6 +1096,51 @@ class BizSampleReception(Base):
|
||||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
|
||||
|
||||
|
||||
class BizSampleSmsNotification(Base):
|
||||
__tablename__ = "biz_sample_sms_notification"
|
||||
|
||||
id = Column(String(64), primary_key=True)
|
||||
sample_reception_id = Column(String(64), nullable=False, comment="关联 biz_sample_reception.id")
|
||||
protocol_id = Column(String(64), comment="关联采集协议单ID")
|
||||
sms_content = Column(String(500), comment="提取的短信内容")
|
||||
sms_notified = Column(SmallInteger, default=0, comment="0=未通知 1=已通知")
|
||||
notified_by = Column(String(64), comment="通知操作人ID")
|
||||
notified_time = Column(DateTime, comment="通知时间")
|
||||
tenant_no = Column(String(32))
|
||||
order_num = Column(Integer, default=0)
|
||||
remark = Column(String(500))
|
||||
create_by = Column(String(64))
|
||||
create_dept_id = Column(String(64))
|
||||
create_time = Column(DateTime, default=datetime.now)
|
||||
update_by = Column(String(64))
|
||||
update_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
del_flag = Column(String(1), default="0")
|
||||
|
||||
|
||||
class BizStorageEntrySmsNotification(Base):
|
||||
"""样本入库短信通知 biz_storage_entry_sms_notification"""
|
||||
|
||||
__tablename__ = "biz_storage_entry_sms_notification"
|
||||
|
||||
id = Column(String(64), primary_key=True)
|
||||
storage_review_id = Column(String(64), nullable=False, comment="关联 biz_storage_release_review.id")
|
||||
protocol_id = Column(String(64), comment="关联采集协议单ID")
|
||||
sms_content = Column(String(500), comment="生成的短信内容")
|
||||
sms_notified = Column(SmallInteger, default=0, comment="0=未通知 1=已通知")
|
||||
notified_by = Column(String(64), comment="通知操作人ID")
|
||||
notified_by_name = Column(String(64), comment="通知操作人姓名")
|
||||
notified_time = Column(DateTime, comment="通知时间")
|
||||
tenant_no = Column(String(32))
|
||||
order_num = Column(Integer, default=0)
|
||||
remark = Column(String(500))
|
||||
create_by = Column(String(64))
|
||||
create_dept_id = Column(String(64))
|
||||
create_time = Column(DateTime, default=datetime.now)
|
||||
update_by = Column(String(64))
|
||||
update_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
del_flag = Column(String(1), default="0")
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 质量检测 — 第三方/实验室主数据、质检工单、质检任务
|
||||
# =============================================================================
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+4598
-3768
File diff suppressed because it is too large.
Load diff
@@ -1,12 +1,12 @@
|
||||
# Graph Report - app (2026-05-23)
|
||||
|
||||
## Corpus Check
|
||||
- 142 files · ~130,208 words
|
||||
- 144 files · ~132,165 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 2542 nodes · 10216 edges · 51 communities detected
|
||||
- Extraction: 41% EXTRACTED · 59% INFERRED · 0% AMBIGUOUS · INFERRED: 6029 edges (avg confidence: 0.63)
|
||||
- 2566 nodes · 10300 edges · 53 communities detected
|
||||
- Extraction: 41% EXTRACTED · 59% INFERRED · 0% AMBIGUOUS · INFERRED: 6067 edges (avg confidence: 0.63)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
@@ -55,24 +55,26 @@
|
||||
- [[_COMMUNITY_Community 42|Community 42]]
|
||||
- [[_COMMUNITY_Community 43|Community 43]]
|
||||
- [[_COMMUNITY_Community 44|Community 44]]
|
||||
- [[_COMMUNITY_Community 47|Community 47]]
|
||||
- [[_COMMUNITY_Community 48|Community 48]]
|
||||
- [[_COMMUNITY_Community 45|Community 45]]
|
||||
- [[_COMMUNITY_Community 46|Community 46]]
|
||||
- [[_COMMUNITY_Community 49|Community 49]]
|
||||
- [[_COMMUNITY_Community 50|Community 50]]
|
||||
- [[_COMMUNITY_Community 51|Community 51]]
|
||||
- [[_COMMUNITY_Community 52|Community 52]]
|
||||
- [[_COMMUNITY_Community 53|Community 53]]
|
||||
- [[_COMMUNITY_Community 54|Community 54]]
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
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
|
||||
1. `success_response()` - 406 edges
|
||||
2. `error_response()` - 325 edges
|
||||
3. `SysUser` - 231 edges
|
||||
4. `BizQcMaterialUsage` - 206 edges
|
||||
5. `BizMaterialStockLog` - 202 edges
|
||||
6. `BizQcTaskResult` - 202 edges
|
||||
7. `BizQcMaterial` - 202 edges
|
||||
8. `BizMaterial` - 199 edges
|
||||
9. `BizQcItemParam` - 197 edges
|
||||
10. `generate_uuid()` - 147 edges
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `统一记录 API 请求/响应出入参的中间件` --uses--> `SysApiRequestLog` [INFERRED]
|
||||
@@ -90,248 +92,256 @@
|
||||
|
||||
### Community 0 - "Community 0"
|
||||
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)
|
||||
Nodes (449): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+441 more)
|
||||
|
||||
### Community 1 - "Community 1"
|
||||
Cohesion: 0.02
|
||||
Nodes (402): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+394 more)
|
||||
Nodes (401): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+393 more)
|
||||
|
||||
### Community 2 - "Community 2"
|
||||
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)
|
||||
Cohesion: 0.05
|
||||
Nodes (280): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+272 more)
|
||||
|
||||
### Community 3 - "Community 3"
|
||||
Cohesion: 0.06
|
||||
Nodes (221): InsuranceCompanyCreateBody, InsuranceCompanyInvoiceCreateBody, InsuranceCompanyInvoiceUpdateBody, InsuranceCompanyUpdateBody, InsuranceProjectPriceCreateBody, InsuranceProjectPriceUpdateBody, 保险公司及险种价格管理 API(保险公司 + 开票信息 + 险种价格), Base (+213 more)
|
||||
Cohesion: 0.01
|
||||
Nodes (244): apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), _resolve_user_role_scopes(), generate_uuid(), delete(), get_multi_with_filters(), batch_stock_in() (+236 more)
|
||||
|
||||
### Community 4 - "Community 4"
|
||||
Cohesion: 0.06
|
||||
Nodes (164): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+156 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (107): _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() (+99 more)
|
||||
|
||||
### Community 5 - "Community 5"
|
||||
Cohesion: 0.03
|
||||
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)
|
||||
Cohesion: 0.04
|
||||
Nodes (66): get_designer_data(), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, 审批意见:前端传 commentText,兼容 comment。, StartInstanceBody, TaskActionBody, BaseStorage (+58 more)
|
||||
|
||||
### Community 6 - "Community 6"
|
||||
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)
|
||||
Nodes (101): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, create_storage_slot(), ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody (+93 more)
|
||||
|
||||
### Community 7 - "Community 7"
|
||||
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)
|
||||
Cohesion: 0.06
|
||||
Nodes (78): _persist_protocol_sub_resources(), _add_months_yyyymmdd(), align_fq_payment_details_payload(), _apply_submit_receipt_finance(), _apply_submit_refund_finance(), attachments_to_urls(), _audit_to_dict(), batch_submit_receipt_finance() (+70 more)
|
||||
|
||||
### Community 8 - "Community 8"
|
||||
Cohesion: 0.06
|
||||
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)
|
||||
Cohesion: 0.04
|
||||
Nodes (49): ApiRequestLogMiddleware, _claims_from_auth(), _format_body_bytes(), _persist_log(), 统一记录 API 请求/响应出入参的中间件, _redact_obj(), _schedule_persist_log(), _should_skip() (+41 more)
|
||||
|
||||
### Community 9 - "Community 9"
|
||||
Cohesion: 0.07
|
||||
Nodes (67): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+59 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (57): 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` 字段约定一致。 (+49 more)
|
||||
|
||||
### Community 10 - "Community 10"
|
||||
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.07
|
||||
Nodes (60): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+52 more)
|
||||
|
||||
### Community 11 - "Community 11"
|
||||
Cohesion: 0.06
|
||||
Nodes (36): BaseHTTPMiddleware, parse_admin_request_json(), 运营 Web(/web/admin)JSON 请求体解析。 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。 Returns:, ApiCryptoError, _b64url_decode(), _b64url_encode(), decrypt_json() (+28 more)
|
||||
Cohesion: 0.11
|
||||
Nodes (43): create_collection_protocol(), _active_link_query(), assert_biz_no_available(), create_convert_link(), get_convert_partner(), get_partner_sample_codes(), has_active_convert_link(), upsert_convert_link_for_to_storage() (+35 more)
|
||||
|
||||
### Community 12 - "Community 12"
|
||||
Cohesion: 0.16
|
||||
Nodes (32): _create_insurance_company(), _create_insurance_company_invoice(), _create_insurance_project_price(), delete_insurance_company(), delete_insurance_company_invoice(), delete_insurance_project_price(), _fmt_dt(), _generate_uuid() (+24 more)
|
||||
|
||||
### Community 13 - "Community 13"
|
||||
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.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 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)
|
||||
Cohesion: 0.15
|
||||
Nodes (20): BaseHTTPMiddleware, ApiCryptoError, _b64url_decode(), _b64url_encode(), decrypt_json(), derive_key(), encrypt_json(), gen_nonce_hex() (+12 more)
|
||||
|
||||
### Community 15 - "Community 15"
|
||||
Cohesion: 0.17
|
||||
Nodes (15): Config, QuotationBase, QuotationCreate, QuotationDetailResponse, QuotationItemBase, QuotationItemCreate, QuotationItemResponse, QuotationItemUpdate (+7 more)
|
||||
Nodes (12): BusinessException, InvalidStatusTransitionException, log_delivery_operation(), log_operation(), log_order_operation(), log_settlement_operation(), log_user_operation(), OrderLockedException (+4 more)
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
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 17 - "Community 17"
|
||||
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 18 - "Community 18"
|
||||
Cohesion: 0.17
|
||||
Nodes (15): Config, QuotationBase, QuotationCreate, QuotationDetailResponse, QuotationItemBase, QuotationItemCreate, QuotationItemResponse, QuotationItemUpdate (+7 more)
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
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)
|
||||
|
||||
### Community 20 - "Community 20"
|
||||
Cohesion: 0.25
|
||||
Nodes (13): code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), _norm_status(), options_list() (+5 more)
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
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 21 - "Community 21"
|
||||
Cohesion: 0.23
|
||||
Nodes (12): create_collection_region(), create_hospital(), get_collection_region(), get_hospital(), _hospital_names_by_region_ids(), _hospital_to_dict(), list_collection_regions(), list_hospitals() (+4 more)
|
||||
|
||||
### Community 18 - "Community 18"
|
||||
Cohesion: 0.25
|
||||
Nodes (13): batch_issue_protocol_nos(), batch_revoke_protocol_nos(), create_protocol_no(), get_protocol_no(), list_protocol_nos(), _parse_issued_time(), protocol_no_exists(), 采集协议号池 CRUD(biz_collection_protocol_no) (+5 more)
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
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"
|
||||
### Community 22 - "Community 22"
|
||||
Cohesion: 0.24
|
||||
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import Wech, 发送模板消息 Args: openid: 用户openid templ, send_delivery_notice(), send_delivery_warning(), send_order_status(), send_payment_success(), send_refund_result(), send_urge_notification() (+1 more)
|
||||
|
||||
### Community 21 - "Community 21"
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 0.22
|
||||
Nodes (12): Config, InquiryBase, InquiryCreate, InquiryDetailResponse, InquiryItemBase, InquiryItemCreate, InquiryItemResponse, InquiryListResponse (+4 more)
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
### Community 24 - "Community 24"
|
||||
Cohesion: 0.23
|
||||
Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
|
||||
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 0.31
|
||||
Nodes (12): _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), options_list(), _row_to_dict() (+4 more)
|
||||
### Community 25 - "Community 25"
|
||||
Cohesion: 0.24
|
||||
Nodes (11): deduct_for_step(), _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), 试剂变动记录 CRUD(biz_reagent_stock_log), 撤销步骤此前 step_save 扣减,便于重新填报。, 扣减试剂库存并生成变动记录。调用方控制事务,本函数不 commit。, _resolve_receiver_purpose() (+3 more)
|
||||
|
||||
### Community 24 - "Community 24"
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 0.27
|
||||
Nodes (11): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), 保留匹配节点及其全部上级,供关键词检索后仍能正确组树。 (+3 more)
|
||||
|
||||
### Community 25 - "Community 25"
|
||||
### Community 27 - "Community 27"
|
||||
Cohesion: 0.29
|
||||
Nodes (9): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), _row_to_dict(), soft_delete_menu() (+1 more)
|
||||
|
||||
### Community 26 - "Community 26"
|
||||
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"
|
||||
### Community 28 - "Community 28"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_express_company(), express_code_exists(), get_express_company(), list_express_companies(), 快递公司 CRUD(biz_express_company), _row_to_dict(), soft_delete_express_company(), update_express_company()
|
||||
|
||||
### Community 28 - "Community 28"
|
||||
### Community 29 - "Community 29"
|
||||
Cohesion: 0.38
|
||||
Nodes (9): create_check_item(), get_check_item(), item_code_exists(), list_active_check_items(), list_check_items(), _order_query(), _row_to_dict(), soft_delete_check_item() (+1 more)
|
||||
|
||||
### Community 29 - "Community 29"
|
||||
### Community 30 - "Community 30"
|
||||
Cohesion: 0.27
|
||||
Nodes (8): create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options(), 字典数据 CRUD(sys_dict_data), _row_to_dict(), soft_delete_dict_data(), update_dict_data()
|
||||
|
||||
### Community 30 - "Community 30"
|
||||
### Community 31 - "Community 31"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): category_code_exists(), create_process_category(), get_process_category(), list_process_categories(), 工艺工序分类 CRUD(biz_process_category), _row_to_dict(), soft_delete_process_category(), update_process_category()
|
||||
|
||||
### Community 31 - "Community 31"
|
||||
### Community 32 - "Community 32"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_item_unit(), get_item_unit(), list_item_units(), 物品单位 CRUD(biz_item_unit), _row_to_dict(), soft_delete_item_unit(), unit_code_exists(), update_item_unit()
|
||||
|
||||
### Community 32 - "Community 32"
|
||||
### 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 33 - "Community 33"
|
||||
### 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 34 - "Community 34"
|
||||
### Community 35 - "Community 35"
|
||||
Cohesion: 0.36
|
||||
Nodes (7): create_tenant(), get_tenant(), list_tenants(), _row_to_dict(), soft_delete_tenant(), tenant_no_exists(), update_tenant()
|
||||
|
||||
### Community 35 - "Community 35"
|
||||
### Community 36 - "Community 36"
|
||||
Cohesion: 0.39
|
||||
Nodes (8): create_lab_item(), get_lab_item(), item_code_exists(), list_active_lab_items(), list_lab_items(), _row_to_dict(), soft_delete_lab_item(), update_lab_item()
|
||||
|
||||
### Community 36 - "Community 36"
|
||||
### Community 37 - "Community 37"
|
||||
Cohesion: 0.36
|
||||
Nodes (7): create_site(), get_site(), list_sites(), _row_to_dict(), site_code_exists(), soft_delete_site(), update_site()
|
||||
|
||||
### Community 38 - "Community 38"
|
||||
Cohesion: 0.29
|
||||
Nodes (2): BaseModel, SoftDeleteModel
|
||||
|
||||
### 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"
|
||||
### Community 39 - "Community 39"
|
||||
Cohesion: 0.38
|
||||
Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
|
||||
|
||||
### Community 39 - "Community 39"
|
||||
### Community 40 - "Community 40"
|
||||
Cohesion: 0.38
|
||||
Nodes (6): Config, UnitBase, UnitCreate, UnitListResponse, UnitResponse, UnitUpdate
|
||||
|
||||
### Community 41 - "Community 41"
|
||||
Cohesion: 0.4
|
||||
Nodes (4): list_ethnics_for_select(), list_ethnics(), 民族码表 CRUD(全局 sys_ethnic), _row_to_dict()
|
||||
|
||||
### Community 40 - "Community 40"
|
||||
### Community 42 - "Community 42"
|
||||
Cohesion: 0.5
|
||||
Nodes (3): BaseSettings, Config, Settings
|
||||
|
||||
### Community 41 - "Community 41"
|
||||
### Community 43 - "Community 43"
|
||||
Cohesion: 0.5
|
||||
Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
|
||||
|
||||
### Community 42 - "Community 42"
|
||||
### Community 44 - "Community 44"
|
||||
Cohesion: 0.67
|
||||
Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)
|
||||
|
||||
### Community 43 - "Community 43"
|
||||
### Community 45 - "Community 45"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
|
||||
|
||||
### Community 44 - "Community 44"
|
||||
### Community 46 - "Community 46"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
|
||||
|
||||
### Community 47 - "Community 47"
|
||||
### Community 49 - "Community 49"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送订单状态通知 Args: openid: 用户openid ord
|
||||
|
||||
### Community 48 - "Community 48"
|
||||
### Community 50 - "Community 50"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送支付成功通知 Args: openid: 用户openid ord
|
||||
|
||||
### Community 49 - "Community 49"
|
||||
### Community 51 - "Community 51"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送配送通知 Args: openid: 配送员openid task
|
||||
|
||||
### Community 50 - "Community 50"
|
||||
### Community 52 - "Community 52"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送配送时效预警 Args: openid: 配送员openid ta
|
||||
|
||||
### Community 51 - "Community 51"
|
||||
### Community 53 - "Community 53"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送退款结果通知 Args: openid: 用户openid ord
|
||||
|
||||
### Community 52 - "Community 52"
|
||||
### Community 54 - "Community 54"
|
||||
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 36`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
|
||||
- **Thin community `Community 38`** (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 41`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
|
||||
- **Thin community `Community 43`** (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 42`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)`
|
||||
- **Thin community `Community 44`** (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 43`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
|
||||
- **Thin community `Community 45`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 44`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
|
||||
- **Thin community `Community 46`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 47`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
|
||||
- **Thin community `Community 49`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 48`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
|
||||
- **Thin community `Community 50`** (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 task`
|
||||
- **Thin community `Community 51`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 50`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
|
||||
- **Thin community `Community 52`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 51`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
|
||||
- **Thin community `Community 53`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 52`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
|
||||
- **Thin community `Community 54`** (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 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._
|
||||
- **Why does `generate_uuid()` connect `Community 3` to `Community 0`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 16`, `Community 17`, `Community 19`, `Community 20`, `Community 21`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`?**
|
||||
_High betweenness centrality (0.132) - this node is a cross-community bridge._
|
||||
- **Why does `SysUser` connect `Community 1` to `Community 0`, `Community 2`, `Community 3`, `Community 5`, `Community 6`, `Community 8`, `Community 9`, `Community 10`, `Community 12`, `Community 19`, `Community 25`?**
|
||||
_High betweenness centrality (0.094) - this node is a cross-community bridge._
|
||||
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 5`, `Community 6`, `Community 41`, `Community 9`, `Community 44`, `Community 12`?**
|
||||
_High betweenness centrality (0.069) - this node is a cross-community bridge._
|
||||
- **Are the 405 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
|
||||
_`success_response()` has 405 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 385 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
|
||||
_`str` has 385 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 324 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
|
||||
_`error_response()` has 324 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 229 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
|
||||
_`SysUser` has 229 INFERRED edges - model-reasoned connections that need verification._
|
||||
@@ -57,12 +57,12 @@
|
||||
</div>
|
||||
<div id="legend"></div>
|
||||
</div>
|
||||
<div id="stats">2542 nodes · 10216 edges · 57 communities</div>
|
||||
<div id="stats">2566 nodes · 10300 edges · 59 communities</div>
|
||||
</div>
|
||||
<script>
|
||||
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}];
|
||||
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 47, "community_name": "Community 47", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 9, "community_name": "Community 9", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_init_scheduled_tasks", "label": "init_scheduled_tasks()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "init_scheduled_tasks()", "community": 9, "community_name": "Community 9", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_shutdown_scheduler", "label": "shutdown_scheduler()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "shutdown_scheduler()", "community": 9, "community_name": "Community 9", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "core_auth_py", "label": "auth.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 11.3, "font": {"size": 0, "color": "#ffffff"}, "title": "auth.py", "community": 9, "community_name": "Community 9", "source_file": "core/auth.py", "file_type": "code", "degree": 18}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_redis_session_enabled()", "community": 9, "community_name": "Community 9", "source_file": "core/auth.py", "file_type": "code", "degree": 2}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "_get_redis_client()", "community": 9, "community_name": "Community 9", "source_file": "core/auth.py", "file_type": "code", "degree": 9}, {"id": "core_auth_session_key", "label": "_session_key()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "_session_key()", "community": 9, "community_name": "Community 9", "source_file": "core/auth.py", "file_type": "code", "degree": 5}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "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": 465}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 431}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 285}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 280}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 115}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 112}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 108}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 80}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 73}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 70}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 67}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 45}, {"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": 23}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 21}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 21}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 20}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 16}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 15}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 15}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 14}, {"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": 13}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 12}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 12}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 11}, {"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": 8}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 7}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 7}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 6}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 4}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 4}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 3}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 2}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 2}, {"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": 1}];
|
||||
|
||||
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
|
||||
function esc(s) {
|
||||
|
||||
+6454
-5230
File diff suppressed because it is too large.
Load diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/__init__.py": 1778578257.989357,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/main.py": 1779491848.22292,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/main.py": 1779523115.988488,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/tasks/__init__.py": 1778579841.437791,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py": 1779245791.6811426,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/api_crypto.py": 1778578258.039314,
|
||||
@@ -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": 1779509954.4854348,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1779523023.381714,
|
||||
"/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,
|
||||
@@ -61,7 +61,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/product_review.py": 1778578258.098316,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/category.py": 1778578258.0941947,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/leave.py": 1778666088.7680702,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py": 1779491764.493821,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py": 1779521568.9195383,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_task.py": 1779332373.211639,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/process_route.py": 1779367598.0383394,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_code.py": 1779279460.690872,
|
||||
@@ -76,14 +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": 1779510193.3188746,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable.py": 1779512620.86979,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sop_document.py": 1779265721.9928973,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779510450.6769412,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779515563.8904932,
|
||||
"/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": 1779510328.552785,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py": 1779512669.9847593,
|
||||
"/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/reagent_stock_log.py": 1779515479.6599197,
|
||||
"/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,
|
||||
@@ -105,13 +105,14 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py": 1779310971.8304002,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/customer.py": 1778733031.447253,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/workflow.py": 1779265993.677624,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py": 1779491879.266598,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py": 1779526388.7832053,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception.py": 1779520697.5570307,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_pack.py": 1779265715.416005,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material.py": 1779284415.64655,
|
||||
"/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/consumable_stock_log.py": 1779515477.284446,
|
||||
"/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,
|
||||
@@ -119,13 +120,13 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/leave.py": 1779265839.500242,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/output_type.py": 1779265703.7363207,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/exhibition_appointment.py": 1778801075.5211918,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py": 1779491799.0764315,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py": 1779526635.1455016,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py": 1779313409.0685387,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py": 1779283386.9305117,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py": 1779332040.5250597,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py": 1779526648.041865,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py": 1779526647.7395403,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/collection_protocol.py": 1779265813.1605325,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py": 1779280842.8447173,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py": 1779491831.2748232,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py": 1779523105.0754724,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py": 1779418318.1375492,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/menu.py": 1779263225.4964793,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py": 1779265690.8423955,
|
||||
@@ -133,9 +134,10 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/ethnic.py": 1779266243.9511197,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py": 1779310968.9855928,
|
||||
"/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/sample_sms_notification.py": 1779526395.021059,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py": 1779526633.9689634,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py": 1779281097.279193,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py": 1779510401.9179235,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py": 1779512577.4061515,
|
||||
"/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,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
-- 样本接收短信通知记录表
|
||||
CREATE TABLE biz_sample_sms_notification (
|
||||
id VARCHAR(64) NOT NULL COMMENT 'UUID',
|
||||
sample_reception_id VARCHAR(64) NOT NULL COMMENT '关联 biz_sample_reception.id',
|
||||
protocol_id VARCHAR(64) DEFAULT NULL COMMENT '关联采集协议单ID(冗余,方便查询)',
|
||||
sms_content VARCHAR(500) DEFAULT NULL COMMENT '提取的短信内容',
|
||||
sms_notified TINYINT(1) DEFAULT 0 COMMENT '0=未通知 1=已通知',
|
||||
notified_by VARCHAR(64) DEFAULT NULL COMMENT '通知操作人ID',
|
||||
notified_time DATETIME DEFAULT NULL COMMENT '通知时间',
|
||||
-- 公共字段
|
||||
tenant_no VARCHAR(32) DEFAULT NULL,
|
||||
order_num INT DEFAULT 0,
|
||||
remark VARCHAR(500) DEFAULT NULL,
|
||||
create_by VARCHAR(64) DEFAULT NULL,
|
||||
create_dept_id VARCHAR(64) DEFAULT NULL,
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64) DEFAULT NULL,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
del_flag CHAR(1) DEFAULT '0',
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_sample_reception_id (sample_reception_id),
|
||||
KEY idx_protocol_id (protocol_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='样本接收短信通知记录';
|
||||
@@ -0,0 +1,25 @@
|
||||
-- 样本入库短信通知记录表
|
||||
CREATE TABLE biz_storage_entry_sms_notification (
|
||||
id VARCHAR(64) NOT NULL COMMENT 'UUID',
|
||||
storage_review_id VARCHAR(64) NOT NULL COMMENT '关联 biz_storage_release_review.id',
|
||||
protocol_id VARCHAR(64) DEFAULT NULL COMMENT '关联采集协议单ID(冗余)',
|
||||
sms_content VARCHAR(500) DEFAULT NULL COMMENT '生成的短信内容',
|
||||
sms_notified TINYINT(1) DEFAULT 0 COMMENT '0=未通知 1=已通知',
|
||||
notified_by VARCHAR(64) DEFAULT NULL COMMENT '通知操作人ID',
|
||||
notified_by_name VARCHAR(64) DEFAULT NULL COMMENT '通知操作人姓名',
|
||||
notified_time DATETIME DEFAULT NULL COMMENT '通知时间',
|
||||
-- 公共字段
|
||||
tenant_no VARCHAR(32) DEFAULT NULL,
|
||||
order_num INT DEFAULT 0,
|
||||
remark VARCHAR(500) DEFAULT NULL,
|
||||
create_by VARCHAR(64) DEFAULT NULL,
|
||||
create_dept_id VARCHAR(64) DEFAULT NULL,
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64) DEFAULT NULL,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
del_flag CHAR(1) DEFAULT '0',
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_storage_review_id (storage_review_id),
|
||||
KEY idx_protocol_id (protocol_id),
|
||||
KEY idx_tenant_no (tenant_no)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='样本入库短信通知记录';
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Fix collation mismatch (1267) when joining biz_sample_sms_notification with biz_sample_reception
|
||||
ALTER TABLE biz_sample_sms_notification
|
||||
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
@@ -0,0 +1,24 @@
|
||||
-- 样本接收信息菜单(位于退费确认与储存证管理之间)
|
||||
-- 注意:插入后需将储存证管理的 order_num 从 6 改为 7
|
||||
|
||||
-- 1. 新增菜单
|
||||
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 (
|
||||
'50000000000000000000000000000011',
|
||||
'样本接收信息',
|
||||
'50000000000000000000000000000001',
|
||||
'C',
|
||||
'sample-reception-info',
|
||||
'/cell-storage/sample-reception-info/index',
|
||||
'cell-storage:sample-reception-info:list',
|
||||
1, '1', '1', 'zkxw', 6, NULL,
|
||||
NULL, '', NOW(), NULL, NOW(), 0
|
||||
);
|
||||
|
||||
-- 2. 后续菜单 order_num +1
|
||||
UPDATE `sys_menu` SET `order_num` = `order_num` + 1
|
||||
WHERE `parent_id` = '50000000000000000000000000000001'
|
||||
AND `order_num` >= 6;
|
||||
@@ -0,0 +1,24 @@
|
||||
-- 样本入库信息菜单(位于样本接收信息与储存证管理之间)
|
||||
-- 注意:插入后需将储存证管理及之后的 order_num +1
|
||||
|
||||
-- 1. 新增菜单
|
||||
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 (
|
||||
'50000000000000000000000000000012',
|
||||
'样本入库信息',
|
||||
'50000000000000000000000000000001',
|
||||
'C',
|
||||
'storage-entry-info',
|
||||
'/cell-storage/storage-entry-info/index',
|
||||
'cell-storage:storage-entry-info:list',
|
||||
1, '1', '1', 'zkxw', 7, NULL,
|
||||
NULL, '', NOW(), NULL, NOW(), 0
|
||||
);
|
||||
|
||||
-- 2. 后续菜单 order_num +1
|
||||
UPDATE `sys_menu` SET `order_num` = `order_num` + 1
|
||||
WHERE `parent_id` = '50000000000000000000000000000001'
|
||||
AND `order_num` >= 7;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,195 @@
|
||||
# 样本入库信息 — 短信通知功能设计
|
||||
|
||||
> 状态:待评审
|
||||
> 日期:2025-05-23
|
||||
> 需求来源:客户提出"样本入库也需要给客户发短信"
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
客户已完成**样本接收信息**页面(`/cell-storage/sample-reception-info`),用于管理样本接收后的短信通知(提取短信内容 → 复制到剪贴板 → 用户线下发送)。现需增加**样本入库信息**页面,在样本完成入库(或拒绝入库)后提供同样的短信通知管理能力。
|
||||
|
||||
**核心模式**:克隆样本接收信息的完整链路(前端页面 + 后端 API + 独立通知表),调整为入库场景。
|
||||
|
||||
**关键约束**:短信不通过系统自动发送,由用户线下手动发送。系统只负责生成短信内容供复制。
|
||||
|
||||
## 2. 决策记录
|
||||
|
||||
| 决策项 | 选择 | 理由 |
|
||||
|---|---|---|
|
||||
| 数据范围 | 已入库(`yrk`) + 拒绝入库(`review_conclusion='btg'`) | 展示最终结果的记录 |
|
||||
| 短信模板 | 系统预设,后续可调 | 先上线后迭代 |
|
||||
| 页面位置 | 细胞存储模块下,与样本接收信息同级 | 用户操作习惯一致 |
|
||||
| 查看弹窗 | 复用 `ProtocolViewDialog` | 与样本接收信息一致,查看协议完整信息 |
|
||||
| 后端存储 | 新建独立表 | 代码独立,不影响现有功能 |
|
||||
|
||||
## 3. 数据范围
|
||||
|
||||
数据源为 `biz_storage_release_review` 表,筛选条件:
|
||||
|
||||
- `storage_status = 'yrk'`(已入库),**或**
|
||||
- `review_conclusion = 'btg'`(审核不通过/拒绝入库)
|
||||
|
||||
不展示 `storage_status = 'drk'`(待入库)且审核未出结论的记录。
|
||||
|
||||
**重要**:仅展示 `reception_source = 'cell_storage'`(细胞存储)的记录,不包含科研捐赠来源的数据。此过滤条件同时应用于「样本接收信息」和「样本入库信息」两个页面。
|
||||
|
||||
## 4. 后端设计
|
||||
|
||||
### 4.1 数据库
|
||||
|
||||
**新建表 `biz_storage_entry_sms_notification`**:
|
||||
|
||||
```sql
|
||||
CREATE TABLE biz_storage_entry_sms_notification (
|
||||
id VARCHAR(64) NOT NULL COMMENT 'UUID主键',
|
||||
storage_review_id VARCHAR(64) NOT NULL COMMENT '关联 biz_storage_release_review.id',
|
||||
protocol_id VARCHAR(64) DEFAULT NULL COMMENT '冗余协议单ID',
|
||||
sms_content VARCHAR(500) DEFAULT NULL COMMENT '生成的短信内容',
|
||||
sms_notified TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0=未通知 1=已通知',
|
||||
notified_by VARCHAR(64) DEFAULT NULL COMMENT '通知操作人ID',
|
||||
notified_by_name VARCHAR(64) DEFAULT NULL COMMENT '通知操作人姓名',
|
||||
notified_time DATETIME DEFAULT NULL COMMENT '通知操作时间',
|
||||
tenant_no VARCHAR(64) DEFAULT NULL COMMENT '租户编号',
|
||||
order_num INT DEFAULT 0 COMMENT '排序',
|
||||
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
|
||||
create_by VARCHAR(64) DEFAULT NULL,
|
||||
create_dept_id VARCHAR(64) DEFAULT NULL,
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64) DEFAULT NULL,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
del_flag CHAR(1) DEFAULT '0' COMMENT '0=正常 1=删除',
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_storage_review_id (storage_review_id),
|
||||
KEY idx_tenant_no (tenant_no)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='样本入库短信通知';
|
||||
```
|
||||
|
||||
### 4.2 ORM 模型
|
||||
|
||||
在 `backend/app/models/models.py` 追加 `BizStorageEntrySmsNotification`,字段与表结构对应。
|
||||
|
||||
### 4.3 CRUD 层
|
||||
|
||||
新建 `backend/app/crud/storage_entry_sms_notification.py`,克隆 `sample_sms_notification.py` 并调整:
|
||||
|
||||
- **联查**:`BizStorageReleaseReview` LEFT JOIN `BizStorageEntrySmsNotification`(通过 `storage_review_id` + `tenant_no`) LEFT JOIN `BizCollectionProtocol` LEFT JOIN `BizProtocolPartyCustomer` LEFT JOIN `BizProtocolSample`
|
||||
- **过滤**:`del_flag=0`,`reception_source='cell_storage'`,`(storage_status='yrk' OR review_conclusion='btg')`,租户隔离,数据权限(`apply_data_scope`)
|
||||
- **懒创建**:列表查询时自动为缺失的 review 记录创建通知记录(`sms_notified=0`)
|
||||
- **`_row_to_dict()`**:蛇形→驼峰,返回前端所需字段
|
||||
|
||||
### 4.4 短信模板
|
||||
|
||||
```
|
||||
已入库:尊敬的{母亲}女士,您的样本(编码:{code})已于{date}完成入库处理。如有疑问请联系客服。
|
||||
拒绝入库:尊敬的{母亲}女士,您的样本(编码:{code})入库审核未通过。如有疑问请联系客服。
|
||||
```
|
||||
|
||||
变量来源:
|
||||
- `{母亲}`:`BizProtocolPartyCustomer.mother_name`
|
||||
- `{code}`:`BizStorageReleaseReview.sample_code`
|
||||
- `{date}`:入库时间 `storage_time`(拒绝入库用审核时间 `review_time`)
|
||||
|
||||
### 4.5 API 端点
|
||||
|
||||
新建 `backend/app/api/storage_entry_sms_notification.py`,前缀 `/api/web/admin`:
|
||||
|
||||
| 方法 | 路径 | 功能 | 权限码 |
|
||||
|---|---|---|---|
|
||||
| GET | `/storage-entry-sms-notifications/list` | 分页列表 | `cell-storage:storage-entry-info:list` |
|
||||
| PUT | `/storage-entry-sms-notifications/{id}/toggle-status` | 切换通知状态 | 同上 |
|
||||
| POST | `/storage-entry-sms-notifications/{id}/generate-sms` | 生成短信内容 | 同上 |
|
||||
|
||||
路由注册:`backend/app/api/__init__.py` + `backend/app/main.py`。
|
||||
|
||||
## 5. 前端设计
|
||||
|
||||
### 5.1 路由
|
||||
|
||||
在 `web-admin/src/router/modules/sqxp.ts` 的 `CellStorage` 子项下添加:
|
||||
|
||||
```
|
||||
path: 'storage-entry-info'
|
||||
name: 'CellStorageStorageEntryInfo'
|
||||
component: '/cell-storage/storage-entry-info/index'
|
||||
meta: { title: '样本入库信息', keepAlive: true, menuCode: 'cell-storage:storage-entry-info:list' }
|
||||
```
|
||||
|
||||
### 5.2 API 模块
|
||||
|
||||
新建 `web-admin/src/api/storage-entry-sms-notification.ts`,3 个函数:
|
||||
|
||||
- `fetchStorageEntrySmsList(params)` → GET `/storage-entry-sms-notifications/list`
|
||||
- `fetchToggleStorageEntrySmsNotified(id, data)` → PUT `/storage-entry-sms-notifications/{id}/toggle-status`
|
||||
- `fetchGenerateStorageEntrySms(id)` → POST `/storage-entry-sms-notifications/{id}/generate-sms`
|
||||
|
||||
### 5.3 页面组件
|
||||
|
||||
新建 `web-admin/src/views/cell-storage/storage-entry-info/index.vue`,克隆 `sample-reception-info/index.vue` 并调整:
|
||||
|
||||
**筛选区**:
|
||||
| 字段 | 控件 | 绑定 |
|
||||
|---|---|---|
|
||||
| 关键词 | `el-input` | `keyword`(协议号/姓名/样本编码) |
|
||||
| 入库状态 | `el-select` | `storageStatus`(已入库 `yrk` / 拒绝入库 `btg`) |
|
||||
| 通知状态 | `el-select` | `smsNotified`(已通知 `1` / 未通知 `0`) |
|
||||
|
||||
**表格列**(全部 `min-width`,`align="center"`):
|
||||
| 列 | prop | 宽度 | 说明 |
|
||||
|---|---|---|---|
|
||||
| 序号 | type=index | 68 | 自动序号 |
|
||||
| 协议号 | protocolNo | 140 | |
|
||||
| 母亲姓名 | motherName | 100 | |
|
||||
| 新生儿姓名 | newbornName | 110 | `show-overflow-tooltip` |
|
||||
| 样本编码 | sampleCode | 130 | |
|
||||
| 样本类型 | sampleTypeName | 110 | |
|
||||
| 入库时间 | storageTime | 170 | 已入库显示入库时间,拒绝入库显示审核时间 |
|
||||
| 入库状态 | storageStatusLabel | 100 | `el-tag`:已入库=`success`,拒绝入库=`danger` |
|
||||
| 通知状态 | smsNotified | 100 | `el-tag`:已通知=`success`,未通知=`info` |
|
||||
| 操作 | — | 260 | `fixed="right"` |
|
||||
|
||||
**操作按钮**:
|
||||
1. **查看** `<el-icon><View /></el-icon>` — 打开 `ProtocolViewDialog`(含 `show-audit-history`、`show-storage-cert`)
|
||||
2. **提取短信** `<el-icon><ChatDotRound /></el-icon>` — 调用 `fetchGenerateStorageEntrySms`,复制到剪贴板
|
||||
3. **标记已/未通知** `<el-icon><Bell /></el-icon>` — 调用 `fetchToggleStorageEntrySmsNotified`
|
||||
|
||||
**交互**:双击行 → `handleView`,分页 `[10, 20, 50]`
|
||||
|
||||
### 5.4 其他修改
|
||||
|
||||
- `App.vue`:在 `panelTitleBarTextRules` 注册「样本入库列表」标题文案
|
||||
- 菜单配置:后台管理中添加「样本入库信息」菜单项,权限码 `cell-storage:storage-entry-info:list`
|
||||
|
||||
## 6. 边界情况
|
||||
|
||||
| 场景 | 处理方式 |
|
||||
|---|---|
|
||||
| 拒绝入库记录无 `storageTime` | 短信模板用 `review_time` 替代,表格列也显示审核时间 |
|
||||
| 协议单为空 | 查看按钮提示"缺少关联协议单",不打开弹窗 |
|
||||
|
||||
## 7. 文件清单
|
||||
|
||||
### 新建(5 个)
|
||||
|
||||
| 文件 | 说明 |
|
||||
|---|---|
|
||||
| `docs/sql/biz_storage_entry_sms_notification.sql` | 建表 DDL |
|
||||
| `backend/app/crud/storage_entry_sms_notification.py` | CRUD 层(联查+懒创建+短信生成) |
|
||||
| `backend/app/api/storage_entry_sms_notification.py` | API 路由(3 个端点) |
|
||||
| `web-admin/src/api/storage-entry-sms-notification.ts` | 前端 API 封装 |
|
||||
| `web-admin/src/views/cell-storage/storage-entry-info/index.vue` | 前端页面 |
|
||||
|
||||
### 修改(4 个)
|
||||
|
||||
| 文件 | 修改内容 |
|
||||
|---|---|
|
||||
| `backend/app/models/models.py` | 追加 `BizStorageEntrySmsNotification` 模型 |
|
||||
| `backend/app/api/__init__.py` | 注册新路由 |
|
||||
| `backend/app/main.py` | 挂载新路由 |
|
||||
| `web-admin/src/router/modules/sqxp.ts` | 添加路由条目(CellStorage 子项) |
|
||||
|
||||
## 8. 不做的事
|
||||
|
||||
- 不实现自动发送短信(线下发送)
|
||||
- 不修改现有 `sample-reception-info` 任何逻辑
|
||||
- 不引入新的 npm/pip 依赖
|
||||
- 不改动入库放行审核页面逻辑
|
||||
@@ -58,3 +58,38 @@
|
||||
|
||||
- **WHEN** 创建合并请求
|
||||
- **THEN** 描述 SHALL 使评审者无需阅读聊天历史即可理解动机与风险
|
||||
|
||||
### Requirement: 前端 API 返回值消费约定
|
||||
|
||||
`web-admin` 的 axios 拦截器(`src/utils/http/index.ts`)已对响应做两层解包:`res.data.data` → 返回值即为后端 `data` 字段的内容。因此页面组件中消费 API 函数返回值时,SHALL NOT 再做 `{ data }` 解构或 `.data` 取值,SHALL 直接从返回值中读取业务字段。
|
||||
|
||||
#### Scenario: 调用列表 API
|
||||
|
||||
- **GIVEN** 后端返回 `{"code": 200, "data": {"list": [...], "total": 12}}`
|
||||
- **WHEN** 页面调用 `const result = await fetchXxxList(params)`
|
||||
- **THEN** `result` 已经是 `{"list": [...], "total": 12}`,SHALL 使用 `result.list`、`result.total`,SHALL NOT 写 `const { data } = await fetchXxxList()` 再从 `data.list` 取值
|
||||
|
||||
#### Scenario: 调用单条 API
|
||||
|
||||
- **GIVEN** 后端返回 `{"code": 200, "data": {"smsContent": "..."}}`
|
||||
- **WHEN** 页面调用 `const result = await fetchGenerateSms(id)`
|
||||
- **THEN** `result` 已经是 `{"smsContent": "..."}`,SHALL 使用 `result.smsContent`,SHALL NOT 写 `const { data } = await fetchGenerateSms()` 再从 `data.smsContent` 取值
|
||||
|
||||
#### Scenario: 新增 API 调用前确认返回值层级
|
||||
|
||||
- **WHEN** 编写新的页面消费 API 函数
|
||||
- **THEN** 开发者 SHALL 先查看 `src/utils/http/index.ts` 第 420 行的 `return res.data.data as T`,确认拦截器已剥离 `{code, data}` 外层包装,消费端直接拿返回值即可
|
||||
|
||||
### Requirement: 前后端 HTTP 方法一致性
|
||||
|
||||
前端 API 函数的 HTTP 方法(GET / POST / PUT / DELETE)SHALL 与后端路由装饰器(`@router.get` / `@router.post` / `@router.put` / `@router.delete`)严格一致。有副作用的操作(创建、更新、状态变更、内容生成)SHALL 使用 POST 或 PUT。
|
||||
|
||||
#### Scenario: 新增 API 接口
|
||||
|
||||
- **WHEN** 后端定义 `@router.post("/generate-sms")`
|
||||
- **THEN** 前端对应的 `fetchGenerateSms` SHALL 使用 `request.post()`,SHALL NOT 使用 `request.get()`
|
||||
|
||||
#### Scenario: 代码评审检查项
|
||||
|
||||
- **WHEN** 评审涉及前后端联调的变更
|
||||
- **THEN** 评审者 SHALL 校验前端 `request.get/post/put/delete` 与后端 `@router.get/post/put/delete` 的方法一一匹配
|
||||
@@ -137,18 +137,44 @@ Web 管理端弹窗 SHALL 遵循规范:表单 `label-position="top"`;遮罩
|
||||
|
||||
### Requirement: 表格操作列固定在右侧
|
||||
|
||||
`web-admin` 中所有业务列表页(系统管理、业务模块等,不含 Demo 参考页)的 `el-table` 操作列 SHALL 使用 `fixed="right"` 固定在表格右侧。宽度规则:2 个按钮时 `width="260"`,3 个按钮时 `width="320"`,4 个及以上按钮时 `width="400"`。全局 CSS 通过 `.el-table-fixed-column--right` 选择器(注意:Element Plus 使用单短横线,非双下划线)提供固定列样式。
|
||||
`web-admin` 中所有业务列表页(系统管理、业务模块等,不含 Demo 参考页)的 `el-table` 操作列 SHALL 使用 `fixed="right"` 固定在表格右侧。宽度规则:2 个按钮时 `min-width="260"`,3 个按钮时 `min-width="320"`,4 个及以上按钮时 `min-width="400"`。全局 CSS 通过 `.el-table-fixed-column--right` 选择器(注意:Element Plus 使用单短横线,非双下划线)提供固定列样式。
|
||||
|
||||
#### Scenario: 新增系统管理列表页
|
||||
|
||||
- **WHEN** 在系统管理模块下新增列表页面(如用户管理、角色管理等)
|
||||
- **THEN** 表格操作列 SHALL 设置 `fixed="right"`,宽度按按钮数设置:≤ 2 按钮用 `width="260"`,3 按钮用 `width="320"`,≥ 4 按钮用 `width="400"`
|
||||
- **THEN** 表格操作列 SHALL 设置 `fixed="right"`,宽度按按钮数设置:≤ 2 按钮用 `min-width="260"`,3 按钮用 `min-width="320"`,≥ 4 按钮用 `min-width="400"`
|
||||
|
||||
#### Scenario: Code review 表格列
|
||||
|
||||
- **WHEN** PR 包含新增或修改的 `el-table-column` 且 `label="操作"`
|
||||
- **THEN** 审查者 SHALL 确认该列包含 `fixed="right"` 属性,且宽度与按钮数量匹配(2 按钮 260px,3+ 按钮 320px)
|
||||
|
||||
### Requirement: 表格列宽使用 min-width 实现等比缩放
|
||||
|
||||
`web-admin` 中所有 `el-table` 的列宽属性 SHALL 使用 `min-width` 替代 `width`,使浏览器视口宽度变化时各列按基础比例等比伸缩。
|
||||
|
||||
**原理**:Element Plus 的布局逻辑是,所有 `min-width` 列按各自 `min-width` 值的比例分配容器可用宽度;当容器宽度小于所有 `min-width` 之和时,触发横向滚动。若部分列使用 `width`(固定宽度),则多余空间全部由 `min-width` 列吸收,导致视口加宽时只有 `min-width` 列变宽而 `width` 列不变。
|
||||
|
||||
**规则**:
|
||||
1. 所有 `el-table-column`(包括序号列、数据列、操作列)SHALL 使用 `min-width` 设定基础宽度,SHALL NOT 使用 `width`。
|
||||
2. `min-width` 值即为该列的最小可读宽度,也是等比分配的权重基数。
|
||||
3. `el-table` 本身的 `width` 属性(如弹窗内嵌表格的固定总宽)不受此规则约束。
|
||||
|
||||
#### Scenario: 新增列表页
|
||||
|
||||
- **WHEN** 新增列表页包含 `el-table`
|
||||
- **THEN** 所有 `el-table-column` 的宽度属性 SHALL 使用 `min-width`,SHALL NOT 使用 `width`
|
||||
|
||||
#### Scenario: 浏览器窗口宽度变化
|
||||
|
||||
- **WHEN** 用户调整浏览器窗口宽度
|
||||
- **THEN** 各列宽度 SHALL 按 `min-width` 设定的基础比例等比伸缩
|
||||
|
||||
#### Scenario: Code review 表格列宽
|
||||
|
||||
- **WHEN** PR 包含新增或修改的 `el-table-column` 且使用 `width` 属性
|
||||
- **THEN** 审查者 SHALL 要求改为 `min-width`
|
||||
|
||||
### Requirement: 侧边栏菜单图标层级规则
|
||||
|
||||
`web-admin` 左侧菜单区域的图标展示 SHALL 遵循以下层级规则:
|
||||
@@ -202,10 +228,11 @@ Web 管理端弹窗 SHALL 遵循规范:表单 `label-position="top"`;遮罩
|
||||
|
||||
### Requirement: 列表行查看弹窗(按钮 + 双击)
|
||||
|
||||
`web-admin` 中所有系统管理与业务列表页(含标准列表、树形列表)的 `el-table` SHALL 提供只读「查看」弹窗能力,实现规则如下:
|
||||
`web-admin` 中**所有** `el-table` 组件——包括主列表页(标准列表、树形列表)、弹窗内嵌列表(如编辑弹窗/查看弹窗/选择弹窗中的子表格)、侧栏面板内的列表——若操作列包含「查看」「查看详情」「查看确认信息」等只读查看类按钮,SHALL 同时提供行双击触发查看的能力,实现规则如下:
|
||||
|
||||
1. **操作列「查看」按钮**:操作列 SHALL 在首位包含一个「查看」按钮(`<el-icon><View /></el-icon>查看`),点击后弹出只读查看弹窗。
|
||||
2. **行双击触发**:`el-table` SHALL 监听 `@row-dblclick` 事件,双击任意行时触发与「查看」按钮相同的弹窗(即调用同一 `handleView(row)` 函数)。
|
||||
3. **条件按钮场景**:当操作列按钮随状态/Tab 变化(如待确认 Tab 显示「确认收款」,已确认 Tab 显示「查看确认信息」),`@row-dblclick` handler SHALL 仅在「查看」类按钮可见时触发对应查看函数,其余状态下可忽略或调用对应主操作函数。
|
||||
3. **弹窗样式**:查看弹窗 SHALL 使用 `SystemViewDialog` 共享组件(`src/components/business/system-view-dialog/index.vue`),样式对齐待办中心「查看详情」弹窗(无标题栏、hero 渐变头图 + 图标、KV grid 字段展示、关闭按钮)。
|
||||
4. **字段内容**:查看弹窗 SHALL 展示该行记录的所有业务字段(含状态映射、字典翻译),不展示 `id`、`del_flag` 等技术字段。长文本/备注字段 SHALL 使用 `span: true` 跨两列展示。
|
||||
5. **区块标题样式**:查看弹窗中各区块标题(`SystemViewDialog` 的 section title,渲染为 `h3`)SHALL 与字段标签(`dt`)形成明显视觉区分。区块标题 SHALL 使用深色文字(`#1e293b`)配合左侧主色竖条装饰(`border-left: 3px solid #10b981`),字号 14px、`font-weight: 600`;字段标签 SHALL 保持为辅助灰色(`#64748b`)、`font-weight: 500`。区块标题样式 SHALL NOT 与字段标签使用相同颜色或相近字重。
|
||||
@@ -566,7 +593,7 @@ import { Plus, Close, Check, Search, RefreshLeft, Edit, Delete, View } from '@el
|
||||
**标准写法:**
|
||||
|
||||
```html
|
||||
<el-table-column prop="status" label="状态" width="90" align="center">
|
||||
<el-table-column prop="status" label="状态" min-width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === '1' ? '正常' : '停用' }}
|
||||
@@ -578,7 +605,7 @@ import { Plus, Close, Check, Search, RefreshLeft, Edit, Delete, View } from '@el
|
||||
**多状态映射标准写法(使用状态标签注册表):**
|
||||
|
||||
```html
|
||||
<el-table-column prop="workOrderStatus" label="状态" width="100" align="center">
|
||||
<el-table-column prop="workOrderStatus" label="状态" min-width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="workOrderStatusTagType(row.workOrderStatus)" size="small">
|
||||
{{ workOrderStatusLabel(row.workOrderStatus) }}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -4268,42 +4268,42 @@
|
||||
"label": "fetchStorageReleaseReviewList()",
|
||||
"file_type": "code",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L108"
|
||||
"source_location": "L118"
|
||||
},
|
||||
{
|
||||
"id": "api_storage_release_review_fetchstoragereleasereviewdetail",
|
||||
"label": "fetchStorageReleaseReviewDetail()",
|
||||
"file_type": "code",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L122"
|
||||
"source_location": "L132"
|
||||
},
|
||||
{
|
||||
"id": "api_storage_release_review_submitstoragereleasereview",
|
||||
"label": "submitStorageReleaseReview()",
|
||||
"file_type": "code",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L128"
|
||||
"source_location": "L138"
|
||||
},
|
||||
{
|
||||
"id": "api_storage_release_review_batchreviewstoragerelease",
|
||||
"label": "batchReviewStorageRelease()",
|
||||
"file_type": "code",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L142"
|
||||
"source_location": "L152"
|
||||
},
|
||||
{
|
||||
"id": "api_storage_release_review_storesample",
|
||||
"label": "storeSample()",
|
||||
"file_type": "code",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L154"
|
||||
"source_location": "L164"
|
||||
},
|
||||
{
|
||||
"id": "api_storage_release_review_batchstoresample",
|
||||
"label": "batchStoreSample()",
|
||||
"file_type": "code",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L160"
|
||||
"source_location": "L170"
|
||||
},
|
||||
{
|
||||
"id": "api_workflow_ts",
|
||||
@@ -8996,11 +8996,46 @@
|
||||
"source_location": "L1"
|
||||
},
|
||||
{
|
||||
"id": "storage_release_review_storagereleaseviewdialog_formatval",
|
||||
"label": "formatVal()",
|
||||
"id": "storage_release_review_storagereleaseviewdialog_formatmetric",
|
||||
"label": "formatMetric()",
|
||||
"file_type": "code",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L175"
|
||||
"source_location": "L211"
|
||||
},
|
||||
{
|
||||
"id": "storage_release_review_storagereleaseviewdialog_attachmentfullurl",
|
||||
"label": "attachmentFullUrl()",
|
||||
"file_type": "code",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L428"
|
||||
},
|
||||
{
|
||||
"id": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentpreview",
|
||||
"label": "handleReceptionAttachmentPreview()",
|
||||
"file_type": "code",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L435"
|
||||
},
|
||||
{
|
||||
"id": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentdownload",
|
||||
"label": "handleReceptionAttachmentDownload()",
|
||||
"file_type": "code",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L440"
|
||||
},
|
||||
{
|
||||
"id": "storage_release_review_storagereleaseviewdialog_handleattachmentpreview",
|
||||
"label": "handleAttachmentPreview()",
|
||||
"file_type": "code",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L444"
|
||||
},
|
||||
{
|
||||
"id": "storage_release_review_storagereleaseviewdialog_handleattachmentdownload",
|
||||
"label": "handleAttachmentDownload()",
|
||||
"file_type": "code",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L448"
|
||||
},
|
||||
{
|
||||
"id": "views_quality_inspection_qc_material_usage_index_vue",
|
||||
@@ -18242,13 +18277,22 @@
|
||||
"source_location": "L1",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "api_storage_release_review_ts",
|
||||
"target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_work_order",
|
||||
"relation": "imports_from",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L2",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "api_storage_release_review_ts",
|
||||
"target": "api_storage_release_review_fetchstoragereleasereviewlist",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L108",
|
||||
"source_location": "L118",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -18257,7 +18301,7 @@
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L122",
|
||||
"source_location": "L132",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -18266,7 +18310,7 @@
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L128",
|
||||
"source_location": "L138",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -18275,7 +18319,7 @@
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L142",
|
||||
"source_location": "L152",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -18284,7 +18328,7 @@
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L154",
|
||||
"source_location": "L164",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -18293,7 +18337,7 @@
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L160",
|
||||
"source_location": "L170",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -25219,11 +25263,83 @@
|
||||
},
|
||||
{
|
||||
"source": "views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_formatval",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_formatmetric",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L175",
|
||||
"source_location": "L211",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_attachmentfullurl",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L428",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentpreview",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L435",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentdownload",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L440",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_handleattachmentpreview",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L444",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_handleattachmentdownload",
|
||||
"relation": "contains",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L448",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentpreview",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_attachmentfullurl",
|
||||
"relation": "calls",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L436",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "storage_release_review_storagereleaseviewdialog_handleattachmentpreview",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentpreview",
|
||||
"relation": "calls",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L445",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "storage_release_review_storagereleaseviewdialog_handleattachmentdownload",
|
||||
"target": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentdownload",
|
||||
"relation": "calls",
|
||||
"confidence": "EXTRACTED",
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L449",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -29276,7 +29392,7 @@
|
||||
"confidence": "INFERRED",
|
||||
"confidence_score": 0.8,
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L116",
|
||||
"source_location": "L126",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -29286,7 +29402,7 @@
|
||||
"confidence": "INFERRED",
|
||||
"confidence_score": 0.8,
|
||||
"source_file": "api/storage-release-review.ts",
|
||||
"source_location": "L123",
|
||||
"source_location": "L133",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
@@ -31579,6 +31695,16 @@
|
||||
"source_location": "L300",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentdownload",
|
||||
"target": "utils_download_attachment_downloadattachmentfile",
|
||||
"relation": "calls",
|
||||
"confidence": "INFERRED",
|
||||
"confidence_score": 0.8,
|
||||
"source_file": "views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue",
|
||||
"source_location": "L441",
|
||||
"weight": 1.0
|
||||
},
|
||||
{
|
||||
"source": "project_price_system_index_if",
|
||||
"target": "api_admin_fetchdeleteprojectsystemitem",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Graph Report - src (2026-05-23)
|
||||
|
||||
## Corpus Check
|
||||
- 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.
|
||||
- Large corpus: 588 files · ~319,711 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
|
||||
|
||||
## Summary
|
||||
- 1473 nodes · 1842 edges · 41 communities detected
|
||||
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 410 edges (avg confidence: 0.8)
|
||||
- 1478 nodes · 1851 edges · 35 communities detected
|
||||
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 411 edges (avg confidence: 0.8)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
@@ -31,25 +31,19 @@
|
||||
- [[_COMMUNITY_Community 19|Community 19]]
|
||||
- [[_COMMUNITY_Community 20|Community 20]]
|
||||
- [[_COMMUNITY_Community 21|Community 21]]
|
||||
- [[_COMMUNITY_Community 22|Community 22]]
|
||||
- [[_COMMUNITY_Community 23|Community 23]]
|
||||
- [[_COMMUNITY_Community 25|Community 25]]
|
||||
- [[_COMMUNITY_Community 24|Community 24]]
|
||||
- [[_COMMUNITY_Community 26|Community 26]]
|
||||
- [[_COMMUNITY_Community 27|Community 27]]
|
||||
- [[_COMMUNITY_Community 28|Community 28]]
|
||||
- [[_COMMUNITY_Community 29|Community 29]]
|
||||
- [[_COMMUNITY_Community 30|Community 30]]
|
||||
- [[_COMMUNITY_Community 31|Community 31]]
|
||||
- [[_COMMUNITY_Community 32|Community 32]]
|
||||
- [[_COMMUNITY_Community 33|Community 33]]
|
||||
- [[_COMMUNITY_Community 34|Community 34]]
|
||||
- [[_COMMUNITY_Community 35|Community 35]]
|
||||
- [[_COMMUNITY_Community 36|Community 36]]
|
||||
- [[_COMMUNITY_Community 37|Community 37]]
|
||||
- [[_COMMUNITY_Community 39|Community 39]]
|
||||
- [[_COMMUNITY_Community 40|Community 40]]
|
||||
- [[_COMMUNITY_Community 41|Community 41]]
|
||||
- [[_COMMUNITY_Community 42|Community 42]]
|
||||
- [[_COMMUNITY_Community 44|Community 44]]
|
||||
- [[_COMMUNITY_Community 38|Community 38]]
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
1. `get()` - 161 edges
|
||||
@@ -64,34 +58,34 @@
|
||||
10. `StorageConfig` - 10 edges
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `handleBatchDelete()` --calls--> `withFullscreenLoading()` [INFERRED]
|
||||
views/system/site/index.vue → utils/fullscreen-loading.ts
|
||||
- `handleBatchDelete()` --calls--> `withFullscreenLoading()` [INFERRED]
|
||||
views/basic-info/customer/index.vue → utils/fullscreen-loading.ts
|
||||
- `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 (80): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+72 more)
|
||||
Nodes (113): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+105 more)
|
||||
|
||||
### Community 1 - "Community 1"
|
||||
Cohesion: 0.03
|
||||
Nodes (60): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+52 more)
|
||||
Cohesion: 0.02
|
||||
Nodes (6): fetchDeleteProjectSystemItem(), fetchGetRoleList(), fetchNotDeletedRegions(), fetchRegionList(), loadRoleList(), if()
|
||||
|
||||
### Community 2 - "Community 2"
|
||||
Cohesion: 0.04
|
||||
Nodes (31): fetchGetUserInfo(), clickTab(), handleTouchEnd(), setTransition(), IframeRouteManager, RouteRegistry, useCommon(), setupAfterEachGuard() (+23 more)
|
||||
Cohesion: 0.03
|
||||
Nodes (61): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+53 more)
|
||||
|
||||
### Community 3 - "Community 3"
|
||||
Cohesion: 0.03
|
||||
Nodes (22): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllConsumableStockLogs(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllReagentStockLogs() (+14 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (31): fetchGetUserInfo(), clickTab(), handleTouchEnd(), setTransition(), IframeRouteManager, RouteRegistry, useCommon(), setupAfterEachGuard() (+23 more)
|
||||
|
||||
### Community 4 - "Community 4"
|
||||
Cohesion: 0.04
|
||||
@@ -103,55 +97,55 @@ Nodes (33): fetchDeptTree(), fetchPostBoundUserIds(), FireworkSystem, reload(),
|
||||
|
||||
### Community 6 - "Community 6"
|
||||
Cohesion: 0.05
|
||||
Nodes (40): fetchAccessLogList(), fetchCleanRoomList(), fetchCreateAccessLog(), fetchCreateCleanRoom(), fetchCreateSite(), fetchDeleteAccessLog(), fetchDeleteCleanRoom(), fetchDeleteSite() (+32 more)
|
||||
Nodes (41): fetchAccessLogList(), fetchCleanRoomList(), fetchCreateAccessLog(), fetchCreateCleanRoom(), fetchCreateSite(), fetchDeleteAccessLog(), fetchDeleteCleanRoom(), fetchDeleteSite() (+33 more)
|
||||
|
||||
### Community 7 - "Community 7"
|
||||
Cohesion: 0.05
|
||||
Nodes (18): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+10 more)
|
||||
Nodes (29): fetchCreateCustomer(), fetchCreateMenu(), fetchCustomerList(), fetchDeleteCustomer(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateCustomer(), fetchUpdateMenu() (+21 more)
|
||||
|
||||
### Community 8 - "Community 8"
|
||||
Cohesion: 0.09
|
||||
Nodes (31): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+23 more)
|
||||
Nodes (5): handleReset(), handleSearch(), WebSocketClient, TableCache, emit()
|
||||
|
||||
### Community 9 - "Community 9"
|
||||
Cohesion: 0.06
|
||||
Nodes (10): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), RoutePermissionValidator, useCeremony(), useTheme(), TableCache, themeAnimation() (+2 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (11): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), ComponentLoader, RoutePermissionValidator, RouteTransformer, useCeremony(), useTheme() (+3 more)
|
||||
|
||||
### Community 10 - "Community 10"
|
||||
Cohesion: 0.09
|
||||
Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
|
||||
Nodes (31): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+23 more)
|
||||
|
||||
### Community 11 - "Community 11"
|
||||
Cohesion: 0.13
|
||||
Nodes (4): handleReset(), handleSearch(), WebSocketClient, emit()
|
||||
Cohesion: 0.06
|
||||
Nodes (17): fetchAttachmentDownloadUrl(), handleReceptionAttachmentDownload(), attachmentFullUrl(), handleAttachmentDownload(), handleAttachmentPreview(), formatDetectMethods(), handleReceptionAttachmentDownload(), handleTaskAttachmentDownload() (+9 more)
|
||||
|
||||
### Community 12 - "Community 12"
|
||||
Cohesion: 0.08
|
||||
Nodes (17): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), collectIds(), postorder(), preorder(), applyTreeExpand() (+9 more)
|
||||
Cohesion: 0.09
|
||||
Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
|
||||
|
||||
### Community 13 - "Community 13"
|
||||
Cohesion: 0.09
|
||||
Nodes (9): fetchGetAllUpgradeLogs(), fetchGetChinaMapData(), fetchGetComments(), fetchGetCurrentVersion(), fetchGetLatestUpgradeLog(), fetchGetSystemConfig(), fetchGetUpgradeLogs(), systemUpgrade() (+1 more)
|
||||
Cohesion: 0.1
|
||||
Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
|
||||
|
||||
### Community 14 - "Community 14"
|
||||
Cohesion: 0.1
|
||||
Nodes (8): fetchGetMenuList(), fetchGetMenuCodes(), fetchLogin(), fetchRefreshToken(), MenuProcessor, useAppMode(), useAuth(), buildWebEncryptedLoginBody()
|
||||
|
||||
### Community 15 - "Community 15"
|
||||
Cohesion: 0.1
|
||||
Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
|
||||
Cohesion: 0.12
|
||||
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
Cohesion: 0.12
|
||||
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
|
||||
Nodes (19): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchRoleOptions(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd() (+11 more)
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
Cohesion: 0.14
|
||||
Nodes (9): auditorDisplay(), dash(), expressName(), formatYm(), formatYmd(), sampleTypeName(), siteName(), unitName() (+1 more)
|
||||
|
||||
### Community 18 - "Community 18"
|
||||
Cohesion: 0.14
|
||||
Nodes (17): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd(), handleDelete() (+9 more)
|
||||
Cohesion: 0.19
|
||||
Nodes (3): fetchGetLatestUpgradeLog(), systemUpgrade(), VersionManager
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
Cohesion: 0.12
|
||||
@@ -162,122 +156,90 @@ 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 23 - "Community 23"
|
||||
Cohesion: 0.17
|
||||
Nodes (12): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), handleAdd(), handleBatchDelete(), handleDelete(), handleReset() (+4 more)
|
||||
|
||||
### Community 25 - "Community 25"
|
||||
Cohesion: 0.17
|
||||
Nodes (3): fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList()
|
||||
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 0.18
|
||||
Nodes (3): fetchMaterialList(), fetchMaterialOptions(), fetchMaterialStockLogList()
|
||||
|
||||
### Community 27 - "Community 27"
|
||||
### Community 24 - "Community 24"
|
||||
Cohesion: 0.2
|
||||
Nodes (2): fetchQcMaterialList(), fetchQcMaterialOptions()
|
||||
|
||||
### Community 29 - "Community 29"
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 0.39
|
||||
Nodes (6): isIgnorableScriptError(), normalizeErrorMessage(), registerPromiseErrorHandler(), registerResourceErrorHandler(), scriptErrorHandler(), setupErrorHandle()
|
||||
|
||||
### Community 30 - "Community 30"
|
||||
### Community 27 - "Community 27"
|
||||
Cohesion: 0.36
|
||||
Nodes (1): TableHeightCalculator
|
||||
|
||||
### Community 31 - "Community 31"
|
||||
### Community 28 - "Community 28"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): logApiCryptoBootInfo(), maskSecret()
|
||||
|
||||
### Community 32 - "Community 32"
|
||||
### Community 29 - "Community 29"
|
||||
Cohesion: 0.29
|
||||
Nodes (2): fetchLeaveDetail(), fetchLeaveList()
|
||||
|
||||
### Community 30 - "Community 30"
|
||||
Cohesion: 0.47
|
||||
Nodes (3): isPaymentDueWithinWarnWindow(), parsePaymentDueYmd(), startOfLocalDay()
|
||||
|
||||
### Community 33 - "Community 33"
|
||||
### Community 31 - "Community 31"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchSampleReceptionCheckItemList(), fetchSampleReceptionCheckItemsActive()
|
||||
|
||||
### Community 34 - "Community 34"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchQcThirdPartyItemList(), fetchQcThirdPartyItemsActive()
|
||||
|
||||
### Community 35 - "Community 35"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchQcThirdPartyCompanyList(), fetchQcThirdPartyCompanyOptions()
|
||||
|
||||
### Community 36 - "Community 36"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchQcLabTestItemList(), fetchQcLabTestItemsActive()
|
||||
|
||||
### Community 37 - "Community 37"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchQcTaskDetail(), fetchQcTaskList()
|
||||
|
||||
### Community 39 - "Community 39"
|
||||
### Community 33 - "Community 33"
|
||||
Cohesion: 0.53
|
||||
Nodes (4): isEtaTodayOrEarlier(), parseEtaLocalDate(), sampleReceptionRowClassName(), startOfLocalDay()
|
||||
|
||||
### Community 40 - "Community 40"
|
||||
### Community 34 - "Community 34"
|
||||
Cohesion: 0.5
|
||||
Nodes (2): focusInput(), handleKeydown()
|
||||
|
||||
### Community 41 - "Community 41"
|
||||
### Community 35 - "Community 35"
|
||||
Cohesion: 0.67
|
||||
Nodes (2): if(), logSidebarMenu()
|
||||
|
||||
### Community 42 - "Community 42"
|
||||
### Community 36 - "Community 36"
|
||||
Cohesion: 1.0
|
||||
Nodes (2): getSettingDefaults(), resetToDefaults()
|
||||
|
||||
### Community 44 - "Community 44"
|
||||
### Community 38 - "Community 38"
|
||||
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`
|
||||
- **Thin community `Community 24`** (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 27`** (10 nodes): `fetchBatchStockInQcMaterial()`, `fetchBatchStockOutQcMaterial()`, `fetchCreateQcMaterial()`, `fetchDeleteQcMaterial()`, `fetchQcMaterialList()`, `fetchQcMaterialOptions()`, `fetchStockInQcMaterial()`, `fetchStockOutQcMaterial()`, `fetchUpdateQcMaterial()`, `qc-material.ts`
|
||||
- **Thin community `Community 27`** (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 30`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
|
||||
- **Thin community `Community 28`** (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 31`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
|
||||
- **Thin community `Community 29`** (7 nodes): `fetchCreateLeave()`, `fetchDeleteLeave()`, `fetchLeaveDetail()`, `fetchLeaveList()`, `fetchSubmitLeave()`, `fetchUpdateLeave()`, `leave.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 33`** (6 nodes): `fetchCreateSampleReceptionCheckItem()`, `fetchDeleteSampleReceptionCheckItem()`, `fetchSampleReceptionCheckItemList()`, `fetchSampleReceptionCheckItemsActive()`, `fetchUpdateSampleReceptionCheckItem()`, `sample-reception-check-item.ts`
|
||||
- **Thin community `Community 31`** (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): `fetchCreateQcThirdPartyItem()`, `fetchDeleteQcThirdPartyItem()`, `fetchQcThirdPartyItemList()`, `fetchQcThirdPartyItemsActive()`, `fetchUpdateQcThirdPartyItem()`, `qc-third-party-item.ts`
|
||||
- **Thin community `Community 34`** (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 35`** (6 nodes): `fetchCreateQcThirdPartyCompany()`, `fetchDeleteQcThirdPartyCompany()`, `fetchQcThirdPartyCompanyList()`, `fetchQcThirdPartyCompanyOptions()`, `fetchUpdateQcThirdPartyCompany()`, `qc-third-party-company.ts`
|
||||
- **Thin community `Community 35`** (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 36`** (6 nodes): `fetchCreateQcLabTestItem()`, `fetchDeleteQcLabTestItem()`, `fetchQcLabTestItemList()`, `fetchQcLabTestItemsActive()`, `fetchUpdateQcLabTestItem()`, `qc-lab-test-item.ts`
|
||||
- **Thin community `Community 36`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **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 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`** (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`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 44`** (3 nodes): `defaultAvatarPathByRole()`, `resolveUserAvatarUrl()`, `user-avatar.ts`
|
||||
- **Thin community `Community 38`** (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 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 `buildTreePathLabelFromFlat()` connect `Community 5` to `Community 0`, `Community 9`?**
|
||||
_High betweenness centrality (0.045) - this node is a cross-community bridge._
|
||||
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 13`, `Community 14`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `Community 23`, `Community 24`, `Community 29`, `Community 31`?**
|
||||
_High betweenness centrality (0.284) - this node is a cross-community bridge._
|
||||
- **Why does `push()` connect `Community 5` to `Community 1`, `Community 8`, `Community 9`, `Community 11`, `Community 13`, `Community 18`?**
|
||||
_High betweenness centrality (0.083) - this node is a cross-community bridge._
|
||||
- **Why does `fetchGetLatestUpgradeLog()` connect `Community 18` to `Community 0`?**
|
||||
_High betweenness centrality (0.043) - 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?**
|
||||
|
||||
@@ -57,12 +57,12 @@
|
||||
</div>
|
||||
<div id="legend"></div>
|
||||
</div>
|
||||
<div id="stats">1473 nodes · 1842 edges · 244 communities</div>
|
||||
<div id="stats">1478 nodes · 1851 edges · 237 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": "#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
|
||||
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 28, "community_name": "Community 28", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 28, "community_name": "Community 28", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 28, "community_name": "Community 28", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 28, "community_name": "Community 28", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 28, "community_name": "Community 28", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 28, "community_name": "Community 28", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 71, "community_name": "Community 71", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 72, "community_name": "Community 72", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 15, "community_name": "Community 15", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 15, "community_name": "Community 15", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 15, "community_name": "Community 15", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 15, "community_name": "Community 15", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 15, "community_name": "Community 15", "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": 220}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 128}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 102}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 69}, {"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": 52}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 49}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 48}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 42}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 39}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 38}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 36}, {"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": 22}, {"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": 19}, {"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": 16}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 11}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 10}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 9}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 8}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 8}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 7}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 7}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 6}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 6}, {"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": 5}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 4}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 3}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 3}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 3}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 3}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 3}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 3}, {"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": 2}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 2}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 2}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 2}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 2}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 2}, {"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}, {"cidLine truncated
|
||||
|
||||
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
|
||||
function esc(s) {
|
||||
|
||||
@@ -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": 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/import/components.d.ts": 1779521178.8516939,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779520345.0217957,
|
||||
"/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,
|
||||
@@ -194,7 +194,7 @@
|
||||
"/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": 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/storage-release-review.ts": 1779521577.6135197,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/workflow.ts": 1778729873.096252,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/production-work-order.ts": 1779341251.2626827,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-task-result.ts": 1779332042.258692,
|
||||
@@ -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": 1779511836.8888884,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/reagent/index.vue": 1779515592.434829,
|
||||
"/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": 1779511015.0429022,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/consumable/index.vue": 1779515588.951384,
|
||||
"/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,
|
||||
@@ -294,9 +294,9 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-material/index.vue": 1779284232.1223023,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/sample-reception/index.vue": 1779423489.553699,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-task/index.vue": 1779371036.8066387,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/index.vue": 1779502744.2123482,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/index.vue": 1779521589.9317381,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseReviewDialog.vue": 1779492551.3344166,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue": 1779492939.2935543,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue": 1779521645.4598894,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-material-usage/index.vue": 1779285902.4727366,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/third-party-company/index.vue": 1779423582.5553048,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/500/index.vue": 1778582068.0705533,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import request from '@/utils/http'
|
||||
|
||||
type PageList<T> = {
|
||||
list: T[]
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
totalPages: number
|
||||
}
|
||||
|
||||
/** 查询列表(联查 sample_reception + sms_notification) */
|
||||
export function fetchSampleSmsNotificationList(params?: {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
keyword?: string
|
||||
acceptConclusion?: string
|
||||
smsNotified?: string
|
||||
}) {
|
||||
return request.get<PageList<Record<string, unknown>>>({
|
||||
url: '/web/admin/sample-sms-notifications/list',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 切换通知状态 */
|
||||
export function fetchToggleSmsNotified(
|
||||
id: string,
|
||||
data: { smsNotified: number; sampleReceptionId?: string }
|
||||
) {
|
||||
return request.put({
|
||||
url: `/web/admin/sample-sms-notifications/${id}/toggle-status`,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 生成短信内容 */
|
||||
export function fetchGenerateSms(id: string, sampleReceptionId?: string) {
|
||||
return request.post<{ smsContent: string }>({
|
||||
url: `/web/admin/sample-sms-notifications/${id}/generate-sms`,
|
||||
params: sampleReceptionId ? { sampleReceptionId } : undefined
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import request from '@/utils/http'
|
||||
|
||||
type PageList<T> = {
|
||||
list: T[]
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
totalPages: number
|
||||
}
|
||||
|
||||
/** 查询列表(联查 storage_release_review + sms_notification) */
|
||||
export function fetchStorageEntrySmsList(params?: {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
keyword?: string
|
||||
storageStatus?: string
|
||||
smsNotified?: string
|
||||
}) {
|
||||
return request.get<PageList<Record<string, unknown>>>({
|
||||
url: '/web/admin/storage-entry-sms-notifications/list',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/** 切换通知状态 */
|
||||
export function fetchToggleStorageEntrySmsNotified(
|
||||
id: string,
|
||||
data: { smsNotified: number; storageReviewId?: string }
|
||||
) {
|
||||
return request.put({
|
||||
url: `/web/admin/storage-entry-sms-notifications/${id}/toggle-status`,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 生成短信内容 */
|
||||
export function fetchGenerateStorageEntrySms(id: string, storageReviewId?: string) {
|
||||
return request.post<{ smsContent: string }>({
|
||||
url: `/web/admin/storage-entry-sms-notifications/${id}/generate-sms`,
|
||||
params: storageReviewId ? { storageReviewId } : undefined
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import request from '@/utils/http'
|
||||
import type { QcWorkOrderReceptionDetail } from '@/api/qc-work-order'
|
||||
|
||||
type PageList<T> = {
|
||||
list: T[]
|
||||
@@ -24,6 +25,12 @@ export type StorageReleaseReview = {
|
||||
reviewTime?: string
|
||||
storageStatus?: string
|
||||
storageStatusLabel?: string
|
||||
sampleTypeName?: string
|
||||
handlerName?: string
|
||||
receptionTime?: string
|
||||
motherName?: string
|
||||
protocolStatus?: string
|
||||
protocolStatusLabel?: string
|
||||
storageBy?: string
|
||||
storageByName?: string
|
||||
storageTime?: string
|
||||
@@ -77,6 +84,7 @@ export type QcInfoTask = {
|
||||
export type QcInfo = {
|
||||
workOrderNo?: string
|
||||
workOrderStatus?: string
|
||||
workOrderStatusLabel?: string
|
||||
tasks?: QcInfoTask[]
|
||||
}
|
||||
|
||||
@@ -93,6 +101,7 @@ export type ProductionInfoTask = {
|
||||
export type ProductionInfo = {
|
||||
workOrderNo?: string
|
||||
workOrderStatus?: string
|
||||
workOrderStatusLabel?: string
|
||||
tasks?: ProductionInfoTask[]
|
||||
}
|
||||
|
||||
@@ -101,6 +110,7 @@ export type StorageReleaseReviewDetail = {
|
||||
protocolInfo?: ProtocolInfo
|
||||
transportInfo?: TransportInfo
|
||||
receptionInfo?: ReceptionInfo
|
||||
reception?: QcWorkOrderReceptionDetail
|
||||
qcInfo?: QcInfo
|
||||
productionInfo?: ProductionInfo
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="56"
|
||||
min-width="56"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => index + 1"
|
||||
@@ -63,7 +63,7 @@
|
||||
{{ row.qty != null && row.qty !== '' ? row.qty : '—' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" width="72" align="center" header-align="center">
|
||||
<el-table-column label="单位" min-width="72" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.unit || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="140" align="center" header-align="center">
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
<!-- 样本查看 — 生产信息卡片(协议单查看弹窗复用) -->
|
||||
<template>
|
||||
<div class="sample-card__section sample-card__section--production">
|
||||
<div class="sample-card__section-label">生产信息</div>
|
||||
|
||||
<div v-if="!productionInfo" class="sample-production-empty">暂无生产信息</div>
|
||||
|
||||
<template v-else>
|
||||
<div class="production-work-order-row">
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">工单号</span>
|
||||
<span class="qc-kv__value qc-kv__value--code">{{
|
||||
productionInfo.workOrderNo || '—'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">工单状态</span>
|
||||
<span class="qc-kv__value">
|
||||
<el-tag
|
||||
:type="productionWorkOrderStatusTagType(productionInfo.workOrderStatus || '')"
|
||||
size="small"
|
||||
>
|
||||
{{
|
||||
productionInfo.workOrderStatusLabel ||
|
||||
productionWorkOrderStatusLabel(productionInfo.workOrderStatus || '')
|
||||
}}
|
||||
</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="productionInfo.workOrderStatus === 'dpz' && !productionInfo.tasks?.length"
|
||||
class="sample-production-hint"
|
||||
>
|
||||
工单待配置生产任务
|
||||
</div>
|
||||
|
||||
<div v-if="productionInfo.tasks?.length" class="production-task-cards">
|
||||
<div v-for="task in productionInfo.tasks" :key="task.id" class="production-task-card">
|
||||
<div class="production-task-card__header">
|
||||
<span class="production-task-card__name">{{
|
||||
task.taskName || task.taskNo || '—'
|
||||
}}</span>
|
||||
<el-tag :type="productionTaskStatusTagType(task.taskStatus || '')" size="small">
|
||||
{{ task.taskStatusLabel || productionTaskStatusLabel(task.taskStatus || '') }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="production-task-card__body">
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">任务号</span>
|
||||
<span class="qc-kv__value">{{ task.taskNo || '—' }}</span>
|
||||
</div>
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">开始时间</span>
|
||||
<span class="qc-kv__value">{{ task.startedTime || '—' }}</span>
|
||||
</div>
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">完成时间</span>
|
||||
<span class="qc-kv__value">{{ task.completedTime || '—' }}</span>
|
||||
</div>
|
||||
<!-- 输入信息 -->
|
||||
<div v-if="task.inputs?.length" class="production-task-card__io">
|
||||
<div class="production-task-card__io-label">输入</div>
|
||||
<div class="production-task-card__io-items">
|
||||
<div v-for="(inp, idx) in task.inputs" :key="'in-' + idx" class="io-item">
|
||||
<el-tag type="info" size="small" class="io-item__type">{{
|
||||
inputTypeLabel(inp.inputType)
|
||||
}}</el-tag>
|
||||
<span class="io-item__name">{{ inp.inputName || inp.inputCode || '—' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 输出信息 -->
|
||||
<div v-if="task.outputs?.length" class="production-task-card__io">
|
||||
<div class="production-task-card__io-label">输出</div>
|
||||
<div class="production-task-card__io-items">
|
||||
<div v-for="(out, idx) in task.outputs" :key="'out-' + idx" class="io-item">
|
||||
<el-tag type="success" size="small" class="io-item__type">{{
|
||||
outputTypeLabel(out.outputType)
|
||||
}}</el-tag>
|
||||
<span class="io-item__name">{{ out.outputName || out.outputCode || '—' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="productionInfo.workOrderStatus !== 'dpz'" class="sample-production-hint">
|
||||
暂无生产任务
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
export type ProductionTaskInput = {
|
||||
inputType?: string
|
||||
inputCode?: string
|
||||
inputName?: string
|
||||
}
|
||||
|
||||
export type ProductionTaskOutput = {
|
||||
outputType?: string
|
||||
outputCode?: string
|
||||
outputName?: string
|
||||
}
|
||||
|
||||
export type ProductionTask = {
|
||||
id?: string
|
||||
taskNo?: string
|
||||
taskName?: string
|
||||
taskStatus?: string
|
||||
taskStatusLabel?: string
|
||||
startedTime?: string
|
||||
completedTime?: string
|
||||
inputs?: ProductionTaskInput[]
|
||||
outputs?: ProductionTaskOutput[]
|
||||
}
|
||||
|
||||
export type ProductionInfo = {
|
||||
workOrderNo?: string
|
||||
workOrderStatus?: string
|
||||
workOrderStatusLabel?: string
|
||||
tasks?: ProductionTask[]
|
||||
}
|
||||
|
||||
const PRODUCTION_WORK_ORDER_STATUS_LABELS: Record<string, string> = {
|
||||
dpz: '待配置',
|
||||
jxz: '进行中',
|
||||
ywc: '已完成'
|
||||
}
|
||||
|
||||
const PRODUCTION_TASK_STATUS_LABELS: Record<string, string> = {
|
||||
dpz: '待配置',
|
||||
dzx: '待执行',
|
||||
jxz: '执行中',
|
||||
ywc: '已完成'
|
||||
}
|
||||
|
||||
defineProps<{
|
||||
productionInfo?: ProductionInfo | null
|
||||
}>()
|
||||
|
||||
function productionWorkOrderStatusLabel(status: string) {
|
||||
return PRODUCTION_WORK_ORDER_STATUS_LABELS[status] || status || '—'
|
||||
}
|
||||
|
||||
function productionWorkOrderStatusTagType(status: string) {
|
||||
if (status === 'ywc') return 'success' as const
|
||||
if (status === 'jxz') return 'warning' as const
|
||||
return 'info' as const
|
||||
}
|
||||
|
||||
function productionTaskStatusLabel(status: string) {
|
||||
return PRODUCTION_TASK_STATUS_LABELS[status] || status || '—'
|
||||
}
|
||||
|
||||
function productionTaskStatusTagType(status: string) {
|
||||
if (status === 'ywc') return 'success' as const
|
||||
if (status === 'jxz') return 'warning' as const
|
||||
if (status === 'dzx') return 'info' as const
|
||||
return 'info' as const
|
||||
}
|
||||
|
||||
function inputTypeLabel(type?: string) {
|
||||
if (type === 'sample') return '样本'
|
||||
if (type === 'reagent') return '试剂'
|
||||
if (type === 'consumable') return '耗材'
|
||||
return type || '—'
|
||||
}
|
||||
|
||||
function outputTypeLabel(type?: string) {
|
||||
if (type === 'sample') return '样本'
|
||||
if (type === 'cell_product') return '细胞产品'
|
||||
if (type === 'other') return '其他'
|
||||
return type || '—'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sample-card__section--production {
|
||||
margin-top: 4px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px dashed #e2e8f0;
|
||||
}
|
||||
|
||||
.sample-card__section-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #94a3b8;
|
||||
margin-bottom: 10px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.sample-production-empty,
|
||||
.sample-production-hint {
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.production-work-order-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: 12px 24px;
|
||||
margin-bottom: 12px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.production-work-order-row .qc-kv {
|
||||
flex: 1;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.production-task-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.production-task-card {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.production-task-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.production-task-card__name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.production-task-card__body {
|
||||
padding: 10px 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.production-task-card__io {
|
||||
margin-top: 4px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px dashed #f1f5f9;
|
||||
}
|
||||
|
||||
.production-task-card__io-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #94a3b8;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.production-task-card__io-items {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.io-item {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
color: #475569;
|
||||
|
||||
.io-item__type {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.io-item__name {
|
||||
max-width: 120px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.qc-kv {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.qc-kv__label {
|
||||
color: #94a3b8;
|
||||
flex-shrink: 0;
|
||||
min-width: 56px;
|
||||
}
|
||||
|
||||
.qc-kv__value {
|
||||
color: #1e293b;
|
||||
font-weight: 500;
|
||||
word-break: break-word;
|
||||
|
||||
&--code {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,182 @@
|
||||
<!-- 样本查看 — 入库放行审核信息(协议单查看弹窗复用) -->
|
||||
<template>
|
||||
<div class="sample-card__section sample-card__section--storage-release">
|
||||
<div class="sample-card__section-label">入库放行审核信息</div>
|
||||
|
||||
<div v-if="!storageReleaseInfo" class="sample-storage-release-empty">
|
||||
暂无入库放行审核信息
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<div class="storage-release-info-grid">
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">审核结论</span>
|
||||
<span class="qc-kv__value">
|
||||
<el-tag
|
||||
v-if="storageReleaseInfo.reviewConclusion"
|
||||
:type="storageReleaseInfo.reviewConclusion === 'tg' ? 'success' : 'danger'"
|
||||
size="small"
|
||||
>
|
||||
{{
|
||||
storageReleaseInfo.reviewConclusionLabel ||
|
||||
conclusionLabel(storageReleaseInfo.reviewConclusion)
|
||||
}}
|
||||
</el-tag>
|
||||
<span v-else class="qc-kv__muted">待审核</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">审核人</span>
|
||||
<span class="qc-kv__value">{{ storageReleaseInfo.reviewByName || '—' }}</span>
|
||||
</div>
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">审核时间</span>
|
||||
<span class="qc-kv__value">{{ storageReleaseInfo.reviewTime || '—' }}</span>
|
||||
</div>
|
||||
<div v-if="storageReleaseInfo.reviewRemark" class="qc-kv qc-kv--full">
|
||||
<span class="qc-kv__label">审核备注</span>
|
||||
<span class="qc-kv__value qc-kv__value--muted">{{
|
||||
storageReleaseInfo.reviewRemark
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="attachmentFiles.length" class="storage-release-attachments">
|
||||
<div class="qc-kv">
|
||||
<span class="qc-kv__label">审核附件</span>
|
||||
<span class="qc-kv__value">
|
||||
<ProtocolAttachmentReadonly
|
||||
:files="attachmentFiles"
|
||||
@preview="handlePreview"
|
||||
@download="handleDownload"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProtocolAttachmentReadonly from '@/views/cell-storage/protocol/ProtocolAttachmentReadonly.vue'
|
||||
import { downloadAttachmentFile } from '@/utils/download-attachment'
|
||||
|
||||
export type StorageReleaseInfo = {
|
||||
reviewConclusion?: string
|
||||
reviewConclusionLabel?: string
|
||||
reviewByName?: string
|
||||
reviewTime?: string
|
||||
reviewRemark?: string
|
||||
reviewAttachments?: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
storageReleaseInfo?: StorageReleaseInfo | null
|
||||
}>()
|
||||
|
||||
const minioBaseUrl = (import.meta.env.VITE_MINIO_BASE_URL || '').replace(/\/$/, '')
|
||||
|
||||
const attachmentFiles = computed(() => {
|
||||
const urls = String(props.storageReleaseInfo?.reviewAttachments || '').trim()
|
||||
if (!urls) return []
|
||||
return urls
|
||||
.split(',')
|
||||
.map((u) => u.trim())
|
||||
.filter(Boolean)
|
||||
.map((fileUrl, i) => ({
|
||||
id: `srr_${i}`,
|
||||
fileUrl,
|
||||
fileName: fileUrl.split('/').pop() || `附件${i + 1}`
|
||||
}))
|
||||
})
|
||||
|
||||
function conclusionLabel(conclusion: string) {
|
||||
if (conclusion === 'tg') return '通过'
|
||||
if (conclusion === 'btg') return '不通过'
|
||||
return conclusion
|
||||
}
|
||||
|
||||
function fullFileUrl(suffix: string) {
|
||||
if (!suffix) return ''
|
||||
if (suffix.startsWith('http://') || suffix.startsWith('https://') || suffix.startsWith('/'))
|
||||
return suffix
|
||||
return minioBaseUrl ? `${minioBaseUrl}/${suffix.replace(/^\//, '')}` : suffix
|
||||
}
|
||||
|
||||
function handlePreview(file: Record<string, any>) {
|
||||
const url = fullFileUrl(String(file.fileUrl || ''))
|
||||
if (url) window.open(url, '_blank')
|
||||
}
|
||||
|
||||
function handleDownload(file: Record<string, any>) {
|
||||
downloadAttachmentFile(file, { fullFileUrl })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.sample-card__section--storage-release {
|
||||
margin-top: 4px;
|
||||
padding-top: 14px;
|
||||
border-top: 1px dashed #e2e8f0;
|
||||
}
|
||||
|
||||
.sample-card__section-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #94a3b8;
|
||||
margin-bottom: 10px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.sample-storage-release-empty {
|
||||
font-size: 13px;
|
||||
color: #94a3b8;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.storage-release-info-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: 12px 24px;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.storage-release-attachments {
|
||||
margin-top: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px dashed #f1f5f9;
|
||||
}
|
||||
|
||||
.qc-kv {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
|
||||
&--full {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.qc-kv__label {
|
||||
color: #94a3b8;
|
||||
flex-shrink: 0;
|
||||
min-width: 56px;
|
||||
}
|
||||
|
||||
.qc-kv__value {
|
||||
color: #1e293b;
|
||||
font-weight: 500;
|
||||
word-break: break-word;
|
||||
|
||||
&--muted {
|
||||
color: #64748b;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.qc-kv__muted {
|
||||
color: #94a3b8;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
+1
@@ -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": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,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": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "label": "storage-release-review.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L1"}, {"id": "api_storage_release_review_fetchstoragereleasereviewlist", "label": "fetchStorageReleaseReviewList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L118"}, {"id": "api_storage_release_review_fetchstoragereleasereviewdetail", "label": "fetchStorageReleaseReviewDetail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L132"}, {"id": "api_storage_release_review_submitstoragereleasereview", "label": "submitStorageReleaseReview()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L138"}, {"id": "api_storage_release_review_batchreviewstoragerelease", "label": "batchReviewStorageRelease()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L152"}, {"id": "api_storage_release_review_storesample", "label": "storeSample()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L164"}, {"id": "api_storage_release_review_batchstoresample", "label": "batchStoreSample()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L170"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_http", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_qc_work_order", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "api_storage_release_review_fetchstoragereleasereviewlist", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L118", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "api_storage_release_review_fetchstoragereleasereviewdetail", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L132", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "api_storage_release_review_submitstoragereleasereview", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L138", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "api_storage_release_review_batchreviewstoragerelease", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L152", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "api_storage_release_review_storesample", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L164", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_storage_release_review_ts", "target": "api_storage_release_review_batchstoresample", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L170", "weight": 1.0}], "raw_calls": [{"caller_nid": "api_storage_release_review_fetchstoragereleasereviewlist", "callee": "get", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L126"}, {"caller_nid": "api_storage_release_review_fetchstoragereleasereviewdetail", "callee": "get", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts", "source_location": "L133"}, {"caller_nid": "api_storage_release_revLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "label": "StorageReleaseViewDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L1"}, {"id": "storage_release_review_storagereleaseviewdialog_formatmetric", "label": "formatMetric()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L211"}, {"id": "storage_release_review_storagereleaseviewdialog_attachmentfullurl", "label": "attachmentFullUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L428"}, {"id": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentpreview", "label": "handleReceptionAttachmentPreview()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L435"}, {"id": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentdownload", "label": "handleReceptionAttachmentDownload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L440"}, {"id": "storage_release_review_storagereleaseviewdialog_handleattachmentpreview", "label": "handleAttachmentPreview()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L444"}, {"id": "storage_release_review_storagereleaseviewdialog_handleattachmentdownload", "label": "handleAttachmentDownload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L448"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "target": "storage_release_review_storagereleaseviewdialog_formatmetric", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L211", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "target": "storage_release_review_storagereleaseviewdialog_attachmentfullurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L428", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "target": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentpreview", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L435", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "target": "storage_release_review_storagereleaseviewdialog_handlereceptionattachmentdownload", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L440", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "target": "storage_release_review_storagereleaseviewdialog_handleattachmentpreview", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L444", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_storage_release_review_storagereleaseviewdialog_vue", "target": "storage_release_review_storagereleaseviewdialog_handleattachmentdownload", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue", "source_location": "L448", "weightLine truncated
|
||||
+1
@@ -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": []}
|
||||
@@ -251,6 +251,20 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
|
||||
component: '/cell-storage/refund-confirm/index',
|
||||
meta: { title: '退费确认(财务)', keepAlive: true, menuCode: 'biz:cellStorageRefundConfirm:list' }
|
||||
},
|
||||
{
|
||||
id: '50000000000000000000000000000011',
|
||||
name: 'CellStorageSampleReceptionInfo',
|
||||
path: 'sample-reception-info',
|
||||
component: '/cell-storage/sample-reception-info/index',
|
||||
meta: { title: '样本接收信息', keepAlive: true, menuCode: 'cell-storage:sample-reception-info:list' }
|
||||
},
|
||||
{
|
||||
id: '50000000000000000000000000000012',
|
||||
name: 'CellStorageStorageEntryInfo',
|
||||
path: 'storage-entry-info',
|
||||
component: '/cell-storage/storage-entry-info/index',
|
||||
meta: { title: '样本入库信息', keepAlive: true, menuCode: 'cell-storage:storage-entry-info:list' }
|
||||
},
|
||||
{
|
||||
id: '50000000000000000000000000000006',
|
||||
name: 'CellStorageStorageCert',
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -85,14 +85,14 @@
|
||||
<el-table-column
|
||||
prop="storageYears"
|
||||
label="存储年限(年)"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="storagePrice"
|
||||
label="存储价格(元)"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -109,7 +109,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="320"
|
||||
min-width="320"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
|
||||
@@ -95,11 +95,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -114,7 +114,7 @@
|
||||
<el-table-column
|
||||
prop="issued"
|
||||
label="是否下发"
|
||||
width="80"
|
||||
min-width="80"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -159,7 +159,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="320"
|
||||
min-width="320"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -117,7 +117,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="400"
|
||||
min-width="400"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
@@ -231,11 +231,11 @@
|
||||
max-height="360"
|
||||
@selection-change="onHospitalSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -261,7 +261,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="260"
|
||||
min-width="260"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
|
||||
@@ -63,11 +63,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -79,7 +79,7 @@
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column prop="sex" label="性别" width="72" align="center" header-align="center">
|
||||
<el-table-column prop="sex" label="性别" min-width="72" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ sexLabel(row.sex) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -92,7 +92,7 @@
|
||||
<el-table-column
|
||||
prop="age"
|
||||
label="年龄"
|
||||
width="72"
|
||||
min-width="72"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -118,7 +118,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="320"
|
||||
min-width="320"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
|
||||
@@ -72,7 +72,7 @@
|
||||
<el-table-column prop="companyAddress" label="地址" min-width="180" align="center" header-align="center" />
|
||||
<el-table-column prop="contactName" label="联系人" min-width="100" align="center" header-align="center" />
|
||||
<el-table-column prop="contactPhone" label="联系电话" min-width="120" align="center" header-align="center" />
|
||||
<el-table-column prop="tag" label="状态" width="90" align="center" header-align="center">
|
||||
<el-table-column prop="tag" label="状态" min-width="90" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status == '1' ? 'success' : 'info'" size="small">{{ row.status == '1' ? '正常' : '停用' }}</el-tag>
|
||||
</template>
|
||||
@@ -196,13 +196,13 @@
|
||||
max-height="460"
|
||||
@selection-change="onItemSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="index" label="序号" width="68" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column type="index" label="序号" min-width="68" align="center" header-align="center" />
|
||||
<el-table-column prop="projectName" label="险种名称" min-width="160" align="center" header-align="center" />
|
||||
<el-table-column prop="projectFee" label="险种费用(元)" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="projectFee" label="险种费用(元)" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.projectFee != null ? `¥${row.projectFee}` : '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="90" align="center" header-align="center">
|
||||
<el-table-column prop="status" label="状态" min-width="90" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status == '1' ? 'success' : 'info'" size="small">{{ row.status == '1' ? '正常' : '停用' }}</el-tag>
|
||||
</template>
|
||||
|
||||
@@ -106,11 +106,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -125,7 +125,7 @@
|
||||
<el-table-column
|
||||
prop="sampleCodeType"
|
||||
label="编码类型"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -134,7 +134,7 @@
|
||||
<el-table-column
|
||||
prop="issued"
|
||||
label="是否下发"
|
||||
width="80"
|
||||
min-width="80"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -179,7 +179,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="320"
|
||||
min-width="320"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
|
||||
@@ -87,11 +87,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
|
||||
@@ -103,6 +103,19 @@
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="协议状态"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="protocolStatusTagType(String(row.protocolStatus || ''))" size="small">{{
|
||||
protocolStatusLabel(String(row.protocolStatus || ''))
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="motherName"
|
||||
label="母亲姓名"
|
||||
@@ -166,7 +179,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="260"
|
||||
min-width="260"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
@@ -461,6 +474,10 @@
|
||||
fetchInsuranceCompanyList,
|
||||
fetchInsuranceProjectPrices
|
||||
} from '@/api/admin'
|
||||
import {
|
||||
protocolStatusLabel,
|
||||
protocolStatusTagType,
|
||||
} from '@/utils/status-tag-registry'
|
||||
|
||||
defineOptions({ name: 'CellStorageFullmoonTodo' })
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
|
||||
@@ -76,11 +76,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -506,15 +506,15 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="56"
|
||||
min-width="56"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => index + 1"
|
||||
/>
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="120" align="center" header-align="center" />
|
||||
<el-table-column prop="materialName" label="物料名称" min-width="140" align="center" header-align="center" />
|
||||
<el-table-column prop="unit" label="单位" width="80" align="center" header-align="center" />
|
||||
<el-table-column label="当前库存" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="unit" label="单位" min-width="80" align="center" header-align="center" />
|
||||
<el-table-column label="当前库存" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.stockQty }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="入库数量" min-width="130" align="center" header-align="center">
|
||||
@@ -534,7 +534,7 @@
|
||||
<el-input v-model="row.remark" placeholder="可选" clearable class="inner-cell-input" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center" header-align="center">
|
||||
<el-table-column label="操作" min-width="80" align="center" header-align="center">
|
||||
<template #default="{ $index }">
|
||||
<el-button link type="danger" size="small" @click="batchStockInLines.splice($index, 1)">
|
||||
移除
|
||||
@@ -670,15 +670,15 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="56"
|
||||
min-width="56"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => index + 1"
|
||||
/>
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="120" align="center" header-align="center" />
|
||||
<el-table-column prop="materialName" label="物料名称" min-width="140" align="center" header-align="center" />
|
||||
<el-table-column prop="unit" label="单位" width="80" align="center" header-align="center" />
|
||||
<el-table-column label="当前库存" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="unit" label="单位" min-width="80" align="center" header-align="center" />
|
||||
<el-table-column label="当前库存" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.stockQty }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出库数量" min-width="130" align="center" header-align="center">
|
||||
@@ -699,7 +699,7 @@
|
||||
<el-input v-model="row.remark" placeholder="可选" clearable class="inner-cell-input" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center" header-align="center">
|
||||
<el-table-column label="操作" min-width="80" align="center" header-align="center">
|
||||
<template #default="{ $index }">
|
||||
<el-button link type="danger" size="small" @click="batchStockOutLines.splice($index, 1)">
|
||||
移除
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap payment-confirm-table-wrap">
|
||||
<el-table class="list-table" :data="tableData" v-loading="loading" stripe row-key="id">
|
||||
<el-table class="list-table" :data="tableData" v-loading="loading" stripe row-key="id" @row-dblclick="handleRowDblClick">
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -59,33 +59,33 @@
|
||||
>
|
||||
<template #default="{ row }">{{ maskIdCard(row.newbornIdCard) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="protocolStatus" label="协议状态" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="protocolStatus" label="协议状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="protocolStatusTagType(String(row.protocolStatus || ''))" size="small">{{ protocolStatusLabel(String(row.protocolStatus || '')) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payMode" label="缴费方式" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="payMode" label="缴费方式" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ payModeLabel(String(row.payMode || '')) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="installmentNo" label="期数" width="80" align="center" header-align="center">
|
||||
<el-table-column prop="installmentNo" label="期数" min-width="80" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.installmentNo ?? '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="installmentDueDate" label="应缴费时间" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="installmentDueDate" label="应缴费时间" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentDueDate(row.installmentDueDate) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dueAmount" label="应缴金额(元)" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="dueAmount" label="应缴金额(元)" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentAmount(row.dueAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transferAmount" label="实缴金额(元)" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="transferAmount" label="实缴金额(元)" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentAmount(row.transferAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transferType" label="转账方式" width="110" align="center" header-align="center">
|
||||
<el-table-column prop="transferType" label="转账方式" min-width="110" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ transferTypeLabel(String(row.transferType || '')) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transferTime" label="转账时间" min-width="170" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.transferTime || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payStatus" label="状态" width="110" align="center" header-align="center">
|
||||
<el-table-column prop="payStatus" label="状态" min-width="110" align="center" header-align="center">
|
||||
<template #default>
|
||||
<el-tag :type="activeTab === 'pending' ? 'warning' : 'success'" size="small">
|
||||
{{ activeTab === 'pending' ? '缴费确认中' : '已缴费' }}
|
||||
@@ -346,6 +346,11 @@
|
||||
viewDialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 双击行:非待确认 tab 时等同于点击「查看确认信息」 */
|
||||
function handleRowDblClick(row: Record<string, unknown>) {
|
||||
if (activeTab.value !== 'pending') openViewConfirm(row)
|
||||
}
|
||||
|
||||
async function submitConfirm() {
|
||||
if (!currentDetailId.value) return
|
||||
if (attachments.value.some((f) => f._uploading)) {
|
||||
|
||||
@@ -91,18 +91,19 @@
|
||||
row-key="id"
|
||||
:row-class-name="paymentRowClassName"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column
|
||||
v-if="activeTab === 'dfj' || activeTab === 'yjf'"
|
||||
type="selection"
|
||||
width="55"
|
||||
min-width="55"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -161,7 +162,7 @@
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="协议状态"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -172,7 +173,7 @@
|
||||
<el-table-column
|
||||
prop="payMode"
|
||||
label="缴费方式"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -183,14 +184,14 @@
|
||||
<el-table-column
|
||||
prop="installmentNo"
|
||||
label="期数"
|
||||
width="80"
|
||||
min-width="80"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="installmentDueDate"
|
||||
label="应缴费时间"
|
||||
width="130"
|
||||
min-width="130"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -201,7 +202,7 @@
|
||||
<el-table-column
|
||||
prop="dueAmount"
|
||||
label="应缴金额(元)"
|
||||
width="130"
|
||||
min-width="130"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -212,7 +213,7 @@
|
||||
<el-table-column
|
||||
prop="transferAmount"
|
||||
label="实缴金额(元)"
|
||||
width="130"
|
||||
min-width="130"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -223,7 +224,7 @@
|
||||
<el-table-column
|
||||
prop="transferType"
|
||||
label="转账方式"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -245,7 +246,7 @@
|
||||
<el-table-column
|
||||
prop="payStatus"
|
||||
label="状态"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
|
||||
@@ -89,11 +89,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -108,7 +108,7 @@
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="状态"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -121,7 +121,7 @@
|
||||
<el-table-column
|
||||
prop="registerDate"
|
||||
label="登记日期"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -156,7 +156,7 @@
|
||||
<el-table-column
|
||||
prop="newbornSex"
|
||||
label="新生儿性别"
|
||||
width="110"
|
||||
min-width="110"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -167,7 +167,7 @@
|
||||
<el-table-column
|
||||
prop="deliveryMode"
|
||||
label="分娩方式"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -178,7 +178,7 @@
|
||||
<el-table-column
|
||||
prop="newbornWeightGram"
|
||||
label="新生儿体重(克)"
|
||||
width="140"
|
||||
min-width="140"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
|
||||
@@ -44,7 +44,10 @@
|
||||
<div class="kpi-card__main">
|
||||
<div class="kpi-label">协议状态</div>
|
||||
<div class="kpi-value">
|
||||
<el-tag :type="protocolStatusTagType(String(protocol?.protocolStatus || ''))" size="small">
|
||||
<el-tag
|
||||
:type="protocolStatusTagType(String(protocol?.protocolStatus || ''))"
|
||||
size="small"
|
||||
>
|
||||
{{ protocolStatusLabel(String(protocol?.protocolStatus || '')) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
@@ -73,37 +76,92 @@
|
||||
<div id="view-section-basic" class="section-card section-card--white">
|
||||
<div class="section-title"><h3>基本信息</h3></div>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item"><div class="data-label">协议号</div><div class="data-value">{{ dash(protocol?.protocolNo) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议状态</div><div class="data-value"><el-tag :type="protocolStatusTagType(String(protocol?.protocolStatus || ''))" size="small">{{ protocolStatusLabel(String(protocol?.protocolStatus || '')) }}</el-tag></div></div>
|
||||
<div class="data-item"><div class="data-label">登记日期</div><div class="data-value">{{ formatYmd(protocol?.registerDate) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">采集专员</div><div class="data-value">{{ collectorDisplay }}</div></div>
|
||||
<div class="data-item"><div class="data-label">创建时间</div><div class="data-value">{{ dash(protocol?.createTime) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议号</div
|
||||
><div class="data-value">{{ dash(protocol?.protocolNo) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议状态</div
|
||||
><div class="data-value"
|
||||
><el-tag
|
||||
:type="protocolStatusTagType(String(protocol?.protocolStatus || ''))"
|
||||
size="small"
|
||||
>{{ protocolStatusLabel(String(protocol?.protocolStatus || '')) }}</el-tag
|
||||
></div
|
||||
></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">登记日期</div
|
||||
><div class="data-value">{{ formatYmd(protocol?.registerDate) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">采集专员</div
|
||||
><div class="data-value">{{ collectorDisplay }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">创建时间</div
|
||||
><div class="data-value">{{ dash(protocol?.createTime) }}</div></div
|
||||
>
|
||||
</div>
|
||||
<!-- 协议状态变更记录(非储存证查看:仍在基本信息内) -->
|
||||
<div v-if="!showStorageCert && hasAnyStatusChange" class="status-change-section">
|
||||
<div class="status-change-title">状态变更记录</div>
|
||||
<div class="data-grid data-grid--4">
|
||||
<template v-if="protocol?.effectiveTime">
|
||||
<div class="data-item"><div class="data-label">协议生效时间</div><div class="data-value">{{ dash(protocol.effectiveTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议生效描述</div><div class="data-value data-value--muted">{{ dash(protocol.effectiveDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议生效时间</div
|
||||
><div class="data-value">{{ dash(protocol.effectiveTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议生效描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.effectiveDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="protocol?.expireTime">
|
||||
<div class="data-item"><div class="data-label">协议过期时间</div><div class="data-value">{{ dash(protocol.expireTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议过期描述</div><div class="data-value data-value--muted">{{ dash(protocol.expireDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议过期时间</div
|
||||
><div class="data-value">{{ dash(protocol.expireTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议过期描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.expireDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="protocol?.voidTime">
|
||||
<div class="data-item"><div class="data-label">协议作废时间</div><div class="data-value">{{ dash(protocol.voidTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议作废描述</div><div class="data-value data-value--muted">{{ dash(protocol.voidDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议作废时间</div
|
||||
><div class="data-value">{{ dash(protocol.voidTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议作废描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.voidDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="protocol?.toResearchTime">
|
||||
<div class="data-item"><div class="data-label">协议转科研时间</div><div class="data-value">{{ dash(protocol.toResearchTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议转科研描述</div><div class="data-value data-value--muted">{{ dash(protocol.toResearchDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议转科研时间</div
|
||||
><div class="data-value">{{ dash(protocol.toResearchTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议转科研描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.toResearchDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 协议附件、备注同一行 -->
|
||||
<div
|
||||
v-if="protocolAttachments.length || (protocol?.remark && String(protocol.remark).trim())"
|
||||
v-if="
|
||||
protocolAttachments.length || (protocol?.remark && String(protocol.remark).trim())
|
||||
"
|
||||
class="data-grid data-grid--2 protocol-attach-remark-row"
|
||||
>
|
||||
<div class="data-item protocol-attachments-item">
|
||||
@@ -152,25 +210,61 @@
|
||||
</div>
|
||||
|
||||
<!-- 状态变更记录(储存证查看:独立区域) -->
|
||||
<div v-if="showStorageCert" id="view-section-status-change" class="section-card section-card--white">
|
||||
<div
|
||||
v-if="showStorageCert"
|
||||
id="view-section-status-change"
|
||||
class="section-card section-card--white"
|
||||
>
|
||||
<div class="section-title"><h3>状态变更记录</h3></div>
|
||||
<el-empty v-if="!hasAnyStatusChange" description="暂无状态变更记录" :image-size="64" />
|
||||
<div v-else class="data-grid data-grid--4">
|
||||
<template v-if="protocol?.effectiveTime">
|
||||
<div class="data-item"><div class="data-label">协议生效时间</div><div class="data-value">{{ dash(protocol.effectiveTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议生效描述</div><div class="data-value data-value--muted">{{ dash(protocol.effectiveDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议生效时间</div
|
||||
><div class="data-value">{{ dash(protocol.effectiveTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议生效描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.effectiveDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="protocol?.expireTime">
|
||||
<div class="data-item"><div class="data-label">协议过期时间</div><div class="data-value">{{ dash(protocol.expireTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议过期描述</div><div class="data-value data-value--muted">{{ dash(protocol.expireDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议过期时间</div
|
||||
><div class="data-value">{{ dash(protocol.expireTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议过期描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.expireDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="protocol?.voidTime">
|
||||
<div class="data-item"><div class="data-label">协议作废时间</div><div class="data-value">{{ dash(protocol.voidTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议作废描述</div><div class="data-value data-value--muted">{{ dash(protocol.voidDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议作废时间</div
|
||||
><div class="data-value">{{ dash(protocol.voidTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议作废描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.voidDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="protocol?.toResearchTime">
|
||||
<div class="data-item"><div class="data-label">协议转科研时间</div><div class="data-value">{{ dash(protocol.toResearchTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">协议转科研描述</div><div class="data-value data-value--muted">{{ dash(protocol.toResearchDesc) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议转科研时间</div
|
||||
><div class="data-value">{{ dash(protocol.toResearchTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">协议转科研描述</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(protocol.toResearchDesc)
|
||||
}}</div></div
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
@@ -181,39 +275,112 @@
|
||||
<div class="client-sub-cards">
|
||||
<!-- 母亲信息 -->
|
||||
<div class="client-sub-card">
|
||||
<div class="sub-card-header"><span class="sub-card-icon">🤱</span><h4>母亲信息</h4></div>
|
||||
<div class="sub-card-header"
|
||||
><span class="sub-card-icon">🤱</span><h4>母亲信息</h4></div
|
||||
>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item"><div class="data-label">关联客户</div><div class="data-value">{{ partyCustomer?.customerId ? dash(partyCustomer?.motherName) : '—' }}</div></div>
|
||||
<div class="data-item"><div class="data-label">母亲姓名</div><div class="data-value">{{ dash(partyCustomer?.motherName) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">母亲联系电话</div><div class="data-value">{{ dash(partyCustomer?.motherPhone) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">母亲身份证号</div><div class="data-value">{{ dash(partyCustomer?.motherIdCard) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">母亲出生年月</div><div class="data-value">{{ formatYm(partyCustomer?.motherBirthYm) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">母亲民族</div><div class="data-value">{{ dash(partyCustomer?.motherEthnic) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">关联客户</div
|
||||
><div class="data-value">{{
|
||||
partyCustomer?.customerId ? dash(partyCustomer?.motherName) : '—'
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">母亲姓名</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.motherName) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">母亲联系电话</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.motherPhone) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">母亲身份证号</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.motherIdCard) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">母亲出生年月</div
|
||||
><div class="data-value">{{ formatYm(partyCustomer?.motherBirthYm) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">母亲民族</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.motherEthnic) }}</div></div
|
||||
>
|
||||
</div>
|
||||
<div class="sub-card-full-row"><div class="data-label">母亲家庭住址</div><div class="data-value data-value--muted">{{ dash(partyCustomer?.motherAddress) }}</div></div>
|
||||
<div class="sub-card-full-row"
|
||||
><div class="data-label">母亲家庭住址</div
|
||||
><div class="data-value data-value--muted">{{
|
||||
dash(partyCustomer?.motherAddress)
|
||||
}}</div></div
|
||||
>
|
||||
</div>
|
||||
<!-- 父亲信息 -->
|
||||
<div class="client-sub-card">
|
||||
<div class="sub-card-header"><span class="sub-card-icon">👨</span><h4>父亲信息</h4></div>
|
||||
<div class="sub-card-header"
|
||||
><span class="sub-card-icon">👨</span><h4>父亲信息</h4></div
|
||||
>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item"><div class="data-label">父亲姓名</div><div class="data-value">{{ dash(partyCustomer?.fatherName) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">父亲电话</div><div class="data-value">{{ dash(partyCustomer?.fatherPhone) }}</div></div>
|
||||
<div class="data-item data-item--full"><div class="data-label">父亲身份证号</div><div class="data-value">{{ dash(partyCustomer?.fatherIdCard) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">父亲姓名</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.fatherName) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">父亲电话</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.fatherPhone) }}</div></div
|
||||
>
|
||||
<div class="data-item data-item--full"
|
||||
><div class="data-label">父亲身份证号</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.fatherIdCard) }}</div></div
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 新生儿信息 -->
|
||||
<div class="client-sub-card">
|
||||
<div class="sub-card-header"><span class="sub-card-icon">👶</span><h4>新生儿信息</h4></div>
|
||||
<div class="sub-card-header"
|
||||
><span class="sub-card-icon">👶</span><h4>新生儿信息</h4></div
|
||||
>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item"><div class="data-label">新生儿姓名</div><div class="data-value">{{ dash(partyCustomer?.newbornName) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">新生儿身份证</div><div class="data-value">{{ dash(partyCustomer?.newbornIdCard) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">新生儿分娩时间</div><div class="data-value">{{ dash(partyCustomer?.newbornDeliveryTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">新生儿性别</div><div class="data-value">{{ newbornSexLabel(String(partyCustomer?.newbornSex || '')) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">分娩方式</div><div class="data-value">{{ deliveryModeLabel(String(partyCustomer?.deliveryMode || '')) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">胎次</div><div class="data-value">{{ dash(partyCustomer?.birthOrder) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">新生儿体重(克)</div><div class="data-value">{{ dash(partyCustomer?.newbornWeightGram) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">新生儿评分1分钟</div><div class="data-value">{{ dash(partyCustomer?.apgar1min) }}</div></div>
|
||||
<div class="data-item data-item--full"><div class="data-label">新生儿评分5分钟</div><div class="data-value">{{ dash(partyCustomer?.apgar5min) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">新生儿姓名</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.newbornName) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">新生儿身份证</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.newbornIdCard) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">新生儿分娩时间</div
|
||||
><div class="data-value">{{
|
||||
dash(partyCustomer?.newbornDeliveryTime)
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">新生儿性别</div
|
||||
><div class="data-value">{{
|
||||
newbornSexLabel(String(partyCustomer?.newbornSex || ''))
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">分娩方式</div
|
||||
><div class="data-value">{{
|
||||
deliveryModeLabel(String(partyCustomer?.deliveryMode || ''))
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">胎次</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.birthOrder) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">新生儿体重(克)</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.newbornWeightGram) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">新生儿评分1分钟</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.apgar1min) }}</div></div
|
||||
>
|
||||
<div class="data-item data-item--full"
|
||||
><div class="data-label">新生儿评分5分钟</div
|
||||
><div class="data-value">{{ dash(partyCustomer?.apgar5min) }}</div></div
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -227,12 +394,17 @@
|
||||
>
|
||||
<div class="section-title"><h3>新生儿保险信息</h3></div>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item"><div class="data-label">满月日期</div><div class="data-value">{{ dash(fullmoonInsuranceInfo?.fullmoonDate) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">满月日期</div
|
||||
><div class="data-value">{{ dash(fullmoonInsuranceInfo?.fullmoonDate) }}</div></div
|
||||
>
|
||||
<div class="data-item">
|
||||
<div class="data-label">待办状态</div>
|
||||
<div class="data-value">
|
||||
<el-tag
|
||||
:type="fullmoonTodoStatusTagType(String(fullmoonInsuranceInfo?.todoStatus || '0'))"
|
||||
:type="
|
||||
fullmoonTodoStatusTagType(String(fullmoonInsuranceInfo?.todoStatus || '0'))
|
||||
"
|
||||
size="small"
|
||||
>
|
||||
{{ fullmoonTodoStatusLabel(String(fullmoonInsuranceInfo?.todoStatus || '0')) }}
|
||||
@@ -243,25 +415,68 @@
|
||||
<div class="data-label">是否已订购保险</div>
|
||||
<div class="data-value">
|
||||
<el-tag
|
||||
:type="insuranceSubscribedTagType(String(fullmoonInsuranceInfo?.insuranceSubscribed || '0'))"
|
||||
:type="
|
||||
insuranceSubscribedTagType(
|
||||
String(fullmoonInsuranceInfo?.insuranceSubscribed || '0')
|
||||
)
|
||||
"
|
||||
size="small"
|
||||
>
|
||||
{{ insuranceSubscribedLabel(String(fullmoonInsuranceInfo?.insuranceSubscribed || '0')) }}
|
||||
{{
|
||||
insuranceSubscribedLabel(
|
||||
String(fullmoonInsuranceInfo?.insuranceSubscribed || '0')
|
||||
)
|
||||
}}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-item"><div class="data-label">保险公司</div><div class="data-value">{{ dash(fullmoonInsuranceInfo?.insuranceCompanyName) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">保险险种</div><div class="data-value">{{ dash(fullmoonInsuranceInfo?.insuranceType) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">保险单号</div><div class="data-value">{{ dash(fullmoonInsuranceInfo?.insurancePolicyNo) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">保单费用(元)</div><div class="data-value">{{ formatMoney(fullmoonInsuranceInfo?.insuranceFee) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">保险单生效时间</div><div class="data-value">{{ formatYmd(fullmoonInsuranceInfo?.insuranceEffectiveDate) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">保险单失效时间</div><div class="data-value">{{ formatYmd(fullmoonInsuranceInfo?.insuranceExpiryDate) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">办理日期</div><div class="data-value">{{ formatYmd(fullmoonInsuranceInfo?.handleDate) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">保险公司</div
|
||||
><div class="data-value">{{
|
||||
dash(fullmoonInsuranceInfo?.insuranceCompanyName)
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">保险险种</div
|
||||
><div class="data-value">{{ dash(fullmoonInsuranceInfo?.insuranceType) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">保险单号</div
|
||||
><div class="data-value">{{
|
||||
dash(fullmoonInsuranceInfo?.insurancePolicyNo)
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">保单费用(元)</div
|
||||
><div class="data-value">{{
|
||||
formatMoney(fullmoonInsuranceInfo?.insuranceFee)
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">保险单生效时间</div
|
||||
><div class="data-value">{{
|
||||
formatYmd(fullmoonInsuranceInfo?.insuranceEffectiveDate)
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">保险单失效时间</div
|
||||
><div class="data-value">{{
|
||||
formatYmd(fullmoonInsuranceInfo?.insuranceExpiryDate)
|
||||
}}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">办理日期</div
|
||||
><div class="data-value">{{
|
||||
formatYmd(fullmoonInsuranceInfo?.handleDate)
|
||||
}}</div></div
|
||||
>
|
||||
</div>
|
||||
<div v-if="fullmoonInsuranceInfo?.handleRemark" class="remark-row">
|
||||
<div class="data-item data-item--full">
|
||||
<div class="data-label">办理备注</div>
|
||||
<div class="data-value data-value--muted">{{ dash(fullmoonInsuranceInfo?.handleRemark) }}</div>
|
||||
<div class="data-value data-value--muted">{{
|
||||
dash(fullmoonInsuranceInfo?.handleRemark)
|
||||
}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attachment-row">
|
||||
@@ -280,12 +495,32 @@
|
||||
<div id="view-section-collection" class="section-card section-card--white">
|
||||
<div class="section-title"><h3>采集信息</h3></div>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item"><div class="data-label">采集地区</div><div class="data-value">{{ regionDisplay }}</div></div>
|
||||
<div class="data-item"><div class="data-label">采集医院</div><div class="data-value">{{ hospitalDisplay }}</div></div>
|
||||
<div class="data-item"><div class="data-label">采集医护</div><div class="data-value">{{ dash(collectionInfo?.medicalStaff) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">销售人员</div><div class="data-value">{{ salesDisplay }}</div></div>
|
||||
<div class="data-item"><div class="data-label">样本采集时间</div><div class="data-value">{{ dash(collectionInfo?.sampleCollectTime) }}</div></div>
|
||||
<div class="data-item"><div class="data-label">母血采集时间</div><div class="data-value">{{ dash(collectionInfo?.maternalBloodCollectTime) }}</div></div>
|
||||
<div class="data-item"
|
||||
><div class="data-label">采集地区</div
|
||||
><div class="data-value">{{ regionDisplay }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">采集医院</div
|
||||
><div class="data-value">{{ hospitalDisplay }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">采集医护</div
|
||||
><div class="data-value">{{ dash(collectionInfo?.medicalStaff) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">销售人员</div
|
||||
><div class="data-value">{{ salesDisplay }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">样本采集时间</div
|
||||
><div class="data-value">{{ dash(collectionInfo?.sampleCollectTime) }}</div></div
|
||||
>
|
||||
<div class="data-item"
|
||||
><div class="data-label">母血采集时间</div
|
||||
><div class="data-value">{{
|
||||
dash(collectionInfo?.maternalBloodCollectTime)
|
||||
}}</div></div
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -297,11 +532,7 @@
|
||||
>
|
||||
<div class="section-title"><h3>样本及运输信息</h3></div>
|
||||
<div v-if="samples.length" class="sample-cards">
|
||||
<div
|
||||
v-for="(row, sIdx) in samples"
|
||||
:key="row.id || sIdx"
|
||||
class="sample-card"
|
||||
>
|
||||
<div v-for="(row, sIdx) in samples" :key="row.id || sIdx" class="sample-card">
|
||||
<div class="sample-card__header">
|
||||
<div class="sample-card__title">
|
||||
<span class="sample-card__seq">{{ sIdx + 1 }}</span>
|
||||
@@ -321,11 +552,15 @@
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">采集量</div>
|
||||
<div class="data-value">{{ dash(row.collectAmount) }} {{ unitName(row.unitId) }}</div>
|
||||
<div class="data-value"
|
||||
>{{ dash(row.collectAmount) }} {{ unitName(row.unitId) }}</div
|
||||
>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">价格(元)</div>
|
||||
<div class="data-value data-value--price">{{ row.price ? `¥${row.price}` : '—' }}</div>
|
||||
<div class="data-value data-value--price">{{
|
||||
row.price ? `¥${row.price}` : '—'
|
||||
}}</div>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">存储年限(年)</div>
|
||||
@@ -337,16 +572,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="row.transport?.transportType" class="sample-card__section sample-card__section--transport">
|
||||
<div
|
||||
v-if="row.transport?.transportType"
|
||||
class="sample-card__section sample-card__section--transport"
|
||||
>
|
||||
<div class="sample-card__section-label">运输信息</div>
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item">
|
||||
<div class="data-label">运输类型</div>
|
||||
<div class="data-value">{{ transportTypeLabel(String(row.transport?.transportType || '')) }}</div>
|
||||
<div class="data-value">{{
|
||||
transportTypeLabel(String(row.transport?.transportType || ''))
|
||||
}}</div>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">目的站点</div>
|
||||
<div class="data-value">{{ siteName(String(row.transport?.destSiteId || '')) }}</div>
|
||||
<div class="data-value">{{
|
||||
siteName(String(row.transport?.destSiteId || ''))
|
||||
}}</div>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">预计到达</div>
|
||||
@@ -364,7 +606,9 @@
|
||||
<div class="data-grid data-grid--4">
|
||||
<div class="data-item">
|
||||
<div class="data-label">接收时间</div>
|
||||
<div class="data-value">{{ dash(row.sampleReception.receptionTime) }}</div>
|
||||
<div class="data-value">{{
|
||||
dash(row.sampleReception.receptionTime)
|
||||
}}</div>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">经手人</div>
|
||||
@@ -382,17 +626,32 @@
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">体积(ml)</div>
|
||||
<div class="data-value">{{ formatMetric(row.sampleReception.volumeMl) }}</div>
|
||||
<div class="data-value">{{
|
||||
formatMetric(row.sampleReception.volumeMl)
|
||||
}}</div>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">净重(g)</div>
|
||||
<div class="data-value">{{ formatMetric(row.sampleReception.netWeightG) }}</div>
|
||||
<div class="data-value">{{
|
||||
formatMetric(row.sampleReception.netWeightG)
|
||||
}}</div>
|
||||
</div>
|
||||
<div class="data-item">
|
||||
<div class="data-label">结论</div>
|
||||
<div class="data-value">
|
||||
<el-tag :type="acceptConclusionTagType(String(row.sampleReception.acceptConclusion || ''))" size="small">
|
||||
{{ acceptConclusionLabel(String(row.sampleReception.acceptConclusion || '')) }}
|
||||
<el-tag
|
||||
:type="
|
||||
acceptConclusionTagType(
|
||||
String(row.sampleReception.acceptConclusion || '')
|
||||
)
|
||||
"
|
||||
size="small"
|
||||
>
|
||||
{{
|
||||
acceptConclusionLabel(
|
||||
String(row.sampleReception.acceptConclusion || '')
|
||||
)
|
||||
}}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
@@ -415,7 +674,9 @@
|
||||
</div>
|
||||
<div v-if="row.sampleReception.remark" class="data-item data-item--full">
|
||||
<div class="data-label">备注</div>
|
||||
<div class="data-value data-value--muted">{{ dash(row.sampleReception.remark) }}</div>
|
||||
<div class="data-value data-value--muted">{{
|
||||
dash(row.sampleReception.remark)
|
||||
}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -432,7 +693,12 @@
|
||||
</template>
|
||||
<div v-else class="sample-reception-empty">暂未接收</div>
|
||||
</div>
|
||||
<SampleQcInfoCards :qc-info="row.qcInfo" :sample-reception="row.sampleReception" />
|
||||
<SampleQcInfoCards
|
||||
:qc-info="row.qcInfo"
|
||||
:sample-reception="row.sampleReception"
|
||||
/>
|
||||
<SampleProductionInfoCards :production-info="row.productionInfo" />
|
||||
<SampleStorageReleaseInfo :storage-release-info="row.storageReleaseInfo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -444,16 +710,41 @@
|
||||
<div class="section-title"><h3>缴费信息</h3></div>
|
||||
<!-- 缴费主表指标卡 -->
|
||||
<div class="payment-summary">
|
||||
<div class="payment-metric"><div class="pm-label">缴费模式</div><div class="pm-value">{{ payModeLabel(String(payment?.payMode || '')) }}</div></div>
|
||||
<div class="payment-metric"><div class="pm-label">合同金额(元)</div><div class="pm-value pm-value--amount">{{ payment?.contractAmount ? `¥${payment.contractAmount}` : '—' }}</div></div>
|
||||
<div class="payment-metric"><div class="pm-label">已收金额(元)</div><div class="pm-value pm-value--amount pm-value--received">{{ receivedAmount ? `¥${receivedAmount}` : '—' }}</div></div>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">缴费模式</div
|
||||
><div class="pm-value">{{ payModeLabel(String(payment?.payMode || '')) }}</div></div
|
||||
>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">合同金额(元)</div
|
||||
><div class="pm-value pm-value--amount">{{
|
||||
payment?.contractAmount ? `¥${payment.contractAmount}` : '—'
|
||||
}}</div></div
|
||||
>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">已收金额(元)</div
|
||||
><div class="pm-value pm-value--amount pm-value--received">{{
|
||||
receivedAmount ? `¥${receivedAmount}` : '—'
|
||||
}}</div></div
|
||||
>
|
||||
<template v-if="payment?.payMode === 'dj'">
|
||||
<div class="payment-metric"><div class="pm-label">趸交截止时间</div><div class="pm-value">{{ formatYmd(payment?.lumpSumDeadline) }}</div></div>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">趸交截止时间</div
|
||||
><div class="pm-value">{{ formatYmd(payment?.lumpSumDeadline) }}</div></div
|
||||
>
|
||||
</template>
|
||||
<template v-if="payment?.payMode === 'fq'">
|
||||
<div class="payment-metric"><div class="pm-label">分期期数</div><div class="pm-value">{{ dash(payment?.installmentCount) }}</div></div>
|
||||
<div class="payment-metric"><div class="pm-label">每期间隔(月)</div><div class="pm-value">{{ dash(payment?.installmentIntervalMonths) }}</div></div>
|
||||
<div class="payment-metric"><div class="pm-label">分期开始时间</div><div class="pm-value">{{ formatYmd(payment?.installmentStartDate) }}</div></div>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">分期期数</div
|
||||
><div class="pm-value">{{ dash(payment?.installmentCount) }}</div></div
|
||||
>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">每期间隔(月)</div
|
||||
><div class="pm-value">{{ dash(payment?.installmentIntervalMonths) }}</div></div
|
||||
>
|
||||
<div class="payment-metric"
|
||||
><div class="pm-label">分期开始时间</div
|
||||
><div class="pm-value">{{ formatYmd(payment?.installmentStartDate) }}</div></div
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
<!-- 缴费明细 -->
|
||||
@@ -491,7 +782,9 @@
|
||||
<div class="pdc-info-row">
|
||||
<div class="pdc-info-item">
|
||||
<span class="info-label">应缴费金额(元)</span>
|
||||
<span class="info-value">{{ detail.dueAmount ? `¥${detail.dueAmount}` : '—' }}</span>
|
||||
<span class="info-value">{{
|
||||
detail.dueAmount ? `¥${detail.dueAmount}` : '—'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="pdc-info-item">
|
||||
<span class="info-label">转账方式</span>
|
||||
@@ -501,7 +794,9 @@
|
||||
</div>
|
||||
<div class="pdc-info-item">
|
||||
<span class="info-label">转账金额(元)</span>
|
||||
<span class="info-value">{{ detail.transferAmount ? `¥${detail.transferAmount}` : '—' }}</span>
|
||||
<span class="info-value">{{
|
||||
detail.transferAmount ? `¥${detail.transferAmount}` : '—'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="pdc-info-item">
|
||||
<span class="info-label">转账时间</span>
|
||||
@@ -543,11 +838,7 @@
|
||||
:style="miniFlowConnectorStyle(flowSteps.length, sIdx)"
|
||||
/>
|
||||
</template>
|
||||
<div
|
||||
v-for="step in flowSteps"
|
||||
:key="step.key"
|
||||
class="mini-flow-step"
|
||||
>
|
||||
<div v-for="step in flowSteps" :key="step.key" class="mini-flow-step">
|
||||
<div class="mini-flow-dot" :class="step.dotClass">
|
||||
{{ step.dotIcon }}
|
||||
</div>
|
||||
@@ -565,21 +856,32 @@
|
||||
:class="'flow-detail-card--' + step.dotClass"
|
||||
>
|
||||
<div class="flow-detail-card__header">
|
||||
<span class="flow-detail-card__dot" :class="step.dotClass">{{ step.dotIcon }}</span>
|
||||
<span class="flow-detail-card__title" :class="step.labelClass">{{ step.label }}</span>
|
||||
<span class="flow-detail-card__dot" :class="step.dotClass">{{
|
||||
step.dotIcon
|
||||
}}</span>
|
||||
<span class="flow-detail-card__title" :class="step.labelClass">{{
|
||||
step.label
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flow-detail-card__body">
|
||||
<template v-if="step.key === 'pay'">
|
||||
<!-- 缴费确认 -->
|
||||
<div class="flow-detail-card__kv">
|
||||
<span class="flow-detail-card__label">确认状态</span>
|
||||
<span class="flow-detail-card__value"><el-tag type="success" size="small">已缴费</el-tag></span>
|
||||
<span class="flow-detail-card__value"
|
||||
><el-tag type="success" size="small">已缴费</el-tag></span
|
||||
>
|
||||
</div>
|
||||
<div v-if="detail.transferTime" class="flow-detail-card__kv">
|
||||
<span class="flow-detail-card__label">缴费时间</span>
|
||||
<span class="flow-detail-card__value">{{ detail.transferTime }}</span>
|
||||
<span class="flow-detail-card__value">{{
|
||||
detail.transferTime
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="detailAttachments(detail).length" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="detailAttachments(detail).length"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">转账凭证</span>
|
||||
<ProtocolAttachmentReadonly
|
||||
:files="detailAttachments(detail)"
|
||||
@@ -592,17 +894,27 @@
|
||||
<!-- 财务确认 -->
|
||||
<div class="flow-detail-card__kv">
|
||||
<span class="flow-detail-card__label">确认状态</span>
|
||||
<span class="flow-detail-card__value"><el-tag type="success" size="small">已确认</el-tag></span>
|
||||
<span class="flow-detail-card__value"
|
||||
><el-tag type="success" size="small">已确认</el-tag></span
|
||||
>
|
||||
</div>
|
||||
<div v-if="detail.updateTime" class="flow-detail-card__kv">
|
||||
<span class="flow-detail-card__label">确认时间</span>
|
||||
<span class="flow-detail-card__value">{{ detail.updateTime }}</span>
|
||||
</div>
|
||||
<div v-if="detail.financeRemark && String(detail.financeRemark).trim()" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="detail.financeRemark && String(detail.financeRemark).trim()"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">财务备注</span>
|
||||
<span class="flow-detail-card__value">{{ detail.financeRemark }}</span>
|
||||
<span class="flow-detail-card__value">{{
|
||||
detail.financeRemark
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="financeConfirmAttachmentFiles(detail).length" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="financeConfirmAttachmentFiles(detail).length"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">财务附件</span>
|
||||
<ProtocolAttachmentReadonly
|
||||
:files="financeConfirmAttachmentFiles(detail)"
|
||||
@@ -618,13 +930,22 @@
|
||||
<span
|
||||
class="flow-detail-card__value"
|
||||
:class="payDetailColorClass(String(detail.payStatus || ''))"
|
||||
>{{ detail.refundAmount ? `¥${detail.refundAmount}` : '—' }}</span>
|
||||
>{{ detail.refundAmount ? `¥${detail.refundAmount}` : '—' }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="detail.refundRemark && String(detail.refundRemark).trim()" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="detail.refundRemark && String(detail.refundRemark).trim()"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">退费备注</span>
|
||||
<span class="flow-detail-card__value">{{ detail.refundRemark }}</span>
|
||||
<span class="flow-detail-card__value">{{
|
||||
detail.refundRemark
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="refundAttachmentFiles(detail).length" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="refundAttachmentFiles(detail).length"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">退费附件</span>
|
||||
<ProtocolAttachmentReadonly
|
||||
:files="refundAttachmentFiles(detail)"
|
||||
@@ -637,17 +958,30 @@
|
||||
<!-- 退费确认(已退费) -->
|
||||
<div class="flow-detail-card__kv">
|
||||
<span class="flow-detail-card__label">确认状态</span>
|
||||
<span class="flow-detail-card__value"><el-tag type="danger" size="small">已退费</el-tag></span>
|
||||
<span class="flow-detail-card__value"
|
||||
><el-tag type="danger" size="small">已退费</el-tag></span
|
||||
>
|
||||
</div>
|
||||
<div v-if="detail.updateTime" class="flow-detail-card__kv">
|
||||
<span class="flow-detail-card__label">确认时间</span>
|
||||
<span class="flow-detail-card__value">{{ detail.updateTime }}</span>
|
||||
</div>
|
||||
<div v-if="detail.refundFinanceRemark && String(detail.refundFinanceRemark).trim()" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="
|
||||
detail.refundFinanceRemark &&
|
||||
String(detail.refundFinanceRemark).trim()
|
||||
"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">财务备注</span>
|
||||
<span class="flow-detail-card__value">{{ detail.refundFinanceRemark }}</span>
|
||||
<span class="flow-detail-card__value">{{
|
||||
detail.refundFinanceRemark
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="refundFinanceConfirmAttachmentFiles(detail).length" class="flow-detail-card__kv">
|
||||
<div
|
||||
v-if="refundFinanceConfirmAttachmentFiles(detail).length"
|
||||
class="flow-detail-card__kv"
|
||||
>
|
||||
<span class="flow-detail-card__label">财务附件</span>
|
||||
<ProtocolAttachmentReadonly
|
||||
:files="refundFinanceConfirmAttachmentFiles(detail)"
|
||||
@@ -694,9 +1028,7 @@
|
||||
<div class="timeline-label" :class="step.labelClass">
|
||||
{{ step.label }}
|
||||
<br />
|
||||
<span style="font-size: 10px; font-weight: 400">{{
|
||||
step.subLabel
|
||||
}}</span>
|
||||
<span style="font-size: 10px; font-weight: 400">{{ step.subLabel }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -705,7 +1037,11 @@
|
||||
</div>
|
||||
|
||||
<!-- 审核记录 -->
|
||||
<div v-if="showAuditHistory" id="view-section-audit" class="section-card section-card--white">
|
||||
<div
|
||||
v-if="showAuditHistory"
|
||||
id="view-section-audit"
|
||||
class="section-card section-card--white"
|
||||
>
|
||||
<div class="section-title"><h3>审核记录</h3></div>
|
||||
<el-table
|
||||
v-loading="auditLoading"
|
||||
@@ -717,7 +1053,7 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -731,7 +1067,7 @@
|
||||
<el-table-column
|
||||
prop="auditStatus"
|
||||
label="审核状态"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -798,6 +1134,8 @@
|
||||
import { Calendar, CircleCheck, Close, Document, User } from '@element-plus/icons-vue'
|
||||
import ProtocolAttachmentReadonly from './ProtocolAttachmentReadonly.vue'
|
||||
import SampleQcInfoCards from '@/components/business/sample-qc-info-cards/index.vue'
|
||||
import SampleProductionInfoCards from '@/components/business/sample-production-info-cards/index.vue'
|
||||
import SampleStorageReleaseInfo from '@/components/business/sample-storage-release-info/index.vue'
|
||||
import {
|
||||
fetchCollectionProtocolAuditList,
|
||||
fetchCollectionProtocolDetail,
|
||||
@@ -1215,9 +1553,7 @@
|
||||
const steps: OverviewTimelineStep[] = details.map((d, i) => {
|
||||
const s = String(d.payStatus || '')
|
||||
const name =
|
||||
payment.value?.payMode === 'fq'
|
||||
? `第${d.installmentNo || i + 1}期`
|
||||
: `缴费${i + 1}`
|
||||
payment.value?.payMode === 'fq' ? `第${d.installmentNo || i + 1}期` : `缴费${i + 1}`
|
||||
|
||||
if (s === 'ytf') {
|
||||
return {
|
||||
@@ -1379,12 +1715,15 @@
|
||||
|
||||
function urlsToAttachmentFiles(urls: string) {
|
||||
if (!urls.trim()) return []
|
||||
return urls.split(',').map((u, i) => {
|
||||
return urls
|
||||
.split(',')
|
||||
.map((u, i) => {
|
||||
const url = u.trim()
|
||||
if (!url) return null
|
||||
const name = url.includes('/') ? url.split('/').pop() || `附件${i + 1}` : url
|
||||
return { id: `url_${i}`, fileUrl: url, fileName: name, fileSize: 0 }
|
||||
}).filter(Boolean) as Array<Record<string, any>>
|
||||
})
|
||||
.filter(Boolean) as Array<Record<string, any>>
|
||||
}
|
||||
|
||||
function hasFinanceRemark(detail: Record<string, any>) {
|
||||
@@ -1577,10 +1916,7 @@
|
||||
try {
|
||||
const pno =
|
||||
String(
|
||||
protocolNoHint ||
|
||||
protocol.value?.protocolNo ||
|
||||
props.listRow?.protocolNo ||
|
||||
''
|
||||
protocolNoHint || protocol.value?.protocolNo || props.listRow?.protocolNo || ''
|
||||
).trim() || undefined
|
||||
const res = await fetchCollectionProtocolAuditList({
|
||||
page: 1,
|
||||
@@ -1606,9 +1942,7 @@
|
||||
const protocolNoHint = String(props.listRow?.protocolNo || '').trim()
|
||||
const baseLookupsPromise = loadBaseLookups().catch(() => {})
|
||||
const auditEarlyPromise =
|
||||
props.showAuditHistory && protocolNoHint
|
||||
? loadAuditRecords(protocolNoHint)
|
||||
: null
|
||||
props.showAuditHistory && protocolNoHint ? loadAuditRecords(protocolNoHint) : null
|
||||
|
||||
let data: Record<string, any> | null = null
|
||||
try {
|
||||
@@ -1787,7 +2121,9 @@
|
||||
padding: 22px 24px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
transition:
|
||||
transform 0.2s,
|
||||
box-shadow 0.2s;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
@@ -1956,7 +2292,9 @@
|
||||
padding: 18px 20px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid rgba(0, 0, 0, 0.03);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
transition:
|
||||
transform 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
@@ -2011,7 +2349,9 @@
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
overflow: hidden;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
transition:
|
||||
transform 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
|
||||
@@ -73,11 +73,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -92,7 +92,7 @@
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="状态"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -105,7 +105,7 @@
|
||||
<el-table-column
|
||||
prop="registerDate"
|
||||
label="登记日期"
|
||||
width="120"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -140,7 +140,7 @@
|
||||
<el-table-column
|
||||
prop="newbornSex"
|
||||
label="新生儿性别"
|
||||
width="110"
|
||||
min-width="110"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -151,7 +151,7 @@
|
||||
<el-table-column
|
||||
prop="deliveryMode"
|
||||
label="分娩方式"
|
||||
width="100"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
@@ -162,7 +162,7 @@
|
||||
<el-table-column
|
||||
prop="newbornWeightGram"
|
||||
label="新生儿体重(克)"
|
||||
width="140"
|
||||
min-width="140"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -210,7 +210,7 @@
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="320"
|
||||
min-width="320"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap refund-confirm-table-wrap">
|
||||
<el-table class="list-table" :data="tableData" v-loading="loading" stripe row-key="id">
|
||||
<el-table class="list-table" :data="tableData" v-loading="loading" stripe row-key="id" @row-dblclick="handleRowDblClick">
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -59,33 +59,33 @@
|
||||
>
|
||||
<template #default="{ row }">{{ maskIdCard(row.newbornIdCard) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="protocolStatus" label="协议状态" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="protocolStatus" label="协议状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="protocolStatusTagType(String(row.protocolStatus || ''))" size="small">{{ protocolStatusLabel(String(row.protocolStatus || '')) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payMode" label="缴费方式" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="payMode" label="缴费方式" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ payModeLabel(String(row.payMode || '')) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="installmentNo" label="期数" width="80" align="center" header-align="center">
|
||||
<el-table-column prop="installmentNo" label="期数" min-width="80" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.installmentNo ?? '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="installmentDueDate" label="应缴费时间" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="installmentDueDate" label="应缴费时间" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentDueDate(row.installmentDueDate) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="dueAmount" label="应缴金额(元)" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="dueAmount" label="应缴金额(元)" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentAmount(row.dueAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transferAmount" label="实缴金额(元)" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="transferAmount" label="实缴金额(元)" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentAmount(row.transferAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transferType" label="转账方式" width="110" align="center" header-align="center">
|
||||
<el-table-column prop="transferType" label="转账方式" min-width="110" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ transferTypeLabel(String(row.transferType || '')) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transferTime" label="转账时间" min-width="170" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.transferTime || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="refundAmount" label="退费金额(元)" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="refundAmount" label="退费金额(元)" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ formatPaymentAmount(row.refundAmount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -98,7 +98,7 @@
|
||||
>
|
||||
<template #default="{ row }">{{ row.refundRemark || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payStatus" label="状态" width="110" align="center" header-align="center">
|
||||
<el-table-column prop="payStatus" label="状态" min-width="110" align="center" header-align="center">
|
||||
<template #default>
|
||||
<el-tag :type="activeTab === 'pending' ? 'warning' : 'success'" size="small">
|
||||
{{ activeTab === 'pending' ? '退费确认中' : '已退费' }}
|
||||
@@ -363,6 +363,11 @@
|
||||
viewDialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 双击行:非待确认 tab 时等同于点击「查看确认信息」 */
|
||||
function handleRowDblClick(row: Record<string, unknown>) {
|
||||
if (activeTab.value !== 'pending') openViewConfirm(row)
|
||||
}
|
||||
|
||||
async function submitConfirm() {
|
||||
if (!currentDetailId.value) return
|
||||
if (attachments.value.some((f) => f._uploading)) {
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
<!-- 样本接收信息 -->
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<header class="page-head">
|
||||
<h1>样本接收信息</h1>
|
||||
<p class="page-desc">查看样本接收信息,提取短信通知内容并管理通知状态。</p>
|
||||
</header>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-top">
|
||||
<h2 class="title-bar-heading">样本接收列表</h2>
|
||||
</div>
|
||||
|
||||
<div class="filter-block">
|
||||
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
||||
<div class="filter-grid">
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="searchForm.keyword" placeholder="协议号/姓名/样本编码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="接收结论">
|
||||
<el-select v-model="searchForm.acceptConclusion" placeholder="全部" clearable style="width: 100%">
|
||||
<el-option label="接收" value="js" />
|
||||
<el-option label="拒收" value="bj" />
|
||||
<el-option label="待接收确认" value="dqr" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知状态">
|
||||
<el-select v-model="searchForm.smsNotified" placeholder="全部" clearable style="width: 100%">
|
||||
<el-option label="已通知" value="1" />
|
||||
<el-option label="未通知" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="filter-actions-row">
|
||||
<div class="filter-actions-end">
|
||||
<el-button class="btn-ghost" @click="handleReset">
|
||||
<el-icon><RefreshLeft /></el-icon>重置
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" @click="handleSearch">
|
||||
<el-icon><Search /></el-icon>搜索
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<el-table
|
||||
class="list-table"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
row-key="id"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
|
||||
/>
|
||||
<el-table-column prop="protocolNo" label="协议号" min-width="140" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="协议状态"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="protocolStatusTagType(String(row.protocolStatus || ''))" size="small">{{
|
||||
protocolStatusLabel(String(row.protocolStatus || ''))
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="motherName" label="母亲姓名" min-width="100" align="center" header-align="center" />
|
||||
<el-table-column prop="newbornName" label="新生儿姓名" min-width="110" align="center" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="sampleCode" label="样本编码" min-width="130" align="center" header-align="center" />
|
||||
<el-table-column prop="sampleTypeName" label="样本类型" min-width="110" align="center" header-align="center" />
|
||||
<el-table-column prop="receptionTime" label="接收时间" min-width="170" align="center" header-align="center" />
|
||||
<el-table-column prop="acceptConclusion" label="接收结论" min-width="110" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="row.acceptConclusion === 'js' ? 'success' : row.acceptConclusion === 'bj' ? 'danger' : 'warning'"
|
||||
size="small"
|
||||
>
|
||||
{{ row.acceptConclusionLabel || (row.acceptConclusion === 'js' ? '接收' : row.acceptConclusion === 'bj' ? '拒收' : '待接收确认') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="smsNotified" label="通知状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.smsNotified == 1 ? 'success' : 'info'" size="small">
|
||||
{{ row.smsNotified == 1 ? '已通知' : '未通知' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="260" fixed="right" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button class="btn-op-item primary" @click="handleView(row)">
|
||||
<el-icon><View /></el-icon>查看
|
||||
</el-button>
|
||||
<el-button class="btn-op-item" @click="handleExtractSms(row)">
|
||||
<el-icon><ChatDotRound /></el-icon>提取短信
|
||||
</el-button>
|
||||
<el-button class="btn-op-item" @click="handleToggleNotified(row)">
|
||||
<el-icon><Bell /></el-icon>{{ row.smsNotified == 1 ? '标记未通知' : '标记已通知' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination list-pager-bar">
|
||||
<el-pagination
|
||||
:current-page="pagination.page"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
|
||||
@current-change="(val) => ((pagination.page = val), loadData())"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ProtocolViewDialog
|
||||
v-model="viewVisible"
|
||||
:protocol-id="viewProtocolId"
|
||||
:list-row="viewRow"
|
||||
show-audit-history
|
||||
show-storage-cert
|
||||
show-fullmoon-insurance
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Search, RefreshLeft, View, ChatDotRound, Bell } from '@element-plus/icons-vue'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import ProtocolViewDialog from '../protocol/ProtocolViewDialog.vue'
|
||||
import {
|
||||
fetchSampleSmsNotificationList,
|
||||
fetchToggleSmsNotified,
|
||||
fetchGenerateSms
|
||||
} from '@/api/sample-sms-notification'
|
||||
import { type CollectionProtocolRow } from '@/api/collection-protocol'
|
||||
import {
|
||||
protocolStatusLabel,
|
||||
protocolStatusTagType,
|
||||
} from '@/utils/status-tag-registry'
|
||||
|
||||
defineOptions({ name: 'CellStorageSampleReceptionInfo' })
|
||||
|
||||
const searchForm = reactive({ keyword: '', acceptConclusion: '', smsNotified: '' })
|
||||
const tableData = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
||||
|
||||
const viewVisible = ref(false)
|
||||
const viewProtocolId = ref<string | null>(null)
|
||||
const viewRow = ref<CollectionProtocolRow | null>(null)
|
||||
|
||||
const { copy } = useClipboard()
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchSampleSmsNotificationList({
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
keyword: searchForm.keyword || undefined,
|
||||
acceptConclusion: searchForm.acceptConclusion || undefined,
|
||||
smsNotified: searchForm.smsNotified || undefined
|
||||
})
|
||||
const res = (result as any) || {}
|
||||
tableData.value = res.list || []
|
||||
pagination.total = res.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
Object.assign(searchForm, { keyword: '', acceptConclusion: '', smsNotified: '' })
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
function handleView(row: Record<string, unknown>) {
|
||||
const pid = String(row.collectionProtocolId || row.protocolId || '')
|
||||
if (!pid) {
|
||||
ElMessage.warning('缺少关联协议单,无法查看')
|
||||
return
|
||||
}
|
||||
viewProtocolId.value = pid
|
||||
viewRow.value = {
|
||||
id: pid,
|
||||
protocolNo: row.protocolNo,
|
||||
motherName: row.motherName,
|
||||
newbornName: row.newbornName
|
||||
}
|
||||
viewVisible.value = true
|
||||
}
|
||||
|
||||
async function handleExtractSms(row: any) {
|
||||
try {
|
||||
const result = await fetchGenerateSms(row.id, row.sampleReceptionId)
|
||||
const content = (result as any)?.smsContent || ''
|
||||
if (!content) {
|
||||
ElMessage.warning('短信内容为空')
|
||||
return
|
||||
}
|
||||
await copy(content)
|
||||
ElMessage.success('短信内容已复制到剪贴板')
|
||||
} catch {
|
||||
ElMessage.error('提取短信失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function handleToggleNotified(row: any) {
|
||||
const newVal = row.smsNotified == 1 ? 0 : 1
|
||||
try {
|
||||
await fetchToggleSmsNotified(row.id, {
|
||||
smsNotified: newVal,
|
||||
sampleReceptionId: row.sampleReceptionId
|
||||
})
|
||||
ElMessage.success(newVal === 1 ? '已标记为已通知' : '已标记为未通知')
|
||||
loadData()
|
||||
} catch {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
@@ -46,17 +46,31 @@
|
||||
stripe
|
||||
row-key="id"
|
||||
:row-class-name="storageCertRowClassName"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
|
||||
/>
|
||||
<el-table-column prop="protocolNo" label="采集协议号" width="160" align="center" header-align="center" />
|
||||
<el-table-column prop="motherName" label="母亲姓名" width="100" align="center" header-align="center" />
|
||||
<el-table-column prop="protocolNo" label="采集协议号" min-width="160" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="协议状态"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="protocolStatusTagType(String(row.protocolStatus || ''))" size="small">{{
|
||||
protocolStatusLabel(String(row.protocolStatus || ''))
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="motherName" label="母亲姓名" min-width="100" align="center" header-align="center" />
|
||||
<el-table-column prop="motherPhone" label="母亲联系方式" min-width="130" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.motherPhone || '—' }}</template>
|
||||
</el-table-column>
|
||||
@@ -65,17 +79,17 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="newbornInfo" label="新生儿信息" min-width="200" align="center" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="sampleInfo" label="样本信息" min-width="200" align="center" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="storageInDate" label="入库日期" width="120" align="center" header-align="center">
|
||||
<el-table-column prop="storageInDate" label="入库日期" min-width="120" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.storageInDate || '—' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="makeStatus" label="制作状态" width="100" align="center" header-align="center">
|
||||
<el-table-column prop="makeStatus" label="制作状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.makeStatus == '1' ? 'success' : 'warning'" size="small">
|
||||
{{ row.makeStatus == '1' ? '已制作' : '未制作' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="makeDate" label="制作日期" width="120" align="center" header-align="center" />
|
||||
<el-table-column prop="makeDate" label="制作日期" min-width="120" align="center" header-align="center" />
|
||||
<el-table-column label="操作" min-width="260" fixed="right" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button class="btn-op-item primary" @click="handleUpload(row)">
|
||||
@@ -284,6 +298,10 @@
|
||||
import { fetchUploadAttachment } from '@/api/business'
|
||||
import { downloadAttachmentFile } from '@/utils/download-attachment'
|
||||
import { maskIdCard } from '@/utils/mask-sensitive'
|
||||
import {
|
||||
protocolStatusLabel,
|
||||
protocolStatusTagType,
|
||||
} from '@/utils/status-tag-registry'
|
||||
|
||||
interface CertAttachmentItem {
|
||||
id: string
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
<!-- 样本入库信息 -->
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<header class="page-head">
|
||||
<h1>样本入库信息</h1>
|
||||
<p class="page-desc">查看样本入库信息,提取短信通知内容并管理通知状态。</p>
|
||||
</header>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panel-top">
|
||||
<h2 class="title-bar-heading">样本入库列表</h2>
|
||||
</div>
|
||||
|
||||
<div class="filter-block">
|
||||
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
||||
<div class="filter-grid">
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="searchForm.keyword" placeholder="协议号/姓名/样本编码" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="入库状态">
|
||||
<el-select v-model="searchForm.storageStatus" placeholder="全部" clearable style="width: 100%">
|
||||
<el-option label="已入库" value="yrk" />
|
||||
<el-option label="拒绝入库" value="btg" />
|
||||
<el-option label="待入库确认" value="drk" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知状态">
|
||||
<el-select v-model="searchForm.smsNotified" placeholder="全部" clearable style="width: 100%">
|
||||
<el-option label="已通知" value="1" />
|
||||
<el-option label="未通知" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="filter-actions-row">
|
||||
<div class="filter-actions-end">
|
||||
<el-button class="btn-ghost" @click="handleReset">
|
||||
<el-icon><RefreshLeft /></el-icon>重置
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" @click="handleSearch">
|
||||
<el-icon><Search /></el-icon>搜索
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<el-table
|
||||
class="list-table"
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
stripe
|
||||
row-key="id"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1"
|
||||
/>
|
||||
<el-table-column prop="protocolNo" label="协议号" min-width="140" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
prop="protocolStatus"
|
||||
label="协议状态"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="protocolStatusTagType(String(row.protocolStatus || ''))" size="small">{{
|
||||
protocolStatusLabel(String(row.protocolStatus || ''))
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="motherName" label="母亲姓名" min-width="100" align="center" header-align="center" />
|
||||
<el-table-column prop="newbornName" label="新生儿姓名" min-width="110" align="center" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="sampleCode" label="样本编码" min-width="130" align="center" header-align="center" />
|
||||
<el-table-column prop="sampleTypeName" label="样本类型" min-width="110" align="center" header-align="center" />
|
||||
<el-table-column prop="storageTime" label="入库时间" min-width="170" align="center" header-align="center" />
|
||||
<el-table-column prop="storageStatusLabel" label="入库状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="
|
||||
row.storageStatusLabel === '已入库'
|
||||
? 'success'
|
||||
: row.storageStatusLabel === '拒绝入库'
|
||||
? 'danger'
|
||||
: 'warning'
|
||||
"
|
||||
size="small"
|
||||
>
|
||||
{{ row.storageStatusLabel }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="smsNotified" label="通知状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.smsNotified == 1 ? 'success' : 'info'" size="small">
|
||||
{{ row.smsNotified == 1 ? '已通知' : '未通知' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="260" fixed="right" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button class="btn-op-item primary" @click="handleView(row)">
|
||||
<el-icon><View /></el-icon>查看
|
||||
</el-button>
|
||||
<el-button class="btn-op-item" @click="handleExtractSms(row)">
|
||||
<el-icon><ChatDotRound /></el-icon>提取短信
|
||||
</el-button>
|
||||
<el-button class="btn-op-item" @click="handleToggleNotified(row)">
|
||||
<el-icon><Bell /></el-icon>{{ row.smsNotified == 1 ? '标记未通知' : '标记已通知' }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination list-pager-bar">
|
||||
<el-pagination
|
||||
:current-page="pagination.page"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
|
||||
@current-change="(val) => ((pagination.page = val), loadData())"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ProtocolViewDialog
|
||||
v-model="viewVisible"
|
||||
:protocol-id="viewProtocolId"
|
||||
:list-row="viewRow"
|
||||
show-audit-history
|
||||
show-storage-cert
|
||||
show-fullmoon-insurance
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Search, RefreshLeft, View, ChatDotRound, Bell } from '@element-plus/icons-vue'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import ProtocolViewDialog from '../protocol/ProtocolViewDialog.vue'
|
||||
import {
|
||||
fetchStorageEntrySmsList,
|
||||
fetchToggleStorageEntrySmsNotified,
|
||||
fetchGenerateStorageEntrySms
|
||||
} from '@/api/storage-entry-sms-notification'
|
||||
import { type CollectionProtocolRow } from '@/api/collection-protocol'
|
||||
import {
|
||||
protocolStatusLabel,
|
||||
protocolStatusTagType,
|
||||
} from '@/utils/status-tag-registry'
|
||||
|
||||
defineOptions({ name: 'CellStorageStorageEntryInfo' })
|
||||
|
||||
const searchForm = reactive({ keyword: '', storageStatus: '', smsNotified: '' })
|
||||
const tableData = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
||||
|
||||
const viewVisible = ref(false)
|
||||
const viewProtocolId = ref<string | null>(null)
|
||||
const viewRow = ref<CollectionProtocolRow | null>(null)
|
||||
|
||||
const { copy } = useClipboard()
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await fetchStorageEntrySmsList({
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
keyword: searchForm.keyword || undefined,
|
||||
storageStatus: searchForm.storageStatus || undefined,
|
||||
smsNotified: searchForm.smsNotified || undefined
|
||||
})
|
||||
const res = (result as any) || {}
|
||||
tableData.value = res.list || []
|
||||
pagination.total = res.total || 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
pagination.page = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
Object.assign(searchForm, { keyword: '', storageStatus: '', smsNotified: '' })
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
function handleView(row: Record<string, unknown>) {
|
||||
const pid = String(row.collectionProtocolId || row.protocolId || '')
|
||||
if (!pid) {
|
||||
ElMessage.warning('缺少关联协议单,无法查看')
|
||||
return
|
||||
}
|
||||
viewProtocolId.value = pid
|
||||
viewRow.value = {
|
||||
id: pid,
|
||||
protocolNo: row.protocolNo,
|
||||
motherName: row.motherName,
|
||||
newbornName: row.newbornName
|
||||
}
|
||||
viewVisible.value = true
|
||||
}
|
||||
|
||||
async function handleExtractSms(row: any) {
|
||||
try {
|
||||
const result = await fetchGenerateStorageEntrySms(row.id, row.storageReviewId)
|
||||
const content = (result as any)?.smsContent || ''
|
||||
if (!content) {
|
||||
ElMessage.warning('短信内容为空')
|
||||
return
|
||||
}
|
||||
await copy(content)
|
||||
ElMessage.success('短信内容已复制到剪贴板')
|
||||
} catch {
|
||||
ElMessage.error('提取短信失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function handleToggleNotified(row: any) {
|
||||
const newVal = row.smsNotified == 1 ? 0 : 1
|
||||
try {
|
||||
await fetchToggleStorageEntrySmsNotified(row.id, {
|
||||
smsNotified: newVal,
|
||||
storageReviewId: row.storageReviewId
|
||||
})
|
||||
ElMessage.success(newVal === 1 ? '已标记为已通知' : '已标记为未通知')
|
||||
loadData()
|
||||
} catch {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
@@ -59,32 +59,32 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
/>
|
||||
<el-table-column prop="roomCode" label="编号" width="140" align="center" header-align="center" />
|
||||
<el-table-column prop="roomCode" label="编号" min-width="140" align="center" header-align="center" />
|
||||
<el-table-column prop="roomName" label="名称" min-width="160" align="center" header-align="center" />
|
||||
<el-table-column label="等级" width="100" align="center" header-align="center">
|
||||
<el-table-column label="等级" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag class="clean-room-grade-tag" :class="gradeTagClass(row.roomGrade)" effect="light">
|
||||
{{ gradeLabel(row.roomGrade) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100" align="center" header-align="center">
|
||||
<el-table-column label="状态" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.roomStatus === 'zc' ? 'success' : 'danger'" effect="plain">
|
||||
{{ row.roomStatus === 'zc' ? '正常' : '异常' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="areaSqm" label="面积(m²)" width="120" align="center" header-align="center" />
|
||||
<el-table-column prop="areaSqm" label="面积(m²)" min-width="120" align="center" header-align="center" />
|
||||
<el-table-column label="操作" min-width="320" fixed="right" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button class="btn-op-item" @click="handleView(row)"
|
||||
@@ -218,7 +218,7 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="60"
|
||||
min-width="60"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (logPagination.page - 1) * logPagination.pageSize + index + 1"
|
||||
@@ -228,7 +228,7 @@
|
||||
<el-table-column prop="enterTime" label="进入时间" min-width="160" align="center" header-align="center" />
|
||||
<el-table-column prop="purpose" label="目的" min-width="120" align="center" header-align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="leaveTime" label="离开时间" min-width="160" align="center" header-align="center" />
|
||||
<el-table-column prop="bodyTemp" label="体温(℃)" width="90" align="center" header-align="center">
|
||||
<el-table-column prop="bodyTemp" label="体温(℃)" min-width="90" align="center" header-align="center">
|
||||
<template #default="{ row }">{{ row.bodyTemp != null ? row.bodyTemp + '℃' : '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="160" align="center" header-align="center" show-overflow-tooltip />
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
|
||||
@@ -381,8 +381,8 @@
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table :data="occupancyList" v-loading="occupancyLoading" size="small" max-height="360">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column label="物品类型" width="120">
|
||||
<el-table-column type="index" label="序号" min-width="60" />
|
||||
<el-table-column label="物品类型" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.itemType === 'cell_product' ? 'primary' : 'info'" size="small">
|
||||
{{ row.itemType === 'cell_product' ? '细胞产品' : '其他' }}
|
||||
@@ -391,13 +391,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="itemCode" label="物品编码" min-width="140" />
|
||||
<el-table-column prop="itemName" label="物品名称" min-width="140" />
|
||||
<el-table-column label="来源" width="120">
|
||||
<el-table-column label="来源" min-width="120">
|
||||
<template #default="{ row }">
|
||||
{{ { production: '生产入库', manual: '手动入库', transfer: '转移' }[row.itemSource] || row.itemSource }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="storedAt" label="入库时间" width="170" />
|
||||
<el-table-column label="操作" width="80" fixed="right">
|
||||
<el-table-column prop="storedAt" label="入库时间" min-width="170" />
|
||||
<el-table-column label="操作" min-width="80" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="danger" link size="small" @click="handleRemoveOccupancy(row)">
|
||||
出库
|
||||
@@ -419,8 +419,8 @@
|
||||
|
||||
<el-tab-pane label="出入库历史" name="history">
|
||||
<el-table :data="historyList" v-loading="historyLoading" size="small" max-height="400">
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column label="物品类型" width="120">
|
||||
<el-table-column type="index" label="序号" min-width="60" />
|
||||
<el-table-column label="物品类型" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.itemType === 'cell_product' ? 'primary' : 'info'" size="small">
|
||||
{{ row.itemType === 'cell_product' ? '细胞产品' : '其他' }}
|
||||
@@ -429,14 +429,14 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="itemCode" label="物品编码" min-width="120" />
|
||||
<el-table-column prop="itemName" label="物品名称" min-width="120" />
|
||||
<el-table-column label="来源" width="100">
|
||||
<el-table-column label="来源" min-width="100">
|
||||
<template #default="{ row }">
|
||||
{{ { production: '生产入库', manual: '手动入库', transfer: '转移' }[row.itemSource] || row.itemSource }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="storedAt" label="入库时间" width="170" />
|
||||
<el-table-column prop="removedAt" label="出库时间" width="170" />
|
||||
<el-table-column label="状态" width="100">
|
||||
<el-table-column prop="storedAt" label="入库时间" min-width="170" />
|
||||
<el-table-column prop="removedAt" label="出库时间" min-width="170" />
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.occupancyStatus === 'stored' ? 'success' : 'warning'" size="small">
|
||||
{{ row.occupancyStatus === 'stored' ? '在库' : '已出库' }}
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
|
||||
@@ -59,11 +59,11 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-dblclick="handleView"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
@@ -688,7 +688,7 @@
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
width="68"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
/>
|
||||
@@ -768,7 +768,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="100"
|
||||
min-width="100"
|
||||
fixed="right"
|
||||
align="center"
|
||||
header-align="center"
|
||||
@@ -954,7 +954,7 @@
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="45"
|
||||
min-width="45"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:selectable="priceSelectorRowSelectable"
|
||||
|
||||
Loaded 100 of 150 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user