This commit is contained in:
zlwu committed 2026-08-06 16:54:32 +08:00
1 parent ac4c3d1886
commit 6a8c3e750e
21 files changed
+9885 -9150

No files matched your search

+35 -6
View File
@@ -118,7 +118,7 @@ def _subtree_contains(node: Optional[Dict[str, Any]], node_id: str) -> bool:
def _merge_after_branch_end(
root: Dict[str, Any], end_id: str
) -> Optional[Dict[str, Any]]:
"""若 end 落在某条件分支组内,且该条件节点有汇合后 child,则返回汇合节点。"""
"""若 end 落在某条件分支组内,返回最近一层条件节点的汇合后 child(若有)。"""
def walk(node: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
if not isinstance(node, dict):
@@ -127,9 +127,14 @@ def _merge_after_branch_end(
for g in node.get("conditionGroups") or []:
if not isinstance(g, dict):
continue
if _subtree_contains(g.get("child"), end_id):
merge = node.get("child")
return merge if isinstance(merge, dict) else None
if not _subtree_contains(g.get("child"), end_id):
continue
# 优先内层条件的汇合,再回退到本层
nested = walk(g.get("child"))
if nested is not None:
return nested
merge = node.get("child")
return merge if isinstance(merge, dict) else None
merge_child = node.get("child")
if isinstance(merge_child, dict):
return walk(merge_child)
@@ -394,16 +399,22 @@ def _iter_resolved_path_nodes(
form_data: Optional[Dict[str, Any]],
*,
initiator_user_id: Optional[str] = None,
flow_root: Optional[Dict[str, Any]] = None,
) -> Optional[List[Dict[str, Any]]]:
"""沿条件命中路径收集节点;无法匹配时返回 None。"""
if not isinstance(root, dict):
return []
data = form_data or {}
tree_root = flow_root if isinstance(flow_root, dict) else root
out: List[Dict[str, Any]] = []
cur: Optional[Dict[str, Any]] = root
while cur and isinstance(cur, dict):
ntype = _node_type(cur)
if ntype == "end":
end_id = (cur.get("id") or "").strip()
# 分支叶子 end 若后面还有汇合主链,不算真正结束
if end_id and _merge_after_branch_end(tree_root, end_id) is not None:
break
out.append(cur)
break
if ntype == "condition":
@@ -415,7 +426,10 @@ def _iter_resolved_path_nodes(
child = g.get("child")
if isinstance(child, dict):
sub = _iter_resolved_path_nodes(
child, data, initiator_user_id=initiator_user_id
child,
data,
initiator_user_id=initiator_user_id,
flow_root=tree_root,
)
if sub is None:
return None
@@ -1120,7 +1134,10 @@ def _form_value_present(form_data: Optional[Dict[str, Any]], field: str) -> bool
def _collect_condition_fields(node: Optional[Dict[str, Any]]) -> List[str]:
"""收集流程树中非默认条件分支引用的表单字段(去重保序)。"""
"""收集流程树中非默认条件分支引用的表单字段(去重保序)。
系统伪字段 ``__initiator__`` 不依赖 formData,不纳入预览门闩。
"""
fields: List[str] = []
seen = set()
@@ -1128,6 +1145,8 @@ def _collect_condition_fields(node: Optional[Dict[str, Any]]) -> List[str]:
key = str(name or "").strip()
if not key or key in seen:
return
if key == INITIATOR_CONDITION_FIELD:
return
seen.add(key)
fields.append(key)
@@ -1194,10 +1213,14 @@ def _walk_preview_nodes(
initiator_select_by_node: Optional[Dict[str, List[str]]],
form_data: Optional[Dict[str, Any]],
steps: List[Dict[str, Any]],
flow_root: Optional[Dict[str, Any]] = None,
) -> bool:
"""沿最终路径写入 steps。条件无法匹配时返回 False。"""
cur = node
data = form_data or {}
tree_root = (
flow_root if isinstance(flow_root, dict) else (node if isinstance(node, dict) else {})
)
while cur and isinstance(cur, dict):
ntype = _node_type(cur)
if ntype == "start":
@@ -1218,6 +1241,10 @@ def _walk_preview_nodes(
continue
if ntype == "end":
end_id = (cur.get("id") or "").strip()
# 分支叶子 end 后若有汇合主链,不写入「结束」(与引擎推进一致)
if end_id and _merge_after_branch_end(tree_root, end_id) is not None:
break
steps.append(
{
"id": cur.get("id") or "",
@@ -1251,6 +1278,7 @@ def _walk_preview_nodes(
initiator_select_by_node=initiator_select_by_node,
form_data=data,
steps=steps,
flow_root=tree_root,
)
if not ok:
return False
@@ -1403,6 +1431,7 @@ def preview_start_flow(
initiator_select_by_node=select_by_node,
form_data=data,
steps=steps,
flow_root=root,
)
if not ok:
return {
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+94 -74
View File
@@ -1,11 +1,11 @@
# Graph Report - app (2026-08-06)
## Corpus Check
- Large corpus: 242 files · ~296,735 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
- Large corpus: 242 files · ~296,924 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
## Summary
- 5118 nodes · 27963 edges · 39 communities detected
- Extraction: 32% EXTRACTED · 68% INFERRED · 0% AMBIGUOUS · INFERRED: 19101 edges (avg confidence: 0.6)
- 5120 nodes · 27972 edges · 43 communities detected
- Extraction: 32% EXTRACTED · 68% INFERRED · 0% AMBIGUOUS · INFERRED: 19105 edges (avg confidence: 0.6)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
@@ -42,12 +42,16 @@
- [[_COMMUNITY_Community 30|Community 30]]
- [[_COMMUNITY_Community 31|Community 31]]
- [[_COMMUNITY_Community 32|Community 32]]
- [[_COMMUNITY_Community 33|Community 33]]
- [[_COMMUNITY_Community 34|Community 34]]
- [[_COMMUNITY_Community 35|Community 35]]
- [[_COMMUNITY_Community 36|Community 36]]
- [[_COMMUNITY_Community 37|Community 37]]
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 40|Community 40]]
- [[_COMMUNITY_Community 41|Community 41]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
## God Nodes (most connected - your core abstractions)
1. `success_response()` - 732 edges
@@ -77,201 +81,217 @@
### Community 0 - "Community 0"
Cohesion: 0.01
Nodes (966): create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post(), create_role_management() (+958 more)
Nodes (952): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+944 more)
### Community 1 - "Community 1"
Cohesion: 0.01
Nodes (736): get_role_menus(), generate_uuid(), 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() (+728 more)
Nodes (716): generate_uuid(), ApiRequestLogCRUD, delete(), get_multi_with_filters(), allocate_next_biz_no(), _format_biz_no(), _prefix_for(), 业务协议号自动生成:XBCC / JZCC + YYYYMMDD + 6 位序号 (+708 more)
### Community 2 - "Community 2"
Cohesion: 0.01
Nodes (626): attachment_download_url(), AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, dict_data_options(), DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody (+618 more)
Nodes (675): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+667 more)
### Community 3 - "Community 3"
Cohesion: 0.06
Nodes (500): 保险公司及险种价格管理 API(保险公司 + 开票信息 + 险种价格), Base, 按输注计划 ID 批量索引缴费记录(列表页展示用,不做关联 enrich), 输注计划创建时自动调用,生成 dfj 缴费记录, 关联查询申请单、患者、输注计划信息,附加到 dict, 将 BizMaterialUsage 行转换为字典(用于我的领用记录)。, 当前登录人的手动出库领用记录:领用人字段存昵称或用户 ID(与生产/质检一致)。, 获取当前用户的物料领用记录(手动出库记录) 筛选条件: - tenant_no = 当前用户租户 - source_type = 'm (+492 more)
Cohesion: 0.05
Nodes (615): BatchRefundFinanceSubmitBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API, 持久化协议子资源。 缴费(含明细校验)须在样本之前:明细校验失败时不得已占用样本编码。 各子表 CRUD 内部仍可能分段 commit,创建接, 与列表接口一致:按租户 + 角色数据权限判断是否可访问该协议单。, If mother info exists but no customerId, create a customer record and link it., RefundFinanceSubmitBody, Base, 细胞产品 CRUD(biz_cell_product) (+607 more)
### Community 4 - "Community 4"
Cohesion: 0.01
Nodes (342): _normalize_date_bound(), list_ethnics_for_select(), apply_data_scope(), format_date(), optional_date(), parse_date(), 将字符串 / date / datetime 转为 date 或 None, ApiRequestLogCRUD (+334 more)
Nodes (366): _normalize_date_bound(), complete_protocol_invoice_request(), create_collection_protocol(), delete_collection_protocol(), _draft_fields_from_body(), _ensure_customer_for_mother(), get_collection_protocol_detail(), _get_current_user_id() (+358 more)
### Community 5 - "Community 5"
Cohesion: 0.02
Nodes (267): _body_to_payload(), _get_current_user_id(), get_production_reception_by_sample_code(), get_production_reception_detail(), _get_tenant_no(), post_production_reception(), put_production_reception(), _resolve_reception_id() (+259 more)
Nodes (231): eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci(), build_void_type_label_map(), format_protocol_status_label() (+223 more)
### Community 6 - "Community 6"
Cohesion: 0.02
Nodes (139): get_designer_data(), _error_json(), lifespan(), 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误, 未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin, sqlalchemy_exception_handler(), unhandled_exception_handler(), BaseHTTPMiddleware (+131 more)
Nodes (200): _ancestor_link_from_cell_product_input(), _ancestor_sample_chain_link(), _apply_cell_product_status_change(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes(), create_cell_products_batch() (+192 more)
### Community 7 - "Community 7"
Cohesion: 0.02
Nodes (185): 截止日期:仅日期时扩到当天 23:59:59。, 发起前预览审批链(条件齐后解析最终路径与审批人)。, 兼容旧 GET:无 formData,含条件分支时多为待确定占位。, _app_to_dict(), _copied_app_name(), copy_app(), create_app(), _create_version() (+177 more)
Nodes (132): get_designer_data(), _error_json(), 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误, 未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin, sqlalchemy_exception_handler(), unhandled_exception_handler(), BaseHTTPMiddleware, ApiCryptoError (+124 more)
### Community 8 - "Community 8"
Cohesion: 0.02
Nodes (191): api_save_application(), get_protocol_nos_used_in_protocols(), _fmt_dt(), get_handover_by_schedule(), get_outbound_handover(), get_outbound_handover_view(), _handover_row_to_dict(), _handover_view_dict() (+183 more)
Nodes (174): 截止日期:仅日期时扩到当天 23:59:59。, 发起前预览审批链(条件齐后解析最终路径与审批人)。, 兼容旧 GET:无 formData,含条件分支时多为待确定占位。, _app_to_dict(), _copied_app_name(), copy_app(), create_app(), _create_version() (+166 more)
### Community 9 - "Community 9"
Cohesion: 0.08
Nodes (189): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+181 more)
Cohesion: 0.03
Nodes (148): _batch_line_to_dict(), _unused_amount(), _unused_line_to_dict(), _filter_material_type(), _get_configured_material(), get_formula(), _line_to_dict(), replace_formula() (+140 more)
### Community 10 - "Community 10"
Cohesion: 0.03
Nodes (141): get_next_cell_product_code(), _ancestor_link_from_cell_product_input(), _ancestor_sample_chain_link(), _apply_cell_product_status_change(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes() (+133 more)
Cohesion: 0.05
Nodes (113): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, list_storage_slot_stats(), OccupancyCreateBody (+105 more)
### Community 11 - "Community 11"
Cohesion: 0.05
Nodes (108): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+100 more)
Cohesion: 0.03
Nodes (93): _jwt_user_payload(), Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致), Web 端登录:账号为 sys_user.user_no,密码为 sys_user.password(bcrypt)。, refresh_token(), web_login(), web_login_rsa_public_key(), lifespan(), create_access_token() (+85 more)
### Community 12 - "Community 12"
Cohesion: 0.04
Nodes (91): get_user_by_id(), _jwt_user_payload(), Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致), Web 端登录:账号为 sys_user.user_no,密码为 sys_user.password(bcrypt)。, refresh_token(), web_login(), web_login_rsa_public_key(), create_access_token() (+83 more)
Cohesion: 0.08
Nodes (52): complete_application(), create_basic_experiment_sale_schedules(), create_infusion_plan(), create_schedule(), _create_schedule_products(), _format_yyyy_mm_dd(), _generate_application_no(), get_application() (+44 more)
### Community 13 - "Community 13"
Cohesion: 0.45
Nodes (71): BatchStockInBody, BatchStockInItem, BatchStockOutBody, BatchStockOutItem, ConsumableCreateBody, ConsumablePackCreateBody, ConsumablePackUpdateBody, ConsumableUpdateBody (+63 more)
Cohesion: 0.11
Nodes (39): _amount_for_row(), _batch_map(), deduct_for_task(), _deduct_task_usage_legacy_batch(), _display_remark(), _fmt_date_val(), _linked_qc_task_no_map(), list_linked_task_usages() (+31 more)
### Community 14 - "Community 14"
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 15 - "Community 15"
Cohesion: 0.16
Nodes (22): _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), get_material_entity(), get_my_usages(), _is_enabled_status() (+14 more)
### Community 16 - "Community 16"
Cohesion: 0.21
Nodes (19): _consumable_row_to_dict(), create_process(), _create_sub_consumable(), _create_sub_data_collection(), _create_sub_output(), _create_sub_reagent(), _data_collection_row_to_dict(), get_process() (+11 more)
### Community 16 - "Community 16"
Cohesion: 0.2
Nodes (19): _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), get_material_entity(), get_my_usages(), _is_enabled_status() (+11 more)
### Community 17 - "Community 17"
Cohesion: 0.27
Nodes (12): create_equipment(), _dec(), equipment_code_exists(), equipment_is_referenced(), get_equipment(), list_equipments(), _norm_status(), _parse_date() (+4 more)
Cohesion: 0.21
Nodes (16): _field_label(), _is_non_empty_str(), _is_required(), _is_valid_receive_account_item(), normalize_account_fields(), _pick(), _pick_order_num(), _pick_str() (+8 more)
### Community 18 - "Community 18"
Cohesion: 0.27
Nodes (12): _field_label(), _is_empty(), _is_required(), _parse_money(), OA 表单设计器:金额控件 form_data 校验, 校验 form_data 中金额控件的值格式,返回中文错误列表(空表示通过)。, 解析金额值。成功返回 (number, None);失败返回 (None, error_key)。, _rule_props() (+4 more)
Nodes (12): create_equipment(), _dec(), equipment_code_exists(), equipment_is_referenced(), get_equipment(), list_equipments(), _norm_status(), _parse_date() (+4 more)
### Community 19 - "Community 19"
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)
Cohesion: 0.27
Nodes (11): _accept_conclusion_label(), _base_query(), _ensure_notification(), _fmt_dt(), generate_sms_content(), list_notifications(), _normalize_date_bound(), resolve_notification() (+3 more)
### Community 20 - "Community 20"
Cohesion: 0.24
Nodes (11): deduct_for_step(), _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), 耗材变动记录 CRUD(biz_consumable_stock_log), 撤销步骤此前 step_save 扣减,便于重新填报。, 扣减耗材库存并生成变动记录。调用方控制事务,本函数不 commit。, _resolve_receiver_purpose() (+3 more)
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import Wech, 发送模板消息 Args: openid: 用户openid templ, send_delivery_notice(), send_delivery_warning(), send_order_status(), send_payment_success(), send_refund_result(), send_urge_notification() (+1 more)
### Community 21 - "Community 21"
Cohesion: 0.23
Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
### Community 22 - "Community 22"
Cohesion: 0.27
Nodes (12): _field_label(), _is_empty(), _is_required(), _parse_money(), OA 表单设计器:金额控件 form_data 校验, 校验 form_data 中金额控件的值格式,返回中文错误列表(空表示通过)。, 解析金额值。成功返回 (number, None);失败返回 (None, error_key)。, _rule_props() (+4 more)
### 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 24 - "Community 24"
Cohesion: 0.24
Nodes (11): deduct_for_step(), _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), 耗材变动记录 CRUD(biz_consumable_stock_log), 撤销步骤此前 step_save 扣减,便于重新填报。, 扣减耗材库存并生成变动记录。调用方控制事务,本函数不 commit。, _resolve_receiver_purpose() (+3 more)
### Community 25 - "Community 25"
Cohesion: 0.31
Nodes (10): create_account(), _filtered_query(), get_account(), list_accounts(), list_options(), OA 收款账户 CRUD(oa_receive_account), row_to_dict(), soft_delete_account() (+2 more)
### Community 22 - "Community 22"
### Community 26 - "Community 26"
Cohesion: 0.31
Nodes (10): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), get_dept(), list_depts(), list_depts_tree(), 保留匹配节点及其全部上级,供关键词检索后仍能正确组树。, _row_to_dict() (+2 more)
### Community 23 - "Community 23"
Cohesion: 0.33
Nodes (8): _build_tree(), _cascade_soft_delete(), get_menu(), list_menus(), list_menus_tree(), _row_to_dict(), soft_delete_menu(), update_menu()
### Community 24 - "Community 24"
### Community 27 - "Community 27"
Cohesion: 0.29
Nodes (2): BaseModel, SoftDeleteModel
### Community 25 - "Community 25"
### Community 28 - "Community 28"
Cohesion: 0.32
Nodes (5): create_leave(), get_leave(), list_leaves(), _row_to_dict(), soft_delete_leave()
### Community 29 - "Community 29"
Cohesion: 0.38
Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 26 - "Community 26"
### Community 30 - "Community 30"
Cohesion: 0.5
Nodes (3): BaseSettings, Config, Settings
### Community 27 - "Community 27"
### Community 31 - "Community 31"
Cohesion: 0.5
Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
### Community 28 - "Community 28"
### Community 32 - "Community 32"
Cohesion: 0.67
Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,5 个一级菜单分组)
### Community 29 - "Community 29"
### Community 33 - "Community 33"
Cohesion: 0.67
Nodes (1): 转正套件:入职日 + 试用期月数 → 建议转正日(YYYY-MM-DD)。
### Community 30 - "Community 30"
### Community 34 - "Community 34"
Cohesion: 1.0
Nodes (1): 质检物料金额查看授权:专用角色与菜单权限常量。
### Community 31 - "Community 31"
### Community 35 - "Community 35"
Cohesion: 1.0
Nodes (1): 请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
### Community 32 - "Community 32"
### Community 36 - "Community 36"
Cohesion: 1.0
Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
### Community 35 - "Community 35"
### Community 39 - "Community 39"
Cohesion: 1.0
Nodes (1): 发送订单状态通知 Args: openid: 用户openid ord
### Community 36 - "Community 36"
### Community 40 - "Community 40"
Cohesion: 1.0
Nodes (1): 发送支付成功通知 Args: openid: 用户openid ord
### Community 37 - "Community 37"
### Community 41 - "Community 41"
Cohesion: 1.0
Nodes (1): 发送配送通知 Args: openid: 配送员openid task
### Community 38 - "Community 38"
### Community 42 - "Community 42"
Cohesion: 1.0
Nodes (1): 发送配送时效预警 Args: openid: 配送员openid ta
### Community 39 - "Community 39"
### Community 43 - "Community 43"
Cohesion: 1.0
Nodes (1): 发送退款结果通知 Args: openid: 用户openid ord
### Community 40 - "Community 40"
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (1): 发送催单通知给配送员 Args: deliver_openid: 配送员openid
## Knowledge Gaps
- **163 isolated node(s):** `刷新会话 TTL(refreshToken 续期;已登录用户每次 API 校验通过后滑动续期)`, `写入 refreshToken(用于 one-time 使用/吊销)`, `根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期)`, `登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。`, `加载 RSA 密钥对:优先环境变量,否则使用内置固定默认密钥。` (+158 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **Thin community `Community 24`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
- **Thin community `Community 27`** (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 27`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
- **Thin community `Community 31`** (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 28`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,5 个一级菜单分组)`
- **Thin community `Community 32`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,5 个一级菜单分组)`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 29`** (3 nodes): `add_months_ymd()`, `oa_confirmation_date.py`, `转正套件:入职日 + 试用期月数 → 建议转正日(YYYY-MM-DD)。`
- **Thin community `Community 33`** (3 nodes): `add_months_ymd()`, `oa_confirmation_date.py`, `转正套件:入职日 + 试用期月数 → 建议转正日(YYYY-MM-DD)。`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 30`** (2 nodes): `qc_material_amount_auth_constants.py`, `质检物料金额查看授权:专用角色与菜单权限常量。`
- **Thin community `Community 34`** (2 nodes): `qc_material_amount_auth_constants.py`, `质检物料金额查看授权:专用角色与菜单权限常量。`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 31`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
- **Thin community `Community 35`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 32`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
- **Thin community `Community 36`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 35`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
- **Thin community `Community 39`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 36`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
- **Thin community `Community 40`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 37`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
- **Thin community `Community 41`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 38`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
- **Thin community `Community 42`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 39`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
- **Thin community `Community 43`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 40`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
- **Thin community `Community 44`** (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 `SysUser` connect `Community 2` to `Community 0`, `Community 1`, `Community 3`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 19`, `Community 20`?**
- **Why does `SysUser` connect `Community 2` to `Community 0`, `Community 1`, `Community 3`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 13`, `Community 15`, `Community 23`, `Community 24`?**
_High betweenness centrality (0.112) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 8`, `Community 10`, `Community 12`, `Community 28`?**
- **Why does `success_response()` connect `Community 0` to `Community 32`, `Community 2`, `Community 4`, `Community 7`, `Community 10`, `Community 11`?**
_High betweenness centrality (0.048) - this node is a cross-community bridge._
- **Why does `generate_uuid()` connect `Community 1` to `Community 0`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 15`, `Community 16`, `Community 17`, `Community 19`, `Community 20`, `Community 21`?**
_High betweenness centrality (0.048) - this node is a cross-community bridge._
- **Are the 859 inferred relationships involving `str` (e.g. with `unhandled_exception_handler()` and `get_current_user_by_token()`) actually correct?**
_`str` has 859 INFERRED edges - model-reasoned connections that need verification._
- **Why does `generate_uuid()` connect `Community 1` to `Community 0`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 13`, `Community 15`, `Community 16`, `Community 18`, `Community 19`, `Community 23`, `Community 24`, `Community 25`, `Community 28`?**
_High betweenness centrality (0.047) - this node is a cross-community bridge._
- **Are the 861 inferred relationships involving `str` (e.g. with `unhandled_exception_handler()` and `get_current_user_by_token()`) actually correct?**
_`str` has 861 INFERRED edges - model-reasoned connections that need verification._
- **Are the 731 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 731 INFERRED edges - model-reasoned connections that need verification._
- **Are the 604 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
File diff suppressed because it is too large. Load diff
+5 -5
View File
@@ -164,7 +164,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol_no.py": 1779882001.753651,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_handover.py": 1780455574.0993364,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_facility.py": 1785832360.7565567,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/oa_instance_draft.py": 1785987242.9388554,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/oa_instance_draft.py": 1785990690.2179956,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception_lab_code.py": 1783308340.5854337,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py": 1781747645.1762104,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_outbound_status_sync.py": 1781595840.6955194,
@@ -197,7 +197,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pre_transit_sample.py": 1782204426.7965167,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc_sms_notification.py": 1780326875.7886882,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/research_donation_sample_collection.py": 1780457788.2998126,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/oa_approval.py": 1785989474.482102,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/oa_approval.py": 1785990693.9799302,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py": 1785213144.2881503,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/menu.py": 1785836159.1492305,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_delivery.py": 1779655584.820777,
@@ -215,14 +215,14 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/api/protocol_sample_collection.py": 1780457788.2093296,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/leave.py": 1779266168.8693042,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/clinical_payment.py": 1781750841.074568,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_engine.py": 1785989236.837867,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_engine.py": 1786005410.2825754,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/workflow_callback.py": 1778727966.7277644,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/qc_work_order_fee_summary.py": 1783329884.6125586,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/storage_facility_code.py": 1785213139.8646047,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_person_select.py": 1785401156.2563787,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/qc_work_order_conclusion.py": 1785206750.2532814,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_dept_select.py": 1785401170.1753807,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_publish.py": 1785835566.6835513,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_dept_select.py": 1786000695.5043027,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_publish.py": 1786001976.196836,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/workflow_engine.py": 1785909957.8243756,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/oa_confirmation_date.py": 1785403063.141215,
"/Users/wuzilong/work/00code/zkxw/backend/app/services/web_auth_roles.py": 1785909942.9479194,
+140
View File
@@ -3,10 +3,12 @@ import unittest
from unittest.mock import MagicMock, patch
from app.services.oa_engine import (
INITIATOR_CONDITION_FIELD,
_FLOW_PREVIEW_PENDING_MSG,
_collect_condition_fields,
_condition_fields_ready,
_form_value_present,
_iter_resolved_path_nodes,
_walk_preview_nodes,
)
@@ -93,6 +95,61 @@ class TestCollectConditionFields(unittest.TestCase):
}
self.assertEqual(_collect_condition_fields(root), ["days", "leaveType"])
def test_initiator_system_field_not_gated_by_form_data(self):
"""系统伪字段 __initiator__ 不依赖 formData,空表单也应 resolved 门闩通过。"""
root = {
"id": "s",
"type": "start",
"child": {
"id": "c1",
"type": "condition",
"conditionGroups": [
{
"name": "条件1",
"rules": [
{
"field": INITIATOR_CONDITION_FIELD,
"op": "contains",
"value": ["u1"],
}
],
"child": {"id": "e1", "type": "end"},
},
{
"name": "默认",
"isDefault": True,
"rules": [],
"child": {"id": "e2", "type": "end"},
},
],
},
}
self.assertEqual(_collect_condition_fields(root), [])
self.assertTrue(_condition_fields_ready(root, {}))
def test_initiator_plus_form_field_still_gates_form(self):
root = {
"type": "condition",
"conditionGroups": [
{
"name": "条件1",
"rules": [
{
"field": INITIATOR_CONDITION_FIELD,
"op": "contains",
"value": ["u1"],
},
{"field": "days", "op": ">", "value": 3},
],
"child": {},
},
{"name": "默认", "isDefault": True, "rules": []},
],
}
self.assertEqual(_collect_condition_fields(root), ["days"])
self.assertFalse(_condition_fields_ready(root, {}))
self.assertTrue(_condition_fields_ready(root, {"days": 5}))
class TestWalkPreviewResolvedPath(unittest.TestCase):
def test_hit_condition1(self):
@@ -145,6 +202,89 @@ class TestWalkPreviewResolvedPath(unittest.TestCase):
def test_pending_message_constant(self):
self.assertEqual(_FLOW_PREVIEW_PENDING_MSG, "必填信息填写后,流程将自动显示")
def test_merge_after_condition_skips_branch_end(self):
"""条件分支叶子 end 后若有汇合主链,预览只保留真正的结束节点。"""
root = {
"id": "s",
"type": "start",
"name": "发起人",
"child": {
"id": "c1",
"type": "condition",
"conditionGroups": [
{
"name": "条件1",
"rules": [{"field": "days", "op": ">", "value": 3}],
"child": {
"id": "a1",
"type": "approval",
"name": "领导会签",
"approverConfig": {
"assigneeType": "users",
"userIds": ["u2"],
"signMode": "and",
},
"child": {"id": "e_branch", "type": "end", "name": "结束"},
},
},
{
"name": "默认",
"isDefault": True,
"rules": [],
"child": {"id": "e_def", "type": "end", "name": "结束"},
},
],
"child": {
"id": "cc1",
"type": "cc",
"name": "抄送人",
"approverConfig": {
"assigneeTypes": ["initiator_select"],
"assigneeType": "initiator_select",
},
"child": {"id": "e_final", "type": "end", "name": "结束"},
},
},
}
db = MagicMock()
steps = []
with patch(
"app.services.oa_engine.resolve_assignees", return_value=(["u2"], {})
), patch(
"app.services.oa_engine.resolve_cc_assignees", return_value=([], {})
), patch(
"app.services.oa_engine._preview_people",
side_effect=lambda _db, ids: [{"id": i, "nickName": i} for i in ids],
), patch(
"app.services.oa_engine._assignee_meta", return_value="指定成员"
), patch(
"app.services.oa_engine._assignee_meta_for_cc", return_value="发起人自选"
):
ok = _walk_preview_nodes(
db,
node=root,
tenant_no="t1",
initiator_user_id="init",
initiator_dept_id=None,
advanced={},
initiator_select_by_node=None,
form_data={"days": 5},
steps=steps,
)
self.assertTrue(ok)
names = [s["name"] for s in steps]
types = [s["type"] for s in steps]
self.assertEqual(names, ["发起人", "领导会签", "抄送人", "结束"])
self.assertEqual(types.count("end"), 1)
self.assertEqual(steps[-1]["id"], "e_final")
path = _iter_resolved_path_nodes(root, {"days": 5}, initiator_user_id="init")
self.assertIsNotNone(path)
path_ids = [n.get("id") for n in path]
self.assertNotIn("e_branch", path_ids)
self.assertIn("e_final", path_ids)
self.assertEqual(sum(1 for n in path if n.get("type") == "end"), 1)
if __name__ == "__main__":
unittest.main()
@@ -175,7 +175,7 @@ Run: `cd web-admin && pnpm exec vue-tsc --noEmit 2>&1 | head -80`
/>
```
- [ ] **Step 2: 精简 script**
- [x] **Step 2: 精简 script**
保留:模板列表、分组、搜索、`displayGroups`、`onPick` 改为调用 dialog、`onMounted` 深链。
@@ -233,13 +233,13 @@ onMounted(async () => {
})
```
- [ ] **Step 3: 手工冒烟(发起页)**
- [x] **Step 3: 手工冒烟(发起页)** — 待本地手测
1. 打开 `/#/system-manage/oa-approval/start`,选模板 → 弹窗与改造前一致。
2. 暂存草稿 → 关闭 → 草稿箱可见。
3. 深链带 `draftId` 仍能打开回显(兼容)。
- [ ] **Step 4: Commit**
- [x] **Step 4: Commit** — `cf009de5`
```bash
git add web-admin/src/views/oa-approval/start/index.vue
@@ -257,7 +257,7 @@ EOF
**Files:**
- Modify: `web-admin/src/views/oa-approval/drafts/index.vue`
- [ ] **Step 1: 模板挂载弹窗**
- [x] **Step 1: 模板挂载弹窗**
在 `</section>` 后、`</div>` 前增加:
@@ -269,7 +269,7 @@ EOF
/>
```
- [ ] **Step 2: 改 script**
- [x] **Step 2: 改 script**
```ts
import OaStartFormDialog from '@/components/oa-approval/OaStartFormDialog.vue'
@@ -330,7 +330,7 @@ async function handleSubmit(row: any) {
补充:`import { ElMessage } from 'element-plus'`(若打开失败提示需要;项目若 auto-import 则勿重复)。
- [ ] **Step 3: 手工验收(对照 spec §7)**
- [x] **Step 3: 手工验收(对照 spec §7)** — 待本地手测
1. 草稿箱「编辑」:URL 仍为 drafts;弹窗回显。
2. 弹窗「保存草稿」:列表刷新,不跳转。
@@ -338,7 +338,7 @@ async function handleSubmit(row: any) {
4. 列表「提交审批」失败:打开弹窗而非跳 start。
5. 发起页选模板发起仍正常。
- [ ] **Step 4: Commit**
- [x] **Step 4: Commit** — `3cf2f68b`
```bash
git add web-admin/src/views/oa-approval/drafts/index.vue
@@ -349,7 +349,7 @@ EOF
)"
```
- [ ] **Step 5: 更新知识图谱**
- [x] **Step 5: 更新知识图谱** — `e93edc77`
```bash
./scripts/update-graph.sh frontend
+5 -2
View File
@@ -148,8 +148,11 @@ analysis = {
Path('graphify-out/.graphify_analysis.json').write_text(json.dumps(analysis, indent=2))
Path('graphify-out/.graphify_labels.json').write_text(json.dumps({str(k): v for k, v in labels.items()}))
# Generate HTML
to_html(G, communities, 'graphify-out/graph.html', community_labels=labels or None)
# Generate HTML(节点过多时跳过可视化,仍保存 json/report)
try:
to_html(G, communities, 'graphify-out/graph.html', community_labels=labels or None)
except ValueError as e:
print(f'[graphify] skip HTML viz: {e}')
# Save manifest
from graphify.detect import save_manifest
File diff suppressed because it is too large. Load diff
+110 -62
View File
@@ -9140,56 +9140,70 @@
"label": "opsForFieldType()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L35"
"source_location": "L37"
},
{
"id": "oa_approval_oa_condition_fields_walkrules",
"label": "walkRules()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L56"
"source_location": "L65"
},
{
"id": "oa_approval_oa_condition_fields_flattenformrules",
"label": "flattenFormRules()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L66"
"source_location": "L75"
},
{
"id": "oa_approval_oa_condition_fields_listconditioncandidates",
"label": "listConditionCandidates()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L81"
"source_location": "L90"
},
{
"id": "oa_approval_oa_condition_fields_collectconditionreferencedfields",
"label": "collectConditionReferencedFields()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L112"
"source_location": "L121"
},
{
"id": "oa_approval_oa_condition_fields_collectformconditionreferencedfields",
"label": "collectFormConditionReferencedFields()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L130"
"source_location": "L139"
},
{
"id": "oa_approval_oa_condition_fields_normalizeschemaconditionrequired",
"label": "normalizeSchemaConditionRequired()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L137"
"source_location": "L146"
},
{
"id": "oa_approval_oa_condition_fields_formatconditionvaluetext",
"label": "formatConditionValueText()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L191"
},
{
"id": "oa_approval_oa_condition_fields_formatconditionpreviewlines",
"label": "formatConditionPreviewLines()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L227"
},
{
"id": "oa_approval_oa_condition_fields_formatconditionpreview",
"label": "formatConditionPreview()",
"file_type": "code",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L175"
"source_location": "L249"
},
{
"id": "components_oa_approval_oapersonselect_vue",
@@ -9563,32 +9577,39 @@
"source_location": "L1"
},
{
"id": "flow_tree_flowbranch_branchtitle",
"label": "branchTitle()",
"id": "flow_tree_flowbranch_branchname",
"label": "branchName()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L160"
"source_location": "L182"
},
{
"id": "flow_tree_flowbranch_branchconditionlines",
"label": "branchConditionLines()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L187"
},
{
"id": "flow_tree_flowbranch_nodesummary",
"label": "nodeSummary()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L167"
"source_location": "L196"
},
{
"id": "flow_tree_flowbranch_onadd",
"label": "onAdd()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L176"
"source_location": "L205"
},
{
"id": "flow_tree_flowbranch_onaddingroup",
"label": "onAddInGroup()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L182"
"source_location": "L211"
},
{
"id": "components_oa_approval_flow_tree_conditionruleeditor_vue",
@@ -9602,7 +9623,7 @@
"label": "if()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L189"
"source_location": "L224"
},
{
"id": "components_oa_approval_flow_tree_flowdesigner_vue",
@@ -9616,7 +9637,7 @@
"label": "if()",
"file_type": "code",
"source_file": "components/oa-approval/flow-tree/FlowDesigner.vue",
"source_location": "L567"
"source_location": "L633"
},
{
"id": "components_oa_approval_flow_tree_types_ts",
@@ -41746,7 +41767,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L35",
"source_location": "L37",
"weight": 1.0
},
{
@@ -41755,7 +41776,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L56",
"source_location": "L65",
"weight": 1.0
},
{
@@ -41764,7 +41785,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L66",
"source_location": "L75",
"weight": 1.0
},
{
@@ -41773,7 +41794,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L81",
"source_location": "L90",
"weight": 1.0
},
{
@@ -41782,7 +41803,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L112",
"source_location": "L121",
"weight": 1.0
},
{
@@ -41791,7 +41812,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L130",
"source_location": "L139",
"weight": 1.0
},
{
@@ -41800,7 +41821,25 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L137",
"source_location": "L146",
"weight": 1.0
},
{
"source": "components_oa_approval_oa_condition_fields_ts",
"target": "oa_approval_oa_condition_fields_formatconditionvaluetext",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L191",
"weight": 1.0
},
{
"source": "components_oa_approval_oa_condition_fields_ts",
"target": "oa_approval_oa_condition_fields_formatconditionpreviewlines",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L227",
"weight": 1.0
},
{
@@ -41809,7 +41848,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L175",
"source_location": "L249",
"weight": 1.0
},
{
@@ -41818,7 +41857,7 @@
"relation": "calls",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L70",
"source_location": "L79",
"weight": 1.0
},
{
@@ -41827,7 +41866,7 @@
"relation": "calls",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L83",
"source_location": "L92",
"weight": 1.0
},
{
@@ -41836,7 +41875,16 @@
"relation": "calls",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L131",
"source_location": "L140",
"weight": 1.0
},
{
"source": "oa_approval_oa_condition_fields_formatconditionpreview",
"target": "oa_approval_oa_condition_fields_formatconditionpreviewlines",
"relation": "calls",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L254",
"weight": 1.0
},
{
@@ -42430,7 +42478,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L119",
"source_location": "L132",
"weight": 1.0
},
{
@@ -42439,7 +42487,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L123",
"source_location": "L137",
"weight": 1.0
},
{
@@ -42448,7 +42496,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L124",
"source_location": "L138",
"weight": 1.0
},
{
@@ -42457,16 +42505,25 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L126",
"source_location": "L140",
"weight": 1.0
},
{
"source": "components_oa_approval_flow_tree_flowbranch_vue",
"target": "flow_tree_flowbranch_branchtitle",
"target": "flow_tree_flowbranch_branchname",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L160",
"source_location": "L182",
"weight": 1.0
},
{
"source": "components_oa_approval_flow_tree_flowbranch_vue",
"target": "flow_tree_flowbranch_branchconditionlines",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L187",
"weight": 1.0
},
{
@@ -42475,7 +42532,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L167",
"source_location": "L196",
"weight": 1.0
},
{
@@ -42484,7 +42541,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L176",
"source_location": "L205",
"weight": 1.0
},
{
@@ -42493,7 +42550,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L182",
"source_location": "L211",
"weight": 1.0
},
{
@@ -42502,7 +42559,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L134",
"source_location": "L152",
"weight": 1.0
},
{
@@ -42511,7 +42568,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L135",
"source_location": "L153",
"weight": 1.0
},
{
@@ -42520,7 +42577,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L136",
"source_location": "L154",
"weight": 1.0
},
{
@@ -42529,7 +42586,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L137",
"source_location": "L155",
"weight": 1.0
},
{
@@ -42538,7 +42595,7 @@
"relation": "imports_from",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L142",
"source_location": "L160",
"weight": 1.0
},
{
@@ -42547,7 +42604,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/ConditionRuleEditor.vue",
"source_location": "L189",
"source_location": "L224",
"weight": 1.0
},
{
@@ -42556,16 +42613,7 @@
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowDesigner.vue",
"source_location": "L567",
"weight": 1.0
},
{
"source": "components_oa_approval_flow_tree_flowdesigner_vue",
"target": "flow_tree_flowdesigner_if",
"relation": "contains",
"confidence": "EXTRACTED",
"source_file": "components/oa-approval/flow-tree/FlowDesigner.vue",
"source_location": "L629",
"source_location": "L633",
"weight": 1.0
},
{
@@ -71726,7 +71774,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L60",
"source_location": "L69",
"weight": 1.0
},
{
@@ -71736,7 +71784,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L101",
"source_location": "L110",
"weight": 1.0
},
{
@@ -71746,7 +71794,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L125",
"source_location": "L134",
"weight": 1.0
},
{
@@ -71756,7 +71804,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/oa-condition-fields.ts",
"source_location": "L168",
"source_location": "L177",
"weight": 1.0
},
{
@@ -71980,13 +72028,13 @@
"weight": 1.0
},
{
"source": "flow_tree_flowbranch_branchtitle",
"target": "oa_approval_oa_condition_fields_formatconditionpreview",
"source": "flow_tree_flowbranch_branchconditionlines",
"target": "oa_approval_oa_condition_fields_formatconditionpreviewlines",
"relation": "calls",
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L162",
"source_location": "L189",
"weight": 1.0
},
{
@@ -71996,7 +72044,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L173",
"source_location": "L202",
"weight": 1.0
},
{
@@ -72006,7 +72054,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L178",
"source_location": "L207",
"weight": 1.0
},
{
@@ -72016,7 +72064,7 @@
"confidence": "INFERRED",
"confidence_score": 0.8,
"source_file": "components/oa-approval/flow-tree/FlowBranch.vue",
"source_location": "L184",
"source_location": "L213",
"weight": 1.0
},
{
+113 -134
View File
@@ -1,10 +1,10 @@
# Graph Report - src (2026-08-06)
## Corpus Check
- Large corpus: 961 files · ~626,054 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
- Large corpus: 961 files · ~626,784 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
## Summary
- 3368 nodes · 4772 edges · 69 communities detected
- 3371 nodes · 4776 edges · 66 communities detected
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 1061 edges (avg confidence: 0.8)
- Token cost: 0 input · 0 output
@@ -50,8 +50,8 @@
- [[_COMMUNITY_Community 38|Community 38]]
- [[_COMMUNITY_Community 39|Community 39]]
- [[_COMMUNITY_Community 40|Community 40]]
- [[_COMMUNITY_Community 41|Community 41]]
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 49|Community 49]]
@@ -64,20 +64,17 @@
- [[_COMMUNITY_Community 57|Community 57]]
- [[_COMMUNITY_Community 58|Community 58]]
- [[_COMMUNITY_Community 60|Community 60]]
- [[_COMMUNITY_Community 61|Community 61]]
- [[_COMMUNITY_Community 64|Community 64]]
- [[_COMMUNITY_Community 66|Community 66]]
- [[_COMMUNITY_Community 67|Community 67]]
- [[_COMMUNITY_Community 63|Community 63]]
- [[_COMMUNITY_Community 69|Community 69]]
- [[_COMMUNITY_Community 72|Community 72]]
- [[_COMMUNITY_Community 73|Community 73]]
- [[_COMMUNITY_Community 74|Community 74]]
- [[_COMMUNITY_Community 75|Community 75]]
- [[_COMMUNITY_Community 76|Community 76]]
- [[_COMMUNITY_Community 78|Community 78]]
- [[_COMMUNITY_Community 79|Community 79]]
- [[_COMMUNITY_Community 80|Community 80]]
- [[_COMMUNITY_Community 83|Community 83]]
- [[_COMMUNITY_Community 92|Community 92]]
- [[_COMMUNITY_Community 94|Community 94]]
- [[_COMMUNITY_Community 95|Community 95]]
- [[_COMMUNITY_Community 97|Community 97]]
- [[_COMMUNITY_Community 98|Community 98]]
## God Nodes (most connected - your core abstractions)
1. `get()` - 305 edges
@@ -92,10 +89,10 @@
10. `MenuProcessor` - 16 edges
## Surprising Connections (you probably didn't know these)
- `handleBatchDelete()` --calls--> `withFullscreenLoading()` [INFERRED]
views/basic-info/customer/index.vue → utils/fullscreen-loading.ts
- `formatReceiveAccountLine()` --calls--> `push()` [INFERRED]
utils/oa-receive-account-value.ts → views/operations/storage-facility/index.vue
- `dash()` --calls--> `formatDisplayOrDash()` [INFERRED]
components/business/infusion-schedule-outbound-chain-view/index.vue → utils/datetime-display.ts
- `dash()` --calls--> `formatDisplayOrDash()` [INFERRED]
components/business/clinical-schedule-payment-detail/index.vue → utils/datetime-display.ts
- `findTreeSelectShortLabel()` --calls--> `walk()` [INFERRED]
@@ -107,176 +104,176 @@
### Community 0 - "Community 0"
Cohesion: 0.01
Nodes (185): fetchAccessLogList(), fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchChannelAccount() (+177 more)
Nodes (176): fetchAccessLogList(), fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchChannelAccount() (+168 more)
### Community 1 - "Community 1"
Cohesion: 0.03
Nodes (90): batchSavePilotCheckup(), deletePilotCheckupActualItem(), fetchCheckupInstitutionList(), fetchCheckupInstitutionPackageDetail(), fetchCheckupInstitutionPackages(), fetchPilotCheckupDetail(), fetchPilotCheckupList(), markPilotCheckupChecked() (+82 more)
Cohesion: 0.02
Nodes (94): batchSavePilotCheckup(), deletePilotCheckupActualItem(), fetchCheckupInstitutionList(), fetchCheckupInstitutionPackageDetail(), fetchCheckupInstitutionPackages(), fetchPilotCheckupDetail(), fetchPilotCheckupList(), markPilotCheckupChecked() (+86 more)
### Community 2 - "Community 2"
Cohesion: 0.02
Nodes (74): fetchUpdatePostBoundRoles(), fetchUploadAttachment(), fetchOaInstanceDetail(), fetchOaTasks(), FireworkSystem, printRow(), handleReportUpload(), handleReportUpload() (+66 more)
Nodes (72): fetchUpdatePostBoundRoles(), fetchUploadAttachment(), fetchOaTasks(), FireworkSystem, handleReportUpload(), handleReportUpload(), walk(), load() (+64 more)
### Community 3 - "Community 3"
Cohesion: 0.03
Nodes (79): fetchEthnicList(), formatNowDatetime(), applyDonationBundleToForm(), createEmptyTransport(), ensureEthnicOptionInList(), handleOpenForAdd(), if(), loadEthnicOptions() (+71 more)
Nodes (78): fetchEthnicList(), applyDonationBundleToForm(), createEmptyTransport(), ensureEthnicOptionInList(), handleOpenForAdd(), if(), loadEthnicOptions(), normalizeSampleRow() (+70 more)
### Community 4 - "Community 4"
Cohesion: 0.03
Nodes (70): buildInboundBasicSection(), buildInboundCellStorageViewSections(), buildInboundResearchDonationViewSections(), buildReceptionSection(), buildTransportSection(), resolveInboundProtocolStatus(), buildBaseFields(), buildInboundBasicSection() (+62 more)
Nodes (64): fetchBatchDeleteOaReceiveAccounts(), fetchBatchMarkOaCcTasksRead(), fetchCreateOaReceiveAccount(), fetchDeleteOaReceiveAccount(), fetchMarkOaCcTaskRead(), fetchOaAppDraft(), fetchOaAppList(), fetchOaCcUnreadCount() (+56 more)
### Community 5 - "Community 5"
Cohesion: 0.03
Nodes (41): fetchGetMenuList(), useSettingsHandlers(), useSettingsPanel(), useSettingsState(), ComponentLoader, IframeRouteManager, MenuProcessor, RouteRegistry (+33 more)
Nodes (34): fetchGetMenuList(), ComponentLoader, IframeRouteManager, MenuProcessor, RoutePermissionValidator, RouteRegistry, RouteTransformer, useAppMode() (+26 more)
### Community 6 - "Community 6"
Cohesion: 0.03
Nodes (60): fetchBatchDeleteOaReceiveAccounts(), fetchBatchMarkOaCcTasksRead(), fetchCreateOaReceiveAccount(), fetchDeleteOaReceiveAccount(), fetchMarkOaCcTaskRead(), fetchOaAppDraft(), fetchOaAppList(), fetchOaCcUnreadCount() (+52 more)
Nodes (63): fetchCheckupInstitutionInvoices(), fetchCheckupInstitutionProjects(), fetchCreateCheckupInstitution(), fetchCreateCheckupInstitutionInvoice(), fetchCreateCheckupInstitutionProject(), fetchUpdateCheckupInstitution(), fetchUpdateCheckupInstitutionInvoice(), fetchUpdateCheckupInstitutionProject() (+55 more)
### Community 7 - "Community 7"
Cohesion: 0.03
Nodes (68): fetchCellSampleTypeList(), fetchCheckupInstitutionInvoices(), fetchCheckupInstitutionProjects(), fetchCreateCellSampleType(), fetchCreateCheckupInstitution(), fetchCreateCheckupInstitutionInvoice(), fetchCreateCheckupInstitutionProject(), fetchDeleteCellSampleType() (+60 more)
Nodes (47): handleBlur(), handleFocus(), handleInput(), fetchClinicalPaymentDetail(), fetchClinicalPayments(), fetchClinicalReceiptConfirmed(), fetchClinicalReceiptPending(), fetchClinicalRefundConfirmed() (+39 more)
### Community 8 - "Community 8"
Cohesion: 0.03
Nodes (48): handleBlur(), handleFocus(), handleInput(), fetchClinicalPaymentDetail(), fetchClinicalPayments(), fetchClinicalReceiptConfirmed(), fetchClinicalReceiptPending(), fetchClinicalRefundConfirmed() (+40 more)
Nodes (57): buildInboundBasicSection(), buildInboundCellStorageViewSections(), buildInboundResearchDonationViewSections(), buildReceptionSection(), buildTemporaryViewSections(), buildTransportSection(), resolveInboundProtocolStatus(), buildInsertedSiblingCard() (+49 more)
### Community 9 - "Community 9"
Cohesion: 0.03
Nodes (54): RoutePermissionValidator, if(), nodeSummary(), createDefaultFlow(), createEndNode(), createNode(), ensureFlowRoot(), newId() (+46 more)
Cohesion: 0.02
Nodes (29): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllConsumableStockLogs(), fetchAllEquipments(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents() (+21 more)
### Community 10 - "Community 10"
Cohesion: 0.03
Nodes (52): buildTemporaryViewSections(), buildInsertedSiblingCard(), resolveShowProtocolPaymentAtGroup(), appendTaskResultSections(), batchTasksForPanelSlot(), buildConfiguredOnlySection(), for(), for() (+44 more)
Nodes (54): fetchMyProductionTasks(), fetchMyQcTaskList(), fetchQcTaskDetail(), fetchQcTaskList(), fetchMineTasksForWorkOrders(), useInboundSiblingNavigation(), shouldApplyTriggerSourceFilter(), useQcWorkOrderTabPage() (+46 more)
### Community 11 - "Community 11"
Cohesion: 0.03
Nodes (56): fetchMyProductionTasks(), fetchMyQcTaskList(), fetchQcTaskDetail(), fetchQcTaskList(), fetchMineTasksForWorkOrders(), useInboundSiblingNavigation(), shouldApplyTriggerSourceFilter(), useQcWorkOrderTabPage() (+48 more)
Nodes (49): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), useCeremony(), useTheme(), if(), nodeSummary(), createDefaultFlow() (+41 more)
### Community 12 - "Community 12"
Cohesion: 0.03
Nodes (58): fetchFullmoonTodoList(), fetchUpdateFullmoonTodoInsurance(), fetchCollectionProtocolAuditList(), fetchCollectionProtocolDetail(), fetchCollectionProtocolList(), fetchCreateProtocolInvoiceRequest(), fetchInvoiceEligiblePayments(), fetchPaymentDetailList() (+50 more)
Cohesion: 0.04
Nodes (42): buildBaseFields(), buildFeeSection(), buildInboundBasicSection(), buildInboundCellStorageProductionViewSections(), buildInboundResearchDonationProductionViewSections(), buildOutboundBasicExperimentProductionViewSections(), buildOutboundClinicalProductionViewSections(), buildOutboundDetail() (+34 more)
### Community 13 - "Community 13"
Cohesion: 0.04
Nodes (66): fetchDeptTree(), fetchUserList(), fetchOaFlowPreview(), fetchOaTemplateDetail(), formatHandoverUserLabel(), formatNowDatetime(), fullFileUrl(), handlePreviewAttachment() (+58 more)
Cohesion: 0.05
Nodes (60): fetchDeptTree(), fetchUserList(), fetchOaFlowPreview(), fetchOaTemplateDetail(), remoteSearchHandoverUsers(), flowNeedsInitiatorSelect(), loadFlowPreview(), loadUsers() (+52 more)
### Community 14 - "Community 14"
Cohesion: 0.03
Nodes (22): fetchProductionWorkOrderQcInfo(), fetchQcMaterialBatchDetail(), fetchQcMaterialBatchList(), fetchQcMaterialBatchOptions(), fetchQcMaterialList(), fetchQcMaterialOptions(), fetchUpdateQcMaterialBatch(), dash() (+14 more)
Cohesion: 0.05
Nodes (53): fetchOaRelatedSummaries(), displayPeople(), personLines(), personTitle(), showNodeComment(), signBadge(), signBadgeText(), statusText() (+45 more)
### Community 15 - "Community 15"
Cohesion: 0.05
Nodes (49): fetchOaRelatedSummaries(), displayPeople(), personLines(), personTitle(), showNodeComment(), signBadge(), signBadgeText(), statusText() (+41 more)
Cohesion: 0.04
Nodes (44): fetchFullmoonTodoList(), fetchUpdateFullmoonTodoInsurance(), fetchCollectionProtocolAuditList(), fetchCollectionProtocolDetail(), fetchCollectionProtocolList(), fetchCreateProtocolInvoiceRequest(), fetchInvoiceEligiblePayments(), fetchPaymentDetailList() (+36 more)
### Community 16 - "Community 16"
Cohesion: 0.05
Nodes (33): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), fetchMarkQcMaterialUsageFullyUsed(), collectIds(), postorder(), preorder() (+25 more)
Cohesion: 0.04
Nodes (38): fetchCellSampleTypeList(), fetchCreateCellSampleType(), fetchCreateMenu(), fetchDeleteCellSampleType(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateCellSampleType(), fetchUpdateMenu() (+30 more)
### Community 17 - "Community 17"
Cohesion: 0.07
Nodes (38): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), updateInfusionScheduleStatus(), handleAdd(), handleDelete(), handleDropdownCommand() (+30 more)
Cohesion: 0.06
Nodes (38): attachmentFullUrl(), dash(), handleAttachmentDownload(), handleAttachmentPreview(), buildPaymentFlowSteps(), dash(), formatAmount(), hasFinanceReceipt() (+30 more)
### Community 18 - "Community 18"
Cohesion: 0.04
Nodes (21): fetchAvailableMaterialBatches(), fetchMyProductionMaterialConsumptions(), fetchMyProductionMaterialUsageList(), fetchProductionMaterialBatchList(), fetchProductionMaterialBatchOptions(), fetchProductionMaterialConsumptions(), fetchProductionMaterialFormula(), fetchProductionMaterialLinkedStepUsages() (+13 more)
Cohesion: 0.07
Nodes (39): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), updateInfusionScheduleStatus(), handleAdd(), handleBatchDelete(), handleDelete() (+31 more)
### Community 19 - "Community 19"
Cohesion: 0.06
Nodes (32): fetchAddTaskStep(), fetchCopyTaskStep(), fetchDeleteTaskStep(), fetchDispatchProductionTaskSteps(), fetchForwardProductionTask(), fetchProductionTaskDetail(), fetchProductionTaskEditorInit(), fetchProductionTaskList() (+24 more)
Cohesion: 0.05
Nodes (14): fetchProductionWorkOrderQcInfo(), dash(), fmtMoney(), auditorDisplay(), dash(), ensureUnitsInOptions(), expressName(), formatYm() (+6 more)
### Community 20 - "Community 20"
Cohesion: 0.06
Nodes (29): qcAttachmentFullUrl(), qcDownloadAttachment(), qcPreviewAttachment(), formatHandoverUserLabel(), formatNowDatetime(), fullFileUrl(), handleDownloadAttachment(), handlePreviewAttachment() (+21 more)
### Community 21 - "Community 21"
Cohesion: 0.08
Nodes (37): formatDatetimeToMinute(), handleChineseDatetimePaste(), parseChineseDatetimeText(), parseBirthOrder(), parseChineseNumeral(), addSampleHint(), earliestCollectTime(), isMaternalBloodEmpty() (+29 more)
### Community 21 - "Community 21"
### Community 22 - "Community 22"
Cohesion: 0.06
Nodes (32): fetchAddTaskStep(), fetchCopyTaskStep(), fetchDeleteTaskStep(), fetchDispatchProductionTaskSteps(), fetchForwardProductionTask(), fetchProductionTaskDetail(), fetchProductionTaskEditorInit(), fetchProductionTaskList() (+24 more)
### Community 23 - "Community 23"
Cohesion: 0.06
Nodes (21): fetchQcMaterialBatchDetail(), fetchQcMaterialBatchList(), fetchQcMaterialBatchOptions(), fetchQcMaterialList(), fetchQcMaterialOptions(), fetchUpdateQcMaterialBatch(), fetchMarkQcMaterialUsageFullyUsed(), financeAttachmentsToUrlString() (+13 more)
### Community 24 - "Community 24"
Cohesion: 0.1
Nodes (2): WebSocketClient, TableCache
### Community 22 - "Community 22"
### Community 25 - "Community 25"
Cohesion: 0.08
Nodes (33): fetchRefreshToken(), toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url() (+25 more)
### Community 23 - "Community 23"
### Community 26 - "Community 26"
Cohesion: 0.09
Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
### Community 24 - "Community 24"
### Community 27 - "Community 27"
Cohesion: 0.08
Nodes (20): createEmptySnapshots(), normalizeConfiguredReagents(), normalizeConsumables(), normalizeDataCollections(), normalizeReagents(), normalizeStepOutputs(), serializeAttachments(), serializeEquipmentIds() (+12 more)
### Community 25 - "Community 25"
### Community 28 - "Community 28"
Cohesion: 0.08
Nodes (18): fetchProductionReceptionBySampleCode(), fetchProductionReceptionSubmit(), fetchProductionReceptionUpdate(), onUserSelectVisible(), remoteSearchUsers(), buildPayload(), ensureDefaultHandler(), initDialog() (+10 more)
### Community 26 - "Community 26"
### Community 29 - "Community 29"
Cohesion: 0.07
Nodes (19): fetchDeleteMaterialBatch(), fetchMaterialBatchList(), fetchMaterialBatchOptions(), fetchMaterialList(), fetchMaterialOptions(), fetchUpdateMaterialBatch(), fetchMaterialUsageList(), fetchMyMaterialUsageList() (+11 more)
### Community 27 - "Community 27"
### Community 30 - "Community 30"
Cohesion: 0.09
Nodes (22): fetchMineProductionWorkOrderTabStepCounts(), fetchMineProductionWorkOrderTabStepCountsDeduped(), fetchProductionWorkOrderCellProductOptions(), fetchProductionWorkOrderDetail(), fetchProductionWorkOrderList(), fetchProductionWorkOrderQcDispatchOptions(), fetchProductionWorkOrderTabStepCounts(), fetchProductionWorkOrderTabStepCountsDeduped() (+14 more)
### Community 28 - "Community 28"
Cohesion: 0.11
Nodes (25): completePilotApplication(), deletePilotApplication(), fetchPilotApplicationList(), startPilotApplication(), voidPilotApplication(), clearTableSelection(), handleBatchComplete(), handleBatchStart() (+17 more)
### Community 29 - "Community 29"
Cohesion: 0.12
Nodes (20): fetchGetMenuCodes(), fetchGetUserInfo(), fetchLogin(), fetchUpdateProfile(), fetchUploadProfileAvatar(), fetchUserInfo(), buildWebEncryptedLoginBody(), defaultAvatarPathByRole() (+12 more)
### Community 30 - "Community 30"
Cohesion: 0.09
Nodes (12): fetchMineQcWorkOrderTabUnfinishedCounts(), fetchOutboundQcDetail(), fetchQcWorkOrderDetail(), fetchQcWorkOrderList(), fetchQcWorkOrdersBySample(), fetchQcWorkOrderTabUnfinishedCounts(), reload(), reloadTabCounts() (+4 more)
### Community 31 - "Community 31"
Cohesion: 0.1
Nodes (12): fetchOutboundReleaseMaterial(), fetchOutboundReleaseReviewDetail(), fetchOutboundReleaseReviewList(), fetchReleaseReviewList(), handleReset(), handleSearch(), handleTabChange(), handleToggleSelect() (+4 more)
Cohesion: 0.09
Nodes (27): completePilotApplication(), deletePilotApplication(), fetchPilotApplicationList(), startPilotApplication(), voidPilotApplication(), handleBatchComplete(), handleBatchStart(), handleBatchVoid() (+19 more)
### Community 32 - "Community 32"
Cohesion: 0.12
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
Nodes (20): fetchGetMenuCodes(), fetchGetUserInfo(), fetchLogin(), fetchUpdateProfile(), fetchUploadProfileAvatar(), fetchUserInfo(), buildWebEncryptedLoginBody(), defaultAvatarPathByRole() (+12 more)
### Community 33 - "Community 33"
Cohesion: 0.09
Nodes (12): fetchMineQcWorkOrderTabUnfinishedCounts(), fetchOutboundQcDetail(), fetchQcWorkOrderDetail(), fetchQcWorkOrderList(), fetchQcWorkOrdersBySample(), fetchQcWorkOrderTabUnfinishedCounts(), reload(), reloadTabCounts() (+4 more)
### Community 34 - "Community 34"
Cohesion: 0.1
Nodes (12): fetchOutboundReleaseMaterial(), fetchOutboundReleaseReviewDetail(), fetchOutboundReleaseReviewList(), fetchReleaseReviewList(), handleReset(), handleSearch(), handleTabChange(), handleToggleSelect() (+4 more)
### Community 35 - "Community 35"
Cohesion: 0.12
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
### Community 36 - "Community 36"
Cohesion: 0.19
Nodes (15): fetchAttachmentDownloadUrl(), attachmentFullUrl(), ensureUniqueZipEntryName(), fetchAttachmentBlob(), getAttachmentExtension(), resolveAttachmentFileName(), sanitizeZipPathSegment(), applyInboundLabStorageCodePrefix() (+7 more)
### Community 34 - "Community 34"
### Community 37 - "Community 37"
Cohesion: 0.13
Nodes (8): chipTitle(), confirmPicker(), memberOptionLabel(), removeUser(), resolveUser(), signBadge(), signBadgeText(), updateSelect()
### Community 38 - "Community 38"
Cohesion: 0.2
Nodes (14): applyFlagToRule(), applySchema(), countRules(), getActiveRule(), getDesigner(), getSetupState(), onMessage(), readFlag() (+6 more)
### Community 35 - "Community 35"
Cohesion: 0.16
Nodes (14): fetchCreateEnvDetectItem(), fetchDeleteEnvDetectItem(), fetchEnvDetectItemDetail(), fetchEnvDetectItemList(), fetchEnvDetectItemsActive(), fetchUpdateEnvDetectItem(), handleAdd(), handleBatchDelete() (+6 more)
### Community 36 - "Community 36"
### Community 39 - "Community 39"
Cohesion: 0.12
Nodes (6): setupOaConfirmationKit(), ensureOaKitMenu(), setupOaLeaveKit(), setupOaOvertimeKit(), setupOaResignationKit(), setupOaTripKit()
### Community 37 - "Community 37"
Cohesion: 0.12
Nodes (6): attachmentFullUrl(), dash(), handleAttachmentDownload(), handleAttachmentPreview(), ensureOaUploadRuleProps(), resolveUploadResponseUrl()
### Community 38 - "Community 38"
### Community 40 - "Community 40"
Cohesion: 0.16
Nodes (10): useTable(), useTableImpl(), getColumnChecks(), useTableColumns(), createErrorHandler(), createSmartDebounce(), defaultResponseAdapter(), extractPagination() (+2 more)
### Community 39 - "Community 39"
### Community 41 - "Community 41"
Cohesion: 0.27
Nodes (14): useChart(), useChartComponent(), useChartOps(), colourBlend(), getCssVar(), getDarkColor(), getLightColor(), handleElementThemeColor() (+6 more)
### Community 40 - "Community 40"
### Community 42 - "Community 42"
Cohesion: 0.19
Nodes (6): fetchServiceOrderTxnList(), handleReset(), handleSearch(), handleTabChange(), loadData(), switchTab()
### Community 42 - "Community 42"
Cohesion: 0.24
Nodes (8): fullFileUrl(), handlePreviewAttachment(), isVideoFile(), normalizeDisplayValue(), resolveReviewCellType(), resolveReviewQuantity(), resolveReviewSpecText(), uniqueJoined()
### Community 43 - "Community 43"
Cohesion: 0.42
Nodes (9): buildPaymentFlowSteps(), dash(), formatAmount(), hasFinanceReceipt(), hasFinanceRefund(), hasReceiptSubmit(), hasRefundSubmit(), receiptSubmitTime() (+1 more)
### Community 44 - "Community 44"
Cohesion: 0.31
Nodes (4): isSlotAvailable(), resolveStorageSlotRangeFill(), slotFacilityNodeId(), sortBoxSlots()
@@ -325,64 +322,52 @@ Nodes (2): parseEquipmentIds(), syncEquipmentNamesFromOptions()
Cohesion: 0.5
Nodes (2): focusInput(), handleKeydown()
### Community 61 - "Community 61"
Cohesion: 0.4
Nodes (1): fetchQcMaterialAmountAuthUsers()
### Community 64 - "Community 64"
### Community 63 - "Community 63"
Cohesion: 0.67
Nodes (2): if(), logSidebarMenu()
### Community 66 - "Community 66"
Cohesion: 0.5
Nodes (1): fetchStorageEntrySmsList()
### Community 67 - "Community 67"
Cohesion: 0.5
Nodes (1): fetchQcSmsList()
### Community 72 - "Community 72"
### Community 69 - "Community 69"
Cohesion: 1.0
Nodes (2): getSettingDefaults(), resetToDefaults()
### Community 75 - "Community 75"
### Community 72 - "Community 72"
Cohesion: 1.0
Nodes (2): buildOvertimeKitChildren(), uniqueId()
### Community 76 - "Community 76"
### Community 73 - "Community 73"
Cohesion: 1.0
Nodes (2): buildLeaveKitChildren(), uniqueId()
### Community 78 - "Community 78"
### Community 74 - "Community 74"
Cohesion: 1.0
Nodes (2): buildConfirmationKitChildren(), uniqueId()
### Community 79 - "Community 79"
### Community 75 - "Community 75"
Cohesion: 1.0
Nodes (2): buildResignationKitChildren(), uniqueId()
### Community 80 - "Community 80"
### Community 76 - "Community 76"
Cohesion: 1.0
Nodes (2): copyTextToClipboard(), copyTextWithFallback()
### Community 83 - "Community 83"
### Community 79 - "Community 79"
Cohesion: 1.0
Nodes (2): getSourceProtocolAttachment(), normalizeAttachmentFiles()
### Community 95 - "Community 95"
### Community 92 - "Community 92"
Cohesion: 1.0
Nodes (2): emptyTabCounts(), useProductionWorkOrderTabStepCounts()
### Community 97 - "Community 97"
### Community 94 - "Community 94"
Cohesion: 1.0
Nodes (2): initialProgress(), useQcWorkOrderAttachmentExport()
### Community 98 - "Community 98"
### Community 95 - "Community 95"
Cohesion: 1.0
Nodes (2): emptyTabCounts(), useQcWorkOrderTabUnfinishedCounts()
## Knowledge Gaps
- **Thin community `Community 21`** (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 24`** (42 nodes): `WebSocketClient`, `.calculateReconnectDelay()`, `.clearAllTimers()`, `.clearConnectionTimers()`, `.clearTimer()`, `.close()`, `.closeCurrentSocketForReconnect()`, `.connect()`, `.connectionStatusText()`, `.constructor()`, `.destroyInstance()`, `.flushMessageQueue()`, `.getInstance()`, `.getReadyStateText()`, `.handleClose()`, `.handleConnectionTimeout()`, `.handleError()`, `.handleMessage()`, `.handleOpen()`, `.init()`, `.isWebSocketConnected()`, `.reconnect()`, `.resetHeartbeat()`, `.send()`, `.startHeartbeat()`, `.startPing()`, `TableCache`, `.cleanupExpired()`, `.clear()`, `.clearByTags()`, `.clearCurrentSearch()`, `.clearPagination()`, `.constructor()`, `.evictLRU()`, `.generateKey()`, `.generateTags()`, `.get()`, `.getStats()`, `.log()`, `.set()`, `index.ts`, `tableCache.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 45`** (9 nodes): `cleanupEventListeners()`, `handleTouchEnd()`, `handleTouchMove()`, `handleTouchStart()`, `handleWheelScroll()`, `if()`, `setTransition()`, `setupEventListeners()`, `index.vue`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
@@ -398,44 +383,38 @@ Nodes (2): emptyTabCounts(), useQcWorkOrderTabUnfinishedCounts()
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 60`** (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 61`** (5 nodes): `fetchBatchRevokeQcMaterialAmountAuth()`, `fetchGrantQcMaterialAmountAuth()`, `fetchQcMaterialAmountAuthUsers()`, `fetchRevokeQcMaterialAmountAuth()`, `qc-material-amount-auth.ts`
- **Thin community `Community 63`** (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 64`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
- **Thin community `Community 69`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 66`** (4 nodes): `fetchGenerateStorageEntrySms()`, `fetchStorageEntrySmsList()`, `fetchToggleStorageEntrySmsNotified()`, `storage-entry-sms-notification.ts`
- **Thin community `Community 72`** (3 nodes): `buildOvertimeKitChildren()`, `oa-overtime-kit-rule.ts`, `uniqueId()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 67`** (4 nodes): `fetchGenerateQcSms()`, `fetchQcSmsList()`, `fetchToggleQcSmsNotified()`, `qc-sms-notification.ts`
- **Thin community `Community 73`** (3 nodes): `buildLeaveKitChildren()`, `oa-leave-kit-rule.ts`, `uniqueId()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 72`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
- **Thin community `Community 74`** (3 nodes): `buildConfirmationKitChildren()`, `oa-confirmation-kit-rule.ts`, `uniqueId()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 75`** (3 nodes): `buildOvertimeKitChildren()`, `oa-overtime-kit-rule.ts`, `uniqueId()`
- **Thin community `Community 75`** (3 nodes): `buildResignationKitChildren()`, `oa-resignation-kit-rule.ts`, `uniqueId()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 76`** (3 nodes): `buildLeaveKitChildren()`, `oa-leave-kit-rule.ts`, `uniqueId()`
- **Thin community `Community 76`** (3 nodes): `copyTextToClipboard()`, `copyTextWithFallback()`, `copy-text.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 78`** (3 nodes): `buildConfirmationKitChildren()`, `oa-confirmation-kit-rule.ts`, `uniqueId()`
- **Thin community `Community 79`** (3 nodes): `getSourceProtocolAttachment()`, `normalizeAttachmentFiles()`, `protocol-source-attachment.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 79`** (3 nodes): `buildResignationKitChildren()`, `oa-resignation-kit-rule.ts`, `uniqueId()`
- **Thin community `Community 92`** (3 nodes): `emptyTabCounts()`, `useProductionWorkOrderTabStepCounts()`, `useProductionWorkOrderTabStepCounts.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 80`** (3 nodes): `copyTextToClipboard()`, `copyTextWithFallback()`, `copy-text.ts`
- **Thin community `Community 94`** (3 nodes): `initialProgress()`, `useQcWorkOrderAttachmentExport()`, `useQcWorkOrderAttachmentExport.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 83`** (3 nodes): `getSourceProtocolAttachment()`, `normalizeAttachmentFiles()`, `protocol-source-attachment.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 95`** (3 nodes): `emptyTabCounts()`, `useProductionWorkOrderTabStepCounts()`, `useProductionWorkOrderTabStepCounts.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 97`** (3 nodes): `initialProgress()`, `useQcWorkOrderAttachmentExport()`, `useQcWorkOrderAttachmentExport.ts`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 98`** (3 nodes): `emptyTabCounts()`, `useQcWorkOrderTabUnfinishedCounts()`, `useQcWorkOrderTabUnfinishedCounts.ts`
- **Thin community `Community 95`** (3 nodes): `emptyTabCounts()`, `useQcWorkOrderTabUnfinishedCounts()`, `useQcWorkOrderTabUnfinishedCounts.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 `push()` connect `Community 2` to `Community 0`, `Community 1`, `Community 3`, `Community 4`, `Community 6`, `Community 7`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 19`, `Community 20`, `Community 21`, `Community 22`, `Community 24`, `Community 27`, `Community 30`, `Community 33`?**
_High betweenness centrality (0.272) - this node is a cross-community bridge._
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 35`, `Community 40`, `Community 44`, `Community 61`, `Community 66`, `Community 67`?**
_High betweenness centrality (0.261) - this node is a cross-community bridge._
- **Why does `handleDynamicRoutes()` connect `Community 5` to `Community 6`, `Community 9`, `Community 15`, `Community 27`, `Community 29`, `Community 30`?**
_High betweenness centrality (0.038) - this node is a cross-community bridge._
- **Why does `push()` connect `Community 2` to `Community 0`, `Community 1`, `Community 3`, `Community 4`, `Community 6`, `Community 8`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 17`, `Community 19`, `Community 20`, `Community 21`, `Community 22`, `Community 24`, `Community 25`, `Community 27`, `Community 30`, `Community 31`, `Community 33`, `Community 36`, `Community 37`?**
_High betweenness centrality (0.281) - this node is a cross-community bridge._
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `Community 19`, `Community 22`, `Community 23`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 42`, `Community 44`?**
_High betweenness centrality (0.273) - this node is a cross-community bridge._
- **Why does `buildInboundBasicSection()` connect `Community 12` to `Community 2`?**
_High betweenness centrality (0.033) - this node is a cross-community bridge._
- **Are the 304 inferred relationships involving `get()` (e.g. with `resolveStorageSlotRangeFill()` and `buildNodeCodePathFromFlat()`) actually correct?**
_`get()` has 304 INFERRED edges - model-reasoned connections that need verification._
- **Are the 109 inferred relationships involving `push()` (e.g. with `refreshQcMenuBadges()` and `collectLeafFacilityNodesInTreeOrder()`) actually correct?**
+4 -4
View File
@@ -57,12 +57,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">3368 nodes &middot; 4772 edges &middot; 382 communities</div>
<div id="stats">3371 nodes &middot; 4776 edges &middot; 379 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 52, "community_name": "Community 52", "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": 52, "community_name": "Community 52", "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": 52, "community_name": "Community 52", "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.4, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 52, "community_name": "Community 52", "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.2, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 52, "community_name": "Community 52", "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.2, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 52, "community_name": "Community 52", "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": 144, "community_name": "Community 144", "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": 145, "community_name": "Community 145", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 32, "community_name": "Community 32", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 32, "community_name": "Community 32", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 32, "community_name": "Community 32", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 32, "community_name": "Community 32", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 32, "community_name": "Community 32", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_setuprolesdirective",Line 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": 514}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 128}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 120}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 110}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 109}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 108}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 104}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 104}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 97}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 95}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 90}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 89}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 89}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 83}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 69}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 64}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 62}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 49}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 48}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 47}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 47}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 42}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 41}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 37}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 36}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 36}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 35}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 34}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 30}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 28}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 25}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 24}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 22}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 20}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 19}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 19}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 17}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 17}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 17}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 16}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 14}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 13}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 13}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 10}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 9}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 9}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 9}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 9}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 9}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 8}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 8}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 8}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 7}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 7}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 7}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 6}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 6}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 5}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 5}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 5}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 5}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 5}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 5}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 4}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 4}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 4}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 4}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 4}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 4}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 4}, {"cid": 70, "color": "#4E79A7", "label": "CommunityLine truncated
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 52, "community_name": "Community 52", "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": 52, "community_name": "Community 52", "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": 52, "community_name": "Community 52", "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.4, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 52, "community_name": "Community 52", "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.2, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 52, "community_name": "Community 52", "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.2, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 52, "community_name": "Community 52", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 141, "community_name": "Community 141", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#E15759", "border": "#E15759", "highlight": {"background": "#ffffff", "border": "#E15759"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 142, "community_name": "Community 142", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 35, "community_name": "Community 35", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 35, "community_name": "Community 35", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 35, "community_name": "Community 35", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 35, "community_name": "Community 35", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 35, "community_name": "Community 35", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_setuprolesdirective",Line 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": 474}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 138}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 119}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 109}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 108}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 101}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 100}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 96}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 92}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 92}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 87}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 80}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 74}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 70}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 69}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 69}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 62}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 55}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 50}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 48}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 47}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 47}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 47}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 43}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 42}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 41}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 37}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 36}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 36}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 35}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 34}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 34}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 28}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 25}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 24}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 22}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 20}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 20}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 19}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 17}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 17}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 16}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 14}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 13}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 9}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 9}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 9}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 9}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 9}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 8}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 8}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 8}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 7}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 7}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 7}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 6}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 6}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 5}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 5}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 5}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 5}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 5}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 4}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 4}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 4}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 4}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 4}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 4}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 3}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 3}, {"cid": 70, "color": "#4E79A7", "label": "Community Line truncated
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
File diff suppressed because it is too large. Load diff
+6 -6
View File
@@ -17,8 +17,8 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/index.ts": 1781272556.3597305,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/directive/directive.d.ts": 1781272556.3601494,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api/api.d.ts": 1781272556.3606477,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1785998258.740974,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1785997075.7526152,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1786004653.5328317,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1786004576.7525966,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/store/index.ts": 1781272556.364766,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/router/index.ts": 1782394569.8806834,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/composables/useAttachmentActions.ts": 1783921717.4015942,
@@ -320,7 +320,7 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/common/decimal-input/index.vue": 1782893851.5090024,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaPostSelect.vue": 1785394386.0894492,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaFlowPreview.vue": 1785392987.9755206,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/oa-condition-fields.ts": 1785401042.1232235,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/oa-condition-fields.ts": 1786002784.7150648,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaPersonSelect.vue": 1785388355.4534001,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaOvertimeKit.vue": 1785404041.649327,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaApprovalPrintSheet.vue": 1785145511.6904423,
@@ -343,9 +343,9 @@
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaOwnerDeptSelect.vue": 1785401021.3290825,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaAppIconPicker.vue": 1785996996.907459,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/OaTripKit.vue": 1785412919.2794502,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/FlowBranch.vue": 1785392944.1165543,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/ConditionRuleEditor.vue": 1785401148.1066115,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/FlowDesigner.vue": 1785910541.8718677,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/FlowBranch.vue": 1786005666.7149255,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/ConditionRuleEditor.vue": 1786002982.9909377,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/FlowDesigner.vue": 1786002526.9068692,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/oa-approval/flow-tree/types.ts": 1785835692.8501098,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/hooks/index.ts": 1781272556.653748,
"/Users/wuzilong/work/00code/zkxw/web-admin/src/hooks/core/useFastEnter.ts": 1781272556.6454022,
@@ -1,19 +1,14 @@
<template>
<div class="oa-icon-picker">
<OaAppIcon :icon-url="modelValue" size="md" />
<button
type="button"
class="oa-icon-picker__trigger"
title="点击选择图标"
@click="panelOpen = !panelOpen"
>
<OaAppIcon :icon-url="modelValue" size="md" />
</button>
<div class="oa-icon-picker__actions">
<el-button class="btn-ghost" type="button" @click="panelOpen = !panelOpen">
<el-icon><Grid /></el-icon>
从图标库选择
</el-button>
<el-button class="btn-ghost" type="button" @click="onRecolor">
<el-icon><Brush /></el-icon>
换底色
</el-button>
<el-button class="btn-ghost" type="button" @click="onRandom">
<el-icon><Refresh /></el-icon>
随机图标+底色
</el-button>
<el-upload
:show-file-list="false"
accept="image/*"
@@ -25,13 +20,11 @@
上传图片
</el-button>
</el-upload>
<p class="oa-icon-picker__tip">
新增时随机淡色底 + EP 图标(同色系深色);可展开选图标/换底色,或上传自定义图
</p>
<p class="oa-icon-picker__tip">点击左侧图标可展开图标库选择;也可上传自定义图片</p>
</div>
<div v-show="panelOpen" class="oa-icon-picker__panel">
<div class="oa-icon-picker__panel-head">
<strong>Element Plus 图标(精选)</strong>
<strong>图标</strong>
<el-button class="btn-ghost" style="height: 24px" @click="panelOpen = false">收起</el-button>
</div>
<div class="oa-icon-picker__grid">
@@ -43,7 +36,7 @@
:class="{ active: currentEp.icon === name && isEp }"
@click="onPickIcon(name)"
>
<el-icon :style="{ color: currentEp.fg }"><component :is="epMap[name]" /></el-icon>
<el-icon :size="22" :style="{ color: currentEp.fg }"><component :is="epMap[name]" /></el-icon>
<span>{{ name }}</span>
</button>
</div>
@@ -72,21 +65,18 @@
import {
Bell,
Briefcase,
Brush,
Calendar,
Checked,
Clock,
CollectionTag,
CreditCard,
Document,
Grid,
Location,
Message,
Money,
Notebook,
OfficeBuilding,
Present,
Refresh,
Setting,
Stamp,
Tickets,
@@ -103,7 +93,6 @@
buildEpIconUrl,
isEpIconUrl,
parseEpIconUrl,
pickRandomOaAppIconUrl,
recolorOaAppIconUrl,
type OaAppEpIconName
} from '@/utils/oa-app-icons'
@@ -152,23 +141,6 @@
setUrl(recolorOaAppIconUrl(props.modelValue, bg))
}
function onRecolor() {
const list = OA_APP_ICON_COLOR_PAIRS
const cur = currentEp.value.bg
let next = list[Math.floor(Math.random() * list.length)].bg
if (list.length > 1) {
let guard = 0
while (next === cur && guard++ < 8) {
next = list[Math.floor(Math.random() * list.length)].bg
}
}
setUrl(recolorOaAppIconUrl(props.modelValue, next))
}
function onRandom() {
setUrl(pickRandomOaAppIconUrl())
}
async function uploadIcon(options: UploadRequestOptions) {
const file = options.file as File
if (!file?.type?.startsWith('image/')) {
@@ -204,6 +176,24 @@
width: 100%;
}
.oa-icon-picker__trigger {
padding: 0;
background: transparent;
border: none;
border-radius: 12px;
cursor: pointer;
&:hover {
outline: 2px solid #a7f3d0;
outline-offset: 2px;
}
&:focus-visible {
outline: 2px solid var(--primary, #10b981);
outline-offset: 2px;
}
}
.oa-icon-picker__actions {
display: flex;
flex: 1;
@@ -242,9 +232,9 @@
.oa-icon-picker__grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
gap: 8px;
max-height: 220px;
max-height: 240px;
overflow: auto;
}
@@ -254,15 +244,35 @@
gap: 4px;
align-items: center;
justify-content: center;
height: 56px;
padding: 4px;
height: 64px;
padding: 6px 4px;
color: #475569;
font-size: 10px;
line-height: 1;
background: #fff;
border: 1px solid transparent;
border-radius: 8px;
cursor: pointer;
:deep(.el-icon) {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
height: 22px;
margin: 0;
}
span {
display: block;
max-width: 100%;
overflow: hidden;
line-height: 1.2;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}
&:hover {
color: var(--primary-dark, #059669);
border-color: #a7f3d0;
@@ -38,6 +38,7 @@
:model-value="rule.op"
placeholder="条件"
:disabled="disabled"
class="cond-rule-editor__op"
@update:model-value="(v) => onOpChange(idx, v)"
>
<el-option
@@ -444,12 +445,24 @@
.cond-rule-editor__row {
display: grid;
grid-template-columns: 1fr auto 1fr auto;
/* 字段 | 运算符(收窄)| 值(加宽)| 删除 */
grid-template-columns: minmax(0, 1fr) 100px minmax(0, 1.8fr) auto;
gap: 6px;
align-items: center;
margin-bottom: 6px;
}
.cond-rule-editor__row > .el-select,
.cond-rule-editor__row > .el-tree-select,
.cond-rule-editor__row > .el-input {
width: 100%;
min-width: 0;
}
.cond-rule-editor__op {
width: 100%;
}
.cond-rule-editor__del {
padding: 4px;
}
@@ -2,7 +2,7 @@
<template>
<div class="flow-branch">
<template v-if="node.type === 'end'">
<div class="flow-end">流程结束</div>
<div class="flow-end">{{ endLabel }}</div>
</template>
<template v-else>
@@ -34,7 +34,14 @@
class="flow-cond-col"
>
<div class="flow-cond-col__title" @click.stop="emit('edit', node)">
{{ branchTitle(g, idx) }}
<span class="flow-cond-col__name">{{ branchName(g, idx) }}</span>
<span
v-for="(line, lineIdx) in branchConditionLines(g)"
:key="`${node.id}_g_${idx}_r_${lineIdx}`"
class="muted"
>
{{ line }}
</span>
</div>
<!-- 分支仅有结束节点时,先露出「+」才能往分支内插入 -->
<el-dropdown
@@ -55,12 +62,14 @@
v-if="g.child && g.child.type !== 'end'"
:node="g.child"
:depth="depth + 1"
:end-label="branchEndLabel"
:candidates="candidates"
:value-label-maps="valueLabelMaps"
@edit="(n) => emit('edit', n)"
@remove="(id) => emit('remove', id)"
@add="(payload) => emit('add', payload)"
/>
<div v-else class="flow-end">流程结束</div>
<div v-else class="flow-end">{{ branchEndLabel }}</div>
</div>
</div>
@@ -79,12 +88,14 @@
v-if="node.child"
:node="node.child"
:depth="depth"
:end-label="endLabel"
:candidates="candidates"
:value-label-maps="valueLabelMaps"
@edit="(n) => emit('edit', n)"
@remove="(id) => emit('remove', id)"
@add="(payload) => emit('add', payload)"
/>
<div v-else class="flow-end">流程结束</div>
<div v-else class="flow-end">{{ endLabel }}</div>
</template>
<template v-else>
@@ -103,12 +114,14 @@
v-if="node.child"
:node="node.child"
:depth="depth"
:end-label="endLabel"
:candidates="candidates"
:value-label-maps="valueLabelMaps"
@edit="(n) => emit('edit', n)"
@remove="(id) => emit('remove', id)"
@add="(payload) => emit('add', payload)"
/>
<div v-else class="flow-end">流程结束</div>
<div v-else class="flow-end">{{ endLabel }}</div>
</template>
</template>
</div>
@@ -117,8 +130,9 @@
<script setup lang="ts">
import { Delete } from '@element-plus/icons-vue'
import {
formatConditionPreview,
type ConditionCandidate
formatConditionPreviewLines,
type ConditionCandidate,
type ConditionValueLabelMaps
} from '@/components/oa-approval/oa-condition-fields'
import type { ConditionGroup, FlowNode } from './types'
import { summarizeApprover } from './types'
@@ -131,9 +145,17 @@
defineProps<{
node: FlowNode
depth?: number
/** 分支/主链末端文案;有汇合后主链时分支内传「汇合」 */
endLabel?: string
candidates?: ConditionCandidate[]
valueLabelMaps?: ConditionValueLabelMaps
}>(),
{ depth: 0, candidates: () => [] }
{ depth: 0, endLabel: '流程结束', candidates: () => [], valueLabelMaps: () => ({}) }
)
/** 本条件有汇合后 child,或外层已标明汇合时,分支列末端用「汇合」 */
const branchEndLabel = computed(() =>
props.node.child || props.endLabel === '汇合' ? '汇合' : props.endLabel
)
const emit = defineEmits<{
@@ -157,13 +179,20 @@
return t
}
function branchTitle(g: ConditionGroup, idx: number) {
function branchName(g: ConditionGroup, idx: number) {
if (g.isDefault) return g.name || '默认 · 其他情况'
const preview = formatConditionPreview(g.rules || [], props.candidates || [])
if (preview && preview !== '未配置') return preview
return g.name || `条件${idx + 1}`
}
function branchConditionLines(g: ConditionGroup) {
if (g.isDefault) return [] as string[]
return formatConditionPreviewLines(
g.rules || [],
props.candidates || [],
props.valueLabelMaps
)
}
function nodeSummary(n: FlowNode) {
if (n.type === 'start') return '谁可以发起本审批'
if (n.type === 'condition') {
@@ -245,9 +274,13 @@
padding: 0;
color: #fff !important;
opacity: 0.85;
background: transparent !important;
&:hover {
&:hover,
&:focus {
color: #ef4444 !important;
opacity: 1;
background: transparent !important;
}
}
@@ -299,15 +332,23 @@
color: #5b21b6;
font-size: 12px;
font-weight: 600;
text-align: center;
cursor: pointer;
background: #ede9fe;
border-radius: 6px;
.flow-cond-col__name {
display: block;
}
.muted {
display: block;
margin-top: 2px;
color: var(--mint-text-muted, #94a3b8);
font-weight: 400;
line-height: 1.4;
text-align: center;
word-break: break-word;
}
}
</style>
@@ -9,6 +9,7 @@
<FlowBranch
:node="root"
:candidates="candidates"
:value-label-maps="conditionValueLabelMaps"
@edit="openEdit"
@remove="onRemove"
@add="onAdd"
@@ -298,9 +299,12 @@
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, UserFilled } from '@element-plus/icons-vue'
import { fetchUserList, fetchPostList } from '@/api/admin'
import { fetchUserList, fetchPostList, fetchDeptTree } from '@/api/admin'
import { MAX_ADMIN_LIST_PAGE_SIZE } from '@/utils/fetch-paged-list'
import type { ConditionCandidate } from '@/components/oa-approval/oa-condition-fields'
import type {
ConditionCandidate,
ConditionValueLabelMaps
} from '@/components/oa-approval/oa-condition-fields'
import ConditionRuleEditor from './ConditionRuleEditor.vue'
import FlowBranch from './FlowBranch.vue'
import {
@@ -407,9 +411,30 @@
type PostOption = { id: string; postName: string; postCode: string }
const postOptions = ref<PostOption[]>([])
const userOptions = ref<UserOption[]>([])
const deptLabelMap = ref<Record<string, string>>({})
const memberPickBuffer = ref('')
const postPickBuffer = ref('')
const conditionValueLabelMaps = computed<ConditionValueLabelMaps>(() => {
const users: Record<string, string> = {}
for (const u of userOptions.value) {
const id = String(u.id)
const name = (u.nickName || '').trim() || (u.userNo || '').trim() || id
users[id] = name
}
const posts: Record<string, string> = {}
for (const p of postOptions.value) {
const id = String(p.id)
const name = (p.postName || '').trim() || (p.postCode || '').trim() || id
posts[id] = name
}
return {
users,
posts,
depts: { ...deptLabelMap.value }
}
})
function avatarColor(id: string) {
let hash = 0
for (let i = 0; i < id.length; i++) hash = (hash * 31 + id.charCodeAt(i)) >>> 0
@@ -557,6 +582,47 @@
}
}
function collectDeptLabels(nodes: Api.Dept.DeptItem[], out: Record<string, string>) {
for (const n of nodes || []) {
const id = String(n.id || '')
if (id) out[id] = String(n.deptName || '').trim() || id
if (n.children?.length) collectDeptLabels(n.children, out)
}
}
async function loadDeptLabels() {
try {
const tree = ((await fetchDeptTree()) || []) as Api.Dept.DeptItem[]
const out: Record<string, string> = {}
collectDeptLabels(tree, out)
deptLabelMap.value = out
} catch {
deptLabelMap.value = {}
}
}
/** 画布条件分支标题:把人员/部门/职位 id 解析成名称 */
async function ensureConditionPreviewLabels() {
const types = new Set((candidates.value || []).map((c) => c.type))
const tasks: Promise<void>[] = []
if (
[...types].some((t) => t === 'person' || t === 'ownerPerson' || t === 'initiator') &&
!userOptions.value.length
) {
tasks.push(loadUsers())
}
if (types.has('post') && !postOptions.value.length) {
tasks.push(loadPosts())
}
if (
[...types].some((t) => t === 'dept' || t === 'ownerDept') &&
!Object.keys(deptLabelMap.value).length
) {
tasks.push(loadDeptLabels())
}
if (tasks.length) await Promise.all(tasks)
}
function findNode(node: FlowNode, id: string): FlowNode | null {
if (node.id === id) return node
if (node.child) {
@@ -762,7 +828,19 @@
onMounted(() => {
commit()
void ensureConditionPreviewLabels()
})
watch(
() =>
(candidates.value || [])
.map((c) => c.type)
.sort()
.join(','),
() => {
void ensureConditionPreviewLabels()
}
)
</script>
<style scoped lang="scss">
@@ -181,10 +181,54 @@ export function normalizeSchemaConditionRequired(schema: unknown): {
}
}
export function formatConditionPreview(
rules: Array<{ field: string; op: string; value: unknown }>,
candidates: ConditionCandidate[]
/** 条件预览:人员/部门/职位 id → 展示名(存库仍为 id) */
export interface ConditionValueLabelMaps {
users?: Record<string, string>
posts?: Record<string, string>
depts?: Record<string, string>
}
function formatConditionValueText(
field: string,
value: unknown,
candidates: ConditionCandidate[],
labelMaps?: ConditionValueLabelMaps
): string {
const cand = candidates.find((c) => c.field === field)
const type = cand?.type || ''
const resolveOne = (raw: unknown): string => {
if (raw == null || raw === '') return '?'
const id = String(raw)
if (type === 'person' || type === 'ownerPerson' || type === 'initiator') {
return labelMaps?.users?.[id] || id
}
if (type === 'post') {
return labelMaps?.posts?.[id] || id
}
if (type === 'dept' || type === 'ownerDept') {
return labelMaps?.depts?.[id] || id
}
if (cand?.options?.length) {
const opt = cand.options.find((o) => String(o.value) === id)
if (opt) return opt.label
}
return id
}
if (Array.isArray(value)) {
if (!value.length) return '(空)'
return value.map(resolveOne).join('、')
}
if (value == null || value === '') return '?'
return resolveOne(value)
}
export function formatConditionPreviewLines(
rules: Array<{ field: string; op: string; value: unknown }>,
candidates: ConditionCandidate[],
labelMaps?: ConditionValueLabelMaps
): string[] {
const titleOf = (f: string) => candidates.find((c) => c.field === f)?.title || f
const opLabel: Record<string, string> = {
'>': '大于',
@@ -195,13 +239,19 @@ export function formatConditionPreview(
'!=': '不等于',
contains: '包含'
}
if (!rules?.length) return '未配置'
return rules
.map((r) => {
const valueText = Array.isArray(r.value)
? r.value.join('、')
: (r.value ?? '?')
return `${titleOf(r.field)} ${opLabel[r.op] || r.op} ${valueText}`
})
.join(' 且 ')
if (!rules?.length) return []
return rules.map((r) => {
const valueText = formatConditionValueText(r.field, r.value, candidates, labelMaps)
return `${titleOf(r.field)} ${opLabel[r.op] || r.op} ${valueText}`
})
}
export function formatConditionPreview(
rules: Array<{ field: string; op: string; value: unknown }>,
candidates: ConditionCandidate[],
labelMaps?: ConditionValueLabelMaps
): string {
const lines = formatConditionPreviewLines(rules, candidates, labelMaps)
if (!lines.length) return '未配置'
return lines.join(' 且 ')
}
+17 -1
View File
@@ -31,8 +31,24 @@
activeMenuTab?: string
}
/**
* @form-create/designer 打包语言包落后于 makeOptionsRule:
* 选项数据下拉含 text/json,但 locale 仅有 struct/fetch,导致空白项。
* 文案与源码 src/locale/zh-cn.js 对齐;仅补缺,不覆盖已有词条。
*/
function patchFcDesignerLocale(base: typeof formCreateZh) {
const locale = { ...(base as Record<string, any>) }
const fetch = { ...(locale.fetch || {}) }
const optionsType = { ...(fetch.optionsType || {}) }
if (!optionsType.text) optionsType.text = '文本录入'
if (!optionsType.json) optionsType.json = 'JSON数据'
fetch.optionsType = optionsType
locale.fetch = fetch
return locale
}
const designerRef = ref<DesignerApi | null>(null)
const fcLocale = formCreateZh
const fcLocale = patchFcDesignerLocale(formCreateZh)
let pendingSchema: { rule: unknown; option: unknown } | null = null
let leaveKitRefreshTimer: number | null = null