This commit is contained in:
zlwu committed 2026-05-24 23:04:33 +08:00
1 parent 13e4c9530a
commit 575e63e7e8
62 files changed
+28759 -9636

No files matched your search

+1 -1
View File
@@ -1 +1 @@
50128
86059
+625
View File
@@ -1544,6 +1544,631 @@ async def delete_checkup_institution_project(
return error_response(400, str(e))
# ---------------------------------------------------------------------------
# 7. 渠道服务购买订单
# ---------------------------------------------------------------------------
class ServiceOrderProductItem(BaseModel):
model_config = ConfigDict(populate_by_name=True)
project_code: Optional[str] = Field(None, alias="projectCode")
project_name: Optional[str] = Field(None, alias="projectName")
cell_type: Optional[str] = Field(None, alias="cellType")
spec_text: Optional[str] = Field(None, alias="specText")
agreement_unit_price: Optional[float] = Field(None, alias="agreementUnitPrice")
buy_qty: Optional[float] = Field(None, alias="buyQty")
buy_amount: Optional[float] = Field(None, alias="buyAmount")
class ServiceOrderCreateBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
channel_id: str = Field(..., alias="channelId")
order_type: str = Field(..., alias="orderType") # yfk / gmcp
dept_name: Optional[str] = Field(None, alias="deptName")
prepay_amount: Optional[float] = Field(None, alias="prepayAmount")
channel_agreement_id: Optional[str] = Field(None, alias="channelAgreementId")
products: Optional[List[ServiceOrderProductItem]] = None
remark: Optional[str] = None
class ServiceOrderUpdateBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
dept_name: Optional[str] = Field(None, alias="deptName")
remark: Optional[str] = None
prepay_amount: Optional[float] = Field(None, alias="prepayAmount")
channel_agreement_id: Optional[str] = Field(None, alias="channelAgreementId")
products: Optional[List[ServiceOrderProductItem]] = None
class FinanceSubmitBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
finance_submit_remark: Optional[str] = Field(None, alias="financeSubmitRemark")
finance_submit_attachments: Optional[str] = Field(None, alias="financeSubmitAttachments")
class FinanceConfirmBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
finance_remark: Optional[str] = Field(None, alias="financeRemark")
finance_confirm_attachments: Optional[str] = Field(None, alias="financeConfirmAttachments")
class RefundSubmitBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
refund_amount: Optional[float] = Field(None, alias="refundAmount")
refund_remark: Optional[str] = Field(None, alias="refundRemark")
refund_attachments: Optional[str] = Field(None, alias="refundAttachments")
class RefundConfirmBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
refund_finance_remark: Optional[str] = Field(None, alias="refundFinanceRemark")
refund_finance_confirm_attachments: Optional[str] = Field(
None, alias="refundFinanceConfirmAttachments"
)
class TxnRechargeBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
amount: float = Field(..., gt=0, alias="amount")
remark: Optional[str] = Field(None, alias="remark")
class TxnRefundBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
amount: float = Field(..., gt=0, alias="amount")
remark: Optional[str] = Field(None, alias="remark")
class TxnProductItem(BaseModel):
model_config = ConfigDict(populate_by_name=True)
project_code: Optional[str] = Field(None, alias="projectCode")
project_name: Optional[str] = Field(None, alias="projectName")
cell_type: Optional[str] = Field(None, alias="cellType")
spec_text: Optional[str] = Field(None, alias="specText")
agreement_unit_price: Optional[float] = Field(None, alias="agreementUnitPrice")
qty: Optional[float] = Field(None, alias="qty")
amount: Optional[float] = Field(None, alias="amount")
class TxnPurchaseBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
products: List[TxnProductItem] = Field(..., alias="products")
remark: Optional[str] = Field(None, alias="remark")
class TxnUnsubscribeBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
products: List[TxnProductItem] = Field(..., alias="products")
remark: Optional[str] = Field(None, alias="remark")
class TxnFinanceSubmitBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
finance_submit_remark: Optional[str] = Field(None, alias="financeSubmitRemark")
finance_submit_attachments: Optional[str] = Field(None, alias="financeSubmitAttachments")
class TxnFinanceConfirmBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
finance_remark: Optional[str] = Field(None, alias="financeRemark")
finance_confirm_attachments: Optional[str] = Field(None, alias="financeConfirmAttachments")
@router.get("/channel-service-orders")
async def list_channel_service_orders(
page: int = Query(1, ge=1),
pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
orderType: Optional[str] = Query(None, alias="orderType"),
orderStatus: Optional[str] = Query(None, alias="orderStatus"),
channelId: Optional[str] = Query(None, alias="channelId"),
keyword: Optional[str] = None,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
tenant_no = _get_tenant_no(db, user)
items, total = ps_svc.list_channel_service_orders(
db,
page=page,
page_size=pageSize,
order_type=orderType,
order_status=orderStatus,
channel_id=channelId,
keyword=keyword,
tenant_no=tenant_no,
user_info=user,
)
tp = ps_svc.total_pages(total, pageSize)
return success_response(
{"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}
)
@router.get("/channel-service-orders/{order_id}")
async def get_channel_service_order_detail(
order_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
order = ps_svc.get_service_order(db, order_id, tenant_no=tenant_no)
if not order:
return error_response(404, "订单不存在")
order_dict = ps_svc._row_to_dict_service_order(order, db, tenant_no)
user_ids = [x for x in (order.create_by, order.finance_submit_by) if x]
name_map = ps_svc._user_nick_name_map(db, user_ids)
order_dict["createByName"] = name_map.get(order.create_by or "", "") or (order.create_by or "")
order_dict["financeSubmitByName"] = name_map.get(order.finance_submit_by or "", "") or (
order.finance_submit_by or ""
)
products = ps_svc.get_service_order_products(db, order_id, tenant_no=tenant_no)
order_dict["products"] = products
txns, _ = ps_svc.list_service_order_txns(db, service_order_id=order_id, tenant_no=tenant_no, page_size=200)
order_dict["transactions"] = txns
return success_response(order_dict)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders")
async def create_channel_service_order(
body: ServiceOrderCreateBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
products_data = None
if body.products:
products_data = [p.model_dump(by_alias=False) for p in body.products]
order = ps_svc.create_channel_service_order(
db,
channel_id=body.channel_id,
order_type=body.order_type,
dept_name=body.dept_name,
prepay_amount=body.prepay_amount,
channel_agreement_id=body.channel_agreement_id,
products=products_data,
tenant_no=tenant_no,
remark=body.remark,
user_id=user.get("user_id"),
)
order_dict = ps_svc._row_to_dict_service_order(order, db, tenant_no)
order_dict["products"] = ps_svc.get_service_order_products(db, order.id, tenant_no=tenant_no)
return success_response(order_dict, message="创建成功")
except ValueError as e:
return error_response(400, str(e))
@router.put("/channel-service-orders/{order_id}")
async def update_channel_service_order(
order_id: str,
body: ServiceOrderUpdateBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
payload: dict[str, Any] = body.model_dump(exclude_unset=True, by_alias=False)
products_data = None
if "products" in payload:
products_data = payload.pop("products")
if products_data is not None:
products_data = [
p.model_dump(by_alias=False) if hasattr(p, "model_dump") else p
for p in (body.products or [])
]
obj = ps_svc.update_channel_service_order(
db,
order_id,
tenant_no=tenant_no,
user_id=user.get("user_id"),
products=products_data,
**payload,
)
return success_response(
ps_svc._row_to_dict_service_order(obj, db, tenant_no), message="更新成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.delete("/channel-service-orders/{order_id}")
async def delete_channel_service_order(
order_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
ps_svc.soft_delete_service_order(db, order_id, tenant_no=tenant_no)
return success_response(None, message="删除成功")
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/submit-finance-confirm")
async def submit_service_order_finance_confirm(
order_id: str,
body: FinanceSubmitBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
obj = ps_svc.submit_finance_confirm(
db,
order_id,
finance_submit_remark=body.finance_submit_remark,
finance_submit_attachments=body.finance_submit_attachments,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order(obj, db, tenant_no), message="已发起财务确认"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/confirm-receipt")
async def confirm_service_order_receipt(
order_id: str,
body: FinanceConfirmBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
obj = ps_svc.confirm_receipt(
db,
order_id,
finance_remark=body.finance_remark,
finance_confirm_attachments=body.finance_confirm_attachments,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order(obj, db, tenant_no), message="确认收款成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/submit-refund")
async def submit_service_order_refund(
order_id: str,
body: RefundSubmitBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
obj = ps_svc.submit_refund(
db,
order_id,
refund_amount=body.refund_amount,
refund_remark=body.refund_remark,
refund_attachments=body.refund_attachments,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order(obj, db, tenant_no), message="提交退款成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/confirm-refund")
async def confirm_service_order_refund(
order_id: str,
body: RefundConfirmBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
obj = ps_svc.confirm_refund(
db,
order_id,
refund_finance_remark=body.refund_finance_remark,
refund_finance_confirm_attachments=body.refund_finance_confirm_attachments,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order(obj, db, tenant_no), message="确认退款成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.put("/channel-service-orders/{order_id}/void")
async def void_channel_service_order(
order_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
obj = ps_svc.void_service_order(
db,
order_id,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order(obj, db, tenant_no), message="作废成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.get("/channel-service-order-txns")
async def list_service_order_txns(
page: int = Query(1, ge=1),
pageSize: int = Query(20, ge=1, le=100, alias="pageSize"),
serviceOrderId: Optional[str] = Query(None, alias="serviceOrderId"),
txnStatus: Optional[str] = Query(None, alias="txnStatus"),
txnType: Optional[str] = Query(None, alias="txnType"),
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
tenant_no = _get_tenant_no(db, user)
items, total = ps_svc.list_service_order_txns(
db,
service_order_id=serviceOrderId,
txn_status=txnStatus,
txn_type=txnType,
page=page,
page_size=pageSize,
tenant_no=tenant_no,
)
tp = ps_svc.total_pages(total, pageSize)
return success_response(
{"list": items, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp}
)
@router.get("/channel-service-order-txns/{txn_id}")
async def get_service_order_txn_detail(
txn_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
txn = ps_svc.get_service_order_txn(db, txn_id, tenant_no=tenant_no)
if not txn:
return error_response(404, "流水不存在")
txn_dict = ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no)
order = ps_svc.get_service_order(db, txn.service_order_id, tenant_no=tenant_no)
if order:
txn_dict["channelName"] = order.channel_name or ""
txn_dict["orderType"] = order.order_type or ""
user_ids = [x for x in (txn.create_by, txn.finance_submit_by) if x]
name_map = ps_svc._user_nick_name_map(db, user_ids)
txn_dict["createByName"] = name_map.get(txn.create_by or "", "") or (txn.create_by or "")
txn_dict["financeSubmitByName"] = name_map.get(txn.finance_submit_by or "", "") or (
txn.finance_submit_by or ""
)
return success_response(txn_dict)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/recharge")
async def create_recharge_txn(
order_id: str,
body: TxnRechargeBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
txn = ps_svc.create_recharge_txn(
db,
order_id,
amount=body.amount,
remark=body.remark,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="充值流水创建成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/refund")
async def create_refund_txn(
order_id: str,
body: TxnRefundBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
txn = ps_svc.create_refund_txn(
db,
order_id,
amount=body.amount,
remark=body.remark,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="退款流水创建成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/purchase")
async def create_purchase_txn(
order_id: str,
body: TxnPurchaseBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
products_data = [p.model_dump(by_alias=False) for p in body.products]
txn = ps_svc.create_purchase_txn(
db,
order_id,
products=products_data,
remark=body.remark,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="购买产品流水创建成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-orders/{order_id}/unsubscribe")
async def create_unsubscribe_txn(
order_id: str,
body: TxnUnsubscribeBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
products_data = [p.model_dump(by_alias=False) for p in body.products]
txn = ps_svc.create_unsubscribe_txn(
db,
order_id,
products=products_data,
remark=body.remark,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="退订产品流水创建成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-order-txns/{txn_id}/submit-finance")
async def submit_txn_finance(
txn_id: str,
body: TxnFinanceSubmitBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
txn = ps_svc.submit_txn_finance(
db,
txn_id,
finance_submit_remark=body.finance_submit_remark,
finance_submit_attachments=body.finance_submit_attachments,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="已发起财务确认"
)
except ValueError as e:
return error_response(400, str(e))
@router.post("/channel-service-order-txns/{txn_id}/confirm")
async def confirm_txn(
txn_id: str,
body: TxnFinanceConfirmBody,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
txn = ps_svc.confirm_txn(
db,
txn_id,
finance_remark=body.finance_remark,
finance_confirm_attachments=body.finance_confirm_attachments,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="财务确认成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.put("/channel-service-order-txns/{txn_id}/void")
async def void_txn(
txn_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
txn = ps_svc.void_txn(
db,
txn_id,
tenant_no=tenant_no,
user_id=user.get("user_id"),
)
return success_response(
ps_svc._row_to_dict_service_order_txn(txn, db, tenant_no), message="作废成功"
)
except ValueError as e:
return error_response(400, str(e))
@router.get("/channels/{channel_id}/account")
async def get_channel_account_info(
channel_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
account = ps_svc.get_channel_account(db, channel_id, tenant_no=tenant_no)
if not account:
return success_response({"channelId": channel_id, "balanceAmount": 0.0})
return success_response(ps_svc._row_to_dict_channel_account(account))
except ValueError as e:
return error_response(400, str(e))
@router.get("/channels/{channel_id}/product-quotas")
async def list_channel_product_quotas(
channel_id: str,
user: dict = Depends(require_admin_or_super_admin),
db: Session = Depends(get_db),
):
try:
tenant_no = _get_tenant_no(db, user)
items = ps_svc.list_channel_product_quotas(db, channel_id, tenant_no=tenant_no)
return success_response(items)
except ValueError as e:
return error_response(400, str(e))
# --- 体检机构项目套餐 ---
File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_pilot_service_py", "label": "pilot_service.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L1"}, {"id": "api_pilot_service_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L17"}, {"id": "api_pilot_service_cellproducttypecreatebody", "label": "CellProductTypeCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L32"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_pilot_service_cellproducttypeupdatebody", "label": "CellProductTypeUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L41"}, {"id": "api_pilot_service_list_cell_product_types", "label": "list_cell_product_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L51"}, {"id": "api_pilot_service_create_cell_product_type", "label": "create_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L69"}, {"id": "api_pilot_service_update_cell_product_type", "label": "update_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L91"}, {"id": "api_pilot_service_delete_cell_product_type", "label": "delete_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L116"}, {"id": "api_pilot_service_cellproductspeccreatebody", "label": "CellProductSpecCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L134"}, {"id": "api_pilot_service_cellproductspecupdatebody", "label": "CellProductSpecUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L143"}, {"id": "api_pilot_service_list_cell_product_specs", "label": "list_cell_product_specs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L153"}, {"id": "api_pilot_service_create_cell_product_spec", "label": "create_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L171"}, {"id": "api_pilot_service_update_cell_product_spec", "label": "update_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L193"}, {"id": "api_pilot_service_delete_cell_product_spec", "label": "delete_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L218"}, {"id": "api_pilot_service_cellproductpricecreatebody", "label": "CellProductPriceCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L236"}, {"id": "api_pilot_service_cellproductpriceupdatebody", "label": "CellProductPriceUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L251"}, {"id": "api_pilot_service_list_cell_product_prices", "label": "list_cell_product_prices()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L267"}, {"id": "api_pilot_service_create_cell_product_price", "label": "create_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L292"}, {"id": "api_pilot_service_update_cell_product_price", "label": "update_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L320"}, {"id": "api_pilot_service_delete_cell_product_price", "label": "delete_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L351"}, {"id": "api_pilot_service_projectsystemcreatebody", "label": "ProjectSystemCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L369"}, {"id": "api_pilot_service_projectsystemupdatebody", "label": "ProjectSystemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/apLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_production_work_order_py", "label": "production_work_order.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L1"}, {"id": "crud_production_work_order_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L44"}, {"id": "crud_production_work_order_soft_delete_sub", "label": "_soft_delete_sub()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L48"}, {"id": "crud_production_work_order_generate_work_order_no", "label": "_generate_work_order_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L60"}, {"id": "crud_production_work_order_wo_to_dict", "label": "_wo_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L79"}, {"id": "crud_production_work_order_enrich_wo_items", "label": "_enrich_wo_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L105"}, {"id": "crud_production_work_order_reception_source_label", "label": "_reception_source_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L111"}, {"id": "crud_production_work_order_accept_conclusion_label", "label": "_accept_conclusion_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L116"}, {"id": "crud_production_work_order_attach_reception_detail", "label": "_attach_reception_detail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L121"}, {"id": "crud_production_work_order_wo_to_response_dict", "label": "_wo_to_response_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L151"}, {"id": "crud_production_work_order_create_production_work_order_from_reception", "label": "create_production_work_order_from_reception()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L158"}, {"id": "crud_production_work_order_list_production_work_orders", "label": "list_production_work_orders()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L269"}, {"id": "crud_production_work_order_sync_production_work_order_status_from_tasks", "label": "sync_production_work_order_status_from_tasks()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L328"}, {"id": "crud_production_work_order_get_production_work_order", "label": "get_production_work_order()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L368"}, {"id": "crud_production_work_order_update_production_work_order", "label": "update_production_work_order()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L382"}, {"id": "crud_production_work_order_complete_production_work_order", "label": "complete_production_work_order()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L403"}, {"id": "crud_production_work_order_production_task_info", "label": "_production_task_info()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L434"}, {"id": "crud_production_work_order_production_info_item", "label": "_production_info_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L485"}, {"id": "crud_production_work_order_get_production_info_map_for_samples", "label": "get_production_info_map_for_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L505"}, {"id": "crud_production_work_order_create_production_work_order_manual", "label": "create_production_work_order_manual()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py", "source_location": "L567"}, {"id": "crud_production_work_order_delete_production_work_order", "label": "delete_productiLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_collection_protocol_py", "label": "collection_protocol.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L1"}, {"id": "crud_collection_protocol_get_protocol_nos_used_in_protocols", "label": "get_protocol_nos_used_in_protocols()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L50"}, {"id": "crud_collection_protocol_get_sample_codes_used_in_protocol_samples", "label": "get_sample_codes_used_in_protocol_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L84"}, {"id": "crud_collection_protocol_validate_sample_codes_not_used", "label": "validate_sample_codes_not_used()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L118"}, {"id": "crud_collection_protocol_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L151"}, {"id": "crud_collection_protocol_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L157"}, {"id": "crud_collection_protocol_dec", "label": "_dec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L161"}, {"id": "crud_collection_protocol_optional_decimal", "label": "_optional_decimal()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L169"}, {"id": "crud_collection_protocol_today_yyyymmdd", "label": "_today_yyyymmdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L175"}, {"id": "crud_collection_protocol_normalize_yyyymmdd_date", "label": "_normalize_yyyymmdd_date()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L179"}, {"id": "crud_collection_protocol_normalize_fields", "label": "_normalize_fields()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L198"}, {"id": "crud_collection_protocol_pop_attachment_urls", "label": "_pop_attachment_urls()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L209"}, {"id": "crud_collection_protocol_attachments_to_urls", "label": "attachments_to_urls()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L220"}, {"id": "crud_collection_protocol_normalize_attachment_url_key", "label": "_normalize_attachment_url_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L239"}, {"id": "crud_collection_protocol_format_attachment_file_size", "label": "_format_attachment_file_size()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L248"}, {"id": "crud_collection_protocol_lookup_attachment_by_url", "label": "_lookup_attachment_by_url()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L256"}, {"id": "crud_collection_protocol_urls_to_attachment_list", "label": "urls_to_attachment_list()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L280"}, {"id": "crud_collection_protocol_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L312"}, {"id": "crud_collection_protocol_protocol_to_dict", "label": "_protocol_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L320"}, {"id": "crud_collection_protocol_payment_to_dict", "label": "_payment_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L345"}, {"id": "crud_collection_protocol_detail_to_dict", "label": "_detail_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L363"}, {"id": "crud_collection_protocol_audit_to_dict", "label": "_audit_to_dict()", "file_type": "code", "source_Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L220"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L240"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L259"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L278"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L297"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L320"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L341"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L359"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L378"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L400"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L428"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L447"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L466"}, {"id": "models_models_sysapirequestlog", "label": "SysApiRequestLog", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_pilot_service_py", "label": "pilot_service.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L1"}, {"id": "crud_pilot_service_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L37"}, {"id": "crud_pilot_service_row_to_dict_cell_product_type", "label": "_row_to_dict_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L49"}, {"id": "crud_pilot_service_list_cell_product_types", "label": "list_cell_product_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L62"}, {"id": "crud_pilot_service_get_cell_product_type", "label": "get_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L88"}, {"id": "crud_pilot_service_cell_product_type_code_exists", "label": "cell_product_type_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L95"}, {"id": "crud_pilot_service_create_cell_product_type", "label": "create_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L106"}, {"id": "crud_pilot_service_update_cell_product_type", "label": "update_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L128"}, {"id": "crud_pilot_service_soft_delete_cell_product_type", "label": "soft_delete_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L150"}, {"id": "crud_pilot_service_row_to_dict_cell_product_spec", "label": "_row_to_dict_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L164"}, {"id": "crud_pilot_service_list_cell_product_specs", "label": "list_cell_product_specs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L177"}, {"id": "crud_pilot_service_get_cell_product_spec", "label": "get_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L203"}, {"id": "crud_pilot_service_cell_product_spec_code_exists", "label": "cell_product_spec_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L210"}, {"id": "crud_pilot_service_create_cell_product_spec", "label": "create_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L221"}, {"id": "crud_pilot_service_update_cell_product_spec", "label": "update_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L243"}, {"id": "crud_pilot_service_soft_delete_cell_product_spec", "label": "soft_delete_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L265"}, {"id": "crud_pilot_service_row_to_dict_cell_product_price", "label": "_row_to_dict_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L279"}, {"id": "crud_pilot_service_list_cell_product_prices", "label": "list_cell_product_prices()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L298"}, {"id": "crud_pilot_service_get_cell_product_price", "label": "get_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L327"}, {"id": "crud_pilot_service_cell_product_price_code_exists", "label": "cell_product_price_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L334"}, {"id": "crud_pilot_service_create_cell_product_price", "label": "create_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L345"}, {"id": "crud_pilot_service_update_cell_product_price", "label": "update_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00codLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_production_task_py", "label": "production_task.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L1"}, {"id": "crud_production_task_production_conclusion_label", "label": "_production_conclusion_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L57"}, {"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": "L64"}, {"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": "L68"}, {"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": "L82"}, {"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": "L107"}, {"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": "L127"}, {"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": "L143"}, {"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": "L159"}, {"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": "L171"}, {"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": "L183"}, {"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": "L205"}, {"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": "L230"}, {"id": "crud_production_task_resolve_sub_table_order_num", "label": "_resolve_sub_table_order_num()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L243"}, {"id": "crud_production_task_step_sub_tables_to_dict", "label": "_step_sub_tables_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py", "source_location": "L252"}, {"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": "L274"}, {"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": "L297"}, {"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": "L320"}, {"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": "L342"}, {"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": "L363"}, {"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": "L396"}, {"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": "L462"}, {"id": "crud_production_task_get_production_task_detail", "laLine truncated
@@ -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": "L49"}, {"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": "L53"}, {"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": "L59"}, {"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": "L87"}, {"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": "L125"}, {"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": "L182"}, {"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": "L263"}, {"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": "L268"}, {"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": "L330"}, {"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": "L387"}, {"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": "L444"}, {"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": "L478"}, {"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": "L512"}, {"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": "L534"}, {"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": "L552"}, {"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": "L570"}, {"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": "L605"}, {"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": "L634"}, {"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": "L688"}, {"id": "crud_storage_release_review_get_storage_release_map_for_samples", "label": "get_storage_release_map_for_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/storaLine truncated
+150
View File
@@ -1713,6 +1713,156 @@ class BizChannelMailAddress(Base):
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
class BizChannelAccount(Base):
"""渠道账户余额 biz_channel_account"""
__tablename__ = "biz_channel_account"
id = Column(String(64), primary_key=True, comment="主键ID")
channel_id = Column(String(64), nullable=False, comment="渠道ID")
balance_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="当前余额(元)")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
create_by = Column(String(64), nullable=True, comment="创建人id")
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
update_by = Column(String(64), nullable=True, comment="更新人id")
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
class BizChannelProductQuota(Base):
"""渠道产品份数库存 biz_channel_product_quota"""
__tablename__ = "biz_channel_product_quota"
id = Column(String(64), primary_key=True, comment="主键ID")
channel_id = Column(String(64), nullable=False, comment="渠道ID")
project_code = Column(String(64), nullable=True, comment="项目编码")
project_name = Column(String(200), nullable=True, comment="项目名称")
cell_type_code = Column(String(64), nullable=True, comment="细胞类型编码")
cell_type_name = Column(String(200), nullable=True, comment="细胞类型名称")
spec_text = Column(String(200), nullable=True, comment="规格")
total_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="总购买份数")
used_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="已使用份数")
remaining_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="剩余份数")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
create_by = Column(String(64), nullable=True, comment="创建人id")
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
update_by = Column(String(64), nullable=True, comment="更新人id")
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
class BizChannelServiceOrder(Base):
"""渠道服务订单 biz_channel_service_order"""
__tablename__ = "biz_channel_service_order"
id = Column(String(64), primary_key=True, comment="主键ID")
channel_id = Column(String(64), nullable=False, comment="渠道ID")
channel_name = Column(String(200), nullable=True, comment="渠道名称")
dept_name = Column(String(200), nullable=True, comment="部门名称")
order_type = Column(String(16), nullable=False, comment="订单类型 cz充值 gm购买 tk退款")
prepay_amount = Column(Numeric(18, 2), nullable=True, comment="预存金额(元)")
purchase_total_amount = Column(Numeric(18, 2), nullable=True, comment="购买总金额(元)")
order_status = Column(String(16), nullable=False, default="sxz", comment="订单状态 sxz生效中 yzf已作废 ywc已完成 dqr待确认 ytk已退款")
channel_agreement_id = Column(String(64), nullable=True, comment="渠道协议ID(预付款/购买订单必填)")
total_recharge_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="累计充值总额")
total_refund_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="累计退款总额")
current_balance = Column(Numeric(18, 2), nullable=False, default=0, comment="当前余额")
balance_before = Column(Numeric(18, 2), nullable=True, comment="操作前余额快照")
balance_after = Column(Numeric(18, 2), nullable=True, comment="操作后余额快照")
finance_submit_by = Column(String(64), nullable=True, comment="发起财务确认人ID")
finance_submit_time = Column(DateTime, nullable=True, comment="发起财务确认时间")
finance_submit_remark = Column(String(512), nullable=True, comment="发起财务确认备注")
finance_submit_attachments = Column(Text, nullable=True, comment="发起财务确认附件(逗号分隔URL)")
finance_confirm_time = Column(DateTime, nullable=True, comment="财务确认时间")
finance_confirm_attachments = Column(Text, nullable=True, comment="财务确认附件(逗号分隔URL)")
finance_remark = Column(String(512), nullable=True, comment="财务确认备注")
refund_apply_by = Column(String(64), nullable=True, comment="退费申请人ID")
refund_apply_time = Column(DateTime, nullable=True, comment="退费申请时间")
refund_amount = Column(Numeric(18, 2), nullable=True, comment="退费金额")
refund_remark = Column(String(512), nullable=True, comment="退费备注")
refund_attachments = Column(Text, nullable=True, comment="退费附件(逗号分隔URL)")
refund_finance_confirm_time = Column(DateTime, nullable=True, comment="退费财务确认时间")
refund_finance_confirm_attachments = Column(Text, nullable=True, comment="退费财务确认附件")
refund_finance_remark = Column(String(512), nullable=True, comment="退费财务确认备注")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
create_by = Column(String(64), nullable=True, comment="创建人id")
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
update_by = Column(String(64), nullable=True, comment="更新人id")
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
class BizChannelServiceOrderProduct(Base):
"""渠道服务订单产品明细 biz_channel_service_order_product"""
__tablename__ = "biz_channel_service_order_product"
id = Column(String(64), primary_key=True, comment="主键ID")
service_order_id = Column(String(64), nullable=False, comment="服务订单ID")
project_code = Column(String(64), nullable=True, comment="项目编码")
project_name = Column(String(200), nullable=True, comment="项目名称")
cell_type = Column(String(200), nullable=True, comment="细胞类型")
spec_text = Column(String(200), nullable=True, comment="规格")
agreement_unit_price = Column(Numeric(18, 2), nullable=True, comment="协议单价(元)")
buy_qty = Column(Numeric(18, 4), nullable=True, comment="购买数量")
buy_amount = Column(Numeric(18, 2), nullable=True, comment="购买金额(元)")
total_buy_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="累计购买数量")
total_unsubscribe_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="累计退订数量")
current_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="当前持有数量")
total_unsubscribe_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="累计退订金额")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
create_by = Column(String(64), nullable=True, comment="创建人id")
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
update_by = Column(String(64), nullable=True, comment="更新人id")
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
class BizChannelServiceOrderTxn(Base):
"""渠道服务订单流水 biz_channel_service_order_txn"""
__tablename__ = "biz_channel_service_order_txn"
id = Column(String(64), primary_key=True, comment="主键ID")
service_order_id = Column(String(64), nullable=False, comment="关联订单ID")
txn_type = Column(String(16), nullable=False, comment="recharge/refund/purchase/unsubscribe")
amount = Column(Numeric(18, 2), nullable=True, comment="本次操作金额")
txn_status = Column(String(16), nullable=False, default="dsx", comment="dsx待生效 dqr待财务确认 yqr已确认 yzf已作废")
products_json = Column(Text, nullable=True, comment="产品明细JSON")
remark = Column(String(512), nullable=True, comment="备注")
finance_submit_by = Column(String(64), nullable=True, comment="发起确认人ID")
finance_submit_time = Column(DateTime, nullable=True, comment="发起确认时间")
finance_submit_remark = Column(String(512), nullable=True, comment="发起确认备注")
finance_submit_attachments = Column(Text, nullable=True, comment="发起确认附件")
finance_confirm_time = Column(DateTime, nullable=True, comment="财务确认时间")
finance_confirm_attachments = Column(Text, nullable=True, comment="财务确认附件")
finance_remark = Column(String(512), nullable=True, comment="财务确认备注")
balance_before = Column(Numeric(18, 2), nullable=True, comment="操作前余额")
balance_after = Column(Numeric(18, 2), nullable=True, comment="操作后余额")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
create_by = Column(String(64), nullable=True, comment="创建人id")
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
update_by = Column(String(64), nullable=True, comment="更新人id")
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
class BizCheckupInstitution(Base):
"""体检机构 biz_checkup_institution"""
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+100 -105
View File
@@ -1,12 +1,12 @@
# Graph Report - app (2026-05-24)
## Corpus Check
- 148 files · ~139,944 words
- 148 files · ~143,468 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 2664 nodes · 11010 edges · 53 communities detected
- Extraction: 40% EXTRACTED · 60% INFERRED · 0% AMBIGUOUS · INFERRED: 6597 edges (avg confidence: 0.63)
- 2723 nodes · 11449 edges · 52 communities detected
- Extraction: 39% EXTRACTED · 61% INFERRED · 0% AMBIGUOUS · INFERRED: 6932 edges (avg confidence: 0.62)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
@@ -56,25 +56,24 @@
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 49|Community 49]]
- [[_COMMUNITY_Community 50|Community 50]]
- [[_COMMUNITY_Community 51|Community 51]]
- [[_COMMUNITY_Community 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
- [[_COMMUNITY_Community 54|Community 54]]
## God Nodes (most connected - your core abstractions)
1. `success_response()` - 419 edges
2. `error_response()` - 337 edges
3. `SysUser` - 234 edges
4. `BizQcTaskResult` - 208 edges
5. `BizQcMaterialUsage` - 208 edges
6. `BizMaterialStockLog` - 204 edges
7. `BizQcMaterial` - 204 edges
8. `BizMaterial` - 201 edges
9. `BizQcItemParam` - 199 edges
10. `generate_uuid()` - 154 edges
1. `success_response()` - 431 edges
2. `error_response()` - 348 edges
3. `SysUser` - 252 edges
4. `BizQcTaskResult` - 216 edges
5. `BizQcMaterialUsage` - 216 edges
6. `BizMaterialStockLog` - 212 edges
7. `BizQcMaterial` - 212 edges
8. `BizMaterial` - 209 edges
9. `BizQcItemParam` - 207 edges
10. `generate_uuid()` - 157 edges
## Surprising Connections (you probably didn't know these)
- `统一记录 API 请求/响应出入参的中间件` --uses--> `SysApiRequestLog` [INFERRED]
@@ -92,71 +91,71 @@
### Community 0 - "Community 0"
Cohesion: 0.02
Nodes (478): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+470 more)
Nodes (472): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+464 more)
### Community 1 - "Community 1"
Cohesion: 0.01
Nodes (417): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+409 more)
Nodes (418): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+410 more)
### Community 2 - "Community 2"
Cohesion: 0.05
Nodes (300): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+292 more)
Nodes (315): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+307 more)
### Community 3 - "Community 3"
Cohesion: 0.02
Nodes (193): generate_uuid(), batch_stock_in(), batch_stock_out(), consumable_code_exists(), create_consumable(), _dec(), get_consumable(), _is_enabled_status() (+185 more)
Nodes (166): list_collection_regions(), list_ethnics_for_select(), apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), 数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3, 根据用户角色的数据权限过滤查询。 Args: query: SQLAlchemy query 对象 model: 查询, 从 SysUser 读取用户的 dept_id。 (+158 more)
### Community 4 - "Community 4"
Cohesion: 0.03
Nodes (141): list_collection_regions(), _ensure_customer_for_mother(), _persist_protocol_sub_resources(), list_ethnics_for_select(), apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), _resolve_user_role_scopes() (+133 more)
Nodes (146): generate_uuid(), batch_stock_in(), batch_stock_out(), consumable_code_exists(), create_consumable(), _dec(), get_consumable(), _is_enabled_status() (+138 more)
### Community 5 - "Community 5"
Cohesion: 0.03
Nodes (142): _format_attachment_file_size(), urls_to_attachment_list(), _accept_conclusion_label(), _attach_reception_detail(), complete_production_work_order(), configure_temp_production_work_order(), create_production_work_order_from_reception(), create_production_work_order_manual() (+134 more)
Nodes (145): _format_attachment_file_size(), get_protocol_nos_used_in_protocols(), urls_to_attachment_list(), _accept_conclusion_label(), _attach_reception_detail(), complete_production_work_order(), configure_temp_production_work_order(), create_production_work_order_from_reception() (+137 more)
### Community 6 - "Community 6"
Cohesion: 0.03
Nodes (90): _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)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。 (+82 more)
Nodes (83): _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)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。 (+75 more)
### Community 7 - "Community 7"
Cohesion: 0.04
Nodes (66): get_designer_data(), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, 审批意见:前端传 commentText,兼容 comment。, StartInstanceBody, TaskActionBody, BaseStorage (+58 more)
Cohesion: 0.06
Nodes (77): _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() (+69 more)
### Community 8 - "Community 8"
Cohesion: 0.07
Nodes (67): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+59 more)
Nodes (65): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+57 more)
### Community 9 - "Community 9"
Cohesion: 0.05
Nodes (26): BusinessException, InvalidStatusTransitionException, log_delivery_operation(), log_operation(), log_order_operation(), log_settlement_operation(), log_user_operation(), OrderLockedException (+18 more)
### Community 10 - "Community 10"
Cohesion: 0.35
Nodes (61): BatchStockInBody, BatchStockInItem, BatchStockOutBody, BatchStockOutItem, ConsumableCreateBody, ConsumablePackCreateBody, ConsumablePackUpdateBody, ConsumableUpdateBody (+53 more)
### Community 10 - "Community 10"
Cohesion: 0.11
Nodes (44): 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() (+36 more)
### Community 11 - "Community 11"
Cohesion: 0.08
Nodes (30): BaseHTTPMiddleware, ApiCryptoError, _b64url_decode(), _b64url_encode(), decrypt_json(), derive_key(), encrypt_json(), gen_nonce_hex() (+22 more)
Cohesion: 0.06
Nodes (53): get_designer_data(), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, 审批意见:前端传 commentText,兼容 comment。, StartInstanceBody, TaskActionBody, list_params_by_item() (+45 more)
### Community 12 - "Community 12"
Cohesion: 0.09
Nodes (57): batch_delete_research_donations(), change_donation_status(), convert_from_storage(), convert_to_storage(), create_research_donation(), delete_research_donation(), _get_current_user_id(), get_research_donation_detail() (+49 more)
### Community 13 - "Community 13"
Cohesion: 0.07
Nodes (34): BaseHTTPMiddleware, ApiCryptoError, _b64url_decode(), _b64url_encode(), decrypt_json(), derive_key(), encrypt_json(), gen_nonce_hex() (+26 more)
### Community 14 - "Community 14"
Cohesion: 0.1
Nodes (35): get_next_cell_product_code(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes(), create_cell_product(), create_cell_products_batch(), create_cell_products_by_quantity() (+27 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 14 - "Community 14"
Cohesion: 0.17
Nodes (12): BusinessException, InvalidStatusTransitionException, log_delivery_operation(), log_operation(), log_order_operation(), log_settlement_operation(), log_user_operation(), OrderLockedException (+4 more)
### Community 15 - "Community 15"
Cohesion: 0.21
Nodes (19): _consumable_row_to_dict(), create_process(), _create_sub_consumable(), _create_sub_data_collection(), _create_sub_output(), _create_sub_reagent(), _data_collection_row_to_dict(), get_process() (+11 more)
Cohesion: 0.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 16 - "Community 16"
Cohesion: 0.18
Nodes (17): generate_sms(), _get_current_user_id(), _get_tenant_no(), list_notifications(), _page_payload(), toggle_status(), ToggleStatusBody, _accept_conclusion_label() (+9 more)
Cohesion: 0.12
Nodes (10): 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, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 tot, 生成签名 V3 (SHA256 with RSA), wechat_pay() (+2 more)
### Community 17 - "Community 17"
Cohesion: 0.18
@@ -168,76 +167,76 @@ Nodes (14): deduct_for_task(), _display_remark(), list_usages(), list_usages_by_
### Community 19 - "Community 19"
Cohesion: 0.25
Nodes (13): code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), _norm_status(), options_list() (+5 more)
### Community 20 - "Community 20"
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 21 - "Community 21"
### Community 20 - "Community 20"
Cohesion: 0.26
Nodes (12): batch_issue_sample_codes(), batch_revoke_sample_codes(), create_sample_code(), get_sample_code(), list_sample_codes(), _parse_issued_time(), 样本编码池 CRUD(biz_sample_code), _resolve_issued_user_display_name() (+4 more)
### Community 22 - "Community 22"
### Community 21 - "Community 21"
Cohesion: 0.24
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import Wech, 发送模板消息 Args: openid: 用户openid templ, send_delivery_notice(), send_delivery_warning(), send_order_status(), send_payment_success(), send_refund_result(), send_urge_notification() (+1 more)
### Community 23 - "Community 23"
Cohesion: 0.23
Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
### Community 22 - "Community 22"
Cohesion: 0.29
Nodes (10): _accept_conclusion_label(), _base_query(), _ensure_notification(), _fmt_dt(), generate_sms_content(), list_notifications(), resolve_notification(), _row_to_dict() (+2 more)
### Community 24 - "Community 24"
### Community 23 - "Community 23"
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 25 - "Community 25"
Cohesion: 0.3
Nodes (10): create_consumable_pack(), get_consumable_pack(), get_pack_detail(), _item_row_to_dict(), list_all_packs(), list_consumable_packs(), pack_code_exists(), _row_to_dict() (+2 more)
### Community 26 - "Community 26"
### Community 24 - "Community 24"
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 27 - "Community 27"
### Community 25 - "Community 25"
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 28 - "Community 28"
### Community 26 - "Community 26"
Cohesion: 0.31
Nodes (8): create_sop_document(), get_sop_document(), list_sop_documents(), SOP文档 CRUD(biz_sop_document), _row_to_dict(), soft_delete_sop_document(), sop_code_exists(), update_sop_document()
### Community 29 - "Community 29"
### Community 27 - "Community 27"
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 30 - "Community 30"
### Community 28 - "Community 28"
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 31 - "Community 31"
### Community 29 - "Community 29"
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 32 - "Community 32"
### Community 30 - "Community 30"
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 33 - "Community 33"
### Community 31 - "Community 31"
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 34 - "Community 34"
### Community 32 - "Community 32"
Cohesion: 0.31
Nodes (8): create_customer(), get_customer(), id_card_taken(), list_customers(), 客户 CRUD(biz_customer), _row_to_dict(), soft_delete_customer(), update_customer()
### 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 35 - "Community 35"
### 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 36 - "Community 36"
### Community 35 - "Community 35"
Cohesion: 0.36
Nodes (7): create_post(), get_post(), list_posts(), post_code_exists(), _row_to_dict(), soft_delete_post(), update_post()
### Community 36 - "Community 36"
Cohesion: 0.36
Nodes (7): create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), _row_to_dict(), soft_delete_dict_type(), update_dict_type()
### Community 37 - "Community 37"
Cohesion: 0.36
Nodes (7): create_tenant(), get_tenant(), list_tenants(), _row_to_dict(), soft_delete_tenant(), tenant_no_exists(), update_tenant()
@@ -255,50 +254,46 @@ Cohesion: 0.38
Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 41 - "Community 41"
Cohesion: 0.33
Nodes (5): 菜单 code 权限守卫(V0.3:通过 sys_user_role → sys_role_menu → sys_menu.perms), 运营端角色守卫:admin / super_admin 可访问。, 接口菜单权限守卫。super_admin 直接放行。, require_admin_or_super_admin(), require_menu_code()
### Community 42 - "Community 42"
Cohesion: 0.5
Nodes (3): BaseSettings, Config, Settings
### Community 43 - "Community 43"
### Community 42 - "Community 42"
Cohesion: 0.5
Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
### Community 44 - "Community 44"
### Community 43 - "Community 43"
Cohesion: 0.67
Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)
### Community 45 - "Community 45"
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (1): 请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
### Community 46 - "Community 46"
### Community 45 - "Community 45"
Cohesion: 1.0
Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
### Community 49 - "Community 49"
### Community 48 - "Community 48"
Cohesion: 1.0
Nodes (1): 发送订单状态通知 Args: openid: 用户openid ord
### Community 50 - "Community 50"
### Community 49 - "Community 49"
Cohesion: 1.0
Nodes (1): 发送支付成功通知 Args: openid: 用户openid ord
### Community 51 - "Community 51"
### Community 50 - "Community 50"
Cohesion: 1.0
Nodes (1): 发送配送通知 Args: openid: 配送员openid task
### Community 52 - "Community 52"
### Community 51 - "Community 51"
Cohesion: 1.0
Nodes (1): 发送配送时效预警 Args: openid: 配送员openid ta
### Community 53 - "Community 53"
### Community 52 - "Community 52"
Cohesion: 1.0
Nodes (1): 发送退款结果通知 Args: openid: 用户openid ord
### Community 54 - "Community 54"
### Community 53 - "Community 53"
Cohesion: 1.0
Nodes (1): 发送催单通知给配送员 Args: deliver_openid: 配送员openid
@@ -307,41 +302,41 @@ Nodes (1): 发送催单通知给配送员 Args: del
These have ≤1 connection - possible missing edges or undocumented components.
- **Thin community `Community 39`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 43`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
- **Thin community `Community 42`** (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 44`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,供后端菜单模式联调)`
- **Thin community `Community 43`** (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 45`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
- **Thin community `Community 44`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 46`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
- **Thin community `Community 45`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 49`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
- **Thin community `Community 48`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 50`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid 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 51`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
- **Thin community `Community 50`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 52`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
- **Thin community `Community 51`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 53`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
- **Thin community `Community 52`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 54`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
- **Thin community `Community 53`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `generate_uuid()` connect `Community 3` to `Community 0`, `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 10`, `Community 11`, `Community 12`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `Community 20`, `Community 21`, `Community 24`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`, `Community 38`?**
- **Why does `generate_uuid()` connect `Community 4` to `Community 0`, `Community 1`, `Community 2`, `Community 3`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 17`, `Community 18`, `Community 19`, `Community 20`, `Community 22`, `Community 23`, `Community 24`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`, `Community 38`?**
_High betweenness centrality (0.094) - this node is a cross-community bridge._
- **Why does `SysUser` connect `Community 1` to `Community 0`, `Community 2`, `Community 3`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 16`, `Community 18`, `Community 20`, `Community 21`, `Community 24`?**
_High betweenness centrality (0.093) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 4`, `Community 6`, `Community 7`, `Community 44`, `Community 12`, `Community 16`?**
_High betweenness centrality (0.065) - this node is a cross-community bridge._
- **Are the 418 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 418 INFERRED edges - model-reasoned connections that need verification._
- **Are the 398 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
_`str` has 398 INFERRED edges - model-reasoned connections that need verification._
- **Are the 336 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
_`error_response()` has 336 INFERRED edges - model-reasoned connections that need verification._
- **Are the 232 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
_`SysUser` has 232 INFERRED edges - model-reasoned connections that need verification._
- **Why does `SysUser` connect `Community 1` to `Community 2`, `Community 3`, `Community 4`, `Community 6`, `Community 8`, `Community 10`, `Community 11`, `Community 12`, `Community 15`, `Community 18`, `Community 19`, `Community 20`, `Community 23`?**
_High betweenness centrality (0.084) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 3`, `Community 6`, `Community 43`, `Community 12`, `Community 11`, `Community 14`, `Community 15`?**
_High betweenness centrality (0.061) - this node is a cross-community bridge._
- **Are the 430 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 430 INFERRED edges - model-reasoned connections that need verification._
- **Are the 409 inferred relationships involving `str` (e.g. with `extract_login_credentials()` and `._make_request()`) actually correct?**
_`str` has 409 INFERRED edges - model-reasoned connections that need verification._
- **Are the 347 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
_`error_response()` has 347 INFERRED edges - model-reasoned connections that need verification._
- **Are the 250 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
_`SysUser` has 250 INFERRED edges - model-reasoned connections that need verification._
+4 -4
View File
@@ -57,12 +57,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">2664 nodes &middot; 11010 edges &middot; 59 communities</div>
<div id="stats">2723 nodes &middot; 11449 edges &middot; 58 communities</div>
</div>
<script>
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": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_init_scheduled_tasks", "label": "init_scheduled_tasks()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "init_scheduled_tasks()", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_shutdown_scheduler", "label": "shutdown_scheduler()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "shutdown_scheduler()", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "core_auth_py", "label": "auth.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 11.3, "font": {"size": 0, "color": "#ffffff"}, "title": "auth.py", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 18}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_redis_session_enabled()", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 2}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.6, "font": {"size": 0, "color": "#ffffff"}, "title": "_get_redis_client()", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 9}, {"id": "core_auth_session_key", "label": "_session_key()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "_session_key()", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 5}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "color": {"background": "#B07AA1", "border": "#B07AA1", "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": 495}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 447}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 305}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 213}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 160}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 149}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 117}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 113}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 71}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 68}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 46}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 41}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 38}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 31}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 21}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 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": 15}, {"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": 12}, {"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": 10}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 9}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 9}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 9}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 8}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 7}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 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}];
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 46, "community_name": "Community 46", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_init_scheduled_tasks", "label": "init_scheduled_tasks()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "init_scheduled_tasks()", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "tasks_init_shutdown_scheduler", "label": "shutdown_scheduler()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "shutdown_scheduler()", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degree": 2}, {"id": "core_auth_py", "label": "auth.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 11.3, "font": {"size": 0, "color": "#ffffff"}, "title": "auth.py", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 18}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_redis_session_enabled()", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 2}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.6, "font": {"size": 0, "color": "#ffffff"}, "title": "_get_redis_client()", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 9}, {"id": "core_auth_session_key", "label": "_session_key()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "_session_key()", "community": 6, "community_name": "Community 6", "source_file": "core/auth.py", "file_type": "code", "degree": 5}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "color": {"background": "#B07AA1", "border": "#B07AA1", "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": 489}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 448}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 320}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 192}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 161}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 155}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 105}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 81}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 69}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 68}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 68}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 67}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 60}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 47}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 38}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 33}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 29}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 20}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 15}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 15}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 14}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 13}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 12}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 12}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 11}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 10}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 10}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 10}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 10}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 10}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 10}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 10}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 10}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 9}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 9}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 9}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 9}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 8}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 7}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 4}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 4}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 3}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 2}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 2}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 1}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 1}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 1}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 1}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 1}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 1}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 1}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 1}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 1}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 1}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 0}];
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
+10463 -4664
View File
File diff suppressed because it is too large. Load diff
+7 -7
View File
@@ -25,7 +25,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/core/wechat_message.py": 1778578258.0458734,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/material.py": 1779283385.245847,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_param.py": 1779022399.0175831,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1779614947.2542932,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1779623962.9411385,
"/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,
@@ -63,7 +63,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": 1779613697.2166514,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_release_review.py": 1779616246.7074304,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_task.py": 1779612097.0528247,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/process_route.py": 1779587424.6859367,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_code.py": 1779279460.690872,
@@ -71,7 +71,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/post.py": 1779265648.38155,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception_check_result.py": 1779255909.8554008,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py": 1778775532.8870275,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py": 1779614962.3649387,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py": 1779615808.132888,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/material.py": 1779283386.3879013,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/dict_type.py": 1779265621.5212462,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_occupancy.py": 1779418213.0446064,
@@ -80,10 +80,10 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/tenant.py": 1779265611.0532296,
"/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": 1779615002.3167124,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779615482.8343122,
"/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": 1779512669.9847593,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1779542463.606357,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1779616277.9259753,
"/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": 1779515479.6599197,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py": 1778775238.2993922,
@@ -105,7 +105,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/item_unit.py": 1779265653.7504313,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_work_order.py": 1779614954.1003788,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/process.py": 1779309113.0447981,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py": 1779310971.8304002,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py": 1779623933.0959795,
"/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_sms_notification.py": 1779545309.6706858,
@@ -136,7 +136,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py": 1779265690.8423955,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/research_donation.py": 1779266149.3047824,
"/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/pilot_service.py": 1779623934.1963308,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/workflow.py": 1779266232.4568832,
"/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,
@@ -0,0 +1,125 @@
-- ============================================================
-- 渠道服务订单:多次操作流水模型迁移
-- Date: 2026-05-24
-- ============================================================
-- 1. 新增操作流水表
DROP TABLE IF EXISTS `biz_channel_service_order_txn`;
CREATE TABLE `biz_channel_service_order_txn` (
`id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主键ID',
`service_order_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '关联订单ID',
`txn_type` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'recharge/refund/purchase/unsubscribe',
`amount` decimal(18,2) DEFAULT NULL COMMENT '本次操作金额',
`txn_status` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'dsx' COMMENT 'dsx待生效 dqr待财务确认 yqr已确认 yzf已作废',
`products_json` text COLLATE utf8mb4_unicode_ci COMMENT '产品明细JSON(purchase/unsubscribe类型)',
`remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
`finance_submit_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发起确认人ID',
`finance_submit_time` datetime DEFAULT NULL COMMENT '发起确认时间',
`finance_submit_remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发起确认备注',
`finance_submit_attachments` text COLLATE utf8mb4_unicode_ci COMMENT '发起确认附件',
`finance_confirm_time` datetime DEFAULT NULL COMMENT '财务确认时间',
`finance_confirm_attachments` text COLLATE utf8mb4_unicode_ci COMMENT '财务确认附件',
`finance_remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '财务确认备注',
`balance_before` decimal(18,2) DEFAULT NULL COMMENT '操作前余额(yfk类型)',
`balance_after` decimal(18,2) DEFAULT NULL COMMENT '操作后余额(yfk类型)',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`create_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_txn_order` (`service_order_id`, `del_flag`),
KEY `idx_txn_status` (`txn_status`, `tenant_no`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='渠道服务订单操作流水';
-- 2. 订单主表新增汇总字段
ALTER TABLE `biz_channel_service_order`
ADD COLUMN `total_recharge_amount` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '累计充值总额' AFTER `channel_agreement_id`,
ADD COLUMN `total_refund_amount` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '累计退款总额' AFTER `total_recharge_amount`,
ADD COLUMN `current_balance` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '当前余额' AFTER `total_refund_amount`;
-- 3. 产品持仓表新增字段
ALTER TABLE `biz_channel_service_order_product`
ADD COLUMN `total_buy_qty` decimal(18,4) NOT NULL DEFAULT 0.0000 COMMENT '累计购买数量' AFTER `buy_amount`,
ADD COLUMN `total_unsubscribe_qty` decimal(18,4) NOT NULL DEFAULT 0.0000 COMMENT '累计退订数量' AFTER `total_buy_qty`,
ADD COLUMN `current_qty` decimal(18,4) NOT NULL DEFAULT 0.0000 COMMENT '当前持有数量' AFTER `total_unsubscribe_qty`,
ADD COLUMN `total_unsubscribe_amount` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '累计退订金额' AFTER `current_qty`;
-- ============================================================
-- 以下为数据迁移(可选执行,用于保留历史数据)
-- ============================================================
-- 4. 迁移现有充值记录到流水表
INSERT INTO `biz_channel_service_order_txn` (
`id`, `service_order_id`, `txn_type`, `amount`, `txn_status`,
`remark`,
`finance_submit_by`, `finance_submit_time`, `finance_submit_remark`, `finance_submit_attachments`,
`finance_confirm_time`, `finance_confirm_attachments`, `finance_remark`,
`balance_before`, `balance_after`,
`tenant_no`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
REPLACE(UUID(),'-','') AS `id`,
o.`id` AS `service_order_id`,
'recharge' AS `txn_type`,
o.`prepay_amount` AS `amount`,
CASE
WHEN o.`finance_confirm_time` IS NOT NULL THEN 'yqr'
WHEN o.`finance_submit_time` IS NOT NULL THEN 'dqr'
ELSE 'dsx'
END AS `txn_status`,
o.`remark`,
o.`finance_submit_by`, o.`finance_submit_time`, o.`finance_submit_remark`, o.`finance_submit_attachments`,
o.`finance_confirm_time`, o.`finance_confirm_attachments`, o.`finance_remark`,
o.`balance_before`, o.`balance_after`,
o.`tenant_no`, o.`create_by`, o.`create_dept_id`, o.`create_time`, o.`update_by`, o.`update_time`, o.`del_flag`
FROM `biz_channel_service_order` o
WHERE o.`order_type` = 'yfk' AND (o.`finance_submit_time` IS NOT NULL OR o.`prepay_amount` IS NOT NULL);
-- 5. 迁移退款记录到流水表
INSERT INTO `biz_channel_service_order_txn` (
`id`, `service_order_id`, `txn_type`, `amount`, `txn_status`,
`remark`,
`finance_submit_by`, `finance_submit_time`, `finance_submit_remark`, `finance_submit_attachments`,
`finance_confirm_time`, `finance_confirm_attachments`, `finance_remark`,
`tenant_no`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
REPLACE(UUID(),'-','') AS `id`,
o.`id` AS `service_order_id`,
'refund' AS `txn_type`,
o.`refund_amount` AS `amount`,
CASE
WHEN o.`refund_finance_confirm_time` IS NOT NULL THEN 'yqr'
ELSE 'dqr'
END AS `txn_status`,
o.`refund_remark` AS `remark`,
o.`refund_apply_by` AS `finance_submit_by`,
o.`refund_apply_time` AS `finance_submit_time`,
o.`refund_remark` AS `finance_submit_remark`,
o.`refund_attachments` AS `finance_submit_attachments`,
o.`refund_finance_confirm_time` AS `finance_confirm_time`,
o.`refund_finance_confirm_attachments` AS `finance_confirm_attachments`,
o.`refund_finance_remark` AS `finance_remark`,
o.`tenant_no`, o.`refund_apply_by` AS `create_by`, o.`create_dept_id`,
COALESCE(o.`refund_apply_time`, o.`update_time`) AS `create_time`,
o.`update_by`, o.`update_time`, o.`del_flag`
FROM `biz_channel_service_order` o
WHERE o.`refund_amount` IS NOT NULL AND o.`refund_amount` > 0;
-- 6. 回填主表汇总字段(yfk类型)
UPDATE `biz_channel_service_order` o
SET
`total_recharge_amount` = COALESCE(o.`prepay_amount`, 0),
`total_refund_amount` = COALESCE(o.`refund_amount`, 0),
`current_balance` = COALESCE(o.`prepay_amount`, 0) - COALESCE(o.`refund_amount`, 0)
WHERE o.`order_type` = 'yfk' AND o.`prepay_amount` IS NOT NULL;
-- 7. 回填产品持仓表的累计字段
UPDATE `biz_channel_service_order_product` p
SET
`total_buy_qty` = COALESCE(p.`buy_qty`, 0),
`current_qty` = COALESCE(p.`buy_qty`, 0);
-59
View File
@@ -1,59 +0,0 @@
-- ============================================================
-- 工单表合并迁移:biz_temp_* → 主表 + work_order_type
-- Date: 2026-05-24
-- 执行顺序:先本脚本,再 work_order_unification_phase1.sql
-- 适用:仍保留 biz_temp_qc_work_order / biz_temp_production_work_order 的旧库
-- ============================================================
-- 1. biz_qc_work_order: 加 work_order_type(若已存在则跳过,需 MySQL 8+ 或手动检查)
-- ALTER TABLE biz_qc_work_order
-- ADD COLUMN work_order_type VARCHAR(20) NOT NULL DEFAULT 'inbound'
-- COMMENT '工单类型: inbound=入库, temporary=临时' AFTER work_order_no;
-- 2. reception 关联字段改为可空(临时工单不需要)
-- ALTER TABLE biz_qc_work_order
-- MODIFY COLUMN reception_id VARCHAR(64) NULL,
-- MODIFY COLUMN protocol_sample_id VARCHAR(64) NULL,
-- MODIFY COLUMN collection_protocol_id VARCHAR(64) NULL,
-- MODIFY COLUMN reception_source VARCHAR(20) NULL DEFAULT 'cell_storage';
-- 3. 迁移临时质检工单(按 id 去重,避免重复执行)
INSERT INTO biz_qc_work_order (
id, work_order_no, work_order_type, work_order_status,
has_lab, has_third_party, third_party_fee_total,
configured_time, configured_by,
tenant_no, order_num, remark,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
t.id, t.work_order_no, 'temporary', t.work_order_status,
t.has_lab, t.has_third_party, t.third_party_fee_total,
t.configured_time, t.configured_by,
t.tenant_no, t.order_num, t.remark,
t.create_by, t.create_dept_id, t.create_time, t.update_by, t.update_time, t.del_flag
FROM biz_temp_qc_work_order t
WHERE NOT EXISTS (SELECT 1 FROM biz_qc_work_order m WHERE m.id = t.id);
-- 4. biz_production_work_order: 加 work_order_type / configured_time / configured_by(若未加请手动 ALTER)
-- ALTER TABLE biz_production_work_order ADD COLUMN work_order_type ...
-- ALTER TABLE biz_production_work_order ADD COLUMN configured_time DATETIME NULL ...
-- ALTER TABLE biz_production_work_order ADD COLUMN configured_by VARCHAR(64) NULL ...
-- 5. 迁移临时生产工单
INSERT INTO biz_production_work_order (
id, work_order_no, work_order_type, work_order_status,
configured_time, configured_by,
tenant_no, order_num, remark,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
t.id, t.work_order_no, 'temporary', t.work_order_status,
t.configured_time, t.configured_by,
t.tenant_no, t.order_num, t.remark,
t.create_by, t.create_dept_id, t.create_time, t.update_by, t.update_time, t.del_flag
FROM biz_temp_production_work_order t
WHERE NOT EXISTS (SELECT 1 FROM biz_production_work_order m WHERE m.id = t.id);
-- 6. 删除临时表(确认迁移成功后执行)
DROP TABLE IF EXISTS biz_temp_qc_work_order;
DROP TABLE IF EXISTS biz_temp_production_work_order;
-5
View File
@@ -1,5 +0,0 @@
-- 生产任务:生产结论(cg=成功 sb=失败)
ALTER TABLE biz_production_task
ADD COLUMN conclusion VARCHAR(16) NULL
COMMENT '生产结论 cg=成功 sb=失败'
AFTER completed_time;
-7
View File
@@ -1,7 +0,0 @@
-- ============================================================
-- 临时质检工单关联细胞产品(质检对象)
-- Date: 2026-05-24
-- ============================================================
ALTER TABLE biz_qc_work_order
ADD COLUMN cell_product_id VARCHAR(64) DEFAULT NULL COMMENT '质检对象-细胞产品ID' AFTER qc_biz_type;
@@ -1,47 +0,0 @@
-- ============================================================
-- 工单融合 Phase 1:菜单收口 + 数据修正 + 删除废弃临时表
-- Date: 2026-05-24
--
-- 执行顺序:
-- 1) 若库中仍有 biz_temp_* 表 → 先执行 merge_work_order_tables.sql
-- 2) 再执行本脚本
--
-- 说明:zkxw.sql 全量基线已无 biz_temp_* 表;本脚本 DROP 用于清理历史库残留。
-- ============================================================
-- 1. 菜单重命名与软删临时工单菜单
UPDATE sys_menu SET menu_name = '质检工单', update_time = NOW()
WHERE id = '70000000000000000000000000000007' AND del_flag = 0;
UPDATE sys_menu SET menu_name = '生产工单', update_time = NOW()
WHERE id = '90000000000000000000000000000011' AND del_flag = 0;
UPDATE sys_menu SET del_flag = 1, update_time = NOW()
WHERE id IN (
'70000000000000000000000000000012',
'90000000000000000000000000000110'
) AND del_flag = 0;
-- 2. 临时工单 reception_id 空串修正为 NULL(避免 uk_qc_wo_reception 冲突)
UPDATE biz_qc_work_order
SET reception_id = NULL,
protocol_sample_id = NULL,
collection_protocol_id = NULL,
update_time = NOW()
WHERE work_order_type = 'temporary'
AND del_flag = 0
AND (reception_id = '' OR reception_id IS NULL);
UPDATE biz_production_work_order
SET reception_id = NULL,
protocol_sample_id = NULL,
collection_protocol_id = NULL,
update_time = NOW()
WHERE work_order_type = 'temporary'
AND del_flag = 0
AND (reception_id = '' OR reception_id IS NULL);
-- 3. 删除已废弃的临时工单表(ORM/代码已不再使用)
-- 若表内仍有未迁移数据,请先执行 merge_work_order_tables.sql 再 DROP
DROP TABLE IF EXISTS biz_temp_qc_work_order;
DROP TABLE IF EXISTS biz_temp_production_work_order;
+270 -82
View File
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,633 @@
# 渠道服务订单多次操作流水模型 实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将渠道服务订单从单次操作模型改造为多次操作流水模型,支持多次充值、退款、购买产品、按份数退订。
**Architecture:** 订单主表(biz_channel_service_order)管汇总,新增操作流水表(biz_channel_service_order_txn)管每笔操作的明细和财务确认流程,产品持仓表(biz_channel_service_order_product)改造为追踪累计购买/退订/当前持有份数。
**Tech Stack:** Python 3.9 / FastAPI / SQLAlchemy / Pydantic v2 / MySQL 5.7 / Vue 3 / Element Plus / TypeScript
**Design Spec:** `docs/superpowers/specs/2026-05-24-channel-service-order-multi-txn-design.md`
---
## 文件结构
### 新增文件
- `docs/sql/channel-service-order-txn-migration.sql` — 数据库迁移 SQL
- `backend/app/models/channel_service_order_txn.py` — 流水 Model(或合并到 models.py)
### 修改文件
- `backend/app/models/models.py` — 新增 BizChannelServiceOrderTxn model,改造 BizChannelServiceOrder/BizChannelServiceOrderProduct
- `backend/app/crud/pilot_service.py` — 新增流水 CRUD + 改造订单 CRUD
- `backend/app/api/pilot_service.py` — 新增流水 API + Pydantic schemas
- `web-admin/src/api/admin.ts` — 新增流水相关 API 调用函数
- `web-admin/src/views/pilot-service/channel-service-order/index.vue` — 订单管理页改造
- `web-admin/src/views/pilot-service/channel-service-order-finance/index.vue` — 财务确认页改造
---
## Task 1: 数据库迁移 — 流水表 + 主表改造 + 产品表改造
**Files:**
- Create: `docs/sql/channel-service-order-txn-migration.sql`
- [ ] **Step 1: 编写迁移 SQL**
```sql
-- ============================================================
-- 渠道服务订单:多次操作流水模型迁移
-- ============================================================
-- 1. 新增操作流水表
CREATE TABLE `biz_channel_service_order_txn` (
`id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主键ID',
`service_order_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '关联订单ID',
`txn_type` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'recharge/refund/purchase/unsubscribe',
`amount` decimal(18,2) DEFAULT NULL COMMENT '本次操作金额',
`txn_status` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'dsx' COMMENT 'dsx待生效 dqr待财务确认 yqr已确认 yzf已作废',
`products_json` text COLLATE utf8mb4_unicode_ci COMMENT '产品明细JSON(purchase/unsubscribe类型)',
`remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
`finance_submit_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发起确认人ID',
`finance_submit_time` datetime DEFAULT NULL COMMENT '发起确认时间',
`finance_submit_remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '发起确认备注',
`finance_submit_attachments` text COLLATE utf8mb4_unicode_ci COMMENT '发起确认附件',
`finance_confirm_time` datetime DEFAULT NULL COMMENT '财务确认时间',
`finance_confirm_attachments` text COLLATE utf8mb4_unicode_ci COMMENT '财务确认附件',
`finance_remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '财务确认备注',
`balance_before` decimal(18,2) DEFAULT NULL COMMENT '操作前余额(yfk类型)',
`balance_after` decimal(18,2) DEFAULT NULL COMMENT '操作后余额(yfk类型)',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_txn_order` (`service_order_id`, `del_flag`),
KEY `idx_txn_status` (`txn_status`, `tenant_no`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='渠道服务订单操作流水';
-- 2. 订单主表新增汇总字段
ALTER TABLE `biz_channel_service_order`
ADD COLUMN `total_recharge_amount` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '累计充值总额' AFTER `channel_agreement_id`,
ADD COLUMN `total_refund_amount` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '累计退款总额' AFTER `total_recharge_amount`,
ADD COLUMN `current_balance` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '当前余额' AFTER `total_refund_amount`;
-- 3. 产品持仓表新增字段
ALTER TABLE `biz_channel_service_order_product`
ADD COLUMN `total_buy_qty` decimal(18,4) NOT NULL DEFAULT 0.0000 COMMENT '累计购买数量' AFTER `buy_amount`,
ADD COLUMN `total_unsubscribe_qty` decimal(18,4) NOT NULL DEFAULT 0.0000 COMMENT '累计退订数量' AFTER `total_buy_qty`,
ADD COLUMN `current_qty` decimal(18,4) NOT NULL DEFAULT 0.0000 COMMENT '当前持有数量' AFTER `total_unsubscribe_qty`,
ADD COLUMN `total_unsubscribe_amount` decimal(18,2) NOT NULL DEFAULT 0.00 COMMENT '累计退订金额' AFTER `current_qty`;
-- 4. 迁移现有订单数据到流水表(一次性,保留历史数据)
-- 注意:仅迁移有操作记录的订单(有 finance_submit_time 或 refund_apply_time 的)
INSERT INTO `biz_channel_service_order_txn` (
`id`, `service_order_id`, `txn_type`, `amount`, `txn_status`,
`remark`,
`finance_submit_by`, `finance_submit_time`, `finance_submit_remark`, `finance_submit_attachments`,
`finance_confirm_time`, `finance_confirm_attachments`, `finance_remark`,
`balance_before`, `balance_after`,
`tenant_no`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
UUID_SHORT() AS `id`,
o.`id` AS `service_order_id`,
'recharge' AS `txn_type`,
o.`prepay_amount` AS `amount`,
CASE
WHEN o.`finance_confirm_time` IS NOT NULL THEN 'yqr'
WHEN o.`finance_submit_time` IS NOT NULL THEN 'dqr'
ELSE 'dsx'
END AS `txn_status`,
o.`remark`,
o.`finance_submit_by`, o.`finance_submit_time`, o.`finance_submit_remark`, o.`finance_submit_attachments`,
o.`finance_confirm_time`, o.`finance_confirm_attachments`, o.`finance_remark`,
o.`balance_before`, o.`balance_after`,
o.`tenant_no`, o.`create_by`, o.`create_dept_id`, o.`create_time`, o.`update_by`, o.`update_time`, o.`del_flag`
FROM `biz_channel_service_order` o
WHERE o.`finance_submit_time` IS NOT NULL OR o.`prepay_amount` IS NOT NULL;
-- 5. 迁移退款记录到流水表
INSERT INTO `biz_channel_service_order_txn` (
`id`, `service_order_id`, `txn_type`, `amount`, `txn_status`,
`remark`,
`finance_submit_by`, `finance_submit_time`, `finance_submit_remark`, `finance_submit_attachments`,
`finance_confirm_time`, `finance_confirm_attachments`, `finance_remark`,
`tenant_no`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
)
SELECT
UUID_SHORT() AS `id`,
o.`id` AS `service_order_id`,
'refund' AS `txn_type`,
o.`refund_amount` AS `amount`,
CASE
WHEN o.`refund_finance_confirm_time` IS NOT NULL THEN 'yqr'
ELSE 'dqr'
END AS `txn_status`,
o.`refund_remark` AS `remark`,
o.`refund_apply_by` AS `finance_submit_by`,
o.`refund_apply_time` AS `finance_submit_time`,
o.`refund_remark` AS `finance_submit_remark`,
o.`refund_attachments` AS `finance_submit_attachments`,
o.`refund_finance_confirm_time` AS `finance_confirm_time`,
o.`refund_finance_confirm_attachments` AS `finance_confirm_attachments`,
o.`refund_finance_remark` AS `finance_remark`,
o.`tenant_no`, o.`refund_apply_by` AS `create_by`, o.`create_dept_id`,
COALESCE(o.`refund_apply_time`, o.`update_time`) AS `create_time`,
o.`update_by`, o.`update_time`, o.`del_flag`
FROM `biz_channel_service_order` o
WHERE o.`refund_amount` IS NOT NULL AND o.`refund_amount` > 0;
-- 6. 回填主表汇总字段
UPDATE `biz_channel_service_order` o
SET
`total_recharge_amount` = COALESCE(o.`prepay_amount`, 0),
`total_refund_amount` = COALESCE(o.`refund_amount`, 0),
`current_balance` = COALESCE(o.`prepay_amount`, 0) - COALESCE(o.`refund_amount`, 0)
WHERE o.`order_type` = 'yfk' AND o.`prepay_amount` IS NOT NULL;
-- 7. 回填产品持仓表的累计字段
UPDATE `biz_channel_service_order_product` p
SET
`total_buy_qty` = COALESCE(p.`buy_qty`, 0),
`current_qty` = COALESCE(p.`buy_qty`, 0);
```
- [ ] **Step 2: 在数据库执行迁移**
Run: 手动在 MySQL 中执行上述 SQL,或逐步执行确认无误。
---
## Task 2: 后端 Model — 新增流水 Model + 改造主表/产品 Model
**Files:**
- Modify: `backend/app/models/models.py` (line ~1762, BizChannelServiceOrder class)
- [ ] **Step 1: 在 models.py 中 BizChannelServiceOrder 类新增字段**
在 `BizChannelServiceOrder` 类的 `channel_agreement_id` 字段后面添加三个汇总字段:
```python
total_recharge_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="累计充值总额")
total_refund_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="累计退款总额")
current_balance = Column(Numeric(18, 2), nullable=False, default=0, comment="当前余额")
```
- [ ] **Step 2: 在 BizChannelServiceOrderProduct 类新增字段**
在 `buy_amount` 字段后面添加:
```python
total_buy_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="累计购买数量")
total_unsubscribe_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="累计退订数量")
current_qty = Column(Numeric(18, 4), nullable=False, default=0, comment="当前持有数量")
total_unsubscribe_amount = Column(Numeric(18, 2), nullable=False, default=0, comment="累计退订金额")
```
- [ ] **Step 3: 在 BizChannelServiceOrderProduct 类后面新增 BizChannelServiceOrderTxn 类**
```python
class BizChannelServiceOrderTxn(Base):
"""渠道服务订单操作流水 biz_channel_service_order_txn"""
__tablename__ = "biz_channel_service_order_txn"
id = Column(String(64), primary_key=True, comment="主键ID")
service_order_id = Column(String(64), nullable=False, comment="关联订单ID")
txn_type = Column(String(16), nullable=False, comment="recharge/refund/purchase/unsubscribe")
amount = Column(Numeric(18, 2), nullable=True, comment="本次操作金额")
txn_status = Column(String(16), nullable=False, default="dsx", comment="dsx待生效 dqr待财务确认 yqr已确认 yzf已作废")
products_json = Column(Text, nullable=True, comment="产品明细JSON(purchase/unsubscribe类型)")
remark = Column(String(512), nullable=True, comment="备注")
finance_submit_by = Column(String(64), nullable=True, comment="发起确认人ID")
finance_submit_time = Column(DateTime, nullable=True, comment="发起确认时间")
finance_submit_remark = Column(String(512), nullable=True, comment="发起确认备注")
finance_submit_attachments = Column(Text, nullable=True, comment="发起确认附件")
finance_confirm_time = Column(DateTime, nullable=True, comment="财务确认时间")
finance_confirm_attachments = Column(Text, nullable=True, comment="财务确认附件")
finance_remark = Column(String(512), nullable=True, comment="财务确认备注")
balance_before = Column(Numeric(18, 2), nullable=True, comment="操作前余额")
balance_after = Column(Numeric(18, 2), nullable=True, comment="操作后余额")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark_col = Column("remark", String(512), nullable=True, comment="备注")
create_by = Column(String(64), nullable=True, comment="创建人id")
create_dept_id = Column(String(64), nullable=False, default="", comment="创建人部门ID")
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
update_by = Column(String(64), nullable=True, comment="更新人id")
update_time = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间")
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标记")
```
注意:Model 中 `remark` 字段和表里的 `remark` 列名冲突(流水表有两个 remark 用途)—— 实际上流水表只有一个 `remark` 列。Model 中只保留一个 `remark` 即可,去掉上面的 `remark_col`,直接用 `remark`。
- [ ] **Step 4: 验证 import**
确保 `models.py` 文件头部已有 `from sqlalchemy import ... Column, String, Numeric, Text, DateTime, SmallInteger, Integer` 等导入。
---
## Task 3: 后端 CRUD — 流水 CRUD + 订单 CRUD 改造
**Files:**
- Modify: `backend/app/crud/pilot_service.py` (line ~2513+)
- [ ] **Step 1: 新增流水 _row_to_dict 函数**
在 `_row_to_dict_service_order_product` 函数后面添加:
```python
def _row_to_dict_service_order_txn(row, db=None, tenant_no=None) -> Dict[str, Any]:
tn = tenant_no or row.tenant_no
d = {
"id": row.id,
"serviceOrderId": row.service_order_id or "",
"txnType": row.txn_type or "",
"amount": float(row.amount) if row.amount else 0,
"txnStatus": row.txn_status or "",
"productsJson": row.products_json or "",
"remark": row.remark or "",
"financeSubmitBy": row.finance_submit_by or "",
"financeSubmitTime": row.finance_submit_time.strftime("%Y-%m-%d %H:%M:%S") if row.finance_submit_time else "",
"financeSubmitRemark": row.finance_submit_remark or "",
"financeSubmitAttachments": row.finance_submit_attachments or "",
"financeSubmitAttachmentFiles": urls_to_attachment_list(row.finance_submit_attachments, db, tn) if db and row.finance_submit_attachments else [],
"financeConfirmTime": row.finance_confirm_time.strftime("%Y-%m-%d %H:%M:%S") if row.finance_confirm_time else "",
"financeConfirmAttachments": row.finance_confirm_attachments or "",
"financeConfirmAttachmentFiles": urls_to_attachment_list(row.finance_confirm_attachments, db, tn) if db and row.finance_confirm_attachments else [],
"financeRemark": row.finance_remark or "",
"balanceBefore": float(row.balance_before) if row.balance_before else 0,
"balanceAfter": float(row.balance_after) if row.balance_after else 0,
"tenantNo": row.tenant_no or "",
"createBy": row.create_by or "",
"createTime": row.create_time.strftime("%Y-%m-%d %H:%M:%S") if row.create_time else "",
"updateTime": row.update_time.strftime("%Y-%m-%d %H:%M:%S") if row.update_time else "",
}
if row.products_json:
try:
d["products"] = json.loads(row.products_json)
except Exception:
d["products"] = []
else:
d["products"] = []
return d
```
- [ ] **Step 2: 改造 _row_to_dict_service_order,新增汇总字段、移除旧字段**
将 `prepayAmount`、`purchaseTotalAmount` 等保留但标记为兼容字段(从汇总计算),新增:
- `totalRechargeAmount`
- `totalRefundAmount`
- `currentBalance`
- `transactions`(列表,由调用方填充)
- `products`(列表,由调用方填充)
同时在详情查询时附带流水列表和产品持仓列表。
- [ ] **Step 3: 新增流水 CRUD 函数**
```python
def list_service_order_txns(db, *, service_order_id=None, txn_status=None, txn_type=None, page=1, page_size=20, tenant_no=None):
"""查询操作流水列表"""
...
def get_service_order_txn(db, txn_id, *, tenant_no=None):
"""获取单条流水"""
...
def create_recharge_txn(db, order_id, *, amount, remark=None, tenant_no=None, user_id=None):
"""创建充值流水(yfk订单)"""
...
def create_refund_txn(db, order_id, *, amount, remark=None, tenant_no=None, user_id=None):
"""创建退款流水(yfk订单),校验 amount <= current_balance"""
...
def create_purchase_txn(db, order_id, *, products, remark=None, tenant_no=None, user_id=None):
"""创建购买产品流水(gmcp订单),同时创建/更新产品持仓"""
...
def create_unsubscribe_txn(db, order_id, *, products, remark=None, tenant_no=None, user_id=None):
"""创建退订产品流水(gmcp订单),校验退订份数 <= current_qty"""
...
def submit_txn_finance(db, txn_id, *, finance_submit_remark=None, finance_submit_attachments=None, tenant_no=None, user_id=None):
"""发起流水财务确认:dsx → dqr"""
...
def confirm_txn(db, txn_id, *, finance_remark=None, finance_confirm_attachments=None, tenant_no=None, user_id=None):
"""财务确认流水:dqr → yqr,更新主表汇总和产品持仓"""
...
def void_txn(db, txn_id, *, tenant_no=None, user_id=None):
"""作废流水:dsx → yzf"""
...
```
- [ ] **Step 4: 改造 _row_to_dict_service_order_product,新增持仓字段**
在返回字典中新增:
```python
"totalBuyQty": float(row.total_buy_qty) if row.total_buy_qty else 0,
"totalUnsubscribeQty": float(row.total_unsubscribe_qty) if row.total_unsubscribe_qty else 0,
"currentQty": float(row.current_qty) if row.current_qty else 0,
"totalUnsubscribeAmount": float(row.total_unsubscribe_amount) if row.total_unsubscribe_amount else 0,
```
---
## Task 4: 后端 API — 流水接口 + Pydantic Schemas
**Files:**
- Modify: `backend/app/api/pilot_service.py` (line ~1552+)
- [ ] **Step 1: 新增 Pydantic Schemas**
在现有 `RefundConfirmBody` 后面添加:
```python
class TxnRechargeBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
amount: float = Field(..., gt=0, alias="amount")
remark: Optional[str] = Field(None, alias="remark")
class TxnRefundBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
amount: float = Field(..., gt=0, alias="amount")
remark: Optional[str] = Field(None, alias="remark")
class TxnProductItem(BaseModel):
model_config = ConfigDict(populate_by_name=True)
project_code: Optional[str] = Field(None, alias="projectCode")
project_name: Optional[str] = Field(None, alias="projectName")
cell_type: Optional[str] = Field(None, alias="cellType")
spec_text: Optional[str] = Field(None, alias="specText")
agreement_unit_price: Optional[float] = Field(None, alias="agreementUnitPrice")
qty: Optional[float] = Field(None, alias="qty")
amount: Optional[float] = Field(None, alias="amount")
class TxnPurchaseBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
products: List[TxnProductItem] = Field(..., alias="products")
remark: Optional[str] = Field(None, alias="remark")
class TxnUnsubscribeBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
products: List[TxnProductItem] = Field(..., alias="products")
remark: Optional[str] = Field(None, alias="remark")
class TxnFinanceSubmitBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
finance_submit_remark: Optional[str] = Field(None, alias="financeSubmitRemark")
finance_submit_attachments: Optional[str] = Field(None, alias="financeSubmitAttachments")
class TxnFinanceConfirmBody(BaseModel):
model_config = ConfigDict(populate_by_name=True)
finance_remark: Optional[str] = Field(None, alias="financeRemark")
finance_confirm_attachments: Optional[str] = Field(None, alias="financeConfirmAttachments")
```
- [ ] **Step 2: 新增流水 API 路由**
```python
@router.get("/channel-service-order-txns")
async def list_txns(...) # 列表查询,支持 status/type/order_id 筛选
@router.get("/channel-service-order-txns/{txn_id}")
async def get_txn_detail(...) # 流水详情
@router.post("/channel-service-orders/{order_id}/recharge")
async def create_recharge(...) # 创建充值流水
@router.post("/channel-service-orders/{order_id}/refund")
async def create_refund(...) # 创建退款流水
@router.post("/channel-service-orders/{order_id}/purchase")
async def create_purchase(...) # 创建购买流水
@router.post("/channel-service-orders/{order_id}/unsubscribe")
async def create_unsubscribe(...) # 创建退订流水
@router.post("/channel-service-order-txns/{txn_id}/submit-finance")
async def submit_txn_finance(...) # 发起财务确认
@router.post("/channel-service-order-txns/{txn_id}/confirm")
async def confirm_txn(...) # 财务确认
@router.put("/channel-service-order-txns/{txn_id}/void")
async def void_txn(...) # 作废流水
```
- [ ] **Step 3: 改造订单详情 API**
修改 `get_channel_service_order_detail` 接口,在返回数据中附带:
- `transactions`: 该订单的所有流水列表
- `products`: 该订单的产品持仓列表(gmcp)
---
## Task 5: 前端 API — 新增流水相关调用函数
**Files:**
- Modify: `web-admin/src/api/admin.ts` (line ~1900+)
- [ ] **Step 1: 新增流水 API 函数**
在现有 `fetchVoidServiceOrder` 后面添加:
```typescript
// ========== 渠道服务订单操作流水 ==========
/** 流水列表 */
export function fetchServiceOrderTxnList(params?: Record<string, any>) {
return request.get({ url: '/web/admin/channel-service-order-txns', params })
}
/** 流水详情 */
export function fetchServiceOrderTxnDetail(txnId: string) {
return request.get({ url: `/web/admin/channel-service-order-txns/${txnId}` })
}
/** 发起充值 */
export function fetchCreateRechargeTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/recharge`, params: data })
}
/** 申请退款 */
export function fetchCreateRefundTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/refund`, params: data })
}
/** 购买产品 */
export function fetchCreatePurchaseTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/purchase`, params: data })
}
/** 退订产品 */
export function fetchCreateUnsubscribeTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/unsubscribe`, params: data })
}
/** 流水发起财务确认 */
export function fetchSubmitTxnFinance(txnId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-order-txns/${txnId}/submit-finance`, params: data })
}
/** 流水财务确认 */
export function fetchConfirmTxn(txnId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-order-txns/${txnId}/confirm`, params: data })
}
/** 作废流水 */
export function fetchVoidTxn(txnId: string) {
return request.put({ url: `/web/admin/channel-service-order-txns/${txnId}/void` })
}
```
- [ ] **Step 2: 保留旧 API 函数但标记废弃**
不删除 `fetchSubmitServiceOrderFinanceConfirm`、`fetchConfirmServiceOrderReceipt`、`fetchSubmitServiceOrderRefund`、`fetchConfirmServiceOrderRefund`,保持向后兼容,但前端页面不再调用。
---
## Task 6: 前端订单管理页改造
**Files:**
- Modify: `web-admin/src/views/pilot-service/channel-service-order/index.vue`
这是改动最大的文件,核心变更:
- [ ] **Step 1: 更新 import**
新增导入流水相关 API 函数:`fetchCreateRechargeTxn`, `fetchCreateRefundTxn`, `fetchCreatePurchaseTxn`, `fetchCreateUnsubscribeTxn`, `fetchSubmitTxnFinance`,移除旧的 `fetchSubmitServiceOrderFinanceConfirm`, `fetchSubmitServiceOrderRefund` 调用。
- [ ] **Step 2: 更新操作按钮**
将操作列的按钮替换为:
- yfk + dsx → 编辑、删除、**发起充值**
- yfk + sxz → **发起充值**、**申请退款**
- gmcp + dsx → 编辑、删除、**购买产品**
- gmcp + sxz → **购买产品**、**退订产品**
- 任意 + yzf → 仅查看
- [ ] **Step 3: 改造详情弹窗(SystemViewDialog)**
在 viewSections computed 中:
- 基本信息section 新增 `currentBalance`(yfk)或产品持仓汇总(gmcp)
- 移除旧的"发起财务确认""财务确认信息""退款信息"平铺 sections
- 新增"操作记录"section,用 inner-table 展示流水列表(类型Tag、金额、状态Tag、时间)
- gmcp 类型新增"产品持仓"section,显示各产品当前持有份数
- [ ] **Step 4: 替换弹窗**
移除旧的"发起财务确认"弹窗和"申请退款"弹窗,新增:
- **发起充值弹窗**:金额输入、备注、凭证上传
- **申请退款弹窗**:金额输入(max=当前余额)、备注、凭证上传
- **购买产品弹窗**:选项目/规格、输入份数、自动算金额(类似现有的新增订单弹窗中产品明细部分)
- **退订产品弹窗**:选已持有项目(下拉,显示当前份数)、输入退订份数(≤持有量)、自动算退款金额
- [ ] **Step 5: 操作按钮点击后,可选择是否立即发起财务确认**
创建流水后,弹出提示"是否立即发起财务确认?",用户点确认则调用 `fetchSubmitTxnFinance`。
---
## Task 7: 前端财务确认页改造
**Files:**
- Modify: `web-admin/src/views/pilot-service/channel-service-order-finance/index.vue`
- [ ] **Step 1: 改为查流水表**
将 `fetchChannelServiceOrderList` 替换为 `fetchServiceOrderTxnList`,参数传递 `txnStatus=dqr`(待处理)或 `txnStatus=yqr`(已处理)。
- [ ] **Step 2: 表格列调整**
列表表格列改为:
- 序号、渠道名称、订单类型Tag、流水类型Tag(充值/退款/购买/退订)、金额、状态Tag、提交人、提交时间、操作
流水类型标签映射:
```typescript
const txnTypeLabel = (t: string) => {
const map: Record<string, string> = { recharge: '充值', refund: '退款', purchase: '购买产品', unsubscribe: '退订产品' }
return map[t] || t
}
```
- [ ] **Step 3: Tab 切换调整**
已有两 tab(待处理/已处理),改为:
- 待处理:`txnStatus=dqr`
- 已处理:`txnStatus=yqr`
- [ ] **Step 4: 确认弹窗改造**
"确认收款"弹窗和"确认退款"弹窗合并为一个"确认操作"弹窗:
- 上半部分展示流水详情(渠道、金额/产品明细、提交人/时间/备注/凭证)
- 下半部分输入财务确认备注 + 上传确认凭证
- 调用 `fetchConfirmTxn(txnId, data)`
- [ ] **Step 5: 详情弹窗**
保留 SystemViewDialog 查看详情,展示流水完整信息。
---
## Task 8: 状态标签注册更新
**Files:**
- Modify: `web-admin/src/utils/status-tag-registry.ts`
- [ ] **Step 1: 新增流水类型标签**
在 `status-tag-registry.ts` 中新增:
```typescript
// 流水类型
export const txnTypeLabel = (type: string): string => {
const map: Record<string, string> = {
recharge: '充值',
refund: '退款',
purchase: '购买产品',
unsubscribe: '退订产品',
}
return map[type] || type
}
export const txnTypeTagType = (type: string): string => {
const map: Record<string, string> = {
recharge: '',
refund: 'danger',
purchase: 'success',
unsubscribe: 'warning',
}
return map[type] || 'info'
}
// 流水状态
export const txnStatusLabel = (status: string): string => {
const map: Record<string, string> = {
dsx: '待生效',
dqr: '待财务确认',
yqr: '已确认',
yzf: '已作废',
}
return map[status] || status
}
export const txnStatusTagType = (status: string): string => {
const map: Record<string, string> = {
dsx: 'info',
dqr: 'warning',
yqr: 'success',
yzf: 'danger',
}
return map[status] || 'info'
}
```
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,491 @@
# 渠道服务购买订单 — 功能设计文档
> 日期:2026-05-24
> 状态:待审阅
> 模块:中试服务管理
> 参考页面:`system/order/index.vue`(复杂列表)、`cell-storage/payment-confirm/index.vue`(财务确认)
---
## 1. 业务背景
渠道商(如医院、合作机构)通过签订渠道协议,以协议价格购买细胞产品服务。渠道服务购买订单支持两种模式:
1. **充值(预付款)**:渠道向账户充值金额,财务确认后余额增加。后续可用于购买产品。
2. **购买产品**:根据渠道协议价格购买细胞产品,直接从渠道账户余额扣减,同时增加产品份数库存。
后续中试服务单会从渠道产品份数库存中扣减。
---
## 2. 业务流程
### 2.1 充值订单 (order_type = yfk)
```
创建充值(待确认 dqr) → 财务确认(已确认 yqr, 余额+) → 发起退费(退费确认中 tfqrz) → 财务确认退费(已退费 ytf, 余额-)
```
| 状态 | 编码 | 操作角色 | 余额影响 |
|------|------|----------|----------|
| 待确认 | `dqr` | 采集人员创建 | 无 |
| 已确认 | `yqr` | 财务确认 | +prepay_amount |
| 退费确认中 | `tfqrz` | 采集人员发起退费 | 无 |
| 已退费 | `ytf` | 财务确认退费 | -refund_amount |
### 2.2 购买产品订单 (order_type = gmcp)
```
创建购买(生效中 sxz, 余额-, 份数+) → 作废(已作废 yzf, 余额+, 份数-)
```
| 状态 | 编码 | 操作角色 | 余额影响 | 份数影响 |
|------|------|----------|----------|----------|
| 生效中 | `sxz` | 采集人员创建时直接扣减 | -purchase_total_amount | +各产品 buy_qty |
| 已作废 | `yzf` | 采集人员/审核人员作废 | +purchase_total_amount | -各产品 buy_qty |
---
## 3. 数据库设计
### 3.1 现有表扩展 — `biz_channel_service_order`
现有 DDL(`docs/sql/zkxw.sql` 行 827-847)基础上新增以下字段:
```sql
ALTER TABLE biz_channel_service_order
ADD COLUMN channel_agreement_id VARCHAR(64) DEFAULT NULL COMMENT '渠道协议ID(购买订单必填,关联 biz_channel_agreement.id)',
ADD COLUMN balance_before DECIMAL(18,2) DEFAULT NULL COMMENT '操作前余额快照',
ADD COLUMN balance_after DECIMAL(18,2) DEFAULT NULL COMMENT '操作后余额快照',
ADD COLUMN finance_confirm_time DATETIME DEFAULT NULL COMMENT '财务确认时间',
ADD COLUMN finance_confirm_attachments VARCHAR(4000) DEFAULT NULL COMMENT '财务确认附件(逗号分隔URL)',
ADD COLUMN finance_remark VARCHAR(512) DEFAULT NULL COMMENT '财务确认备注',
ADD COLUMN refund_apply_by VARCHAR(64) DEFAULT NULL COMMENT '退费申请人ID',
ADD COLUMN refund_apply_time DATETIME DEFAULT NULL COMMENT '退费申请时间',
ADD COLUMN refund_amount DECIMAL(18,2) DEFAULT NULL COMMENT '退费金额',
ADD COLUMN refund_remark VARCHAR(512) DEFAULT NULL COMMENT '退费备注',
ADD COLUMN refund_attachments VARCHAR(4000) DEFAULT NULL COMMENT '退费附件(逗号分隔URL)',
ADD COLUMN refund_finance_confirm_time DATETIME DEFAULT NULL COMMENT '退费财务确认时间',
ADD COLUMN refund_finance_confirm_attachments VARCHAR(4000) DEFAULT NULL COMMENT '退费财务确认附件(逗号分隔URL)',
ADD COLUMN refund_finance_remark VARCHAR(512) DEFAULT NULL COMMENT '退费财务确认备注';
```
**设计决策:** 财务确认字段直接放主表(1:1 关系),不再使用现有空表 `biz_channel_service_order_finance_confirm`。余额变动历史通过 `balance_before / balance_after` 可追溯。
**完整字段清单(含原有 + 新增):**
| 字段 | 类型 | 说明 | 充值 | 购买 |
|------|------|------|------|------|
| id | VARCHAR(64) PK | 主键UUID | ✅ | ✅ |
| channel_id | VARCHAR(64) NOT NULL | 渠道ID | ✅ | ✅ |
| channel_name | VARCHAR(200) | 渠道名称冗余 | ✅ | ✅ |
| dept_name | VARCHAR(200) | 科室/部门 | ✅ | ✅ |
| order_type | VARCHAR(16) NOT NULL | yfk预付款 / gmcp购买产品 | ✅ | ✅ |
| prepay_amount | DECIMAL(18,2) | 预付金额 | ✅ | — |
| purchase_total_amount | DECIMAL(18,2) | 购买总金额 | — | ✅ |
| order_status | VARCHAR(16) NOT NULL DEFAULT 'sxz' | 订单状态 | dqr/yqr/tfqrz/ytf | sxz/yzf |
| channel_agreement_id | VARCHAR(64) | 渠道协议ID | — | ✅ 必填 |
| balance_before | DECIMAL(18,2) | 操作前余额 | 财务确认时填 | 创建时填 |
| balance_after | DECIMAL(18,2) | 操作后余额 | 财务确认时填 | 创建时填 |
| finance_confirm_time | DATETIME | 财务确认时间 | ✅ | — |
| finance_confirm_attachments | VARCHAR(4000) | 财务确认附件 | ✅ | — |
| finance_remark | VARCHAR(512) | 财务确认备注 | ✅ | — |
| refund_apply_by | VARCHAR(64) | 退费申请人 | ✅ | — |
| refund_apply_time | DATETIME | 退费申请时间 | ✅ | — |
| refund_amount | DECIMAL(18,2) | 退费金额 | ✅ | — |
| refund_remark | VARCHAR(512) | 退费备注 | ✅ | — |
| refund_attachments | VARCHAR(4000) | 退费附件 | ✅ | — |
| refund_finance_confirm_time | DATETIME | 退费确认时间 | ✅ | — |
| refund_finance_confirm_attachments | VARCHAR(4000) | 退费确认附件 | ✅ | — |
| refund_finance_remark | VARCHAR(512) | 退费确认备注 | ✅ | — |
### 3.2 现有表保持 — `biz_channel_service_order_product`
现有 DDL(行 888-909)无需改动。字段:`service_order_id`, `project_code`, `project_name`, `cell_type`, `spec_text`, `agreement_unit_price`, `buy_qty`, `buy_amount`。
### 3.3 新增表 — `biz_channel_account`(渠道账户余额)
```sql
CREATE TABLE biz_channel_account (
id VARCHAR(64) NOT NULL COMMENT '主键ID',
channel_id VARCHAR(64) NOT NULL COMMENT '渠道ID',
balance_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '当前余额(元)',
tenant_no VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
order_num INT DEFAULT NULL COMMENT '排序号',
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
create_dept_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
del_flag TINYINT(4) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (id),
UNIQUE KEY uk_account_channel (channel_id, del_flag),
KEY idx_ca_tenant (tenant_no, del_flag)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='渠道账户余额';
```
**业务规则:**
- 一个渠道一条记录(UNIQUE KEY)
- `balance_amount` 实时更新,不可为负
- 余额变动历史通过 `biz_channel_service_order.balance_before / balance_after` 追溯
- 首次充值/购买时自动创建账户记录
### 3.4 新增表 — `biz_channel_product_quota`(渠道产品份数库存)
```sql
CREATE TABLE biz_channel_product_quota (
id VARCHAR(64) NOT NULL COMMENT '主键ID',
channel_id VARCHAR(64) NOT NULL COMMENT '渠道ID',
project_code VARCHAR(64) DEFAULT NULL COMMENT '项目编码',
project_name VARCHAR(200) DEFAULT NULL COMMENT '项目名称',
cell_type_code VARCHAR(64) DEFAULT NULL COMMENT '细胞类型编码',
cell_type_name VARCHAR(200) DEFAULT NULL COMMENT '细胞类型名称',
spec_text VARCHAR(200) DEFAULT NULL COMMENT '规格',
total_qty DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '总购买份数',
used_qty DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '已使用份数(中试服务扣减)',
remaining_qty DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '剩余份数 = total_qty - used_qty',
tenant_no VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
order_num INT DEFAULT NULL COMMENT '排序号',
remark VARCHAR(512) DEFAULT NULL COMMENT '备注',
create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
create_dept_id VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
del_flag TINYINT(4) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (id),
UNIQUE KEY uk_quota_channel_product (channel_id, project_code, cell_type_code, spec_text, del_flag),
KEY idx_cpq_tenant (tenant_no, del_flag)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='渠道产品份数库存';
```
**业务规则:**
- 同一渠道同一产品规格只有一条库存记录(UNIQUE KEY)
- 购买订单创建时:`total_qty += buy_qty`, `remaining_qty += buy_qty`
- 购买订单作废时:`total_qty -= buy_qty`, `remaining_qty -= buy_qty`(需校验 remaining_qty >= buy_qty,防止已使用部分被退回)
- 后续中试服务单扣减时:`used_qty += qty`, `remaining_qty -= qty`(本次不实现,但预留字段)
### 3.5 现有空表 — `biz_channel_service_order_finance_confirm`
保留不删(当前无数据)。本次不使用,财务确认字段已放入主表。
### 3.6 表关系图
```
biz_channel (渠道)
├── biz_channel_agreement (协议)
│ └── biz_channel_agreement_product_price (协议产品价格)
├── biz_channel_account (账户余额) [NEW]
├── biz_channel_product_quota (产品份数库存) [NEW]
└── biz_channel_service_order (服务购买订单) [EXTEND]
├── biz_channel_service_order_product (产品明细)
└── (finance_confirm 字段已在主表)
```
---
## 4. 后端设计
### 4.1 SQLAlchemy 模型
在 `backend/app/models/models.py` 中新增:
1. **`BizChannelAccount`** — 对应 `biz_channel_account` 表
2. **`BizChannelProductQuota`** — 对应 `biz_channel_product_quota` 表
3. **`BizChannelServiceOrder`** — 扩展现有模型(如果已有则更新字段),对应 `biz_channel_service_order` + 新增字段
4. **`BizChannelServiceOrderProduct`** — 对应 `biz_channel_service_order_product`(如果已有则保持)
### 4.2 API 端点
在 `backend/app/api/pilot_service.py` 中扩展。前缀 `/web/admin/`。
#### 4.2.1 订单 CRUD
| 方法 | URL | 说明 | 权限 |
|------|-----|------|------|
| GET | `/channel-service-orders` | 订单列表(支持 order_type, order_status, channel_id, keyword 筛选) | 中试服务 |
| GET | `/channel-service-orders/{id}` | 订单详情(含产品明细列表) | 中试服务 |
| POST | `/channel-service-orders` | 创建订单 | 中试服务 |
| PUT | `/channel-service-orders/{id}` | 修改订单(仅 dqr/sxz 状态可改) | 中试服务 |
| DELETE | `/channel-service-orders/{id}` | 删除订单(仅 dqr 状态可删,软删除) | 中试服务 |
#### 4.2.2 状态流转操作
| 方法 | URL | 前置状态 | 目标状态 | 说明 | 操作角色 |
|------|-----|----------|----------|------|----------|
| POST | `/channel-service-orders/{id}/confirm-receipt` | dqr | yqr | 财务确认充值(余额+) | 财务 |
| POST | `/channel-service-orders/{id}/submit-refund` | yqr | tfqrz | 发起退费申请 | 中试服务 |
| POST | `/channel-service-orders/{id}/confirm-refund` | tfqrz | ytf | 财务确认退费(余额-) | 财务 |
| PUT | `/channel-service-orders/{id}/void` | sxz | yzf | 作废购买订单(余额+, 份数-) | 中试服务 |
#### 4.2.3 渠道账户 & 份数查询
| 方法 | URL | 说明 |
|------|-----|------|
| GET | `/channels/{channelId}/account` | 获取渠道账户余额(不存在则返回 balance=0) |
| GET | `/channels/{channelId}/product-quotas` | 获取渠道产品份数列表 |
### 4.3 CRUD 函数
在 `backend/app/crud/pilot_service.py` 中新增。遵循现有 `_row_to_dict_*` 模式。
**核心函数:**
| 函数名 | 说明 |
|--------|------|
| `_row_to_dict_channel_service_order` | 订单行转字典(单一真相源) |
| `list_channel_service_orders` | 列表查询(带筛选、分页、数据权限) |
| `get_channel_service_order` | 获取单条(含产品明细) |
| `create_channel_service_order` | 创建订单(充值直接创建;购买需扣余额+增份数) |
| `update_channel_service_order` | 修改订单(校验状态、业务字段) |
| `soft_delete_channel_service_order` | 软删除(仅 dqr 状态) |
| `confirm_receipt` | 财务确认充值(dqr→yqr,余额+) |
| `submit_refund` | 发起退费(yqr→tfqrz,记录退费信息) |
| `confirm_refund` | 财务确认退费(tfqrz→ytf,余额-) |
| `void_order` | 作废购买订单(sxz→yzf,余额+,份数-) |
| `_get_or_create_channel_account` | 获取或创建渠道账户 |
| `_upsert_channel_product_quota` | 新增或更新渠道产品份数 |
| `_reduce_channel_product_quota` | 扣减渠道产品份数(作废时用) |
### 4.4 核心业务逻辑
#### 创建充值订单
```
1. 校验 channel_id 存在
2. 校验 prepay_amount > 0
3. 创建订单 (order_type=yfk, order_status=dqr)
4. 不动余额
```
#### 创建购买订单
```
1. 校验 channel_id 存在
2. 校验 channel_agreement_id 存在且 agreement_status='sxz'
3. 从 biz_channel_agreement_product_price 加载协议价格
4. 校验所有产品明细的项目编码+细胞类型+规格在协议价格表中存在
5. 允许用户修改单价(agreement_unit_price 可与协议价不同)
6. 计算总金额 = sum(buy_qty * agreement_unit_price)
7. 获取渠道账户,校验 balance_amount >= purchase_total_amount
8. 扣减余额 (account.balance_amount -= total)
9. 记录 balance_before / balance_after
10. 创建订单 (order_type=gmcp, order_status=sxz) + 产品明细
11. 对每个产品明细,upsert biz_channel_product_quota (total_qty+=, remaining_qty+=)
```
#### 财务确认充值
```
1. 校验 order_status == 'dqr'
2. 获取/创建渠道账户
3. account.balance_amount += prepay_amount
4. 记录 balance_before, balance_after, finance_confirm_time, finance_confirm_attachments, finance_remark
5. order_status = 'yqr'
```
#### 发起退费
```
1. 校验 order_status == 'yqr'
2. 记录 refund_apply_by, refund_apply_time, refund_amount(=prepay_amount), refund_remark, refund_attachments
3. order_status = 'tfqrz'
```
#### 财务确认退费
```
1. 校验 order_status == 'tfqrz'
2. account.balance_amount -= refund_amount
3. 记录 balance_before, balance_after, refund_finance_confirm_time, refund_finance_confirm_attachments, refund_finance_remark
4. order_status = 'ytf'
```
#### 作废购买订单
```
1. 校验 order_status == 'sxz'
2. 查询产品明细列表
3. 对每个产品明细:
a. 校验 remaining_qty >= buy_qty(防止已使用部分被退回)
b. 如果 remaining_qty < buy_qty → 返回错误("产品 XXX 已使用 N 份,无法作废")
4. account.balance_amount += purchase_total_amount
5. 记录 balance_before, balance_after
6. 对每个产品明细:total_qty -= buy_qty, remaining_qty -= buy_qty
7. order_status = 'yzf'
```
---
## 5. 前端设计
### 5.1 菜单配置
在系统菜单管理中新增(中试服务管理 下):
| 菜单名称 | 路由路径 | 组件 | 说明 |
|----------|----------|------|------|
| 渠道服务购买订单 | `/pilot-service/channel-service-order` | `pilot-service/channel-service-order/index.vue` | 订单管理 |
| 渠道服务购买订单(财务确认) | `/pilot-service/channel-service-order-finance` | `pilot-service/channel-service-order-finance/index.vue` | 财务确认 |
### 5.2 订单管理页
**参考页面:** `system/order/index.vue`(复杂列表)
**搜索条件:**
- 订单类型(下拉:充值/购买产品)
- 订单状态(下拉:根据类型动态切换选项)
- 渠道名称(模糊搜索)
- 创建时间范围
**列表列:**
| 列 | 字段 | 宽度 | 说明 |
|----|------|------|------|
| 订单编号 | id 后 6 位 | min-width 120 | |
| 渠道名称 | channelName | min-width 160 | |
| 订单类型 | orderType | min-width 100 | Tag: yfk=充值(info), gmcp=购买产品(primary) |
| 订单金额 | prepayAmount / purchaseTotalAmount | min-width 120 | 根据 orderType 展示对应字段 |
| 订单状态 | orderStatus | min-width 100 | Tag,颜色见 5.5 |
| 操作前余额 | balanceBefore | min-width 120 | |
| 操作后余额 | balanceAfter | min-width 120 | |
| 创建时间 | createTime | min-width 160 | |
| 操作 | — | min-width 260, fixed="right" | 按状态显示按钮 |
**操作按钮规则:**
| 状态 | 可用操作 |
|------|----------|
| dqr(待确认) | 编辑、删除 |
| yqr(已确认) | 发起退费、查看 |
| tfqrz(退费确认中) | 查看 |
| ytf(已退费) | 查看 |
| sxz(生效中) | 查看、作废 |
| yzf(已作废) | 查看 |
**新增/编辑弹窗:**
- 选择渠道(下拉搜索,`fetchChannelList`)
- 订单类型(充值/购买产品,单选,新建后不可修改)
- **充值模式字段:** 预付金额(number input, > 0)
- **购买模式字段:**
- 选择渠道协议(下拉,仅显示该渠道 `agreement_status='sxz'` 的协议)
- 产品明细表格(动态行):
- 「添加产品」按钮 → 弹窗选择协议产品价格 → 填入行
- 每行:项目名称(只读)、细胞类型(只读)、规格(只读)、协议单价(可修改)、购买数量(必填)、购买金额(自动计算 = 单价 × 数量)
- 可删除行
- 底部汇总:合计金额 + 当前渠道余额(余额不足时红色提示)
- 备注(textarea)
**查看弹窗:**
- 展示订单基础信息 + 产品明细(只读表格)
- 充值订单:展示财务确认信息(确认时间、附件、备注)、退费信息(如有)
- 购买订单:展示余额变动信息
**作废确认弹窗:**
- 展示订单信息和产品明细
- 填写作废原因(textarea)
- 确认作废
**发起退费弹窗:**
- 展示充值金额
- 退费金额(默认=充值金额,可修改但不能超过充值金额)
- 退费备注(textarea)
- 退费附件(上传)
- 确认提交
### 5.3 财务确认页
**参考页面:** `cell-storage/payment-confirm/index.vue`
**Tab 1:待确认**
- 列表显示所有 `order_status IN ('dqr', 'tfqrz')` 的订单
- 操作:
- dqr 订单 → 「确认收款」按钮 → 弹窗(只读订单信息 + 财务备注 textarea + 附件上传)
- tfqrz 订单 → 「确认退费」按钮 → 弹窗(只读订单信息+退费信息 + 退费确认备注 + 退费确认附件)
**Tab 2:已确认**
- 列表显示所有 `order_status IN ('yqr', 'ytf')` 的订单
- 「查看详情」按钮 → 查看确认信息
### 5.4 渠道信息页扩展
在 `pilot-service/channel/index.vue` 的编辑弹窗或查看弹窗中新增「账户信息」Tab:
- 展示当前余额
- 展示产品份数库存列表(表格:项目名称、细胞类型、规格、总份数、已使用、剩余份数)
### 5.5 状态标签注册
在 `web-admin/src/utils/status-tag-registry.ts` 中新增:
```typescript
serviceOrderType: {
yfk: { label: '充值', tagType: 'info' },
gmcp: { label: '购买产品', tagType: 'primary' },
},
serviceOrderStatus: {
dqr: { label: '待确认', tagType: 'info' },
yqr: { label: '已确认', tagType: 'success' },
tfqrz: { label: '退费确认中', tagType: 'warning' },
ytf: { label: '已退费', tagType: 'danger' },
sxz: { label: '生效中', tagType: 'success' },
yzf: { label: '已作废', tagType: 'danger' },
},
```
### 5.6 前端 API 封装
在 `web-admin/src/api/admin.ts` 中新增:
```typescript
// 渠道服务购买订单
fetchChannelServiceOrderList(params) // GET /channel-service-orders
fetchChannelServiceOrderDetail(id) // GET /channel-service-orders/{id}
fetchCreateChannelServiceOrder(data) // POST /channel-service-orders
fetchUpdateChannelServiceOrder(id, data) // PUT /channel-service-orders/{id}
fetchDeleteChannelServiceOrder(id) // DELETE /channel-service-orders/{id}
// 状态流转
fetchConfirmReceipt(id, data) // POST /channel-service-orders/{id}/confirm-receipt
fetchSubmitRefund(id, data) // POST /channel-service-orders/{id}/submit-refund
fetchConfirmRefund(id, data) // POST /channel-service-orders/{id}/confirm-refund
fetchVoidChannelServiceOrder(id, data) // PUT /channel-service-orders/{id}/void
// 渠道账户 & 份数
fetchChannelAccount(channelId) // GET /channels/{channelId}/account
fetchChannelProductQuotas(channelId) // GET /channels/{channelId}/product-quotas
```
---
## 6. 开发范围边界
### 本次实现 ✅
1. 数据库:2 张新表 + 1 张表扩展字段
2. 后端:4 个新 SQLAlchemy 模型 + CRUD 函数 + API 端点
3. 前端:2 个新页面(订单管理 + 财务确认)+ 渠道信息页扩展(账户 Tab)
4. 状态标签注册
5. 菜单数据初始化 SQL
### 后续实现 ❌(不在本次范围)
1. 中试服务单(biz_channel_pilot_service)的创建和产品份数扣减
2. 中试服务单与渠道购买订单的关联
3. 渠道账户对账报表
4. 渠道协议授信额度校验(可后续增强)
---
## 7. 注意事项
1. **并发安全:** 余额扣减和份数更新需使用数据库行锁(`SELECT ... FOR UPDATE`)或乐观锁,防止并发创建订单导致余额超扣。
2. **作废校验:** 购买订单作废时,需校验产品份数的 `remaining_qty >= buy_qty`。如果部分份数已被中试服务消耗(后续功能),则不允许作废或只能部分退回。
3. **数据权限:** 所有查询需应用 `apply_data_scope()` 数据范围过滤。
4. **租户隔离:** 所有操作带 `tenant_no` 过滤。
5. **操作日志:** 建议参考采集协议单的模式,记录订单状态变更日志(可选,后续增强)。
6. **前端参考页面:** 新页面严格遵循 `docs/web-admin-ui-spec-fresh-mint.md` 的 Fresh Mint 色彩规范。
7. **order_status 默认值:** 现有 DDL 中 `order_status DEFAULT 'sxz'`,但充值订单初始状态为 `dqr`。后端 create 函数必须根据 `order_type` 显式设置 order_status,不依赖 DDL 默认值:`order_type='yfk' → order_status='dqr'`,`order_type='gmcp' → order_status='sxz'`。
8. **cell_type 字段映射:** `biz_channel_service_order_product.cell_type` 存储细胞类型名称(冗余文本),但 `biz_channel_product_quota` 使用 `cell_type_code` + `cell_type_name` 分开存储。创建份数库存时,`cell_type_code` 和 `cell_type_name` 从 `biz_channel_agreement_product_price` 协议产品价格表获取,不从订单明细的 `cell_type` 取值。
9. **并发方案确定:** 余额扣减使用 `SELECT ... FOR UPDATE` 悲观行锁。在创建购买订单和财务确认充值时,先锁定 `biz_channel_account` 行再更新余额,防止并发超扣。整个余额操作在一个数据库事务内完成。
@@ -0,0 +1,256 @@
# 渠道服务订单 — 多次操作流水模型设计
## 背景
现有渠道服务订单(`biz_channel_service_order`)为单次操作模型:一个订单 = 一次充值或一次购买,退款只能做一次。业务要求每个订单支持多次充值、多次退款、多次购买产品、按份数退订产品,且所有涉及金额的操作都需走财务确认流程。
## 业务模型
```
渠道服务订单(运营手动创建,选渠道+协议,选类型 yfk/gmcp)
├── 充值型(yfk):独立充钱、独立退钱,走渠道账户余额
│ ├── 多次充值 → 每次独立金额 + 财务确认 → 余额增加
│ └── 多次退款 → 每次独立金额 + 财务确认 → 余额减少
│
└── 购买型(gmcp):独立买产品、独立退订,与余额无关
├── 多次购买 → 每次独立购买产品(份数) + 财务确认 → 持仓增加
└── 多次退订 → 按份数退订 + 财务确认 → 持仓减少
```
两种类型完全独立。充值管渠道余额,购买管产品份数。
## 方案:操作流水子表
核心思路:订单主表管汇总,新增操作流水表管明细,产品表管持仓。
---
## 1. 数据模型
### 1.1 订单主表 `biz_channel_service_order`(改造)
**保留字段:**
- `id`, `channel_id`, `channel_name`, `dept_name`, `order_type`(yfk/gmcp), `order_status`(dsx/sxz/yzf), `channel_agreement_id`
- 公共字段:`tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
**移除字段(迁移到流水表):**
- `prepay_amount`, `purchase_total_amount`
- `finance_submit_by`, `finance_submit_time`, `finance_submit_remark`, `finance_submit_attachments`
- `finance_confirm_time`, `finance_confirm_attachments`, `finance_remark`
- `refund_apply_by`, `refund_apply_time`, `refund_amount`, `refund_remark`, `refund_attachments`
- `refund_finance_confirm_time`, `refund_finance_confirm_attachments`, `refund_finance_remark`
- `balance_before`, `balance_after`
**新增汇总字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| `total_recharge_amount` | decimal(18,2) DEFAULT 0 | 累计充值总额(yfk) |
| `total_refund_amount` | decimal(18,2) DEFAULT 0 | 累计退款总额(yfk) |
| `current_balance` | decimal(18,2) DEFAULT 0 | 当前余额(yfk),= 累计充值 - 累计退款 |
### 1.2 操作流水表 `biz_channel_service_order_txn`(新增)
```sql
CREATE TABLE `biz_channel_service_order_txn` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`service_order_id` varchar(64) NOT NULL COMMENT '关联订单ID',
`txn_type` varchar(16) NOT NULL COMMENT 'recharge/refund/purchase/unsubscribe',
`amount` decimal(18,2) DEFAULT NULL COMMENT '本次操作金额',
`txn_status` varchar(16) NOT NULL DEFAULT 'dsx' COMMENT 'dsx待生效 dqr待财务确认 yqr已确认 yzf已作废',
`products_json` text COMMENT '产品明细JSON(purchase/unsubscribe类型)',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
-- 发起财务确认
`finance_submit_by` varchar(64) DEFAULT NULL COMMENT '发起确认人ID',
`finance_submit_time` datetime DEFAULT NULL COMMENT '发起确认时间',
`finance_submit_remark` varchar(512) DEFAULT NULL COMMENT '发起确认备注',
`finance_submit_attachments` text COMMENT '发起确认附件',
-- 财务确认
`finance_confirm_time` datetime DEFAULT NULL COMMENT '财务确认时间',
`finance_confirm_attachments` text COMMENT '财务确认附件',
`finance_remark` varchar(512) DEFAULT NULL COMMENT '财务确认备注',
-- 余额快照(仅 yfk 类型)
`balance_before` decimal(18,2) DEFAULT NULL COMMENT '操作前余额',
`balance_after` decimal(18,2) DEFAULT NULL COMMENT '操作后余额',
-- 公共字段
`tenant_no` varchar(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_txn_order` (`service_order_id`, `del_flag`),
KEY `idx_txn_status` (`txn_status`, `tenant_no`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='渠道服务订单操作流水';
```
### 1.3 产品持仓表 `biz_channel_service_order_product`(改造)
在现有字段基础上新增:
| 字段 | 类型 | 说明 |
|------|------|------|
| `total_buy_qty` | decimal(18,4) DEFAULT 0 | 累计购买数量 |
| `total_unsubscribe_qty` | decimal(18,4) DEFAULT 0 | 累计退订数量 |
| `current_qty` | decimal(18,4) DEFAULT 0 | 当前持有数量 |
| `total_unsubscribe_amount` | decimal(18,2) DEFAULT 0 | 累计退订金额 |
保留现有字段:`agreement_unit_price`, `buy_qty`(首次购买), `buy_amount`。
### 1.4 关系图
```
biz_channel_service_order(订单主表)
│
├── biz_channel_service_order_txn(操作流水)× N
│ 每条流水 = 一次充值/退款/购买/退订
│ 每条流水独立走财务确认流程
│
└── biz_channel_service_order_product(产品持仓)× N
购买时增加 current_qty,退订时减少
```
### 1.5 废弃表
`biz_channel_service_order_finance_confirm` — 已有但未使用,保留不删,不再使用。
---
## 2. 状态机
### 2.1 订单主表状态
| 状态 | 含义 | 说明 |
|------|------|------|
| `dsx` | 待生效 | 刚创建,尚无已确认的流水 |
| `sxz` | 生效中 | 至少有一笔流水已确认 |
| `yzf` | 已作废 | 手动作废,不再允许新操作 |
### 2.2 流水状态
| 状态 | 含义 | 可转至 |
|------|------|--------|
| `dsx` | 待生效 | `dqr`(发起确认)、`yzf`(作废) |
| `dqr` | 待财务确认 | `yqr`(财务确认) |
| `yqr` | 已确认(终态) | — |
| `yzf` | 已作废(终态) | — |
### 2.3 操作流转
**充值型(yfk):**
```
创建订单 → [dsx]
├─ 发起充值 → txn(recharge, dsx)
│ └─ 发起确认 → txn(dqr) → 财务确认 → txn(yqr)
│ └─ order.total_recharge_amount += amount
│ order.current_balance += amount
│ order.status → sxz (首次确认时)
│
└─ 申请退款 → txn(refund, dsx), amount ≤ current_balance
└─ 发起确认 → txn(dqr) → 财务确认 → txn(yqr)
└─ order.total_refund_amount += amount
order.current_balance -= amount
```
**购买型(gmcp):**
```
创建订单 → [dsx]
├─ 购买产品 → txn(purchase, dsx) + 创建/更新 product 持仓
│ └─ 发起确认 → txn(dqr) → 财务确认 → txn(yqr)
│ └─ product.total_buy_qty += qty
│ product.current_qty += qty
│ order.status → sxz (首次确认时)
│
└─ 退订产品 → txn(unsubscribe, dsx), qty ≤ product.current_qty
└─ 发起确认 → txn(dqr) → 财务确认 → txn(yqr)
└─ product.total_unsubscribe_qty += qty
product.current_qty -= qty
product.total_unsubscribe_amount += qty × unit_price
```
---
## 3. API 设计
### 3.1 订单管理(`/api/admin/channel-service-orders`)
| 接口 | 方法 | 说明 | 变更 |
|------|------|------|------|
| `/` | GET | 订单列表 | 不变 |
| `/{order_id}` | GET | 订单详情 + 流水列表 + 产品持仓 | **扩展返回** |
| `/` | POST | 创建订单 | 不变 |
| `/{order_id}` | PUT | 编辑订单基本信息 | 不变 |
| `/{order_id}` | DELETE | 删除 dsx 状态订单 | 不变 |
| `/{order_id}/void` | PUT | 作废订单 | 不变 |
| `/{order_id}/recharge` | POST | **新增** 发起充值流水 | 新增 |
| `/{order_id}/refund` | POST | **新增** 申请退款流水 | 替代原退款 |
| `/{order_id}/purchase` | POST | **新增** 购买产品流水 | 新增 |
| `/{order_id}/unsubscribe` | POST | **新增** 退订产品流水 | 新增 |
### 3.2 流水操作
| 接口 | 方法 | 说明 |
|------|------|------|
| `/channel-service-order-txns/{txn_id}/submit-finance` | POST | 发起财务确认 |
| `/channel-service-order-txns/{txn_id}/confirm` | POST | 财务确认(收款/退付) |
| `/channel-service-order-txns/{txn_id}/void` | PUT | 作废流水 |
### 3.3 财务确认页
| 接口 | 方法 | 说明 | 变更 |
|------|------|------|------|
| `/channel-service-order-txns` | GET | 查流水列表(按 status 筛选) | **改为查流水表** |
| `/channel-service-order-txns/{txn_id}` | GET | 流水详情 | 新增 |
| 确认 | POST | 复用 3.2 的 confirm 接口 | — |
---
## 4. 前端改造
### 4.1 订单管理页(`channel-service-order/index.vue`)
**操作按钮:**
| 条件 | 按钮 |
|------|------|
| yfk + dsx | 编辑、删除、发起充值 |
| yfk + sxz | 发起充值、申请退款 |
| gmcp + dsx | 编辑、删除、购买产品 |
| gmcp + sxz | 购买产品、退订产品 |
| 任意 + yzf | 仅查看 |
**详情弹窗改造:**
- Section 1:基本信息(含余额/汇总金额)
- Section 2:操作记录(流水时间线列表)
- Section 3:产品持仓(gmcp 类型,显示当前持有份数)
**新增弹窗:**
- 发起充值:金额、备注、凭证上传
- 申请退款:金额(≤余额)、备注、凭证上传
- 购买产品:选项目/规格、输入份数、自动算金额
- 退订产品:选已持有项目、输入退订份数(≤持有量)
### 4.2 财务确认页(`channel-service-order-finance/index.vue`)
**改为以流水为维度展示:**
**待处理 Tab(status=dqr):**
- 显示:流水类型标签、渠道名称、金额、产品明细、提交人/时间
- 操作:查看详情、确认收款/退付
**已处理 Tab(status=yqr):**
- 显示同上,操作仅查看
**确认弹窗:**
- 上半部分展示流水详情(发起确认信息)
- 下半部分输入财务确认备注+凭证
### 4.3 废弃功能
- 移除原订单级别的「发起财务确认」「申请退款」按钮和弹窗(改为流水级别操作)
- 移除订单主表上平铺的 finance/refund 字段展示
File diff suppressed because it is too large. Load diff
+358 -32
View File
@@ -728,6 +728,27 @@
"source_file": "utils/mask-sensitive.ts",
"source_location": "L2"
},
{
"id": "utils_production_labels_ts",
"label": "production-labels.ts",
"file_type": "code",
"source_file": "utils/production-labels.ts",
"source_location": "L1"
},
{
"id": "utils_production_labels_productionconclusionlabel",
"label": "productionConclusionLabel()",
"file_type": "code",
"source_file": "utils/production-labels.ts",
"source_location": "L4"
},
{
"id": "utils_production_labels_productionconclusiontagtype",
"label": "productionConclusionTagType()",
"file_type": "code",
"source_file": "utils/production-labels.ts",
"source_location": "L11"
},
{
"id": "utils_index_ts",
"label": "index.ts",
@@ -3442,7 +3463,7 @@
"label": "productionTaskStatusLabel()",
"file_type": "code",
"source_file": "components/business/sample-production-info-cards/index.vue",
"source_location": "L153"
"source_location": "L172"
},
{
"id": "components_business_sample_storage_release_info_index_vue",
@@ -3498,35 +3519,35 @@
"label": "taskStatusLabel()",
"file_type": "code",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L155"
"source_location": "L159"
},
{
"id": "production_task_view_dialog_index_tasktypelabel",
"label": "taskTypeLabel()",
"file_type": "code",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L166"
"source_location": "L170"
},
{
"id": "production_task_view_dialog_index_productstatustagtype",
"label": "productStatusTagType()",
"file_type": "code",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L176"
"source_location": "L180"
},
{
"id": "production_task_view_dialog_index_productstatuslabel",
"label": "productStatusLabel()",
"file_type": "code",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L186"
"source_location": "L190"
},
{
"id": "production_task_view_dialog_index_formatdateonly",
"label": "formatDateOnly()",
"file_type": "code",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L196"
"source_location": "L200"
},
{
"id": "components_business_order_operate_dialog_bridge_index_vue",
@@ -4422,42 +4443,42 @@
"label": "fetchStorageReleaseReviewList()",
"file_type": "code",
"source_file": "api/storage-release-review.ts",
"source_location": "L118"
"source_location": "L120"
},
{
"id": "api_storage_release_review_fetchstoragereleasereviewdetail",
"label": "fetchStorageReleaseReviewDetail()",
"file_type": "code",
"source_file": "api/storage-release-review.ts",
"source_location": "L132"
"source_location": "L134"
},
{
"id": "api_storage_release_review_submitstoragereleasereview",
"label": "submitStorageReleaseReview()",
"file_type": "code",
"source_file": "api/storage-release-review.ts",
"source_location": "L138"
"source_location": "L140"
},
{
"id": "api_storage_release_review_batchreviewstoragerelease",
"label": "batchReviewStorageRelease()",
"file_type": "code",
"source_file": "api/storage-release-review.ts",
"source_location": "L152"
"source_location": "L154"
},
{
"id": "api_storage_release_review_storesample",
"label": "storeSample()",
"file_type": "code",
"source_file": "api/storage-release-review.ts",
"source_location": "L164"
"source_location": "L166"
},
{
"id": "api_storage_release_review_batchstoresample",
"label": "batchStoreSample()",
"file_type": "code",
"source_file": "api/storage-release-review.ts",
"source_location": "L170"
"source_location": "L172"
},
{
"id": "api_workflow_ts",
@@ -6517,6 +6538,90 @@
"source_file": "api/admin.ts",
"source_location": "L1891"
},
{
"id": "api_admin_fetchchannelserviceorderlist",
"label": "fetchChannelServiceOrderList()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1900"
},
{
"id": "api_admin_fetchchannelserviceorderdetail",
"label": "fetchChannelServiceOrderDetail()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1905"
},
{
"id": "api_admin_fetchcreatechannelserviceorder",
"label": "fetchCreateChannelServiceOrder()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1910"
},
{
"id": "api_admin_fetchupdatechannelserviceorder",
"label": "fetchUpdateChannelServiceOrder()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1915"
},
{
"id": "api_admin_fetchdeletechannelserviceorder",
"label": "fetchDeleteChannelServiceOrder()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1920"
},
{
"id": "api_admin_fetchsubmitserviceorderfinanceconfirm",
"label": "fetchSubmitServiceOrderFinanceConfirm()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1925"
},
{
"id": "api_admin_fetchconfirmserviceorderreceipt",
"label": "fetchConfirmServiceOrderReceipt()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1933"
},
{
"id": "api_admin_fetchsubmitserviceorderrefund",
"label": "fetchSubmitServiceOrderRefund()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1938"
},
{
"id": "api_admin_fetchconfirmserviceorderrefund",
"label": "fetchConfirmServiceOrderRefund()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1943"
},
{
"id": "api_admin_fetchvoidserviceorder",
"label": "fetchVoidServiceOrder()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1948"
},
{
"id": "api_admin_fetchchannelaccount",
"label": "fetchChannelAccount()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1953"
},
{
"id": "api_admin_fetchchannelproductquotas",
"label": "fetchChannelProductQuotas()",
"file_type": "code",
"source_file": "api/admin.ts",
"source_location": "L1958"
},
{
"id": "api_ethnic_ts",
"label": "ethnic.ts",
@@ -9105,14 +9210,14 @@
"label": "handleClose()",
"file_type": "code",
"source_file": "views/production/production-work-order/CompleteProductionTaskDialog.vue",
"source_location": "L66"
"source_location": "L76"
},
{
"id": "production_work_order_completeproductiontaskdialog_handlesubmit",
"label": "handleSubmit()",
"file_type": "code",
"source_file": "views/production/production-work-order/CompleteProductionTaskDialog.vue",
"source_location": "L70"
"source_location": "L80"
},
{
"id": "views_production_production_work_order_taskinputenhancedtable_vue",
@@ -9569,6 +9674,27 @@
"source_file": "views/pilot-service/checkup-institution/CheckupPackagePanel.vue",
"source_location": "L1"
},
{
"id": "views_pilot_service_channel_service_order_index_vue",
"label": "index.vue",
"file_type": "code",
"source_file": "views/pilot-service/channel-service-order/index.vue",
"source_location": "L1"
},
{
"id": "channel_service_order_index_validate",
"label": "validate()",
"file_type": "code",
"source_file": "views/pilot-service/channel-service-order/index.vue",
"source_location": "L1465"
},
{
"id": "channel_service_order_index_if",
"label": "if()",
"file_type": "code",
"source_file": "views/pilot-service/channel-service-order/index.vue",
"source_location": "L1470"
},
{
"id": "views_pilot_service_channel_index_vue",
"label": "index.vue",
@@ -9590,6 +9716,13 @@
"source_file": "views/pilot-service/cell-product-price/index.vue",
"source_location": "L1"
},
{
"id": "views_pilot_service_channel_service_order_finance_index_vue",
"label": "index.vue",
"file_type": "code",
"source_file": "views/pilot-service/channel-service-order-finance/index.vue",
"source_location": "L1"
},
{
"id": "views_pilot_service_project_price_system_index_vue",
"label": "index.vue",
@@ -12381,6 +12514,33 @@
"source_location": "L2",
"weight": 1.0
},
{
"source": "utils_production_labels_ts",
"target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry",
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "utils/production-labels.ts",
"source_location": "L1",
"weight": 1.0
},
{
"source": "utils_production_labels_ts",
"target": "utils_production_labels_productionconclusionlabel",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "utils/production-labels.ts",
"source_location": "L4",
"weight": 1.0
},
{
"source": "utils_production_labels_ts",
"target": "utils_production_labels_productionconclusiontagtype",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "utils/production-labels.ts",
"source_location": "L11",
"weight": 1.0
},
{
"source": "utils_category_path_display_ts",
"target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin",
@@ -17373,7 +17533,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/business/sample-production-info-cards/index.vue",
"source_location": "L153",
"source_location": "L172",
"weight": 1.0
},
{
@@ -17409,7 +17569,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L155",
"source_location": "L159",
"weight": 1.0
},
{
@@ -17418,7 +17578,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L166",
"source_location": "L170",
"weight": 1.0
},
{
@@ -17427,7 +17587,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L176",
"source_location": "L180",
"weight": 1.0
},
{
@@ -17436,7 +17596,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L186",
"source_location": "L190",
"weight": 1.0
},
{
@@ -17445,7 +17605,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/business/production-task-view-dialog/index.vue",
"source_location": "L196",
"source_location": "L200",
"weight": 1.0
},
{
@@ -18966,7 +19126,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/storage-release-review.ts",
"source_location": "L118",
"source_location": "L120",
"weight": 1.0
},
{
@@ -18975,7 +19135,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/storage-release-review.ts",
"source_location": "L132",
"source_location": "L134",
"weight": 1.0
},
{
@@ -18984,7 +19144,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/storage-release-review.ts",
"source_location": "L138",
"source_location": "L140",
"weight": 1.0
},
{
@@ -18993,7 +19153,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/storage-release-review.ts",
"source_location": "L152",
"source_location": "L154",
"weight": 1.0
},
{
@@ -19002,7 +19162,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/storage-release-review.ts",
"source_location": "L164",
"source_location": "L166",
"weight": 1.0
},
{
@@ -19011,7 +19171,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/storage-release-review.ts",
"source_location": "L170",
"source_location": "L172",
"weight": 1.0
},
{
@@ -21687,6 +21847,114 @@
"source_location": "L1891",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchchannelserviceorderlist",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1900",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchchannelserviceorderdetail",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1905",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchcreatechannelserviceorder",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1910",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchupdatechannelserviceorder",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1915",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchdeletechannelserviceorder",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1920",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchsubmitserviceorderfinanceconfirm",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1925",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchconfirmserviceorderreceipt",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1933",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchsubmitserviceorderrefund",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1938",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchconfirmserviceorderrefund",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1943",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchvoidserviceorder",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1948",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchchannelaccount",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1953",
"weight": 1.0
},
{
"source": "api_admin_ts",
"target": "api_admin_fetchchannelproductquotas",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "api/admin.ts",
"source_location": "L1958",
"weight": 1.0
},
{
"source": "api_admin_fetchnotdeletedregions",
"target": "api_admin_fetchregionlist",
@@ -26076,7 +26344,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "views/production/production-work-order/CompleteProductionTaskDialog.vue",
"source_location": "L66",
"source_location": "L76",
"weight": 1.0
},
{
@@ -26085,7 +26353,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "views/production/production-work-order/CompleteProductionTaskDialog.vue",
"source_location": "L70",
"source_location": "L80",
"weight": 1.0
},
{
@@ -26610,6 +26878,24 @@
"source_location": "L334",
"weight": 1.0
},
{
"source": "views_pilot_service_channel_service_order_index_vue",
"target": "channel_service_order_index_validate",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "views/pilot-service/channel-service-order/index.vue",
"source_location": "L1465",
"weight": 1.0
},
{
"source": "views_pilot_service_channel_service_order_index_vue",
"target": "channel_service_order_index_if",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "views/pilot-service/channel-service-order/index.vue",
"source_location": "L1470",
"weight": 1.0
},
{
"source": "views_pilot_service_channel_index_vue",
"target": "element_plus",
@@ -30720,7 +31006,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/storage-release-review.ts",
"source_location": "L126",
"source_location": "L128",
"weight": 1.0
},
{
@@ -30730,7 +31016,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/storage-release-review.ts",
"source_location": "L133",
"source_location": "L135",
"weight": 1.0
},
{
@@ -31683,6 +31969,46 @@
"source_location": "L1888",
"weight": 1.0
},
{
"source": "api_admin_fetchchannelserviceorderlist",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/admin.ts",
"source_location": "L1901",
"weight": 1.0
},
{
"source": "api_admin_fetchchannelserviceorderdetail",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/admin.ts",
"source_location": "L1906",
"weight": 1.0
},
{
"source": "api_admin_fetchchannelaccount",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/admin.ts",
"source_location": "L1954",
"weight": 1.0
},
{
"source": "api_admin_fetchchannelproductquotas",
"target": "process_route_index_get",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "api/admin.ts",
"source_location": "L1959",
"weight": 1.0
},
{
"source": "api_ethnic_fetchethniclist",
"target": "process_route_index_get",
@@ -32880,7 +33206,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "views/production/production-work-order/CompleteProductionTaskDialog.vue",
"source_location": "L72",
"source_location": "L82",
"weight": 1.0
},
{
@@ -32890,7 +33216,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "views/production/production-work-order/CompleteProductionTaskDialog.vue",
"source_location": "L73",
"source_location": "L83",
"weight": 1.0
},
{
+74 -116
View File
@@ -1,11 +1,11 @@
# Graph Report - src (2026-05-24)
## Corpus Check
- Large corpus: 607 files · ~332,821 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
- Large corpus: 610 files · ~341,034 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
## Summary
- 1546 nodes · 1923 edges · 46 communities detected
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 415 edges (avg confidence: 0.8)
- 1565 nodes · 1943 edges · 40 communities detected
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 419 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
@@ -34,30 +34,24 @@
- [[_COMMUNITY_Community 22|Community 22]]
- [[_COMMUNITY_Community 23|Community 23]]
- [[_COMMUNITY_Community 24|Community 24]]
- [[_COMMUNITY_Community 25|Community 25]]
- [[_COMMUNITY_Community 27|Community 27]]
- [[_COMMUNITY_Community 26|Community 26]]
- [[_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 43|Community 43]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 47|Community 47]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 50|Community 50]]
## God Nodes (most connected - your core abstractions)
1. `get()` - 166 edges
1. `get()` - 170 edges
2. `WebSocketClient` - 26 edges
3. `push()` - 20 edges
4. `withFullscreenLoading()` - 17 edges
@@ -84,11 +78,11 @@
### Community 0 - "Community 0"
Cohesion: 0.01
Nodes (84): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAgreementPrices() (+76 more)
Nodes (86): fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList(), fetchChannelAccount() (+78 more)
### Community 1 - "Community 1"
Cohesion: 0.03
Nodes (56): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+48 more)
Nodes (57): fetchBatchGenerateProtocolNos(), fetchBatchGenerateSampleCodes(), fetchBatchIssueProtocolNos(), fetchBatchIssueSampleCodes(), fetchCollectionProtocolNoList(), fetchCreateCollectionProtocolNo(), fetchCreateSampleCode(), fetchDeleteCollectionProtocolNo() (+49 more)
### Community 2 - "Community 2"
Cohesion: 0.03
@@ -103,218 +97,182 @@ Cohesion: 0.03
Nodes (22): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllConsumableStockLogs(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllReagentStockLogs() (+14 more)
### Community 5 - "Community 5"
Cohesion: 0.08
Nodes (6): handleReset(), handleSearch(), WebSocketClient, TableCache, emit(), handleSubmit()
### Community 6 - "Community 6"
Cohesion: 0.05
Nodes (40): fetchAccessLogList(), fetchCleanRoomList(), fetchCreateAccessLog(), fetchCreateCleanRoom(), fetchCreateSite(), fetchDeleteAccessLog(), fetchDeleteCleanRoom(), fetchDeleteSite() (+32 more)
### Community 6 - "Community 6"
Cohesion: 0.1
Nodes (2): WebSocketClient, TableCache
### Community 7 - "Community 7"
Cohesion: 0.07
Nodes (21): auditorDisplay(), dash(), expressName(), formatYm(), formatYmd(), sampleTypeName(), siteName(), unitName() (+13 more)
Nodes (35): disableDevTools(), handleLock(), handleUnlock(), isMobile(), toLogin(), base64ToBytes(), bytesToBase64(), decryptJson() (+27 more)
### Community 8 - "Community 8"
Cohesion: 0.06
Nodes (18): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+10 more)
Nodes (12): collectIds(), useSettingsHandlers(), useSettingsPanel(), useSettingsState(), ComponentLoader, RoutePermissionValidator, RouteTransformer, useCeremony() (+4 more)
### Community 9 - "Community 9"
Cohesion: 0.07
Nodes (21): auditorDisplay(), dash(), expressName(), formatYm(), formatYmd(), sampleTypeName(), siteName(), unitName() (+13 more)
### Community 10 - "Community 10"
Cohesion: 0.06
Nodes (18): fetchAttachmentDownloadUrl(), fetchOrderAdjusts(), fetchOrderDetail(), fetchOrderItems(), fetchOrderList(), fetchPriceVersionDetail(), fetchSystemConfig(), handleReceptionAttachmentDownload() (+10 more)
### Community 11 - "Community 11"
Cohesion: 0.09
Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
### Community 10 - "Community 10"
Cohesion: 0.09
Nodes (29): base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes(), sha256Hex() (+21 more)
### Community 11 - "Community 11"
Cohesion: 0.07
Nodes (17): fetchApproveTask(), fetchBusinessAllTasks(), fetchCompletedTasks(), fetchDesignerData(), fetchInstanceDetail(), fetchMyInstances(), fetchPendingTasks(), fetchProcessDefList() (+9 more)
### Community 12 - "Community 12"
Cohesion: 0.08
Nodes (10): collectIds(), useSettingsHandlers(), useSettingsPanel(), useSettingsState(), RoutePermissionValidator, useCeremony(), useTheme(), themeAnimation() (+2 more)
Cohesion: 0.05
Nodes (9): fetchMaterialList(), fetchMaterialOptions(), fetchMaterialStockLogList(), fetchQcThirdPartyCompanyList(), fetchQcThirdPartyCompanyOptions(), fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList() (+1 more)
### Community 13 - "Community 13"
Cohesion: 0.09
Nodes (16): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), postorder(), preorder(), applyTreeExpand(), handleAdd() (+8 more)
Nodes (9): fetchGetAllUpgradeLogs(), fetchGetChinaMapData(), fetchGetComments(), fetchGetCurrentVersion(), fetchGetLatestUpgradeLog(), fetchGetSystemConfig(), fetchGetUpgradeLogs(), systemUpgrade() (+1 more)
### Community 14 - "Community 14"
Cohesion: 0.11
Nodes (8): disableDevTools(), handleLock(), handleUnlock(), isMobile(), toLogin(), logOut(), systemUpgrade(), VersionManager
### Community 15 - "Community 15"
Cohesion: 0.1
Nodes (8): fetchGetMenuList(), fetchGetMenuCodes(), fetchLogin(), fetchRefreshToken(), MenuProcessor, useAppMode(), useAuth(), buildWebEncryptedLoginBody()
### Community 16 - "Community 16"
### Community 15 - "Community 15"
Cohesion: 0.1
Nodes (13): fetchEthnicList(), addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureDonationProtocolNoInOptions(), ensureEthnicOptionInList(), handleOpenForAdd() (+5 more)
### Community 17 - "Community 17"
### Community 16 - "Community 16"
Cohesion: 0.1
Nodes (18): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+10 more)
### Community 18 - "Community 18"
### Community 17 - "Community 17"
Cohesion: 0.12
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
### Community 19 - "Community 19"
### Community 18 - "Community 18"
Cohesion: 0.1
Nodes (6): fetchProductionTaskDetail(), fetchProductionTaskList(), fetchUpdateProductionTask(), handleClose(), handleSubmit(), loadTaskDetail()
### Community 19 - "Community 19"
Cohesion: 0.13
Nodes (16): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), postorder(), preorder(), applyTreeExpand(), handleAdd() (+8 more)
### Community 20 - "Community 20"
Cohesion: 0.14
Nodes (17): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd(), handleDelete() (+9 more)
### Community 21 - "Community 21"
Cohesion: 0.2
Nodes (2): ComponentLoader, RouteTransformer
Cohesion: 0.12
Nodes (12): fetchApproveTask(), fetchBusinessAllTasks(), fetchCompletedTasks(), fetchDesignerData(), fetchInstanceDetail(), fetchMyInstances(), fetchPendingTasks(), fetchProcessDefList() (+4 more)
### Community 22 - "Community 22"
Cohesion: 0.16
Nodes (10): useTable(), useTableImpl(), getColumnChecks(), useTableColumns(), createErrorHandler(), createSmartDebounce(), defaultResponseAdapter(), extractPagination() (+2 more)
### Community 23 - "Community 23"
Cohesion: 0.11
Nodes (5): fetchMaterialList(), fetchMaterialOptions(), fetchMaterialStockLogList(), fetchSampleReceptionCheckItemList(), fetchSampleReceptionCheckItemsActive()
### Community 24 - "Community 24"
Cohesion: 0.27
Nodes (14): useChart(), useChartComponent(), useChartOps(), colourBlend(), getCssVar(), getDarkColor(), getLightColor(), handleElementThemeColor() (+6 more)
### Community 25 - "Community 25"
### Community 24 - "Community 24"
Cohesion: 0.17
Nodes (12): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), handleAdd(), handleBatchDelete(), handleDelete(), handleReset() (+4 more)
### Community 27 - "Community 27"
Cohesion: 0.17
Nodes (3): fetchResearchDonationAuditList(), fetchResearchDonationDetail(), fetchResearchDonationList()
### Community 28 - "Community 28"
### Community 26 - "Community 26"
Cohesion: 0.2
Nodes (2): fetchQcMaterialList(), fetchQcMaterialOptions()
### Community 30 - "Community 30"
### Community 28 - "Community 28"
Cohesion: 0.39
Nodes (6): isIgnorableScriptError(), normalizeErrorMessage(), registerPromiseErrorHandler(), registerResourceErrorHandler(), scriptErrorHandler(), setupErrorHandle()
### Community 31 - "Community 31"
### Community 29 - "Community 29"
Cohesion: 0.36
Nodes (1): TableHeightCalculator
### Community 32 - "Community 32"
### Community 30 - "Community 30"
Cohesion: 0.25
Nodes (2): fetchProductionWorkOrderDetail(), fetchProductionWorkOrderList()
### Community 33 - "Community 33"
### Community 31 - "Community 31"
Cohesion: 0.25
Nodes (2): fetchQcTaskDetail(), fetchQcTaskList()
### Community 34 - "Community 34"
### Community 32 - "Community 32"
Cohesion: 0.33
Nodes (2): logApiCryptoBootInfo(), maskSecret()
### Community 35 - "Community 35"
### Community 33 - "Community 33"
Cohesion: 0.29
Nodes (2): fetchLeaveDetail(), fetchLeaveList()
### Community 36 - "Community 36"
Cohesion: 0.29
Nodes (2): fetchQcWorkOrderDetail(), fetchQcWorkOrderList()
### Community 37 - "Community 37"
### Community 34 - "Community 34"
Cohesion: 0.47
Nodes (3): isPaymentDueWithinWarnWindow(), parsePaymentDueYmd(), startOfLocalDay()
### Community 39 - "Community 39"
### Community 36 - "Community 36"
Cohesion: 0.33
Nodes (2): fetchSampleReceptionCheckItemList(), fetchSampleReceptionCheckItemsActive()
### Community 37 - "Community 37"
Cohesion: 0.33
Nodes (2): fetchQcThirdPartyItemList(), fetchQcThirdPartyItemsActive()
### Community 40 - "Community 40"
Cohesion: 0.33
Nodes (2): fetchQcThirdPartyCompanyList(), fetchQcThirdPartyCompanyOptions()
### Community 41 - "Community 41"
Cohesion: 0.33
Nodes (2): fetchQcLabTestItemList(), fetchQcLabTestItemsActive()
### Community 43 - "Community 43"
### Community 39 - "Community 39"
Cohesion: 0.53
Nodes (4): isEtaTodayOrEarlier(), parseEtaLocalDate(), sampleReceptionRowClassName(), startOfLocalDay()
### Community 44 - "Community 44"
### Community 40 - "Community 40"
Cohesion: 0.5
Nodes (2): focusInput(), handleKeydown()
### Community 45 - "Community 45"
### Community 41 - "Community 41"
Cohesion: 0.67
Nodes (2): if(), logSidebarMenu()
### Community 46 - "Community 46"
Cohesion: 0.5
Nodes (1): fetchStorageEntrySmsList()
### Community 47 - "Community 47"
Cohesion: 0.5
Nodes (1): fetchSampleSmsNotificationList()
### Community 48 - "Community 48"
### Community 42 - "Community 42"
Cohesion: 1.0
Nodes (2): getSettingDefaults(), resetToDefaults()
### Community 50 - "Community 50"
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (2): defaultAvatarPathByRole(), resolveUserAvatarUrl()
## Knowledge Gaps
- **Thin community `Community 6`** (42 nodes): `WebSocketClient`, `.calculateReconnectDelay()`, `.clearAllTimers()`, `.clearConnectionTimers()`, `.clearTimer()`, `.close()`, `.closeCurrentSocketForReconnect()`, `.connect()`, `.connectionStatusText()`, `.constructor()`, `.destroyInstance()`, `.flushMessageQueue()`, `.getInstance()`, `.getReadyStateText()`, `.handleClose()`, `.handleConnectionTimeout()`, `.handleError()`, `.handleMessage()`, `.handleOpen()`, `.init()`, `.isWebSocketConnected()`, `.reconnect()`, `.resetHeartbeat()`, `.send()`, `.startHeartbeat()`, `.startPing()`, `TableCache`, `.cleanupExpired()`, `.clear()`, `.clearByTags()`, `.clearCurrentSearch()`, `.clearPagination()`, `.constructor()`, `.evictLRU()`, `.generateKey()`, `.generateTags()`, `.get()`, `.getStats()`, `.log()`, `.set()`, `index.ts`, `tableCache.ts`
- **Thin community `Community 26`** (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 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 29`** (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 28`** (10 nodes): `fetchBatchStockInQcMaterial()`, `fetchBatchStockOutQcMaterial()`, `fetchCreateQcMaterial()`, `fetchDeleteQcMaterial()`, `fetchQcMaterialList()`, `fetchQcMaterialOptions()`, `fetchStockInQcMaterial()`, `fetchStockOutQcMaterial()`, `fetchUpdateQcMaterial()`, `qc-material.ts`
- **Thin community `Community 30`** (8 nodes): `fetchCompleteProductionWorkOrder()`, `fetchConfigureProductionWorkOrder()`, `fetchCreateProductionWorkOrder()`, `fetchDeleteProductionWorkOrder()`, `fetchProductionWorkOrderDetail()`, `fetchProductionWorkOrderList()`, `fetchUpdateProductionWorkOrder()`, `production-work-order.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 31`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
- **Thin community `Community 31`** (8 nodes): `fetchCompleteQcTask()`, `fetchCreateQcTask()`, `fetchDeleteQcTask()`, `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 32`** (8 nodes): `fetchCompleteProductionWorkOrder()`, `fetchConfigureProductionWorkOrder()`, `fetchCreateProductionWorkOrder()`, `fetchDeleteProductionWorkOrder()`, `fetchProductionWorkOrderDetail()`, `fetchProductionWorkOrderList()`, `fetchUpdateProductionWorkOrder()`, `production-work-order.ts`
- **Thin community `Community 32`** (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 33`** (8 nodes): `fetchCompleteQcTask()`, `fetchCreateQcTask()`, `fetchDeleteQcTask()`, `fetchQcTaskDetail()`, `fetchQcTaskList()`, `fetchStartQcTask()`, `fetchUpdateQcTaskAttachments()`, `qc-task.ts`
- **Thin community `Community 33`** (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 34`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
- **Thin community `Community 36`** (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 35`** (7 nodes): `fetchCreateLeave()`, `fetchDeleteLeave()`, `fetchLeaveDetail()`, `fetchLeaveList()`, `fetchSubmitLeave()`, `fetchUpdateLeave()`, `leave.ts`
- **Thin community `Community 37`** (6 nodes): `fetchCreateQcThirdPartyItem()`, `fetchDeleteQcThirdPartyItem()`, `fetchQcThirdPartyItemList()`, `fetchQcThirdPartyItemsActive()`, `fetchUpdateQcThirdPartyItem()`, `qc-third-party-item.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 36`** (7 nodes): `fetchConfigureQcWorkOrder()`, `fetchCreateQcWorkOrder()`, `fetchDeleteQcWorkOrder()`, `fetchQcWorkOrderDetail()`, `fetchQcWorkOrderList()`, `fetchUpdateQcWorkOrder()`, `qc-work-order.ts`
- **Thin community `Community 40`** (5 nodes): `focusInput()`, `handleKeydown()`, `if()`, `search()`, `index.vue`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 39`** (6 nodes): `fetchCreateQcThirdPartyItem()`, `fetchDeleteQcThirdPartyItem()`, `fetchQcThirdPartyItemList()`, `fetchQcThirdPartyItemsActive()`, `fetchUpdateQcThirdPartyItem()`, `qc-third-party-item.ts`
- **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 40`** (6 nodes): `fetchCreateQcThirdPartyCompany()`, `fetchDeleteQcThirdPartyCompany()`, `fetchQcThirdPartyCompanyList()`, `fetchQcThirdPartyCompanyOptions()`, `fetchUpdateQcThirdPartyCompany()`, `qc-third-party-company.ts`
- **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 41`** (6 nodes): `fetchCreateQcLabTestItem()`, `fetchDeleteQcLabTestItem()`, `fetchQcLabTestItemList()`, `fetchQcLabTestItemsActive()`, `fetchUpdateQcLabTestItem()`, `qc-lab-test-item.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 44`** (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 45`** (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 46`** (4 nodes): `fetchGenerateStorageEntrySms()`, `fetchStorageEntrySmsList()`, `fetchToggleStorageEntrySmsNotified()`, `storage-entry-sms-notification.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 47`** (4 nodes): `fetchGenerateSms()`, `fetchSampleSmsNotificationList()`, `fetchToggleSmsNotified()`, `sample-sms-notification.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 48`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 50`** (3 nodes): `defaultAvatarPathByRole()`, `resolveUserAvatarUrl()`, `user-avatar.ts`
- **Thin community `Community 44`** (3 nodes): `defaultAvatarPathByRole()`, `resolveUserAvatarUrl()`, `user-avatar.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 8`, `Community 11`, `Community 13`, `Community 15`, `Community 16`, `Community 17`, `Community 19`, `Community 20`, `Community 23`, `Community 25`, `Community 27`, `Community 28`, `Community 32`, `Community 33`, `Community 35`, `Community 36`, `Community 39`, `Community 40`, `Community 41`, `Community 46`, `Community 47`?**
_High betweenness centrality (0.299) - this node is a cross-community bridge._
- **Why does `push()` connect `Community 2` to `Community 0`, `Community 6`, `Community 12`, `Community 14`, `Community 16`?**
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 6`, `Community 10`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `Community 19`, `Community 20`, `Community 21`, `Community 24`, `Community 26`, `Community 30`, `Community 31`, `Community 33`, `Community 36`, `Community 37`?**
_High betweenness centrality (0.272) - this node is a cross-community bridge._
- **Why does `push()` connect `Community 2` to `Community 0`, `Community 5`, `Community 8`, `Community 13`, `Community 15`?**
_High betweenness centrality (0.099) - this node is a cross-community bridge._
- **Why does `fetchGetLatestUpgradeLog()` connect `Community 0` to `Community 14`?**
_High betweenness centrality (0.043) - this node is a cross-community bridge._
- **Are the 165 inferred relationships involving `get()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `buildTreePathLabelFromFlat()`) actually correct?**
_`get()` has 165 INFERRED edges - model-reasoned connections that need verification._
- **Why does `handleDynamicRoutes()` connect `Community 3` to `Community 8`, `Community 14`?**
_High betweenness centrality (0.057) - this node is a cross-community bridge._
- **Are the 169 inferred relationships involving `get()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `buildTreePathLabelFromFlat()`) actually correct?**
_`get()` has 169 INFERRED edges - model-reasoned connections that need verification._
- **Are the 19 inferred relationships involving `push()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `fetchAllPagedRecords()`) actually correct?**
_`push()` has 19 INFERRED edges - model-reasoned connections that need verification._
- **Are the 16 inferred relationships involving `withFullscreenLoading()` (e.g. with `.close()` and `handleSubmit()`) actually correct?**
+4 -4
View File
@@ -57,12 +57,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">1546 nodes &middot; 1923 edges &middot; 259 communities</div>
<div id="stats">1565 nodes &middot; 1943 edges &middot; 256 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 34, "community_name": "Community 34", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 34, "community_name": "Community 34", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 34, "community_name": "Community 34", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 34, "community_name": "Community 34", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 34, "community_name": "Community 34", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 34, "community_name": "Community 34", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 84, "community_name": "Community 84", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 85, "community_name": "Community 85", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 18, "community_name": "Community 18", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.7, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 18, "community_name": "Community 18", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 18, "community_name": "Community 18", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 18, "community_name": "Community 18", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 18, "community_name": "Community 18", "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": 236}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 92}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 79}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 68}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 65}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 51}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 42}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 42}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 38}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 37}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 37}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 31}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 30}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 29}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 28}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 28}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 27}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 26}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 22}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 22}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 20}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 17}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 17}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 17}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 16}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 16}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 13}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 12}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 10}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 9}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 8}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 8}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 8}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 8}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 7}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 7}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 7}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 6}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 6}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 6}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 6}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 6}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 6}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 6}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 5}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 4}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 4}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 4}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 3}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 3}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 3}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 3}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 3}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 3}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 3}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 3}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 3}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 3}, {"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": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 32, "community_name": "Community 32", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 32, "community_name": "Community 32", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 32, "community_name": "Community 32", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 32, "community_name": "Community 32", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 32, "community_name": "Community 32", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 32, "community_name": "Community 32", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 80, "community_name": "Community 80", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 81, "community_name": "Community 81", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 17, "community_name": "Community 17", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.6, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 17, "community_name": "Community 17", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 17, "community_name": "Community 17", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 17, "community_name": "Community 17", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 17, "community_name": "Community 17", "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": 252}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 103}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 79}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 68}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 65}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 51}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 51}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 48}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 47}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 42}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 38}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 36}, {"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": 28}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 27}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 26}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 22}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 22}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 21}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 20}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 19}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 17}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 16}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 16}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 13}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 10}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 9}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 8}, {"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": 8}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 7}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 7}, {"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": 3}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 3}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 2}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 2}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 2}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 2}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 2}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 2}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 2}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 2}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 2}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 2}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 2}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 2}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 2}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 2}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 2}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 2}, {"cid": 70, "color": "#4E79A7", "label": "Community 70", "count": 2}, {"ciLine truncated
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
+20 -17
View File
@@ -17,8 +17,8 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/index.ts": 1778582068.0254738,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/directive/directive.d.ts": 1778582068.026978,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api/api.d.ts": 1778582068.0246184,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1779615010.407172,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779613863.0353637,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1779624160.2284083,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1779624041.8643298,
"/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,
@@ -44,11 +44,12 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/fullscreen-loading.ts": 1779117454.818312,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/router.ts": 1778582068.0393815,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-labels.ts": 1779199125.4894068,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts": 1779611349.8407457,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts": 1779623065.8389401,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/fetch-paged-list.ts": 1778775532.895782,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sort-order.ts": 1778775532.8963482,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/tree-path.ts": 1778800847.103174,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/mask-sensitive.ts": 1778984825.4182227,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts": 1779615806.1798687,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/index.ts": 1778582068.0369413,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/category-path-display.ts": 1778582068.0304127,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/qc-labels.ts": 1779199108.173778,
@@ -176,12 +177,12 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-qc-info-cards/index.vue": 1779525781.6078143,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/order-operate-local-dialog/index.vue": 1779525781.608513,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/product-view-dialog/index.vue": 1779525781.6090777,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-production-info-cards/index.vue": 1779591224.5145729,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-production-info-cards/index.vue": 1779615820.4916759,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-storage-release-info/index.vue": 1779542542.2434525,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/work-order-remark-dialog/index.vue": 1779615010.0847185,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/protocol-payment-detail-readonly/index.vue": 1779525781.6098895,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/system-view-dialog/index.vue": 1779586311.488459,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue": 1779615141.6682072,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue": 1779615853.6423426,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/order-operate-dialog-bridge/index.vue": 1779525781.611354,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/hooks/index.ts": 1778582068.0037498,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/hooks/core/useFastEnter.ts": 1778582068.0014625,
@@ -200,7 +201,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": 1779521577.6135197,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-release-review.ts": 1779615813.3431153,
"/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": 1779615080.6717544,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-task-result.ts": 1779332042.258692,
@@ -209,7 +210,7 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/chinaRegion.ts": 1778582067.8620915,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/storage-entry-sms-notification.ts": 1779528209.939984,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/business.ts": 1779159587.6033742,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts": 1779418057.065808,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts": 1779623066.1765516,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/ethnic.ts": 1778929297.3919344,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-lab-test-item.ts": 1779017838.8231559,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/cell-product.ts": 1779594447.3049195,
@@ -233,13 +234,13 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolAttachmentReadonly.vue": 1779525781.6162472,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue": 1779525781.6179993,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolAuditDialog.vue": 1779525781.6193507,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/sample-reception-info/index.vue": 1779543540.7133334,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/sample-reception-info/index.vue": 1779616455.4280064,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/payment-info/index.vue": 1779543540.712599,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/storage-cert/index.vue": 1779543540.7106564,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/storage-cert/index.vue": 1779616329.0604427,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol-audit/index.vue": 1779543540.7095993,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue": 1779543540.7084875,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/fullmoon-todo/index.vue": 1779543540.7066376,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/storage-entry-info/index.vue": 1779543540.7045276,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/storage-entry-info/index.vue": 1779616456.4401474,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/payment-confirm/index.vue": 1779525781.6252205,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material-stock-log/index.vue": 1779543540.7038007,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/outside/Iframe.vue": 1779525781.6271372,
@@ -290,14 +291,14 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/cell-product/source-chain/chainToFlow.ts": 1779601450.3906622,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/process-route/index.vue": 1779543540.7289982,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/sop/index.vue": 1779543540.726837,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-task/index.vue": 1779615118.6620471,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-task/index.vue": 1779615840.3873165,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/reagent/index.vue": 1779589143.1296964,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue": 1779615100.306273,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts": 1779615065.4906602,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue": 1779615827.927988,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts": 1779615478.2475564,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/StepDetailPanel.vue": 1779525781.678735,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue": 1779615017.576425,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue": 1779615467.9727454,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskInputEnhancedTable.vue": 1779525781.679505,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskExecutionDialog.vue": 1779615057.3333266,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskExecutionDialog.vue": 1779615834.8266983,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/EditTaskInfoDialog.vue": 1779525781.6816807,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskOutputList.vue": 1779525781.6822913,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/DispatchTaskDialog.vue": 1779608520.251511,
@@ -324,9 +325,11 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/cell-product-type/index.vue": 1779543540.6913223,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/checkup-institution/index.vue": 1779543540.6905549,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/checkup-institution/CheckupPackagePanel.vue": 1779525781.7596755,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue": 1779624477.8303812,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel/index.vue": 1779543540.6894271,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel/ChannelViewDialog.vue": 1779525781.762359,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel/ChannelViewDialog.vue": 1779619832.8572278,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/cell-product-price/index.vue": 1779543540.6862803,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order-finance/index.vue": 1779624069.7118964,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/project-price-system/index.vue": 1779543540.6854389,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/cell-product-spec/index.vue": 1779543540.6845775,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/basic-info/sample-code/index.vue": 1779543540.6835444,
@@ -352,7 +355,7 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/RoutePermissionValidator.ts": 1778582068.0127926,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/index.ts": 1778582068.0138035,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/IframeRouteManager.ts": 1778582068.0121944,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/sqxp.ts": 1779607268.816103,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/sqxp.ts": 1779621228.5497704,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/index.ts": 1778598510.6043763,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/exception.ts": 1779546186.993006,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/routes/staticRoutes.ts": 1779546226.1088154,
+114
View File
@@ -1891,3 +1891,117 @@ export function fetchFullmoonTodoList(params?: {
export function fetchUpdateFullmoonTodoInsurance(protocolId: string, data: Record<string, any>) {
return request.put({ url: `/web/admin/fullmoon-todos/${protocolId}/insurance`, params: data })
}
// ---------------------------------------------------------------------------
// 渠道服务购买订单
// ---------------------------------------------------------------------------
/** 渠道服务订单列表 */
export function fetchChannelServiceOrderList(params?: Record<string, any>) {
return request.get({ url: '/web/admin/channel-service-orders', params })
}
/** 渠道服务订单详情 */
export function fetchChannelServiceOrderDetail(orderId: string) {
return request.get({ url: `/web/admin/channel-service-orders/${orderId}` })
}
/** 创建渠道服务订单 */
export function fetchCreateChannelServiceOrder(data: Record<string, any>) {
return request.post({ url: '/web/admin/channel-service-orders', params: data })
}
/** 更新渠道服务订单 */
export function fetchUpdateChannelServiceOrder(orderId: string, data: Record<string, any>) {
return request.put({ url: `/web/admin/channel-service-orders/${orderId}`, params: data })
}
/** 删除渠道服务订单 */
export function fetchDeleteChannelServiceOrder(orderId: string) {
return request.del({ url: `/web/admin/channel-service-orders/${orderId}` })
}
/** 发起财务确认(市场人员提交备注与凭证) */
export function fetchSubmitServiceOrderFinanceConfirm(orderId: string, data: Record<string, any>) {
return request.post({
url: `/web/admin/channel-service-orders/${orderId}/submit-finance-confirm`,
params: data
})
}
/** 财务确认收款 */
export function fetchConfirmServiceOrderReceipt(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/confirm-receipt`, params: data })
}
/** 提交退款 */
export function fetchSubmitServiceOrderRefund(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/submit-refund`, params: data })
}
/** 确认退款 */
export function fetchConfirmServiceOrderRefund(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/confirm-refund`, params: data })
}
/** 作废订单 */
export function fetchVoidServiceOrder(orderId: string) {
return request.put({ url: `/web/admin/channel-service-orders/${orderId}/void` })
}
/** 渠道账户 */
export function fetchChannelAccount(channelId: string) {
return request.get({ url: `/web/admin/channels/${channelId}/account` })
}
/** 渠道产品份数 */
export function fetchChannelProductQuotas(channelId: string) {
return request.get({ url: `/web/admin/channels/${channelId}/product-quotas` })
}
// ========== 渠道服务订单操作流水 ==========
/** 流水列表 */
export function fetchServiceOrderTxnList(params?: Record<string, any>) {
return request.get({ url: '/web/admin/channel-service-order-txns', params })
}
/** 流水详情 */
export function fetchServiceOrderTxnDetail(txnId: string) {
return request.get({ url: `/web/admin/channel-service-order-txns/${txnId}` })
}
/** 发起充值 */
export function fetchCreateRechargeTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/recharge`, params: data })
}
/** 申请退款 */
export function fetchCreateRefundTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/refund`, params: data })
}
/** 购买产品 */
export function fetchCreatePurchaseTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/purchase`, params: data })
}
/** 退订产品 */
export function fetchCreateUnsubscribeTxn(orderId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-orders/${orderId}/unsubscribe`, params: data })
}
/** 流水发起财务确认 */
export function fetchSubmitTxnFinance(txnId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-order-txns/${txnId}/submit-finance`, params: data })
}
/** 流水财务确认 */
export function fetchConfirmTxn(txnId: string, data: Record<string, any>) {
return request.post({ url: `/web/admin/channel-service-order-txns/${txnId}/confirm`, params: data })
}
/** 作废流水 */
export function fetchVoidTxn(txnId: string) {
return request.put({ url: `/web/admin/channel-service-order-txns/${txnId}/void` })
}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry_ts", "label": "status-tag-registry.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts", "source_location": "L1"}, {"id": "utils_status_tag_registry_createlabelgetter", "label": "createLabelGetter()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts", "source_location": "L29"}, {"id": "utils_status_tag_registry_createtagtypegetter", "label": "createTagTypeGetter()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts", "source_location": "L33"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry_ts", "target": "utils_status_tag_registry_createlabelgetter", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts", "source_location": "L29", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry_ts", "target": "utils_status_tag_registry_createtagtypegetter", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts", "source_location": "L33", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin_ts", "label": "admin.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L1"}, {"id": "api_admin_fetchgetmenulist", "label": "fetchGetMenuList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L10"}, {"id": "api_admin_fetchgetrolelist", "label": "fetchGetRoleList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L19"}, {"id": "api_admin_fetchuseroptions", "label": "fetchUserOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L26"}, {"id": "api_admin_fetchroleoptions", "label": "fetchRoleOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L33"}, {"id": "api_admin_fetchtenantlist", "label": "fetchTenantList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L43"}, {"id": "api_admin_fetchcreatetenant", "label": "fetchCreateTenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L56"}, {"id": "api_admin_fetchupdatetenant", "label": "fetchUpdateTenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L71"}, {"id": "api_admin_fetchdeletetenant", "label": "fetchDeleteTenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L89"}, {"id": "api_admin_fetchuserlist", "label": "fetchUserList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L100"}, {"id": "api_admin_fetchuserdetail", "label": "fetchUserDetail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L119"}, {"id": "api_admin_fetchcreateuser", "label": "fetchCreateUser()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L125"}, {"id": "api_admin_fetchupdateuser", "label": "fetchUpdateUser()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L147"}, {"id": "api_admin_fetchdeleteuser", "label": "fetchDeleteUser()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L170"}, {"id": "api_admin_fetchresetpassword", "label": "fetchResetPassword()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L177"}, {"id": "api_admin_fetchuploaduseravatar", "label": "fetchUploadUserAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L185"}, {"id": "api_admin_fetchregionlist", "label": "fetchRegionList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L196"}, {"id": "api_admin_fetchactiveregions", "label": "fetchActiveRegions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L214"}, {"id": "api_admin_fetchnotdeletedregions", "label": "fetchNotDeletedRegions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L231"}, {"id": "api_admin_fetchcategorylist", "label": "fetchCategoryList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L259"}, {"id": "api_admin_fetchcreatecategory", "label": "fetchCreateCategory()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L277"}, {"id": "api_admin_fetchupdatecategory", "label": "fetchUpdateCategory()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L290"}, {"id": "api_admin_fetchdeletecategory", "label": "fetchDeleteCategory()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L307"}, {"id": "api_admin_fetchuploadcategoryimage", "label": "fetchUploadCategoryImage()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L313"}, {"id": "api_admin_fetchunitlist", "label": "fetchUnitList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/admin.ts", "source_location": "L324"}, {"id": "api_admin_fetchcreateunit", "label": "fetchCrLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_finance_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order-finance/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -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": "L120"}, {"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": "L134"}, {"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": "L140"}, {"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": "L154"}, {"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": "L166"}, {"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": "L172"}], "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": "L120", "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": "L134", "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": "L140", "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": "L154", "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": "L166", "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": "L172", "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": "L128"}, {"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": "L135"}, {"caller_nid": "api_storage_release_revLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1"}, {"id": "channel_service_order_index_validate", "label": "validate()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1394"}, {"id": "channel_service_order_index_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1399"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "target": "channel_service_order_index_validate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1394", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "target": "channel_service_order_index_if", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1399", "weight": 1.0}], "raw_calls": [{"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1401"}, {"caller_nid": "channel_service_order_index_if", "callee": "some", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1404"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1408"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1412"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1"}, {"id": "channel_service_order_index_validate", "label": "validate()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1465"}, {"id": "channel_service_order_index_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1470"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "target": "channel_service_order_index_validate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1465", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "target": "channel_service_order_index_if", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1470", "weight": 1.0}], "raw_calls": [{"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1472"}, {"caller_nid": "channel_service_order_index_if", "callee": "filter", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1475"}, {"caller_nid": "channel_service_order_index_if", "callee": "map", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1475"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1477"}, {"caller_nid": "channel_service_order_index_if", "callee": "some", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1480"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1484"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1488"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_production_labels_ts", "label": "production-labels.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L1"}, {"id": "utils_production_labels_productionconclusionlabel", "label": "productionConclusionLabel()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L4"}, {"id": "utils_production_labels_productionconclusiontagtype", "label": "productionConclusionTagType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L11"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_production_labels_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_status_tag_registry", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_production_labels_ts", "target": "utils_production_labels_productionconclusionlabel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_production_labels_ts", "target": "utils_production_labels_productionconclusiontagtype", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L11", "weight": 1.0}], "raw_calls": [{"caller_nid": "utils_production_labels_productionconclusionlabel", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L5"}, {"caller_nid": "utils_production_labels_productionconclusiontagtype", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/production-labels.ts", "source_location": "L12"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_channelviewdialog_vue", "label": "ChannelViewDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel/ChannelViewDialog.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_storage_cert_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/storage-cert/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_task_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-task/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1"}, {"id": "channel_service_order_index_validate", "label": "validate()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1392"}, {"id": "channel_service_order_index_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1397"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "target": "channel_service_order_index_validate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1392", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_index_vue", "target": "channel_service_order_index_if", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1397", "weight": 1.0}], "raw_calls": [{"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1399"}, {"caller_nid": "channel_service_order_index_if", "callee": "some", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1402"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1406"}, {"caller_nid": "channel_service_order_index_if", "callee": "warning", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order/index.vue", "source_location": "L1410"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_storage_entry_info_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/storage-entry-info/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "label": "useTaskStepEditor.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L1"}, {"id": "production_work_order_usetaskstepeditor_toapiflag", "label": "toApiFlag()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L35"}, {"id": "production_work_order_usetaskstepeditor_fromapiflag", "label": "fromApiFlag()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L39"}, {"id": "production_work_order_usetaskstepeditor_normalizestepsubtables", "label": "normalizeStepSubTables()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L42"}, {"id": "production_work_order_usetaskstepeditor_parseordernum", "label": "parseOrderNum()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L57"}, {"id": "production_work_order_usetaskstepeditor_usetaskstepeditor", "label": "useTaskStepEditor()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L64"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_production_task", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_production", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L16", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L24", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_cell_product", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L25", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L26", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_storage_slot_options", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L32", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "production_work_order_usetaskstepeditor_toapiflag", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L35", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_usetaskstepeditor_ts", "target": "production_work_order_usetaskstepeditor_fromapiflag", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/useTaskStepEditor.ts", "source_location": "L39", "weight": 1.0}, {"source"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_sample_reception_info_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/sample-reception-info/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_sample_production_info_cards_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-production-info-cards/index.vue", "source_location": "L1"}, {"id": "sample_production_info_cards_index_productiontaskstatuslabel", "label": "productionTaskStatusLabel()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-production-info-cards/index.vue", "source_location": "L172"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_sample_production_info_cards_index_vue", "target": "sample_production_info_cards_index_productiontaskstatuslabel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/sample-production-info-cards/index.vue", "source_location": "L172", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_taskexecutiondialog_vue", "label": "TaskExecutionDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/TaskExecutionDialog.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_production_task_view_dialog_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L1"}, {"id": "production_task_view_dialog_index_taskstatuslabel", "label": "taskStatusLabel()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L159"}, {"id": "production_task_view_dialog_index_tasktypelabel", "label": "taskTypeLabel()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L170"}, {"id": "production_task_view_dialog_index_productstatustagtype", "label": "productStatusTagType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L180"}, {"id": "production_task_view_dialog_index_productstatuslabel", "label": "productStatusLabel()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L190"}, {"id": "production_task_view_dialog_index_formatdateonly", "label": "formatDateOnly()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L200"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_production_task_view_dialog_index_vue", "target": "production_task_view_dialog_index_taskstatuslabel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L159", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_production_task_view_dialog_index_vue", "target": "production_task_view_dialog_index_tasktypelabel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L170", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_production_task_view_dialog_index_vue", "target": "production_task_view_dialog_index_productstatustagtype", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L180", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_production_task_view_dialog_index_vue", "target": "production_task_view_dialog_index_productstatuslabel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L190", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_production_task_view_dialog_index_vue", "target": "production_task_view_dialog_index_formatdateonly", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L200", "weight": 1.0}], "raw_calls": [{"caller_nid": "production_task_view_dialog_index_formatdateonly", "callee": "String", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L202"}, {"caller_nid": "production_task_view_dialog_index_formatdateonly", "callee": "slice", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/production-task-view-dialog/index.vue", "source_location": "L203"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_pilot_service_channel_service_order_finance_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/channel-service-order-finance/index.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_router_modules_sqxp_ts", "label": "sqxp.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/sqxp.ts", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_router_modules_sqxp_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_types_router", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/sqxp.ts", "source_location": "L1", "weight": 1.0}], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_completeproductiontaskdialog_vue", "label": "CompleteProductionTaskDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L1"}, {"id": "production_work_order_completeproductiontaskdialog_handleclose", "label": "handleClose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L76"}, {"id": "production_work_order_completeproductiontaskdialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L80"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_completeproductiontaskdialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L42", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_completeproductiontaskdialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L43", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_completeproductiontaskdialog_vue", "target": "production_work_order_completeproductiontaskdialog_handleclose", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L76", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_production_production_work_order_completeproductiontaskdialog_vue", "target": "production_work_order_completeproductiontaskdialog_handlesubmit", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L80", "weight": 1.0}], "raw_calls": [{"caller_nid": "production_work_order_completeproductiontaskdialog_handlesubmit", "callee": "validate", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L82"}, {"caller_nid": "production_work_order_completeproductiontaskdialog_handlesubmit", "callee": "emit", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L83"}, {"caller_nid": "production_work_order_completeproductiontaskdialog_handlesubmit", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/production/production-work-order/CompleteProductionTaskDialog.vue", "source_location": "L85"}]}
+22
View File
@@ -617,6 +617,28 @@ export const sqxpAdminRoutes: AppRouteRecord[] = [
path: 'checkup-institution',
component: '/pilot-service/checkup-institution/index',
meta: { title: '体检机构及项目价格', keepAlive: true, menuCode: 'pilot-service:checkup-institution:list' }
},
{
id: '80000000000000000000000000000008',
name: 'ChannelServiceOrder',
path: 'channel-service-order',
component: '/pilot-service/channel-service-order/index',
meta: {
title: '渠道服务购买订单',
keepAlive: true,
menuCode: 'pilot-service:channel-service-order:list'
}
},
{
id: '80000000000000000000000000000009',
name: 'ChannelServiceOrderFinance',
path: 'channel-service-order-finance',
component: '/pilot-service/channel-service-order-finance/index',
meta: {
title: '渠道服务购买订单(财务确认)',
keepAlive: true,
menuCode: 'pilot-service:channel-service-order-finance:list'
}
}
]
}
@@ -344,4 +344,74 @@ export const storageStatus: StatusRegistry = {
export const storageStatusLabel = createLabelGetter(storageStatus)
export const storageStatusTagType = createTagTypeGetter(storageStatus)
// ══════════════════════════════════════════════════════════════════════════════
// 渠道服务订单域
// ══════════════════════════════════════════════════════════════════════════════
/** 渠道服务订单类型 */
export const channelServiceOrderType: StatusRegistry = {
yfk: { label: '预付款充值', tagType: 'primary' },
gmcp: { label: '购买产品份数', tagType: 'success' }
}
export const channelServiceOrderTypeLabel = createLabelGetter(channelServiceOrderType)
export const channelServiceOrderTypeTagType = createTagTypeGetter(channelServiceOrderType)
/** 渠道服务订单状态 */
export const channelServiceOrderStatus: StatusRegistry = {
dsx: { label: '待生效', tagType: 'info' },
dqr: { label: '待确认', tagType: 'warning' },
yqr: { label: '已确认', tagType: 'success' },
sxz: { label: '生效中', tagType: 'success' },
tfqrz: { label: '退款确认中', tagType: 'danger' },
ytf: { label: '已退款', tagType: 'info' },
yzf: { label: '已作废', tagType: 'info' }
}
export const channelServiceOrderStatusLabel = createLabelGetter(channelServiceOrderStatus)
export const channelServiceOrderStatusTagType = createTagTypeGetter(channelServiceOrderStatus)
// ══════════════════════════════════════════════════════════════════════════════
// 流水域
// ══════════════════════════════════════════════════════════════════════════════
// 流水类型
export const txnTypeLabel = (type: string): string => {
const map: Record<string, string> = {
recharge: '充值',
refund: '退款',
purchase: '购买产品',
unsubscribe: '退订产品',
}
return map[type] || type
}
export const txnTypeTagType = (type: string): string => {
const map: Record<string, string> = {
recharge: '',
refund: 'danger',
purchase: 'success',
unsubscribe: 'warning',
}
return map[type] || 'info'
}
// 流水状态
export const txnStatusLabel = (status: string): string => {
const map: Record<string, string> = {
dsx: '待生效',
dqr: '待财务确认',
yqr: '已确认',
yzf: '已作废',
}
return map[status] || status
}
export const txnStatusTagType = (status: string): string => {
const map: Record<string, string> = {
dsx: 'info',
dqr: 'warning',
yqr: 'success',
yzf: 'danger',
}
return map[status] || 'info'
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -177,6 +177,80 @@
<el-empty v-else description="暂无邮寄地址" :image-size="48" />
</div>
<div id="view-section-account" class="section-card section-card--white">
<div class="section-title"><h3>账户信息</h3></div>
<div class="account-balance-card">
<div class="account-balance-card__label">账户余额</div>
<div class="account-balance-card__value">
¥ {{ accountLoading ? '—' : formatAmount(accountData?.balanceAmount) }}
</div>
</div>
<div class="account-quotas-head">
<h4 class="account-quotas-title">产品份数</h4>
</div>
<div v-if="quotasLoading" v-loading="true" style="min-height: 120px"></div>
<div v-else-if="productQuotas.length" class="list-body list-wrap account-quota-list-wrap">
<el-table
:data="productQuotas"
class="list-table account-quota-table"
stripe
row-key="id"
max-height="360"
>
<el-table-column
type="index"
label="序号"
min-width="68"
align="center"
header-align="center"
/>
<el-table-column
prop="projectName"
label="项目名称"
min-width="150"
align="center"
header-align="center"
/>
<el-table-column
prop="cellTypeName"
label="细胞类型"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="specText"
label="规格"
min-width="150"
align="center"
header-align="center"
/>
<el-table-column
prop="totalQty"
label="总份数"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column
prop="usedQty"
label="已用份数"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column
prop="remainingQty"
label="剩余份数"
min-width="100"
align="center"
header-align="center"
/>
</el-table>
</div>
<el-empty v-else description="暂无产品份数数据" :image-size="48" />
</div>
<div id="view-section-agreement" class="section-card">
<div class="section-title"><h3>协议信息</h3></div>
<div v-if="agreementList.length" class="agreement-cards">
@@ -354,7 +428,9 @@
fetchChannelInvoices,
fetchChannelMailAddresses,
fetchChannelAgreements,
fetchChannelAgreementPrices
fetchChannelAgreementPrices,
fetchChannelAccount,
fetchChannelProductQuotas
} from '@/api/admin'
const props = defineProps<{
@@ -371,7 +447,8 @@
{ key: 'basic', label: '基础信息' },
{ key: 'invoice', label: '开票信息' },
{ key: 'mail', label: '邮寄地址' },
{ key: 'agreement', label: '协议信息' }
{ key: 'agreement', label: '协议信息' },
{ key: 'account', label: '账户信息' }
] as const
const loading = ref(false)
@@ -380,6 +457,11 @@
const mailList = ref<any[]>([])
const agreementList = ref<any[]>([])
const agreementPricesMap = ref<Record<string, any[]>>({})
const accountData = ref<{ balanceAmount: number } | null>(null)
const productQuotas = ref<any[]>([])
const accountLoading = ref(false)
const quotasLoading = ref(false)
const accountLoaded = ref(false)
const channel = computed(() => props.listRow || null)
@@ -460,6 +542,35 @@
downloadAttachmentFile(file, { fullFileUrl })
}
function formatAmount(val: unknown) {
if (val === null || val === undefined || val === '') return '0.00'
const num = Number(val)
if (isNaN(num)) return '0.00'
return num.toFixed(2)
}
async function loadAccountData() {
if (!props.channelId || accountLoaded.value) return
accountLoading.value = true
quotasLoading.value = true
try {
const [accRes, quotaRes] = await Promise.all([
fetchChannelAccount(props.channelId),
fetchChannelProductQuotas(props.channelId)
])
accountData.value = (accRes as any)?.data ?? accRes ?? null
const quotaRows = Array.isArray(quotaRes) ? quotaRes : (quotaRes as any)?.list || []
productQuotas.value = quotaRows
accountLoaded.value = true
} catch {
accountData.value = null
productQuotas.value = []
} finally {
accountLoading.value = false
quotasLoading.value = false
}
}
async function loadSubTables() {
if (!props.channelId) {
invoiceList.value = []
@@ -531,13 +642,19 @@
mailList.value = []
agreementList.value = []
agreementPricesMap.value = {}
accountData.value = null
productQuotas.value = []
accountLoaded.value = false
activeTab.value = 'basic'
}
watch(
() => [props.modelValue, props.channelId] as const,
([visible, id]) => {
if (visible && id) loadSubTables()
if (visible && id) {
loadSubTables()
loadAccountData()
}
}
)
</script>
@@ -915,6 +1032,86 @@
text-align: center;
}
/* 账户信息 */
.account-balance-card {
display: flex;
align-items: center;
gap: 16px;
padding: 18px 22px;
background: linear-gradient(135deg, #ecfdf5 0%, #f0fdf4 100%);
border: 1px solid #a7f3d0;
border-radius: 10px;
margin-bottom: 20px;
}
.account-balance-card__label {
font-size: 14px;
color: #64748b;
font-weight: 500;
}
.account-balance-card__value {
font-size: 26px;
font-weight: 700;
color: #059669;
letter-spacing: 0.02em;
}
.account-quotas-head {
margin-bottom: 10px;
}
.account-quotas-title {
margin: 0;
font-size: 14px;
font-weight: 600;
color: #1e293b;
line-height: 1.4;
&::before {
content: '';
display: inline-block;
width: 3px;
height: 14px;
background: #10b981;
border-radius: 2px;
margin-right: 8px;
vertical-align: -2px;
}
}
.account-quota-list-wrap {
margin-bottom: 0;
border-radius: 8px;
background: #fff;
}
.account-quota-table.list-table {
border: none !important;
box-shadow: none !important;
&::before,
&::after {
display: none !important;
}
:deep(.el-table__inner-wrapper) {
border: none !important;
&::before {
display: none !important;
}
}
:deep(.el-table__cell) {
border-right: none !important;
}
:deep(.el-table__body tr:last-child td.el-table__cell) {
border-bottom: none !important;
}
}
@media (max-width: 1200px) {
.kpi-strip {
grid-template-columns: repeat(2, 1fr);