Selaa lähdekoodia

优化启动DEBUG提示

zyp 6 päivää sitten
vanhempi
commit
bfcf481a46
40 muutettua tiedostoa jossa 7001 lisäystä ja 0 poistoa
  1. 21 0
      sql/_check_f.py
  2. 32 0
      sql/_check_orphan.py
  3. 14 0
      sql/_crm_paths.py
  4. 28 0
      sql/_preview_menu.py
  5. 3013 0
      sql/adminUI_menu_tree_zh.md
  6. 898 0
      sql/adminUI_views_menu_structure.md
  7. 48 0
      sql/analyze_menu_issues.py
  8. 31 0
      sql/check_archive.py
  9. 46 0
      sql/check_menu_detail.py
  10. 60 0
      sql/check_menu_state.py
  11. 53 0
      sql/check_other_children_visible.py
  12. 30 0
      sql/compare_menu_bak.py
  13. 37 0
      sql/compare_missing_ids.py
  14. 26 0
      sql/find_qw_dup.py
  15. 40 0
      sql/fix_tenant_sys_menu_other_parent.sql
  16. 109 0
      sql/fix_tenant_sys_menu_paths.sql
  17. 399 0
      sql/generate_adminUI_menu_doc.py
  18. 439 0
      sql/generate_menu_tree_zh.py
  19. 33 0
      sql/inspect_tenant_menu.py
  20. 34 0
      sql/list_broken_paths.py
  21. 1 0
      sql/menu_tree_his.txt
  22. 1 0
      sql/menu_tree_lobster.txt
  23. 1 0
      sql/menu_tree_qw.txt
  24. 1 0
      sql/menu_tree_store.txt
  25. 1 0
      sql/menu_tree_system.txt
  26. 2 0
      sql/menu_tree_system_all.txt
  27. 75 0
      sql/organize_tenant_sys_menu.sql
  28. 35 0
      sql/organize_tenant_sys_menu_full_readme.sql
  29. 227 0
      sql/organize_tenant_sys_menu_subtree.sql
  30. 348 0
      sql/run_full_menu_organize_and_sync.py
  31. 113 0
      sql/run_organize_menu.py
  32. 40 0
      sql/simulate_api_visible.py
  33. 58 0
      sql/simulate_tenant_menu_api.py
  34. 94 0
      sql/tenant_sys_menu_target_structure.txt
  35. 471 0
      sql/tenant_sys_menu_visible_tree.txt
  36. 9 0
      sql/verify_final.py
  37. 36 0
      sql/verify_menu_ids.py
  38. 26 0
      sql/verify_menu_organize.py
  39. 33 0
      sql/verify_other_menu.py
  40. 38 0
      sql/verify_other_visible.py

+ 21 - 0
sql/_check_f.py

@@ -0,0 +1,21 @@
+import pymysql
+M=dict(host='cq-cdb-8fjmemkb.sql.tencentcdb.com',port=27220,user='root',password='Ylrz_1q2w3e4r5t6y',database='ylrz_saas',charset='utf8mb4')
+c=pymysql.connect(**M);cur=c.cursor()
+cur.execute("SELECT COUNT(*) FROM tenant_sys_menu WHERE menu_type='F'")
+print('total F', cur.fetchone()[0])
+cur.execute("""
+SELECT COUNT(*) FROM tenant_sys_menu f
+JOIN tenant_sys_menu p ON f.parent_id=p.menu_id
+WHERE f.menu_type='F' AND p.menu_type='C'
+""")
+print('F under C', cur.fetchone()[0])
+cur.execute("""
+SELECT p.menu_id, p.menu_name, p.component, COUNT(*) 
+FROM tenant_sys_menu f
+JOIN tenant_sys_menu p ON f.parent_id=p.menu_id
+WHERE f.menu_type='F' AND p.component LIKE 'qw/%'
+GROUP BY p.menu_id ORDER BY COUNT(*) DESC LIMIT 5
+""")
+print('qw pages with most F buttons:')
+for r in cur.fetchall(): print(r)
+c.close()

+ 32 - 0
sql/_check_orphan.py

@@ -0,0 +1,32 @@
+import pymysql
+from collections import defaultdict
+
+M=dict(host='cq-cdb-8fjmemkb.sql.tencentcdb.com',port=27220,user='root',password='Ylrz_1q2w3e4r5t6y',database='ylrz_saas',charset='utf8mb4')
+c=pymysql.connect(**M);cur=c.cursor(pymysql.cursors.DictCursor)
+cur.execute('SELECT menu_id, parent_id, menu_type FROM tenant_sys_menu')
+rows=cur.fetchall()
+ids={r['menu_id'] for r in rows}
+orph=[r for r in rows if r['parent_id'] not in ids and r['parent_id']!=0]
+print('orphans', len(orph))
+by=defaultdict(int)
+for r in rows: by[r['menu_type']]+=1
+print('types', dict(by))
+
+# reachable from roots
+roots=[r for r in rows if r['parent_id']==0]
+ch=defaultdict(list)
+for r in rows: ch[r['parent_id']].append(r)
+seen=set()
+stack=[r['menu_id'] for r in roots]
+while stack:
+    mid=stack.pop()
+    if mid in seen: continue
+    seen.add(mid)
+    for child in ch.get(mid,[]):
+        stack.append(child['menu_id'])
+print('reachable', len(seen), 'total', len(rows), 'missing', len(rows)-len(seen))
+missing=[r for r in rows if r['menu_id'] not in seen]
+by2=defaultdict(int)
+for r in missing: by2[r['menu_type']]+=1
+print('missing by type', dict(by2))
+c.close()

+ 14 - 0
sql/_crm_paths.py

@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M=dict(host='cq-cdb-8fjmemkb.sql.tencentcdb.com',port=27220,user='root',password='Ylrz_1q2w3e4r5t6y',database='ylrz_saas',charset='utf8mb4')
+c=pymysql.connect(**M);cur=c.cursor()
+cur.execute("""
+SELECT menu_id, menu_name, parent_id, path, component, menu_type, visible
+FROM tenant_sys_menu
+WHERE parent_id=32347 OR menu_id=32347 OR parent_id=35020
+ORDER BY parent_id, order_num, menu_id
+""")
+for r in cur.fetchall():
+    print(r)
+c.close()

+ 28 - 0
sql/_preview_menu.py

@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+"""Preview tenant_sys_menu tree stats."""
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+c = pymysql.connect(**M)
+cur = c.cursor()
+cur.execute('SELECT menu_type, COUNT(*) FROM tenant_sys_menu GROUP BY menu_type')
+print('by type', cur.fetchall())
+cur.execute("SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=0")
+print('roots', cur.fetchone()[0])
+cur.execute("SELECT COUNT(*) FROM tenant_sys_menu WHERE visible='0'")
+print('visible', cur.fetchone()[0])
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, menu_type, path, component "
+    "FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' ORDER BY order_num"
+)
+print('visible roots:')
+for r in cur.fetchall():
+    print(r)
+c.close()

+ 3013 - 0
sql/adminUI_menu_tree_zh.md

@@ -0,0 +1,3013 @@
+# 租户管理端菜单完整树(中文)
+
+> 数据来源:`ylrz_saas.tenant_sys_menu` + adminUI 视图/权限补全
+> 生成日期:2026-05-29
+> 总计:**2399** 条(目录 107 / 菜单 594 / 按钮 1698)
+> 树中可达:**1522** 条,孤立节点(parent_id 无效):**877** 条
+
+## 图例
+
+- `[目录]` = M 类型,顶栏/侧栏分组
+- `[菜单]` = C 类型,可路由页面
+- `[按钮]` = F 类型,页面内权限按钮(`perms`)
+- 显示/隐藏 = visible 0/1
+
+---
+
+## 完整树状结构
+
+### 1. 企微管理
+
+- [目录] **企微管理**  `id=32361` path=`qw` component=`-` 显示
+  - [目录] **消息管理**  `id=35001` path=`qwMsg` component=`-` 显示
+    - [菜单] **企微工作任务**  `id=32704` path=`QwWorkTask` component=`qw/QwWorkTask/index` 显示
+    - [菜单] **企微**  `id=32705` path=`QwWorkTaskQw` component=`qw/QwWorkTask/qw/index` 显示
+    - [菜单] **群消息**  `id=32739` path=`groupMsg` component=`qw/groupMsg/index` 显示
+    - [菜单] **群消息明细**  `id=32740` path=`groupMsgItem` component=`qw/groupMsgItem/index` 显示
+    - [菜单] **企微推送统计**  `id=32745` path=`qwPushCount` component=`qw/qwPushCount/index/index` 显示
+    - [菜单] **租户管理-操作记录**  `id=32749` path=`record` component=`qw/record/index/index` 显示
+  - [目录] **客户管理**  `id=35002` path=`qwCustomer` component=`-` 显示
+    - [菜单] **分配规则**  `id=32708` path=`assignRule` component=`qw/assignRule/index` 显示
+    - [菜单] **联系人批次**  `id=32714` path=`contactBatch` component=`qw/contactBatch/index` 显示
+    - [菜单] **渠道码**  `id=32715` path=`contactWay` component=`qw/contactWay/index` 显示
+    - [菜单] **联系人方式日志**  `id=32716` path=`contactWayLogs` component=`qw/contactWayLogs/index` 显示
+    - [菜单] **客户链接**  `id=32717` path=`customerLink` component=`qw/customerLink/index` 显示
+    - [菜单] **引流链接**  `id=32718` path=`drainageLink` component=`qw/drainageLink/index` 显示
+    - [菜单] **引流链接日志**  `id=32719` path=`drainageLinkLogs` component=`qw/drainageLinkLogs/index` 显示
+    - [菜单] **外部联系人流失**  `id=32720` path=`externalContactLoss` component=`qw/externalContactLoss/index` 显示
+    - [菜单] **外部联系人阶段**  `id=32721` path=`externalContactStage` component=`qw/externalContactStage/index` 显示
+    - [菜单] **外部联系人转移**  `id=32722` path=`externalContactTransfer` component=`qw/externalContactTransfer/index` 显示
+    - [菜单] **外部联系人转移审核**  `id=32723` path=`externalContactTransferAudit` component=`qw/externalContactTransferAudit/index` 显示
+    - [菜单] **外部联系人转移企业审核**  `id=32724` path=`externalContactTransferCompanyAudit` component=`qw/externalContactTransferCompanyAudit/index/index` 显示
+    - [菜单] **外部联系人转移日志**  `id=32725` path=`externalContactTransferLog` component=`qw/externalContactTransferLog/index` 显示
+    - [菜单] **外部联系人未分配**  `id=32726` path=`externalContactUnassigned` component=`qw/externalContactUnassigned/index` 显示
+    - [菜单] **企微外部联系人**  `id=32755` path=`qwExternalContact` component=`qwExternalContact/index/index` 显示
+  - [目录] **群聊管理**  `id=35003` path=`qwGroup` component=`-` 显示
+    - [菜单] **群实际**  `id=32733` path=`groupActual` component=`qw/groupActual/index` 显示
+    - [菜单] **群chat统计**  `id=32734` path=`groupChatStatistic` component=`qw/groupChatStatistic/index` 显示
+    - [菜单] **群chat转移**  `id=32735` path=`groupChatTransfer` component=`qw/groupChatTransfer/index` 显示
+    - [菜单] **群chat转移日志**  `id=32736` path=`groupChatTransferLog` component=`qw/groupChatTransferLog/index` 显示
+    - [菜单] **群chat转移on定时任务**  `id=32737` path=`groupChatTransferOnJob` component=`qw/groupChatTransferOnJob/index` 显示
+    - [菜单] **群直播码**  `id=32738` path=`groupLiveCode` component=`qw/groupLiveCode/index` 显示
+  - [目录] **朋友圈**  `id=35004` path=`qwMoments` component=`-` 显示
+    - [菜单] **朋友圈**  `id=32727` path=`friendCircle` component=`qw/friendCircle/index` 显示
+    - [菜单] **friend圈任务**  `id=32728` path=`friendCircleTask` component=`qw/friendCircleTask/index` 显示
+    - [菜单] **friend评论**  `id=32729` path=`friendComments` component=`qw/friendComments/index` 显示
+    - [菜单] **friend客户列表**  `id=32730` path=`friendCustomerList` component=`qw/friendCustomerList/index` 显示
+    - [菜单] **friend素材**  `id=32731` path=`friendMaterial` component=`qw/friendMaterial/index` 显示
+    - [菜单] **friend欢迎语明细**  `id=32732` path=`friendWelcomeItem` component=`qw/friendWelcomeItem/index` 显示
+  - [目录] **引流管理**  `id=35005` path=`qwDrainage` component=`-` 显示
+    - [菜单] **app广告报表**  `id=32706` path=`appAdvertisingReport` component=`qw/appAdvertisingReport/index` 显示
+  - [目录] **标签管理**  `id=35006` path=`qwTag` component=`-` 显示
+    - [菜单] **标签**  `id=32751` path=`tag` component=`qw/tag/index` 显示
+    - [菜单] **标签组**  `id=32752` path=`tagGroup` component=`qw/tagGroup/index` 显示
+    - [菜单] **自动标签**  `id=32900` path=`autoTags` component=`qw/autoTags/index` 显示
+  - [目录] **企微设置**  `id=35007` path=`qwSetting` component=`-` 显示
+    - [菜单] **applyiPad**  `id=32707` path=`applyIpad` component=`qw/applyIpad/index` 显示
+    - [菜单] **企业用户**  `id=32713` path=`companyUser` component=`qw/companyUser/index` 显示
+    - [菜单] **素材**  `id=32741` path=`material` component=`qw/material/index` 显示
+    - [菜单] **企微部门**  `id=32744` path=`qwDept` component=`qw/qwDept/index/index` 显示
+    - [菜单] **企微用户del流失统计**  `id=32746` path=`qwUserDelLossStatistics` component=`qw/qwUserDelLossStatistics/index` 显示
+    - [菜单] **用户行为数据**  `id=32753` path=`userBehaviorData` component=`qw/userBehaviorData/index` 显示
+    - [菜单] **欢迎语**  `id=32754` path=`welcome` component=`qw/welcome/index` 显示
+
+### 2. 微信管理
+
+- [目录] **微信管理**  `id=32380` path=`wx` component=`-` 显示
+  - [菜单] **网关账户**  `id=32540` path=`gwAccount` component=`gw/gwAccount/index` 显示
+  - [目录] **微信账号**  `id=35010` path=`wxAccount` component=`-` 显示
+    - [菜单] **个微账号**  `id=32482` path=`wxAccount` component=`company/wxAccount/index` 显示
+  - [目录] **微信对话**  `id=35011` path=`wxDialog` component=`-` 显示
+    - [菜单] **微信dialog**  `id=32483` path=`wxDialog` component=`company/wxDialog/index` 显示
+  - [目录] **微信用户**  `id=35012` path=`wxUser` component=`-` 显示
+    - [菜单] **个微用户**  `id=32484` path=`wxUser` component=`company/wxUser/index` 显示
+  - [目录] **微信用户组**  `id=35013` path=`wxUserGroup` component=`-` 显示
+    - [菜单] **微信用户分组**  `id=32485` path=`wxUserGroup` component=`company/wxUserGroup/index` 显示
+
+### 3. CRM客户
+
+- [目录] **CRM客户**  `id=32347` path=`crm` component=`-` 显示
+  - [目录] **CRM客户管理**  `id=35020` path=`crmCustomer` component=`-` 显示
+    - [菜单] **客户aichat**  `id=32521` path=`customerAiChat` component=`crm/customerAiChat/index` 显示
+    - [菜单] **客户分配**  `id=32522` path=`customerAssign` component=`crm/customerAssign/index/index` 显示
+    - [菜单] **客户business**  `id=32523` path=`customerBusiness` component=`crm/customerBusiness/index` 显示
+    - [菜单] **客户contacts**  `id=32524` path=`customerContacts` component=`crm/customerContacts/index` 显示
+    - [菜单] **客户ext**  `id=32525` path=`customerExt` component=`crm/customerExt/index` 显示
+    - [菜单] **客户level**  `id=32526` path=`customerLevel` component=`crm/customerLevel/index/index` 显示
+    - [菜单] **客户日志**  `id=32527` path=`customerLogs` component=`crm/customerLogs/index` 显示
+  - [目录] **商机管理**  `id=35021` path=`crmBusiness` component=`-` 隐藏
+  - [目录] **AI辅助**  `id=35023` path=`crmAi` component=`-` 隐藏
+
+### 4. 会员管理
+
+- [目录] **会员管理**  `id=32357` path=`member` component=`-` 显示
+  - [菜单] **黑名单**  `id=32842` path=`blacklist` component=`user/blacklist/index` 显示
+  - [菜单] **category**  `id=32843` path=`category` component=`user/complaint/category/index` 显示
+  - [菜单] **小黑屋**  `id=32844` path=`darkRoom` component=`user/darkRoom/index` 显示
+  - [菜单] **积分管理**  `id=32845` path=`integral` component=`user/integral/index` 显示
+  - [菜单] **CRM客户-消息管理**  `id=32846` path=`msg` component=`user/msg/index/index` 显示
+  - [菜单] **充值模板**  `id=32847` path=`rechargeTemplate` component=`user/rechargeTemplate/index` 显示
+  - [菜单] **转接管理**  `id=32848` path=`transfer` component=`user/transfer/index` 显示
+
+### 5. 诊所管理
+
+- [目录] **诊所管理**  `id=32351` path=`his` component=`-` 显示
+  - [菜单] **租户管理-操作记录**  `id=32539` path=`record` component=`food/record/index` 显示
+
+### 6. 商城管理
+
+- [目录] **商城管理**  `id=32369` path=`store` component=`-` 显示
+  - [目录] **订单管理**  `id=35040` path=`storeOrder` component=`-` 显示
+    - [菜单] **售后**  `id=32798` path=`storeAfterSales` component=`store/storeAfterSales/index/index` 显示
+    - [菜单] **商城aftersales明细**  `id=32799` path=`storeAfterSalesItem` component=`store/storeAfterSalesItem/index/index` 显示
+    - [菜单] **商城aftersalesstatus**  `id=32800` path=`storeAfterSalesStatus` component=`store/storeAfterSalesStatus/index/index` 显示
+    - [菜单] **fs随访报表**  `id=32772` path=`FsFollowReport` component=`store/FsFollowReport/index` 显示
+    - [菜单] **推广订单**  `id=32773` path=`PromotionOrder` component=`store/PromotionOrder/index/index` 显示
+    - [菜单] **诊所管理-用药报告**  `id=32777` path=`drugReport` component=`store/drugReport/index` 显示
+    - [菜单] **诊所管理-用药统计**  `id=32778` path=`drugReportCount` component=`store/drugReportCount/index` 显示
+    - [菜单] **health商城订单**  `id=32781` path=`healthStoreOrder` component=`store/healthStoreOrder/index/index` 显示
+    - [菜单] **诊所管理-问诊订单报告**  `id=32787` path=`inquiryOrderReport` component=`store/inquiryOrderReport/index` 显示
+    - [菜单] **订单管理**  `id=32806` path=`storeOrder` component=`store/storeOrder/index/index` 显示
+    - [菜单] **订单审核**  `id=32807` path=`storeOrderAudit` component=`store/storeOrderAudit/index/index` 显示
+    - [菜单] **商城订单明细**  `id=32808` path=`storeOrderItem` component=`store/storeOrderItem/index/index` 显示
+    - [菜单] **商城订单公告**  `id=32809` path=`storeOrderNotice` component=`store/storeOrderNotice/index/index` 显示
+    - [菜单] **线下订单**  `id=32810` path=`storeOrderOffline` component=`store/storeOrderOffline/index/index` 显示
+    - [菜单] **商城订单status**  `id=32811` path=`storeOrderStatus` component=`store/storeOrderStatus/index/index` 显示
+  - [目录] **商品管理**  `id=35041` path=`storeProduct` component=`-` 显示
+    - [菜单] **套餐**  `id=32790` path=`package` component=`store/package/index` 显示
+    - [菜单] **处方**  `id=32791` path=`prescribe` component=`store/prescribe/index/index` 显示
+    - [菜单] **处方drug**  `id=32792` path=`prescribeDrug` component=`store/prescribeDrug/index/index` 显示
+    - [菜单] **运费templates**  `id=32794` path=`shippingTemplates` component=`store/shippingTemplates/index/index` 显示
+    - [菜单] **运费templatesfree**  `id=32795` path=`shippingTemplatesFree` component=`store/shippingTemplatesFree/index/index` 显示
+    - [菜单] **运费templatesregion**  `id=32796` path=`shippingTemplatesRegion` component=`store/shippingTemplatesRegion/index/index` 显示
+    - [菜单] **商城商品属性**  `id=32812` path=`storeProductAttr` component=`store/storeProductAttr/index/index` 显示
+    - [菜单] **商城商品属性value**  `id=32813` path=`storeProductAttrValue` component=`store/storeProductAttrValue/index/index` 显示
+    - [菜单] **诊所管理-门店商品分类**  `id=32814` path=`storeProductCategory` component=`store/storeProductCategory/index/index` 显示
+    - [菜单] **商城商品详情**  `id=32815` path=`storeProductDetails` component=`store/storeProductDetails/index/index` 显示
+    - [菜单] **商城商品分组**  `id=32816` path=`storeProductGroup` component=`store/storeProductGroup/index/index` 显示
+    - [菜单] **商城商品关联**  `id=32817` path=`storeProductRelation` component=`store/storeProductRelation/index/index` 显示
+    - [菜单] **商城商品回复**  `id=32818` path=`storeProductReply` component=`store/storeProductReply/index/index` 显示
+    - [菜单] **商城商品规则**  `id=32819` path=`storeProductRule` component=`store/storeProductRule/index/index` 显示
+    - [菜单] **商城商品模板**  `id=32820` path=`storeProductTemplate` component=`store/storeProductTemplate/index/index` 显示
+  - [目录] **门店运营**  `id=35042` path=`storeOps` component=`-` 显示
+    - [菜单] **诊所管理-广告管理**  `id=32774` path=`adv` component=`store/adv/index/index` 显示
+    - [菜单] **collection排班**  `id=32775` path=`collectionSchedule` component=`store/collectionSchedule/index` 显示
+    - [菜单] **诊所管理-优惠券**  `id=32776` path=`coupon` component=`store/coupon/index` 显示
+    - [菜单] **诊所管理-导出任务**  `id=32779` path=`exportTask` component=`store/exportTask/index` 显示
+    - [菜单] **诊所管理-健康档案**  `id=32780` path=`healthRecord` component=`store/healthRecord/index` 显示
+    - [菜单] **healthtongue**  `id=32782` path=`healthTongue` component=`store/healthTongue/index` 显示
+    - [菜单] **home文章**  `id=32783` path=`homeArticle` component=`store/homeArticle/index/index` 显示
+    - [菜单] **home分类**  `id=32784` path=`homeCategory` component=`store/homeCategory/index/index` 显示
+    - [菜单] **homeview**  `id=32785` path=`homeView` component=`store/homeView/index/index` 显示
+    - [菜单] **诊所管理-门店管理**  `id=32786` path=`store` component=`store/index/index` 显示
+    - [菜单] **系统管理-菜单管理**  `id=32788` path=`menu` component=`store/menu/index/index` 显示
+    - [菜单] **my健康tongue**  `id=32789` path=`myHealthTongue` component=`store/myHealthTongue/index` 显示
+    - [菜单] **recommend**  `id=32793` path=`recommend` component=`store/recommend/index/index` 显示
+    - [菜单] **诊所管理-门店活动**  `id=32797` path=`storeActivity` component=`store/storeActivity/index/index` 显示
+    - [菜单] **商城购物车**  `id=32801` path=`storeCart` component=`store/storeCart/index/index` 显示
+    - [菜单] **优惠券**  `id=32802` path=`storeCoupon` component=`store/storeCoupon/index/index` 显示
+    - [菜单] **商城优扣券issue**  `id=32803` path=`storeCouponIssue` component=`store/storeCouponIssue/index/index` 显示
+    - [菜单] **商城优扣券issue用户**  `id=32804` path=`storeCouponIssueUser` component=`store/storeCouponIssueUser/index/index` 显示
+    - [菜单] **商城优扣券用户**  `id=32805` path=`storeCouponUser` component=`store/storeCouponUser/index/index` 显示
+    - [菜单] **门店管理**  `id=32821` path=`storeShop` component=`store/storeShop/index/index` 显示
+    - [菜单] **商城shop员工**  `id=32822` path=`storeShopStaff` component=`store/storeShopStaff/index/index` 显示
+    - [菜单] **商城访问**  `id=32823` path=`storeVisit` component=`store/storeVisit/index/index` 显示
+    - [菜单] **诊所管理-用户优惠券**  `id=32824` path=`userCoupon` component=`store/userCoupon/index` 显示
+    - [菜单] **用户promoter申请**  `id=32825` path=`userPromoterApply` component=`store/userPromoterApply/index/index` 显示
+
+### 7. 直播管理
+
+- [目录] **直播管理**  `id=32353` path=`live` component=`-` 显示
+  - [菜单] **直播数据**  `id=32676` path=`liveData` component=`liveData/index/index` 显示
+  - [目录] **直播运营**  `id=35050` path=`liveOps` component=`-` 显示
+    - [菜单] **评论**  `id=32645` path=`comment` component=`live/comment/index` 显示
+    - [菜单] **health直播订单**  `id=32646` path=`healthLiveOrder` component=`live/healthLiveOrder/index/index` 显示
+    - [菜单] **直播配置**  `id=32647` path=`live` component=`live/index/index` 显示
+    - [菜单] **issue**  `id=32648` path=`issue` component=`live/issue/index/index` 显示
+    - [菜单] **直播配置**  `id=32649` path=`live2` component=`live/live/index` 显示
+    - [菜单] **直播aftersales**  `id=32650` path=`liveAfterSales` component=`live/liveAfterSales/index/index` 显示
+    - [菜单] **直播afterasales**  `id=32651` path=`liveAfteraSales` component=`live/liveAfteraSales/index` 显示
+    - [菜单] **直播配置**  `id=32652` path=`liveConfig` component=`live/liveConfig/index` 显示
+    - [菜单] **直播控制台**  `id=32653` path=`liveConsole` component=`live/liveConsole/index` 显示
+    - [菜单] **直播优扣券issue**  `id=32654` path=`liveCouponIssue` component=`live/liveCouponIssue/index` 显示
+    - [菜单] **直播优扣券issue用户**  `id=32655` path=`liveCouponIssueUser` component=`live/liveCouponIssueUser/index` 显示
+    - [菜单] **直播优扣券用户**  `id=32656` path=`liveCouponUser` component=`live/liveCouponUser/index` 显示
+    - [菜单] **直播数据**  `id=32657` path=`liveData` component=`live/liveData/index` 显示
+    - [菜单] **直播lottery商品conf**  `id=32658` path=`liveLotteryProductConf` component=`live/liveLotteryProductConf/index` 显示
+    - [菜单] **直播订单status**  `id=32659` path=`liveOrderStatus` component=`live/liveOrderStatus/index` 显示
+    - [菜单] **直播orderitems**  `id=32660` path=`liveOrderitems` component=`live/liveOrderitems/index` 显示
+    - [菜单] **直播分账**  `id=32661` path=`liveProfit` component=`live/liveProfit/index` 显示
+    - [菜单] **直播问题**  `id=32662` path=`liveQuestion` component=`live/liveQuestion/index` 显示
+    - [菜单] **直播问题题库**  `id=32663` path=`liveQuestionBank` component=`live/liveQuestionBank/index` 显示
+    - [菜单] **直播奖励记录**  `id=32664` path=`liveRewardRecord` component=`live/liveRewardRecord/index` 显示
+    - [菜单] **直播流量日志**  `id=32665` path=`liveTrafficLog` component=`live/liveTrafficLog/index` 显示
+    - [菜单] **直播用户收藏**  `id=32666` path=`liveUserFavorite` component=`live/liveUserFavorite/index/index` 显示
+    - [菜单] **直播用户随访**  `id=32667` path=`liveUserFollow` component=`live/liveUserFollow/index/index` 显示
+    - [菜单] **直播用户like**  `id=32668` path=`liveUserLike` component=`live/liveUserLike/index/index` 显示
+    - [菜单] **直播观看日志**  `id=32669` path=`liveWatchLog` component=`live/liveWatchLog/index` 显示
+    - [菜单] **直播观看用户**  `id=32670` path=`liveWatchUser` component=`live/liveWatchUser/index` 显示
+    - [菜单] **订单**  `id=32671` path=`order` component=`live/order/index` 显示
+    - [菜单] **租户管理-操作记录**  `id=32672` path=`record` component=`live/record/index/index` 显示
+    - [菜单] **talent直播信息**  `id=32673` path=`talentLiveInfo` component=`live/talentLiveInfo/index` 显示
+    - [菜单] **task**  `id=32674` path=`task` component=`live/task/index/index` 显示
+    - [菜单] **流量日志**  `id=32675` path=`trafficLog` component=`live/trafficLog/index/index` 显示
+  - [目录] **直播互动**  `id=35051` path=`liveInteract` component=`-` 隐藏
+  - [目录] **直播订单**  `id=35052` path=`liveOrder` component=`-` 隐藏
+  - [目录] **直播数据**  `id=35053` path=`liveData` component=`-` 隐藏
+
+### 8. 课程管理
+
+- [目录] **课程管理**  `id=32345` path=`course` component=`-` 显示
+  - [菜单] **课程配置**  `id=32520` path=`course` component=`courseFinishTemp/course/index/index` 显示
+  - [目录] **课程内容**  `id=35060` path=`courseContent` component=`-` 显示
+    - [菜单] **素材**  `id=32486` path=`Material` component=`course/Material/index` 显示
+    - [菜单] **课程答案日志**  `id=32487` path=`courseAnswerLog` component=`course/courseAnswerLog/index/index` 显示
+    - [菜单] **课程answerlogs**  `id=32488` path=`courseAnswerlogs` component=`course/courseAnswerlogs/index` 显示
+    - [菜单] **结课模板**  `id=32489` path=`courseFinishTemp` component=`course/courseFinishTemp/index` 显示
+    - [菜单] **课程playsource配置**  `id=32490` path=`coursePlaySourceConfig` component=`course/coursePlaySourceConfig/index` 显示
+    - [菜单] **课程问题分类**  `id=32491` path=`courseQuestionCategory` component=`course/courseQuestionCategory/index/index` 显示
+    - [菜单] **课程redpacket统计**  `id=32492` path=`courseRedPacketStatistics` component=`course/courseRedPacketStatistics/index` 显示
+    - [菜单] **课程用户统计**  `id=32493` path=`courseUserStatistics` component=`course/courseUserStatistics/index` 显示
+    - [菜单] **企微**  `id=32494` path=`qw` component=`course/courseUserStatistics/qw/index` 显示
+    - [菜单] **课程观看评论**  `id=32495` path=`courseWatchComment` component=`course/courseWatchComment/index` 显示
+    - [菜单] **课程观看日志**  `id=32496` path=`courseWatchLog` component=`course/courseWatchLog/index` 显示
+    - [菜单] **企微**  `id=32497` path=`qw2` component=`course/courseWatchLog/qw/index` 显示
+    - [菜单] **huaweicloud统计**  `id=32498` path=`huaweiCloudStatistics` component=`course/huaweiCloudStatistics/index` 显示
+    - [菜单] **课程配置**  `id=32499` path=`course` component=`course/index/index` 显示
+    - [菜单] **period**  `id=32500` path=`period` component=`course/period/index/index` 显示
+    - [菜单] **playsource配置**  `id=32501` path=`playSourceConfig` component=`course/playSourceConfig/index/index` 显示
+    - [菜单] **push**  `id=32502` path=`push` component=`course/push/index` 显示
+    - [菜单] **training营**  `id=32504` path=`trainingCamp` component=`course/trainingCamp/index/index` 显示
+    - [菜单] **用户课程评论like**  `id=32505` path=`userCourseCommentLike` component=`course/userCourseCommentLike/index/index` 显示
+    - [菜单] **用户课程收藏**  `id=32506` path=`userCourseFavorite` component=`course/userCourseFavorite/index/index` 显示
+    - [菜单] **用户课程notelike**  `id=32507` path=`userCourseNoteLike` component=`course/userCourseNoteLike/index/index` 显示
+    - [菜单] **用户课程期数**  `id=32508` path=`userCoursePeriod` component=`course/userCoursePeriod/index` 显示
+    - [菜单] **用户课程视频**  `id=32509` path=`userCourseVideo` component=`course/userCourseVideo/index/index` 显示
+    - [菜单] **用户达人随访**  `id=32510` path=`userTalentFollow` component=`course/userTalentFollow/index/index` 显示
+    - [菜单] **用户视频评论like**  `id=32511` path=`userVideoCommentLike` component=`course/userVideoCommentLike/index/index` 显示
+    - [菜单] **用户视频收藏**  `id=32512` path=`userVideoFavorite` component=`course/userVideoFavorite/index/index` 显示
+    - [菜单] **用户视频like**  `id=32513` path=`userVideoLike` component=`course/userVideoLike/index/index` 显示
+    - [菜单] **用户视频tags**  `id=32514` path=`userVideoTags` component=`course/userVideoTags/index` 显示
+    - [菜单] **用户视频view**  `id=32515` path=`userVideoView` component=`course/userVideoView/index/index` 显示
+    - [菜单] **用户观看课程统计**  `id=32516` path=`userWatchCourseStatistics` component=`course/userWatchCourseStatistics/index` 显示
+    - [菜单] **用户观看课程total统计**  `id=32517` path=`userWatchCourseTotalStatistics` component=`course/userWatchCourseTotalStatistics/index` 显示
+    - [菜单] **用户观看统计**  `id=32518` path=`userWatchStatistics` component=`course/userWatchStatistics/index` 显示
+    - [菜单] **视频tags**  `id=32519` path=`videoTags` component=`course/videoTags/index/index` 显示
+  - [目录] **课程资源**  `id=35061` path=`courseResource` component=`-` 隐藏
+  - [目录] **学习管理**  `id=35062` path=`courseStudy` component=`-` 隐藏
+  - [目录] **课程统计**  `id=35063` path=`courseStat` component=`-` 隐藏
+
+### 9. AI聊天
+
+- [目录] **AI聊天**  `id=32348` path=`fastGpt` component=`-` 显示
+  - [菜单] **fastgptext用户标签**  `id=32381` path=`FastGptExtUserTag` component=`FastGptExtUserTag/index/index` 显示
+  - [菜单] **消息日志**  `id=32425` path=`chatMsgLogs` component=`chat/chatMsgLogs/index` 显示
+  - [目录] **AI对话管理**  `id=35070` path=`aiChat` component=`-` 显示
+    - [菜单] **AI关键词管理**  `id=32528` path=`fastGptChatKeyword` component=`fastGpt/fastGptChatKeyword/index` 显示
+    - [菜单] **AI对话消息**  `id=32529` path=`fastGptChatMsg` component=`fastGpt/fastGptChatMsg/index` 显示
+    - [菜单] **AI对话消息日志**  `id=32530` path=`fastGptChatMsgLogs` component=`fastGpt/fastGptChatMsgLogs/index` 显示
+    - [菜单] **fastgptchat替换text**  `id=32531` path=`fastGptChatReplaceText` component=`fastGpt/fastGptChatReplaceText/index/index` 显示
+    - [菜单] **AI会话记录**  `id=32532` path=`fastGptChatSession` component=`fastGpt/fastGptChatSession/index` 显示
+    - [菜单] **知识采集**  `id=32533` path=`fastGptCollection` component=`fastGpt/fastGptCollection/index` 显示
+    - [菜单] **采集数据**  `id=32534` path=`fastGptCollentionData` component=`fastGpt/fastGptCollentionData/index` 显示
+    - [菜单] **数据集**  `id=32535` path=`fastGptDataset` component=`fastGpt/fastGptDataset/index` 显示
+    - [菜单] **AI用户**  `id=32537` path=`fastGptUser` component=`fastGpt/fastGptUser/index` 显示
+  - [目录] **角色管理**  `id=35071` path=`aiRole` component=`-` 隐藏
+  - [菜单] **AI聊天质检**  `id=29186` path=`aiChatQuality` component=`aiChatQuality/index` 显示
+    - └─ [按钮] **新增**  `perms=admin:aiChatQuality:add`
+    - └─ [按钮] **按钮**  `perms=admin:aiChatQuality:batch`
+    - └─ [按钮] **修改**  `perms=admin:aiChatQuality:edit`
+    - └─ [按钮] **查询**  `perms=admin:aiChatQuality:query`
+    - └─ [按钮] **删除**  `perms=admin:aiChatQuality:remove`
+  - [目录] **知识管理**  `id=35072` path=`aiKnowledge` component=`-` 隐藏
+  - [目录] **关键词管理**  `id=35073` path=`aiKeyword` component=`-` 隐藏
+  - [目录] **AI质检**  `id=35074` path=`aiQuality` component=`-` 隐藏
+  - [目录] **统计分析**  `id=35075` path=`aiStat` component=`-` 隐藏
+
+### 10. 龙虸引擎
+
+- [目录] **龙虸引擎**  `id=32355` path=`lobster` component=`-` 显示
+  - [目录] **龙虸工作流**  `id=35080` path=`lobsterFlow` component=`-` 显示
+    - [菜单] **接口注册中心**  `id=32677` path=`api-registry` component=`lobster/api-registry/index` 显示
+    - [菜单] **聚合聊天**  `id=32679` path=`chat-aggregate` component=`lobster/chat-aggregate/index` 显示
+    - [菜单] **死信队列**  `id=32680` path=`dead-letter` component=`lobster/dead-letter/index` 显示
+    - [菜单] **节点审核**  `id=32681` path=`event-audit` component=`lobster/event-audit/index` 显示
+    - [菜单] **实例监控**  `id=32682` path=`instance` component=`lobster/instance/index` 显示
+    - [菜单] **AI优化建议**  `id=32684` path=`optimization` component=`lobster/optimization/index` 显示
+    - [菜单] **提示词管理**  `id=32685` path=`prompt` component=`lobster/prompt/index` 显示
+    - [菜单] **销冠语料学习**  `id=32686` path=`sales-corpus` component=`lobster/sales-corpus/index` 显示
+    - [菜单] **工作流模板库**  `id=32687` path=`template` component=`lobster/template/index` 显示
+    - [菜单] **工作流画布**  `id=32688` path=`workflow-canvas` component=`lobster/workflow-canvas/index` 显示
+    - [菜单] **龙虾工作流**  `id=32481` path=`workflowLobster` component=`company/workflowLobster/index` 显示
+  - [菜单] **工作流生成**  `id=32329` path=`workflow-generate` component=`lobster/workflow-generate/index` 显示
+
+### 11. 广告投放
+
+- [目录] **广告投放**  `id=32331` path=`ad` component=`-` 显示
+  - [菜单] **广告主管理**  `id=32406` path=`advertiser` component=`adv/advertiser/index` 显示
+  - [目录] **投放运营**  `id=35090` path=`adOps` component=`-` 显示
+    - [菜单] **广告账户**  `id=32382` path=`adAccount` component=`ad/adAccount/index` 显示
+    - [菜单] **抖音API**  `id=32383` path=`adDyApi` component=`ad/adDyApi/index/index` 显示
+    - [菜单] **click日志**  `id=32384` path=`clickLog` component=`ad/clickLog/index/index` 显示
+  - [菜单] **回调账户**  `id=32407` path=`callbackAccount` component=`adv/callbackAccount/index` 显示
+  - [菜单] **渠道管理**  `id=32408` path=`channel` component=`adv/channel/index` 显示
+  - [菜单] **配置管理**  `id=32409` path=`configuration` component=`adv/configuration/index` 显示
+  - [菜单] **转化日志**  `id=32410` path=`conversionLog` component=`adv/conversionLog/index` 显示
+  - [菜单] **自定义推广账户**  `id=32411` path=`customPromotionAccount` component=`adv/customPromotionAccount/index` 显示
+  - [菜单] **域名管理**  `id=32412` path=`domain` component=`adv/domain/index` 显示
+  - [菜单] **落地页模板**  `id=32413` path=`landingPageTemplate` component=`adv/landingPageTemplate/index` 显示
+  - [菜单] **项目管理**  `id=32414` path=`project` component=`adv/project/index` 显示
+  - [菜单] **推广账户**  `id=32415` path=`promotionAccount` component=`adv/promotionAccount/index` 显示
+  - [菜单] **站点管理**  `id=32416` path=`site` component=`adv/site/index` 显示
+  - [菜单] **广告统计**  `id=32417` path=`statistics` component=`adv/statistics/index` 显示
+  - [菜单] **追踪链接**  `id=32418` path=`trackingLink` component=`adv/trackingLink/index` 显示
+
+### 12. 系统管理
+
+- [目录] **系统管理**  `id=32372` path=`system` component=`-` 显示
+  - [目录] **组织管理**  `id=35100` path=`sysOrg` component=`-` 显示
+    - [菜单] **部门管理**  `id=35204` path=`sysDept` component=`system/dept/index` 显示
+    - [菜单] **岗位管理**  `id=35205` path=`sysPost` component=`system/post/index` 显示
+    - [菜单] **企业申请**  `id=32431` path=`companyApply` component=`company/companyApply/index` 显示
+    - [菜单] **企业bind用户**  `id=32432` path=`companyBindUser` component=`company/companyBindUser/index` 显示
+    - [菜单] **企业客户端**  `id=32433` path=`companyClient` component=`company/companyClient/index` 显示
+    - [菜单] **企业部门**  `id=32436` path=`companyDept` component=`company/companyDept/index` 显示
+    - [菜单] **企业域名**  `id=32437` path=`companyDomain` component=`company/companyDomain/index` 显示
+    - [菜单] **企业域名bind**  `id=32438` path=`companyDomainBind` component=`company/companyDomainBind/index` 显示
+    - [菜单] **企业岗位**  `id=32443` path=`companyPost` component=`company/companyPost/index` 显示
+    - [菜单] **企业usercard**  `id=32455` path=`companyUserCard` component=`company/companyUser/card/index` 显示
+    - [菜单] **企业userprofile**  `id=32456` path=`companyUserProfile` component=`company/companyUser/profile/index` 显示
+    - [菜单] **企业用户岗位**  `id=32457` path=`companyUserPost` component=`company/companyUserPost/index` 显示
+    - [菜单] **诊所管理-企业管理**  `id=32473` path=`companyIndex` component=`company/index/index` 显示
+    - [菜单] **排班**  `id=32475` path=`schedule` component=`company/schedule/index` 显示
+    - [菜单] **排班报表**  `id=32476` path=`scheduleReport` component=`company/scheduleReport/index` 显示
+    - [菜单] **tcm排班报表**  `id=32477` path=`tcmScheduleReport` component=`company/tcmScheduleReport/index` 显示
+  - [目录] **权限管理**  `id=35101` path=`sysPerm` component=`-` 显示
+    - [菜单] **用户管理**  `id=35201` path=`sysUser` component=`system/user/index` 显示
+    - [菜单] **角色管理**  `id=35202` path=`sysRole` component=`system/role/index` 显示
+    - [菜单] **菜单管理**  `id=35203` path=`sysMenu` component=`system/menu/index` 显示
+    - [菜单] **企业菜单**  `id=32440` path=`companyMenu` component=`company/companyMenu/index` 显示
+    - [菜单] **企业角色**  `id=32447` path=`companyRole` component=`company/companyRole/index` 显示
+    - [菜单] **企业角色部门**  `id=32448` path=`companyRoleDept` component=`company/companyRoleDept/index` 显示
+    - [菜单] **企业角色菜单**  `id=32449` path=`companyRoleMenu` component=`company/companyRoleMenu/index` 显示
+  - [目录] **通信管理**  `id=35102` path=`sysVoice` component=`-` 显示
+    - [菜单] **inbound呼叫管理**  `id=32427` path=`inboundCallManage` component=`company/aiModel/inboundCallManage/index` 显示
+    - [菜单] **企业短信日志**  `id=32451` path=`companySmsLogs` component=`company/companySmsLogs/index` 显示
+    - [菜单] **企业短信订单**  `id=32452` path=`companySmsOrder` component=`company/companySmsOrder/index` 显示
+    - [菜单] **企业短信套餐**  `id=32453` path=`companySmsPackage` component=`company/companySmsPackage/index` 显示
+    - [菜单] **企业短信模板**  `id=32454` path=`companySmsTemp` component=`company/companySmsTemp/index` 显示
+    - [菜单] **AI外呼工作流**  `id=32470` path=`companyWorkflow` component=`company/companyWorkflow/index` 显示
+    - [菜单] **企业工作流管理**  `id=32471` path=`companyWorkflowManage` component=`company/companyWorkflowManage/index` 显示
+    - [菜单] **企业微信**  `id=32472` path=`companyWx` component=`company/companyWx/index` 显示
+  - [目录] **日志管理**  `id=35105` path=`sysLog` component=`-` 显示
+    - [菜单] **企业登录日志**  `id=32439` path=`companyLogininfor` component=`company/companyLogininfor/index` 显示
+    - [菜单] **企业oper日志**  `id=32442` path=`companyOperLog` component=`company/companyOperLog/index` 显示
+  - [目录] **系统设置**  `id=35106` path=`sysConfig` component=`-` 显示
+    - [菜单] **字典管理**  `id=35206` path=`sysDict` component=`system/dict/index` 显示
+    - [菜单] **参数设置**  `id=35207` path=`sysConfigPage` component=`system/config/index` 显示
+    - [菜单] **通知公告**  `id=35208` path=`sysNotice` component=`system/notice/index` 显示
+    - [菜单] **违规词语**  `id=35209` path=`sysKeyword` component=`system/keyword/index` 显示
+    - [菜单] **AI工作流**  `id=32430` path=`aiWorkflow` component=`company/aiWorkflow/index` 显示
+    - [菜单] **企业配置**  `id=32434` path=`companyConfig` component=`company/companyConfig/index` 显示
+    - [菜单] **流量**  `id=32478` path=`traffic` component=`company/traffic/index` 显示
+    - [菜单] **流量日志**  `id=32479` path=`trafficLog` component=`company/trafficLog/index` 显示
+    - [菜单] **工作流外部API**  `id=32480` path=`workflowExternalApi` component=`company/workflowExternalApi/index` 显示
+    - [菜单] **企业set**  `id=32832` path=`companySet` component=`system/set/index/index` 显示
+    - [菜单] **用户profile**  `id=32833` path=`userProfile` component=`system/user/profile/index` 显示
+
+### 13. 财务管理
+
+- [目录] **财务管理**  `id=32339` path=`bill` component=`-` 显示
+  - [菜单] **钱包**  `id=32422` path=`wallet` component=`billing/wallet/index` 显示
+  - [目录] **充值管理**  `id=35111` path=`billRecharge` component=`-` 显示
+    - [菜单] **充值记录**  `id=32445` path=`companyRecharge` component=`company/companyRecharge/index` 显示
+  - [目录] **扣费管理**  `id=35112` path=`billDeduct` component=`-` 显示
+    - [菜单] **诊所管理-企业扣款**  `id=32435` path=`companyDeduct` component=`company/companyDeduct/index` 显示
+  - [目录] **分账管理**  `id=35113` path=`billProfit` component=`-` 显示
+    - [菜单] **分账记录**  `id=32444` path=`companyProfit` component=`company/companyProfit/index` 显示
+    - [菜单] **企业redpacketbalance日志**  `id=32446` path=`companyRedPacketBalanceLogs` component=`company/companyRedPacketBalanceLogs/index` 显示
+    - [菜单] **red套餐**  `id=32474` path=`redPackage` component=`company/redPackage/index` 显示
+  - [目录] **资金日志**  `id=35114` path=`billMoneyLog` component=`-` 显示
+    - [菜单] **资金流水**  `id=32441` path=`companyMoneyLogs` component=`company/companyMoneyLogs/index` 显示
+
+### 14. 日程管理
+
+- [目录] **日程管理**  `id=32341` path=`calendar` component=`-` 显示
+  - [菜单] **my日程**  `id=32423` path=`myCalendar` component=`calendar/myCalendar/index` 显示
+
+### 15. 数据统计
+
+- [目录] **数据统计**  `id=32368` path=`statistics` component=`-` 显示
+  - [菜单] **模块用量**  `id=32693` path=`moduleUsagePage` component=`moduleUsage/index/index` 显示
+  - [菜单] **会员**  `id=32769` path=`member` component=`statistics/member/index` 显示
+  - [菜单] **报表**  `id=32770` path=`report` component=`statistics/report/index` 显示
+  - [菜单] **分组统计**  `id=32771` path=`section` component=`statistics/section/index` 显示
+  - [菜单] **通话日志**  `id=32834` path=`callLog` component=`taskStatistics/callLog/index` 显示
+  - [菜单] **发信日志**  `id=32835` path=`sendMsgLog` component=`taskStatistics/sendMsgLog/index` 显示
+  - [菜单] **模块消费统计**  `id=32859` path=`consumeReport` component=`company/consumeReport/index` 显示
+  - [菜单] **统计中心**  `id=29194` path=`statisticsIndex` component=`statistics/index` 显示
+    - └─ [按钮] **consumetype**  `perms=admin:statistics:consumeType`
+    - └─ [按钮] **cost配置**  `perms=admin:statistics:costConfig`
+    - └─ [按钮] **costsummary**  `perms=admin:statistics:costSummary`
+    - └─ [按钮] **统计执行**  `perms=admin:statistics:execute`
+    - └─ [按钮] **按钮**  `perms=admin:statistics:hourly`
+    - └─ [按钮] **代理分账**  `perms=admin:statistics:proxyProfit`
+    - └─ [按钮] **租户consume**  `perms=admin:statistics:tenantConsume`
+    - └─ [按钮] **按钮**  `perms=admin:statistics:trend`
+  - [菜单] **模块用量统计**  `id=29227` path=`moduleUsageIndex` component=`moduleUsage/index` 显示
+    - └─ [按钮] **刷新**  `perms=admin:moduleUsage:refresh`
+
+### 16. 监控管理
+
+- [目录] **监控管理**  `id=32379` path=`watch` component=`-` 显示
+  - [菜单] **医生oper日志**  `id=32695` path=`doctorOperLog` component=`monitor/doctorOperLog/index` 显示
+  - [菜单] **数据监控**  `id=32696` path=`druid` component=`monitor/druid/index` 显示
+  - [菜单] **定时任务**  `id=32697` path=`job` component=`monitor/job/index` 显示
+  - [菜单] **物联网**  `id=32850` path=`iot` component=`watch/iot/index` 显示
+  - [菜单] **绑定状态**  `id=32851` path=`isBind` component=`watch/isBind/index` 显示
+  - [菜单] **下发状态**  `id=32852` path=`isSend` component=`watch/isSend/index` 显示
+
+### 17. 其他
+
+- [目录] **其他**  `id=35300` path=`other` component=`-` 显示
+  - [目录] **快速GPT扩展标签**  `id=32330` path=`FastGptExtUserTag` component=`-` 显示
+  - [目录] **通讯录**  `id=32332` path=`addressBook` component=`-` 显示
+  - [目录] **数据大屏**  `id=32334` path=`adv` component=`-` 显示
+  - [目录] **AI会话质检**  `id=32335` path=`aiChatQuality` component=`-` 显示
+  - [目录] **AI外呼**  `id=32336` path=`aiSipCall` component=`-` 显示
+  - [目录] **AI智能体**  `id=32337` path=`aiob` component=`-` 显示
+  - [目录] **百度统计**  `id=32338` path=`baidu` component=`-` 显示
+  - [目录] **通话记录**  `id=32342` path=`callRecord` component=`-` 显示
+  - [目录] **会话管理**  `id=32343` path=`chat` component=`-` 显示
+  - [目录] **企业管理**  `id=32344` path=`company` component=`-` 显示
+    - [菜单] **公司管理**  `id=35117` path=`company` component=`his/company/index` 显示
+      - └─ [按钮] **诊所管理查询**  `perms=his:company:query`
+      - └─ [按钮] **红包充值**  `perms=his:company:redRecharge`
+      - └─ [按钮] **红包扣款**  `perms=his:company:redDeduct`
+      - └─ [按钮] **诊所管理新增**  `perms=his:company:add`
+      - └─ [按钮] **诊所管理修改**  `perms=his:company:edit`
+      - └─ [按钮] **诊所管理删除**  `perms=his:company:remove`
+      - └─ [按钮] **诊所管理导出**  `perms=his:company:export`
+      - └─ [按钮] **诊所管理充值**  `perms=his:company:recharge`
+      - └─ [按钮] **诊所管理扣款**  `perms=his:company:deduct`
+      - └─ [按钮] **诊所管理重置密码**  `perms=his:company:pass`
+      - └─ [按钮] **分账配置**  `perms=his:companyDivConfig:set`
+  - [目录] **课程模板**  `id=32346` path=`courseFinishTemp` component=`-` 显示
+  - [目录] **药膳食疗**  `id=32349` path=`food` component=`-` 显示
+  - [目录] **网关管理**  `id=32350` path=`gw` component=`-` 显示
+  - [目录] **商城管理**  `id=32352` path=`hisStore` component=`-` 显示
+  - [目录] **直播数据**  `id=32354` path=`liveData` component=`-` 显示
+  - [目录] **医疗管理**  `id=32356` path=`medical` component=`-` 显示
+  - [目录] **模块用量**  `id=32358` path=`moduleUsage` component=`-` 显示
+  - [目录] **系统监控**  `id=32359` path=`monitor` component=`-` 显示
+  - [目录] **代理管理**  `id=32360` path=`proxy` component=`-` 显示
+  - [目录] **企微外部联系人**  `id=32362` path=`qwExternalContact` component=`-` 显示
+  - [目录] **企业微信**  `id=32363` path=`qwechat` component=`-` 显示
+  - [目录] **SaaS管理**  `id=32364` path=`saas` component=`-` 显示
+  - [目录] **销售人员**  `id=32365` path=`saler` component=`-` 显示
+  - [目录] **门店管理**  `id=32366` path=`shop` component=`-` 显示
+  - [目录] **商城订单线下明细**  `id=32370` path=`storeOrderOfflineItem` component=`-` 显示
+  - [目录] **sys用户**  `id=32371` path=`sysUser` component=`-` 显示
+  - [目录] **任务统计**  `id=32373` path=`taskStatistics` component=`-` 显示
+  - [目录] **租户管理**  `id=32374` path=`tenant` component=`-` 显示
+  - [目录] **待办事项**  `id=32375` path=`todo` component=`-` 显示
+  - [目录] **系统工具**  `id=32376` path=`tool` component=`-` 显示
+  - [目录] **用户管理**  `id=32377` path=`user` component=`-` 显示
+  - [目录] **用户管理**  `id=32378` path=`users` component=`-` 显示
+  - [菜单] **广告配置**  `id=32385` path=`ad` component=`ad/index` 显示
+  - [菜单] **诊所管理-广告管理**  `id=32591` path=`adv` component=`hisStore/adv/index` 显示
+  - [菜单] **企业用户**  `id=32592` path=`companyUser` component=`hisStore/companyUser/index` 显示
+  - [菜单] **诊所管理-快递管理**  `id=32593` path=`express` component=`hisStore/express/index` 显示
+  - [菜单] **诊所管理-积分商品**  `id=32594` path=`integralGoods` component=`hisStore/integralGoods/index` 显示
+  - [菜单] **诊所管理-积分订单**  `id=32595` path=`integralOrder` component=`hisStore/integralOrder/index` 显示
+  - [菜单] **系统管理-菜单管理**  `id=32596` path=`menu` component=`hisStore/menu/index` 显示
+  - [菜单] **处方**  `id=32597` path=`prescribe` component=`hisStore/prescribe/index` 显示
+  - [菜单] **处方drug**  `id=32598` path=`prescribeDrug` component=`hisStore/prescribeDrug/index` 显示
+  - [菜单] **运费templates**  `id=32599` path=`shippingTemplates` component=`hisStore/shippingTemplates/index` 显示
+  - [菜单] **运费templatesfree**  `id=32600` path=`shippingTemplatesFree` component=`hisStore/shippingTemplatesFree/index` 显示
+  - [菜单] **运费templatesregion**  `id=32601` path=`shippingTemplatesRegion` component=`hisStore/shippingTemplatesRegion/index` 显示
+  - [菜单] **诊所管理-门店管理**  `id=32602` path=`store` component=`hisStore/store/index` 显示
+  - [菜单] **诊所管理-门店活动**  `id=32603` path=`storeActivity` component=`hisStore/storeActivity/index` 显示
+  - [菜单] **售后**  `id=32604` path=`storeAfterSales` component=`hisStore/storeAfterSales/index` 显示
+  - [菜单] **商城aftersales明细**  `id=32605` path=`storeAfterSalesItem` component=`hisStore/storeAfterSalesItem/index` 显示
+  - [菜单] **商城aftersalesstatus**  `id=32606` path=`storeAfterSalesStatus` component=`hisStore/storeAfterSalesStatus/index` 显示
+  - [菜单] **商城canvas**  `id=32607` path=`storeCanvas` component=`hisStore/storeCanvas/index` 显示
+  - [菜单] **商城购物车**  `id=32608` path=`storeCart` component=`hisStore/storeCart/index` 显示
+  - [菜单] **优惠券**  `id=32609` path=`storeCoupon` component=`hisStore/storeCoupon/index` 显示
+  - [菜单] **商城优扣券issue**  `id=32610` path=`storeCouponIssue` component=`hisStore/storeCouponIssue/index` 显示
+  - [菜单] **商城优扣券issue用户**  `id=32611` path=`storeCouponIssueUser` component=`hisStore/storeCouponIssueUser/index` 显示
+  - [菜单] **商城优扣券用户**  `id=32612` path=`storeCouponUser` component=`hisStore/storeCouponUser/index` 显示
+  - [菜单] **商城instandiscountissue**  `id=32613` path=`storeInstanDiscountIssue` component=`hisStore/storeInstanDiscountIssue/index` 显示
+  - [菜单] **商城instantdiscount**  `id=32614` path=`storeInstantDiscount` component=`hisStore/storeInstantDiscount/index` 显示
+  - [菜单] **商城instantdiscount用户**  `id=32615` path=`storeInstantDiscountUser` component=`hisStore/storeInstantDiscountUser/index` 显示
+  - [菜单] **dimension统计**  `id=32616` path=`dimensionStatistics` component=`hisStore/storeOrder/dimensionStatistics/index` 显示
+  - [菜单] **门店订单**  `id=32617` path=`storeOrder` component=`hisStore/storeOrder/index` 显示
+  - [菜单] **订单审核**  `id=32618` path=`storeOrderAudit` component=`hisStore/storeOrderAudit/index` 显示
+  - [菜单] **商城订单公告**  `id=32619` path=`storeOrderNotice` component=`hisStore/storeOrderNotice/index` 显示
+  - [菜单] **线下订单**  `id=32620` path=`storeOrderOffline` component=`hisStore/storeOrderOffline/index` 显示
+  - [菜单] **商城订单status**  `id=32621` path=`storeOrderStatus` component=`hisStore/storeOrderStatus/index` 显示
+  - [菜单] **商城管理-商城支付**  `id=32622` path=`storePayment` component=`hisStore/storePayment/index` 显示
+  - [菜单] **商城管理-商城商品**  `id=32623` path=`storeProduct` component=`hisStore/storeProduct/index` 显示
+  - [菜单] **商城商品属性**  `id=32624` path=`storeProductAttr` component=`hisStore/storeProductAttr/index` 显示
+  - [菜单] **商城商品属性value**  `id=32625` path=`storeProductAttrValue` component=`hisStore/storeProductAttrValue/index` 显示
+  - [菜单] **商城商品审核**  `id=32626` path=`storeProductAudit` component=`hisStore/storeProductAudit/index` 显示
+  - [菜单] **诊所管理-门店商品分类**  `id=32627` path=`storeProductCategory` component=`hisStore/storeProductCategory/index` 显示
+  - [菜单] **商城商品详情**  `id=32628` path=`storeProductDetails` component=`hisStore/storeProductDetails/index` 显示
+  - [菜单] **商城商品分组**  `id=32629` path=`storeProductGroup` component=`hisStore/storeProductGroup/index` 显示
+  - [菜单] **商城商品关联**  `id=32631` path=`storeProductRelation` component=`hisStore/storeProductRelation/index` 显示
+  - [菜单] **商城商品回复**  `id=32632` path=`storeProductReply` component=`hisStore/storeProductReply/index` 显示
+  - [菜单] **商城商品规则**  `id=32633` path=`storeProductRule` component=`hisStore/storeProductRule/index` 显示
+  - [菜单] **商城商品模板**  `id=32634` path=`storeProductTemplate` component=`hisStore/storeProductTemplate/index` 显示
+  - [菜单] **商城商品yuyue**  `id=32635` path=`storeProductYuyue` component=`hisStore/storeProductYuyue/index` 显示
+  - [菜单] **冗余销售**  `id=32636` path=`storeRedundSales` component=`hisStore/storeRedundSales/index` 显示
+  - [菜单] **门店管理**  `id=32637` path=`storeShop` component=`hisStore/storeShop/index` 显示
+  - [菜单] **商城shop员工**  `id=32638` path=`storeShopStaff` component=`hisStore/storeShopStaff/index` 显示
+  - [菜单] **商城访问**  `id=32639` path=`storeVisit` component=`hisStore/storeVisit/index` 显示
+  - [菜单] **用户账单**  `id=32640` path=`userBill` component=`hisStore/userBill/index` 显示
+  - [菜单] **用户extract**  `id=32641` path=`userExtract` component=`hisStore/userExtract/index` 显示
+  - [菜单] **用户在线状态**  `id=32642` path=`userOnlineState` component=`hisStore/userOnlineState/index` 显示
+  - [菜单] **用户promoter申请**  `id=32643` path=`userPromoterApply` component=`hisStore/userPromoterApply/index` 显示
+  - [菜单] **模块用量**  `id=32698` path=`moduleUsage` component=`proxy/moduleUsage/index` 显示
+  - [菜单] **quota**  `id=32699` path=`quota` component=`proxy/quota/index` 显示
+  - [菜单] **serviceprice**  `id=32700` path=`servicePrice` component=`proxy/servicePrice/index` 显示
+  - [菜单] **租户管理**  `id=32701` path=`tenant` component=`proxy/tenant/index` 显示
+  - [菜单] **租户rel**  `id=32702` path=`tenantRel` component=`proxy/tenantRel/index` 显示
+  - [菜单] **提现**  `id=32703` path=`withdraw` component=`proxy/withdraw/index` 显示
+  - [菜单] **billing**  `id=32756` path=`billing` component=`saas/billing/index` 显示
+  - [菜单] **billing平台**  `id=32757` path=`billingAdmin` component=`saas/billingAdmin/index` 显示
+  - [菜单] **billing租户**  `id=32758` path=`billingTenant` component=`saas/billingTenant/index` 显示
+  - [菜单] **租户管理-操作记录**  `id=32759` path=`record` component=`saas/record/index` 显示
+  - [菜单] **系统管理-参数配置**  `id=32760` path=`config` component=`saas/tenant/config/index` 显示
+  - [菜单] **租户管理**  `id=32761` path=`tenant2` component=`saas/tenant/index` 显示
+  - [菜单] **租户企业**  `id=32762` path=`tenantCompany` component=`saas/tenantCompany/index` 显示
+  - [菜单] **租户菜单**  `id=32763` path=`tenantMenu` component=`saas/tenantMenu/index` 显示
+  - [菜单] **CRM客户-消息管理**  `id=32766` path=`msg` component=`shop/msg/index/index` 显示
+  - [菜单] **records**  `id=32767` path=`records` component=`shop/records/index/index` 显示
+  - [菜单] **系统管理-角色管理**  `id=32768` path=`role` component=`shop/role/index/index` 显示
+  - [菜单] **诊所管理-门店管理**  `id=32826` path=`store2` component=`storeOrderOfflineItem/store/index/index` 显示
+  - [菜单] **租户管理**  `id=32837` path=`tenant3` component=`tenant/index/index` 显示
+  - [菜单] **构建工具**  `id=32839` path=`build` component=`tool/build/index` 显示
+  - [菜单] **代码生成**  `id=32840` path=`gen` component=`tool/gen/index` 显示
+  - [菜单] **接口文档**  `id=32841` path=`swagger` component=`tool/swagger/index` 显示
+  - [目录] **钱包管理**  `id=35110` path=`finWallet` component=`-` 显示
+  - [目录] **AI管理**  `id=35129` path=`aaa` component=`-` 显示
+  - [菜单] **AI服务商**  `id=32386` path=`aiProvider` component=`aiProvider/index` 显示
+  - [目录] **语料与提示词**  `id=35081` path=`lobsterCorpus` component=`-` 显示
+  - [目录] **配置管理**  `id=35091` path=`advConfig` component=`-` 显示
+  - [菜单] **文章管理**  `id=32387` path=`article` component=`article/index` 显示
+  - [目录] **模型与配置**  `id=35082` path=`lobsterModel` component=`-` 显示
+  - [目录] **数据统计**  `id=35092` path=`advStat` component=`-` 显示
+  - [菜单] **通话记录**  `id=32388` path=`callRecord` component=`callRecord/index` 显示
+  - [目录] **用户管理**  `id=35033` path=`hisUser` component=`-` 显示
+  - [目录] **运维监控**  `id=35083` path=`lobsterOps` component=`-` 显示
+  - [菜单] **佣金记录**  `id=32389` path=`commissionRecord` component=`commissionRecord/index` 显示
+  - [目录] **门店管理**  `id=35034` path=`hisStore` component=`-` 显示
+  - [菜单] **消费记录**  `id=32390` path=`consumeRecord` component=`consumeRecord/index` 显示
+  - [目录] **网关管理**  `id=35015` path=`gwMgmt` component=`-` 显示
+  - [目录] **导出与日志**  `id=35035` path=`hisExport` component=`-` 显示
+  - [目录] **聚合聊天**  `id=35085` path=`lobsterChat` component=`-` 显示
+  - [目录] **流量管理**  `id=35115` path=`finTraffic` component=`-` 显示
+  - [菜单] **课程配置**  `id=32391` path=`course` component=`course/index` 显示
+  - [目录] **使用统计**  `id=35116` path=`finUsage` component=`-` 显示
+  - [菜单] **CRM配置**  `id=32392` path=`crm` component=`crm/index` 显示
+  - [菜单] **直播配置**  `id=32393` path=`live` component=`live/index` 显示
+  - [目录] **SaaS管理**  `id=35108` path=`sysSaas` component=`-` 显示
+  - [菜单] **直播视频**  `id=32394` path=`liveVideo` component=`liveVideo/index` 显示
+  - [菜单] **模块用量**  `id=32395` path=`moduleUsage2` component=`moduleUsage/index` 显示
+  - [菜单] **商品配置**  `id=32396` path=`product` component=`product/index` 显示
+  - [菜单] **代理配置**  `id=32397` path=`proxy` component=`proxy/index` 显示
+  - [菜单] **企微外部联系人**  `id=32398` path=`qwExternalContact` component=`qwExternalContact/index` 显示
+  - [菜单] **充值记录**  `id=32399` path=`rechargeRecord` component=`rechargeRecord/index` 显示
+  - [菜单] **商城订单**  `id=32401` path=`storeOrder2` component=`storeOrder/index` 显示
+  - [菜单] **企业信息**  `id=32402` path=`sysCompany` component=`sysCompany/index` 显示
+  - [菜单] **系统用户**  `id=32403` path=`sysUser` component=`sysUser/index` 显示
+  - [菜单] **视频资源**  `id=32404` path=`videoResource` component=`videoResource/index` 显示
+  - [菜单] **提现管理**  `id=32405` path=`withdrawalManage` component=`withdrawalManage/index` 显示
+  - [菜单] **广告投放-抖音广告账户**  `id=29217` path=`AdDyAccount` component=`ad/AdDyAccount/index` 显示
+    - └─ [按钮] **新增**  `perms=ad:AdDyAccount:add`
+    - └─ [按钮] **修改**  `perms=ad:AdDyAccount:edit`
+    - └─ [按钮] **导出**  `perms=ad:AdDyAccount:export`
+    - └─ [按钮] **查询**  `perms=ad:AdDyAccount:query`
+    - └─ [按钮] **删除**  `perms=ad:AdDyAccount:remove`
+  - [菜单] **广告投放-爱奇艺广告账户**  `id=29218` path=`AdIqiyiAccount` component=`ad/AdIqiyiAccount/index` 显示
+    - └─ [按钮] **新增**  `perms=ad:AdIqiyiAccount:add`
+    - └─ [按钮] **修改**  `perms=ad:AdIqiyiAccount:edit`
+    - └─ [按钮] **导出**  `perms=ad:AdIqiyiAccount:export`
+    - └─ [按钮] **查询**  `perms=ad:AdIqiyiAccount:query`
+    - └─ [按钮] **删除**  `perms=ad:AdIqiyiAccount:remove`
+  - [菜单] **广告投放-广告上传日志**  `id=29219` path=`AdUploadLog` component=`ad/AdUploadLog/index` 显示
+    - └─ [按钮] **新增**  `perms=ad:AdUploadLog:add`
+    - └─ [按钮] **修改**  `perms=ad:AdUploadLog:edit`
+    - └─ [按钮] **导出**  `perms=ad:AdUploadLog:export`
+    - └─ [按钮] **查询**  `perms=ad:AdUploadLog:query`
+    - └─ [按钮] **删除**  `perms=ad:AdUploadLog:remove`
+  - [菜单] **广告投放-优酷广告账户**  `id=29220` path=`AdYouKuaccount` component=`ad/AdYouKuaccount/index` 显示
+    - └─ [按钮] **新增**  `perms=ad:AdYouKuaccount:add`
+    - └─ [按钮] **修改**  `perms=ad:AdYouKuaccount:edit`
+    - └─ [按钮] **导出**  `perms=ad:AdYouKuaccount:export`
+    - └─ [按钮] **查询**  `perms=ad:AdYouKuaccount:query`
+    - └─ [按钮] **删除**  `perms=ad:AdYouKuaccount:remove`
+  - [菜单] **广告投放-广告站点**  `id=29223` path=`adSite` component=`ad/adSite/index` 显示
+    - └─ [按钮] **新增**  `perms=ad:adSite:add`
+    - └─ [按钮] **修改**  `perms=ad:adSite:edit`
+    - └─ [按钮] **导出**  `perms=ad:adSite:export`
+    - └─ [按钮] **查询**  `perms=ad:adSite:query`
+    - └─ [按钮] **删除**  `perms=ad:adSite:remove`
+  - [菜单] **广告投放-落地页管理**  `id=29225` path=`html` component=`ad/html/index` 显示
+    - └─ [按钮] **新增**  `perms=ad:html:add`
+    - └─ [按钮] **修改**  `perms=ad:html:edit`
+    - └─ [按钮] **导出**  `perms=ad:html:export`
+    - └─ [按钮] **查询**  `perms=ad:html:query`
+    - └─ [按钮] **删除**  `perms=ad:html:remove`
+  - [菜单] **平台管理-企微联系人**  `id=29228` path=`qwContact` component=`qwContact/index` 显示
+    - └─ [按钮] **查询**  `perms=admin:qwContact:query`
+  - [菜单] **百度统计-百度账户**  `id=29232` path=`BdAccount` component=`baidu/BdAccount/index` 显示
+    - └─ [按钮] **新增**  `perms=baidu:BdAccount:add`
+    - └─ [按钮] **修改**  `perms=baidu:BdAccount:edit`
+    - └─ [按钮] **导出**  `perms=baidu:BdAccount:export`
+    - └─ [按钮] **查询**  `perms=baidu:BdAccount:query`
+    - └─ [按钮] **删除**  `perms=baidu:BdAccount:remove`
+  - [菜单] **会话管理-数据集管理**  `id=29234` path=`chatDataset` component=`chat/chatDataset/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatDataset:add`
+    - └─ [按钮] **修改**  `perms=chat:chatDataset:edit`
+    - └─ [按钮] **导出**  `perms=chat:chatDataset:export`
+    - └─ [按钮] **查询**  `perms=chat:chatDataset:query`
+    - └─ [按钮] **删除**  `perms=chat:chatDataset:remove`
+  - [菜单] **会话管理-数据文件管理**  `id=29235` path=`chatDatasetFile` component=`chat/chatDatasetFile/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatDatasetFile:add`
+    - └─ [按钮] **修改**  `perms=chat:chatDatasetFile:edit`
+    - └─ [按钮] **导出**  `perms=chat:chatDatasetFile:export`
+    - └─ [按钮] **查询**  `perms=chat:chatDatasetFile:query`
+    - └─ [按钮] **删除**  `perms=chat:chatDatasetFile:remove`
+  - [菜单] **会话管理-关键词管理**  `id=29236` path=`chatKeyword` component=`chat/chatKeyword/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatKeyword:add`
+    - └─ [按钮] **修改**  `perms=chat:chatKeyword:edit`
+    - └─ [按钮] **查询**  `perms=chat:chatKeyword:query`
+    - └─ [按钮] **删除**  `perms=chat:chatKeyword:remove`
+  - [菜单] **会话管理-消息记录**  `id=29237` path=`chatMsg` component=`chat/chatMsg/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatMsg:add`
+    - └─ [按钮] **修改**  `perms=chat:chatMsg:edit`
+    - └─ [按钮] **导出**  `perms=chat:chatMsg:export`
+    - └─ [按钮] **查询**  `perms=chat:chatMsg:query`
+    - └─ [按钮] **删除**  `perms=chat:chatMsg:remove`
+  - [菜单] **会话管理-角色管理**  `id=29239` path=`chatRole` component=`chat/chatRole/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatRole:add`
+    - └─ [按钮] **修改**  `perms=chat:chatRole:edit`
+    - └─ [按钮] **导出**  `perms=chat:chatRole:export`
+    - └─ [按钮] **查询**  `perms=chat:chatRole:query`
+    - └─ [按钮] **删除**  `perms=chat:chatRole:remove`
+  - [菜单] **会话管理-会话记录**  `id=29240` path=`chatSession` component=`chat/chatSession/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatSession:add`
+    - └─ [按钮] **修改**  `perms=chat:chatSession:edit`
+    - └─ [按钮] **导出**  `perms=chat:chatSession:export`
+    - └─ [按钮] **查询**  `perms=chat:chatSession:query`
+    - └─ [按钮] **删除**  `perms=chat:chatSession:remove`
+  - [菜单] **会话管理-用户管理**  `id=29241` path=`chatUser` component=`chat/chatUser/index` 显示
+    - └─ [按钮] **新增**  `perms=chat:chatUser:add`
+    - └─ [按钮] **修改**  `perms=chat:chatUser:edit`
+    - └─ [按钮] **导出**  `perms=chat:chatUser:export`
+    - └─ [按钮] **查询**  `perms=chat:chatUser:query`
+    - └─ [按钮] **删除**  `perms=chat:chatUser:remove`
+  - [菜单] **课程管理-结课模板上级**  `id=29311` path=`courseFinishTempParent` component=`course/courseFinishTempParent/index` 显示
+    - └─ [按钮] **新增**  `perms=course:courseFinishTempParent:add`
+    - └─ [按钮] **修改**  `perms=course:courseFinishTempParent:edit`
+    - └─ [按钮] **导出**  `perms=course:courseFinishTempParent:export`
+    - └─ [按钮] **查询**  `perms=course:courseFinishTempParent:query`
+    - └─ [按钮] **删除**  `perms=course:courseFinishTempParent:remove`
+  - [菜单] **课程管理-课程链接**  `id=29312` path=`courseLink` component=`course/courseLink/index` 显示
+    - └─ [按钮] **新增**  `perms=course:courseLink:add`
+    - └─ [按钮] **按钮**  `perms=course:courseLink:create`
+    - └─ [按钮] **修改**  `perms=course:courseLink:edit`
+    - └─ [按钮] **导出**  `perms=course:courseLink:export`
+    - └─ [按钮] **查询**  `perms=course:courseLink:query`
+    - └─ [按钮] **删除**  `perms=course:courseLink:remove`
+  - [菜单] **课程管理-课程题库**  `id=29313` path=`courseQuestionBank` component=`course/courseQuestionBank/index` 显示
+    - └─ [按钮] **新增**  `perms=course:courseQuestionBank:add`
+    - └─ [按钮] **修改**  `perms=course:courseQuestionBank:edit`
+    - └─ [按钮] **导出**  `perms=course:courseQuestionBank:export`
+    - └─ [按钮] **导出fail**  `perms=course:courseQuestionBank:exportFail`
+    - └─ [按钮] **导入数据**  `perms=course:courseQuestionBank:importData`
+    - └─ [按钮] **查询**  `perms=course:courseQuestionBank:query`
+    - └─ [按钮] **删除**  `perms=course:courseQuestionBank:remove`
+  - [菜单] **课程管理-红包日志**  `id=29315` path=`courseRedPacketLog` component=`course/courseRedPacketLog/index` 显示
+    - └─ [按钮] **新增**  `perms=course:courseRedPacketLog:add`
+    - └─ [按钮] **修改**  `perms=course:courseRedPacketLog:edit`
+    - └─ [按钮] **导出**  `perms=course:courseRedPacketLog:export`
+    - └─ [按钮] **page列表**  `perms=course:courseRedPacketLog:pageList`
+    - └─ [按钮] **查询**  `perms=course:courseRedPacketLog:query`
+    - └─ [按钮] **删除**  `perms=course:courseRedPacketLog:remove`
+  - [菜单] **课程管理-流量日志**  `id=29316` path=`courseTrafficLog` component=`course/courseTrafficLog/index` 显示
+    - └─ [按钮] **新增**  `perms=course:courseTrafficLog:add`
+    - └─ [按钮] **修改**  `perms=course:courseTrafficLog:edit`
+    - └─ [按钮] **导出**  `perms=course:courseTrafficLog:export`
+    - └─ [按钮] **查询**  `perms=course:courseTrafficLog:query`
+    - └─ [按钮] **删除**  `perms=course:courseTrafficLog:remove`
+    - └─ [按钮] **统计**  `perms=course:courseTrafficLog:statistics`
+    - └─ [按钮] **统计导出**  `perms=course:courseTrafficLog:statisticsExport`
+  - [菜单] **课程管理-课程产品**  `id=29318` path=`fsCourseProduct` component=`course/fsCourseProduct/index` 显示
+    - └─ [按钮] **新增**  `perms=course:fsCourseProduct:add`
+    - └─ [按钮] **修改**  `perms=course:fsCourseProduct:edit`
+    - └─ [按钮] **导出**  `perms=course:fsCourseProduct:export`
+    - └─ [按钮] **查询**  `perms=course:fsCourseProduct:query`
+    - └─ [按钮] **删除**  `perms=course:fsCourseProduct:remove`
+  - [菜单] **课程管理-课程产品订单**  `id=29319` path=`fsCourseProductOrder` component=`course/fsCourseProductOrder/index` 显示
+    - └─ [按钮] **新增**  `perms=course:fsCourseProductOrder:add`
+    - └─ [按钮] **decode导出**  `perms=course:fsCourseProductOrder:decodeExport`
+    - └─ [按钮] **修改**  `perms=course:fsCourseProductOrder:edit`
+    - └─ [按钮] **导出**  `perms=course:fsCourseProductOrder:export`
+    - └─ [按钮] **查询**  `perms=course:fsCourseProductOrder:query`
+    - └─ [按钮] **queryphone**  `perms=course:fsCourseProductOrder:queryPhone`
+    - └─ [按钮] **按钮**  `perms=course:fsCourseProductOrder:refund`
+    - └─ [按钮] **删除**  `perms=course:fsCourseProductOrder:remove`
+  - [菜单] **课程管理-课程统计**  `id=29325` path=`statistics` component=`course/statistics/index` 显示
+    - └─ [按钮] **新增**  `perms=course:statistics:add`
+    - └─ [按钮] **修改**  `perms=course:statistics:edit`
+    - └─ [按钮] **导出**  `perms=course:statistics:export`
+    - └─ [按钮] **查询**  `perms=course:statistics:query`
+    - └─ [按钮] **删除**  `perms=course:statistics:remove`
+  - [菜单] **课程管理-用户课程**  `id=29327` path=`userCourse` component=`course/userCourse/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourse:add`
+    - └─ [按钮] **用户课程复制**  `perms=course:userCourse:copy`
+    - └─ [按钮] **修改**  `perms=course:userCourse:edit`
+    - └─ [按钮] **edit配置**  `perms=course:userCourse:editConfig`
+    - └─ [按钮] **editredpage**  `perms=course:userCourse:editRedPage`
+    - └─ [按钮] **导出**  `perms=course:userCourse:export`
+    - └─ [按钮] **publicadd**  `perms=course:userCourse:publicAdd`
+    - └─ [按钮] **publicedit**  `perms=course:userCourse:publicEdit`
+    - └─ [按钮] **public导出**  `perms=course:userCourse:publicExport`
+    - └─ [按钮] **public列表**  `perms=course:userCourse:publicList`
+    - └─ [按钮] **publicputoff**  `perms=course:userCourse:publicPutOff`
+    - └─ [按钮] **publicputon**  `perms=course:userCourse:publicPutOn`
+    - └─ [按钮] **publicquery**  `perms=course:userCourse:publicQuery`
+    - └─ [按钮] **publicremove**  `perms=course:userCourse:publicRemove`
+    - └─ [按钮] **publicupdateisshow**  `perms=course:userCourse:publicUpdateIsShow`
+    - └─ [按钮] **puton**  `perms=course:userCourse:putOn`
+    - └─ [按钮] **查询**  `perms=course:userCourse:query`
+    - └─ [按钮] **删除**  `perms=course:userCourse:remove`
+    - └─ [按钮] **updateisshow**  `perms=course:userCourse:updateIsShow`
+  - [菜单] **课程管理-用户课程分类**  `id=29328` path=`userCourseCategory` component=`course/userCourseCategory/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseCategory:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseCategory:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseCategory:export`
+    - └─ [按钮] **导出fail**  `perms=course:userCourseCategory:exportFail`
+    - └─ [按钮] **导入数据**  `perms=course:userCourseCategory:importData`
+    - └─ [按钮] **查询**  `perms=course:userCourseCategory:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseCategory:remove`
+  - [菜单] **课程管理-课程评论**  `id=29329` path=`userCourseComment` component=`course/userCourseComment/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseComment:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseComment:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseComment:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseComment:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseComment:remove`
+  - [菜单] **课程管理-投诉记录**  `id=29331` path=`userCourseComplaintRecord` component=`course/userCourseComplaintRecord/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseComplaintRecord:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseComplaintRecord:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseComplaintRecord:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseComplaintRecord:query`
+    - └─ [按钮] **query企微**  `perms=course:userCourseComplaintRecord:queryQw`
+    - └─ [按钮] **删除**  `perms=course:userCourseComplaintRecord:remove`
+  - [菜单] **课程管理-投诉类型**  `id=29332` path=`userCourseComplaintType` component=`course/userCourseComplaintType/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseComplaintType:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseComplaintType:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseComplaintType:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseComplaintType:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseComplaintType:remove`
+  - [菜单] **课程管理-课程笔记**  `id=29334` path=`userCourseNote` component=`course/userCourseNote/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseNote:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseNote:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseNote:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseNote:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseNote:remove`
+  - [菜单] **课程管理-课程订单**  `id=29336` path=`userCourseOrder` component=`course/userCourseOrder/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseOrder:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseOrder:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseOrder:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseOrder:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseOrder:remove`
+  - [菜单] **课程管理-学习记录**  `id=29337` path=`userCourseStudy` component=`course/userCourseStudy/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseStudy:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseStudy:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseStudy:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseStudy:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseStudy:remove`
+  - [菜单] **课程管理-学习日志**  `id=29338` path=`userCourseStudyLog` component=`course/userCourseStudyLog/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userCourseStudyLog:add`
+    - └─ [按钮] **修改**  `perms=course:userCourseStudyLog:edit`
+    - └─ [按钮] **导出**  `perms=course:userCourseStudyLog:export`
+    - └─ [按钮] **查询**  `perms=course:userCourseStudyLog:query`
+    - └─ [按钮] **删除**  `perms=course:userCourseStudyLog:remove`
+  - [菜单] **课程管理-用户达人**  `id=29340` path=`userTalent` component=`course/userTalent/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userTalent:add`
+    - └─ [按钮] **用户达人审核**  `perms=course:userTalent:audit`
+    - └─ [按钮] **修改**  `perms=course:userTalent:edit`
+    - └─ [按钮] **导出**  `perms=course:userTalent:export`
+    - └─ [按钮] **查询**  `perms=course:userTalent:query`
+    - └─ [按钮] **删除**  `perms=course:userTalent:remove`
+  - [菜单] **课程管理-用户视频**  `id=29342` path=`userVideo` component=`course/userVideo/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userVideo:add`
+    - └─ [按钮] **用户视频审核**  `perms=course:userVideo:audit`
+    - └─ [按钮] **修改**  `perms=course:userVideo:edit`
+    - └─ [按钮] **导出**  `perms=course:userVideo:export`
+    - └─ [按钮] **puton**  `perms=course:userVideo:putOn`
+    - └─ [按钮] **查询**  `perms=course:userVideo:query`
+    - └─ [按钮] **删除**  `perms=course:userVideo:remove`
+    - └─ [按钮] **upload用户视频**  `perms=course:userVideo:uploadUserVideo`
+  - [菜单] **课程管理-视频评论**  `id=29343` path=`userVideoComment` component=`course/userVideoComment/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userVideoComment:add`
+    - └─ [按钮] **修改**  `perms=course:userVideoComment:edit`
+    - └─ [按钮] **导出**  `perms=course:userVideoComment:export`
+    - └─ [按钮] **查询**  `perms=course:userVideoComment:query`
+    - └─ [按钮] **删除**  `perms=course:userVideoComment:remove`
+  - [菜单] **课程管理-VIP订单**  `id=29348` path=`userVipOrder` component=`course/userVipOrder/index` 显示
+    - └─ [按钮] **新增**  `perms=course:userVipOrder:add`
+    - └─ [按钮] **修改**  `perms=course:userVipOrder:edit`
+    - └─ [按钮] **导出**  `perms=course:userVipOrder:export`
+    - └─ [按钮] **查询**  `perms=course:userVipOrder:query`
+    - └─ [按钮] **删除**  `perms=course:userVipOrder:remove`
+  - [菜单] **课程管理-视频资源**  `id=29352` path=`videoResource2` component=`course/videoResource/index` 显示
+    - └─ [按钮] **新增**  `perms=course:videoResource:add`
+    - └─ [按钮] **batchadd**  `perms=course:videoResource:batchAdd`
+    - └─ [按钮] **batchupdateclass**  `perms=course:videoResource:batchUpdateClass`
+    - └─ [按钮] **修改**  `perms=course:videoResource:edit`
+    - └─ [按钮] **查询**  `perms=course:videoResource:query`
+    - └─ [按钮] **删除**  `perms=course:videoResource:remove`
+  - [菜单] **CRM客户-客户管理**  `id=29355` path=`customer` component=`crm/customer/index` 显示
+    - └─ [按钮] **新增**  `perms=crm:customer:add`
+    - └─ [按钮] **addline**  `perms=crm:customer:addLine`
+    - └─ [按钮] **客户分配**  `perms=crm:customer:assign`
+    - └─ [按钮] **修改**  `perms=crm:customer:edit`
+    - └─ [按钮] **editline**  `perms=crm:customer:editLine`
+    - └─ [按钮] **editsource**  `perms=crm:customer:editSource`
+    - └─ [按钮] **导出**  `perms=crm:customer:export`
+    - └─ [按钮] **导出line**  `perms=crm:customer:exportLine`
+    - └─ [按钮] **导入line**  `perms=crm:customer:importLine`
+    - └─ [按钮] **line列表**  `perms=crm:customer:lineList`
+    - └─ [按钮] **查询**  `perms=crm:customer:query`
+    - └─ [按钮] **按钮**  `perms=crm:customer:query1`
+    - └─ [按钮] **按钮**  `perms=crm:customer:query2`
+    - └─ [按钮] **queryline**  `perms=crm:customer:queryLine`
+    - └─ [按钮] **删除**  `perms=crm:customer:remove`
+    - └─ [按钮] **removeline**  `perms=crm:customer:removeLine`
+  - [菜单] **CRM客户-客户用户**  `id=29360` path=`customerUser` component=`crm/customerUser/index` 显示
+    - └─ [按钮] **新增**  `perms=crm:customerUser:add`
+    - └─ [按钮] **修改**  `perms=crm:customerUser:edit`
+    - └─ [按钮] **导出**  `perms=crm:customerUser:export`
+    - └─ [按钮] **查询**  `perms=crm:customerUser:query`
+    - └─ [按钮] **删除**  `perms=crm:customerUser:remove`
+  - [菜单] **CRM客户-客户访问**  `id=29361` path=`customerVisit` component=`crm/customerVisit/index` 显示
+    - └─ [按钮] **新增**  `perms=crm:customerVisit:add`
+    - └─ [按钮] **修改**  `perms=crm:customerVisit:edit`
+    - └─ [按钮] **导出**  `perms=crm:customerVisit:export`
+    - └─ [按钮] **查询**  `perms=crm:customerVisit:query`
+    - └─ [按钮] **删除**  `perms=crm:customerVisit:remove`
+  - [菜单] **CRM客户-事件管理**  `id=29362` path=`event` component=`crm/event/index` 显示
+    - └─ [按钮] **新增**  `perms=crm:event:add`
+    - └─ [按钮] **修改**  `perms=crm:event:edit`
+    - └─ [按钮] **导出**  `perms=crm:event:export`
+    - └─ [按钮] **查询**  `perms=crm:event:query`
+    - └─ [按钮] **删除**  `perms=crm:event:remove`
+  - [菜单] **CRM客户-消息管理**  `id=29363` path=`msg2` component=`crm/msg/index` 显示
+    - └─ [按钮] **新增**  `perms=crm:msg:add`
+    - └─ [按钮] **修改**  `perms=crm:msg:edit`
+    - └─ [按钮] **导出**  `perms=crm:msg:export`
+    - └─ [按钮] **查询**  `perms=crm:msg:query`
+    - └─ [按钮] **删除**  `perms=crm:msg:remove`
+  - [菜单] **CRM客户-第三方**  `id=29365` path=`third` component=`crm/third/index` 显示
+    - └─ [按钮] **新增**  `perms=crm:third:add`
+    - └─ [按钮] **删除**  `perms=crm:third:delete`
+    - └─ [按钮] **修改**  `perms=crm:third:edit`
+    - └─ [按钮] **导出**  `perms=crm:third:export`
+    - └─ [按钮] **查询**  `perms=crm:third:query`
+  - [菜单] **AI知识库-替换词管理**  `id=29371` path=`fastGptChatReplaceWords` component=`fastGpt/fastGptChatReplaceWords/index` 显示
+    - └─ [按钮] **新增**  `perms=fastGpt:fastGptChatReplaceWords:add`
+    - └─ [按钮] **修改**  `perms=fastGpt:fastGptChatReplaceWords:edit`
+    - └─ [按钮] **导出**  `perms=fastGpt:fastGptChatReplaceWords:export`
+    - └─ [按钮] **查询**  `perms=fastGpt:fastGptChatReplaceWords:query`
+    - └─ [按钮] **删除**  `perms=fastGpt:fastGptChatReplaceWords:remove`
+  - [菜单] **AI知识库-关键词发送**  `id=29376` path=`fastGptKeywordSend` component=`fastGpt/fastGptKeywordSend/index` 显示
+    - └─ [按钮] **新增**  `perms=fastGpt:fastGptKeywordSend:add`
+    - └─ [按钮] **修改**  `perms=fastGpt:fastGptKeywordSend:edit`
+    - └─ [按钮] **导出**  `perms=fastGpt:fastGptKeywordSend:export`
+    - └─ [按钮] **查询**  `perms=fastGpt:fastGptKeywordSend:query`
+    - └─ [按钮] **删除**  `perms=fastGpt:fastGptKeywordSend:remove`
+  - [菜单] **AI知识库-角色管理**  `id=29377` path=`fastGptRole` component=`fastGpt/fastGptRole/index` 显示
+    - └─ [按钮] **新增**  `perms=fastGpt:fastGptRole:add`
+    - └─ [按钮] **修改**  `perms=fastGpt:fastGptRole:edit`
+    - └─ [按钮] **导出**  `perms=fastGpt:fastGptRole:export`
+    - └─ [按钮] **new列表**  `perms=fastGpt:fastGptRole:newList`
+    - └─ [按钮] **按钮**  `perms=fastGpt:fastGptRole:relieve`
+    - └─ [按钮] **删除**  `perms=fastGpt:fastGptRole:remove`
+  - [菜单] **AI知识库-角色标签**  `id=29378` path=`fastGptRoleTag` component=`fastGpt/fastGptRoleTag/index` 显示
+    - └─ [按钮] **新增**  `perms=fastGpt:fastGptRoleTag:add`
+    - └─ [按钮] **修改**  `perms=fastGpt:fastGptRoleTag:edit`
+    - └─ [按钮] **导出**  `perms=fastGpt:fastGptRoleTag:export`
+    - └─ [按钮] **查询**  `perms=fastGpt:fastGptRoleTag:query`
+    - └─ [按钮] **删除**  `perms=fastGpt:fastGptRoleTag:remove`
+  - [菜单] **AI知识库-人工话术**  `id=29380` path=`fastgptChatArtificialWords` component=`fastGpt/fastgptChatArtificialWords/index` 显示
+    - └─ [按钮] **新增**  `perms=fastGpt:fastgptChatArtificialWords:add`
+    - └─ [按钮] **修改**  `perms=fastGpt:fastgptChatArtificialWords:edit`
+    - └─ [按钮] **导出**  `perms=fastGpt:fastgptChatArtificialWords:export`
+    - └─ [按钮] **查询**  `perms=fastGpt:fastgptChatArtificialWords:query`
+    - └─ [按钮] **删除**  `perms=fastGpt:fastgptChatArtificialWords:remove`
+  - [菜单] **AI知识库-事件日志统计**  `id=29381` path=`fastgptEventLogTotal` component=`fastGpt/fastgptEventLogTotal/index` 显示
+    - └─ [按钮] **新增**  `perms=fastGpt:fastgptEventLogTotal:add`
+    - └─ [按钮] **修改**  `perms=fastGpt:fastgptEventLogTotal:edit`
+    - └─ [按钮] **导出**  `perms=fastGpt:fastgptEventLogTotal:export`
+    - └─ [按钮] **查询**  `perms=fastGpt:fastgptEventLogTotal:query`
+    - └─ [按钮] **删除**  `perms=fastGpt:fastgptEventLogTotal:remove`
+  - [菜单] **诊所管理-广告管理**  `id=29385` path=`adv2` component=`his/adv/index` 显示
+    - └─ [按钮] **新增**  `perms=his:adv:add`
+    - └─ [按钮] **修改**  `perms=his:adv:edit`
+    - └─ [按钮] **导出**  `perms=his:adv:export`
+    - └─ [按钮] **查询**  `perms=his:adv:query`
+    - └─ [按钮] **删除**  `perms=his:adv:remove`
+  - [菜单] **诊所管理-问答管理**  `id=29386` path=`answer` component=`his/answer/index` 显示
+    - └─ [按钮] **新增**  `perms=his:answer:add`
+    - └─ [按钮] **修改**  `perms=his:answer:edit`
+    - └─ [按钮] **导出**  `perms=his:answer:export`
+    - └─ [按钮] **查询**  `perms=his:answer:query`
+    - └─ [按钮] **删除**  `perms=his:answer:remove`
+  - [菜单] **诊所管理-APP版本**  `id=29387` path=`appVersion` component=`his/appVersion/index` 显示
+    - └─ [按钮] **新增**  `perms=his:appVersion:add`
+    - └─ [按钮] **导出**  `perms=his:appVersion:export`
+    - └─ [按钮] **查询**  `perms=his:appVersion:query`
+    - └─ [按钮] **删除**  `perms=his:appVersion:remove`
+    - └─ [按钮] **修改**  `perms=his:appVersion:update`
+  - [菜单] **诊所管理-文章管理**  `id=29388` path=`article2` component=`his/article/index` 显示
+    - └─ [按钮] **新增**  `perms=his:article:add`
+    - └─ [按钮] **修改**  `perms=his:article:edit`
+    - └─ [按钮] **导出**  `perms=his:article:export`
+    - └─ [按钮] **查询**  `perms=his:article:query`
+    - └─ [按钮] **删除**  `perms=his:article:remove`
+  - [菜单] **诊所管理-文章分类**  `id=29389` path=`articleCate` component=`his/articleCate/index` 显示
+    - └─ [按钮] **新增**  `perms=his:articleCate:add`
+    - └─ [按钮] **修改**  `perms=his:articleCate:edit`
+    - └─ [按钮] **导出**  `perms=his:articleCate:export`
+    - └─ [按钮] **查询**  `perms=his:articleCate:query`
+    - └─ [按钮] **删除**  `perms=his:articleCate:remove`
+  - [菜单] **诊所管理-中药管理**  `id=29390` path=`chineseMedicine` component=`his/chineseMedicine/index` 显示
+    - └─ [按钮] **新增**  `perms=his:chineseMedicine:add`
+    - └─ [按钮] **修改**  `perms=his:chineseMedicine:edit`
+    - └─ [按钮] **导出**  `perms=his:chineseMedicine:export`
+    - └─ [按钮] **查询**  `perms=his:chineseMedicine:query`
+    - └─ [按钮] **删除**  `perms=his:chineseMedicine:remove`
+  - [菜单] **诊所管理-企业管理**  `id=29394` path=`company` component=`his/company/index` 显示
+    - └─ [按钮] **新增**  `perms=his:company:add`
+    - └─ [按钮] **扣费**  `perms=his:company:deduct`
+    - └─ [按钮] **修改**  `perms=his:company:edit`
+    - └─ [按钮] **导出**  `perms=his:company:export`
+    - └─ [按钮] **按钮**  `perms=his:company:pass`
+    - └─ [按钮] **查询**  `perms=his:company:query`
+    - └─ [按钮] **充值**  `perms=his:company:recharge`
+    - └─ [按钮] **red扣费**  `perms=his:company:redDeduct`
+    - └─ [按钮] **red充值**  `perms=his:company:redRecharge`
+    - └─ [按钮] **删除**  `perms=his:company:remove`
+  - [菜单] **诊所管理-企业扣款**  `id=29395` path=`companyDeduct` component=`his/companyDeduct/index` 显示
+    - └─ [按钮] **新增**  `perms=his:companyDeduct:add`
+    - └─ [按钮] **修改**  `perms=his:companyDeduct:edit`
+    - └─ [按钮] **导出**  `perms=his:companyDeduct:export`
+    - └─ [按钮] **查询**  `perms=his:companyDeduct:query`
+    - └─ [按钮] **删除**  `perms=his:companyDeduct:remove`
+  - [菜单] **诊所管理-企业充值**  `id=29397` path=`companyRecharge` component=`his/companyRecharge/index` 显示
+    - └─ [按钮] **新增**  `perms=his:companyRecharge:add`
+    - └─ [按钮] **修改**  `perms=his:companyRecharge:edit`
+    - └─ [按钮] **导出**  `perms=his:companyRecharge:export`
+    - └─ [按钮] **查询**  `perms=his:companyRecharge:query`
+    - └─ [按钮] **删除**  `perms=his:companyRecharge:remove`
+  - [菜单] **诊所管理-投诉管理**  `id=29398` path=`complaint` component=`his/complaint/index` 显示
+    - └─ [按钮] **新增**  `perms=his:complaint:add`
+    - └─ [按钮] **修改**  `perms=his:complaint:edit`
+    - └─ [按钮] **导出**  `perms=his:complaint:export`
+    - └─ [按钮] **查询**  `perms=his:complaint:query`
+    - └─ [按钮] **删除**  `perms=his:complaint:remove`
+  - [菜单] **诊所管理-优惠券**  `id=29399` path=`coupon` component=`his/coupon/index` 显示
+    - └─ [按钮] **新增**  `perms=his:coupon:add`
+    - └─ [按钮] **修改**  `perms=his:coupon:edit`
+    - └─ [按钮] **导出**  `perms=his:coupon:export`
+    - └─ [按钮] **查询**  `perms=his:coupon:query`
+    - └─ [按钮] **删除**  `perms=his:coupon:remove`
+  - [菜单] **诊所管理-科室管理**  `id=29400` path=`department` component=`his/department/index` 显示
+    - └─ [按钮] **新增**  `perms=his:department:add`
+    - └─ [按钮] **修改**  `perms=his:department:edit`
+    - └─ [按钮] **导出**  `perms=his:department:export`
+    - └─ [按钮] **查询**  `perms=his:department:query`
+    - └─ [按钮] **删除**  `perms=his:department:remove`
+  - [菜单] **诊所管理-疾病管理**  `id=29402` path=`disease` component=`his/disease/index` 显示
+    - └─ [按钮] **新增**  `perms=his:disease:add`
+    - └─ [按钮] **修改**  `perms=his:disease:edit`
+    - └─ [按钮] **导出**  `perms=his:disease:export`
+    - └─ [按钮] **查询**  `perms=his:disease:query`
+    - └─ [按钮] **删除**  `perms=his:disease:remove`
+  - [菜单] **诊所管理-DIV项目**  `id=29403` path=`divItem` component=`his/divItem/index` 显示
+    - └─ [按钮] **新增**  `perms=his:divItem:add`
+    - └─ [按钮] **按钮**  `perms=his:divItem:confirm`
+    - └─ [按钮] **修改**  `perms=his:divItem:edit`
+    - └─ [按钮] **导出**  `perms=his:divItem:export`
+    - └─ [按钮] **查询**  `perms=his:divItem:query`
+    - └─ [按钮] **删除**  `perms=his:divItem:remove`
+  - [菜单] **诊所管理-医生文章分类**  `id=29405` path=`doctorArticleCate` component=`his/doctorArticleCate/index` 显示
+    - └─ [按钮] **新增**  `perms=his:doctorArticleCate:add`
+    - └─ [按钮] **修改**  `perms=his:doctorArticleCate:edit`
+    - └─ [按钮] **导出**  `perms=his:doctorArticleCate:export`
+    - └─ [按钮] **查询**  `perms=his:doctorArticleCate:query`
+    - └─ [按钮] **删除**  `perms=his:doctorArticleCate:remove`
+  - [菜单] **诊所管理-用药报告**  `id=29412` path=`drugReport` component=`his/drugReport/index` 显示
+    - └─ [按钮] **新增**  `perms=his:drugReport:add`
+    - └─ [按钮] **修改**  `perms=his:drugReport:edit`
+    - └─ [按钮] **导出**  `perms=his:drugReport:export`
+    - └─ [按钮] **查询**  `perms=his:drugReport:query`
+    - └─ [按钮] **删除**  `perms=his:drugReport:remove`
+  - [菜单] **诊所管理-用药统计**  `id=29413` path=`drugReportCount` component=`his/drugReportCount/index` 显示
+    - └─ [按钮] **新增**  `perms=his:drugReportCount:add`
+    - └─ [按钮] **修改**  `perms=his:drugReportCount:edit`
+    - └─ [按钮] **导出**  `perms=his:drugReportCount:export`
+    - └─ [按钮] **查询**  `perms=his:drugReportCount:query`
+    - └─ [按钮] **删除**  `perms=his:drugReportCount:remove`
+  - [菜单] **诊所管理-导出任务**  `id=29414` path=`exportTask` component=`his/exportTask/index` 显示
+    - └─ [按钮] **新增**  `perms=his:exportTask:add`
+    - └─ [按钮] **修改**  `perms=his:exportTask:edit`
+    - └─ [按钮] **导出**  `perms=his:exportTask:export`
+    - └─ [按钮] **查询**  `perms=his:exportTask:query`
+    - └─ [按钮] **删除**  `perms=his:exportTask:remove`
+  - [菜单] **诊所管理-快递管理**  `id=29415` path=`express2` component=`his/express/index` 显示
+    - └─ [按钮] **新增**  `perms=his:express:add`
+    - └─ [按钮] **按钮**  `perms=his:express:allot`
+    - └─ [按钮] **修改**  `perms=his:express:edit`
+    - └─ [按钮] **导出**  `perms=his:express:export`
+    - └─ [按钮] **查询**  `perms=his:express:query`
+    - └─ [按钮] **删除**  `perms=his:express:remove`
+  - [菜单] **诊所管理-名方管理**  `id=29416` path=`famousPrescribe` component=`his/famousPrescribe/index` 显示
+    - └─ [按钮] **新增**  `perms=his:famousPrescribe:add`
+    - └─ [按钮] **修改**  `perms=his:famousPrescribe:edit`
+    - └─ [按钮] **导出**  `perms=his:famousPrescribe:export`
+    - └─ [按钮] **查询**  `perms=his:famousPrescribe:query`
+    - └─ [按钮] **删除**  `perms=his:famousPrescribe:remove`
+  - [菜单] **诊所管理-随访管理**  `id=29417` path=`follow` component=`his/follow/index` 显示
+    - └─ [按钮] **新增**  `perms=his:follow:add`
+    - └─ [按钮] **修改**  `perms=his:follow:edit`
+    - └─ [按钮] **导出**  `perms=his:follow:export`
+    - └─ [按钮] **查询**  `perms=his:follow:query`
+    - └─ [按钮] **删除**  `perms=his:follow:remove`
+    - └─ [按钮] **统计**  `perms=his:follow:statistics`
+  - [菜单] **诊所管理-随访模板**  `id=29418` path=`followTemp` component=`his/followTemp/index` 显示
+    - └─ [按钮] **新增**  `perms=his:followTemp:add`
+    - └─ [按钮] **修改**  `perms=his:followTemp:edit`
+    - └─ [按钮] **导出**  `perms=his:followTemp:export`
+    - └─ [按钮] **查询**  `perms=his:followTemp:query`
+    - └─ [按钮] **删除**  `perms=his:followTemp:remove`
+  - [菜单] **诊所管理-首诊管理**  `id=29419` path=`fsFirstDiagnosis` component=`his/fsFirstDiagnosis/index` 显示
+    - └─ [按钮] **新增**  `perms=his:fsFirstDiagnosis:add`
+    - └─ [按钮] **修改**  `perms=his:fsFirstDiagnosis:edit`
+    - └─ [按钮] **导出**  `perms=his:fsFirstDiagnosis:export`
+    - └─ [按钮] **查询**  `perms=his:fsFirstDiagnosis:query`
+    - └─ [按钮] **删除**  `perms=his:fsFirstDiagnosis:remove`
+  - [菜单] **诊所管理-健康史模板**  `id=29422` path=`healthHistoryTemp` component=`his/healthHistoryTemp/index` 显示
+    - └─ [按钮] **新增**  `perms=his:healthHistoryTemp:add`
+    - └─ [按钮] **修改**  `perms=his:healthHistoryTemp:edit`
+    - └─ [按钮] **导出**  `perms=his:healthHistoryTemp:export`
+    - └─ [按钮] **查询**  `perms=his:healthHistoryTemp:query`
+    - └─ [按钮] **删除**  `perms=his:healthHistoryTemp:remove`
+  - [菜单] **诊所管理-健康档案**  `id=29424` path=`healthRecord` component=`his/healthRecord/index` 显示
+    - └─ [按钮] **新增**  `perms=his:healthRecord:add`
+    - └─ [按钮] **修改**  `perms=his:healthRecord:edit`
+    - └─ [按钮] **导出**  `perms=his:healthRecord:export`
+    - └─ [按钮] **查询**  `perms=his:healthRecord:query`
+    - └─ [按钮] **删除**  `perms=his:healthRecord:remove`
+  - [菜单] **诊所管理-汇付支付配置**  `id=29426` path=`hfpayConfig` component=`his/hfpayConfig/index` 显示
+    - └─ [按钮] **新增**  `perms=his:hfpayConfig:add`
+    - └─ [按钮] **修改**  `perms=his:hfpayConfig:edit`
+    - └─ [按钮] **导出**  `perms=his:hfpayConfig:export`
+    - └─ [按钮] **查询**  `perms=his:hfpayConfig:query`
+    - └─ [按钮] **删除**  `perms=his:hfpayConfig:remove`
+  - [菜单] **诊所管理-医院管理**  `id=29427` path=`hospital` component=`his/hospital/index` 显示
+    - └─ [按钮] **新增**  `perms=his:hospital:add`
+    - └─ [按钮] **修改**  `perms=his:hospital:edit`
+    - └─ [按钮] **导出**  `perms=his:hospital:export`
+    - └─ [按钮] **查询**  `perms=his:hospital:query`
+    - └─ [按钮] **删除**  `perms=his:hospital:remove`
+  - [菜单] **诊所管理-ICD编码**  `id=29428` path=`icd` component=`his/icd/index` 显示
+    - └─ [按钮] **新增**  `perms=his:icd:add`
+    - └─ [按钮] **修改**  `perms=his:icd:edit`
+    - └─ [按钮] **导出**  `perms=his:icd:export`
+    - └─ [按钮] **查询**  `perms=his:icd:query`
+    - └─ [按钮] **删除**  `perms=his:icd:remove`
+  - [菜单] **诊所管理-疾病库**  `id=29429` path=`illnessLibrary` component=`his/illnessLibrary/index` 显示
+    - └─ [按钮] **新增**  `perms=his:illnessLibrary:add`
+    - └─ [按钮] **修改**  `perms=his:illnessLibrary:edit`
+    - └─ [按钮] **导出**  `perms=his:illnessLibrary:export`
+    - └─ [按钮] **查询**  `perms=his:illnessLibrary:query`
+    - └─ [按钮] **删除**  `perms=his:illnessLibrary:remove`
+  - [菜单] **诊所管理-问诊疾病**  `id=29430` path=`inquiryDisease` component=`his/inquiryDisease/index` 显示
+    - └─ [按钮] **新增**  `perms=his:inquiryDisease:add`
+    - └─ [按钮] **修改**  `perms=his:inquiryDisease:edit`
+    - └─ [按钮] **导出**  `perms=his:inquiryDisease:export`
+    - └─ [按钮] **查询**  `perms=his:inquiryDisease:query`
+    - └─ [按钮] **删除**  `perms=his:inquiryDisease:remove`
+  - [菜单] **诊所管理-问诊订单Ping**  `id=29432` path=`inquiryOrderPing` component=`his/inquiryOrderPing/index` 显示
+    - └─ [按钮] **新增**  `perms=his:inquiryOrderPing:add`
+    - └─ [按钮] **修改**  `perms=his:inquiryOrderPing:edit`
+    - └─ [按钮] **导出**  `perms=his:inquiryOrderPing:export`
+    - └─ [按钮] **查询**  `perms=his:inquiryOrderPing:query`
+    - └─ [按钮] **删除**  `perms=his:inquiryOrderPing:remove`
+  - [菜单] **诊所管理-问诊订单报告**  `id=29433` path=`inquiryOrderReport` component=`his/inquiryOrderReport/index` 显示
+    - └─ [按钮] **新增**  `perms=his:inquiryOrderReport:add`
+    - └─ [按钮] **问诊订单报表审核**  `perms=his:inquiryOrderReport:audit`
+    - └─ [按钮] **修改**  `perms=his:inquiryOrderReport:edit`
+    - └─ [按钮] **导出**  `perms=his:inquiryOrderReport:export`
+    - └─ [按钮] **查询**  `perms=his:inquiryOrderReport:query`
+    - └─ [按钮] **query患者mobile**  `perms=his:inquiryOrderReport:queryPatientMobile`
+    - └─ [按钮] **删除**  `perms=his:inquiryOrderReport:remove`
+  - [菜单] **诊所管理-问诊模板**  `id=29435` path=`inquiryTemp` component=`his/inquiryTemp/index` 显示
+    - └─ [按钮] **新增**  `perms=his:inquiryTemp:add`
+    - └─ [按钮] **修改**  `perms=his:inquiryTemp:edit`
+    - └─ [按钮] **导出**  `perms=his:inquiryTemp:export`
+    - └─ [按钮] **查询**  `perms=his:inquiryTemp:query`
+    - └─ [按钮] **删除**  `perms=his:inquiryTemp:remove`
+  - [菜单] **诊所管理-积分商品**  `id=29436` path=`integralGoods2` component=`his/integralGoods/index` 显示
+    - └─ [按钮] **新增**  `perms=his:integralGoods:add`
+    - └─ [按钮] **修改**  `perms=his:integralGoods:edit`
+    - └─ [按钮] **导出**  `perms=his:integralGoods:export`
+    - └─ [按钮] **查询**  `perms=his:integralGoods:query`
+    - └─ [按钮] **删除**  `perms=his:integralGoods:remove`
+  - [菜单] **诊所管理-积分订单**  `id=29437` path=`integralOrder2` component=`his/integralOrder/index` 显示
+    - └─ [按钮] **新增**  `perms=his:integralOrder:add`
+    - └─ [按钮] **积分订单取消**  `perms=his:integralOrder:cancel`
+    - └─ [按钮] **修改**  `perms=his:integralOrder:edit`
+    - └─ [按钮] **导出**  `perms=his:integralOrder:export`
+    - └─ [按钮] **按钮**  `perms=his:integralOrder:express`
+    - └─ [按钮] **查询**  `perms=his:integralOrder:query`
+    - └─ [按钮] **queryphone**  `perms=his:integralOrder:queryPhone`
+    - └─ [按钮] **删除**  `perms=his:integralOrder:remove`
+    - └─ [按钮] **sendgoods**  `perms=his:integralOrder:sendGoods`
+  - [菜单] **诊所管理-药膳食疗**  `id=29439` path=`medicatedFood` component=`his/medicatedFood/index` 显示
+    - └─ [按钮] **新增**  `perms=his:medicatedFood:add`
+    - └─ [按钮] **修改**  `perms=his:medicatedFood:edit`
+    - └─ [按钮] **导出**  `perms=his:medicatedFood:export`
+    - └─ [按钮] **查询**  `perms=his:medicatedFood:query`
+    - └─ [按钮] **删除**  `perms=his:medicatedFood:remove`
+  - [菜单] **诊所管理-商户应用配置**  `id=29440` path=`merchantAppConfig` component=`his/merchantAppConfig/index` 显示
+    - └─ [按钮] **新增**  `perms=his:merchantAppConfig:add`
+    - └─ [按钮] **修改**  `perms=his:merchantAppConfig:edit`
+    - └─ [按钮] **导出**  `perms=his:merchantAppConfig:export`
+    - └─ [按钮] **查询**  `perms=his:merchantAppConfig:query`
+    - └─ [按钮] **删除**  `perms=his:merchantAppConfig:remove`
+  - [菜单] **诊所管理-患者管理**  `id=29446` path=`patient` component=`his/patient/index` 显示
+    - └─ [按钮] **新增**  `perms=his:patient:add`
+    - └─ [按钮] **修改**  `perms=his:patient:edit`
+    - └─ [按钮] **导出**  `perms=his:patient:export`
+    - └─ [按钮] **删除**  `perms=his:patient:remove`
+  - [菜单] **诊所管理-体检报告模板**  `id=29448` path=`physicalReportTemplate` component=`his/physicalReportTemplate/index` 显示
+    - └─ [按钮] **新增**  `perms=his:physicalReportTemplate:add`
+    - └─ [按钮] **修改**  `perms=his:physicalReportTemplate:edit`
+    - └─ [按钮] **导出**  `perms=his:physicalReportTemplate:export`
+    - └─ [按钮] **查询**  `perms=his:physicalReportTemplate:query`
+    - └─ [按钮] **删除**  `perms=his:physicalReportTemplate:remove`
+  - [菜单] **诊所管理-体检报告模板字段**  `id=29449` path=`physicalReportTemplateField` component=`his/physicalReportTemplateField/index` 显示
+    - └─ [按钮] **新增**  `perms=his:physicalReportTemplateField:add`
+    - └─ [按钮] **修改**  `perms=his:physicalReportTemplateField:edit`
+    - └─ [按钮] **导出**  `perms=his:physicalReportTemplateField:export`
+    - └─ [按钮] **查询**  `perms=his:physicalReportTemplateField:query`
+    - └─ [按钮] **删除**  `perms=his:physicalReportTemplateField:remove`
+  - [菜单] **诊所管理-题库管理**  `id=29455` path=`questions` component=`his/questions/index` 显示
+    - └─ [按钮] **新增**  `perms=his:questions:add`
+    - └─ [按钮] **修改**  `perms=his:questions:edit`
+    - └─ [按钮] **导出**  `perms=his:questions:export`
+    - └─ [按钮] **查询**  `perms=his:questions:query`
+    - └─ [按钮] **删除**  `perms=his:questions:remove`
+  - [菜单] **诊所管理-门店管理**  `id=29456` path=`store3` component=`his/store/index` 显示
+    - └─ [按钮] **新增**  `perms=his:store:add`
+    - └─ [按钮] **商城审核**  `perms=his:store:audit`
+    - └─ [按钮] **修改**  `perms=his:store:edit`
+    - └─ [按钮] **导出**  `perms=his:store:export`
+    - └─ [按钮] **查询**  `perms=his:store:query`
+    - └─ [按钮] **删除**  `perms=his:store:remove`
+  - [菜单] **诊所管理-门店活动**  `id=29457` path=`storeActivity2` component=`his/storeActivity/index` 显示
+    - └─ [按钮] **新增**  `perms=his:storeActivity:add`
+    - └─ [按钮] **修改**  `perms=his:storeActivity:edit`
+    - └─ [按钮] **导出**  `perms=his:storeActivity:export`
+    - └─ [按钮] **查询**  `perms=his:storeActivity:query`
+    - └─ [按钮] **删除**  `perms=his:storeActivity:remove`
+  - [菜单] **诊所管理-门店支付**  `id=29463` path=`storePayment2` component=`his/storePayment/index` 显示
+    - └─ [按钮] **新增**  `perms=his:storePayment:add`
+    - └─ [按钮] **修改**  `perms=his:storePayment:edit`
+    - └─ [按钮] **导出**  `perms=his:storePayment:export`
+    - └─ [按钮] **查询**  `perms=his:storePayment:query`
+    - └─ [按钮] **按钮**  `perms=his:storePayment:refund`
+    - └─ [按钮] **删除**  `perms=his:storePayment:remove`
+  - [菜单] **诊所管理-门店商品**  `id=29464` path=`storeProduct2` component=`his/storeProduct/index` 显示
+    - └─ [按钮] **新增**  `perms=his:storeProduct:add`
+    - └─ [按钮] **修改**  `perms=his:storeProduct:edit`
+    - └─ [按钮] **editprice**  `perms=his:storeProduct:editPrice`
+    - └─ [按钮] **导出**  `perms=his:storeProduct:export`
+    - └─ [按钮] **删除**  `perms=his:storeProduct:remove`
+  - [菜单] **诊所管理-门店商品分类**  `id=29465` path=`storeProductCategory2` component=`his/storeProductCategory/index` 显示
+    - └─ [按钮] **新增**  `perms=his:storeProductCategory:add`
+    - └─ [按钮] **修改**  `perms=his:storeProductCategory:edit`
+    - └─ [按钮] **导出**  `perms=his:storeProductCategory:export`
+    - └─ [按钮] **查询**  `perms=his:storeProductCategory:query`
+    - └─ [按钮] **删除**  `perms=his:storeProductCategory:remove`
+  - [菜单] **诊所管理-门店子订单**  `id=29466` path=`storeSubOrder` component=`his/storeSubOrder/index` 显示
+    - └─ [按钮] **新增**  `perms=his:storeSubOrder:add`
+    - └─ [按钮] **修改**  `perms=his:storeSubOrder:edit`
+    - └─ [按钮] **导出**  `perms=his:storeSubOrder:export`
+    - └─ [按钮] **查询**  `perms=his:storeSubOrder:query`
+    - └─ [按钮] **删除**  `perms=his:storeSubOrder:remove`
+  - [菜单] **诊所管理-检测报告**  `id=29468` path=`testReport` component=`his/testReport/index` 显示
+    - └─ [按钮] **新增**  `perms=his:testReport:add`
+    - └─ [按钮] **修改**  `perms=his:testReport:edit`
+    - └─ [按钮] **导出**  `perms=his:testReport:export`
+    - └─ [按钮] **查询**  `perms=his:testReport:query`
+    - └─ [按钮] **删除**  `perms=his:testReport:remove`
+  - [菜单] **诊所管理-检测模板**  `id=29469` path=`testTemp` component=`his/testTemp/index` 显示
+    - └─ [按钮] **新增**  `perms=his:testTemp:add`
+    - └─ [按钮] **修改**  `perms=his:testTemp:edit`
+    - └─ [按钮] **导出**  `perms=his:testTemp:export`
+    - └─ [按钮] **查询**  `perms=his:testTemp:query`
+    - └─ [按钮] **删除**  `perms=his:testTemp:remove`
+  - [菜单] **诊所管理-用户管理**  `id=29470` path=`user` component=`his/user/index` 显示
+    - └─ [按钮] **新增**  `perms=his:user:add`
+    - └─ [按钮] **addpoints**  `perms=his:user:addPoints`
+    - └─ [按钮] **黑名单**  `perms=his:user:blacklist`
+    - └─ [按钮] **darkroom列表**  `perms=his:user:darkRoomList`
+    - └─ [按钮] **修改**  `perms=his:user:edit`
+    - └─ [按钮] **enabledblack用户**  `perms=his:user:enabledBlackUsers`
+    - └─ [按钮] **enabled用户**  `perms=his:user:enabledUsers`
+    - └─ [按钮] **导出**  `perms=his:user:export`
+    - └─ [按钮] **删除**  `perms=his:user:remove`
+    - └─ [按钮] **用户解绑**  `perms=his:user:unbind`
+  - [菜单] **诊所管理-用户优惠券**  `id=29474` path=`userCoupon` component=`his/userCoupon/index` 显示
+    - └─ [按钮] **新增**  `perms=his:userCoupon:add`
+    - └─ [按钮] **修改**  `perms=his:userCoupon:edit`
+    - └─ [按钮] **导出**  `perms=his:userCoupon:export`
+    - └─ [按钮] **查询**  `perms=his:userCoupon:query`
+    - └─ [按钮] **删除**  `perms=his:userCoupon:remove`
+    - └─ [按钮] **按钮**  `perms=his:userCoupon:send`
+  - [菜单] **诊所管理-用户积分日志**  `id=29476` path=`userIntegralLogs` component=`his/userIntegralLogs/index` 显示
+    - └─ [按钮] **新增**  `perms=his:userIntegralLogs:add`
+    - └─ [按钮] **修改**  `perms=his:userIntegralLogs:edit`
+    - └─ [按钮] **导出**  `perms=his:userIntegralLogs:export`
+    - └─ [按钮] **查询**  `perms=his:userIntegralLogs:query`
+    - └─ [按钮] **删除**  `perms=his:userIntegralLogs:remove`
+  - [菜单] **诊所管理-用户充值**  `id=29479` path=`userRecharge` component=`his/userRecharge/index` 显示
+    - └─ [按钮] **新增**  `perms=his:userRecharge:add`
+    - └─ [按钮] **修改**  `perms=his:userRecharge:edit`
+    - └─ [按钮] **导出**  `perms=his:userRecharge:export`
+    - └─ [按钮] **查询**  `perms=his:userRecharge:query`
+    - └─ [按钮] **删除**  `perms=his:userRecharge:remove`
+  - [菜单] **诊所管理-体质管理**  `id=29480` path=`vessel` component=`his/vessel/index` 显示
+    - └─ [按钮] **新增**  `perms=his:vessel:add`
+    - └─ [按钮] **修改**  `perms=his:vessel:edit`
+    - └─ [按钮] **导出**  `perms=his:vessel:export`
+    - └─ [按钮] **查询**  `perms=his:vessel:query`
+    - └─ [按钮] **删除**  `perms=his:vessel:remove`
+  - [菜单] **直播管理-礼物管理**  `id=29489` path=`gift` component=`live/gift/index` 显示
+    - └─ [按钮] **新增**  `perms=live:gift:add`
+    - └─ [按钮] **修改**  `perms=live:gift:edit`
+    - └─ [按钮] **导出**  `perms=live:gift:export`
+    - └─ [按钮] **查询**  `perms=live:gift:query`
+    - └─ [按钮] **删除**  `perms=live:gift:remove`
+  - [菜单] **直播管理-售后明细**  `id=29494` path=`liveAfterSalesItem` component=`live/liveAfterSalesItem/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveAfterSalesItem:add`
+    - └─ [按钮] **修改**  `perms=live:liveAfterSalesItem:edit`
+    - └─ [按钮] **导出**  `perms=live:liveAfterSalesItem:export`
+    - └─ [按钮] **查询**  `perms=live:liveAfterSalesItem:query`
+    - └─ [按钮] **删除**  `perms=live:liveAfterSalesItem:remove`
+  - [菜单] **直播管理-售后日志**  `id=29495` path=`liveAfterSalesLogs` component=`live/liveAfterSalesLogs/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveAfterSalesLogs:add`
+    - └─ [按钮] **修改**  `perms=live:liveAfterSalesLogs:edit`
+    - └─ [按钮] **导出**  `perms=live:liveAfterSalesLogs:export`
+    - └─ [按钮] **查询**  `perms=live:liveAfterSalesLogs:query`
+    - └─ [按钮] **删除**  `perms=live:liveAfterSalesLogs:remove`
+  - [菜单] **直播管理-主播管理**  `id=29496` path=`liveAnchor` component=`live/liveAnchor/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveAnchor:add`
+    - └─ [按钮] **修改**  `perms=live:liveAnchor:edit`
+    - └─ [按钮] **导出**  `perms=live:liveAnchor:export`
+    - └─ [按钮] **查询**  `perms=live:liveAnchor:query`
+    - └─ [按钮] **删除**  `perms=live:liveAnchor:remove`
+  - [菜单] **直播管理-直播购物车**  `id=29497` path=`liveCart` component=`live/liveCart/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveCart:add`
+    - └─ [按钮] **修改**  `perms=live:liveCart:edit`
+    - └─ [按钮] **导出**  `perms=live:liveCart:export`
+    - └─ [按钮] **查询**  `perms=live:liveCart:query`
+    - └─ [按钮] **删除**  `perms=live:liveCart:remove`
+  - [菜单] **直播管理-直播优惠券**  `id=29498` path=`liveCoupon` component=`live/liveCoupon/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveCoupon:add`
+    - └─ [按钮] **batchpublish**  `perms=live:liveCoupon:batchPublish`
+    - └─ [按钮] **修改**  `perms=live:liveCoupon:edit`
+    - └─ [按钮] **导出**  `perms=live:liveCoupon:export`
+    - └─ [按钮] **直播优扣券发布**  `perms=live:liveCoupon:publish`
+    - └─ [按钮] **查询**  `perms=live:liveCoupon:query`
+    - └─ [按钮] **删除**  `perms=live:liveCoupon:remove`
+  - [菜单] **直播管理-活动配置**  `id=29499` path=`liveEventConf` component=`live/liveEventConf/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveEventConf:add`
+    - └─ [按钮] **修改**  `perms=live:liveEventConf:edit`
+    - └─ [按钮] **导出**  `perms=live:liveEventConf:export`
+    - └─ [按钮] **查询**  `perms=live:liveEventConf:query`
+    - └─ [按钮] **删除**  `perms=live:liveEventConf:remove`
+  - [菜单] **直播管理-直播商品**  `id=29500` path=`liveGoods` component=`live/liveGoods/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveGoods:add`
+    - └─ [按钮] **修改**  `perms=live:liveGoods:edit`
+    - └─ [按钮] **导出**  `perms=live:liveGoods:export`
+    - └─ [按钮] **查询**  `perms=live:liveGoods:query`
+    - └─ [按钮] **删除**  `perms=live:liveGoods:remove`
+  - [菜单] **直播管理-抽奖配置**  `id=29501` path=`liveLotteryConf` component=`live/liveLotteryConf/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveLotteryConf:add`
+    - └─ [按钮] **修改**  `perms=live:liveLotteryConf:edit`
+    - └─ [按钮] **导出**  `perms=live:liveLotteryConf:export`
+    - └─ [按钮] **查询**  `perms=live:liveLotteryConf:query`
+    - └─ [按钮] **删除**  `perms=live:liveLotteryConf:remove`
+  - [菜单] **直播管理-抽奖记录**  `id=29502` path=`liveLotteryRecord` component=`live/liveLotteryRecord/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveLotteryRecord:add`
+    - └─ [按钮] **修改**  `perms=live:liveLotteryRecord:edit`
+    - └─ [按钮] **导出**  `perms=live:liveLotteryRecord:export`
+    - └─ [按钮] **查询**  `perms=live:liveLotteryRecord:query`
+    - └─ [按钮] **删除**  `perms=live:liveLotteryRecord:remove`
+  - [菜单] **直播管理-抽奖报名**  `id=29503` path=`liveLotteryRegistration` component=`live/liveLotteryRegistration/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveLotteryRegistration:add`
+    - └─ [按钮] **修改**  `perms=live:liveLotteryRegistration:edit`
+    - └─ [按钮] **导出**  `perms=live:liveLotteryRegistration:export`
+    - └─ [按钮] **查询**  `perms=live:liveLotteryRegistration:query`
+    - └─ [按钮] **删除**  `perms=live:liveLotteryRegistration:remove`
+  - [菜单] **直播管理-小程序直播**  `id=29504` path=`liveMiniLives` component=`live/liveMiniLives/index` 显示
+  - [菜单] **直播管理-直播消息**  `id=29505` path=`liveMsg` component=`live/liveMsg/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveMsg:add`
+    - └─ [按钮] **修改**  `perms=live:liveMsg:edit`
+    - └─ [按钮] **导出**  `perms=live:liveMsg:export`
+    - └─ [按钮] **查询**  `perms=live:liveMsg:query`
+    - └─ [按钮] **删除**  `perms=live:liveMsg:remove`
+  - [菜单] **直播管理-直播订单**  `id=29506` path=`liveOrder` component=`live/liveOrder/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveOrder:add`
+    - └─ [按钮] **addtuimoney**  `perms=live:liveOrder:addTuiMoney`
+    - └─ [按钮] **auditpayremain**  `perms=live:liveOrder:auditPayRemain`
+    - └─ [按钮] **createerp订单**  `perms=live:liveOrder:createErpOrder`
+    - └─ [按钮] **修改**  `perms=live:liveOrder:edit`
+    - └─ [按钮] **editdeliveryid**  `perms=live:liveOrder:editDeliveryId`
+    - └─ [按钮] **edittuimoney**  `perms=live:liveOrder:editTuiMoney`
+    - └─ [按钮] **导出**  `perms=live:liveOrder:export`
+    - └─ [按钮] **finish订单**  `perms=live:liveOrder:finishOrder`
+    - └─ [按钮] **getero订单**  `perms=live:liveOrder:getEroOrder`
+    - └─ [按钮] **health导出运费订单**  `perms=live:liveOrder:healthExportShippingOrder`
+    - └─ [按钮] **按钮**  `perms=live:liveOrder:pay`
+    - └─ [按钮] **查询**  `perms=live:liveOrder:query`
+    - └─ [按钮] **queryaddress**  `perms=live:liveOrder:queryAddress`
+    - └─ [按钮] **queryphone**  `perms=live:liveOrder:queryPhone`
+    - └─ [按钮] **refund订单money**  `perms=live:liveOrder:refundOrderMoney`
+    - └─ [按钮] **删除**  `perms=live:liveOrder:remove`
+    - └─ [按钮] **syncexpress**  `perms=live:liveOrder:syncExpress`
+    - └─ [按钮] **updateerp订单**  `perms=live:liveOrder:updateErpOrder`
+    - └─ [按钮] **updateexpress**  `perms=live:liveOrder:updateExpress`
+  - [菜单] **直播管理-直播订单明细**  `id=29507` path=`liveOrderItem` component=`live/liveOrderItem/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveOrderItem:add`
+    - └─ [按钮] **修改**  `perms=live:liveOrderItem:edit`
+    - └─ [按钮] **导出**  `perms=live:liveOrderItem:export`
+    - └─ [按钮] **查询**  `perms=live:liveOrderItem:query`
+    - └─ [按钮] **删除**  `perms=live:liveOrderItem:remove`
+  - [菜单] **直播管理-直播订单日志**  `id=29508` path=`liveOrderLogs` component=`live/liveOrderLogs/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveOrderLogs:add`
+    - └─ [按钮] **修改**  `perms=live:liveOrderLogs:edit`
+    - └─ [按钮] **导出**  `perms=live:liveOrderLogs:export`
+    - └─ [按钮] **查询**  `perms=live:liveOrderLogs:query`
+    - └─ [按钮] **删除**  `perms=live:liveOrderLogs:remove`
+  - [菜单] **直播管理-红包配置**  `id=29509` path=`liveRedConf` component=`live/liveRedConf/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveRedConf:add`
+    - └─ [按钮] **修改**  `perms=live:liveRedConf:edit`
+    - └─ [按钮] **导出**  `perms=live:liveRedConf:export`
+    - └─ [按钮] **查询**  `perms=live:liveRedConf:query`
+    - └─ [按钮] **删除**  `perms=live:liveRedConf:remove`
+  - [菜单] **直播管理-用户抽奖记录**  `id=29513` path=`liveUserLotteryRecord` component=`live/liveUserLotteryRecord/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveUserLotteryRecord:add`
+    - └─ [按钮] **修改**  `perms=live:liveUserLotteryRecord:edit`
+    - └─ [按钮] **导出**  `perms=live:liveUserLotteryRecord:export`
+    - └─ [按钮] **查询**  `perms=live:liveUserLotteryRecord:query`
+    - └─ [按钮] **删除**  `perms=live:liveUserLotteryRecord:remove`
+  - [菜单] **直播管理-用户红包记录**  `id=29514` path=`liveUserRedRecord` component=`live/liveUserRedRecord/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveUserRedRecord:add`
+    - └─ [按钮] **修改**  `perms=live:liveUserRedRecord:edit`
+    - └─ [按钮] **导出**  `perms=live:liveUserRedRecord:export`
+    - └─ [按钮] **查询**  `perms=live:liveUserRedRecord:query`
+    - └─ [按钮] **删除**  `perms=live:liveUserRedRecord:remove`
+  - [菜单] **直播管理-直播视频**  `id=29515` path=`liveVideo2` component=`live/liveVideo/index` 显示
+    - └─ [按钮] **新增**  `perms=live:liveVideo:add`
+    - └─ [按钮] **修改**  `perms=live:liveVideo:edit`
+    - └─ [按钮] **导出**  `perms=live:liveVideo:export`
+    - └─ [按钮] **查询**  `perms=live:liveVideo:query`
+    - └─ [按钮] **删除**  `perms=live:liveVideo:remove`
+  - [菜单] **直播管理-话术管理**  `id=29522` path=`words` component=`live/words/index` 显示
+    - └─ [按钮] **新增**  `perms=live:words:add`
+    - └─ [按钮] **修改**  `perms=live:words:edit`
+    - └─ [按钮] **导出**  `perms=live:words:export`
+    - └─ [按钮] **查询**  `perms=live:words:query`
+    - └─ [按钮] **删除**  `perms=live:words:remove`
+  - [菜单] **系统监控-缓存监控**  `id=29525` path=`cache` component=`monitor/cache/index` 显示
+  - [菜单] **系统监控-登录日志**  `id=29526` path=`logininfor` component=`monitor/logininfor/index` 显示
+    - └─ [按钮] **导出**  `perms=monitor:logininfor:export`
+    - └─ [按钮] **删除**  `perms=monitor:logininfor:remove`
+  - [菜单] **系统监控-在线用户**  `id=29527` path=`online` component=`monitor/online/index` 显示
+    - └─ [按钮] **forcelogout**  `perms=monitor:online:forceLogout`
+  - [菜单] **系统监控-操作日志**  `id=29528` path=`operlog` component=`monitor/operlog/index` 显示
+    - └─ [按钮] **导出**  `perms=monitor:operlog:export`
+    - └─ [按钮] **删除**  `perms=monitor:operlog:remove`
+  - [菜单] **系统监控-服务器监控**  `id=29529` path=`server` component=`monitor/server/index` 显示
+  - [菜单] **企微管理-外部联系人**  `id=29556` path=`externalContact` component=`qw/externalContact/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:externalContact:add`
+    - └─ [按钮] **add标签**  `perms=qw:externalContact:addTag`
+    - └─ [按钮] **add未分配**  `perms=qw:externalContact:addUnassigned`
+    - └─ [按钮] **修改**  `perms=qw:externalContact:edit`
+    - └─ [按钮] **导出**  `perms=qw:externalContact:export`
+    - └─ [按钮] **get用户信息**  `perms=qw:externalContact:getUserInfo`
+    - └─ [按钮] **查询**  `perms=qw:externalContact:query`
+    - └─ [按钮] **删除**  `perms=qw:externalContact:remove`
+    - └─ [按钮] **转移**  `perms=qw:externalContact:transfer`
+  - [菜单] **企微管理-好友欢迎语**  `id=29565` path=`friendWelcome` component=`qw/friendWelcome/index` 显示
+  - [菜单] **企微管理-客户群管理**  `id=29567` path=`groupChat` component=`qw/groupChat/index` 显示
+    - └─ [按钮] **部门列表**  `perms=qw:groupChat:deptList`
+    - └─ [按钮] **my列表**  `perms=qw:groupChat:myList`
+    - └─ [按钮] **查询**  `perms=qw:groupChat:query`
+  - [菜单] **企微管理-企微企业**  `id=29577` path=`qwCompany` component=`qw/qwCompany/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:qwCompany:add`
+    - └─ [按钮] **修改**  `perms=qw:qwCompany:edit`
+    - └─ [按钮] **导出**  `perms=qw:qwCompany:export`
+    - └─ [按钮] **查询**  `perms=qw:qwCompany:query`
+    - └─ [按钮] **删除**  `perms=qw:qwCompany:remove`
+    - └─ [按钮] **租户**  `perms=qw:qwCompany:tenant`
+  - [菜单] **企微管理-企微信息**  `id=29579` path=`qwInformation` component=`qw/qwInformation/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:qwInformation:add`
+    - └─ [按钮] **修改**  `perms=qw:qwInformation:edit`
+    - └─ [按钮] **导出**  `perms=qw:qwInformation:export`
+    - └─ [按钮] **查询**  `perms=qw:qwInformation:query`
+    - └─ [按钮] **删除**  `perms=qw:qwInformation:remove`
+  - [菜单] **企微管理-iPad服务**  `id=29580` path=`qwIpadServer` component=`qw/qwIpadServer/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:qwIpadServer:add`
+    - └─ [按钮] **修改**  `perms=qw:qwIpadServer:edit`
+    - └─ [按钮] **导出**  `perms=qw:qwIpadServer:export`
+    - └─ [按钮] **查询**  `perms=qw:qwIpadServer:query`
+    - └─ [按钮] **删除**  `perms=qw:qwIpadServer:remove`
+  - [菜单] **企微管理-iPad服务日志**  `id=29581` path=`qwIpadServerLog` component=`qw/qwIpadServerLog/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:qwIpadServerLog:add`
+    - └─ [按钮] **修改**  `perms=qw:qwIpadServerLog:edit`
+    - └─ [按钮] **导出**  `perms=qw:qwIpadServerLog:export`
+    - └─ [按钮] **查询**  `perms=qw:qwIpadServerLog:query`
+    - └─ [按钮] **删除**  `perms=qw:qwIpadServerLog:remove`
+  - [菜单] **企微管理-iPad服务用户**  `id=29582` path=`qwIpadServerUser` component=`qw/qwIpadServerUser/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:qwIpadServerUser:add`
+    - └─ [按钮] **修改**  `perms=qw:qwIpadServerUser:edit`
+    - └─ [按钮] **导出**  `perms=qw:qwIpadServerUser:export`
+    - └─ [按钮] **查询**  `perms=qw:qwIpadServerUser:query`
+    - └─ [按钮] **删除**  `perms=qw:qwIpadServerUser:remove`
+  - [菜单] **企微管理-企微用户**  `id=29596` path=`user2` component=`qw/user/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:user:add`
+    - └─ [按钮] **authappkey**  `perms=qw:user:authAppKey`
+    - └─ [按钮] **用户绑定**  `perms=qw:user:bind`
+    - └─ [按钮] **bindai**  `perms=qw:user:bindAi`
+    - └─ [按钮] **bindip**  `perms=qw:user:bindIp`
+    - └─ [按钮] **按钮**  `perms=qw:user:cloudAP`
+    - └─ [按钮] **导出**  `perms=qw:user:export`
+    - └─ [按钮] **按钮**  `perms=qw:user:isauto`
+    - └─ [按钮] **按钮**  `perms=qw:user:login`
+    - └─ [按钮] **loginip**  `perms=qw:user:loginIp`
+    - └─ [按钮] **loginipout**  `perms=qw:user:loginIpOut`
+    - └─ [按钮] **mydepart列表**  `perms=qw:user:myDepartList`
+    - └─ [按钮] **my列表**  `perms=qw:user:myList`
+    - └─ [按钮] **my员工列表**  `perms=qw:user:myStaffList`
+    - └─ [按钮] **删除**  `perms=qw:user:remove`
+    - └─ [按钮] **staff列表**  `perms=qw:user:staffList`
+    - └─ [按钮] **staff列表岗位**  `perms=qw:user:staffListPost`
+    - └─ [按钮] **用户同步**  `perms=qw:user:sync`
+  - [菜单] **企微管理-获客链接**  `id=29600` path=`workLink` component=`qw/workLink/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:workLink:add`
+    - └─ [按钮] **修改**  `perms=qw:workLink:edit`
+    - └─ [按钮] **导出**  `perms=qw:workLink:export`
+    - └─ [按钮] **列表all**  `perms=qw:workLink:listAll`
+    - └─ [按钮] **查询**  `perms=qw:workLink:query`
+    - └─ [按钮] **删除**  `perms=qw:workLink:remove`
+  - [菜单] **企微管理-获客链接用户**  `id=29601` path=`workLinkUser` component=`qw/workLinkUser/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:workLinkUser:add`
+    - └─ [按钮] **修改**  `perms=qw:workLinkUser:edit`
+    - └─ [按钮] **导出**  `perms=qw:workLinkUser:export`
+    - └─ [按钮] **查询**  `perms=qw:workLinkUser:query`
+    - └─ [按钮] **删除**  `perms=qw:workLinkUser:remove`
+  - [菜单] **企微管理-企微员工**  `id=29602` path=`workUser` component=`qw/workUser/index` 显示
+    - └─ [按钮] **新增**  `perms=qw:workUser:add`
+    - └─ [按钮] **修改**  `perms=qw:workUser:edit`
+    - └─ [按钮] **导出**  `perms=qw:workUser:export`
+    - └─ [按钮] **查询**  `perms=qw:workUser:query`
+    - └─ [按钮] **删除**  `perms=qw:workUser:remove`
+  - [菜单] **商城管理-商城支付**  `id=29656` path=`storePayment3` component=`store/storePayment/index` 显示
+    - └─ [按钮] **新增**  `perms=store:storePayment:add`
+    - └─ [按钮] **修改**  `perms=store:storePayment:edit`
+    - └─ [按钮] **导出**  `perms=store:storePayment:export`
+    - └─ [按钮] **paynotify**  `perms=store:storePayment:payNotify`
+    - └─ [按钮] **查询**  `perms=store:storePayment:query`
+    - └─ [按钮] **按钮**  `perms=store:storePayment:refund`
+    - └─ [按钮] **删除**  `perms=store:storePayment:remove`
+  - [菜单] **商城管理-商城商品**  `id=29657` path=`storeProduct3` component=`store/storeProduct/index` 显示
+    - └─ [按钮] **新增**  `perms=store:storeProduct:add`
+    - └─ [按钮] **bulkcopy**  `perms=store:storeProduct:bulkCopy`
+    - └─ [按钮] **商城商品复制**  `perms=store:storeProduct:copy`
+    - └─ [按钮] **导出**  `perms=store:storeProduct:export`
+    - └─ [按钮] **导入**  `perms=store:storeProduct:import`
+    - └─ [按钮] **查询**  `perms=store:storeProduct:query`
+    - └─ [按钮] **删除**  `perms=store:storeProduct:remove`
+  - [菜单] **商城管理-用户在线状态**  `id=29671` path=`userOnlineState2` component=`store/userOnlineState/index` 显示
+    - └─ [按钮] **新增**  `perms=store:userOnlineState:add`
+    - └─ [按钮] **修改**  `perms=store:userOnlineState:edit`
+    - └─ [按钮] **导出**  `perms=store:userOnlineState:export`
+    - └─ [按钮] **查询**  `perms=store:userOnlineState:query`
+    - └─ [按钮] **删除**  `perms=store:userOnlineState:remove`
+  - [菜单] **系统管理-审批管理**  `id=29674` path=`approval` component=`system/approval/index` 显示
+    - └─ [按钮] **新增**  `perms=system:approval:add`
+    - └─ [按钮] **修改**  `perms=system:approval:edit`
+    - └─ [按钮] **导出**  `perms=system:approval:export`
+    - └─ [按钮] **查询**  `perms=system:approval:query`
+    - └─ [按钮] **删除**  `perms=system:approval:remove`
+  - [菜单] **系统管理-参数配置**  `id=29678` path=`config2` component=`system/config/index` 显示
+    - └─ [按钮] **新增**  `perms=system:config:add`
+    - └─ [按钮] **修改**  `perms=system:config:edit`
+    - └─ [按钮] **导出**  `perms=system:config:export`
+    - └─ [按钮] **查询**  `perms=system:config:query`
+    - └─ [按钮] **删除**  `perms=system:config:remove`
+  - [菜单] **系统管理-部门管理**  `id=29680` path=`dept` component=`system/dept/index` 显示
+    - └─ [按钮] **新增**  `perms=system:dept:add`
+    - └─ [按钮] **修改**  `perms=system:dept:edit`
+    - └─ [按钮] **查询**  `perms=system:dept:query`
+    - └─ [按钮] **删除**  `perms=system:dept:remove`
+  - [菜单] **系统管理-字典管理**  `id=29681` path=`dict` component=`system/dict/index` 显示
+    - └─ [按钮] **新增**  `perms=system:dict:add`
+    - └─ [按钮] **修改**  `perms=system:dict:edit`
+    - └─ [按钮] **导出**  `perms=system:dict:export`
+    - └─ [按钮] **查询**  `perms=system:dict:query`
+    - └─ [按钮] **删除**  `perms=system:dict:remove`
+  - [菜单] **系统管理-关键词管理**  `id=29682` path=`keyword` component=`system/keyword/index` 显示
+    - └─ [按钮] **新增**  `perms=system:keyword:add`
+    - └─ [按钮] **修改**  `perms=system:keyword:edit`
+    - └─ [按钮] **导出**  `perms=system:keyword:export`
+    - └─ [按钮] **查询**  `perms=system:keyword:query`
+    - └─ [按钮] **删除**  `perms=system:keyword:remove`
+  - [菜单] **系统管理-菜单管理**  `id=29683` path=`menu2` component=`system/menu/index` 显示
+    - └─ [按钮] **新增**  `perms=system:menu:add`
+    - └─ [按钮] **修改**  `perms=system:menu:edit`
+    - └─ [按钮] **查询**  `perms=system:menu:query`
+    - └─ [按钮] **删除**  `perms=system:menu:remove`
+  - [菜单] **系统管理-通知公告**  `id=29684` path=`notice` component=`system/notice/index` 显示
+    - └─ [按钮] **新增**  `perms=system:notice:add`
+    - └─ [按钮] **修改**  `perms=system:notice:edit`
+    - └─ [按钮] **查询**  `perms=system:notice:query`
+    - └─ [按钮] **删除**  `perms=system:notice:remove`
+  - [菜单] **系统管理-岗位管理**  `id=29685` path=`post` component=`system/post/index` 显示
+    - └─ [按钮] **新增**  `perms=system:post:add`
+    - └─ [按钮] **修改**  `perms=system:post:edit`
+    - └─ [按钮] **导出**  `perms=system:post:export`
+    - └─ [按钮] **查询**  `perms=system:post:query`
+    - └─ [按钮] **删除**  `perms=system:post:remove`
+  - [菜单] **系统管理-角色管理**  `id=29686` path=`role2` component=`system/role/index` 显示
+    - └─ [按钮] **新增**  `perms=system:role:add`
+    - └─ [按钮] **修改**  `perms=system:role:edit`
+    - └─ [按钮] **导出**  `perms=system:role:export`
+    - └─ [按钮] **查询**  `perms=system:role:query`
+    - └─ [按钮] **删除**  `perms=system:role:remove`
+  - [菜单] **系统管理-用户管理**  `id=29688` path=`user3` component=`system/user/index` 显示
+    - └─ [按钮] **新增**  `perms=system:user:add`
+    - └─ [按钮] **修改**  `perms=system:user:edit`
+    - └─ [按钮] **导出**  `perms=system:user:export`
+    - └─ [按钮] **导入**  `perms=system:user:import`
+    - └─ [按钮] **查询**  `perms=system:user:query`
+    - └─ [按钮] **删除**  `perms=system:user:remove`
+    - └─ [按钮] **重置密码**  `perms=system:user:resetPwd`
+  - [菜单] **租户管理-操作记录**  `id=29690` path=`record2` component=`tenant/record/index` 显示
+    - └─ [按钮] **新增**  `perms=tenant:record:add`
+    - └─ [按钮] **修改**  `perms=tenant:record:edit`
+    - └─ [按钮] **导出**  `perms=tenant:record:export`
+    - └─ [按钮] **查询**  `perms=tenant:record:query`
+    - └─ [按钮] **删除**  `perms=tenant:record:remove`
+  - [菜单] **用户管理-投诉管理**  `id=29694` path=`complaint2` component=`user/complaint/index` 显示
+    - └─ [按钮] **新增**  `perms=user:complaint:add`
+    - └─ [按钮] **修改**  `perms=user:complaint:edit`
+    - └─ [按钮] **导出**  `perms=user:complaint:export`
+    - └─ [按钮] **查询**  `perms=user:complaint:query`
+    - └─ [按钮] **删除**  `perms=user:complaint:remove`
+
+### 18. 首页
+
+- [菜单] **首页**  `id=32644` path=`index` component=`index` 隐藏
+
+### 19. 平台管理(归档)
+
+- [目录] **平台管理(归档)**  `id=32333` path=`admin` component=`-` 隐藏
+
+### 20. workflow:lobster:list
+
+- [菜单] **workflow:lobster:list**  `id=32323` path=`#` component=`-` 隐藏
+
+### 21. 孤立菜单(parent_id 在库中不存在)
+
+> 共 **877** 条,按原 parent_id 分组展示。建议后续数据清理时修复 parent_id 或删除废弃节点。
+
+#### parent_id = 2000(无效)
+
+- └─ [按钮] **按钮**  `perms=workflow:lobster:start`
+- └─ [按钮] **按钮**  `perms=workflow:lobster:exec`
+- └─ [按钮] **按钮**  `perms=workflow:lobster:pause`
+- └─ [按钮] **按钮**  `perms=workflow:lobster:resume`
+- └─ [按钮] **按钮**  `perms=workflow:lobster:terminate`
+- └─ [按钮] **龙虸查询**  `perms=workflow:lobster:query`
+
+#### parent_id = 29189(无效)
+
+- └─ [按钮] **课程审核**  `perms=admin:course:audit`
+- └─ [按钮] **查询**  `perms=admin:course:query`
+- └─ [按钮] **删除**  `perms=admin:course:remove`
+
+#### parent_id = 29190(无效)
+
+- └─ [按钮] **直播审核**  `perms=admin:live:audit`
+- └─ [按钮] **查询**  `perms=admin:live:query`
+- └─ [按钮] **删除**  `perms=admin:live:remove`
+
+#### parent_id = 29216(无效)
+
+- └─ [按钮] **新增**  `perms=FastGptExtUserTag:FastGptExtUserTag:add`
+- └─ [按钮] **修改**  `perms=FastGptExtUserTag:FastGptExtUserTag:edit`
+- └─ [按钮] **导出**  `perms=FastGptExtUserTag:FastGptExtUserTag:export`
+- └─ [按钮] **查询**  `perms=FastGptExtUserTag:FastGptExtUserTag:query`
+- └─ [按钮] **删除**  `perms=FastGptExtUserTag:FastGptExtUserTag:remove`
+
+#### parent_id = 29221(无效)
+
+- └─ [按钮] **新增**  `perms=ad:adDomain:add`
+- └─ [按钮] **修改**  `perms=ad:adDomain:edit`
+- └─ [按钮] **导出**  `perms=ad:adDomain:export`
+- └─ [按钮] **查询**  `perms=ad:adDomain:query`
+- └─ [按钮] **删除**  `perms=ad:adDomain:remove`
+
+#### parent_id = 29222(无效)
+
+- └─ [按钮] **新增**  `perms=ad:adDyApi:add`
+- └─ [按钮] **修改**  `perms=ad:adDyApi:edit`
+- └─ [按钮] **导出**  `perms=ad:adDyApi:export`
+- └─ [按钮] **查询**  `perms=ad:adDyApi:query`
+- └─ [按钮] **删除**  `perms=ad:adDyApi:remove`
+
+#### parent_id = 29224(无效)
+
+- └─ [按钮] **新增**  `perms=ad:clickLog:add`
+- └─ [按钮] **修改**  `perms=ad:clickLog:edit`
+- └─ [按钮] **导出**  `perms=ad:clickLog:export`
+- └─ [按钮] **查询**  `perms=ad:clickLog:query`
+- └─ [按钮] **删除**  `perms=ad:clickLog:remove`
+
+#### parent_id = 29226(无效)
+
+- └─ [按钮] **change列表**  `perms=admin:companyUser:changeList`
+- └─ [按钮] **修改**  `perms=admin:companyUser:edit`
+- └─ [按钮] **查询**  `perms=admin:companyUser:query`
+
+#### parent_id = 29233(无效)
+
+- └─ [按钮] **新增**  `perms=bill:billLog:add`
+- └─ [按钮] **修改**  `perms=bill:billLog:edit`
+- └─ [按钮] **导出**  `perms=bill:billLog:export`
+- └─ [按钮] **查询**  `perms=bill:billLog:query`
+- └─ [按钮] **删除**  `perms=bill:billLog:remove`
+
+#### parent_id = 29238(无效)
+
+- └─ [按钮] **新增**  `perms=chat:chatMsgLogs:add`
+- └─ [按钮] **修改**  `perms=chat:chatMsgLogs:edit`
+- └─ [按钮] **导出**  `perms=chat:chatMsgLogs:export`
+- └─ [按钮] **查询**  `perms=chat:chatMsgLogs:query`
+- └─ [按钮] **删除**  `perms=chat:chatMsgLogs:remove`
+
+#### parent_id = 29305(无效)
+
+- └─ [按钮] **新增**  `perms=company:user:add`
+- └─ [按钮] **add码url**  `perms=company:user:addCodeUrl`
+- └─ [按钮] **allowedallregister**  `perms=company:user:allowedAllRegister`
+- └─ [按钮] **修改**  `perms=company:user:edit`
+- └─ [按钮] **导出**  `perms=company:user:export`
+- └─ [按钮] **导入**  `perms=company:user:import`
+- └─ [按钮] **查询**  `perms=company:user:query`
+- └─ [按钮] **删除**  `perms=company:user:remove`
+- └─ [按钮] **setregister**  `perms=company:user:setRegister`
+- └─ [按钮] **update企业用户area列表**  `perms=company:user:updateCompanyUserAreaList`
+
+#### parent_id = 29309(无效)
+
+- └─ [按钮] **新增**  `perms=course:courseAnswerLog:add`
+- └─ [按钮] **修改**  `perms=course:courseAnswerLog:edit`
+- └─ [按钮] **导出**  `perms=course:courseAnswerLog:export`
+- └─ [按钮] **查询**  `perms=course:courseAnswerLog:query`
+- └─ [按钮] **删除**  `perms=course:courseAnswerLog:remove`
+
+#### parent_id = 29310(无效)
+
+- └─ [按钮] **新增**  `perms=course:courseDomainName:add`
+- └─ [按钮] **修改**  `perms=course:courseDomainName:edit`
+- └─ [按钮] **导出**  `perms=course:courseDomainName:export`
+- └─ [按钮] **查询**  `perms=course:courseDomainName:query`
+- └─ [按钮] **删除**  `perms=course:courseDomainName:remove`
+
+#### parent_id = 29314(无效)
+
+- └─ [按钮] **新增**  `perms=course:courseQuestionCategory:add`
+- └─ [按钮] **修改**  `perms=course:courseQuestionCategory:edit`
+- └─ [按钮] **导出**  `perms=course:courseQuestionCategory:export`
+- └─ [按钮] **查询**  `perms=course:courseQuestionCategory:query`
+- └─ [按钮] **删除**  `perms=course:courseQuestionCategory:remove`
+
+#### parent_id = 29320(无效)
+
+- └─ [按钮] **新增**  `perms=course:period:add`
+- └─ [按钮] **add课程**  `perms=course:period:addCourse`
+- └─ [按钮] **按钮**  `perms=course:period:close`
+- └─ [按钮] **课程move**  `perms=course:period:courseMove`
+- └─ [按钮] **dayremove**  `perms=course:period:dayRemove`
+- └─ [按钮] **修改**  `perms=course:period:edit`
+- └─ [按钮] **导出**  `perms=course:period:export`
+- └─ [按钮] **查询**  `perms=course:period:query`
+- └─ [按钮] **删除**  `perms=course:period:remove`
+- └─ [按钮] **set企业redpacket**  `perms=course:period:setCompanyRedPacket`
+- └─ [按钮] **set课程redpacket**  `perms=course:period:setCourseRedPacket`
+- └─ [按钮] **setredpacket**  `perms=course:period:setRedPacket`
+- └─ [按钮] **update课程time**  `perms=course:period:updateCourseTime`
+
+#### parent_id = 29321(无效)
+
+- └─ [按钮] **新增**  `perms=course:playSourceConfig:add`
+- └─ [按钮] **按钮**  `perms=course:playSourceConfig:agreement`
+- └─ [按钮] **playsource配置绑定**  `perms=course:playSourceConfig:bind`
+- └─ [按钮] **修改**  `perms=course:playSourceConfig:edit`
+- └─ [按钮] **查询**  `perms=course:playSourceConfig:query`
+- └─ [按钮] **删除**  `perms=course:playSourceConfig:remove`
+- └─ [按钮] **playsource配置解绑**  `perms=course:playSourceConfig:unbind`
+
+#### parent_id = 29323(无效)
+
+- └─ [按钮] **新增**  `perms=course:sop:add`
+- └─ [按钮] **修改**  `perms=course:sop:edit`
+- └─ [按钮] **导出**  `perms=course:sop:export`
+- └─ [按钮] **查询**  `perms=course:sop:query`
+- └─ [按钮] **删除**  `perms=course:sop:remove`
+
+#### parent_id = 29324(无效)
+
+- └─ [按钮] **新增**  `perms=course:sopLogs:add`
+- └─ [按钮] **修改**  `perms=course:sopLogs:edit`
+- └─ [按钮] **导出**  `perms=course:sopLogs:export`
+- └─ [按钮] **查询**  `perms=course:sopLogs:query`
+- └─ [按钮] **删除**  `perms=course:sopLogs:remove`
+
+#### parent_id = 29326(无效)
+
+- └─ [按钮] **新增**  `perms=course:trainingCamp:add`
+- └─ [按钮] **training营复制**  `perms=course:trainingCamp:copy`
+- └─ [按钮] **修改**  `perms=course:trainingCamp:edit`
+- └─ [按钮] **删除**  `perms=course:trainingCamp:remove`
+
+#### parent_id = 29330(无效)
+
+- └─ [按钮] **新增**  `perms=course:userCourseCommentLike:add`
+- └─ [按钮] **修改**  `perms=course:userCourseCommentLike:edit`
+- └─ [按钮] **导出**  `perms=course:userCourseCommentLike:export`
+- └─ [按钮] **查询**  `perms=course:userCourseCommentLike:query`
+- └─ [按钮] **删除**  `perms=course:userCourseCommentLike:remove`
+
+#### parent_id = 29333(无效)
+
+- └─ [按钮] **新增**  `perms=course:userCourseFavorite:add`
+- └─ [按钮] **修改**  `perms=course:userCourseFavorite:edit`
+- └─ [按钮] **导出**  `perms=course:userCourseFavorite:export`
+- └─ [按钮] **查询**  `perms=course:userCourseFavorite:query`
+- └─ [按钮] **删除**  `perms=course:userCourseFavorite:remove`
+
+#### parent_id = 29335(无效)
+
+- └─ [按钮] **新增**  `perms=course:userCourseNoteLike:add`
+- └─ [按钮] **修改**  `perms=course:userCourseNoteLike:edit`
+- └─ [按钮] **导出**  `perms=course:userCourseNoteLike:export`
+- └─ [按钮] **查询**  `perms=course:userCourseNoteLike:query`
+- └─ [按钮] **删除**  `perms=course:userCourseNoteLike:remove`
+
+#### parent_id = 29339(无效)
+
+- └─ [按钮] **新增**  `perms=course:userCourseVideo:add`
+- └─ [按钮] **batchdown**  `perms=course:userCourseVideo:batchDown`
+- └─ [按钮] **batcheditcover**  `perms=course:userCourseVideo:batchEditCover`
+- └─ [按钮] **修改**  `perms=course:userCourseVideo:edit`
+- └─ [按钮] **导出**  `perms=course:userCourseVideo:export`
+- └─ [按钮] **查询**  `perms=course:userCourseVideo:query`
+- └─ [按钮] **删除**  `perms=course:userCourseVideo:remove`
+- └─ [按钮] **用户课程视频同步**  `perms=course:userCourseVideo:sync`
+
+#### parent_id = 29341(无效)
+
+- └─ [按钮] **新增**  `perms=course:userTalentFollow:add`
+- └─ [按钮] **修改**  `perms=course:userTalentFollow:edit`
+- └─ [按钮] **导出**  `perms=course:userTalentFollow:export`
+- └─ [按钮] **查询**  `perms=course:userTalentFollow:query`
+- └─ [按钮] **删除**  `perms=course:userTalentFollow:remove`
+
+#### parent_id = 29344(无效)
+
+- └─ [按钮] **新增**  `perms=course:userVideoCommentLike:add`
+- └─ [按钮] **修改**  `perms=course:userVideoCommentLike:edit`
+- └─ [按钮] **导出**  `perms=course:userVideoCommentLike:export`
+- └─ [按钮] **查询**  `perms=course:userVideoCommentLike:query`
+- └─ [按钮] **删除**  `perms=course:userVideoCommentLike:remove`
+
+#### parent_id = 29345(无效)
+
+- └─ [按钮] **新增**  `perms=course:userVideoFavorite:add`
+- └─ [按钮] **修改**  `perms=course:userVideoFavorite:edit`
+- └─ [按钮] **导出**  `perms=course:userVideoFavorite:export`
+- └─ [按钮] **查询**  `perms=course:userVideoFavorite:query`
+- └─ [按钮] **删除**  `perms=course:userVideoFavorite:remove`
+
+#### parent_id = 29346(无效)
+
+- └─ [按钮] **新增**  `perms=course:userVideoLike:add`
+- └─ [按钮] **修改**  `perms=course:userVideoLike:edit`
+- └─ [按钮] **导出**  `perms=course:userVideoLike:export`
+- └─ [按钮] **查询**  `perms=course:userVideoLike:query`
+- └─ [按钮] **删除**  `perms=course:userVideoLike:remove`
+
+#### parent_id = 29347(无效)
+
+- └─ [按钮] **新增**  `perms=course:userVideoView:add`
+- └─ [按钮] **修改**  `perms=course:userVideoView:edit`
+- └─ [按钮] **导出**  `perms=course:userVideoView:export`
+- └─ [按钮] **查询**  `perms=course:userVideoView:query`
+- └─ [按钮] **删除**  `perms=course:userVideoView:remove`
+
+#### parent_id = 29349(无效)
+
+- └─ [按钮] **新增**  `perms=course:userVipPackage:add`
+- └─ [按钮] **修改**  `perms=course:userVipPackage:edit`
+- └─ [按钮] **导出**  `perms=course:userVipPackage:export`
+- └─ [按钮] **查询**  `perms=course:userVipPackage:query`
+- └─ [按钮] **删除**  `perms=course:userVipPackage:remove`
+
+#### parent_id = 29353(无效)
+
+- └─ [按钮] **新增**  `perms=course:videoTags:add`
+- └─ [按钮] **修改**  `perms=course:videoTags:edit`
+- └─ [按钮] **导出**  `perms=course:videoTags:export`
+- └─ [按钮] **查询**  `perms=course:videoTags:query`
+- └─ [按钮] **删除**  `perms=course:videoTags:remove`
+
+#### parent_id = 29354(无效)
+
+- └─ [按钮] **新增**  `perms=courseFinishTemp:course:add`
+- └─ [按钮] **修改**  `perms=courseFinishTemp:course:edit`
+- └─ [按钮] **导出**  `perms=courseFinishTemp:course:export`
+- └─ [按钮] **查询**  `perms=courseFinishTemp:course:query`
+- └─ [按钮] **删除**  `perms=courseFinishTemp:course:remove`
+
+#### parent_id = 29356(无效)
+
+- └─ [按钮] **客户分配取消**  `perms=crm:customerAssign:cancel`
+- └─ [按钮] **导出**  `perms=crm:customerAssign:export`
+- └─ [按钮] **查询**  `perms=crm:customerAssign:query`
+
+#### parent_id = 29357(无效)
+
+- └─ [按钮] **导出**  `perms=crm:customerContacts:export`
+
+#### parent_id = 29358(无效)
+
+- └─ [按钮] **新增**  `perms=crm:customerLevel:add`
+- └─ [按钮] **客户level删除**  `perms=crm:customerLevel:delete`
+- └─ [按钮] **修改**  `perms=crm:customerLevel:edit`
+- └─ [按钮] **查询**  `perms=crm:customerLevel:query`
+
+#### parent_id = 29370(无效)
+
+- └─ [按钮] **新增**  `perms=fastGpt:fastGptChatReplaceText:add`
+- └─ [按钮] **修改**  `perms=fastGpt:fastGptChatReplaceText:edit`
+- └─ [按钮] **导出**  `perms=fastGpt:fastGptChatReplaceText:export`
+- └─ [按钮] **查询**  `perms=fastGpt:fastGptChatReplaceText:query`
+- └─ [按钮] **删除**  `perms=fastGpt:fastGptChatReplaceText:remove`
+
+#### parent_id = 29383(无效)
+
+- └─ [按钮] **平台列表**  `perms=fee:billing:admin:list`
+- └─ [按钮] **租户列表**  `perms=fee:billing:tenant:list`
+
+#### parent_id = 29384(无效)
+
+- └─ [按钮] **新增**  `perms=his:FsFollowReport:add`
+- └─ [按钮] **修改**  `perms=his:FsFollowReport:edit`
+- └─ [按钮] **导出**  `perms=his:FsFollowReport:export`
+- └─ [按钮] **查询**  `perms=his:FsFollowReport:query`
+- └─ [按钮] **删除**  `perms=his:FsFollowReport:remove`
+
+#### parent_id = 29391(无效)
+
+- └─ [按钮] **新增**  `perms=his:city:add`
+- └─ [按钮] **修改**  `perms=his:city:edit`
+- └─ [按钮] **导出**  `perms=his:city:export`
+- └─ [按钮] **查询**  `perms=his:city:query`
+- └─ [按钮] **删除**  `perms=his:city:remove`
+
+#### parent_id = 29396(无效)
+
+- └─ [按钮] **查询**  `perms=his:companyDivConfig:query`
+- └─ [按钮] **按钮**  `perms=his:companyDivConfig:set`
+
+#### parent_id = 29401(无效)
+
+- └─ [按钮] **新增**  `perms=his:dfAccount:add`
+- └─ [按钮] **修改**  `perms=his:dfAccount:edit`
+- └─ [按钮] **导出**  `perms=his:dfAccount:export`
+- └─ [按钮] **查询**  `perms=his:dfAccount:query`
+- └─ [按钮] **删除**  `perms=his:dfAccount:remove`
+
+#### parent_id = 29404(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctor:add`
+- └─ [按钮] **医生审核**  `perms=his:doctor:audit`
+- └─ [按钮] **修改**  `perms=his:doctor:edit`
+- └─ [按钮] **edit随访**  `perms=his:doctor:editFollow`
+- └─ [按钮] **导出**  `perms=his:doctor:export`
+- └─ [按钮] **问诊**  `perms=his:doctor:inquiry`
+- └─ [按钮] **删除**  `perms=his:doctor:remove`
+- └─ [按钮] **按钮**  `perms=his:doctor:resetpwd`
+
+#### parent_id = 29406(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctorBill:add`
+- └─ [按钮] **修改**  `perms=his:doctorBill:edit`
+- └─ [按钮] **导出**  `perms=his:doctorBill:export`
+- └─ [按钮] **查询**  `perms=his:doctorBill:query`
+- └─ [按钮] **删除**  `perms=his:doctorBill:remove`
+
+#### parent_id = 29407(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctorExtract:add`
+- └─ [按钮] **修改**  `perms=his:doctorExtract:edit`
+- └─ [按钮] **导出**  `perms=his:doctorExtract:export`
+- └─ [按钮] **查询**  `perms=his:doctorExtract:query`
+- └─ [按钮] **删除**  `perms=his:doctorExtract:remove`
+
+#### parent_id = 29408(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctorOperLog:add`
+- └─ [按钮] **修改**  `perms=his:doctorOperLog:edit`
+- └─ [按钮] **导出**  `perms=his:doctorOperLog:export`
+- └─ [按钮] **查询**  `perms=his:doctorOperLog:query`
+- └─ [按钮] **删除**  `perms=his:doctorOperLog:remove`
+
+#### parent_id = 29409(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctorPrescribe:add`
+- └─ [按钮] **修改**  `perms=his:doctorPrescribe:edit`
+- └─ [按钮] **导出**  `perms=his:doctorPrescribe:export`
+- └─ [按钮] **查询**  `perms=his:doctorPrescribe:query`
+- └─ [按钮] **删除**  `perms=his:doctorPrescribe:remove`
+
+#### parent_id = 29410(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctorPrescribeDrug:add`
+- └─ [按钮] **修改**  `perms=his:doctorPrescribeDrug:edit`
+- └─ [按钮] **导出**  `perms=his:doctorPrescribeDrug:export`
+- └─ [按钮] **查询**  `perms=his:doctorPrescribeDrug:query`
+- └─ [按钮] **删除**  `perms=his:doctorPrescribeDrug:remove`
+
+#### parent_id = 29411(无效)
+
+- └─ [按钮] **新增**  `perms=his:doctorProduct:add`
+- └─ [按钮] **修改**  `perms=his:doctorProduct:edit`
+- └─ [按钮] **导出**  `perms=his:doctorProduct:export`
+- └─ [按钮] **查询**  `perms=his:doctorProduct:query`
+- └─ [按钮] **删除**  `perms=his:doctorProduct:remove`
+
+#### parent_id = 29420(无效)
+
+- └─ [按钮] **新增**  `perms=his:healthArticle:add`
+- └─ [按钮] **修改**  `perms=his:healthArticle:edit`
+- └─ [按钮] **导出**  `perms=his:healthArticle:export`
+- └─ [按钮] **查询**  `perms=his:healthArticle:query`
+- └─ [按钮] **删除**  `perms=his:healthArticle:remove`
+
+#### parent_id = 29421(无效)
+
+- └─ [按钮] **新增**  `perms=his:healthData:add`
+- └─ [按钮] **修改**  `perms=his:healthData:edit`
+- └─ [按钮] **导出**  `perms=his:healthData:export`
+- └─ [按钮] **查询**  `perms=his:healthData:query`
+- └─ [按钮] **删除**  `perms=his:healthData:remove`
+
+#### parent_id = 29423(无效)
+
+- └─ [按钮] **新增**  `perms=his:healthLife:add`
+- └─ [按钮] **修改**  `perms=his:healthLife:edit`
+- └─ [按钮] **导出**  `perms=his:healthLife:export`
+- └─ [按钮] **删除**  `perms=his:healthLife:remove`
+
+#### parent_id = 29425(无效)
+
+- └─ [按钮] **新增**  `perms=his:healthTongue:add`
+- └─ [按钮] **修改**  `perms=his:healthTongue:edit`
+- └─ [按钮] **导出**  `perms=his:healthTongue:export`
+- └─ [按钮] **查询**  `perms=his:healthTongue:query`
+- └─ [按钮] **删除**  `perms=his:healthTongue:remove`
+
+#### parent_id = 29431(无效)
+
+- └─ [按钮] **新增**  `perms=his:inquiryOrder:add`
+- └─ [按钮] **修改**  `perms=his:inquiryOrder:edit`
+- └─ [按钮] **editstatus**  `perms=his:inquiryOrder:editStatus`
+- └─ [按钮] **导出**  `perms=his:inquiryOrder:export`
+- └─ [按钮] **messagefeedback导出**  `perms=his:inquiryOrder:messageFeedbackExport`
+- └─ [按钮] **查询**  `perms=his:inquiryOrder:query`
+- └─ [按钮] **refund订单**  `perms=his:inquiryOrder:refundOrder`
+- └─ [按钮] **删除**  `perms=his:inquiryOrder:remove`
+- └─ [按钮] **send消息**  `perms=his:inquiryOrder:sendMsg`
+
+#### parent_id = 29434(无效)
+
+- └─ [按钮] **新增**  `perms=his:inquiryPatientInfo:add`
+- └─ [按钮] **修改**  `perms=his:inquiryPatientInfo:edit`
+
+#### parent_id = 29438(无效)
+
+- └─ [按钮] **新增**  `perms=his:logs:add`
+- └─ [按钮] **修改**  `perms=his:logs:edit`
+- └─ [按钮] **导出**  `perms=his:logs:export`
+- └─ [按钮] **查询**  `perms=his:logs:query`
+- └─ [按钮] **删除**  `perms=his:logs:remove`
+
+#### parent_id = 29441(无效)
+
+- └─ [按钮] **新增**  `perms=his:package:add`
+- └─ [按钮] **bulkcopy**  `perms=his:package:bulkCopy`
+- └─ [按钮] **修改**  `perms=his:package:edit`
+- └─ [按钮] **导出**  `perms=his:package:export`
+- └─ [按钮] **查询**  `perms=his:package:query`
+- └─ [按钮] **删除**  `perms=his:package:remove`
+
+#### parent_id = 29442(无效)
+
+- └─ [按钮] **新增**  `perms=his:packageCate:add`
+- └─ [按钮] **修改**  `perms=his:packageCate:edit`
+- └─ [按钮] **导出**  `perms=his:packageCate:export`
+- └─ [按钮] **查询**  `perms=his:packageCate:query`
+- └─ [按钮] **删除**  `perms=his:packageCate:remove`
+
+#### parent_id = 29443(无效)
+
+- └─ [按钮] **新增**  `perms=his:packageFavorite:add`
+- └─ [按钮] **修改**  `perms=his:packageFavorite:edit`
+- └─ [按钮] **导出**  `perms=his:packageFavorite:export`
+- └─ [按钮] **查询**  `perms=his:packageFavorite:query`
+- └─ [按钮] **删除**  `perms=his:packageFavorite:remove`
+
+#### parent_id = 29444(无效)
+
+- └─ [按钮] **新增**  `perms=his:packageOrder:add`
+- └─ [按钮] **修改**  `perms=his:packageOrder:edit`
+- └─ [按钮] **导出**  `perms=his:packageOrder:export`
+- └─ [按钮] **问诊refund**  `perms=his:packageOrder:inquiryRefund`
+- └─ [按钮] **商品refund**  `perms=his:packageOrder:productRefund`
+- └─ [按钮] **查询**  `perms=his:packageOrder:query`
+- └─ [按钮] **queryphone**  `perms=his:packageOrder:queryPhone`
+- └─ [按钮] **按钮**  `perms=his:packageOrder:refund`
+- └─ [按钮] **删除**  `perms=his:packageOrder:remove`
+
+#### parent_id = 29445(无效)
+
+- └─ [按钮] **新增**  `perms=his:packageSolarTerm:add`
+- └─ [按钮] **修改**  `perms=his:packageSolarTerm:edit`
+- └─ [按钮] **查询**  `perms=his:packageSolarTerm:query`
+- └─ [按钮] **删除**  `perms=his:packageSolarTerm:remove`
+
+#### parent_id = 29447(无效)
+
+- └─ [按钮] **新增**  `perms=his:pharmacist:add`
+- └─ [按钮] **审核**  `perms=his:pharmacist:audit`
+- └─ [按钮] **修改**  `perms=his:pharmacist:edit`
+- └─ [按钮] **edit随访**  `perms=his:pharmacist:editFollow`
+- └─ [按钮] **导出**  `perms=his:pharmacist:export`
+- └─ [按钮] **问诊**  `perms=his:pharmacist:inquiry`
+- └─ [按钮] **删除**  `perms=his:pharmacist:remove`
+- └─ [按钮] **按钮**  `perms=his:pharmacist:resetpwd`
+
+#### parent_id = 29450(无效)
+
+- └─ [按钮] **新增**  `perms=his:prescribe:add`
+- └─ [按钮] **修改**  `perms=his:prescribe:edit`
+- └─ [按钮] **导出**  `perms=his:prescribe:export`
+- └─ [按钮] **messagefeedback导出**  `perms=his:prescribe:messageFeedbackExport`
+- └─ [按钮] **queryidcard**  `perms=his:prescribe:queryIdCard`
+- └─ [按钮] **删除**  `perms=his:prescribe:remove`
+
+#### parent_id = 29451(无效)
+
+- └─ [按钮] **新增**  `perms=his:price:add`
+- └─ [按钮] **修改**  `perms=his:price:edit`
+- └─ [按钮] **导出**  `perms=his:price:export`
+- └─ [按钮] **查询**  `perms=his:price:query`
+- └─ [按钮] **删除**  `perms=his:price:remove`
+
+#### parent_id = 29452(无效)
+
+- └─ [按钮] **查询**  `perms=his:product:query`
+
+#### parent_id = 29453(无效)
+
+- └─ [按钮] **新增**  `perms=his:promotionActive:add`
+- └─ [按钮] **修改**  `perms=his:promotionActive:edit`
+- └─ [按钮] **删除**  `perms=his:promotionActive:remove`
+
+#### parent_id = 29458(无效)
+
+- └─ [按钮] **新增**  `perms=his:storeAfterSales:add`
+- └─ [按钮] **商城aftersales审核**  `perms=his:storeAfterSales:audit`
+- └─ [按钮] **按钮**  `perms=his:storeAfterSales:depot`
+- └─ [按钮] **修改**  `perms=his:storeAfterSales:edit`
+- └─ [按钮] **导出**  `perms=his:storeAfterSales:export`
+- └─ [按钮] **按钮**  `perms=his:storeAfterSales:finance`
+- └─ [按钮] **查询**  `perms=his:storeAfterSales:query`
+- └─ [按钮] **删除**  `perms=his:storeAfterSales:remove`
+- └─ [按钮] **按钮**  `perms=his:storeAfterSales:revoke`
+
+#### parent_id = 29459(无效)
+
+- └─ [按钮] **新增**  `perms=his:storeBill:add`
+- └─ [按钮] **修改**  `perms=his:storeBill:edit`
+- └─ [按钮] **导出**  `perms=his:storeBill:export`
+- └─ [按钮] **查询**  `perms=his:storeBill:query`
+- └─ [按钮] **删除**  `perms=his:storeBill:remove`
+
+#### parent_id = 29460(无效)
+
+- └─ [按钮] **新增**  `perms=his:storeExtract:add`
+- └─ [按钮] **修改**  `perms=his:storeExtract:edit`
+- └─ [按钮] **导出**  `perms=his:storeExtract:export`
+- └─ [按钮] **查询**  `perms=his:storeExtract:query`
+- └─ [按钮] **删除**  `perms=his:storeExtract:remove`
+
+#### parent_id = 29461(无效)
+
+- └─ [按钮] **导出**  `perms=his:storeLog:export`
+
+#### parent_id = 29462(无效)
+
+- └─ [按钮] **新增**  `perms=his:storeOrder:add`
+- └─ [按钮] **aftersales**  `perms=his:storeOrder:afterSales`
+- └─ [按钮] **createerp订单**  `perms=his:storeOrder:createErpOrder`
+- └─ [按钮] **修改**  `perms=his:storeOrder:edit`
+- └─ [按钮] **edit导入**  `perms=his:storeOrder:editImport`
+- └─ [按钮] **edittuimoney**  `perms=his:storeOrder:editTuiMoney`
+- └─ [按钮] **导出**  `perms=his:storeOrder:export`
+- └─ [按钮] **按钮**  `perms=his:storeOrder:express`
+- └─ [按钮] **按钮**  `perms=his:storeOrder:follow`
+- └─ [按钮] **getero订单**  `perms=his:storeOrder:getEroOrder`
+- └─ [按钮] **按钮**  `perms=his:storeOrder:good`
+- └─ [按钮] **消息列表**  `perms=his:storeOrder:msgList`
+- └─ [按钮] **按钮**  `perms=his:storeOrder:price`
+- └─ [按钮] **queryphone**  `perms=his:storeOrder:queryPhone`
+- └─ [按钮] **删除**  `perms=his:storeOrder:remove`
+- └─ [按钮] **returncost**  `perms=his:storeOrder:returnCost`
+- └─ [按钮] **sendgoods**  `perms=his:storeOrder:sendGoods`
+- └─ [按钮] **send诊所goods**  `perms=his:storeOrder:sendHisGoods`
+- └─ [按钮] **send消息**  `perms=his:storeOrder:sendMsg`
+- └─ [按钮] **syncexpress**  `perms=his:storeOrder:syncExpress`
+- └─ [按钮] **updatedelivery**  `perms=his:storeOrder:updateDelivery`
+- └─ [按钮] **updateexpress**  `perms=his:storeOrder:updateExpress`
+
+#### parent_id = 29467(无效)
+
+- └─ [按钮] **新增**  `perms=his:template:add`
+- └─ [按钮] **修改**  `perms=his:template:edit`
+- └─ [按钮] **导出**  `perms=his:template:export`
+- └─ [按钮] **查询**  `perms=his:template:query`
+- └─ [按钮] **删除**  `perms=his:template:remove`
+
+#### parent_id = 29471(无效)
+
+- └─ [按钮] **新增**  `perms=his:userAddress:add`
+- └─ [按钮] **修改**  `perms=his:userAddress:edit`
+- └─ [按钮] **导出**  `perms=his:userAddress:export`
+- └─ [按钮] **查询**  `perms=his:userAddress:query`
+- └─ [按钮] **删除**  `perms=his:userAddress:remove`
+
+#### parent_id = 29472(无效)
+
+- └─ [按钮] **新增**  `perms=his:userBill:add`
+- └─ [按钮] **修改**  `perms=his:userBill:edit`
+- └─ [按钮] **导出**  `perms=his:userBill:export`
+- └─ [按钮] **查询**  `perms=his:userBill:query`
+- └─ [按钮] **删除**  `perms=his:userBill:remove`
+
+#### parent_id = 29473(无效)
+
+- └─ [按钮] **删除**  `perms=his:userCompanyUser:remove`
+
+#### parent_id = 29475(无效)
+
+- └─ [按钮] **新增**  `perms=his:userExtract:add`
+- └─ [按钮] **用户extract审核**  `perms=his:userExtract:audit`
+- └─ [按钮] **修改**  `perms=his:userExtract:edit`
+- └─ [按钮] **导出**  `perms=his:userExtract:export`
+- └─ [按钮] **查询**  `perms=his:userExtract:query`
+- └─ [按钮] **删除**  `perms=his:userExtract:remove`
+
+#### parent_id = 29477(无效)
+
+- └─ [按钮] **新增**  `perms=his:userNewTask:add`
+- └─ [按钮] **修改**  `perms=his:userNewTask:edit`
+- └─ [按钮] **导出**  `perms=his:userNewTask:export`
+- └─ [按钮] **查询**  `perms=his:userNewTask:query`
+- └─ [按钮] **删除**  `perms=his:userNewTask:remove`
+
+#### parent_id = 29490(无效)
+
+- └─ [按钮] **导出**  `perms=live:healthLiveOrder:export`
+- └─ [按钮] **导出items**  `perms=live:healthLiveOrder:exportItems`
+
+#### parent_id = 29491(无效)
+
+- └─ [按钮] **新增**  `perms=live:issue:add`
+- └─ [按钮] **修改**  `perms=live:issue:edit`
+- └─ [按钮] **导出**  `perms=live:issue:export`
+- └─ [按钮] **查询**  `perms=live:issue:query`
+- └─ [按钮] **删除**  `perms=live:issue:remove`
+
+#### parent_id = 29492(无效)
+
+- └─ [按钮] **新增**  `perms=live:live:add`
+- └─ [按钮] **修改**  `perms=live:live:edit`
+- └─ [按钮] **导出**  `perms=live:live:export`
+- └─ [按钮] **查询**  `perms=live:live:query`
+- └─ [按钮] **删除**  `perms=live:live:remove`
+
+#### parent_id = 29493(无效)
+
+- └─ [按钮] **新增**  `perms=live:liveAfterSales:add`
+- └─ [按钮] **修改**  `perms=live:liveAfterSales:edit`
+- └─ [按钮] **导出**  `perms=live:liveAfterSales:export`
+- └─ [按钮] **查询**  `perms=live:liveAfterSales:query`
+- └─ [按钮] **删除**  `perms=live:liveAfterSales:remove`
+
+#### parent_id = 29510(无效)
+
+- └─ [按钮] **新增**  `perms=live:liveUserFavorite:add`
+- └─ [按钮] **修改**  `perms=live:liveUserFavorite:edit`
+- └─ [按钮] **导出**  `perms=live:liveUserFavorite:export`
+- └─ [按钮] **查询**  `perms=live:liveUserFavorite:query`
+- └─ [按钮] **删除**  `perms=live:liveUserFavorite:remove`
+
+#### parent_id = 29511(无效)
+
+- └─ [按钮] **新增**  `perms=live:liveUserFollow:add`
+- └─ [按钮] **修改**  `perms=live:liveUserFollow:edit`
+- └─ [按钮] **导出**  `perms=live:liveUserFollow:export`
+- └─ [按钮] **查询**  `perms=live:liveUserFollow:query`
+- └─ [按钮] **删除**  `perms=live:liveUserFollow:remove`
+
+#### parent_id = 29512(无效)
+
+- └─ [按钮] **新增**  `perms=live:liveUserLike:add`
+- └─ [按钮] **修改**  `perms=live:liveUserLike:edit`
+- └─ [按钮] **导出**  `perms=live:liveUserLike:export`
+- └─ [按钮] **查询**  `perms=live:liveUserLike:query`
+- └─ [按钮] **删除**  `perms=live:liveUserLike:remove`
+
+#### parent_id = 29518(无效)
+
+- └─ [按钮] **导出**  `perms=live:order:export`
+- └─ [按钮] **导出all**  `perms=live:order:exportAll`
+- └─ [按钮] **导出other**  `perms=live:order:exportOther`
+- └─ [按钮] **修改**  `perms=live:order:payment:edit`
+- └─ [按钮] **导出**  `perms=live:order:payment:export`
+- └─ [按钮] **查询**  `perms=live:order:payment:query`
+- └─ [按钮] **删除**  `perms=live:order:payment:remove`
+
+#### parent_id = 29519(无效)
+
+- └─ [按钮] **新增**  `perms=live:record:add`
+- └─ [按钮] **修改**  `perms=live:record:edit`
+- └─ [按钮] **导出**  `perms=live:record:export`
+- └─ [按钮] **查询**  `perms=live:record:query`
+- └─ [按钮] **删除**  `perms=live:record:remove`
+
+#### parent_id = 29520(无效)
+
+- └─ [按钮] **导出**  `perms=live:task:export`
+
+#### parent_id = 29521(无效)
+
+- └─ [按钮] **新增**  `perms=live:trafficLog:add`
+- └─ [按钮] **修改**  `perms=live:trafficLog:edit`
+- └─ [按钮] **导出**  `perms=live:trafficLog:export`
+- └─ [按钮] **查询**  `perms=live:trafficLog:query`
+- └─ [按钮] **删除**  `perms=live:trafficLog:remove`
+
+#### parent_id = 29523(无效)
+
+- └─ [按钮] **修改**  `perms=liveData:liveData:edit`
+- └─ [按钮] **导出**  `perms=liveData:liveData:export`
+- └─ [按钮] **查询**  `perms=liveData:liveData:query`
+
+#### parent_id = 29530(无效)
+
+- └─ [按钮] **配置**  `perms=proxy:balance:config`
+- └─ [按钮] **按钮**  `perms=proxy:balance:fee`
+- └─ [按钮] **按钮**  `perms=proxy:balance:purchase`
+- └─ [按钮] **充值**  `perms=proxy:balance:recharge`
+- └─ [按钮] **转移**  `perms=proxy:balance:transfer`
+- └─ [按钮] **查看**  `perms=proxy:balance:view`
+
+#### parent_id = 29531(无效)
+
+- └─ [按钮] **查看**  `perms=proxy:dashboard:view`
+
+#### parent_id = 29532(无效)
+
+- └─ [按钮] **信息查看**  `perms=proxy:info:view`
+
+#### parent_id = 29534(无效)
+
+- └─ [按钮] **查看**  `perms=proxy:performance:view`
+
+#### parent_id = 29535(无效)
+
+- └─ [按钮] **查看**  `perms=proxy:price:view`
+
+#### parent_id = 29536(无效)
+
+- └─ [按钮] **分账查看**  `perms=proxy:profit:view`
+
+#### parent_id = 29543(无效)
+
+- └─ [按钮] **新增**  `perms=qw:QwWorkTaskNew:add`
+- └─ [按钮] **部门列表**  `perms=qw:QwWorkTaskNew:deptList`
+- └─ [按钮] **修改**  `perms=qw:QwWorkTaskNew:edit`
+- └─ [按钮] **导出**  `perms=qw:QwWorkTaskNew:export`
+- └─ [按钮] **查询**  `perms=qw:QwWorkTaskNew:query`
+- └─ [按钮] **删除**  `perms=qw:QwWorkTaskNew:remove`
+
+#### parent_id = 29544(无效)
+
+- └─ [按钮] **新增**  `perms=qw:appContactWay:add`
+- └─ [按钮] **修改**  `perms=qw:appContactWay:edit`
+- └─ [按钮] **导出**  `perms=qw:appContactWay:export`
+- └─ [按钮] **查询**  `perms=qw:appContactWay:query`
+- └─ [按钮] **删除**  `perms=qw:appContactWay:remove`
+
+#### parent_id = 29548(无效)
+
+- └─ [按钮] **bind医生id**  `perms=qw:companyUser:bindDoctorId`
+- └─ [按钮] **unbind医生id**  `perms=qw:companyUser:unBindDoctorId`
+
+#### parent_id = 29559(无效)
+
+- └─ [按钮] **外部联系人转移企业审核审核**  `perms=qw:externalContactTransferCompanyAudit:audit`
+- └─ [按钮] **详情**  `perms=qw:externalContactTransferCompanyAudit:detail`
+
+#### parent_id = 29576(无效)
+
+- └─ [按钮] **新增**  `perms=qw:qwAppContactWayLogs:add`
+- └─ [按钮] **修改**  `perms=qw:qwAppContactWayLogs:edit`
+- └─ [按钮] **导出**  `perms=qw:qwAppContactWayLogs:export`
+- └─ [按钮] **查询**  `perms=qw:qwAppContactWayLogs:query`
+- └─ [按钮] **删除**  `perms=qw:qwAppContactWayLogs:remove`
+
+#### parent_id = 29578(无效)
+
+- └─ [按钮] **新增**  `perms=qw:qwDept:add`
+- └─ [按钮] **修改**  `perms=qw:qwDept:edit`
+- └─ [按钮] **导出**  `perms=qw:qwDept:export`
+- └─ [按钮] **查询**  `perms=qw:qwDept:query`
+- └─ [按钮] **删除**  `perms=qw:qwDept:remove`
+
+#### parent_id = 29584(无效)
+
+- └─ [按钮] **新增**  `perms=qw:qwPushCount:add`
+- └─ [按钮] **修改**  `perms=qw:qwPushCount:edit`
+- └─ [按钮] **导出**  `perms=qw:qwPushCount:export`
+- └─ [按钮] **查询**  `perms=qw:qwPushCount:query`
+- └─ [按钮] **删除**  `perms=qw:qwPushCount:remove`
+
+#### parent_id = 29587(无效)
+
+- └─ [按钮] **新增**  `perms=qw:record:add`
+- └─ [按钮] **修改**  `perms=qw:record:edit`
+- └─ [按钮] **导出**  `perms=qw:record:export`
+- └─ [按钮] **查询**  `perms=qw:record:query`
+- └─ [按钮] **删除**  `perms=qw:record:remove`
+
+#### parent_id = 29588(无效)
+
+- └─ [按钮] **新增**  `perms=qw:sop:add`
+- └─ [按钮] **修改**  `perms=qw:sop:edit`
+- └─ [按钮] **导出**  `perms=qw:sop:export`
+- └─ [按钮] **my列表**  `perms=qw:sop:myList`
+- └─ [按钮] **删除**  `perms=qw:sop:remove`
+
+#### parent_id = 29589(无效)
+
+- └─ [按钮] **新增**  `perms=qw:sopLogs:add`
+- └─ [按钮] **修改**  `perms=qw:sopLogs:edit`
+- └─ [按钮] **导出**  `perms=qw:sopLogs:export`
+- └─ [按钮] **my导出**  `perms=qw:sopLogs:myExport`
+- └─ [按钮] **查询**  `perms=qw:sopLogs:query`
+- └─ [按钮] **删除**  `perms=qw:sopLogs:remove`
+
+#### parent_id = 29590(无效)
+
+- └─ [按钮] **新增**  `perms=qw:sopTemp:add`
+- └─ [按钮] **修改**  `perms=qw:sopTemp:edit`
+- └─ [按钮] **导出**  `perms=qw:sopTemp:export`
+- └─ [按钮] **删除**  `perms=qw:sopTemp:remove`
+- └─ [按钮] **按钮**  `perms=qw:sopTemp:share`
+
+#### parent_id = 29592(无效)
+
+- └─ [按钮] **消息**  `perms=qw:sopUserLogsInfo:msg`
+
+#### parent_id = 29594(无效)
+
+- └─ [按钮] **新增**  `perms=qw:tag:add`
+- └─ [按钮] **修改**  `perms=qw:tag:edit`
+- └─ [按钮] **导出**  `perms=qw:tag:export`
+- └─ [按钮] **查询**  `perms=qw:tag:query`
+- └─ [按钮] **删除**  `perms=qw:tag:remove`
+
+#### parent_id = 29606(无效)
+
+- └─ [按钮] **新增**  `perms=shop:msg:add`
+- └─ [按钮] **修改**  `perms=shop:msg:edit`
+- └─ [按钮] **导出**  `perms=shop:msg:export`
+- └─ [按钮] **查询**  `perms=shop:msg:query`
+- └─ [按钮] **删除**  `perms=shop:msg:remove`
+
+#### parent_id = 29607(无效)
+
+- └─ [按钮] **新增**  `perms=shop:records:add`
+- └─ [按钮] **修改**  `perms=shop:records:edit`
+- └─ [按钮] **导出**  `perms=shop:records:export`
+- └─ [按钮] **查询**  `perms=shop:records:query`
+- └─ [按钮] **删除**  `perms=shop:records:remove`
+
+#### parent_id = 29608(无效)
+
+- └─ [按钮] **新增**  `perms=shop:role:add`
+- └─ [按钮] **修改**  `perms=shop:role:edit`
+- └─ [按钮] **导出**  `perms=shop:role:export`
+- └─ [按钮] **查询**  `perms=shop:role:query`
+- └─ [按钮] **删除**  `perms=shop:role:remove`
+
+#### parent_id = 29609(无效)
+
+- └─ [按钮] **删除**  `perms=shop:session:remove`
+
+#### parent_id = 29611(无效)
+
+- └─ [按钮] **新增**  `perms=shop:task:add`
+- └─ [按钮] **修改**  `perms=shop:task:edit`
+- └─ [按钮] **导出**  `perms=shop:task:export`
+- └─ [按钮] **删除**  `perms=shop:task:remove`
+
+#### parent_id = 29613(无效)
+
+- └─ [按钮] **新增**  `perms=sop:companySopRole:add`
+- └─ [按钮] **修改**  `perms=sop:companySopRole:edit`
+- └─ [按钮] **导出**  `perms=sop:companySopRole:export`
+- └─ [按钮] **查询**  `perms=sop:companySopRole:query`
+- └─ [按钮] **删除**  `perms=sop:companySopRole:remove`
+
+#### parent_id = 29615(无效)
+
+- └─ [按钮] **新增**  `perms=store:adv:add`
+- └─ [按钮] **修改**  `perms=store:adv:edit`
+- └─ [按钮] **导出**  `perms=store:adv:export`
+- └─ [按钮] **查询**  `perms=store:adv:query`
+- └─ [按钮] **删除**  `perms=store:adv:remove`
+
+#### parent_id = 29621(无效)
+
+- └─ [按钮] **导出**  `perms=store:healthStoreOrder:export`
+- └─ [按钮] **导出**  `perms=store:healthStoreOrder:export:details`
+- └─ [按钮] **导出items**  `perms=store:healthStoreOrder:exportItems`
+- └─ [按钮] **导出items**  `perms=store:healthStoreOrder:exportItems:details`
+
+#### parent_id = 29622(无效)
+
+- └─ [按钮] **商城新增**  `perms=store:his:store:add`
+- └─ [按钮] **商城审核**  `perms=store:his:store:audit`
+- └─ [按钮] **商城**  `perms=store:his:store:auditLog`
+- └─ [按钮] **商城修改**  `perms=store:his:store:edit`
+- └─ [按钮] **商城导出**  `perms=store:his:store:export`
+- └─ [按钮] **商城列表**  `perms=store:his:store:list`
+- └─ [按钮] **商城查询**  `perms=store:his:store:query`
+- └─ [按钮] **商城刷新**  `perms=store:his:store:refresh`
+- └─ [按钮] **商城删除**  `perms=store:his:store:remove`
+
+#### parent_id = 29623(无效)
+
+- └─ [按钮] **新增**  `perms=store:homeArticle:add`
+- └─ [按钮] **修改**  `perms=store:homeArticle:edit`
+- └─ [按钮] **导出**  `perms=store:homeArticle:export`
+- └─ [按钮] **查询**  `perms=store:homeArticle:query`
+- └─ [按钮] **删除**  `perms=store:homeArticle:remove`
+
+#### parent_id = 29624(无效)
+
+- └─ [按钮] **新增**  `perms=store:homeCategory:add`
+- └─ [按钮] **修改**  `perms=store:homeCategory:edit`
+- └─ [按钮] **导出**  `perms=store:homeCategory:export`
+- └─ [按钮] **查询**  `perms=store:homeCategory:query`
+- └─ [按钮] **删除**  `perms=store:homeCategory:remove`
+
+#### parent_id = 29625(无效)
+
+- └─ [按钮] **新增**  `perms=store:homeView:add`
+- └─ [按钮] **修改**  `perms=store:homeView:edit`
+- └─ [按钮] **导出**  `perms=store:homeView:export`
+- └─ [按钮] **查询**  `perms=store:homeView:query`
+- └─ [按钮] **删除**  `perms=store:homeView:remove`
+
+#### parent_id = 29628(无效)
+
+- └─ [按钮] **新增**  `perms=store:menu:add`
+- └─ [按钮] **修改**  `perms=store:menu:edit`
+- └─ [按钮] **导出**  `perms=store:menu:export`
+- └─ [按钮] **查询**  `perms=store:menu:query`
+- └─ [按钮] **删除**  `perms=store:menu:remove`
+
+#### parent_id = 29631(无效)
+
+- └─ [按钮] **新增**  `perms=store:prescribe:add`
+- └─ [按钮] **修改**  `perms=store:prescribe:edit`
+- └─ [按钮] **导出**  `perms=store:prescribe:export`
+- └─ [按钮] **查询**  `perms=store:prescribe:query`
+- └─ [按钮] **删除**  `perms=store:prescribe:remove`
+
+#### parent_id = 29632(无效)
+
+- └─ [按钮] **新增**  `perms=store:prescribeDrug:add`
+- └─ [按钮] **修改**  `perms=store:prescribeDrug:edit`
+- └─ [按钮] **导出**  `perms=store:prescribeDrug:export`
+- └─ [按钮] **查询**  `perms=store:prescribeDrug:query`
+- └─ [按钮] **删除**  `perms=store:prescribeDrug:remove`
+
+#### parent_id = 29633(无效)
+
+- └─ [按钮] **导出**  `perms=store:promotionOrder:export`
+- └─ [按钮] **导出items**  `perms=store:promotionOrder:exportItems`
+
+#### parent_id = 29634(无效)
+
+- └─ [按钮] **新增**  `perms=store:recommend:add`
+- └─ [按钮] **删除**  `perms=store:recommend:delete`
+- └─ [按钮] **修改**  `perms=store:recommend:edit`
+- └─ [按钮] **导出**  `perms=store:recommend:export`
+- └─ [按钮] **查询**  `perms=store:recommend:query`
+
+#### parent_id = 29635(无效)
+
+- └─ [按钮] **新增**  `perms=store:shippingTemplates:add`
+- └─ [按钮] **修改**  `perms=store:shippingTemplates:edit`
+- └─ [按钮] **导出**  `perms=store:shippingTemplates:export`
+- └─ [按钮] **查询**  `perms=store:shippingTemplates:query`
+- └─ [按钮] **删除**  `perms=store:shippingTemplates:remove`
+
+#### parent_id = 29636(无效)
+
+- └─ [按钮] **新增**  `perms=store:shippingTemplatesFree:add`
+- └─ [按钮] **修改**  `perms=store:shippingTemplatesFree:edit`
+- └─ [按钮] **导出**  `perms=store:shippingTemplatesFree:export`
+- └─ [按钮] **查询**  `perms=store:shippingTemplatesFree:query`
+- └─ [按钮] **删除**  `perms=store:shippingTemplatesFree:remove`
+
+#### parent_id = 29637(无效)
+
+- └─ [按钮] **新增**  `perms=store:shippingTemplatesRegion:add`
+- └─ [按钮] **修改**  `perms=store:shippingTemplatesRegion:edit`
+- └─ [按钮] **导出**  `perms=store:shippingTemplatesRegion:export`
+- └─ [按钮] **查询**  `perms=store:shippingTemplatesRegion:query`
+- └─ [按钮] **删除**  `perms=store:shippingTemplatesRegion:remove`
+
+#### parent_id = 29638(无效)
+
+- └─ [按钮] **商城订单**  `perms=store:statistics:storeOrder`
+- └─ [按钮] **商城payment**  `perms=store:statistics:storePayment`
+- └─ [按钮] **商城商品**  `perms=store:statistics:storeProduct`
+
+#### parent_id = 29639(无效)
+
+- └─ [按钮] **新增**  `perms=store:store:add`
+- └─ [按钮] **商城审核**  `perms=store:store:audit`
+- └─ [按钮] **修改**  `perms=store:store:edit`
+- └─ [按钮] **导出**  `perms=store:store:export`
+- └─ [按钮] **查询**  `perms=store:store:query`
+- └─ [按钮] **删除**  `perms=store:store:remove`
+
+#### parent_id = 29640(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeActivity:add`
+- └─ [按钮] **修改**  `perms=store:storeActivity:edit`
+- └─ [按钮] **导出**  `perms=store:storeActivity:export`
+- └─ [按钮] **查询**  `perms=store:storeActivity:query`
+- └─ [按钮] **删除**  `perms=store:storeActivity:remove`
+
+#### parent_id = 29641(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeAfterSales:add`
+- └─ [按钮] **按钮**  `perms=store:storeAfterSales:audit1`
+- └─ [按钮] **按钮**  `perms=store:storeAfterSales:audit2`
+- └─ [按钮] **商城aftersales取消**  `perms=store:storeAfterSales:cancel`
+- └─ [按钮] **修改**  `perms=store:storeAfterSales:edit`
+- └─ [按钮] **导出**  `perms=store:storeAfterSales:export`
+- └─ [按钮] **查询**  `perms=store:storeAfterSales:query`
+- └─ [按钮] **按钮**  `perms=store:storeAfterSales:refund`
+- └─ [按钮] **删除**  `perms=store:storeAfterSales:remove`
+
+#### parent_id = 29642(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeAfterSalesItem:add`
+- └─ [按钮] **修改**  `perms=store:storeAfterSalesItem:edit`
+- └─ [按钮] **导出**  `perms=store:storeAfterSalesItem:export`
+- └─ [按钮] **查询**  `perms=store:storeAfterSalesItem:query`
+- └─ [按钮] **删除**  `perms=store:storeAfterSalesItem:remove`
+
+#### parent_id = 29643(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeAfterSalesStatus:add`
+- └─ [按钮] **修改**  `perms=store:storeAfterSalesStatus:edit`
+- └─ [按钮] **导出**  `perms=store:storeAfterSalesStatus:export`
+- └─ [按钮] **查询**  `perms=store:storeAfterSalesStatus:query`
+- └─ [按钮] **删除**  `perms=store:storeAfterSalesStatus:remove`
+
+#### parent_id = 29644(无效)
+
+- └─ [按钮] **修改**  `perms=store:storeCanvas:edit`
+- └─ [按钮] **查询**  `perms=store:storeCanvas:query`
+
+#### parent_id = 29645(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeCart:add`
+- └─ [按钮] **修改**  `perms=store:storeCart:edit`
+- └─ [按钮] **导出**  `perms=store:storeCart:export`
+- └─ [按钮] **查询**  `perms=store:storeCart:query`
+- └─ [按钮] **删除**  `perms=store:storeCart:remove`
+
+#### parent_id = 29646(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeCoupon:add`
+- └─ [按钮] **batchpublish**  `perms=store:storeCoupon:batchPublish`
+- └─ [按钮] **修改**  `perms=store:storeCoupon:edit`
+- └─ [按钮] **导出**  `perms=store:storeCoupon:export`
+- └─ [按钮] **商城优扣券发布**  `perms=store:storeCoupon:publish`
+- └─ [按钮] **查询**  `perms=store:storeCoupon:query`
+- └─ [按钮] **删除**  `perms=store:storeCoupon:remove`
+
+#### parent_id = 29647(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeCouponIssue:add`
+- └─ [按钮] **修改**  `perms=store:storeCouponIssue:edit`
+- └─ [按钮] **导出**  `perms=store:storeCouponIssue:export`
+- └─ [按钮] **查询**  `perms=store:storeCouponIssue:query`
+- └─ [按钮] **删除**  `perms=store:storeCouponIssue:remove`
+
+#### parent_id = 29648(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeCouponIssueUser:add`
+- └─ [按钮] **修改**  `perms=store:storeCouponIssueUser:edit`
+- └─ [按钮] **导出**  `perms=store:storeCouponIssueUser:export`
+- └─ [按钮] **查询**  `perms=store:storeCouponIssueUser:query`
+- └─ [按钮] **删除**  `perms=store:storeCouponIssueUser:remove`
+
+#### parent_id = 29649(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeCouponUser:add`
+- └─ [按钮] **修改**  `perms=store:storeCouponUser:edit`
+- └─ [按钮] **导出**  `perms=store:storeCouponUser:export`
+- └─ [按钮] **查询**  `perms=store:storeCouponUser:query`
+- └─ [按钮] **删除**  `perms=store:storeCouponUser:remove`
+
+#### parent_id = 29650(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeOrder:add`
+- └─ [按钮] **addtuimoney**  `perms=store:storeOrder:addTuiMoney`
+- └─ [按钮] **auditpayremain**  `perms=store:storeOrder:auditPayRemain`
+- └─ [按钮] **batch审核**  `perms=store:storeOrder:batchAudit`
+- └─ [按钮] **createerp订单**  `perms=store:storeOrder:createErpOrder`
+- └─ [按钮] **修改**  `perms=store:storeOrder:edit`
+- └─ [按钮] **editdeliveryid**  `perms=store:storeOrder:editDeliveryId`
+- └─ [按钮] **edittuimoney**  `perms=store:storeOrder:editTuiMoney`
+- └─ [按钮] **导出**  `perms=store:storeOrder:export`
+- └─ [按钮] **导出**  `perms=store:storeOrder:export:details`
+- └─ [按钮] **导出items**  `perms=store:storeOrder:exportItems`
+- └─ [按钮] **导出items**  `perms=store:storeOrder:exportItems:details`
+- └─ [按钮] **按钮**  `perms=store:storeOrder:express`
+- └─ [按钮] **finish订单**  `perms=store:storeOrder:finishOrder`
+- └─ [按钮] **getero订单**  `perms=store:storeOrder:getEroOrder`
+- └─ [按钮] **health导出运费订单**  `perms=store:storeOrder:healthExportShippingOrder`
+- └─ [按钮] **导入express**  `perms=store:storeOrder:importExpress`
+- └─ [按钮] **payremain列表**  `perms=store:storeOrder:payRemainList`
+- └─ [按钮] **查询**  `perms=store:storeOrder:query`
+- └─ [按钮] **queryaddress**  `perms=store:storeOrder:queryAddress`
+- └─ [按钮] **queryphone**  `perms=store:storeOrder:queryPhone`
+- └─ [按钮] **refund订单money**  `perms=store:storeOrder:refundOrderMoney`
+- └─ [按钮] **按钮**  `perms=store:storeOrder:remark`
+- └─ [按钮] **删除**  `perms=store:storeOrder:remove`
+- └─ [按钮] **syncexpress**  `perms=store:storeOrder:syncExpress`
+- └─ [按钮] **updateerp订单**  `perms=store:storeOrder:updateErpOrder`
+- └─ [按钮] **updateexpress**  `perms=store:storeOrder:updateExpress`
+
+#### parent_id = 29651(无效)
+
+- └─ [按钮] **商城订单审核审核**  `perms=store:storeOrderAudit:audit`
+
+#### parent_id = 29652(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeOrderItem:add`
+- └─ [按钮] **修改**  `perms=store:storeOrderItem:edit`
+- └─ [按钮] **导出**  `perms=store:storeOrderItem:export`
+- └─ [按钮] **查询**  `perms=store:storeOrderItem:query`
+- └─ [按钮] **删除**  `perms=store:storeOrderItem:remove`
+- └─ [按钮] **updatenum**  `perms=store:storeOrderItem:updateNum`
+
+#### parent_id = 29653(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeOrderNotice:add`
+- └─ [按钮] **修改**  `perms=store:storeOrderNotice:edit`
+- └─ [按钮] **导出**  `perms=store:storeOrderNotice:export`
+- └─ [按钮] **查询**  `perms=store:storeOrderNotice:query`
+- └─ [按钮] **删除**  `perms=store:storeOrderNotice:remove`
+
+#### parent_id = 29654(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeOrderOffline:add`
+- └─ [按钮] **商城订单线下审核**  `perms=store:storeOrderOffline:audit`
+- └─ [按钮] **修改**  `perms=store:storeOrderOffline:edit`
+- └─ [按钮] **导出**  `perms=store:storeOrderOffline:export`
+- └─ [按钮] **查询**  `perms=store:storeOrderOffline:query`
+- └─ [按钮] **queryphone**  `perms=store:storeOrderOffline:queryPhone`
+- └─ [按钮] **删除**  `perms=store:storeOrderOffline:remove`
+
+#### parent_id = 29655(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeOrderStatus:add`
+- └─ [按钮] **修改**  `perms=store:storeOrderStatus:edit`
+- └─ [按钮] **导出**  `perms=store:storeOrderStatus:export`
+- └─ [按钮] **查询**  `perms=store:storeOrderStatus:query`
+- └─ [按钮] **删除**  `perms=store:storeOrderStatus:remove`
+
+#### parent_id = 29658(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductAttr:add`
+- └─ [按钮] **修改**  `perms=store:storeProductAttr:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductAttr:export`
+- └─ [按钮] **查询**  `perms=store:storeProductAttr:query`
+- └─ [按钮] **删除**  `perms=store:storeProductAttr:remove`
+
+#### parent_id = 29659(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductAttrValue:add`
+- └─ [按钮] **修改**  `perms=store:storeProductAttrValue:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductAttrValue:export`
+- └─ [按钮] **查询**  `perms=store:storeProductAttrValue:query`
+- └─ [按钮] **删除**  `perms=store:storeProductAttrValue:remove`
+
+#### parent_id = 29660(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductCategory:add`
+- └─ [按钮] **修改**  `perms=store:storeProductCategory:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductCategory:export`
+- └─ [按钮] **查询**  `perms=store:storeProductCategory:query`
+- └─ [按钮] **删除**  `perms=store:storeProductCategory:remove`
+
+#### parent_id = 29661(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductDetails:add`
+- └─ [按钮] **修改**  `perms=store:storeProductDetails:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductDetails:export`
+- └─ [按钮] **查询**  `perms=store:storeProductDetails:query`
+- └─ [按钮] **删除**  `perms=store:storeProductDetails:remove`
+
+#### parent_id = 29662(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductGroup:add`
+- └─ [按钮] **修改**  `perms=store:storeProductGroup:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductGroup:export`
+- └─ [按钮] **查询**  `perms=store:storeProductGroup:query`
+- └─ [按钮] **删除**  `perms=store:storeProductGroup:remove`
+
+#### parent_id = 29663(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductPackage:add`
+- └─ [按钮] **修改**  `perms=store:storeProductPackage:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductPackage:export`
+- └─ [按钮] **查询**  `perms=store:storeProductPackage:query`
+- └─ [按钮] **删除**  `perms=store:storeProductPackage:remove`
+
+#### parent_id = 29664(无效)
+
+- └─ [按钮] **导出**  `perms=store:storeProductRelation:export`
+
+#### parent_id = 29665(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductReply:add`
+- └─ [按钮] **修改**  `perms=store:storeProductReply:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductReply:export`
+- └─ [按钮] **查询**  `perms=store:storeProductReply:query`
+- └─ [按钮] **删除**  `perms=store:storeProductReply:remove`
+- └─ [按钮] **按钮**  `perms=store:storeProductReply:reply`
+
+#### parent_id = 29666(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductRule:add`
+- └─ [按钮] **修改**  `perms=store:storeProductRule:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductRule:export`
+- └─ [按钮] **查询**  `perms=store:storeProductRule:query`
+- └─ [按钮] **删除**  `perms=store:storeProductRule:remove`
+
+#### parent_id = 29667(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeProductTemplate:add`
+- └─ [按钮] **修改**  `perms=store:storeProductTemplate:edit`
+- └─ [按钮] **导出**  `perms=store:storeProductTemplate:export`
+- └─ [按钮] **查询**  `perms=store:storeProductTemplate:query`
+- └─ [按钮] **删除**  `perms=store:storeProductTemplate:remove`
+
+#### parent_id = 29668(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeShop:add`
+- └─ [按钮] **修改**  `perms=store:storeShop:edit`
+- └─ [按钮] **导出**  `perms=store:storeShop:export`
+- └─ [按钮] **查询**  `perms=store:storeShop:query`
+- └─ [按钮] **删除**  `perms=store:storeShop:remove`
+
+#### parent_id = 29669(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeShopStaff:add`
+- └─ [按钮] **修改**  `perms=store:storeShopStaff:edit`
+- └─ [按钮] **导出**  `perms=store:storeShopStaff:export`
+- └─ [按钮] **查询**  `perms=store:storeShopStaff:query`
+- └─ [按钮] **删除**  `perms=store:storeShopStaff:remove`
+
+#### parent_id = 29670(无效)
+
+- └─ [按钮] **新增**  `perms=store:storeVisit:add`
+- └─ [按钮] **修改**  `perms=store:storeVisit:edit`
+- └─ [按钮] **导出**  `perms=store:storeVisit:export`
+- └─ [按钮] **查询**  `perms=store:storeVisit:query`
+- └─ [按钮] **删除**  `perms=store:storeVisit:remove`
+
+#### parent_id = 29672(无效)
+
+- └─ [按钮] **新增**  `perms=store:userPromoterApply:add`
+- └─ [按钮] **修改**  `perms=store:userPromoterApply:edit`
+- └─ [按钮] **导出**  `perms=store:userPromoterApply:export`
+- └─ [按钮] **查询**  `perms=store:userPromoterApply:query`
+- └─ [按钮] **删除**  `perms=store:userPromoterApply:remove`
+
+#### parent_id = 29673(无效)
+
+- └─ [按钮] **新增**  `perms=storeOrderOfflineItem:store:add`
+- └─ [按钮] **修改**  `perms=storeOrderOfflineItem:store:edit`
+- └─ [按钮] **导出**  `perms=storeOrderOfflineItem:store:export`
+- └─ [按钮] **查询**  `perms=storeOrderOfflineItem:store:query`
+- └─ [按钮] **删除**  `perms=storeOrderOfflineItem:store:remove`
+
+#### parent_id = 29675(无效)
+
+- └─ [按钮] **新增**  `perms=system:companyVoiceDialog:add`
+- └─ [按钮] **修改**  `perms=system:companyVoiceDialog:edit`
+- └─ [按钮] **导出**  `perms=system:companyVoiceDialog:export`
+- └─ [按钮] **查询**  `perms=system:companyVoiceDialog:query`
+- └─ [按钮] **删除**  `perms=system:companyVoiceDialog:remove`
+
+#### parent_id = 29676(无效)
+
+- └─ [按钮] **新增**  `perms=system:companyVoiceRobotic:add`
+- └─ [按钮] **修改**  `perms=system:companyVoiceRobotic:edit`
+- └─ [按钮] **导出**  `perms=system:companyVoiceRobotic:export`
+- └─ [按钮] **查询**  `perms=system:companyVoiceRobotic:query`
+- └─ [按钮] **删除**  `perms=system:companyVoiceRobotic:remove`
+
+#### parent_id = 29677(无效)
+
+- └─ [按钮] **新增**  `perms=system:companyVoiceRoboticCallees:add`
+- └─ [按钮] **修改**  `perms=system:companyVoiceRoboticCallees:edit`
+- └─ [按钮] **导出**  `perms=system:companyVoiceRoboticCallees:export`
+- └─ [按钮] **查询**  `perms=system:companyVoiceRoboticCallees:query`
+- └─ [按钮] **删除**  `perms=system:companyVoiceRoboticCallees:remove`
+
+#### parent_id = 29687(无效)
+
+- └─ [按钮] **新增**  `perms=system:set:add`
+- └─ [按钮] **修改**  `perms=system:set:edit`
+- └─ [按钮] **导出**  `perms=system:set:export`
+- └─ [按钮] **查询**  `perms=system:set:query`
+- └─ [按钮] **删除**  `perms=system:set:remove`
+
+#### parent_id = 29689(无效)
+
+- └─ [按钮] **修改**  `perms=tenant:config:edit`
+
+#### parent_id = 29691(无效)
+
+- └─ [按钮] **新增**  `perms=tenant:tenant:add`
+- └─ [按钮] **修改**  `perms=tenant:tenant:edit`
+- └─ [按钮] **导出**  `perms=tenant:tenant:export`
+- └─ [按钮] **查询**  `perms=tenant:tenant:query`
+- └─ [按钮] **删除**  `perms=tenant:tenant:remove`
+
+#### parent_id = 29692(无效)
+
+- └─ [按钮] **修改**  `perms=third:third:edit`
+
+#### parent_id = 29693(无效)
+
+- └─ [按钮] **查看**  `perms=tool:swagger:view`
+
+#### parent_id = 29696(无效)
+
+- └─ [按钮] **新增**  `perms=user:msg:add`
+- └─ [按钮] **修改**  `perms=user:msg:edit`
+- └─ [按钮] **导出**  `perms=user:msg:export`
+- └─ [按钮] **查询**  `perms=user:msg:query`
+- └─ [按钮] **删除**  `perms=user:msg:remove`
+
+#### parent_id = 35030(无效)
+
+- [菜单] **fs随访报表**  `id=32541` path=`FsFollowReport` component=`his/FsFollowReport/index/index` 显示
+- [菜单] **ai医生chat消息**  `id=32542` path=`aiDoctorChatMsg` component=`his/aiDoctorChatMsg/index` 显示
+- [菜单] **ai医生chat会话**  `id=32543` path=`aiDoctorChatSession` component=`his/aiDoctorChatSession/index` 显示
+- [菜单] **ai医生角色**  `id=32544` path=`aiDoctorRole` component=`his/aiDoctorRole/index` 显示
+- [菜单] **AI工作流**  `id=32545` path=`aiWorkflow` component=`his/aiWorkflow/index` 显示
+- [菜单] **文章views**  `id=32546` path=`articleViews` component=`his/articleViews/index` 显示
+- [菜单] **医生账单**  `id=32547` path=`doctorBill` component=`his/bill/doctorBill/index` 显示
+- [菜单] **医生extract**  `id=32548` path=`doctorExtract` component=`his/bill/doctorExtract/index` 显示
+- [菜单] **red套餐**  `id=32549` path=`redPackage` component=`his/bill/redPackage/index` 显示
+- [菜单] **商城账单**  `id=32550` path=`storeBill` component=`his/bill/storeBill/index` 显示
+- [菜单] **商城extract**  `id=32551` path=`storeExtract` component=`his/bill/storeExtract/index` 显示
+- [菜单] **用户账单**  `id=32552` path=`userBill` component=`his/bill/userBill/index` 显示
+- [菜单] **用户extract**  `id=32553` path=`userExtract` component=`his/bill/userExtract/index` 显示
+- [菜单] **case文章**  `id=32554` path=`caseArticle` component=`his/caseArticle/index` 显示
+- [菜单] **city**  `id=32555` path=`city` component=`his/city/index/index` 显示
+- [菜单] **dfaccount**  `id=32556` path=`dfAccount` component=`his/dfAccount/index` 显示
+- [菜单] **医生**  `id=32557` path=`doctor` component=`his/doctor/index/index` 显示
+- [菜单] **医生文章**  `id=32558` path=`doctorArticle` component=`his/doctorArticle/index` 显示
+- [菜单] **医生账单**  `id=32559` path=`doctorBill2` component=`his/doctorBill/index/index` 显示
+- [菜单] **医生extract**  `id=32560` path=`doctorExtract2` component=`his/doctorExtract/index/index` 显示
+- [菜单] **医生oper日志**  `id=32561` path=`doctorOperLog` component=`his/doctorOperLog/index/index` 显示
+- [菜单] **医生商品**  `id=32562` path=`doctorProduct` component=`his/doctorProduct/index/index` 显示
+- [菜单] **follow报表**  `id=32563` path=`followReport` component=`his/followReport/index` 显示
+- [菜单] **health文章**  `id=32564` path=`healthArticle` component=`his/healthArticle/index/index` 显示
+- [菜单] **health数据**  `id=32565` path=`healthData` component=`his/healthData/index` 显示
+- [菜单] **healthlife**  `id=32566` path=`healthLife` component=`his/healthLife/index` 显示
+- [菜单] **home文章**  `id=32567` path=`homeArticle` component=`his/homeArticle/index` 显示
+- [菜单] **home分类**  `id=32568` path=`homeCategory` component=`his/homeCategory/index` 显示
+- [菜单] **homeview**  `id=32569` path=`homeView` component=`his/homeView/index` 显示
+- [菜单] **日志**  `id=32570` path=`logs` component=`his/logs/index/index` 显示
+- [菜单] **套餐收藏**  `id=32571` path=`packageFavorite` component=`his/packageFavorite/index/index` 显示
+- [菜单] **pharmacist**  `id=32572` path=`pharmacist` component=`his/pharmacist/index/index` 显示
+- [菜单] **price**  `id=32573` path=`price` component=`his/price/index/index` 显示
+- [菜单] **promotionactive**  `id=32574` path=`promotionActive` component=`his/promotionActive/index/index` 显示
+- [菜单] **promotionactive日志**  `id=32575` path=`promotionActiveLog` component=`his/promotionActiveLog/index/index` 显示
+- [菜单] **promotionalactive**  `id=32576` path=`promotionalActive` component=`his/promotionalActive/index` 显示
+- [菜单] **redpacket配置**  `id=32577` path=`redPacketConfig` component=`his/redPacketConfig/index` 显示
+- [菜单] **售后**  `id=32578` path=`storeAfterSales` component=`his/storeAfterSales/index/index` 显示
+- [菜单] **商城账单**  `id=32579` path=`storeBill2` component=`his/storeBill/index/index` 显示
+- [菜单] **商城extract**  `id=32580` path=`storeExtract2` component=`his/storeExtract/index/index` 显示
+- [菜单] **商城日志**  `id=32581` path=`storeLog` component=`his/storeLog/index/index` 显示
+- [菜单] **商城商品套餐**  `id=32582` path=`storeProductPackage` component=`his/storeProductPackage/index` 显示
+- [菜单] **工作流模板库**  `id=32583` path=`template` component=`his/template/index/index` 显示
+- [菜单] **检测模板项**  `id=32584` path=`testTempItem` component=`his/testTempItem/index` 显示
+- [菜单] **用户address**  `id=32585` path=`userAddress` component=`his/userAddress/index/index` 显示
+- [菜单] **用户账单**  `id=32586` path=`userBill2` component=`his/userBill/index/index` 显示
+- [菜单] **用户extract**  `id=32587` path=`userExtract2` component=`his/userExtract/index/index` 显示
+- [菜单] **用户new任务**  `id=32588` path=`userNewTask` component=`his/userNewTask/index/index` 显示
+- [菜单] **商城管理-用户在线状态**  `id=32589` path=`userOnlineState` component=`his/userOnlineState/index` 显示
+- [菜单] **用户operation日志**  `id=32590` path=`userOperationLog` component=`his/userOperationLog/index/index` 显示
+
+---
+
+## 附录:按模块统计
+
+| 顶级模块 | 目录 | 菜单 | 按钮 | 合计 |
+|----------|------|------|------|------|
+| 企微管理 | 7 | 44 | 0 | 50 |
+| 微信管理 | 4 | 5 | 0 | 8 |
+| CRM客户 | 3 | 7 | 0 | 9 |
+| 会员管理 | 0 | 7 | 0 | 6 |
+| 诊所管理 | 0 | 1 | 0 | 0 |
+| 商城管理 | 3 | 54 | 0 | 56 |
+| 直播管理 | 4 | 32 | 0 | 35 |
+| 课程管理 | 4 | 34 | 0 | 37 |
+| AI聊天 | 6 | 12 | 5 | 22 |
+| 龙虸引擎 | 1 | 12 | 0 | 12 |
+| 广告投放 | 1 | 16 | 0 | 16 |
+| 系统管理 | 5 | 44 | 0 | 48 |
+| 财务管理 | 4 | 7 | 0 | 10 |
+| 日程管理 | 0 | 1 | 0 | 0 |
+| 数据统计 | 0 | 9 | 9 | 17 |
+| 监控管理 | 0 | 6 | 0 | 5 |
+| 其他 | 47 | 251 | 857 | 1154 |
+
+*Generated by `sql/generate_menu_tree_zh.py`*

+ 898 - 0
sql/adminUI_views_menu_structure.md

@@ -0,0 +1,898 @@
+# adminUI 视图反向梳理 — 租户管理端菜单建议结构
+
+> 文档类型:**只读梳理**,暂不修改数据库或代码。
+> 扫描来源:`ylrz_saas_his_scrm_adminUI/src/views`
+> 生成日期:2026-05-29
+> 扫描结果:共 **1160** 个 `.vue` 文件,识别 **826** 个可独立路由页面
+
+---
+
+## 一、梳理方法
+
+| 项目 | 说明 |
+|------|------|
+| 页面识别 | `index.vue` / `list.vue` / `myList.vue` 及模块根目录单层 `.vue` |
+| 排除 | `components/`、详情页、授权页、字典子页、设计器、日志子页等 |
+| 组件路径 | 对应后端 `sys_menu.component`,如 `qw/externalContact/index` |
+| 路由加载 | 后端 `getRouters` → `loadView(@/views/${component})` |
+| 参考 | `src/views/admin/menu.js` (总后台 `/admin/*` 对照表) |
+
+---
+
+## 二、建议顶级模块(租户 saasadminui 顶栏)
+
+| 序号 | 模块名 | path | 视图根目录 | 页面数 | 备注 |
+|------|--------|------|------------|--------|------|
+| 1 | 首页 | `index` | index.vue | 1 | 仪表盘,可 hidden |
+| 2 | 企微管理 | `qw` | qw/ | 73 |  |
+| 3 | 微信管理 | `wx` | wx/, gw/ | 5 |  |
+| 4 | CRM客户 | `crm` | crm/ | 13 |  |
+| 5 | 会员管理 | `member` | user/, users/, member/ | 20 |  |
+| 6 | 诊所管理 | `his` | his/ | 135 |  |
+| 7 | 商城管理 | `store` | store/ | 114 | canonical |
+| 8 | 直播管理 | `live` | live/, liveData/ | 60 |  |
+| 9 | 课程管理 | `course` | course/, courseFinishTemp/ | 77 |  |
+| 10 | AI聊天 | `fastGpt` | fastGpt/, chat/, aiob/ | 31 |  |
+| 11 | 龙虾引擎 | `lobster` | lobster/ | 13 |  |
+| 12 | 广告投放 | `ad` | adv/, ad/ | 25 |  |
+| 13 | 系统管理 | `system` | system/, company/ | 73 |  |
+| 14 | 财务管理 | `bill` | bill/, billing/ | 2 |  |
+| 15 | 日程管理 | `calendar` | calendar/ | 1 |  |
+| 16 | 数据统计 | `statistics` | statistics/, taskStatistics/ | 9 |  |
+| 17 | 监控管理 | `watch` | watch/, monitor/ | 15 |  |
+| 18 | 其他 | `other` | 平台/遗留 | 0 | 不下发租户默认菜单 |
+
+---
+
+## 三、总后台专用(归入「其他」)
+
+| 目录 | 页面数 | 说明 |
+|------|--------|------|
+| `admin/` | 60 | 总后台业务(租户/代理/外呼/短信/财务审计) |
+| `aiSipCall/` | 9 | 平台或遗留 |
+| `baidu/` | 1 | 平台或遗留 |
+| `callRecord/` | 2 | 平台或遗留 |
+| `food/` | 1 | 平台或遗留 |
+| `hisStore/` | 54 | 旧版商城,与 store 重复 |
+| `medical/` | 4 | 平台或遗留 |
+| `operation/` | 1 | 平台或遗留 |
+| `saas/` | 11 | SaaS 计费/租户字典/租户菜单模板 |
+| `saler/` | 2 | 平台或遗留 |
+| `shop/` | 6 | 门店独立菜单(遗留) |
+| `storeOrderOfflineItem/` | 2 | 平台或遗留 |
+| `sysUser/` | 2 | 总后台员工(与 system/user 不同) |
+| `todo/` | 1 | 平台或遗留 |
+
+### 3.1 admin/menu.js 对照(总后台 /admin/*)
+
+| 菜单标题 | path | component |
+|----------|------|-----------|
+| 数据看板 | `/admin/dashboard` | `admin/dashboard/index` |
+| 租户管理 | `/admin/company` | `admin/sysCompany/index` |
+| 租户模块使用统计 | `/admin/moduleUsage` | `admin/moduleUsage/index` |
+| 租户管理端菜单 | `/admin/tenantMenu` | `admin/tenantMenu/index` |
+| 租户销售端菜单 | `/admin/tenantCompany` | `admin/tenantCompany/index` |
+| 代理管理 | `/admin/proxy` | `admin/proxy/index` |
+| 收费配置 | `/admin/serviceCost` | `admin/serviceCost/index` |
+| 员工管理 | `/admin/sysUser` | `admin/sysUser/index` |
+| 角色管理 | `/admin/role` | `system/role/index` |
+| 菜单管理 | `/admin/menu` | `system/menu/index` |
+| 外呼管理 | `/admin/voice` | `admin/voice/index` |
+| 短信管理 | `/admin/sms` | `admin/sms/index` |
+| AI模型配置 | `/admin/aiModel` | `admin/aiModel/index` |
+| AI生成工作流 | `/admin/workflowGenerate` | `lobster/workflow-generate/index` |
+
+---
+
+## 四、各业务模块二级分组与页面清单
+
+### 4.1 企微管理 (`qw/`) — 72 页
+
+建议路由前缀:`/qw`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `qw/QwWorkTask/index` | `qw/QwWorkTask/index.vue` |
+| index | `qw/QwWorkTask/qw/index` | `qw/QwWorkTask/qw/index.vue` |
+| index | `qw/QwWorkTaskNew/index` | `qw/QwWorkTaskNew/index.vue` |
+| index | `qw/appAdvertisingReport/index` | `qw/appAdvertisingReport/index.vue` |
+| index | `qw/appContactWay/index` | `qw/appContactWay/index.vue` |
+| index | `qw/applyIpad/index` | `qw/applyIpad/index.vue` |
+| index | `qw/assignRule/index` | `qw/assignRule/index.vue` |
+| index | `qw/autoTagsLogs/index` | `qw/autoTagsLogs/index.vue` |
+| index | `qw/autoTagsRules/index` | `qw/autoTagsRules/index.vue` |
+| index | `qw/companyTag/index` | `qw/companyTag/index.vue` |
+| index | `qw/companyTagGroup/index` | `qw/companyTagGroup/index.vue` |
+| index | `qw/companyUser/index` | `qw/companyUser/index.vue` |
+| index | `qw/contactBatch/index` | `qw/contactBatch/index.vue` |
+| index | `qw/contactWay/index` | `qw/contactWay/index.vue` |
+| index | `qw/contactWayLogs/index` | `qw/contactWayLogs/index.vue` |
+| index | `qw/customerLink/index` | `qw/customerLink/index.vue` |
+| index | `qw/drainageLink/index` | `qw/drainageLink/index.vue` |
+| index | `qw/drainageLinkLogs/index` | `qw/drainageLinkLogs/index.vue` |
+| index | `qw/externalContact/index` | `qw/externalContact/index.vue` |
+| index | `qw/externalContactLoss/index` | `qw/externalContactLoss/index.vue` |
+| index | `qw/externalContactStage/index` | `qw/externalContactStage/index.vue` |
+| index | `qw/externalContactTransfer/index` | `qw/externalContactTransfer/index.vue` |
+| index | `qw/externalContactTransferAudit/index` | `qw/externalContactTransferAudit/index.vue` |
+| index | `qw/externalContactTransferCompanyAudit/index` | `qw/externalContactTransferCompanyAudit/index.vue` |
+| index | `qw/externalContactTransferCompanyAudit/index` | `qw/externalContactTransferCompanyAudit/index/index.vue` |
+| index | `qw/externalContactTransferLog/index` | `qw/externalContactTransferLog/index.vue` |
+| index | `qw/externalContactUnassigned/index` | `qw/externalContactUnassigned/index.vue` |
+| index | `qw/friendCircle/index` | `qw/friendCircle/index.vue` |
+| index | `qw/friendCircleTask/index` | `qw/friendCircleTask/index.vue` |
+| index | `qw/friendComments/index` | `qw/friendComments/index.vue` |
+| index | `qw/friendCustomerList/index` | `qw/friendCustomerList/index.vue` |
+| index | `qw/friendMaterial/index` | `qw/friendMaterial/index.vue` |
+| index | `qw/friendWelcome/index` | `qw/friendWelcome/index.vue` |
+| index | `qw/friendWelcomeItem/index` | `qw/friendWelcomeItem/index.vue` |
+| index | `qw/groupActual/index` | `qw/groupActual/index.vue` |
+| index | `qw/groupChat/index` | `qw/groupChat/index.vue` |
+| index | `qw/groupChatStatistic/index` | `qw/groupChatStatistic/index.vue` |
+| index | `qw/groupChatTransfer/index` | `qw/groupChatTransfer/index.vue` |
+| index | `qw/groupChatTransferLog/index` | `qw/groupChatTransferLog/index.vue` |
+| index | `qw/groupChatTransferOnJob/index` | `qw/groupChatTransferOnJob/index.vue` |
+| index | `qw/groupLiveCode/index` | `qw/groupLiveCode/index.vue` |
+| index | `qw/groupMsg/index` | `qw/groupMsg/index.vue` |
+| index | `qw/groupMsgItem/index` | `qw/groupMsgItem/index.vue` |
+| index | `qw/material/index` | `qw/material/index.vue` |
+| index | `qw/materialQw/index` | `qw/materialQw/index.vue` |
+| index | `qw/myVoiceLog/index` | `qw/myVoiceLog/index.vue` |
+| index | `qw/qwAppContactWayLogs/index` | `qw/qwAppContactWayLogs/index.vue` |
+| index | `qw/qwCompany/index` | `qw/qwCompany/index.vue` |
+| index | `qw/qwDept/index` | `qw/qwDept/index.vue` |
+| index | `qw/qwDept/index` | `qw/qwDept/index/index.vue` |
+| index | `qw/qwInformation/index` | `qw/qwInformation/index.vue` |
+| index | `qw/qwIpadServer/index` | `qw/qwIpadServer/index.vue` |
+| index | `qw/qwIpadServerLog/index` | `qw/qwIpadServerLog/index.vue` |
+| index | `qw/qwIpadServerUser/index` | `qw/qwIpadServerUser/index.vue` |
+| index | `qw/qwPushCount/index` | `qw/qwPushCount/index.vue` |
+| index | `qw/qwPushCount/index` | `qw/qwPushCount/index/index.vue` |
+| index | `qw/qwUserDelLossStatistics/index` | `qw/qwUserDelLossStatistics/index.vue` |
+| index | `qw/qwUserVoiceLog/index` | `qw/qwUserVoiceLog/index.vue` |
+| index | `qw/qwUserVoiceLogTotal/index` | `qw/qwUserVoiceLogTotal/index.vue` |
+| index | `qw/record/index` | `qw/record/index.vue` |
+| index | `qw/record/index` | `qw/record/index/index.vue` |
+| index | `qw/sop/index` | `qw/sop/index.vue` |
+| index | `qw/sop/index` | `qw/sop/index/index.vue` |
+| index | `qw/sopTemp/index` | `qw/sopTemp/index.vue` |
+| index | `qw/tag/index` | `qw/tag/index.vue` |
+| index | `qw/tagGroup/index` | `qw/tagGroup/index.vue` |
+| index | `qw/user/index` | `qw/user/index.vue` |
+| index | `qw/userBehaviorData/index` | `qw/userBehaviorData/index.vue` |
+| index | `qw/welcome/index` | `qw/welcome/index.vue` |
+| index | `qw/workLink/index` | `qw/workLink/index.vue` |
+| index | `qw/workLinkUser/index` | `qw/workLinkUser/index.vue` |
+| index | `qw/workUser/index` | `qw/workUser/index.vue` |
+
+### 4.2 CRM (`crm/`) — 13 页
+
+建议路由前缀:`/crm`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `crm/customer/index` | `crm/customer/index.vue` |
+| index | `crm/customerAssign/index` | `crm/customerAssign/index.vue` |
+| index | `crm/customerAssign/index` | `crm/customerAssign/index/index.vue` |
+| index | `crm/customerContacts/index` | `crm/customerContacts/index.vue` |
+| index | `crm/customerExt/index` | `crm/customerExt/index.vue` |
+| index | `crm/customerLevel/index` | `crm/customerLevel/index/index.vue` |
+| index | `crm/customerLogs/index` | `crm/customerLogs/index.vue` |
+| index | `crm/customerUser/index` | `crm/customerUser/index.vue` |
+| index | `crm/customerVisit/index` | `crm/customerVisit/index.vue` |
+| index | `crm/event/index` | `crm/event/index.vue` |
+| index | `crm/externalContact/index` | `crm/externalContact/index.vue` |
+| index | `crm/msg/index` | `crm/msg/index.vue` |
+| index | `crm/third/index` | `crm/third/index.vue` |
+
+### 4.3 商城 (`store/`) — 114 页
+
+建议路由前缀:`/store`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `store/FsFollowReport/index` | `store/FsFollowReport/index.vue` |
+| index | `store/PromotionOrder/index` | `store/PromotionOrder/index.vue` |
+| index | `store/PromotionOrder/index` | `store/PromotionOrder/index/index.vue` |
+| index | `store/adv/index` | `store/adv/index.vue` |
+| index | `store/adv/index` | `store/adv/index/index.vue` |
+| index | `store/collectionSchedule/index` | `store/collectionSchedule/index.vue` |
+| index | `store/coupon/index` | `store/coupon/index.vue` |
+| index | `store/drugReport/index` | `store/drugReport/index.vue` |
+| index | `store/drugReportCount/index` | `store/drugReportCount/index.vue` |
+| index | `store/exportTask/index` | `store/exportTask/index.vue` |
+| list | `store/follow/list` | `store/follow/list.vue` |
+| myList | `store/follow/myList` | `store/follow/myList.vue` |
+| index | `store/healthRecord/index` | `store/healthRecord/index.vue` |
+| index | `store/healthStoreOrder/index` | `store/healthStoreOrder/index.vue` |
+| index | `store/healthStoreOrder/index` | `store/healthStoreOrder/index/index.vue` |
+| index | `store/healthTongue/index` | `store/healthTongue/index.vue` |
+| index | `store/homeArticle/index` | `store/homeArticle/index.vue` |
+| index | `store/homeArticle/index` | `store/homeArticle/index/index.vue` |
+| index | `store/homeCategory/index` | `store/homeCategory/index.vue` |
+| index | `store/homeCategory/index` | `store/homeCategory/index/index.vue` |
+| index | `store/homeView/index` | `store/homeView/index.vue` |
+| index | `store/homeView/index` | `store/homeView/index/index.vue` |
+| index | `store/index` | `store/index.vue` |
+| index | `store/index` | `store/index/index.vue` |
+| list | `store/inquiryOrder/list` | `store/inquiryOrder/list.vue` |
+| myList | `store/inquiryOrder/myList` | `store/inquiryOrder/myList.vue` |
+| index | `store/inquiryOrderReport/index` | `store/inquiryOrderReport/index.vue` |
+| index | `store/menu/index` | `store/menu/index.vue` |
+| index | `store/menu/index` | `store/menu/index/index.vue` |
+| index | `store/myHealthTongue/index` | `store/myHealthTongue/index.vue` |
+| index | `store/package/index` | `store/package/index.vue` |
+| list | `store/packageOrder/list` | `store/packageOrder/list.vue` |
+| myList | `store/packageOrder/myList` | `store/packageOrder/myList.vue` |
+| index | `store/prescribe/index` | `store/prescribe/index.vue` |
+| index | `store/prescribe/index` | `store/prescribe/index/index.vue` |
+| list | `store/prescribe/list` | `store/prescribe/list.vue` |
+| myList | `store/prescribe/myList` | `store/prescribe/myList.vue` |
+| index | `store/prescribeDrug/index` | `store/prescribeDrug/index.vue` |
+| index | `store/prescribeDrug/index` | `store/prescribeDrug/index/index.vue` |
+| index | `store/recommend/index` | `store/recommend/index.vue` |
+| index | `store/recommend/index` | `store/recommend/index/index.vue` |
+| index | `store/shippingTemplates/index` | `store/shippingTemplates/index.vue` |
+| index | `store/shippingTemplates/index` | `store/shippingTemplates/index/index.vue` |
+| index | `store/shippingTemplatesFree/index` | `store/shippingTemplatesFree/index.vue` |
+| index | `store/shippingTemplatesFree/index` | `store/shippingTemplatesFree/index/index.vue` |
+| index | `store/shippingTemplatesRegion/index` | `store/shippingTemplatesRegion/index.vue` |
+| index | `store/shippingTemplatesRegion/index` | `store/shippingTemplatesRegion/index/index.vue` |
+| index | `store/storeActivity/index` | `store/storeActivity/index.vue` |
+| index | `store/storeActivity/index` | `store/storeActivity/index/index.vue` |
+| index | `store/storeAfterSales/index` | `store/storeAfterSales/index.vue` |
+| index | `store/storeAfterSales/index` | `store/storeAfterSales/index/index.vue` |
+| list | `store/storeAfterSales/list` | `store/storeAfterSales/list.vue` |
+| myList | `store/storeAfterSales/myList` | `store/storeAfterSales/myList.vue` |
+| index | `store/storeAfterSalesItem/index` | `store/storeAfterSalesItem/index.vue` |
+| index | `store/storeAfterSalesItem/index` | `store/storeAfterSalesItem/index/index.vue` |
+| index | `store/storeAfterSalesStatus/index` | `store/storeAfterSalesStatus/index.vue` |
+| index | `store/storeAfterSalesStatus/index` | `store/storeAfterSalesStatus/index/index.vue` |
+| index | `store/storeCart/index` | `store/storeCart/index.vue` |
+| index | `store/storeCart/index` | `store/storeCart/index/index.vue` |
+| index | `store/storeCoupon/index` | `store/storeCoupon/index.vue` |
+| index | `store/storeCoupon/index` | `store/storeCoupon/index/index.vue` |
+| index | `store/storeCouponIssue/index` | `store/storeCouponIssue/index.vue` |
+| index | `store/storeCouponIssue/index` | `store/storeCouponIssue/index/index.vue` |
+| index | `store/storeCouponIssueUser/index` | `store/storeCouponIssueUser/index.vue` |
+| index | `store/storeCouponIssueUser/index` | `store/storeCouponIssueUser/index/index.vue` |
+| index | `store/storeCouponUser/index` | `store/storeCouponUser/index.vue` |
+| index | `store/storeCouponUser/index` | `store/storeCouponUser/index/index.vue` |
+| index | `store/storeOrder/index` | `store/storeOrder/index.vue` |
+| index | `store/storeOrder/index` | `store/storeOrder/index/index.vue` |
+| list | `store/storeOrder/list` | `store/storeOrder/list.vue` |
+| myList | `store/storeOrder/myList` | `store/storeOrder/myList.vue` |
+| index | `store/storeOrderAudit/index` | `store/storeOrderAudit/index.vue` |
+| index | `store/storeOrderAudit/index` | `store/storeOrderAudit/index/index.vue` |
+| index | `store/storeOrderItem/index` | `store/storeOrderItem/index.vue` |
+| index | `store/storeOrderItem/index` | `store/storeOrderItem/index/index.vue` |
+| index | `store/storeOrderNotice/index` | `store/storeOrderNotice/index.vue` |
+| index | `store/storeOrderNotice/index` | `store/storeOrderNotice/index/index.vue` |
+| index | `store/storeOrderOffline/index` | `store/storeOrderOffline/index.vue` |
+| index | `store/storeOrderOffline/index` | `store/storeOrderOffline/index/index.vue` |
+| index | `store/storeOrderStatus/index` | `store/storeOrderStatus/index.vue` |
+| index | `store/storeOrderStatus/index` | `store/storeOrderStatus/index/index.vue` |
+| index | `store/storePayment/index` | `store/storePayment/index.vue` |
+| index | `store/storeProduct/index` | `store/storeProduct/index.vue` |
+| index | `store/storeProductAttr/index` | `store/storeProductAttr/index.vue` |
+| index | `store/storeProductAttr/index` | `store/storeProductAttr/index/index.vue` |
+| index | `store/storeProductAttrValue/index` | `store/storeProductAttrValue/index.vue` |
+| index | `store/storeProductAttrValue/index` | `store/storeProductAttrValue/index/index.vue` |
+| index | `store/storeProductCategory/index` | `store/storeProductCategory/index.vue` |
+| index | `store/storeProductCategory/index` | `store/storeProductCategory/index/index.vue` |
+| index | `store/storeProductDetails/index` | `store/storeProductDetails/index.vue` |
+| index | `store/storeProductDetails/index` | `store/storeProductDetails/index/index.vue` |
+| index | `store/storeProductGroup/index` | `store/storeProductGroup/index.vue` |
+| index | `store/storeProductGroup/index` | `store/storeProductGroup/index/index.vue` |
+| index | `store/storeProductPackage/index` | `store/storeProductPackage/index.vue` |
+| index | `store/storeProductRelation/index` | `store/storeProductRelation/index.vue` |
+| index | `store/storeProductRelation/index` | `store/storeProductRelation/index/index.vue` |
+| index | `store/storeProductReply/index` | `store/storeProductReply/index.vue` |
+| index | `store/storeProductReply/index` | `store/storeProductReply/index/index.vue` |
+| index | `store/storeProductRule/index` | `store/storeProductRule/index.vue` |
+| index | `store/storeProductRule/index` | `store/storeProductRule/index/index.vue` |
+| index | `store/storeProductTemplate/index` | `store/storeProductTemplate/index.vue` |
+| index | `store/storeProductTemplate/index` | `store/storeProductTemplate/index/index.vue` |
+| index | `store/storeShop/index` | `store/storeShop/index.vue` |
+| index | `store/storeShop/index` | `store/storeShop/index/index.vue` |
+| index | `store/storeShopStaff/index` | `store/storeShopStaff/index.vue` |
+| index | `store/storeShopStaff/index` | `store/storeShopStaff/index/index.vue` |
+| index | `store/storeVisit/index` | `store/storeVisit/index.vue` |
+| index | `store/storeVisit/index` | `store/storeVisit/index/index.vue` |
+| list | `store/user/list` | `store/user/list.vue` |
+| myList | `store/user/myList` | `store/user/myList.vue` |
+| index | `store/userCoupon/index` | `store/userCoupon/index.vue` |
+| index | `store/userOnlineState/index` | `store/userOnlineState/index.vue` |
+| index | `store/userPromoterApply/index` | `store/userPromoterApply/index.vue` |
+| index | `store/userPromoterApply/index` | `store/userPromoterApply/index/index.vue` |
+
+### 4.4 诊所 (`his/`) — 135 页
+
+建议路由前缀:`/his`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `his/FsFollowReport/index` | `his/FsFollowReport/index.vue` |
+| index | `his/FsFollowReport/index` | `his/FsFollowReport/index/index.vue` |
+| index | `his/adv/index` | `his/adv/index.vue` |
+| index | `his/aiDoctorChatMsg/index` | `his/aiDoctorChatMsg/index.vue` |
+| index | `his/aiDoctorChatSession/index` | `his/aiDoctorChatSession/index.vue` |
+| index | `his/aiDoctorRole/index` | `his/aiDoctorRole/index.vue` |
+| index | `his/aiWorkflow/index` | `his/aiWorkflow/index.vue` |
+| index | `his/answer/index` | `his/answer/index.vue` |
+| index | `his/appVersion/index` | `his/appVersion/index.vue` |
+| index | `his/article/index` | `his/article/index.vue` |
+| index | `his/articleCate/index` | `his/articleCate/index.vue` |
+| index | `his/articleViews/index` | `his/articleViews/index.vue` |
+| index | `his/bill/doctorBill/index` | `his/bill/doctorBill/index.vue` |
+| index | `his/bill/doctorExtract/index` | `his/bill/doctorExtract/index.vue` |
+| index | `his/bill/redPackage/index` | `his/bill/redPackage/index.vue` |
+| index | `his/bill/storeBill/index` | `his/bill/storeBill/index.vue` |
+| index | `his/bill/storeExtract/index` | `his/bill/storeExtract/index.vue` |
+| index | `his/bill/userBill/index` | `his/bill/userBill/index.vue` |
+| index | `his/bill/userExtract/index` | `his/bill/userExtract/index.vue` |
+| index | `his/caseArticle/index` | `his/caseArticle/index.vue` |
+| index | `his/chineseMedicine/index` | `his/chineseMedicine/index.vue` |
+| index | `his/city/index` | `his/city/index.vue` |
+| index | `his/city/index` | `his/city/index/index.vue` |
+| index | `his/company/index` | `his/company/index.vue` |
+| index | `his/companyDeduct/index` | `his/companyDeduct/index.vue` |
+| index | `his/companyRecharge/index` | `his/companyRecharge/index.vue` |
+| index | `his/complaint/index` | `his/complaint/index.vue` |
+| index | `his/coupon/index` | `his/coupon/index.vue` |
+| index | `his/department/index` | `his/department/index.vue` |
+| index | `his/dfAccount/index` | `his/dfAccount/index.vue` |
+| index | `his/disease/index` | `his/disease/index.vue` |
+| index | `his/divItem/index` | `his/divItem/index.vue` |
+| index | `his/doctor/index` | `his/doctor/index.vue` |
+| index | `his/doctor/index` | `his/doctor/index/index.vue` |
+| index | `his/doctorArticle/index` | `his/doctorArticle/index.vue` |
+| index | `his/doctorArticleCate/index` | `his/doctorArticleCate/index.vue` |
+| index | `his/doctorBill/index` | `his/doctorBill/index.vue` |
+| index | `his/doctorBill/index` | `his/doctorBill/index/index.vue` |
+| index | `his/doctorExtract/index` | `his/doctorExtract/index.vue` |
+| index | `his/doctorExtract/index` | `his/doctorExtract/index/index.vue` |
+| index | `his/doctorOperLog/index` | `his/doctorOperLog/index.vue` |
+| index | `his/doctorOperLog/index` | `his/doctorOperLog/index/index.vue` |
+| index | `his/doctorProduct/index` | `his/doctorProduct/index.vue` |
+| index | `his/doctorProduct/index` | `his/doctorProduct/index/index.vue` |
+| index | `his/drugReport/index` | `his/drugReport/index.vue` |
+| index | `his/drugReportCount/index` | `his/drugReportCount/index.vue` |
+| index | `his/exportTask/index` | `his/exportTask/index.vue` |
+| index | `his/express/index` | `his/express/index.vue` |
+| index | `his/famousPrescribe/index` | `his/famousPrescribe/index.vue` |
+| index | `his/follow/index` | `his/follow/index.vue` |
+| index | `his/followReport/index` | `his/followReport/index.vue` |
+| index | `his/followTemp/index` | `his/followTemp/index.vue` |
+| index | `his/fsFirstDiagnosis/index` | `his/fsFirstDiagnosis/index.vue` |
+| index | `his/healthArticle/index` | `his/healthArticle/index.vue` |
+| index | `his/healthArticle/index` | `his/healthArticle/index/index.vue` |
+| index | `his/healthData/index` | `his/healthData/index.vue` |
+| index | `his/healthHistoryTemp/index` | `his/healthHistoryTemp/index.vue` |
+| index | `his/healthLife/index` | `his/healthLife/index.vue` |
+| index | `his/healthRecord/index` | `his/healthRecord/index.vue` |
+| index | `his/healthTongue/index` | `his/healthTongue/index.vue` |
+| index | `his/hfpayConfig/index` | `his/hfpayConfig/index.vue` |
+| index | `his/homeArticle/index` | `his/homeArticle/index.vue` |
+| index | `his/homeCategory/index` | `his/homeCategory/index.vue` |
+| index | `his/homeView/index` | `his/homeView/index.vue` |
+| index | `his/hospital/index` | `his/hospital/index.vue` |
+| index | `his/icd/index` | `his/icd/index.vue` |
+| index | `his/illnessLibrary/index` | `his/illnessLibrary/index.vue` |
+| index | `his/inquiryDisease/index` | `his/inquiryDisease/index.vue` |
+| order1 | `his/inquiryOrder/order1` | `his/inquiryOrder/order1.vue` |
+| index | `his/inquiryOrderPing/index` | `his/inquiryOrderPing/index.vue` |
+| index | `his/inquiryOrderReport/index` | `his/inquiryOrderReport/index.vue` |
+| index | `his/inquiryTemp/index` | `his/inquiryTemp/index.vue` |
+| index | `his/integralGoods/index` | `his/integralGoods/index.vue` |
+| index | `his/integralOrder/index` | `his/integralOrder/index.vue` |
+| index | `his/logs/index` | `his/logs/index.vue` |
+| index | `his/logs/index` | `his/logs/index/index.vue` |
+| index | `his/medicatedFood/index` | `his/medicatedFood/index.vue` |
+| index | `his/merchantAppConfig/index` | `his/merchantAppConfig/index.vue` |
+| index | `his/package/index` | `his/package/index.vue` |
+| index | `his/packageCate/index` | `his/packageCate/index.vue` |
+| index | `his/packageFavorite/index` | `his/packageFavorite/index.vue` |
+| index | `his/packageFavorite/index` | `his/packageFavorite/index/index.vue` |
+| index | `his/packageOrder/index` | `his/packageOrder/index.vue` |
+| index | `his/packageSolarTerm/index` | `his/packageSolarTerm/index.vue` |
+| index | `his/patient/index` | `his/patient/index.vue` |
+| index | `his/pharmacist/index` | `his/pharmacist/index.vue` |
+| index | `his/pharmacist/index` | `his/pharmacist/index/index.vue` |
+| index | `his/physicalReportTemplate/index` | `his/physicalReportTemplate/index.vue` |
+| index | `his/physicalReportTemplateField/index` | `his/physicalReportTemplateField/index.vue` |
+| index | `his/price/index` | `his/price/index.vue` |
+| index | `his/price/index` | `his/price/index/index.vue` |
+| index | `his/promotionActive/index` | `his/promotionActive/index.vue` |
+| index | `his/promotionActive/index` | `his/promotionActive/index/index.vue` |
+| index | `his/promotionActiveLog/index` | `his/promotionActiveLog/index.vue` |
+| index | `his/promotionActiveLog/index` | `his/promotionActiveLog/index/index.vue` |
+| index | `his/promotionalActive/index` | `his/promotionalActive/index.vue` |
+| index | `his/questions/index` | `his/questions/index.vue` |
+| index | `his/redPacketConfig/index` | `his/redPacketConfig/index.vue` |
+| index | `his/store/index` | `his/store/index.vue` |
+| index | `his/storeActivity/index` | `his/storeActivity/index.vue` |
+| index | `his/storeAfterSales/index` | `his/storeAfterSales/index.vue` |
+| index | `his/storeAfterSales/index` | `his/storeAfterSales/index/index.vue` |
+| index | `his/storeBill/index` | `his/storeBill/index.vue` |
+| index | `his/storeBill/index` | `his/storeBill/index/index.vue` |
+| index | `his/storeExtract/index` | `his/storeExtract/index.vue` |
+| index | `his/storeExtract/index` | `his/storeExtract/index/index.vue` |
+| index | `his/storeLog/index` | `his/storeLog/index.vue` |
+| index | `his/storeLog/index` | `his/storeLog/index/index.vue` |
+| order1 | `his/storeOrder/order1` | `his/storeOrder/order1.vue` |
+| index | `his/storePayment/index` | `his/storePayment/index.vue` |
+| index | `his/storeProduct/index` | `his/storeProduct/index.vue` |
+| index | `his/storeProductCategory/index` | `his/storeProductCategory/index.vue` |
+| index | `his/storeProductPackage/index` | `his/storeProductPackage/index.vue` |
+| index | `his/storeSubOrder/index` | `his/storeSubOrder/index.vue` |
+| index | `his/template/index` | `his/template/index.vue` |
+| index | `his/template/index` | `his/template/index/index.vue` |
+| index | `his/testReport/index` | `his/testReport/index.vue` |
+| index | `his/testTemp/index` | `his/testTemp/index.vue` |
+| index | `his/testTempItem/index` | `his/testTempItem/index.vue` |
+| index | `his/user/index` | `his/user/index.vue` |
+| index | `his/userAddress/index` | `his/userAddress/index.vue` |
+| index | `his/userAddress/index` | `his/userAddress/index/index.vue` |
+| index | `his/userBill/index` | `his/userBill/index.vue` |
+| index | `his/userBill/index` | `his/userBill/index/index.vue` |
+| index | `his/userCoupon/index` | `his/userCoupon/index.vue` |
+| index | `his/userExtract/index` | `his/userExtract/index.vue` |
+| index | `his/userExtract/index` | `his/userExtract/index/index.vue` |
+| index | `his/userIntegralLogs/index` | `his/userIntegralLogs/index.vue` |
+| index | `his/userNewTask/index` | `his/userNewTask/index.vue` |
+| index | `his/userNewTask/index` | `his/userNewTask/index/index.vue` |
+| index | `his/userOnlineState/index` | `his/userOnlineState/index.vue` |
+| index | `his/userOperationLog/index` | `his/userOperationLog/index.vue` |
+| index | `his/userOperationLog/index` | `his/userOperationLog/index/index.vue` |
+| index | `his/userRecharge/index` | `his/userRecharge/index.vue` |
+| index | `his/vessel/index` | `his/vessel/index.vue` |
+
+### 4.5 直播 (`live/`) — 58 页
+
+建议路由前缀:`/live`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `live/gift/index` | `live/gift/index.vue` |
+| index | `live/healthLiveOrder/index` | `live/healthLiveOrder/index.vue` |
+| index | `live/healthLiveOrder/index` | `live/healthLiveOrder/index/index.vue` |
+| index | `live/index` | `live/index/index.vue` |
+| index | `live/issue/index` | `live/issue/index.vue` |
+| index | `live/issue/index` | `live/issue/index/index.vue` |
+| index | `live/live/index` | `live/live/index.vue` |
+| index | `live/liveAfterSales/index` | `live/liveAfterSales/index.vue` |
+| index | `live/liveAfterSales/index` | `live/liveAfterSales/index/index.vue` |
+| index | `live/liveAfterSalesItem/index` | `live/liveAfterSalesItem/index.vue` |
+| index | `live/liveAfterSalesLogs/index` | `live/liveAfterSalesLogs/index.vue` |
+| index | `live/liveAfteraSales/index` | `live/liveAfteraSales/index.vue` |
+| index | `live/liveAnchor/index` | `live/liveAnchor/index.vue` |
+| index | `live/liveConfig/index` | `live/liveConfig/index.vue` |
+| index | `live/liveConsole/index` | `live/liveConsole/index.vue` |
+| index | `live/liveCoupon/index` | `live/liveCoupon/index.vue` |
+| index | `live/liveCouponIssue/index` | `live/liveCouponIssue/index.vue` |
+| index | `live/liveCouponIssueUser/index` | `live/liveCouponIssueUser/index.vue` |
+| index | `live/liveCouponUser/index` | `live/liveCouponUser/index.vue` |
+| index | `live/liveData/index` | `live/liveData/index.vue` |
+| index | `live/liveEventConf/index` | `live/liveEventConf/index.vue` |
+| index | `live/liveGoods/index` | `live/liveGoods/index.vue` |
+| index | `live/liveLotteryConf/index` | `live/liveLotteryConf/index.vue` |
+| index | `live/liveLotteryProductConf/index` | `live/liveLotteryProductConf/index.vue` |
+| index | `live/liveLotteryRecord/index` | `live/liveLotteryRecord/index.vue` |
+| index | `live/liveLotteryRegistration/index` | `live/liveLotteryRegistration/index.vue` |
+| index | `live/liveMiniLives/index` | `live/liveMiniLives/index.vue` |
+| index | `live/liveMsg/index` | `live/liveMsg/index.vue` |
+| index | `live/liveOrder/index` | `live/liveOrder/index.vue` |
+| index | `live/liveOrderLogs/index` | `live/liveOrderLogs/index.vue` |
+| index | `live/liveOrderStatus/index` | `live/liveOrderStatus/index.vue` |
+| index | `live/liveOrderitems/index` | `live/liveOrderitems/index.vue` |
+| index | `live/liveProfit/index` | `live/liveProfit/index.vue` |
+| index | `live/liveQuestion/index` | `live/liveQuestion/index.vue` |
+| index | `live/liveQuestionBank/index` | `live/liveQuestionBank/index.vue` |
+| index | `live/liveRedConf/index` | `live/liveRedConf/index.vue` |
+| index | `live/liveRewardRecord/index` | `live/liveRewardRecord/index.vue` |
+| index | `live/liveTrafficLog/index` | `live/liveTrafficLog/index.vue` |
+| index | `live/liveUserFavorite/index` | `live/liveUserFavorite/index.vue` |
+| index | `live/liveUserFavorite/index` | `live/liveUserFavorite/index/index.vue` |
+| index | `live/liveUserFollow/index` | `live/liveUserFollow/index.vue` |
+| index | `live/liveUserFollow/index` | `live/liveUserFollow/index/index.vue` |
+| index | `live/liveUserLike/index` | `live/liveUserLike/index.vue` |
+| index | `live/liveUserLike/index` | `live/liveUserLike/index/index.vue` |
+| index | `live/liveUserLotteryRecord/index` | `live/liveUserLotteryRecord/index.vue` |
+| index | `live/liveUserRedRecord/index` | `live/liveUserRedRecord/index.vue` |
+| index | `live/liveVideo/index` | `live/liveVideo/index.vue` |
+| index | `live/liveWatchLog/index` | `live/liveWatchLog/index.vue` |
+| index | `live/liveWatchUser/index` | `live/liveWatchUser/index.vue` |
+| index | `live/order/index` | `live/order/index.vue` |
+| index | `live/record/index` | `live/record/index.vue` |
+| index | `live/record/index` | `live/record/index/index.vue` |
+| index | `live/talentLiveInfo/index` | `live/talentLiveInfo/index.vue` |
+| index | `live/task/index` | `live/task/index.vue` |
+| index | `live/task/index` | `live/task/index/index.vue` |
+| index | `live/trafficLog/index` | `live/trafficLog/index.vue` |
+| index | `live/trafficLog/index` | `live/trafficLog/index/index.vue` |
+| index | `live/words/index` | `live/words/index.vue` |
+
+### 4.6 课程 (`course/`) — 75 页
+
+建议路由前缀:`/course`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `course/Material/index` | `course/Material/index.vue` |
+| index | `course/courseAnswerLog/index` | `course/courseAnswerLog/index.vue` |
+| index | `course/courseAnswerLog/index` | `course/courseAnswerLog/index/index.vue` |
+| index | `course/courseAnswerlogs/index` | `course/courseAnswerlogs/index.vue` |
+| index | `course/courseDomainName/index` | `course/courseDomainName/index.vue` |
+| index | `course/courseFinishTemp/index` | `course/courseFinishTemp/index.vue` |
+| index | `course/courseFinishTempParent/index` | `course/courseFinishTempParent/index.vue` |
+| index | `course/courseLink/index` | `course/courseLink/index.vue` |
+| index | `course/coursePlaySourceConfig/index` | `course/coursePlaySourceConfig/index.vue` |
+| index | `course/courseQuestionBank/index` | `course/courseQuestionBank/index.vue` |
+| index | `course/courseQuestionCategory/index` | `course/courseQuestionCategory/index.vue` |
+| index | `course/courseQuestionCategory/index` | `course/courseQuestionCategory/index/index.vue` |
+| index | `course/courseRedPacketLog/index` | `course/courseRedPacketLog/index.vue` |
+| index | `course/courseRedPacketStatistics/index` | `course/courseRedPacketStatistics/index.vue` |
+| index | `course/courseTrafficLog/index` | `course/courseTrafficLog/index.vue` |
+| index | `course/courseUserStatistics/index` | `course/courseUserStatistics/index.vue` |
+| index | `course/courseUserStatistics/qw/index` | `course/courseUserStatistics/qw/index.vue` |
+| index | `course/courseWatchComment/index` | `course/courseWatchComment/index.vue` |
+| index | `course/courseWatchLog/index` | `course/courseWatchLog/index.vue` |
+| index | `course/courseWatchLog/qw/index` | `course/courseWatchLog/qw/index.vue` |
+| index | `course/fsCourseProduct/index` | `course/fsCourseProduct/index.vue` |
+| index | `course/fsCourseProductOrder/index` | `course/fsCourseProductOrder/index.vue` |
+| index | `course/huaweiCloudStatistics/index` | `course/huaweiCloudStatistics/index.vue` |
+| index | `course/index` | `course/index/index.vue` |
+| index | `course/period/index` | `course/period/index.vue` |
+| index | `course/period/index` | `course/period/index/index.vue` |
+| index | `course/playSourceConfig/index` | `course/playSourceConfig/index.vue` |
+| index | `course/playSourceConfig/index` | `course/playSourceConfig/index/index.vue` |
+| index | `course/push/index` | `course/push/index.vue` |
+| index | `course/sop/index` | `course/sop/index.vue` |
+| index | `course/sopLogs/index` | `course/sopLogs/index.vue` |
+| index | `course/sopLogs/index` | `course/sopLogs/index/index.vue` |
+| index | `course/statistics/index` | `course/statistics/index.vue` |
+| index | `course/trainingCamp/index` | `course/trainingCamp/index.vue` |
+| index | `course/trainingCamp/index` | `course/trainingCamp/index/index.vue` |
+| index | `course/userCourse/index` | `course/userCourse/index.vue` |
+| index | `course/userCourseCategory/index` | `course/userCourseCategory/index.vue` |
+| index | `course/userCourseComment/index` | `course/userCourseComment/index.vue` |
+| index | `course/userCourseCommentLike/index` | `course/userCourseCommentLike/index.vue` |
+| index | `course/userCourseCommentLike/index` | `course/userCourseCommentLike/index/index.vue` |
+| index | `course/userCourseComplaintRecord/index` | `course/userCourseComplaintRecord/index.vue` |
+| index | `course/userCourseComplaintType/index` | `course/userCourseComplaintType/index.vue` |
+| index | `course/userCourseFavorite/index` | `course/userCourseFavorite/index.vue` |
+| index | `course/userCourseFavorite/index` | `course/userCourseFavorite/index/index.vue` |
+| index | `course/userCourseNote/index` | `course/userCourseNote/index.vue` |
+| index | `course/userCourseNoteLike/index` | `course/userCourseNoteLike/index.vue` |
+| index | `course/userCourseNoteLike/index` | `course/userCourseNoteLike/index/index.vue` |
+| index | `course/userCourseOrder/index` | `course/userCourseOrder/index.vue` |
+| index | `course/userCoursePeriod/index` | `course/userCoursePeriod/index.vue` |
+| index | `course/userCourseStudy/index` | `course/userCourseStudy/index.vue` |
+| index | `course/userCourseStudyLog/index` | `course/userCourseStudyLog/index.vue` |
+| index | `course/userCourseVideo/index` | `course/userCourseVideo/index.vue` |
+| index | `course/userCourseVideo/index` | `course/userCourseVideo/index/index.vue` |
+| index | `course/userTalent/index` | `course/userTalent/index.vue` |
+| index | `course/userTalentFollow/index` | `course/userTalentFollow/index.vue` |
+| index | `course/userTalentFollow/index` | `course/userTalentFollow/index/index.vue` |
+| index | `course/userVideo/index` | `course/userVideo/index.vue` |
+| index | `course/userVideoComment/index` | `course/userVideoComment/index.vue` |
+| index | `course/userVideoCommentLike/index` | `course/userVideoCommentLike/index.vue` |
+| index | `course/userVideoCommentLike/index` | `course/userVideoCommentLike/index/index.vue` |
+| index | `course/userVideoFavorite/index` | `course/userVideoFavorite/index.vue` |
+| index | `course/userVideoFavorite/index` | `course/userVideoFavorite/index/index.vue` |
+| index | `course/userVideoLike/index` | `course/userVideoLike/index.vue` |
+| index | `course/userVideoLike/index` | `course/userVideoLike/index/index.vue` |
+| index | `course/userVideoTags/index` | `course/userVideoTags/index.vue` |
+| index | `course/userVideoView/index` | `course/userVideoView/index.vue` |
+| index | `course/userVideoView/index` | `course/userVideoView/index/index.vue` |
+| index | `course/userVipOrder/index` | `course/userVipOrder/index.vue` |
+| index | `course/userVipPackage/index` | `course/userVipPackage/index.vue` |
+| index | `course/userWatchCourseStatistics/index` | `course/userWatchCourseStatistics/index.vue` |
+| index | `course/userWatchCourseTotalStatistics/index` | `course/userWatchCourseTotalStatistics/index.vue` |
+| index | `course/userWatchStatistics/index` | `course/userWatchStatistics/index.vue` |
+| index | `course/videoResource/index` | `course/videoResource/index.vue` |
+| index | `course/videoTags/index` | `course/videoTags/index.vue` |
+| index | `course/videoTags/index` | `course/videoTags/index/index.vue` |
+
+### 4.7 AI (`fastGpt/`) — 31 页
+
+建议路由前缀:`/fastGpt`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `FastGptExtUserTag/index` | `FastGptExtUserTag/index.vue` |
+| index | `FastGptExtUserTag/index` | `FastGptExtUserTag/index/index.vue` |
+| index | `aiob/AiobBaiduCallApi/index` | `aiob/AiobBaiduCallApi/index.vue` |
+| index | `aiob/AiobBaiduEncryption/index` | `aiob/AiobBaiduEncryption/index.vue` |
+| index | `aiob/AiobBaiduTask/index` | `aiob/AiobBaiduTask/index.vue` |
+| index | `chat/chatDataset/index` | `chat/chatDataset/index.vue` |
+| index | `chat/chatDatasetFile/index` | `chat/chatDatasetFile/index.vue` |
+| index | `chat/chatKeyword/index` | `chat/chatKeyword/index.vue` |
+| index | `chat/chatMsg/index` | `chat/chatMsg/index.vue` |
+| index | `chat/chatMsgLogs/index` | `chat/chatMsgLogs/index.vue` |
+| index | `chat/chatRole/index` | `chat/chatRole/index.vue` |
+| index | `chat/chatSession/index` | `chat/chatSession/index.vue` |
+| index | `chat/chatUser/index` | `chat/chatUser/index.vue` |
+| index | `fastGpt/fastGptChatKeyword/index` | `fastGpt/fastGptChatKeyword/index.vue` |
+| index | `fastGpt/fastGptChatMsg/index` | `fastGpt/fastGptChatMsg/index.vue` |
+| index | `fastGpt/fastGptChatMsgLogs/index` | `fastGpt/fastGptChatMsgLogs/index.vue` |
+| index | `fastGpt/fastGptChatReplaceText/index` | `fastGpt/fastGptChatReplaceText/index.vue` |
+| index | `fastGpt/fastGptChatReplaceWords/index` | `fastGpt/fastGptChatReplaceWords/index.vue` |
+| index | `fastGpt/fastGptChatSession/index` | `fastGpt/fastGptChatSession/index.vue` |
+| index | `fastGpt/fastGptCollection/index` | `fastGpt/fastGptCollection/index.vue` |
+| index | `fastGpt/fastGptCollentionData/index` | `fastGpt/fastGptCollentionData/index.vue` |
+| index | `fastGpt/fastGptDataset/index` | `fastGpt/fastGptDataset/index.vue` |
+| index | `fastGpt/fastGptExtUserTag/index` | `fastGpt/fastGptExtUserTag/index.vue` |
+| index | `fastGpt/fastGptKeywordSend/index` | `fastGpt/fastGptKeywordSend/index.vue` |
+| index | `fastGpt/fastGptPushTokenTotal/index` | `fastGpt/fastGptPushTokenTotal/index.vue` |
+| index | `fastGpt/fastGptPushTokenTotalDept/index` | `fastGpt/fastGptPushTokenTotalDept/index.vue` |
+| index | `fastGpt/fastGptRole/index` | `fastGpt/fastGptRole/index.vue` |
+| index | `fastGpt/fastGptRoleTag/index` | `fastGpt/fastGptRoleTag/index.vue` |
+| index | `fastGpt/fastGptUser/index` | `fastGpt/fastGptUser/index.vue` |
+| index | `fastGpt/fastgptChatArtificialWords/index` | `fastGpt/fastgptChatArtificialWords/index.vue` |
+| index | `fastGpt/fastgptEventLogTotal/index` | `fastGpt/fastgptEventLogTotal/index.vue` |
+
+### 4.8 企业/组织 (`company/`) — 52 页
+
+建议路由前缀:`/company`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `company/VoiceRoboticWx/index` | `company/VoiceRoboticWx/index.vue` |
+| index | `company/aiModel/index` | `company/aiModel/index.vue` |
+| index | `company/aiModel/voiceClone/index` | `company/aiModel/voiceClone/index.vue` |
+| index | `company/aiWorkflow/index` | `company/aiWorkflow/index.vue` |
+| index | `company/company/index` | `company/company/index.vue` |
+| index | `company/companyApply/index` | `company/companyApply/index.vue` |
+| index | `company/companyBindUser/index` | `company/companyBindUser/index.vue` |
+| index | `company/companyClient/index` | `company/companyClient/index.vue` |
+| index | `company/companyConfig/index` | `company/companyConfig/index.vue` |
+| index | `company/companyDeduct/index` | `company/companyDeduct/index.vue` |
+| index | `company/companyDept/index` | `company/companyDept/index.vue` |
+| index | `company/companyDomain/index` | `company/companyDomain/index.vue` |
+| index | `company/companyDomainBind/index` | `company/companyDomainBind/index.vue` |
+| index | `company/companyLogininfor/index` | `company/companyLogininfor/index.vue` |
+| index | `company/companyMenu/index` | `company/companyMenu/index.vue` |
+| index | `company/companyMoneyLogs/index` | `company/companyMoneyLogs/index.vue` |
+| index | `company/companyOperLog/index` | `company/companyOperLog/index.vue` |
+| index | `company/companyPost/index` | `company/companyPost/index.vue` |
+| index | `company/companyProfit/index` | `company/companyProfit/index.vue` |
+| index | `company/companyRecharge/index` | `company/companyRecharge/index.vue` |
+| index | `company/companyRedPacketBalanceLogs/index` | `company/companyRedPacketBalanceLogs/index.vue` |
+| index | `company/companyRole/index` | `company/companyRole/index.vue` |
+| index | `company/companyRoleDept/index` | `company/companyRoleDept/index.vue` |
+| index | `company/companyRoleMenu/index` | `company/companyRoleMenu/index.vue` |
+| index | `company/companySms/index` | `company/companySms/index.vue` |
+| index | `company/companySmsLogs/index` | `company/companySmsLogs/index.vue` |
+| index | `company/companySmsOrder/index` | `company/companySmsOrder/index.vue` |
+| index | `company/companySmsPackage/index` | `company/companySmsPackage/index.vue` |
+| index | `company/companySmsTemp/index` | `company/companySmsTemp/index.vue` |
+| index | `company/companyTraffic/index` | `company/companyTraffic/index.vue` |
+| index | `company/companyTrafficLog/index` | `company/companyTrafficLog/index.vue` |
+| index | `company/companyUser/index` | `company/companyUser/index.vue` |
+| index | `company/companyUserPost/index` | `company/companyUserPost/index.vue` |
+| index | `company/companyUserRole/index` | `company/companyUserRole/index.vue` |
+| index | `company/companyVoice/index` | `company/companyVoice/index.vue` |
+| index | `company/companyVoiceApi/index` | `company/companyVoiceApi/index.vue` |
+| index | `company/companyVoiceBlacklist/index` | `company/companyVoiceBlacklist/index.vue` |
+| index | `company/companyVoiceCaller/index` | `company/companyVoiceCaller/index.vue` |
+| index | `company/companyVoiceConfig/index` | `company/companyVoiceConfig/index.vue` |
+| index | `company/companyVoiceDialog/index` | `company/companyVoiceDialog/index.vue` |
+| index | `company/companyVoiceLogs/index` | `company/companyVoiceLogs/index.vue` |
+| index | `company/companyVoiceMobile/index` | `company/companyVoiceMobile/index.vue` |
+| index | `company/companyVoicePackage/index` | `company/companyVoicePackage/index.vue` |
+| index | `company/companyVoicePackageOrder/index` | `company/companyVoicePackageOrder/index.vue` |
+| index | `company/companyVoiceRobotic/index` | `company/companyVoiceRobotic/index.vue` |
+| index | `company/companyWorkflow/index` | `company/companyWorkflow/index.vue` |
+| index | `company/tcmScheduleReport/index` | `company/tcmScheduleReport/index.vue` |
+| index | `company/workflowExternalApi/index` | `company/workflowExternalApi/index.vue` |
+| index | `company/workflowLobster/index` | `company/workflowLobster/index.vue` |
+| index | `company/wxAccount/index` | `company/wxAccount/index.vue` |
+| index | `company/wxDialog/index` | `company/wxDialog/index.vue` |
+| index | `company/wxUser/index` | `company/wxUser/index.vue` |
+
+### 4.9 系统 (`system/`) — 18 页
+
+建议路由前缀:`/system`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `system/companyVoiceDialog/index` | `system/companyVoiceDialog/index.vue` |
+| index | `system/companyVoiceDialog/index` | `system/companyVoiceDialog/index/index.vue` |
+| index | `system/companyVoiceRobotic/index` | `system/companyVoiceRobotic/index.vue` |
+| index | `system/companyVoiceRobotic/index` | `system/companyVoiceRobotic/index/index.vue` |
+| index | `system/companyVoiceRoboticCallees/index` | `system/companyVoiceRoboticCallees/index.vue` |
+| index | `system/companyVoiceRoboticCallees/index` | `system/companyVoiceRoboticCallees/index/index.vue` |
+| index | `system/config/index` | `system/config/index.vue` |
+| index | `system/dept/index` | `system/dept/index.vue` |
+| index | `system/dict/index` | `system/dict/index.vue` |
+| index | `system/keyword/index` | `system/keyword/index.vue` |
+| index | `system/menu/index` | `system/menu/index.vue` |
+| index | `system/notice/index` | `system/notice/index.vue` |
+| index | `system/post/index` | `system/post/index.vue` |
+| index | `system/role/index` | `system/role/index.vue` |
+| index | `system/set/index` | `system/set/index.vue` |
+| index | `system/set/index` | `system/set/index/index.vue` |
+| index | `system/user/index` | `system/user/index.vue` |
+| index | `system/user/profile/index` | `system/user/profile/index.vue` |
+
+### 4.10 龙虾 (`lobster/`) — 13 页
+
+建议路由前缀:`/lobster`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `lobster/api-registry/index` | `lobster/api-registry/index.vue` |
+| index | `lobster/billing/index` | `lobster/billing/index.vue` |
+| index | `lobster/chat-aggregate/index` | `lobster/chat-aggregate/index.vue` |
+| index | `lobster/dead-letter/index` | `lobster/dead-letter/index.vue` |
+| index | `lobster/event-audit/index` | `lobster/event-audit/index.vue` |
+| index | `lobster/instance/index` | `lobster/instance/index.vue` |
+| index | `lobster/model-config/index` | `lobster/model-config/index.vue` |
+| index | `lobster/optimization/index` | `lobster/optimization/index.vue` |
+| index | `lobster/prompt/index` | `lobster/prompt/index.vue` |
+| index | `lobster/sales-corpus/index` | `lobster/sales-corpus/index.vue` |
+| index | `lobster/template/index` | `lobster/template/index.vue` |
+| index | `lobster/workflow-canvas/index` | `lobster/workflow-canvas/index.vue` |
+| index | `lobster/workflow-generate/index` | `lobster/workflow-generate/index.vue` |
+
+### 4.11 广告 (`adv/`) — 13 页
+
+建议路由前缀:`/ad`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `adv/advertiser/index` | `adv/advertiser/index.vue` |
+| index | `adv/callbackAccount/index` | `adv/callbackAccount/index.vue` |
+| index | `adv/channel/index` | `adv/channel/index.vue` |
+| index | `adv/configuration/index` | `adv/configuration/index.vue` |
+| index | `adv/conversionLog/index` | `adv/conversionLog/index.vue` |
+| index | `adv/customPromotionAccount/index` | `adv/customPromotionAccount/index.vue` |
+| index | `adv/domain/index` | `adv/domain/index.vue` |
+| index | `adv/landingPageTemplate/index` | `adv/landingPageTemplate/index.vue` |
+| index | `adv/project/index` | `adv/project/index.vue` |
+| index | `adv/promotionAccount/index` | `adv/promotionAccount/index.vue` |
+| index | `adv/site/index` | `adv/site/index.vue` |
+| index | `adv/statistics/index` | `adv/statistics/index.vue` |
+| index | `adv/trackingLink/index` | `adv/trackingLink/index.vue` |
+
+### 4.12 微信 (`wx/`) — 4 页
+
+建议路由前缀:`/wx`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `wx/wxSop/index` | `wx/wxSop/index.vue` |
+| index | `wx/wxSopLogs/index` | `wx/wxSopLogs/index.vue` |
+| index | `wx/wxSopUser/index` | `wx/wxSopUser/index.vue` |
+| index | `wx/wxSopUserInfo/index` | `wx/wxSopUserInfo/index.vue` |
+
+### 4.13 监控 (`monitor/`) — 9 页
+
+建议路由前缀:`/monitor`
+
+#### 通用/待分组
+
+| 建议 menu_name | component | 源文件 |
+|--------------|-----------|--------|
+| index | `monitor/cache/index` | `monitor/cache/index.vue` |
+| index | `monitor/componentsOperLog/index` | `monitor/componentsOperLog/index.vue` |
+| index | `monitor/doctorOperLog/index` | `monitor/doctorOperLog/index.vue` |
+| index | `monitor/druid/index` | `monitor/druid/index.vue` |
+| index | `monitor/job/index` | `monitor/job/index.vue` |
+| index | `monitor/logininfor/index` | `monitor/logininfor/index.vue` |
+| index | `monitor/online/index` | `monitor/online/index.vue` |
+| index | `monitor/operlog/index` | `monitor/operlog/index.vue` |
+| index | `monitor/server/index` | `monitor/server/index.vue` |
+
+---
+
+## 五、重复/遗留模块合并建议
+
+| 组 | 目录 | 建议 |
+|------|------|------|
+| 商城 | `store/` vs `hisStore/` | 保留 store,hisStore 放其他 |
+| 商城 | `store/` vs `his/store*` | his 内嵌套页留在诊所模块 |
+| 会员 | `user/` `users/` `member/` | 合并为 member 顶栏 |
+| AI | `fastGpt/` `chat/` `aiob/` | 合并为 fastGpt |
+| 广告 | `adv/` `ad/` | 统一 adv |
+| 微信 | `wx/` `gw/` | gwAccount 归入 wx |
+| 统计 | `statistics/` `taskStatistics/` | 合并 statistics |
+| 监控 | `monitor/` `watch/` | 合并 watch |
+| 用户 | `system/user` vs `sysUser/` | sysUser 仅总后台 |
+
+---
+
+## 六、完整一级目录扫描表
+
+| views 一级目录 | 可路由页面数 | 归类 |
+|----------------|-------------|------|
+| `FastGptExtUserTag/` | 2 | 租户 — AI聊天 |
+| `ad/` | 12 | 租户 — 广告投放 |
+| `addressBook/` | 1 | 待确认 |
+| `admin/` | 60 | 平台/其他 |
+| `adv/` | 13 | 租户 — 广告投放 |
+| `aiSipCall/` | 9 | 平台/其他 |
+| `aiob/` | 3 | 租户 — AI聊天 |
+| `baidu/` | 1 | 平台/其他 |
+| `bill/` | 1 | 租户 — 财务管理 |
+| `billing/` | 1 | 租户 — 财务管理 |
+| `calendar/` | 1 | 租户 — 日程管理 |
+| `callRecord/` | 2 | 平台/其他 |
+| `chat/` | 8 | 租户 — AI聊天 |
+| `company/` | 52 | 租户 — 系统管理 |
+| `course/` | 75 | 租户 — 课程管理 |
+| `courseFinishTemp/` | 2 | 租户 — 课程管理 |
+| `crm/` | 13 | 租户 — CRM客户 |
+| `customer/` | 1 | 待确认 |
+| `fastGpt/` | 18 | 租户 — AI聊天 |
+| `food/` | 1 | 平台/其他 |
+| `gw/` | 1 | 租户 — 微信管理 |
+| `his/` | 135 | 租户 — 诊所管理 |
+| `hisStore/` | 54 | 平台/其他 |
+| `index.vue/` | 1 | 待确认 |
+| `live/` | 58 | 租户 — 直播管理 |
+| `liveData/` | 2 | 租户 — 直播管理 |
+| `lobster/` | 13 | 租户 — 龙虹引擎 |
+| `medical/` | 4 | 平台/其他 |
+| `member/` | 9 | 租户 — 会员管理 |
+| `moduleUsage/` | 2 | 租户 — 数据统计 |
+| `monitor/` | 9 | 租户 — 监控管理 |
+| `operation/` | 1 | 平台/其他 |
+| `qw/` | 72 | 租户 — 企微管理 |
+| `qwExternalContact/` | 1 | 租户 — 企微管理 |
+| `saas/` | 11 | 平台/其他 |
+| `saler/` | 2 | 平台/其他 |
+| `shop/` | 6 | 平台/其他 |
+| `sop/` | 1 | 待确认 |
+| `statistics/` | 4 | 租户 — 数据统计 |
+| `store/` | 114 | 租户 — 商城管理 |
+| `storeOrderOfflineItem/` | 2 | 平台/其他 |
+| `sysUser/` | 2 | 平台/其他 |
+| `system/` | 18 | 租户 — 系统管理 |
+| `taskStatistics/` | 3 | 租户 — 数据统计 |
+| `todo/` | 1 | 平台/其他 |
+| `tool/` | 3 | 租户 — 系统工具 |
+| `user/` | 8 | 租户 — 会员管理 |
+| `users/` | 3 | 租户 — 会员管理 |
+| `watch/` | 6 | 租户 — 监控管理 |
+| `wx/` | 4 | 租户 — 微信管理 |
+
+---
+
+## 七、本次不执行的落地步骤
+
+1. 评审本文档二级分组
+2. 导出 component 与 tenant_sys_menu diff
+3. 合并重复菜单
+4. 更新模板并同步租户库
+5. saasadminui 验证路由
+
+---
+
+*Generated by `sql/generate_adminUI_menu_doc.py`*

+ 48 - 0
sql/analyze_menu_issues.py

@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+"""Analyze tenant_sys_menu issues for full organize."""
+import pymysql
+from collections import defaultdict
+
+DB = dict(host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+          user='root', password='Ylrz_1q2w3e4r5t6y', database='ylrz_saas', charset='utf8mb4')
+
+conn = pymysql.connect(**DB)
+cur = conn.cursor(pymysql.cursors.DictCursor)
+cur.execute('SELECT * FROM tenant_sys_menu')
+rows = {r['menu_id']: r for r in cur.fetchall()}
+
+# path dup within parent (visible C/M only)
+dups = defaultdict(list)
+for r in rows.values():
+    if r['menu_type'] == 'F' or r['visible'] != '0':
+        continue
+    key = (r['parent_id'], r['path'] or '')
+    dups[key].append(r['menu_id'])
+
+print('PATH_DUPS (visible):')
+for k, ids in sorted(dups.items()):
+    if len(ids) > 1:
+        print(k, ids)
+
+# empty visible M nodes
+print('\nEMPTY_VISIBLE_M:')
+for r in rows.values():
+    if r['menu_type'] != 'M' or r['visible'] != '0':
+        continue
+    children = [x for x in rows.values() if x['parent_id'] == r['menu_id'] and x['menu_type'] != 'F']
+    if not children:
+        print(r['menu_id'], r['menu_name'], r['path'], 'parent', r['parent_id'])
+
+# platform components still visible
+print('\nBAD_VISIBLE:')
+for r in rows.values():
+    if r['visible'] != '0':
+        continue
+    comp = r.get('component') or ''
+    if comp.startswith('admin/') or comp.startswith('proxy/') or comp.startswith('saas/'):
+        print(r['menu_id'], comp)
+    if (r.get('path') or '') in ('tool', 'tenant', 'monitor') and r['menu_type'] == 'C':
+        print('path', r['menu_id'], r['path'], comp)
+
+cur.close()
+conn.close()

+ 31 - 0
sql/check_archive.py

@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+cur.execute('SELECT MAX(menu_id) FROM tenant_sys_menu')
+print('max_id', cur.fetchone()[0])
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=32333')
+print('direct under 32333', cur.fetchone()[0])
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, visible, menu_type "
+    "FROM tenant_sys_menu WHERE menu_id=32333"
+)
+print('32333', cur.fetchone())
+cur.execute(
+    "SELECT COUNT(*) FROM tenant_sys_menu WHERE visible='1' AND menu_type='M' AND parent_id=0"
+)
+print('hidden root M', cur.fetchone()[0])
+cur.execute('SELECT menu_id FROM tenant_sys_menu WHERE menu_id=35300')
+print('35300 exists', cur.fetchone())
+cur.close()
+c.close()

+ 46 - 0
sql/check_menu_detail.py

@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+
+print('=== system direct children count by visible ===')
+cur.execute(
+    "SELECT visible, COUNT(*) FROM tenant_sys_menu WHERE parent_id=32372 "
+    "AND menu_type<>'F' GROUP BY visible"
+)
+print(cur.fetchall())
+
+print('\n=== system visible direct children (should be 35100-35106 only) ===')
+cur.execute(
+    "SELECT menu_id, menu_name, order_num, path, visible "
+    "FROM tenant_sys_menu WHERE parent_id=32372 AND visible='0' "
+    "ORDER BY order_num, menu_id"
+)
+for r in cur.fetchall():
+    print(r)
+
+print('\n=== secondary groups under qw (32361) ===')
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, order_num, path, visible "
+    "FROM tenant_sys_menu WHERE parent_id=32361 OR menu_id=32361 "
+    "ORDER BY parent_id, order_num LIMIT 20"
+)
+for r in cur.fetchall():
+    print(r)
+
+print('\n=== path m-prefix count (broken by post_process) ===')
+cur.execute("SELECT COUNT(*) FROM tenant_sys_menu WHERE path LIKE 'm%' AND menu_type='M'")
+print(cur.fetchone()[0])
+
+cur.close()
+c.close()

+ 60 - 0
sql/check_menu_state.py

@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+
+print('=== ROOT MENUS (parent_id=0, menu_type=M) ===')
+cur.execute(
+    "SELECT menu_id, menu_name, order_num, path, visible, status "
+    "FROM tenant_sys_menu WHERE parent_id=0 AND menu_type='M' "
+    "ORDER BY order_num, menu_id"
+)
+for r in cur.fetchall():
+    print(r)
+
+print('\n=== visible roots (visible=0) ===')
+cur.execute(
+    "SELECT menu_id, menu_name, order_num, path "
+    "FROM tenant_sys_menu WHERE parent_id=0 AND menu_type='M' AND visible='0' "
+    "ORDER BY order_num"
+)
+for r in cur.fetchall():
+    print(r)
+
+print('\n=== stats ===')
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu')
+print('total', cur.fetchone()[0])
+
+cur.execute(
+    "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' "
+    "AND path IN ('admin','saas','proxy','tenant','monitor','tool','company')"
+)
+print('bad platform visible roots', cur.fetchone()[0])
+
+cur.execute(
+    "SELECT COUNT(*) FROM tenant_sys_menu WHERE component LIKE 'admin/%' AND visible='0'"
+)
+print('visible admin components', cur.fetchone()[0])
+
+# system subtree
+print('\n=== system (32372) children ===')
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, order_num, path, visible "
+    "FROM tenant_sys_menu WHERE parent_id=32372 OR menu_id=32372 "
+    "ORDER BY parent_id, order_num LIMIT 30"
+)
+for r in cur.fetchall():
+    print(r)
+
+cur.close()
+c.close()

+ 53 - 0
sql/check_other_children_visible.py

@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35300')
+print('direct children', cur.fetchone()[0])
+cur.execute(
+    "SELECT visible, COUNT(*) FROM tenant_sys_menu WHERE parent_id=35300 GROUP BY visible"
+)
+print('direct by visible', cur.fetchall())
+cur.execute(
+    "SELECT menu_id, menu_name, visible, menu_type FROM tenant_sys_menu "
+    "WHERE parent_id=35300 ORDER BY order_num LIMIT 8"
+)
+print('sample direct:')
+for r in cur.fetchall():
+    print(' ', r)
+
+# count all descendants visible status
+cur.execute('SELECT menu_id, parent_id FROM tenant_sys_menu')
+rows = cur.fetchall()
+children_map = {}
+for mid, pid in rows:
+    children_map.setdefault(pid, []).append(mid)
+menu_vis = {r[0]: r[1] for r in cur.execute('SELECT menu_id, visible FROM tenant_sys_menu') or []}
+cur.execute('SELECT menu_id, visible FROM tenant_sys_menu')
+menu_vis = dict(cur.fetchall())
+
+def descendants(root):
+    out = []
+    stack = list(children_map.get(root, []))
+    while stack:
+        mid = stack.pop()
+        out.append(mid)
+        stack.extend(children_map.get(mid, []))
+    return out
+
+desc = descendants(35300)
+vis0 = sum(1 for i in desc if menu_vis.get(i) == '0')
+vis1 = sum(1 for i in desc if menu_vis.get(i) == '1')
+print('total descendants', len(desc), 'visible=0', vis0, 'visible=1', vis1)
+cur.close()
+c.close()

+ 30 - 0
sql/compare_menu_bak.py

@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+conn = pymysql.connect(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+    user='root', password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas', charset='utf8mb4',
+)
+cur = conn.cursor()
+
+ids = [32431,32440,32704,32806,32591,32385,35106]
+for mid in ids:
+    cur.execute('SELECT menu_id, parent_id, visible FROM tenant_sys_menu WHERE menu_id=%s', (mid,))
+    cur_row = cur.fetchone()
+    cur.execute('SELECT menu_id, parent_id, visible FROM tenant_sys_menu_bak WHERE menu_id=%s', (mid,))
+    bak_row = cur.fetchone()
+    print(mid, 'current=', cur_row, 'backup=', bak_row)
+
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu_bak WHERE parent_id=35106 AND menu_type<>"F"')
+print('bak_35106_children', cur.fetchone()[0])
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35106 AND menu_type<>"F"')
+print('cur_35106_children', cur.fetchone()[0])
+
+cur.execute('SELECT menu_id FROM tenant_sys_menu_bak WHERE menu_id BETWEEN 32427 AND 32485 LIMIT 5')
+print('bak_company_sample', cur.fetchall())
+cur.execute('SELECT menu_id FROM tenant_sys_menu WHERE menu_id BETWEEN 32427 AND 32485 LIMIT 5')
+print('cur_company_sample', cur.fetchall())
+
+cur.close()
+conn.close()

+ 37 - 0
sql/compare_missing_ids.py

@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+conn = pymysql.connect(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+    user='root', password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas', charset='utf8mb4',
+)
+cur = conn.cursor()
+
+cur.execute('SELECT menu_id FROM tenant_sys_menu_bak')
+bak_ids = set(r[0] for r in cur.fetchall())
+cur.execute('SELECT menu_id FROM tenant_sys_menu')
+cur_ids = set(r[0] for r in cur.fetchall())
+
+missing = sorted(bak_ids - cur_ids)
+extra = sorted(cur_ids - bak_ids)
+print('missing_count', len(missing))
+print('extra_count', len(extra))
+print('missing_first20', missing[:20])
+print('missing_last20', missing[-20:])
+
+# check if missing are contiguous ranges
+if missing:
+    ranges = []
+    start = prev = missing[0]
+    for x in missing[1:]:
+        if x == prev + 1:
+            prev = x
+        else:
+            ranges.append((start, prev))
+            start = prev = x
+    ranges.append((start, prev))
+    print('missing_ranges_sample', ranges[:15], '... total_ranges', len(ranges))
+
+cur.close()
+conn.close()

+ 26 - 0
sql/find_qw_dup.py

@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+conn = pymysql.connect(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+    user='root', password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas', charset='utf8mb4',
+)
+cur = conn.cursor()
+cur.execute("""
+SELECT parent_id, path, GROUP_CONCAT(menu_id) ids, COUNT(*) cnt
+FROM tenant_sys_menu
+WHERE parent_id IN (35001,35002,35003,35004,35005,35006,35007)
+  AND menu_type <> 'F' AND visible='0'
+GROUP BY parent_id, path HAVING COUNT(*)>1
+""")
+rows = cur.fetchall()
+print('qw_dup:', rows)
+for r in rows:
+    ids = [int(x) for x in r[2].split(',')]
+    cur.execute('SELECT menu_id, menu_name, path, component FROM tenant_sys_menu WHERE menu_id IN (%s)' % ','.join(map(str, ids)))
+    for row in cur.fetchall():
+        print(' ', row)
+
+cur.close()
+conn.close()

+ 40 - 0
sql/fix_tenant_sys_menu_other_parent.sql

@@ -0,0 +1,40 @@
+-- Create visible top-level "????" parent and move archived hidden menus under it.
+-- Replaces hidden archive root 32333 as the grouping parent for maintenance UI.
+
+-- Ensure parent exists (idempotent; menu_name via Python post_process if re-run)
+INSERT INTO tenant_sys_menu
+(menu_id, menu_name, parent_id, order_num, path, component, query,
+ is_frame, is_cache, menu_type, visible, status, perms, icon,
+ create_by, create_time, remark)
+SELECT 35300, '????', 0, 17, 'other', NULL, NULL,
+       1, 0, 'M', '0', '0', NULL, 'more',
+       'admin', NOW(), '[organize:other-parent]'
+FROM DUAL
+WHERE NOT EXISTS (SELECT 1 FROM tenant_sys_menu WHERE menu_id = 35300);
+
+UPDATE tenant_sys_menu
+SET menu_name = '????', parent_id = 0, order_num = 17, path = 'other',
+    menu_type = 'M', visible = '0', status = '0', icon = 'more'
+WHERE menu_id = 35300;
+
+-- Move former platform archive children -> ????
+UPDATE tenant_sys_menu SET parent_id = 35300 WHERE parent_id = 32333;
+
+-- Keep legacy platform root hidden and empty (historical menu_id)
+UPDATE tenant_sys_menu
+SET parent_id = 0, visible = '1', status = '0', order_num = 99
+WHERE menu_id = 32333;
+
+-- Show entire subtree under ÆäËû (maintenance bucket; was hidden before grouping)
+UPDATE tenant_sys_menu
+SET visible = '0', status = '0'
+WHERE menu_id IN (
+  WITH RECURSIVE other_tree AS (
+    SELECT menu_id FROM tenant_sys_menu WHERE parent_id = 35300
+    UNION ALL
+    SELECT m.menu_id
+    FROM tenant_sys_menu m
+    INNER JOIN other_tree t ON m.parent_id = t.menu_id
+  )
+  SELECT menu_id FROM other_tree
+);

+ 109 - 0
sql/fix_tenant_sys_menu_paths.sql

@@ -0,0 +1,109 @@
+-- Restore directory (M) paths broken by post_process path dedup
+-- Run as part of organize pipeline AFTER subtree SQL
+
+UPDATE tenant_sys_menu SET path = 'index'       WHERE menu_id = 32644;
+UPDATE tenant_sys_menu SET path = 'qw'          WHERE menu_id = 32361;
+UPDATE tenant_sys_menu SET path = 'wx'          WHERE menu_id = 32380;
+UPDATE tenant_sys_menu SET path = 'crm'         WHERE menu_id = 32347;
+UPDATE tenant_sys_menu SET path = 'member'      WHERE menu_id = 32357;
+UPDATE tenant_sys_menu SET path = 'his'         WHERE menu_id = 32351;
+UPDATE tenant_sys_menu SET path = 'store'       WHERE menu_id = 32369;
+UPDATE tenant_sys_menu SET path = 'live'        WHERE menu_id = 32353;
+UPDATE tenant_sys_menu SET path = 'course'      WHERE menu_id = 32345;
+UPDATE tenant_sys_menu SET path = 'fastGpt'     WHERE menu_id = 32348;
+UPDATE tenant_sys_menu SET path = 'lobster'     WHERE menu_id = 32355;
+UPDATE tenant_sys_menu SET path = 'ad'          WHERE menu_id = 32331;
+UPDATE tenant_sys_menu SET path = 'system'      WHERE menu_id = 32372;
+UPDATE tenant_sys_menu SET path = 'bill'        WHERE menu_id = 32339;
+UPDATE tenant_sys_menu SET path = 'calendar'    WHERE menu_id = 32341;
+UPDATE tenant_sys_menu SET path = 'statistics'  WHERE menu_id = 32368;
+UPDATE tenant_sys_menu SET path = 'watch'       WHERE menu_id = 32379;
+
+-- system secondary groups
+UPDATE tenant_sys_menu SET path = 'sysOrg'      WHERE menu_id = 35100;
+UPDATE tenant_sys_menu SET path = 'sysPerm'     WHERE menu_id = 35101;
+UPDATE tenant_sys_menu SET path = 'sysVoice'    WHERE menu_id = 35102;
+UPDATE tenant_sys_menu SET path = 'sysLog'      WHERE menu_id = 35105;
+UPDATE tenant_sys_menu SET path = 'sysConfig'   WHERE menu_id = 35106;
+
+-- qw secondary groups
+UPDATE tenant_sys_menu SET path = 'qwMsg'       WHERE menu_id = 35001;
+UPDATE tenant_sys_menu SET path = 'qwCustomer'  WHERE menu_id = 35002;
+UPDATE tenant_sys_menu SET path = 'qwGroup'     WHERE menu_id = 35003;
+UPDATE tenant_sys_menu SET path = 'qwMoments'   WHERE menu_id = 35004;
+UPDATE tenant_sys_menu SET path = 'qwDrainage'  WHERE menu_id = 35005;
+UPDATE tenant_sys_menu SET path = 'qwTag'       WHERE menu_id = 35006;
+UPDATE tenant_sys_menu SET path = 'qwSetting'   WHERE menu_id = 35007;
+
+-- store secondary groups
+UPDATE tenant_sys_menu SET path = 'storeOrder'   WHERE menu_id = 35040;
+UPDATE tenant_sys_menu SET path = 'storeProduct' WHERE menu_id = 35041;
+UPDATE tenant_sys_menu SET path = 'storeOps'     WHERE menu_id = 35042;
+
+-- wx secondary groups
+UPDATE tenant_sys_menu SET path = 'wxAccount'  WHERE menu_id = 35010;
+UPDATE tenant_sys_menu SET path = 'wxDialog'   WHERE menu_id = 35011;
+UPDATE tenant_sys_menu SET path = 'wxUser'     WHERE menu_id = 35012;
+UPDATE tenant_sys_menu SET path = 'wxUserGroup' WHERE menu_id = 35013;
+
+-- crm / live / course / ai / bill / ad secondary groups
+UPDATE tenant_sys_menu SET path = 'crmCustomer'  WHERE menu_id = 35020;
+UPDATE tenant_sys_menu SET path = 'liveOps'      WHERE menu_id = 35050;
+UPDATE tenant_sys_menu SET path = 'courseContent' WHERE menu_id = 35060;
+UPDATE tenant_sys_menu SET path = 'aiChat'       WHERE menu_id = 35070;
+UPDATE tenant_sys_menu SET path = 'lobsterFlow'  WHERE menu_id = 35080;
+UPDATE tenant_sys_menu SET path = 'adOps'        WHERE menu_id = 35090;
+UPDATE tenant_sys_menu SET path = 'billRecharge' WHERE menu_id = 35111;
+UPDATE tenant_sys_menu SET path = 'billDeduct'   WHERE menu_id = 35112;
+UPDATE tenant_sys_menu SET path = 'billProfit'   WHERE menu_id = 35113;
+UPDATE tenant_sys_menu SET path = 'billMoneyLog' WHERE menu_id = 35114;
+
+-- hide company root (by menu_id, path may have been corrupted)
+UPDATE tenant_sys_menu SET visible = '1', status = '0' WHERE menu_id = 32344;
+
+INSERT INTO tenant_sys_menu
+(menu_id, menu_name, parent_id, order_num, path, component, query,
+ is_frame, is_cache, menu_type, visible, status, perms, icon,
+ create_by, create_time, remark)
+SELECT 35300, 'ÆäËû', 0, 17, 'other', NULL, NULL,
+       1, 0, 'M', '0', '0', NULL, 'more',
+       'admin', NOW(), '[organize:other-parent]'
+FROM DUAL
+WHERE NOT EXISTS (SELECT 1 FROM tenant_sys_menu WHERE menu_id = 35300);
+
+UPDATE tenant_sys_menu
+SET menu_name = 'ÆäËû', parent_id = 0, order_num = 17, path = 'other',
+    menu_type = 'M', visible = '0', status = '0', icon = 'more'
+WHERE menu_id = 35300;
+
+-- move hidden top-level modules under other (35300)
+UPDATE tenant_sys_menu SET parent_id = 35300
+WHERE parent_id = 0 AND visible = '1' AND menu_type = 'M'
+  AND menu_id NOT IN (32333, 35300);
+
+-- hide index dashboard template entry (not a tenant top-nav module)
+UPDATE tenant_sys_menu SET visible = '1' WHERE menu_id = 32644;
+
+-- archive hidden platform/legacy menus under ???? (35300)
+UPDATE tenant_sys_menu SET parent_id = 35300
+WHERE parent_id = 32372 AND visible = '1' AND menu_type <> 'F';
+
+UPDATE tenant_sys_menu SET parent_id = 35300
+WHERE parent_id = 32361 AND visible = '1' AND menu_type <> 'F'
+  AND menu_id NOT IN (35001, 35002, 35003, 35004, 35005, 35006, 35007);
+
+UPDATE tenant_sys_menu SET parent_id = 35300
+WHERE parent_id IN (32347, 32348, 32345, 32353, 32369, 32380, 32339, 32331, 32355, 32368, 32379, 32351, 32357, 32341)
+  AND visible = '1' AND menu_type <> 'F'
+  AND menu_id NOT IN (
+    35001,35002,35003,35004,35005,35006,35007,
+    35010,35011,35012,35013,
+    35020,35021,35023,
+    35040,35041,35042,
+    35050,35051,35052,35053,
+    35060,35061,35062,35063,
+    35070,35071,35072,35073,35074,35075,
+    35080,35090,
+    35100,35101,35102,35105,35106,
+    35111,35112,35113,35114
+  );

+ 399 - 0
sql/generate_adminUI_menu_doc.py

@@ -0,0 +1,399 @@
+# -*- coding: utf-8 -*-
+"""
+Scan adminUI src/views and generate reverse-engineered menu structure document.
+"""
+import os
+import re
+from collections import defaultdict
+from datetime import date
+
+ROOT = os.path.normpath(
+    os.path.join(os.path.dirname(__file__), '..', '..', 'ylrz_saas_his_scrm_adminUI', 'src', 'views')
+)
+OUT = os.path.join(os.path.dirname(__file__), 'adminUI_views_menu_structure.md')
+
+SKIP_TOP = {'components', 'error', 'dashboard', 'icons', 'login', 'register', 'redirect'}
+SKIP_REL = re.compile(
+    r'(components/|/profile/|authRole|authUser|selectUser|/data\.vue|/design\.vue|'
+    r'/log\.vue|/editTable|/details\.vue|/my\.vue|sopLogsList|sopUserLogsSchedule|'
+    r'/transferLog\.vue|/transfer\.vue|/darkRoom\.vue|/blackroom\.vue|config2\.vue|'
+    r'/sopTempe/|mixins/)'
+)
+LIST_NAMES = {'index.vue', 'list.vue', 'myList.vue', 'order.vue', 'order1.vue'}
+
+ADMIN_ONLY_TOP = {
+    'admin', 'saas', 'sysUser', 'saler', 'shop', 'medical', 'food', 'todo',
+    'baidu', 'callRecord', 'aiSipCall', 'storeOrderOfflineItem', 'operation', 'hisStore',
+}
+
+TENANT_TOP = {
+    'qw': ('\u4f01\u5fae\u7ba1\u7406', 'qw'),
+    'wx': ('\u5fae\u4fe1\u7ba1\u7406', 'wx'),
+    'gw': ('\u5fae\u4fe1\u7ba1\u7406', 'wx'),
+    'crm': ('CRM\u5ba2\u6237', 'crm'),
+    'user': ('\u4f1a\u5458\u7ba1\u7406', 'member'),
+    'users': ('\u4f1a\u5458\u7ba1\u7406', 'member'),
+    'member': ('\u4f1a\u5458\u7ba1\u7406', 'member'),
+    'his': ('\u8bca\u6240\u7ba1\u7406', 'his'),
+    'store': ('\u5546\u57ce\u7ba1\u7406', 'store'),
+    'live': ('\u76f4\u64ad\u7ba1\u7406', 'live'),
+    'liveData': ('\u76f4\u64ad\u7ba1\u7406', 'live'),
+    'course': ('\u8bfe\u7a0b\u7ba1\u7406', 'course'),
+    'courseFinishTemp': ('\u8bfe\u7a0b\u7ba1\u7406', 'course'),
+    'fastGpt': ('AI\u804a\u5929', 'fastGpt'),
+    'FastGptExtUserTag': ('AI\u804a\u5929', 'fastGpt'),
+    'chat': ('AI\u804a\u5929', 'fastGpt'),
+    'aiob': ('AI\u804a\u5929', 'fastGpt'),
+    'lobster': ('\u9f99\u8679\u5f15\u64ce', 'lobster'),
+    'adv': ('\u5e7f\u544a\u6295\u653e', 'ad'),
+    'ad': ('\u5e7f\u544a\u6295\u653e', 'ad'),
+    'company': ('\u7cfb\u7edf\u7ba1\u7406', 'system'),
+    'system': ('\u7cfb\u7edf\u7ba1\u7406', 'system'),
+    'bill': ('\u8d22\u52a1\u7ba1\u7406', 'bill'),
+    'billing': ('\u8d22\u52a1\u7ba1\u7406', 'bill'),
+    'calendar': ('\u65e5\u7a0b\u7ba1\u7406', 'calendar'),
+    'statistics': ('\u6570\u636e\u7edf\u8ba1', 'statistics'),
+    'taskStatistics': ('\u6570\u636e\u7edf\u8ba1', 'statistics'),
+    'moduleUsage': ('\u6570\u636e\u7edf\u8ba1', 'statistics'),
+    'monitor': ('\u76d1\u63a7\u7ba1\u7406', 'watch'),
+    'watch': ('\u76d1\u63a7\u7ba1\u7406', 'watch'),
+    'tool': ('\u7cfb\u7edf\u5de5\u5177', 'system'),
+    'qwExternalContact': ('\u4f01\u5fae\u7ba1\u7406', 'qw'),
+}
+
+SECONDARY_HINTS = {
+    'qw': {
+        'msg': ['QwWorkTask', 'groupMsg', 'record', 'qwPushCount'],
+        'customer': ['externalContact', 'contactWay', 'drainageLink', 'assignRule', 'customerLink'],
+        'group': ['groupChat', 'groupLiveCode', 'groupActual'],
+        'moments': ['friendCircle', 'friendMaterial', 'friendWelcome'],
+        'drainage': ['appAdvertisingReport', 'appContactWay'],
+        'tag': ['tag', 'tagGroup', 'autoTags'],
+        'setting': ['qwDept', 'companyUser', 'material', 'welcome', 'applyIpad', 'userBehaviorData'],
+        'sop': ['sop', 'sopTemp', 'sopLogs', 'aiSop'],
+    },
+    'store': {
+        'order': ['storeOrder', 'storeAfterSales', 'inquiryOrder', 'PromotionOrder', 'healthStoreOrder'],
+        'product': ['storeProduct', 'prescribe', 'shippingTemplates', 'package'],
+        'ops': ['storeShop', 'storeCoupon', 'homeArticle', 'exportTask', 'userPromoterApply', 'adv'],
+    },
+    'his': {
+        'doctor': ['doctor', 'doctorBill', 'doctorExtract', 'doctorOperLog'],
+        'inquiry': ['inquiryOrder', 'inquiryOrderReport', 'patient'],
+        'store': ['storeOrder', 'storeProduct', 'storeBill'],
+        'content': ['article', 'articleCate', 'answer'],
+        'ai': ['aiWorkflow', 'aiDoctorRole', 'aiDoctorChatSession'],
+    },
+    'system': {
+        'org': ['dept', 'post', 'user'],
+        'perm': ['role', 'menu'],
+        'config': ['dict', 'config', 'notice', 'keyword', 'set'],
+        'voice': ['companyVoiceDialog', 'companyVoiceRobotic'],
+    },
+    'company': {
+        'org': ['companyDept', 'companyPost', 'companyUser'],
+        'perm': ['companyRole', 'companyMenu'],
+        'finance': ['companyRecharge', 'companyProfit', 'companyMoneyLogs', 'companyDeduct'],
+        'comm': ['companySms', 'companyVoice', 'companyWorkflow'],
+        'wx': ['wxAccount', 'wxUser', 'wxDialog'],
+    },
+    'live': {
+        'ops': ['liveConsole', 'liveConfig', 'liveData', 'liveWatch'],
+        'order': ['liveOrder', 'liveAfterSales', 'healthLiveOrder'],
+        'interact': ['liveCoupon', 'liveQuestion', 'liveReward', 'comment'],
+    },
+    'course': {
+        'content': ['videoResource', 'Material', 'period', 'courseFinishTemp'],
+        'study': ['userCourse', 'courseWatchLog', 'userWatch'],
+        'stat': ['statistics', 'courseUserStatistics', 'huaweiCloudStatistics'],
+    },
+}
+
+GROUP_TITLES = {
+    'msg': '\u6d88\u606f\u7ba1\u7406', 'customer': '\u5ba2\u6237\u7ba1\u7406',
+    'group': '\u7fa4\u804a\u7ba1\u7406', 'moments': '\u670b\u53cb\u5708',
+    'drainage': '\u5f15\u6d41\u7ba1\u7406', 'tag': '\u6807\u7b7e\u7ba1\u7406',
+    'setting': '\u4f01\u5fae\u8bbe\u7f6e', 'sop': 'SOP/\u81ea\u52a8\u5316',
+    'order': '\u8ba2\u5355\u7ba1\u7406', 'product': '\u5546\u54c1\u7ba1\u7406',
+    'ops': '\u95e8\u5e97\u8fd0\u8425', 'doctor': '\u533b\u751f\u7ba1\u7406',
+    'inquiry': '\u95ee\u8bca\u7ba1\u7406', 'content': '\u5185\u5bb9\u7ba1\u7406',
+    'ai': 'AI/\u5de5\u4f5c\u6d41', 'org': '\u7ec4\u7ec7\u7ba1\u7406',
+    'perm': '\u6743\u9650\u7ba1\u7406', 'config': '\u7cfb\u7edf\u8bbe\u7f6e',
+    'voice': '\u8bed\u97f3/\u5916\u547c', 'finance': '\u8d22\u52a1',
+    'comm': '\u901a\u4fe1/\u5de5\u4f5c\u6d41', 'wx': '\u5fae\u4fe1\u8d26\u53f7',
+    'interact': '\u4e92\u52a8\u8425\u9500', 'study': '\u5b66\u4e60\u8ddf\u8e2a',
+    'stat': '\u7edf\u8ba1\u5206\u6790', 'general': '\u901a\u7528/\u5f85\u5206\u7ec4',
+}
+
+
+def to_component(rel_path):
+    comp = rel_path.replace('\\', '/').replace('.vue', '')
+    if comp.endswith('/index/index'):
+        comp = comp[:-6]
+    return comp
+
+
+def is_menu_page(rel_path, filename):
+    if SKIP_REL.search(rel_path):
+        return False
+    parts = rel_path.replace('\\', '/').split('/')
+    if parts[0] in SKIP_TOP:
+        return False
+    if filename in LIST_NAMES:
+        return True
+    if len(parts) == 2 and filename.endswith('.vue'):
+        return True
+    return False
+
+
+def scan_views():
+    pages = []
+    all_files = 0
+    for dirpath, dirnames, filenames in os.walk(ROOT):
+        dirnames[:] = [d for d in dirnames if d not in SKIP_TOP and d != 'mixins']
+        for fn in filenames:
+            if not fn.endswith('.vue'):
+                continue
+            all_files += 1
+            full = os.path.join(dirpath, fn)
+            rel = full[len(ROOT) + 1:]
+            if is_menu_page(rel, fn):
+                comp = to_component(rel)
+                module = rel.replace('\\', '/').split('/')[1] if '/' in rel else fn.replace('.vue', '')
+                pages.append({
+                    'top': rel.replace('\\', '/').split('/')[0],
+                    'module': module,
+                    'component': comp,
+                    'file': rel.replace('\\', '/'),
+                })
+    return pages, all_files
+
+
+def guess_secondary(top, module):
+    hints = SECONDARY_HINTS.get(top, {})
+    for group, keys in hints.items():
+        for k in keys:
+            if k.lower() in module.lower():
+                return group
+    return 'general'
+
+
+def build_markdown(pages, all_files):
+    by_top = defaultdict(list)
+    for p in pages:
+        by_top[p['top']].append(p)
+
+    agg_count = defaultdict(int)
+    for p in pages:
+        info = TENANT_TOP.get(p['top'])
+        key = info[1] if info else ('other' if p['top'] in ADMIN_ONLY_TOP else 'other')
+        agg_count[key] += 1
+
+    L = []
+    w = L.append
+    w('# adminUI \u89c6\u56fe\u53cd\u5411\u68b3\u7406 \u2014 \u79df\u6237\u7ba1\u7406\u7aef\u83dc\u5355\u5efa\u8bae\u7ed3\u6784')
+    w('')
+    w('> \u6587\u6863\u7c7b\u578b\uff1a**\u53ea\u8bfb\u68b3\u7406**\uff0c\u6682\u4e0d\u4fee\u6539\u6570\u636e\u5e93\u6216\u4ee3\u7801\u3002')
+    w('> \u626b\u63cf\u6765\u6e90\uff1a`ylrz_saas_his_scrm_adminUI/src/views`')
+    w('> \u751f\u6210\u65e5\u671f\uff1a%s' % date.today().isoformat())
+    w('> \u626b\u63cf\u7ed3\u679c\uff1a\u5171 **%d** \u4e2a `.vue` \u6587\u4ef6\uff0c\u8bc6\u522b **%d** \u4e2a\u53ef\u72ec\u7acb\u8def\u7531\u9875\u9762' % (all_files, len(pages)))
+    w('')
+    w('---')
+    w('')
+    w('## \u4e00\u3001\u68b3\u7406\u65b9\u6cd5')
+    w('')
+    w('| \u9879\u76ee | \u8bf4\u660e |')
+    w('|------|------|')
+    w('| \u9875\u9762\u8bc6\u522b | `index.vue` / `list.vue` / `myList.vue` \u53ca\u6a21\u5757\u6839\u76ee\u5f55\u5355\u5c42 `.vue` |')
+    w('| \u6392\u9664 | `components/`\u3001\u8be6\u60c5\u9875\u3001\u6388\u6743\u9875\u3001\u5b57\u5178\u5b50\u9875\u3001\u8bbe\u8ba1\u5668\u3001\u65e5\u5fd7\u5b50\u9875\u7b49 |')
+    w('| \u7ec4\u4ef6\u8def\u5ef6 | \u5bf9\u5e94\u540e\u7aef `sys_menu.component`\uff0c\u5982 `qw/externalContact/index` |')
+    w('| \u8def\u7531\u52a0\u8f7d | \u540e\u7aef `getRouters` \u2192 `loadView(@/views/${component})` |')
+    w('| \u53c2\u8003 | `src/views/admin/menu.js` \uff08\u603b\u540e\u53f0 `/admin/*` \u5bf9\u7167\u8868\uff09 |')
+    w('')
+    w('---')
+    w('')
+    w('## \u4e8c\u3001\u5efa\u8bae\u9876\u7ea7\u6a21\u5757\uff08\u79df\u6237 saasadminui \u9876\u680f\uff09')
+    w('')
+    w('| \u5e8f\u53f7 | \u6a21\u5757\u540d | path | \u89c6\u56fe\u6839\u76ee\u5f55 | \u9875\u9762\u6570 | \u5907\u6ce8 |')
+    w('|------|--------|------|------------|--------|------|')
+    tops = [
+        (1, '\u9996\u9875', 'index', 'index.vue', 1, '\u4eea\u8868\u76d8\uff0c\u53ef hidden'),
+        (2, '\u4f01\u5fae\u7ba1\u7406', 'qw', 'qw/', agg_count['qw'], ''),
+        (3, '\u5fae\u4fe1\u7ba1\u7406', 'wx', 'wx/, gw/', agg_count['wx'], ''),
+        (4, 'CRM\u5ba2\u6237', 'crm', 'crm/', agg_count['crm'], ''),
+        (5, '\u4f1a\u5458\u7ba1\u7406', 'member', 'user/, users/, member/', agg_count['member'], ''),
+        (6, '\u8bca\u6240\u7ba1\u7406', 'his', 'his/', agg_count['his'], ''),
+        (7, '\u5546\u57ce\u7ba1\u7406', 'store', 'store/', agg_count['store'], 'canonical'),
+        (8, '\u76f4\u64ad\u7ba1\u7406', 'live', 'live/, liveData/', agg_count['live'], ''),
+        (9, '\u8bfe\u7a0b\u7ba1\u7406', 'course', 'course/, courseFinishTemp/', agg_count['course'], ''),
+        (10, 'AI\u804a\u5929', 'fastGpt', 'fastGpt/, chat/, aiob/', agg_count['fastGpt'], ''),
+        (11, '\u9f99\u8679\u5f15\u64ce', 'lobster', 'lobster/', agg_count['lobster'], ''),
+        (12, '\u5e7f\u544a\u6295\u653e', 'ad', 'adv/, ad/', agg_count['ad'], ''),
+        (13, '\u7cfb\u7edf\u7ba1\u7406', 'system', 'system/, company/', agg_count['system'], ''),
+        (14, '\u8d22\u52a1\u7ba1\u7406', 'bill', 'bill/, billing/', agg_count['bill'], ''),
+        (15, '\u65e5\u7a0b\u7ba1\u7406', 'calendar', 'calendar/', agg_count['calendar'], ''),
+        (16, '\u6570\u636e\u7edf\u8ba1', 'statistics', 'statistics/, taskStatistics/', agg_count['statistics'], ''),
+        (17, '\u76d1\u63a7\u7ba1\u7406', 'watch', 'watch/, monitor/', agg_count['watch'], ''),
+        (18, '\u5176\u4ed6', 'other', '\u5e73\u53f0/\u9057\u7559', 0, '\u4e0d\u4e0b\u53d1\u79df\u6237\u9ed8\u8ba4\u83dc\u5355'),
+    ]
+    for row in tops:
+        w('| %d | %s | `%s` | %s | %d | %s |' % row)
+
+    w('')
+    w('---')
+    w('')
+    w('## \u4e09\u3001\u603b\u540e\u53f0\u4e13\u7528\uff08\u5f52\u5165\u300c\u5176\u4ed6\u300d\uff09')
+    w('')
+    w('| \u76ee\u5f55 | \u9875\u9762\u6570 | \u8bf4\u660e |')
+    w('|------|--------|------|')
+    notes = {
+        'admin': '\u603b\u540e\u53f0\u4e1a\u52a1\uff08\u79df\u6237/\u4ee3\u7406/\u5916\u547c/\u77ed\u4fe1/\u8d22\u52a1\u5ba1\u8ba1\uff09',
+        'saas': 'SaaS \u8ba1\u8d39/\u79df\u6237\u5b57\u5178/\u79df\u6237\u83dc\u5355\u6a21\u677f',
+        'sysUser': '\u603b\u540e\u53f0\u5458\u5de5\uff08\u4e0e system/user \u4e0d\u540c\uff09',
+        'hisStore': '\u65e7\u7248\u5546\u57ce\uff0c\u4e0e store \u91cd\u590d',
+        'shop': '\u95e8\u5e97\u72ec\u7acb\u83dc\u5355\uff08\u9057\u7559\uff09',
+    }
+    for t in sorted(set(ADMIN_ONLY_TOP) | {'admin', 'saas'}):
+        cnt = len(by_top.get(t, []))
+        if cnt:
+            w('| `%s/` | %d | %s |' % (t, cnt, notes.get(t, '\u5e73\u53f0\u6216\u9057\u7559')))
+
+    w('')
+    w('### 3.1 admin/menu.js \u5bf9\u7167\uff08\u603b\u540e\u53f0 /admin/*\uff09')
+    w('')
+    w('| \u83dc\u5355\u6807\u9898 | path | component |')
+    w('|----------|------|-----------|')
+    admin_rows = [
+        ('\u6570\u636e\u770b\u677f', 'dashboard', 'admin/dashboard/index'),
+        ('\u79df\u6237\u7ba1\u7406', 'company', 'admin/sysCompany/index'),
+        ('\u79df\u6237\u6a21\u5757\u4f7f\u7528\u7edf\u8ba1', 'moduleUsage', 'admin/moduleUsage/index'),
+        ('\u79df\u6237\u7ba1\u7406\u7aef\u83dc\u5355', 'tenantMenu', 'admin/tenantMenu/index'),
+        ('\u79df\u6237\u9500\u552e\u7aef\u83dc\u5355', 'tenantCompany', 'admin/tenantCompany/index'),
+        ('\u4ee3\u7406\u7ba1\u7406', 'proxy', 'admin/proxy/index'),
+        ('\u6536\u8d39\u914d\u7f6e', 'serviceCost', 'admin/serviceCost/index'),
+        ('\u5458\u5de5\u7ba1\u7406', 'sysUser', 'admin/sysUser/index'),
+        ('\u89d2\u8272\u7ba1\u7406', 'role', 'system/role/index'),
+        ('\u83dc\u5355\u7ba1\u7406', 'menu', 'system/menu/index'),
+        ('\u5916\u547c\u7ba1\u7406', 'voice', 'admin/voice/index'),
+        ('\u77ed\u4fe1\u7ba1\u7406', 'sms', 'admin/sms/index'),
+        ('AI\u6a21\u578b\u914d\u7f6e', 'aiModel', 'admin/aiModel/index'),
+        ('AI\u751f\u6210\u5de5\u4f5c\u6d41', 'workflowGenerate', 'lobster/workflow-generate/index'),
+    ]
+    for title, path, comp in admin_rows:
+        w('| %s | `/admin/%s` | `%s` |' % (title, path, comp))
+
+    w('')
+    w('---')
+    w('')
+    w('## \u56db\u3001\u5404\u4e1a\u52a1\u6a21\u5757\u4e8c\u7ea7\u5206\u7ec4\u4e0e\u9875\u9762\u6e05\u5355')
+    w('')
+
+    detail = [
+        ('qw', '\u4f01\u5fae\u7ba1\u7406', 'qw'),
+        ('crm', 'CRM', 'crm'),
+        ('store', '\u5546\u57ce', 'store'),
+        ('his', '\u8bca\u6240', 'his'),
+        ('live', '\u76f4\u64ad', 'live'),
+        ('course', '\u8bfe\u7a0b', 'course'),
+        ('fastGpt', 'AI', 'fastGpt'),
+        ('company', '\u4f01\u4e1a/\u7ec4\u7ec7', 'company'),
+        ('system', '\u7cfb\u7edf', 'system'),
+        ('lobster', '\u9f99\u8679', 'lobster'),
+        ('adv', '\u5e7f\u544a', 'ad'),
+        ('wx', '\u5fae\u4fe1', 'wx'),
+        ('monitor', '\u76d1\u63a7', 'monitor'),
+    ]
+
+    sec_no = 1
+    for top_key, title, path_prefix in detail:
+        items = list(by_top.get(top_key, []))
+        if top_key == 'fastGpt':
+            for extra in ('chat', 'aiob', 'FastGptExtUserTag'):
+                items.extend(by_top.get(extra, []))
+        if not items:
+            continue
+        w('### 4.%d %s (`%s/`) \u2014 %d \u9875' % (sec_no, title, top_key, len(items)))
+        sec_no += 1
+        w('')
+        w('\u5efa\u8bae\u8def\u7531\u524d\u7f00\uff1a`/%s`' % path_prefix)
+        w('')
+        groups = defaultdict(list)
+        for p in sorted(items, key=lambda x: x['component']):
+            groups[guess_secondary(top_key, p['module'])].append(p)
+        order = list(SECONDARY_HINTS.get(top_key, {}).keys()) + ['general']
+        for g in order:
+            if g not in groups:
+                continue
+            w('#### %s' % GROUP_TITLES.get(g, g))
+            w('')
+            w('| \u5efa\u8bae menu_name | component | \u6e90\u6587\u4ef6 |')
+            w('|--------------|-----------|--------|')
+            for p in groups[g]:
+                w('| %s | `%s` | `%s` |' % (p['module'], p['component'], p['file']))
+            w('')
+
+    w('---')
+    w('')
+    w('## \u4e94\u3001\u91cd\u590d/\u9057\u7559\u6a21\u5757\u5408\u5e76\u5efa\u8bae')
+    w('')
+    w('| \u7ec4 | \u76ee\u5f55 | \u5efa\u8bae |')
+    w('|------|------|------|')
+    dupes = [
+        ('\u5546\u57ce', '`store/` vs `hisStore/`', '\u4fdd\u7559 store\uff0chisStore \u653e\u5176\u4ed6'),
+        ('\u5546\u57ce', '`store/` vs `his/store*`', 'his \u5185\u5d4c\u5957\u9875\u7559\u5728\u8bca\u6240\u6a21\u5757'),
+        ('\u4f1a\u5458', '`user/` `users/` `member/`', '\u5408\u5e76\u4e3a member \u9876\u680f'),
+        ('AI', '`fastGpt/` `chat/` `aiob/`', '\u5408\u5e76\u4e3a fastGpt'),
+        ('\u5e7f\u544a', '`adv/` `ad/`', '\u7edf\u4e00 adv'),
+        ('\u5fae\u4fe1', '`wx/` `gw/`', 'gwAccount \u5f52\u5165 wx'),
+        ('\u7edf\u8ba1', '`statistics/` `taskStatistics/`', '\u5408\u5e76 statistics'),
+        ('\u76d1\u63a7', '`monitor/` `watch/`', '\u5408\u5e76 watch'),
+        ('\u7528\u6237', '`system/user` vs `sysUser/`', 'sysUser \u4ec5\u603b\u540e\u53f0'),
+    ]
+    for a, b, c in dupes:
+        w('| %s | %s | %s |' % (a, b, c))
+
+    w('')
+    w('---')
+    w('')
+    w('## \u516d\u3001\u5b8c\u6574\u4e00\u7ea7\u76ee\u5f55\u626b\u63cf\u8868')
+    w('')
+    w('| views \u4e00\u7ea7\u76ee\u5f55 | \u53ef\u8def\u7531\u9875\u9762\u6570 | \u5f52\u7c7b |')
+    w('|----------------|-------------|------|')
+    for top in sorted(by_top.keys()):
+        cnt = len(by_top[top])
+        if top in ADMIN_ONLY_TOP or top == 'admin':
+            cat = '\u5e73\u53f0/\u5176\u4ed6'
+        elif top in TENANT_TOP:
+            cat = '\u79df\u6237 \u2014 ' + TENANT_TOP[top][0]
+        else:
+            cat = '\u5f85\u786e\u8ba4'
+        w('| `%s/` | %d | %s |' % (top, cnt, cat))
+
+    w('')
+    w('---')
+    w('')
+    w('## \u4e03\u3001\u672c\u6b21\u4e0d\u6267\u884c\u7684\u843d\u5730\u6b65\u9aa4')
+    w('')
+    w('1. \u8bc4\u5ba1\u672c\u6587\u6863\u4e8c\u7ea7\u5206\u7ec4')
+    w('2. \u5bfc\u51fa component \u4e0e tenant_sys_menu diff')
+    w('3. \u5408\u5e76\u91cd\u590d\u83dc\u5355')
+    w('4. \u66f4\u65b0\u6a21\u677f\u5e76\u540c\u6b65\u79df\u6237\u5e93')
+    w('5. saasadminui \u9a8c\u8bc1\u8def\u7531')
+    w('')
+    w('---')
+    w('')
+    w('*Generated by `sql/generate_adminUI_menu_doc.py`*')
+    return '\n'.join(L)
+
+
+def main():
+    pages, all_files = scan_views()
+    md = build_markdown(pages, all_files)
+    with open(OUT, 'w', encoding='utf-8') as f:
+        f.write(md)
+    print('Wrote', OUT)
+    print('pages', len(pages), 'all vue', all_files)
+
+
+if __name__ == '__main__':
+    main()

+ 439 - 0
sql/generate_menu_tree_zh.py

@@ -0,0 +1,439 @@
+# -*- coding: utf-8 -*-
+"""
+Generate complete Chinese menu tree (M/C/F) from tenant_sys_menu + view title hints.
+Output: adminUI_menu_tree_zh.md
+"""
+import os
+import re
+from collections import defaultdict
+from datetime import date
+
+try:
+    import pymysql
+except ImportError:
+    pymysql = None
+
+ROOT = os.path.normpath(
+    os.path.join(os.path.dirname(__file__), '..', '..', 'ylrz_saas_his_scrm_adminUI')
+)
+OUT = os.path.join(os.path.dirname(__file__), 'adminUI_menu_tree_zh.md')
+MENU_JS = os.path.join(ROOT, 'src', 'views', 'admin', 'menu.js')
+
+DB = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+TYPE_LABEL = {'M': '\u76ee\u5f55', 'C': '\u83dc\u5355', 'F': '\u6309\u94ae'}
+
+# Root menu_id -> fixed Chinese name
+ROOT_ZH = {
+    32361: '\u4f01\u5fae\u7ba1\u7406', 32380: '\u5fae\u4fe1\u7ba1\u7406', 32347: 'CRM\u5ba2\u6237',
+    32357: '\u4f1a\u5458\u7ba1\u7406', 32351: '\u8bca\u6240\u7ba1\u7406', 32369: '\u5546\u57ce\u7ba1\u7406',
+    32353: '\u76f4\u64ad\u7ba1\u7406', 32345: '\u8bfe\u7a0b\u7ba1\u7406', 32348: 'AI\u804a\u5929',
+    32355: '\u9f99\u8678\u5f15\u64ce', 32331: '\u5e7f\u544a\u6295\u653e', 32372: '\u7cfb\u7edf\u7ba1\u7406',
+    32339: '\u8d22\u52a1\u7ba1\u7406', 32341: '\u65e5\u7a0b\u7ba1\u7406', 32368: '\u6570\u636e\u7edf\u8ba1',
+    32379: '\u76d1\u63a7\u7ba1\u7406', 35300: '\u5176\u4ed6', 32333: '\u5e73\u53f0\u7ba1\u7406\uff08\u5f52\u6863\uff09',
+    32644: '\u9996\u9875', 35100: '\u7ec4\u7ec7\u7ba1\u7406', 35101: '\u6743\u9650\u7ba1\u7406',
+    35102: '\u901a\u4fe1\u7ba1\u7406', 35105: '\u65e5\u5fd7\u7ba1\u7406', 35106: '\u7cfb\u7edf\u8bbe\u7f6e',
+    35001: '\u6d88\u606f\u7ba1\u7406', 35002: '\u5ba2\u6237\u7ba1\u7406', 35003: '\u7fa4\u804a\u7ba1\u7406',
+    35004: '\u670b\u53cb\u5708', 35005: '\u5f15\u6d41\u7ba1\u7406', 35006: '\u6807\u7b7e\u7ba1\u7406',
+    35007: '\u4f01\u5fae\u8bbe\u7f6e', 35040: '\u8ba2\u5355\u7ba1\u7406', 35041: '\u5546\u54c1\u7ba1\u7406',
+    35042: '\u95e8\u5e97\u8fd0\u8425', 35010: '\u5fae\u4fe1\u8d26\u53f7', 35011: '\u5fae\u4fe1\u5bf9\u8bdd',
+    35012: '\u5fae\u4fe1\u7528\u6237', 35013: '\u5fae\u4fe1\u7528\u6237\u7ec4', 35020: 'CRM\u5ba2\u6237\u7ba1\u7406',
+    35050: '\u76f4\u64ad\u8fd0\u8425', 35060: '\u8bfe\u7a0b\u5185\u5bb9', 35070: 'AI\u5bf9\u8bdd\u7ba1\u7406',
+    35080: '\u9f99\u8678\u5de5\u4f5c\u6d41', 35090: '\u6295\u653e\u8fd0\u8425',
+    35111: '\u5145\u503c\u7ba1\u7406', 35112: '\u6263\u8d39\u7ba1\u7406', 35113: '\u5206\u8d26\u7ba1\u7406',
+    35114: '\u8d44\u91d1\u65e5\u5fd7',
+    35201: '\u7528\u6237\u7ba1\u7406', 35202: '\u89d2\u8272\u7ba1\u7406', 35203: '\u83dc\u5355\u7ba1\u7406',
+    35204: '\u90e8\u95e8\u7ba1\u7406', 35205: '\u5c97\u4f4d\u7ba1\u7406', 35206: '\u5b57\u5178\u7ba1\u7406',
+    35207: '\u53c2\u6570\u8bbe\u7f6e', 35208: '\u901a\u77e5\u516c\u544a', 35209: '\u8fdd\u89c4\u8bcd\u8bed',
+}
+
+# component suffix / module -> Chinese
+COMP_ZH = {
+    'externalContact': '\u5916\u90e8\u8054\u7cfb\u4eba', 'QwWorkTask': '\u4f01\u5fae\u5de5\u4f5c\u4efb\u52a1',
+    'groupMsg': '\u7fa4\u6d88\u606f', 'contactWay': '\u6e20\u9053\u7801', 'friendCircle': '\u670b\u53cb\u5708',
+    'storeOrder': '\u8ba2\u5355\u7ba1\u7406', 'storeProduct': '\u5546\u54c1\u7ba1\u7406', 'storeShop': '\u95e8\u5e97\u7ba1\u7406',
+    'liveConsole': '\u76f4\u64ad\u63a7\u5236\u53f0', 'liveOrder': '\u76f4\u64ad\u8ba2\u5355', 'videoResource': '\u89c6\u9891\u8d44\u6e90',
+    'userCourse': '\u7528\u6237\u8bfe\u7a0b', 'fastGptRole': 'AI\u89d2\u8272', 'fastGptDataset': 'AI\u77e5\u8bc6\u5e93',
+    'companyUser': '\u4f01\u4e1a\u7528\u6237', 'companyRole': '\u4f01\u4e1a\u89d2\u8272', 'companyMenu': '\u4f01\u4e1a\u83dc\u5355',
+    'companyDept': '\u4f01\u4e1a\u90e8\u95e8', 'companyRecharge': '\u5145\u503c\u8bb0\u5f55',
+    'companyProfit': '\u5206\u8d26\u8bb0\u5f55', 'companyMoneyLogs': '\u8d44\u91d1\u6d41\u6c34',
+    'sysCompany': '\u79df\u6237\u7ba1\u7406', 'tenantMenu': '\u79df\u6237\u7ba1\u7406\u7aef\u83dc\u5355',
+    'operlog': '\u64cd\u4f5c\u65e5\u5fd7', 'logininfor': '\u767b\u5f55\u65e5\u5fd7', 'workflow-generate': 'AI\u751f\u6210\u5de5\u4f5c\u6d41',
+    'dead-letter': '\u6b7b\u4fe1\u961f\u5217', 'workflow-canvas': '\u5de5\u4f5c\u6d41\u753b\u5e03',
+}
+
+WORD_ZH = {
+    'user': '\u7528\u6237', 'users': '\u7528\u6237', 'role': '\u89d2\u8272', 'menu': '\u83dc\u5355',
+    'dept': '\u90e8\u95e8', 'post': '\u5c97\u4f4d', 'dict': '\u5b57\u5178', 'config': '\u914d\u7f6e',
+    'notice': '\u516c\u544a', 'keyword': '\u5173\u952e\u8bcd', 'order': '\u8ba2\u5355', 'store': '\u5546\u57ce',
+    'product': '\u5546\u54c1', 'customer': '\u5ba2\u6237', 'company': '\u4f01\u4e1a', 'tenant': '\u79df\u6237',
+    'proxy': '\u4ee3\u7406', 'admin': '\u5e73\u53f0', 'live': '\u76f4\u64ad', 'course': '\u8bfe\u7a0b',
+    'doctor': '\u533b\u751f', 'patient': '\u60a3\u8005', 'inquiry': '\u95ee\u8bca', 'statistics': '\u7edf\u8ba1',
+    'report': '\u62a5\u8868', 'log': '\u65e5\u5fd7', 'logs': '\u65e5\u5fd7', 'record': '\u8bb0\u5f55',
+    'tag': '\u6807\u7b7e', 'group': '\u7fa4', 'msg': '\u6d88\u606f', 'voice': '\u8bed\u97f3', 'sms': '\u77ed\u4fe1',
+    'coupon': '\u4f18\u6263\u5238', 'export': '\u5bfc\u51fa', 'import': '\u5bfc\u5165', 'package': '\u5957\u9910',
+    'wallet': '\u94b1\u5305', 'bill': '\u8d26\u5355', 'calendar': '\u65e5\u7a0b', 'monitor': '\u76d1\u63a7',
+    'watch': '\u76d1\u63a7', 'material': '\u7d20\u6750', 'welcome': '\u6b22\u8fce\u8bed', 'sop': 'SOP',
+    'advertiser': '\u5e7f\u544a\u4e3b', 'channel': '\u6e20\u9053', 'domain': '\u57df\u540d', 'site': '\u7ad9\u70b9',
+    'recharge': '\u5145\u503c', 'deduct': '\u6263\u8d39', 'profit': '\u5206\u8d26', 'withdraw': '\u63d0\u73b0',
+    'article': '\u6587\u7ae0', 'video': '\u89c6\u9891', 'comment': '\u8bc4\u8bba', 'question': '\u95ee\u9898',
+    'answer': '\u7b54\u6848', 'schedule': '\u6392\u73ed', 'traffic': '\u6d41\u91cf', 'workflow': '\u5de5\u4f5c\u6d41',
+    'lobster': '\u9f99\u8678', 'prompt': '\u63d0\u793a\u8bcd', 'instance': '\u5b9e\u4f8b', 'template': '\u6a21\u677f',
+    'shipping': '\u8fd0\u8d39', 'prescribe': '\u5904\u65b9', 'integral': '\u79ef\u5206', 'member': '\u4f1a\u5458',
+    'blacklist': '\u9ed1\u540d\u5355', 'complaint': '\u6295\u8bc9', 'transfer': '\u8f6c\u79fb', 'external': '\u5916\u90e8',
+    'contact': '\u8054\u7cfb\u4eba', 'qw': '\u4f01\u5fae', 'wx': '\u5fae\u4fe1', 'crm': 'CRM', 'his': '\u8bca\u6240',
+    'adv': '\u5e7f\u544a', 'ad': '\u5e7f\u544a', 'tool': '\u5de5\u5177', 'gen': '\u4ee3\u7801\u751f\u6210',
+    'job': '\u5b9a\u65f6\u4efb\u52a1', 'online': '\u5728\u7ebf\u7528\u6237', 'cache': '\u7f13\u5b58', 'server': '\u670d\u52a1\u5668',
+    'druid': '\u6570\u636e\u76d1\u63a7', 'iot': '\u7269\u8054\u7f51', 'device': '\u8bbe\u5907', 'index': '\u9996\u9875',
+    'list': '\u5217\u8868', 'manage': '\u7ba1\u7406', 'setting': '\u8bbe\u7f6e', 'info': '\u4fe1\u606f',
+    'detail': '\u8be6\u60c5', 'data': '\u6570\u636e', 'temp': '\u6a21\u677f', 'api': 'API',     'Actual': '\u5b9e\u9645', 'Statistic': '\u7edf\u8ba1', 'OnJob': '\u5728\u804c',
+    'Live': '\u76f4\u64ad', 'Code': '\u7801', 'Circle': '\u5708', 'Task': '\u4efb\u52a1',
+    'Comments': '\u8bc4\u8bba', 'Customer': '\u5ba2\u6237', 'Item': '\u660e\u7ec6',
+    'Advertising': '\u5e7f\u544a', 'Apply': '\u7533\u8bf7', 'Ipad': 'iPad',
+    'Behavior': '\u884c\u4e3a', 'Push': '\u63a8\u9001', 'Count': '\u7edf\u8ba1',
+    'Assign': '\u5206\u914d', 'assign': '\u5206\u914d', 'Rule': '\u89c4\u5219', 'Batch': '\u6279\u6b21',
+    'Way': '\u65b9\u5f0f', 'Link': '\u94fe\u63a5', 'Drainage': '\u5f15\u6d41', 'drainage': '\u5f15\u6d41',
+    'Loss': '\u6d41\u5931', 'Stage': '\u9636\u6bb5', 'Transfer': '\u8f6c\u79fb',
+    'Audit': '\u5ba1\u6838', 'Unassigned': '\u672a\u5206\u914d', 'AfterSales': '\u552e\u540e',
+    'Promotion': '\u63a8\u5e7f', 'Health': '\u5065\u5eb7', 'Inquiry': '\u95ee\u8bca',
+    'Category': '\u5206\u7c7b', 'DarkRoom': '\u5c0f\u9ed1\u5c4b', 'Recharge': '\u5145\u503c',
+    'Template': '\u6a21\u677f', 'Follow': '\u968f\u8bbf', 'Audit': '\u5ba1\u6838',
+    'Offline': '\u7ebf\u4e0b', 'Audit': '\u5ba1\u6838', 'Staff': '\u5458\u5de5',
+    'Cart': '\u8d2d\u7269\u8f66', 'Visit': '\u8bbf\u95ee', 'Relation': '\u5173\u8054',
+    'Reply': '\u56de\u590d', 'Attr': '\u5c5e\u6027', 'Details': '\u8be6\u60c5',
+    'Category': '\u5206\u7c7b', 'Group': '\u5206\u7ec4', 'Console': '\u63a7\u5236\u53f0',
+    'Config': '\u914d\u7f6e', 'Coupon': '\u4f18\u6263\u5238', 'Question': '\u95ee\u9898',
+    'Reward': '\u5956\u52b1', 'Favorite': '\u6536\u85cf', 'Watch': '\u89c2\u770b',
+    'Talent': '\u8fbe\u4eba', 'Training': '\u57f9\u8bad', 'Camp': '\u8425',
+    'Material': '\u7d20\u6750', 'Period': '\u671f\u6570', 'Resource': '\u8d44\u6e90',
+    'Finish': '\u5b8c\u7ed3', 'Temp': '\u6a21\u677f', 'Bank': '\u9898\u5e93',
+    'Answer': '\u7b54\u6848', 'RedPacket': '\u7ea2\u5305', 'Traffic': '\u6d41\u91cf',
+    'Collection': '\u6536\u85cf', 'Dataset': '\u77e5\u8bc6\u5e93', 'Session': '\u4f1a\u8bdd',
+    'Keyword': '\u5173\u952e\u8bcd', 'Role': '\u89d2\u8272', 'Replace': '\u66ff\u6362',
+    'Words': '\u8bcd\u6761', 'Quality': '\u8d28\u68c0', 'Gateway': '\u7f51\u5173',
+    'Sip': 'SIP', 'Call': '\u547c\u53eb', 'Client': '\u5ba2\u6237\u7aef',
+    'Offline': '\u7ebf\u4e0b', 'Item': '\u660e\u7ec6',
+}
+
+PERM_ACTION_ZH = {
+    'add': '\u65b0\u589e', 'edit': '\u4fee\u6539', 'update': '\u4fee\u6539', 'remove': '\u5220\u9664',
+    'delete': '\u5220\u9664', 'query': '\u67e5\u8be2', 'list': '\u5217\u8868', 'export': '\u5bfc\u51fa',
+    'import': '\u5bfc\u5165', 'view': '\u67e5\u770b', 'detail': '\u8be6\u60c5', 'reset': '\u91cd\u7f6e',
+    'auth': '\u6388\u6743', 'assign': '\u5206\u914d', 'changeStatus': '\u72b6\u6001\u53d8\u66f4',
+    'audit': '\u5ba1\u6838', 'approve': '\u5ba1\u6279', 'reject': '\u9a73\u56de', 'sync': '\u540c\u6b65',
+    'refresh': '\u5237\u65b0', 'execute': '\u6267\u884c', 'cancel': '\u53d6\u6d88', 'submit': '\u63d0\u4ea4',
+    'publish': '\u53d1\u5e03', 'copy': '\u590d\u5236', 'download': '\u4e0b\u8f7d', 'upload': '\u4e0a\u4f20',
+    'bind': '\u7ed1\u5b9a', 'unbind': '\u89e3\u7ed1', 'enable': '\u542f\u7528', 'disable': '\u505c\u7528',
+}
+
+
+def has_chinese(s):
+    return bool(s and re.search(r'[\u4e00-\u9fff]', s))
+
+
+def split_camel(s):
+    parts = re.sub(r'([a-z0-9])([A-Z])', r'\1 \2', s or '')
+    parts = re.sub(r'[-_/]', ' ', parts)
+    return [p for p in parts.split() if p]
+
+
+def translate_tokens(text):
+    if not text:
+        return ''
+    out = []
+    for tok in split_camel(text):
+        low = tok.lower()
+        if tok in WORD_ZH:
+            out.append(WORD_ZH[tok])
+        elif low in WORD_ZH:
+            out.append(WORD_ZH[low])
+        elif tok in COMP_ZH:
+            out.append(COMP_ZH[tok])
+        elif re.match(r'^[A-Z][a-z]+', tok):
+            out.append(translate_tokens(tok[0].lower() + tok[1:]) or tok)
+        else:
+            out.append(tok)
+    return ''.join(out) if out else text
+
+
+def load_admin_titles():
+    titles = {}
+    if not os.path.exists(MENU_JS):
+        return titles
+    with open(MENU_JS, 'r', encoding='utf-8') as f:
+        content = f.read()
+    for m in re.finditer(
+        r"import\('@/views/([^']+)'\)[^}]*title:\s*'([^']+)'", content
+    ):
+        comp, title = m.group(1).replace('.vue', ''), m.group(2)
+        if comp.endswith('/index'):
+            comp = comp[:-6]
+        titles[comp] = title
+    return titles
+
+
+def load_menus():
+    conn = pymysql.connect(**DB)
+    cur = conn.cursor(pymysql.cursors.DictCursor)
+    cur.execute(
+        'SELECT menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, perms '
+        'FROM tenant_sys_menu ORDER BY parent_id, order_num, menu_id'
+    )
+    rows = cur.fetchall()
+    cur.close()
+    conn.close()
+    return rows
+
+
+def comp_key(component):
+    if not component:
+        return ''
+    c = component.replace('/index/index', '/index').replace('/index', '')
+    return c.strip('/')
+
+
+def to_chinese(menu, admin_titles, comp_zh=None, parent_zh=''):
+    comp_zh = comp_zh or COMP_ZH
+    mid = menu['menu_id']
+    if mid in ROOT_ZH:
+        return ROOT_ZH[mid]
+
+    name = (menu.get('menu_name') or '').strip()
+    if has_chinese(name) and not re.match(r'^[a-zA-Z\s]+$', name):
+        # clean mixed English-only names
+        if not re.fullmatch(r'[A-Za-z0-9\s\-_]+', name):
+            return name
+
+    comp = comp_key(menu.get('component') or '')
+    if comp in admin_titles:
+        return admin_titles[comp]
+    if comp in comp_zh:
+        return comp_zh[comp]
+
+    # component last segment
+    if comp:
+        seg = comp.split('/')[-1]
+        if seg in comp_zh:
+            return comp_zh[seg]
+        zh = translate_tokens(seg)
+        if zh and zh != seg:
+            return zh
+        # two segments
+        if '/' in comp:
+            zh2 = translate_tokens(comp.split('/')[-2] + seg)
+            if has_chinese(zh2):
+                return zh2
+
+    if menu['menu_type'] == 'F':
+        perms = menu.get('perms') or ''
+        if perms:
+            parts = perms.split(':')
+            action = parts[-1] if parts else ''
+            act_zh = PERM_ACTION_ZH.get(action, PERM_ACTION_ZH.get(action.lower(), ''))
+            if act_zh:
+                if parent_zh and parent_zh not in ('\u6309\u94ae', act_zh):
+                    return parent_zh + act_zh
+                if len(parts) >= 2:
+                    res = translate_tokens(parts[-2])
+                    if has_chinese(res):
+                        return res + act_zh
+                return act_zh
+        if name and name != '#':
+            zh = translate_tokens(name)
+            return zh if has_chinese(zh) or zh != name else (act_zh or '\u6309\u94ae')
+
+    if name:
+        zh = translate_tokens(name.replace(' ', ''))
+        if has_chinese(zh):
+            return zh
+        # title case words
+        if ' ' in name:
+            parts = [WORD_ZH.get(w.lower(), w) for w in name.split()]
+            joined = ''.join(parts)
+            if has_chinese(joined):
+                return joined
+
+    path = menu.get('path') or ''
+    if path and path != '#':
+        zh = translate_tokens(path)
+        if has_chinese(zh):
+            return zh
+
+    return name or comp or ('\u672a\u547d\u540d\u83dc\u5355%d' % mid)
+
+
+def build_children_map(menus):
+    ch = defaultdict(list)
+    by_id = {}
+    for m in menus:
+        by_id[m['menu_id']] = m
+        ch[m['parent_id']].append(m)
+    for pid in ch:
+        ch[pid].sort(key=lambda x: (x.get('order_num') or 0, x['menu_id']))
+    return ch, by_id
+
+
+def build_comp_zh_from_db(menus):
+    comp_zh = dict(COMP_ZH)
+    for m in menus:
+        if m['menu_type'] not in ('C', 'M'):
+            continue
+        name = (m.get('menu_name') or '').strip()
+        comp = comp_key(m.get('component') or '')
+        if comp and has_chinese(name) and not re.fullmatch(r'[A-Za-z0-9\s\-_:.]+', name):
+            comp_zh[comp] = name
+            seg = comp.split('/')[-1]
+            if seg and has_chinese(name):
+                comp_zh[seg] = name
+    return comp_zh
+
+
+def collect_reachable(ch_map, roots):
+    seen = set()
+    stack = [r['menu_id'] for r in roots]
+    while stack:
+        mid = stack.pop()
+        if mid in seen:
+            continue
+        seen.add(mid)
+        for child in ch_map.get(mid, []):
+            stack.append(child['menu_id'])
+    return seen
+
+
+def render_node(menu, zh_name, depth, lines, ch_map, zh_cache, admin_titles, comp_zh):
+    mtype = menu['menu_type']
+    label = TYPE_LABEL.get(mtype, mtype)
+    vis = '\u9690\u85cf' if menu.get('visible') == '1' else '\u663e\u793a'
+    comp = menu.get('component') or '-'
+    perms = menu.get('perms') or '-'
+    mid = menu['menu_id']
+    indent = '  ' * depth
+    if mtype == 'F':
+        lines.append('%s- \u2514\u2500 [%s] **%s**  `perms=%s`' % (indent, label, zh_name, perms))
+    else:
+        lines.append('%s- [%s] **%s**  `id=%s` path=`%s` component=`%s` %s' % (
+            indent, label, zh_name, mid, menu.get('path') or '', comp, vis))
+    for child in ch_map.get(mid, []):
+        if child['menu_id'] not in zh_cache:
+            parent_name = zh_name if mtype == 'C' else ''
+            zh_cache[child['menu_id']] = to_chinese(
+                child, admin_titles, comp_zh, parent_zh=parent_name if child['menu_type'] == 'F' else '')
+        render_node(child, zh_cache[child['menu_id']], depth + 1, lines, ch_map, zh_cache, admin_titles, comp_zh)
+
+
+def main():
+    menus = load_menus()
+    admin_titles = load_admin_titles()
+    comp_zh = build_comp_zh_from_db(menus)
+    ch_map, by_id = build_children_map(menus)
+    zh_cache = {m['menu_id']: to_chinese(m, admin_titles, comp_zh) for m in menus}
+
+    roots = ch_map.get(0, [])
+    biz_roots = [r for r in roots if r['menu_id'] != 32333 and r.get('visible') == '0']
+    hidden_roots = [r for r in roots if r not in biz_roots]
+    biz_roots.sort(key=lambda x: (x.get('order_num') or 0, x['menu_id']))
+    hidden_roots.sort(key=lambda x: (x.get('order_num') or 0, x['menu_id']))
+    ordered_roots = biz_roots + hidden_roots
+    reachable = collect_reachable(ch_map, roots)
+    orphans = [m for m in menus if m['menu_id'] not in reachable]
+    orphan_groups = defaultdict(list)
+    for m in orphans:
+        orphan_groups[m['parent_id']].append(m)
+    for pid in orphan_groups:
+        orphan_groups[pid].sort(key=lambda x: (x.get('order_num') or 0, x['menu_id']))
+
+    stats = defaultdict(int)
+    for m in menus:
+        stats[m['menu_type']] += 1
+
+    lines = []
+    w = lines.append
+    w('# \u79df\u6237\u7ba1\u7406\u7aef\u83dc\u5355\u5b8c\u6574\u6811\uff08\u4e2d\u6587\uff09')
+    w('')
+    w('> \u6570\u636e\u6765\u6e90\uff1a`ylrz_saas.tenant_sys_menu` + adminUI \u89c6\u56fe/\u6743\u9650\u8865\u5168')
+    w('> \u751f\u6210\u65e5\u671f\uff1a%s' % date.today().isoformat())
+    w('> \u603b\u8ba1\uff1a**%d** \u6761\uff08\u76ee\u5f55 %d / \u83dc\u5355 %d / \u6309\u94ae %d\uff09' % (
+        len(menus), stats['M'], stats['C'], stats['F']))
+    w('> \u6811\u4e2d\u53ef\u8fbe\uff1a**%d** \u6761\uff0c\u5b64\u7acb\u8282\u70b9\uff08parent_id \u65e0\u6548\uff09\uff1a**%d** \u6761' % (
+        len(reachable), len(orphans)))
+    w('')
+    w('## \u56fe\u4f8b')
+    w('')
+    w('- `[\u76ee\u5f55]` = M \u7c7b\u578b\uff0c\u9876\u680f/\u4fa7\u680f\u5206\u7ec4')
+    w('- `[\u83dc\u5355]` = C \u7c7b\u578b\uff0c\u53ef\u8def\u7531\u9875\u9762')
+    w('- `[\u6309\u94ae]` = F \u7c7b\u578b\uff0c\u9875\u9762\u5185\u6743\u9650\u6309\u94ae\uff08`perms`\uff09')
+    w('- \u663e\u793a/\u9690\u85cf = visible 0/1')
+    w('')
+    w('---')
+    w('')
+    w('## \u5b8c\u6574\u6811\u72b6\u7ed3\u6784')
+    w('')
+
+    sec = 1
+    for root in ordered_roots:
+        zh = zh_cache[root['menu_id']]
+        w('### %d. %s' % (sec, zh))
+        w('')
+        render_node(root, zh, 0, lines, ch_map, zh_cache, admin_titles, comp_zh)
+        w('')
+        sec += 1
+
+    if orphans:
+        w('### %d. \u5b64\u7acb\u83dc\u5355\uff08parent_id \u5728\u5e93\u4e2d\u4e0d\u5b58\u5728\uff09' % sec)
+        w('')
+        w('> \u5171 **%d** \u6761\uff0c\u6309\u539f parent_id \u5206\u7ec4\u5c55\u793a\u3002\u5efa\u8bae\u540e\u7eed\u6570\u636e\u6e05\u7406\u65f6\u4fee\u590d parent_id \u6216\u5220\u9664\u5e9f\u5f03\u8282\u70b9\u3002' % len(orphans))
+        w('')
+        for pid in sorted(orphan_groups.keys()):
+            w('#### parent_id = %s\uff08\u65e0\u6548\uff09' % pid)
+            w('')
+            for node in orphan_groups[pid]:
+                zh = zh_cache[node['menu_id']]
+                render_node(node, zh, 0, lines, ch_map, zh_cache, admin_titles, comp_zh)
+            w('')
+        sec += 1
+
+    w('---')
+    w('')
+    w('## \u9644\u5f55\uff1a\u6309\u6a21\u5757\u7edf\u8ba1')
+    w('')
+    w('| \u9876\u7ea7\u6a21\u5757 | \u76ee\u5f55 | \u83dc\u5355 | \u6309\u94ae | \u5408\u8ba1 |')
+    w('|----------|------|------|------|------|')
+
+    def count_subtree(root_id):
+        c = {'M': 0, 'C': 0, 'F': 0}
+        seen = set()
+
+        def walk(pid):
+            if pid in seen:
+                return
+            seen.add(pid)
+            for node in ch_map.get(pid, []):
+                c[node['menu_type']] += 1
+                walk(node['menu_id'])
+        walk(root_id)
+        return c
+
+    for root in biz_roots:
+        c = count_subtree(root['menu_id'])
+        total = sum(c.values()) - 1  # exclude self
+        w('| %s | %d | %d | %d | %d |' % (
+            zh_cache[root['menu_id']], c['M'], c['C'], c['F'], total))
+
+    w('')
+    w('*Generated by `sql/generate_menu_tree_zh.py`*')
+
+    with open(OUT, 'w', encoding='utf-8') as f:
+        f.write('\n'.join(lines))
+    print('Wrote', OUT, 'lines', len(lines))
+
+
+if __name__ == '__main__':
+    main()

+ 33 - 0
sql/inspect_tenant_menu.py

@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+DB = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+    user='root', password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas', charset='utf8mb4',
+)
+
+conn = pymysql.connect(**DB)
+cur = conn.cursor()
+cur.execute('SELECT id, tenant_code, tenant_name, db_name, status FROM tenant_info ORDER BY id')
+print('TENANTS:')
+for r in cur.fetchall():
+    print(r)
+
+checks = [
+    ('template_count', 'SELECT COUNT(*) FROM tenant_sys_menu'),
+    ('visible_roots', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' AND menu_type='M'"),
+    ('bad_admin', "SELECT COUNT(*) FROM tenant_sys_menu WHERE component LIKE 'admin/%' AND visible='0'"),
+    ('empty_M_dirs', "SELECT COUNT(*) FROM tenant_sys_menu m WHERE menu_type='M' AND visible='0' AND NOT EXISTS (SELECT 1 FROM tenant_sys_menu c WHERE c.parent_id=m.menu_id AND c.menu_type<>'F')"),
+    ('path_dup_qw', """SELECT COUNT(*) FROM (SELECT parent_id,path FROM tenant_sys_menu WHERE parent_id IN (35001,35002,35003,35004,35005,35006,35007) AND menu_type<>'F' AND visible='0' GROUP BY parent_id,path HAVING COUNT(*)>1) t"""),
+]
+print('STATS:')
+for name, sql in checks:
+    cur.execute(sql)
+    print(' ', name, cur.fetchone()[0])
+
+cur.execute("SELECT menu_id, menu_name, parent_id, path, visible FROM tenant_sys_menu WHERE parent_id IN (35100,35101,35102,35105,35106) AND visible='0' ORDER BY parent_id, order_num LIMIT 30")
+print('SYSTEM_SAMPLE:', cur.fetchall())
+
+cur.close()
+conn.close()

+ 34 - 0
sql/list_broken_paths.py

@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, path, component "
+    "FROM tenant_sys_menu WHERE menu_type='M' AND path LIKE 'm%' "
+    "ORDER BY parent_id, menu_id"
+)
+rows = cur.fetchall()
+print('M menus with m-prefix path:', len(rows))
+for r in rows:
+    print(r)
+
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, path FROM tenant_sys_menu "
+    "WHERE menu_id IN (35010,35011,35012,35013,35020,35021,35023,35050,35051,35052,35053,35060,35061,35062,35063,35070,35071,35072,35073,35074,35075,35080,35111,35112,35113,35114)"
+)
+print('\nsecondary module groups:')
+for r in cur.fetchall():
+    print(r)
+
+cur.close()
+c.close()

+ 1 - 0
sql/menu_tree_his.txt

@@ -0,0 +1 @@
+# his (root menu_id=32351)

+ 1 - 0
sql/menu_tree_lobster.txt

@@ -0,0 +1 @@
+# lobster (root menu_id=32355)

+ 1 - 0
sql/menu_tree_qw.txt

@@ -0,0 +1 @@
+# qw (root menu_id=32361)

+ 1 - 0
sql/menu_tree_store.txt

@@ -0,0 +1 @@
+# store (root menu_id=32369)

+ 1 - 0
sql/menu_tree_system.txt

@@ -0,0 +1 @@
+# system (root menu_id=32372)

+ 2 - 0
sql/menu_tree_system_all.txt

@@ -0,0 +1,2 @@
+# system_all (root menu_id=32372)
+

+ 75 - 0
sql/organize_tenant_sys_menu.sql

@@ -0,0 +1,75 @@
+-- ============================================================
+-- Organize tenant_sys_menu template (master DB: ylrz_saas)
+-- Backup first: CREATE TABLE tenant_sys_menu_bak AS SELECT * FROM tenant_sys_menu;
+-- ============================================================
+
+-- 1) Top-level visible module order (saasadminui top nav)
+UPDATE tenant_sys_menu SET order_num = 0  WHERE menu_id = 32644; -- index
+UPDATE tenant_sys_menu SET order_num = 1  WHERE menu_id = 32361; -- qw
+UPDATE tenant_sys_menu SET order_num = 2  WHERE menu_id = 32380; -- wx
+UPDATE tenant_sys_menu SET order_num = 3  WHERE menu_id = 32347; -- crm
+UPDATE tenant_sys_menu SET order_num = 4  WHERE menu_id = 32357; -- member
+UPDATE tenant_sys_menu SET order_num = 5  WHERE menu_id = 32351; -- his
+UPDATE tenant_sys_menu SET order_num = 6  WHERE menu_id = 32369; -- store
+UPDATE tenant_sys_menu SET order_num = 7  WHERE menu_id = 32353; -- live
+UPDATE tenant_sys_menu SET order_num = 8  WHERE menu_id = 32345; -- course
+UPDATE tenant_sys_menu SET order_num = 9  WHERE menu_id = 32348; -- fastGpt
+UPDATE tenant_sys_menu SET order_num = 10 WHERE menu_id = 32355; -- lobster
+UPDATE tenant_sys_menu SET order_num = 11 WHERE menu_id = 32331; -- ad
+UPDATE tenant_sys_menu SET order_num = 12 WHERE menu_id = 32372; -- system
+UPDATE tenant_sys_menu SET order_num = 13 WHERE menu_id = 32339; -- bill
+UPDATE tenant_sys_menu SET order_num = 14 WHERE menu_id = 32341; -- calendar
+UPDATE tenant_sys_menu SET order_num = 15 WHERE menu_id = 32368; -- statistics
+UPDATE tenant_sys_menu SET order_num = 16 WHERE menu_id = 32379; -- watch
+UPDATE tenant_sys_menu SET order_num = 17 WHERE menu_id = 35300; -- other
+
+-- Hide empty placeholder module
+UPDATE tenant_sys_menu SET visible = '1', status = '0'
+WHERE menu_id = 35129;
+
+-- Hide company root by id (path may have been corrupted by prior runs)
+UPDATE tenant_sys_menu SET visible = '1', status = '0'
+WHERE menu_id = 32344;
+
+-- 2) Hide platform-only root menus (should not be assigned to tenants)
+UPDATE tenant_sys_menu
+SET visible = '1', status = '0'
+WHERE parent_id = 0
+  AND path IN (
+    'admin', 'saas', 'proxy', 'tenant', 'monitor', 'moduleUsage',
+    'sysUser', 'tool', 'saler', 'company', 'qwechat', 'qwExternalContact',
+    'storeOrderOfflineItem', 'FastGptExtUserTag', 'addressBook', 'adv',
+    'aiChatQuality', 'aiSipCall', 'aiob', 'baidu', 'callRecord', 'chat',
+    'courseFinishTemp', 'food', 'gw', 'hisStore', 'liveData', 'medical',
+    'taskStatistics', 'todo', 'user', 'users', 'shop'
+  );
+
+-- Hide menus whose component points to super-admin pages
+UPDATE tenant_sys_menu
+SET visible = '1', status = '0'
+WHERE component LIKE 'admin/%';
+
+UPDATE tenant_sys_menu SET visible = '1', status = '0' WHERE menu_id = 29228;
+
+-- 3) Fix known wrong component paths for tenant UI
+UPDATE tenant_sys_menu SET component = 'crm/customer/index'
+WHERE menu_id = 29355 AND component = 'admin/crm/index';
+
+UPDATE tenant_sys_menu
+SET component = SUBSTRING(component, 7)
+WHERE component LIKE 'admin/%';
+
+-- 4) Verification queries
+-- SELECT menu_id, menu_name, order_num, path, visible
+-- FROM tenant_sys_menu WHERE parent_id = 0 AND menu_type = 'M' AND visible = '0'
+-- ORDER BY order_num, menu_id;
+
+-- SELECT menu_id, menu_name, component, visible
+-- FROM tenant_sys_menu WHERE component LIKE 'admin/%';
+
+-- SELECT COUNT(*) total,
+--        SUM(parent_id = 0) root_count,
+--        SUM(parent_id = 0 AND visible = '0') visible_root_count
+-- FROM tenant_sys_menu;
+
+-- Next step: run organize_tenant_sys_menu_subtree.sql for system/qw/store hierarchy

+ 35 - 0
sql/organize_tenant_sys_menu_full_readme.sql

@@ -0,0 +1,35 @@
+-- ============================================================
+-- Full tenant_sys_menu organize - executed via run_full_menu_organize_and_sync.py
+-- Master DB: ylrz_saas.tenant_sys_menu
+-- Tenant sync: ylrz_saas_tenant_1 / fs_tenant_* .sys_menu
+-- ============================================================
+
+-- Step 1: base organize (top-level order, hide platform menus, fix admin/ component)
+-- File: organize_tenant_sys_menu.sql
+
+-- Step 2: subtree reparent (system/qw/store/crm/live/course/fastGpt/member/statistics)
+-- File: organize_tenant_sys_menu_subtree.sql
+
+-- Step 3: post-process (Python)
+-- - unique path per parent (fix all path collisions)
+-- - hide empty secondary M directories
+-- - move watch menus from lobster to watch module (32850-32852, 32695-32697)
+-- - add core system pages menu_id 35201-35209
+
+-- Step 4: sync tenant sys_menu from template
+-- UPDATE structure fields; preserve tenant visible assignment unless template hidden
+-- INSERT missing menu_id with visible=1 (unassigned)
+-- HIDE menus not in template
+
+-- Re-run anytime:
+--   python sql/run_full_menu_organize_and_sync.py
+
+-- Sync single tenant only: set TENANT_CODES = ['test001'] in script
+
+-- Verification:
+SELECT COUNT(*) AS total FROM tenant_sys_menu;
+SELECT COUNT(*) AS visible_roots FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' AND menu_type='M';
+SELECT COUNT(*) AS path_dup FROM (
+  SELECT parent_id, path FROM tenant_sys_menu WHERE menu_type<>'F' AND visible='0'
+  GROUP BY parent_id, path HAVING COUNT(*)>1
+) t;

+ 227 - 0
sql/organize_tenant_sys_menu_subtree.sql

@@ -0,0 +1,227 @@
+-- ============================================================
+-- tenant_sys_menu subtree organize (system / qw / store / ...)
+-- Run AFTER organize_tenant_sys_menu.sql
+-- Backup: CREATE TABLE tenant_sys_menu_bak2 AS SELECT * FROM tenant_sys_menu;
+-- ============================================================
+
+-- ============================================================
+-- PART A: system (32372) - hide platform-only flat menus
+-- ============================================================
+UPDATE tenant_sys_menu SET visible = '1', status = '0'
+WHERE parent_id = 32372
+  AND menu_id IN (
+    32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,
+    32401,32402,32403,32404,32405,
+    32698,32699,32700,32701,32702,32703,
+    32756,32757,32758,32759,32760,32761,32762,32763,
+    32837,32839,32840,32841,
+    35108
+  );
+
+-- Move statistics pages out of sysOrg (35100) -> statistics root (32368)
+UPDATE tenant_sys_menu SET parent_id = 32368, order_num = order_num
+WHERE menu_id IN (29194, 32769, 32770, 32771);
+
+-- sysOrg (35100): organization
+UPDATE tenant_sys_menu SET parent_id = 35100, order_num = 10
+WHERE menu_id IN (32431,32432,32433,32436,32437,32438,32443,32455,32456,32457,32473,32475,32476,32477);
+
+-- sysPerm (35101): roles & menus
+UPDATE tenant_sys_menu SET parent_id = 35101, order_num = 10
+WHERE menu_id IN (32440,32447,32448,32449);
+
+-- sysVoice (35102): SMS / voice / workflow
+UPDATE tenant_sys_menu SET parent_id = 35102, order_num = 10
+WHERE menu_id IN (32427,32451,32452,32453,32454,32470,32471,32472);
+
+-- sysLog (35105): audit logs
+UPDATE tenant_sys_menu SET parent_id = 35105, order_num = 10
+WHERE menu_id IN (32439,32442);
+
+-- sysConfig (35106): settings only (keep platform-neutral pages)
+UPDATE tenant_sys_menu SET parent_id = 35106, order_num = 10
+WHERE menu_id IN (32430,32434,32478,32479,32480,32832,32833);
+
+-- Move finance pages system -> bill module
+UPDATE tenant_sys_menu SET parent_id = 35114, order_num = 10 WHERE menu_id = 32441; -- money logs
+UPDATE tenant_sys_menu SET parent_id = 35111, order_num = 10 WHERE menu_id IN (32445); -- recharge
+UPDATE tenant_sys_menu SET parent_id = 35112, order_num = 10 WHERE menu_id = 32435; -- deduct
+UPDATE tenant_sys_menu SET parent_id = 35113, order_num = 10 WHERE menu_id IN (32444,32446,32474); -- profit/redpacket
+
+-- Move wx pages system -> wx module
+UPDATE tenant_sys_menu SET parent_id = 35010, order_num = 10 WHERE menu_id = 32482;
+UPDATE tenant_sys_menu SET parent_id = 35011, order_num = 10 WHERE menu_id = 32483;
+UPDATE tenant_sys_menu SET parent_id = 35012, order_num = 10 WHERE menu_id = 32484;
+UPDATE tenant_sys_menu SET parent_id = 35013, order_num = 10 WHERE menu_id = 32485;
+
+-- Lobster duplicate under system -> lobster workflow group
+UPDATE tenant_sys_menu SET parent_id = 35080, order_num = 99 WHERE menu_id = 32481;
+
+-- Unique path for company/* menus (fix path=company collision)
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(component, '/', 2), '/', -1)
+WHERE component LIKE 'company/%/%'
+  AND parent_id IN (35100,35101,35102,35105,35106,35111,35112,35113,35114);
+
+UPDATE tenant_sys_menu SET path = 'companyIndex' WHERE menu_id = 32473;
+UPDATE tenant_sys_menu SET path = 'companySet' WHERE menu_id = 32832;
+UPDATE tenant_sys_menu SET path = 'userProfile' WHERE menu_id = 32833;
+
+-- ============================================================
+-- PART B: qw (32361) - reparent into secondary groups
+-- ============================================================
+
+-- qwMsg (35001)
+UPDATE tenant_sys_menu SET parent_id = 35001, order_num = 10
+WHERE menu_id IN (32704,32705,32739,32740,32749,32745);
+
+-- qwCustomer (35002)
+UPDATE tenant_sys_menu SET parent_id = 35002, order_num = 10
+WHERE menu_id IN (32708,32714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,32726,32755);
+
+-- qwGroup (35003)
+UPDATE tenant_sys_menu SET parent_id = 35003, order_num = 10
+WHERE menu_id IN (32733,32734,32735,32736,32737,32738);
+
+-- qwMoments (35004)
+UPDATE tenant_sys_menu SET parent_id = 35004, order_num = 10
+WHERE menu_id IN (32727,32728,32729,32730,32731,32732);
+
+-- qwDrainage (35005)
+UPDATE tenant_sys_menu SET parent_id = 35005, order_num = 10
+WHERE menu_id IN (32706);
+
+-- qwTag (35006)
+UPDATE tenant_sys_menu SET parent_id = 35006, order_num = 10
+WHERE menu_id IN (32900,32751,32752);
+
+-- qwSetting (35007)
+UPDATE tenant_sys_menu SET parent_id = 35007, order_num = 10
+WHERE menu_id IN (32707,32713,32741,32744,32746,32753,32754);
+
+-- Unique path for qw/* (fix path=qw collision)
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(component, '/', 2), '/', -1)
+WHERE component LIKE 'qw/%'
+  AND parent_id IN (35001,35002,35003,35004,35005,35006,35007,32361);
+
+UPDATE tenant_sys_menu SET path = 'qwExternalContact' WHERE menu_id = 32755;
+UPDATE tenant_sys_menu SET path = 'QwWorkTaskQw' WHERE menu_id = 32705;
+
+-- ============================================================
+-- PART C: store (32369) - hide legacy duplicate + reparent store/*
+-- ============================================================
+
+-- Hide hisStore duplicate set (keep store/* canonical)
+UPDATE tenant_sys_menu SET visible = '1', status = '0'
+WHERE menu_id BETWEEN 32591 AND 32643;
+
+UPDATE tenant_sys_menu SET visible = '1', status = '0'
+WHERE menu_id IN (32766,32767,32768,32826);
+
+-- storeOrder (35040): orders & reports
+UPDATE tenant_sys_menu SET parent_id = 35040, order_num = 10
+WHERE menu_id IN (
+  32772,32773,32777,32778,32781,32787,
+  32806,32807,32808,32809,32810,32811
+);
+
+-- storeProduct (35041): products & shipping
+UPDATE tenant_sys_menu SET parent_id = 35041, order_num = 10
+WHERE menu_id IN (
+  32790,32791,32792,32794,32795,32796,
+  32812,32813,32814,32815,32816,32817,32818,32819,32820
+);
+
+-- storeOps (35042): shop ops / coupon / home / export
+UPDATE tenant_sys_menu SET parent_id = 35042, order_num = 10
+WHERE menu_id IN (
+  32774,32775,32776,32779,32780,32782,32783,32784,32785,32786,32788,32789,32793,32797,
+  32801,32802,32803,32804,32805,32821,32822,32823,32824,32825
+);
+
+-- Unique path for store/* (fix path=store collision)
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(component, '/index/index', '/index'), '/', 2), '/', -1)
+WHERE component LIKE 'store/%'
+  AND parent_id IN (35040,35041,35042,32369);
+
+-- ============================================================
+-- PART D: other noisy modules (quick fixes)
+-- ============================================================
+
+-- CRM: move flat pages into crmCustomer (35020)
+UPDATE tenant_sys_menu SET parent_id = 35020, order_num = 10
+WHERE menu_id IN (32521,32522,32523,32524,32525,32526,32527)
+  AND parent_id = 32347;
+
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(component, '/', 2), '/', -1)
+WHERE component LIKE 'crm/%' AND parent_id IN (35020,35021,35023,32347);
+
+-- fastGpt: move chat pages into aiChat (35070)
+UPDATE tenant_sys_menu SET parent_id = 35070, order_num = 10
+WHERE menu_id BETWEEN 32528 AND 32537 AND parent_id = 32348;
+
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(component, '/', 2), '/', -1)
+WHERE component LIKE 'fastGpt/%' AND parent_id IN (35070,35071,35072,35073,35074,35075,32348);
+
+-- live: move flat pages into liveOps (35050)
+UPDATE tenant_sys_menu SET parent_id = 35050, order_num = 10
+WHERE menu_id BETWEEN 32645 AND 32675 AND parent_id = 32353;
+
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(component, '/index/index', '/index'), '/', 2), '/', -1)
+WHERE component LIKE 'live/%' AND parent_id IN (35050,35051,35052,35053,32353);
+
+-- course: move flat pages into courseContent (35060)
+UPDATE tenant_sys_menu SET parent_id = 35060, order_num = 10
+WHERE menu_id BETWEEN 32486 AND 32519 AND parent_id = 32345;
+
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(component, '/index/index', '/index'), '/', 2), '/', -1)
+WHERE component LIKE 'course/%' AND parent_id IN (35060,35061,35062,35063,32345);
+
+-- member: move flat pages under member root (keep flat but unique path)
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(component, '/index/index', '/index'), '/', 2), '/', -1)
+WHERE component LIKE 'user/%' AND parent_id = 32357;
+
+-- statistics: unique path
+UPDATE tenant_sys_menu
+SET path = SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(component, '/index/index', '/index'), '/', 2), '/', -1)
+WHERE parent_id = 32368 AND component IS NOT NULL AND component <> '';
+
+-- ============================================================
+-- PART E: optional - add missing core system pages (tenant admin)
+-- Skip if already exists. Adjust menu_id if conflict.
+-- ============================================================
+-- INSERT INTO tenant_sys_menu (menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status, is_frame, is_cache, create_by, create_time)
+-- VALUES
+-- (35201, '???????', 35101, 1, 'user', 'system/user/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35202, '???????', 35101, 2, 'role', 'system/role/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35203, '???????', 35101, 3, 'menu', 'system/menu/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35204, '???????', 35100, 1, 'dept', 'system/dept/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35205, '??��????', 35100, 2, 'post', 'system/post/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35206, '??????', 35106, 3, 'dict', 'system/dict/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35207, '????????', 35106, 4, 'config', 'system/config/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35208, '??????', 35106, 5, 'notice', 'system/notice/index', 'C', '0', '0', 1, 0, 'admin', NOW()),
+-- (35209, '��?????', 35106, 6, 'keyword', 'system/keyword/index', 'C', '0', '0', 1, 0, 'admin', NOW());
+
+-- ============================================================
+-- Verification
+-- ============================================================
+-- SELECT menu_id, menu_name, parent_id, path, component, visible
+-- FROM tenant_sys_menu WHERE parent_id = 32372 AND visible = '0' ORDER BY order_num, menu_id;
+
+-- SELECT menu_id, menu_name, parent_id, path FROM tenant_sys_menu
+-- WHERE parent_id IN (35100,35101,35102,35105,35106) AND visible = '0' ORDER BY parent_id, order_num;
+
+-- SELECT parent_id, path, COUNT(*) cnt FROM tenant_sys_menu
+-- WHERE parent_id IN (35001,35002,35003,35004,35005,35006,35007) AND menu_type <> 'F'
+-- GROUP BY parent_id, path HAVING cnt > 1;
+
+-- SELECT parent_id, path, COUNT(*) cnt FROM tenant_sys_menu
+-- WHERE parent_id IN (35040,35041,35042) AND menu_type <> 'F'
+-- GROUP BY parent_id, path HAVING cnt > 1;

+ 348 - 0
sql/run_full_menu_organize_and_sync.py

@@ -0,0 +1,348 @@
+# -*- coding: utf-8 -*-
+"""
+Full organize tenant_sys_menu template and sync structure to tenant sys_menu.
+Preserves tenant assignment (visible) except when template marks menu hidden.
+"""
+import os
+import pymysql
+
+MASTER = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+    autocommit=False,
+)
+
+SQL_DIR = os.path.dirname(os.path.abspath(__file__))
+SQL_FILES = [
+    'organize_tenant_sys_menu.sql',
+    'organize_tenant_sys_menu_subtree.sql',
+    'fix_tenant_sys_menu_paths.sql',
+    'fix_tenant_sys_menu_other_parent.sql',
+]
+
+OTHER_MENU_ID = 35300
+ARCHIVE_PARENT_ID = 35300
+
+
+def other_subtree_ids(menus, root=OTHER_MENU_ID):
+    ids = set()
+    stack = [root]
+    while stack:
+        mid = stack.pop()
+        for r in menus.values():
+            if r['parent_id'] == mid and r['menu_id'] not in ids:
+                ids.add(r['menu_id'])
+                stack.append(r['menu_id'])
+    return ids
+
+# Directory (M) paths must never be overwritten by dedup logic
+MODULE_PATHS = {
+    32644: 'index', 32361: 'qw', 32380: 'wx', 32347: 'crm', 32357: 'member',
+    32351: 'his', 32369: 'store', 32353: 'live', 32345: 'course', 32348: 'fastGpt',
+    32355: 'lobster', 32331: 'ad', 32372: 'system', 32339: 'bill', 32341: 'calendar',
+    32368: 'statistics', 32379: 'watch',
+    35100: 'sysOrg', 35101: 'sysPerm', 35102: 'sysVoice', 35105: 'sysLog', 35106: 'sysConfig',
+    35001: 'qwMsg', 35002: 'qwCustomer', 35003: 'qwGroup', 35004: 'qwMoments',
+    35005: 'qwDrainage', 35006: 'qwTag', 35007: 'qwSetting',
+    35040: 'storeOrder', 35041: 'storeProduct', 35042: 'storeOps',
+    35010: 'wxAccount', 35011: 'wxDialog', 35012: 'wxUser', 35013: 'wxUserGroup',
+    35020: 'crmCustomer', 35050: 'liveOps', 35060: 'courseContent', 35070: 'aiChat',
+    35080: 'lobsterFlow', 35090: 'adOps',
+    35111: 'billRecharge', 35112: 'billDeduct', 35113: 'billProfit', 35114: 'billMoneyLog',
+    35300: 'other',
+}
+
+CORE_SYSTEM_MENUS = [
+    (35201, '\u7528\u6237\u7ba1\u7406', 35101, 1, 'sysUser', 'system/user/index', 'C', 'user'),
+    (35202, '\u89d2\u8272\u7ba1\u7406', 35101, 2, 'sysRole', 'system/role/index', 'C', 'peoples'),
+    (35203, '\u83dc\u5355\u7ba1\u7406', 35101, 3, 'sysMenu', 'system/menu/index', 'C', 'tree-table'),
+    (35204, '\u90e8\u95e8\u7ba1\u7406', 35100, 1, 'sysDept', 'system/dept/index', 'C', 'tree'),
+    (35205, '\u5c97\u4f4d\u7ba1\u7406', 35100, 2, 'sysPost', 'system/post/index', 'C', 'post'),
+    (35206, '\u5b57\u5178\u7ba1\u7406', 35106, 3, 'sysDict', 'system/dict/index', 'C', 'dict'),
+    (35207, '\u53c2\u6570\u8bbe\u7f6e', 35106, 4, 'sysConfigPage', 'system/config/index', 'C', 'edit'),
+    (35208, '\u901a\u77e5\u516c\u544a', 35106, 5, 'sysNotice', 'system/notice/index', 'C', 'message'),
+    (35209, '\u8fdd\u89c4\u8bcd\u8bed', 35106, 6, 'sysKeyword', 'system/keyword/index', 'C', 'education'),
+]
+
+WATCH_MOVE_TO_32379 = [32850, 32851, 32852]
+TENANT_CODES = None
+
+
+def load_sql_statements(path):
+    for enc in ('utf-8', 'utf-8-sig', 'gbk'):
+        try:
+            with open(path, 'r', encoding=enc) as f:
+                content = f.read()
+            break
+        except UnicodeDecodeError:
+            content = None
+    if content is None:
+        with open(path, 'r', encoding='utf-8', errors='ignore') as f:
+            content = f.read()
+    lines = [ln for ln in content.splitlines() if not ln.strip().startswith('--')]
+    return [p.strip() for p in '\n'.join(lines).split(';') if p.strip()]
+
+
+def path_from_component(menu_id, component):
+    comp = (component or '').replace('/index/index', '/index').strip()
+    if not comp or comp == '#':
+        return 'm' + str(menu_id)
+    parts = [p for p in comp.split('/') if p]
+    if len(parts) >= 2 and parts[-1] == 'index':
+        return parts[-2]
+    if parts:
+        return parts[-1]
+    return 'm' + str(menu_id)
+
+
+def fetch_menus(cur):
+    cur.execute('SELECT * FROM tenant_sys_menu')
+    cols = [d[0] for d in cur.description]
+    return {dict(zip(cols, raw))['menu_id']: dict(zip(cols, raw)) for raw in cur.fetchall()}
+
+
+def run_base_sql(cur, conn):
+    for fn in SQL_FILES:
+        fp = os.path.join(SQL_DIR, fn)
+        if not os.path.exists(fp):
+            continue
+        stmts = load_sql_statements(fp)
+        total = 0
+        for stmt in stmts:
+            cur.execute(stmt)
+            total += cur.rowcount
+        conn.commit()
+        print('[SQL] %s statements=%s rowcount=%s' % (fn, len(stmts), total))
+
+
+def post_process(cur, conn, menus):
+    other_ids = other_subtree_ids(menus)
+
+    for mid in WATCH_MOVE_TO_32379:
+        if mid in menus:
+            menus[mid]['parent_id'] = 32379
+    for mid in (32695, 32696, 32697):
+        if mid in menus:
+            menus[mid]['parent_id'] = 32379
+    if 35053 in menus and 32676 in menus:
+        menus[35053]['visible'] = '1'
+
+    for r in menus.values():
+        if r['menu_id'] in other_ids or r['menu_id'] == OTHER_MENU_ID:
+            continue
+        if r['menu_type'] != 'M' or r['visible'] != '0':
+            continue
+        children = [x for x in menus.values() if x['parent_id'] == r['menu_id'] and x['menu_type'] != 'F']
+        if not children:
+            r['visible'] = '1'
+
+    if OTHER_MENU_ID in menus:
+        menus[OTHER_MENU_ID]['visible'] = '0'
+        menus[OTHER_MENU_ID]['menu_name'] = '\u5176\u4ed6'
+        menus[OTHER_MENU_ID]['path'] = 'other'
+    for mid in other_ids:
+        if mid in menus:
+            menus[mid]['visible'] = '0'
+            menus[mid]['status'] = '0'
+
+    for mid, path in MODULE_PATHS.items():
+        if mid in menus:
+            menus[mid]['path'] = path
+
+    groups = {}
+    for r in menus.values():
+        if r['menu_type'] != 'C' or r['visible'] != '0':
+            continue
+        groups.setdefault(r['parent_id'], []).append(r)
+
+    for items in groups.values():
+        used = set()
+        for r in sorted(items, key=lambda x: (x.get('order_num') or 0, x['menu_id'])):
+            base = path_from_component(r['menu_id'], r.get('component'))
+            path = base
+            n = 2
+            while path in used:
+                path = '%s%s' % (base, n)
+                n += 1
+            used.add(path)
+            r['path'] = path
+
+    manual = {
+        32455: 'companyUserCard', 32456: 'companyUserProfile', 32705: 'QwWorkTaskQw',
+        32755: 'qwExternalContact', 32473: 'companyIndex', 32832: 'companySet',
+        32833: 'userProfile', 29194: 'statisticsIndex', 29227: 'moduleUsageIndex',
+        32693: 'moduleUsagePage',
+    }
+    for mid, path in manual.items():
+        if mid in menus:
+            menus[mid]['path'] = path
+
+    for mid, path in MODULE_PATHS.items():
+        if mid in menus:
+            menus[mid]['path'] = path
+
+    new_ids = set()
+    for item in CORE_SYSTEM_MENUS:
+        mid, name, pid, order_num, path, comp, mtype, icon = item
+        if mid in menus:
+            menus[mid]['menu_name'] = name
+            menus[mid]['path'] = path
+        elif mid not in menus:
+            new_ids.add(mid)
+            menus[mid] = {
+                'menu_id': mid, 'menu_name': name, 'parent_id': pid, 'order_num': order_num,
+                'path': path, 'component': comp, 'query': None, 'is_frame': 1, 'is_cache': 0,
+                'menu_type': mtype, 'visible': '0', 'status': '0', 'perms': None, 'icon': icon,
+                'create_by': 'admin', 'create_time': None, 'update_by': None,
+                'update_time': None, 'remark': '[organize:auto-add]',
+            }
+
+    upsert_sql = """
+    REPLACE INTO tenant_sys_menu
+    (menu_id, menu_name, parent_id, order_num, path, component, query,
+     is_frame, is_cache, menu_type, visible, status, perms, icon,
+     create_by, create_time, update_by, update_time, remark)
+    VALUES (%(menu_id)s, %(menu_name)s, %(parent_id)s, %(order_num)s, %(path)s, %(component)s, %(query)s,
+            %(is_frame)s, %(is_cache)s, %(menu_type)s, %(visible)s, %(status)s, %(perms)s, %(icon)s,
+            %(create_by)s, IFNULL(%(create_time)s, NOW()), %(update_by)s, %(update_time)s, %(remark)s)
+    """
+    update_sql = """
+    UPDATE tenant_sys_menu SET
+      menu_name=%(menu_name)s, parent_id=%(parent_id)s, order_num=%(order_num)s,
+      path=%(path)s, component=%(component)s, menu_type=%(menu_type)s,
+      visible=%(visible)s, status=%(status)s, icon=%(icon)s
+    WHERE menu_id=%(menu_id)s
+    """
+    for r in menus.values():
+        if r['menu_id'] in new_ids:
+            cur.execute(upsert_sql, r)
+        else:
+            cur.execute(update_sql, r)
+    conn.commit()
+    print('[POST] rows persisted=%s new=%s' % (len(menus), len(new_ids)))
+
+
+def verify(cur):
+    checks = [
+        ('total', 'SELECT COUNT(*) FROM tenant_sys_menu'),
+        ('visible_roots', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' AND menu_type='M'"),
+        ('bad_admin', "SELECT COUNT(*) FROM tenant_sys_menu WHERE component LIKE 'admin/%' AND visible='0'"),
+        ('path_dup', """
+            SELECT COUNT(*) FROM (
+              SELECT parent_id, path FROM tenant_sys_menu
+              WHERE menu_type<>'F' AND visible='0'
+              GROUP BY parent_id, path HAVING COUNT(*)>1
+            ) t
+        """),
+        ('empty_visible_m', """
+            SELECT COUNT(*) FROM tenant_sys_menu m
+            WHERE m.menu_type='M' AND m.visible='0'
+              AND NOT EXISTS (
+                SELECT 1 FROM tenant_sys_menu c
+                WHERE c.parent_id=m.menu_id AND c.menu_type<>'F' AND c.visible='0'
+              )
+        """),
+        ('broken_m_paths', "SELECT COUNT(*) FROM tenant_sys_menu WHERE menu_type='M' AND path REGEXP '^m[0-9]+$'"),
+        ('hidden_root_count', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=0 AND visible='1' AND menu_type='M'"),
+        ('other_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35300"),
+    ]
+    print('[VERIFY template]')
+    for name, sql in checks:
+        cur.execute(sql)
+        print('  %s=%s' % (name, cur.fetchone()[0]))
+
+
+def sync_tenant(cur, conn, tenant_db):
+    db = tenant_db.replace('`', '')
+    cur.execute("""
+        UPDATE `{db}`.sys_menu t
+        INNER JOIN tenant_sys_menu s ON t.menu_id = s.menu_id
+        SET
+          t.menu_name = s.menu_name,
+          t.parent_id = s.parent_id,
+          t.order_num = s.order_num,
+          t.path = s.path,
+          t.component = s.component,
+          t.menu_type = s.menu_type,
+          t.icon = s.icon,
+          t.status = s.status,
+          t.is_frame = s.is_frame,
+          t.is_cache = s.is_cache,
+          t.query = s.query,
+          t.perms = s.perms,
+          t.visible = CASE WHEN s.visible = '1' THEN '1' ELSE t.visible END
+    """.format(db=db))
+    updated = cur.rowcount
+
+    cur.execute("""
+        INSERT INTO `{db}`.sys_menu
+        (menu_id, menu_name, parent_id, order_num, path, component, query,
+         is_frame, is_cache, menu_type, visible, status, perms, icon,
+         create_by, create_time, update_by, update_time, remark)
+        SELECT s.menu_id, s.menu_name, s.parent_id, s.order_num, s.path, s.component, s.query,
+               s.is_frame, s.is_cache, s.menu_type, '1', s.status, s.perms, s.icon,
+               IFNULL(s.create_by,'admin'), IFNULL(s.create_time, NOW()), s.update_by, s.update_time, s.remark
+        FROM tenant_sys_menu s
+        LEFT JOIN `{db}`.sys_menu t ON t.menu_id = s.menu_id
+        WHERE t.menu_id IS NULL
+    """.format(db=db))
+    inserted = cur.rowcount
+
+    cur.execute("""
+        UPDATE `{db}`.sys_menu t
+        LEFT JOIN tenant_sys_menu s ON t.menu_id = s.menu_id
+        SET t.visible = '1'
+        WHERE s.menu_id IS NULL
+    """.format(db=db))
+    orphaned = cur.rowcount
+    conn.commit()
+    return updated, inserted, orphaned
+
+
+def main():
+    conn = pymysql.connect(**MASTER)
+    cur = conn.cursor()
+    try:
+        run_base_sql(cur, conn)
+        menus = fetch_menus(cur)
+        post_process(cur, conn, menus)
+        verify(cur)
+
+        cur.execute('SELECT tenant_code, db_name, status FROM tenant_info ORDER BY id')
+        tenants = cur.fetchall()
+        if TENANT_CODES:
+            tenants = [t for t in tenants if t[0] in TENANT_CODES]
+
+        print('[SYNC tenants]')
+        for code, db_name, status in tenants:
+            if not db_name or status not in (1, '1'):
+                print('  skip %s status=%s' % (code, status))
+                continue
+            cur.execute('SELECT COUNT(*) FROM information_schema.SCHEMATA WHERE SCHEMA_NAME=%s', (db_name,))
+            if cur.fetchone()[0] == 0:
+                print('  skip %s db missing: %s' % (code, db_name))
+                continue
+            cur.execute(
+                'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=%s AND TABLE_NAME=%s',
+                (db_name, 'sys_menu'),
+            )
+            if cur.fetchone()[0] == 0:
+                print('  skip %s no sys_menu in %s' % (code, db_name))
+                continue
+            u, i, o = sync_tenant(cur, conn, db_name)
+            print('  %s (%s): updated=%s inserted=%s hidden_orphan=%s' % (code, db_name, u, i, o))
+        print('DONE')
+    except Exception:
+        conn.rollback()
+        raise
+    finally:
+        cur.close()
+        conn.close()
+
+
+if __name__ == '__main__':
+    main()

+ 113 - 0
sql/run_organize_menu.py

@@ -0,0 +1,113 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+DB = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+    autocommit=False,
+)
+
+FILES = [
+    r'f:\project\Saas\ylrz_saas_his_scrm\sql\organize_tenant_sys_menu.sql',
+    r'f:\project\Saas\ylrz_saas_his_scrm\sql\organize_tenant_sys_menu_subtree.sql',
+]
+
+RESTORE_SQL = """
+INSERT INTO tenant_sys_menu
+SELECT b.*
+FROM tenant_sys_menu_bak b
+LEFT JOIN tenant_sys_menu t ON t.menu_id = b.menu_id
+WHERE t.menu_id IS NULL
+"""
+
+
+def load_statements(path):
+    for enc in ('utf-8', 'utf-8-sig', 'gbk'):
+        try:
+            with open(path, 'r', encoding=enc) as f:
+                content = f.read()
+            break
+        except UnicodeDecodeError:
+            content = None
+    if content is None:
+        with open(path, 'r', encoding='utf-8', errors='ignore') as f:
+            content = f.read()
+    lines = []
+    for line in content.splitlines():
+        if line.strip().startswith('--'):
+            continue
+        lines.append(line)
+    return [p.strip() for p in '\n'.join(lines).split(';') if p.strip()]
+
+
+def main():
+    conn = pymysql.connect(**DB)
+    cur = conn.cursor()
+    try:
+        cur.execute('SELECT COUNT(*) FROM tenant_sys_menu')
+        before = cur.fetchone()[0]
+        cur.execute(RESTORE_SQL)
+        restored = cur.rowcount
+        conn.commit()
+        cur.execute('SELECT COUNT(*) FROM tenant_sys_menu')
+        after_restore = cur.fetchone()[0]
+        print('restore: before=%s restored=%s after=%s' % (before, restored, after_restore))
+
+        for fp in FILES:
+            stmts = load_statements(fp)
+            affected = 0
+            for stmt in stmts:
+                cur.execute(stmt)
+                affected += cur.rowcount
+            conn.commit()
+            print('FILE %s: statements=%s rowcount_sum=%s' % (fp.split('\\')[-1], len(stmts), affected))
+
+        checks = [
+            ('total', 'SELECT COUNT(*) FROM tenant_sys_menu'),
+            ('visible_roots', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' AND menu_type='M'"),
+            ('bad_admin_visible', "SELECT COUNT(*) FROM tenant_sys_menu WHERE component LIKE 'admin/%' AND visible='0'"),
+            ('sys_35100_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35100 AND visible='0' AND menu_type<>'F'"),
+            ('sys_35101_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35101 AND visible='0' AND menu_type<>'F'"),
+            ('sys_35106_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35106 AND visible='0' AND menu_type<>'F'"),
+            ('qw_35001_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35001 AND visible='0' AND menu_type<>'F'"),
+            ('qw_35002_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35002 AND visible='0' AND menu_type<>'F'"),
+            ('store_35040_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35040 AND visible='0' AND menu_type<>'F'"),
+            ('hidden_hisstore', "SELECT COUNT(*) FROM tenant_sys_menu WHERE menu_id BETWEEN 32591 AND 32643 AND visible='1'"),
+            ('qw_path_dup', """
+                SELECT COUNT(*) FROM (
+                  SELECT parent_id, path FROM tenant_sys_menu
+                  WHERE parent_id IN (35001,35002,35003,35004,35005,35006,35007)
+                    AND menu_type <> 'F' AND visible='0'
+                  GROUP BY parent_id, path HAVING COUNT(*)>1
+                ) t
+            """),
+            ('store_path_dup', """
+                SELECT COUNT(*) FROM (
+                  SELECT parent_id, path FROM tenant_sys_menu
+                  WHERE parent_id IN (35040,35041,35042)
+                    AND menu_type <> 'F' AND visible='0'
+                  GROUP BY parent_id, path HAVING COUNT(*)>1
+                ) t
+            """),
+        ]
+        print('VERIFY:')
+        for name, sql in checks:
+            cur.execute(sql)
+            print('  %s=%s' % (name, cur.fetchone()[0]))
+
+        print('EXEC_OK')
+    except Exception as e:
+        conn.rollback()
+        print('EXEC_FAIL: %s' % e)
+        raise
+    finally:
+        cur.close()
+        conn.close()
+
+
+if __name__ == '__main__':
+    main()

+ 40 - 0
sql/simulate_api_visible.py

@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+def build_tree(rows, parent_id=0):
+    tree = []
+    for r in rows:
+        if r['parent_id'] == parent_id:
+            node = dict(r)
+            node['children'] = build_tree(rows, r['menu_id'])
+            tree.append(node)
+    tree.sort(key=lambda x: (x.get('order_num') or 0, x['menu_id']))
+    return tree
+
+def print_tree(nodes, depth=0, max_depth=2):
+    for n in nodes:
+        print('  ' * depth + '- %s (id=%s, path=%s)' % (n['menu_name'], n['menu_id'], n['path']))
+        if depth < max_depth and n.get('children'):
+            print_tree(n['children'], depth + 1, max_depth)
+
+c = pymysql.connect(**M)
+cur = c.cursor(pymysql.cursors.DictCursor)
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, order_num, path, menu_type, visible "
+    "FROM tenant_sys_menu WHERE visible='0' ORDER BY parent_id, order_num, menu_id"
+)
+rows = cur.fetchall()
+tree = build_tree(rows, 0)
+print('API visible=0 top level count:', len(tree))
+print_tree(tree, 0, 2)
+cur.close()
+c.close()

+ 58 - 0
sql/simulate_tenant_menu_api.py

@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+"""Simulate /tenant/tenant/tenantMenu/list API tree output."""
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+def build_tree(rows, parent_id=0):
+    tree = []
+    for r in rows:
+        if r['parent_id'] == parent_id:
+            node = dict(r)
+            node['children'] = build_tree(rows, r['menu_id'])
+            tree.append(node)
+    tree.sort(key=lambda x: (x.get('order_num') or 0, x['menu_id']))
+    return tree
+
+def print_tree(nodes, depth=0, max_depth=2):
+    for n in nodes:
+        vis = 'show' if n['visible'] == '0' else 'hide'
+        print('  ' * depth + '- [%s] %s (id=%s, path=%s, order=%s)' % (
+            n['menu_type'], n['menu_name'], n['menu_id'], n['path'], n['order_num']))
+        if depth < max_depth and n.get('children'):
+            print_tree(n['children'], depth + 1, max_depth)
+
+c = pymysql.connect(**M)
+cur = c.cursor(pymysql.cursors.DictCursor)
+cur.execute(
+    'SELECT menu_id, menu_name, parent_id, order_num, path, component, menu_type, visible, status '
+    'FROM tenant_sys_menu ORDER BY parent_id, order_num, menu_id'
+)
+rows = cur.fetchall()
+tree = build_tree(rows, 0)
+
+print('=== TOP LEVEL (parent_id=0) count=%s ===' % len(tree))
+print_tree(tree, 0, 1)
+
+print('\n=== VISIBLE TOP LEVEL only ===')
+print_tree([n for n in tree if n['visible'] == '0'], 0, 2)
+
+print('\n=== system subtree (32372) ===')
+sys_node = next((n for n in tree if n['menu_id'] == 32372), None)
+if sys_node:
+    print_tree([sys_node], 0, 2)
+
+print('\n=== qw subtree (32361) ===')
+qw_node = next((n for n in tree if n['menu_id'] == 32361), None)
+if qw_node:
+    print_tree([qw_node], 0, 2)
+
+cur.close()
+c.close()

+ 94 - 0
sql/tenant_sys_menu_target_structure.txt

@@ -0,0 +1,94 @@
+租户管理端菜单 - 整理后目标结构(tenant_sys_menu)
+============================================================
+
+一、系统管理 (32372, path=system)
+--------------------------------
+├── 组织管理 (35100, sysOrg)
+│   ├── 企业申请/绑定/客户 (32431-32433)
+│   ├── 部门/岗位/用户岗位 (32436,32443,32457)
+│   ├── 域名/域名绑定 (32437-32438)
+│   ├── 用户名片/资料 (32455-32456)
+│   ├── 企业首页 (32473)
+│   └── 排班/报表 (32475-32477)
+├── 权限管理 (35101, sysPerm)
+│   ├── 企业菜单 (32440)
+│   └── 企业角色/角色部门/角色菜单 (32447-32449)
+│   └── [建议补] system/user, system/role, system/menu, system/dept, system/post
+├── 通信管理 (35102, sysVoice)
+│   ├── AI外呼/工作流 (32427,32470-32472)
+│   └── 短信套餐/订单/模板/日志 (32451-32454)
+├── 日志管理 (35105, sysLog)
+│   ├── 登录日志 (32439)
+│   └── 操作日志 (32442)
+└── 系统设置 (35106, sysConfig)
+    ├── AI工作流/企业配置 (32430,32434)
+    ├── 流量/流量日志 (32478-32479)
+    ├── 外部工作流API (32480)
+    ├── 系统设置 (32832)
+    └── 个人中心 (32833)
+
+已从 system 迁出:
+- 29194,32769-32771 → 数据统计 (32368)
+- 32482-32485 → 微信管理 wx 子模块
+- 32435,32441,32444-32446,32474 → 财务管理 bill 子模块
+- 32481 → 龙虾引擎/工作流 (35080)
+
+已隐藏(不下发租户):
+- 32385-32405 admin/*
+- 32698-32703 proxy/*
+- 32756-32763 saas/*
+- 32837 tenant, 32839-32841 tool/*
+- 35108 sysSaas
+
+
+二、企微管理 (32361, path=qw)
+--------------------------------
+├── 消息管理 (35001, qwMsg)
+│   └── 工作任务/群消息/消息记录/推送统计 (32704,32705,32739,32740,32749,32745)
+├── 客户管理 (35002, qwCustomer)
+│   └── 联系人/引流/转接/流失/外部联系人等 (32708,32714-32726,32755)
+├── 群聊管理 (35003, qwGroup)
+│   └── 群统计/转接/活码/群消息等 (32733-32738)
+├── 朋友圈 (35004, qwMoments)
+│   └── 朋友圈/任务/评论/素材等 (32727-32732)
+├── 引流管理 (35005, qwDrainage)
+│   └── 广告报表等 (32706)
+├── 标签管理 (35006, qwTag)
+│   └── 自动标签/标签/标签组 (32900,32751,32752)
+└── 企微设置 (35007, qwSetting)
+    └── 部门/素材/欢迎语/行为数据等 (32707,32713,32741,32744-32746,32753-32754)
+
+修复:所有子菜单 path 不再共用 qw,改为组件名唯一 path
+
+
+三、商城管理 (32369, path=store)
+--------------------------------
+├── 订单管理 (35040, storeOrder)
+│   └── 订单/售后/线下单/健康订单/报表 (32806-32811,32772-32773,32777-32778,32781,32787)
+├── 商品管理 (35041, storeProduct)
+│   └── 商品属性/分类/处方/运费模板 (32812-32820,32790-32796)
+└── 门店运营 (35042, storeOps)
+    └── 门店/员工/优惠券/首页/导出/推广 (32774-32786,32801-32805,32821-32825)
+
+已隐藏:
+- 32591-32643 hisStore/* 旧版重复
+- 32766-32768 shop/*
+- 32826 storeOrderOfflineItem
+
+
+四、其他模块(同脚本 PART D)
+--------------------------------
+- CRM:页面归入 35020 客户管理
+- AI聊天 fastGpt:页面归入 35070 对话管理
+- 直播 live:页面归入 35050 直播运营
+- 课程 course:页面归入 35060 课程内容
+- 会员 member:path 唯一化
+
+
+执行顺序
+--------------------------------
+1. CREATE TABLE tenant_sys_menu_bak AS SELECT * FROM tenant_sys_menu;
+2. 执行 organize_tenant_sys_menu.sql(顶级整理)
+3. 执行 organize_tenant_sys_menu_subtree.sql(本文件对应脚本)
+4. 验证 SQL(脚本末尾注释)
+5. 已有租户:到「租户管理 → 管理端菜单」重新勾选,或同步租户库 sys_menu

+ 471 - 0
sql/tenant_sys_menu_visible_tree.txt

@@ -0,0 +1,471 @@
+租户管理端菜单 - 当前可见结构
+生成时间: 2026-05-29 09:37
+
+## 企微管理 [order=1, path=qw]
+[C] qw External Contact (id=32755, path=qwExternalContact, comp=qwExternalContact/index/index)
+[M] 消息管理 (id=35001, path=qwMsg, comp=)
+[M] 客户管理 (id=35002, path=qwCustomer, comp=)
+[M] 群聊管理 (id=35003, path=qwGroup, comp=)
+[M] 朋友圈 (id=35004, path=qwMoments, comp=)
+[M] 引流管理 (id=35005, path=qwDrainage, comp=)
+[M] 标签管理 (id=35006, path=qwTag, comp=)
+  [C] 自动标签 (id=32900, path=autoTags, comp=qw/autoTags/index)
+[M] 企微设置 (id=35007, path=qwSetting, comp=)
+  [C] Qw Work Task (id=32704, path=qw, comp=qw/QwWorkTask/index)
+  [C] qw (id=32705, path=qw, comp=qw/QwWorkTask/qw/index)
+  [C] app Advertising Report (id=32706, path=qw, comp=qw/appAdvertisingReport/index)
+  [C] apply Ipad (id=32707, path=qw, comp=qw/applyIpad/index)
+  [C] assign Rule (id=32708, path=qw, comp=qw/assignRule/index)
+  [C] company User (id=32713, path=qw, comp=qw/companyUser/index)
+  [C] contact Batch (id=32714, path=qw, comp=qw/contactBatch/index)
+  [C] contact Way (id=32715, path=qw, comp=qw/contactWay/index)
+  [C] contact Way Logs (id=32716, path=qw, comp=qw/contactWayLogs/index)
+  [C] customer Link (id=32717, path=qw, comp=qw/customerLink/index)
+  [C] drainage Link (id=32718, path=qw, comp=qw/drainageLink/index)
+  [C] drainage Link Logs (id=32719, path=qw, comp=qw/drainageLinkLogs/index)
+  [C] external Contact Loss (id=32720, path=qw, comp=qw/externalContactLoss/index)
+  [C] external Contact Stage (id=32721, path=qw, comp=qw/externalContactStage/index)
+  [C] external Contact Transfer (id=32722, path=qw, comp=qw/externalContactTransfer/index)
+  [C] external Contact Transfer Audit (id=32723, path=qw, comp=qw/externalContactTransferAudit/index)
+  [C] external Contact Transfer Company Audit (id=32724, path=qw, comp=qw/externalContactTransferCompanyAudit/index/index)
+  [C] external Contact Transfer Log (id=32725, path=qw, comp=qw/externalContactTransferLog/index)
+  [C] external Contact Unassigned (id=32726, path=qw, comp=qw/externalContactUnassigned/index)
+  [C] friend Circle (id=32727, path=qw, comp=qw/friendCircle/index)
+  [C] friend Circle Task (id=32728, path=qw, comp=qw/friendCircleTask/index)
+  [C] friend Comments (id=32729, path=qw, comp=qw/friendComments/index)
+  [C] friend Customer List (id=32730, path=qw, comp=qw/friendCustomerList/index)
+  [C] friend Material (id=32731, path=qw, comp=qw/friendMaterial/index)
+  [C] friend Welcome Item (id=32732, path=qw, comp=qw/friendWelcomeItem/index)
+  [C] group Actual (id=32733, path=qw, comp=qw/groupActual/index)
+  [C] group Chat Statistic (id=32734, path=qw, comp=qw/groupChatStatistic/index)
+  [C] group Chat Transfer (id=32735, path=qw, comp=qw/groupChatTransfer/index)
+  [C] group Chat Transfer Log (id=32736, path=qw, comp=qw/groupChatTransferLog/index)
+  [C] group Chat Transfer On Job (id=32737, path=qw, comp=qw/groupChatTransferOnJob/index)
+  [C] group Live Code (id=32738, path=qw, comp=qw/groupLiveCode/index)
+  [C] group Msg (id=32739, path=qw, comp=qw/groupMsg/index)
+  [C] group Msg Item (id=32740, path=qw, comp=qw/groupMsgItem/index)
+  [C] material (id=32741, path=qw, comp=qw/material/index)
+  [C] 企微部门 (id=32744, path=qw, comp=qw/qwDept/index/index)
+  [C] qw Push Count (id=32745, path=qw, comp=qw/qwPushCount/index/index)
+  [C] qw User Del Loss Statistics (id=32746, path=qw, comp=qw/qwUserDelLossStatistics/index)
+  [C] record (id=32749, path=qw, comp=qw/record/index/index)
+  [C] tag (id=32751, path=qw, comp=qw/tag/index)
+  [C] 标签组 (id=32752, path=qw, comp=qw/tagGroup/index)
+  [C] user Behavior Data (id=32753, path=qw, comp=qw/userBehaviorData/index)
+  [C] welcome (id=32754, path=qw, comp=qw/welcome/index)
+
+## index [order=1, path=index]
+
+## AI管理 [order=1, path=aaa]
+
+## 龙虾引擎 [order=10, path=lobster]
+[M] 工作流 (id=35080, path=lobsterWorkflow, comp=)
+  [C] 接口注册中心 (id=32677, path=lobster, comp=lobster/api-registry/index)
+  [C] 聚合聊天 (id=32679, path=lobster, comp=lobster/chat-aggregate/index)
+  [C] 死信队列 (id=32680, path=lobster, comp=lobster/dead-letter/index)
+  [C] 节点审核 (id=32681, path=lobster, comp=lobster/event-audit/index)
+  [C] 实例监控 (id=32682, path=lobster, comp=lobster/instance/index)
+  [C] AI优化建议 (id=32684, path=lobster, comp=lobster/optimization/index)
+  [C] 提示词管理 (id=32685, path=lobster, comp=lobster/prompt/index)
+  [C] 销冠语料学习 (id=32686, path=lobster, comp=lobster/sales-corpus/index)
+  [C] 工作流模板库 (id=32687, path=lobster, comp=lobster/template/index)
+  [C] 工作流画布 (id=32688, path=lobster, comp=lobster/workflow-canvas/index)
+  [C] 龙虾引擎 (id=32329, path=lobster, comp=lobster/workflow-generate/index)
+[M] 语料与提示词 (id=35081, path=lobsterCorpus, comp=)
+[M] 模型与配置 (id=35082, path=lobsterModel, comp=)
+[M] 运维监控 (id=35083, path=lobsterOps, comp=)
+  [C] 物联网 (id=32850, path=watch, comp=watch/iot/index)
+  [C] 绑定状态 (id=32851, path=watch, comp=watch/isBind/index)
+  [C] 下发状态 (id=32852, path=watch, comp=watch/isSend/index)
+[M] 聚合聊天 (id=35085, path=lobsterChat, comp=)
+
+## 广告投放 [order=11, path=ad]
+[C] advertiser (id=32406, path=adv, comp=adv/advertiser/index)
+[C] callback Account (id=32407, path=adv, comp=adv/callbackAccount/index)
+[C] channel (id=32408, path=adv, comp=adv/channel/index)
+[C] configuration (id=32409, path=adv, comp=adv/configuration/index)
+[C] conversion Log (id=32410, path=adv, comp=adv/conversionLog/index)
+[C] custom Promotion Account (id=32411, path=adv, comp=adv/customPromotionAccount/index)
+[C] domain (id=32412, path=adv, comp=adv/domain/index)
+[C] landing Page Template (id=32413, path=adv, comp=adv/landingPageTemplate/index)
+[C] project (id=32414, path=adv, comp=adv/project/index)
+[C] promotion Account (id=32415, path=adv, comp=adv/promotionAccount/index)
+[C] site (id=32416, path=adv, comp=adv/site/index)
+[C] statistics (id=32417, path=adv, comp=adv/statistics/index)
+[C] tracking Link (id=32418, path=adv, comp=adv/trackingLink/index)
+[M] 投放管理 (id=35090, path=advCampaign, comp=)
+  [C] 广告账户 (id=32382, path=ad, comp=ad/adAccount/index)
+  [C] 抖音API (id=32383, path=ad, comp=ad/adDyApi/index/index)
+  [C] click Log (id=32384, path=ad, comp=ad/clickLog/index/index)
+[M] 配置管理 (id=35091, path=advConfig, comp=)
+[M] 数据统计 (id=35092, path=advStat, comp=)
+
+## 系统管理 [order=12, path=system]
+[C] ad (id=32385, path=admin, comp=admin/ad/index)
+[C] ai Provider (id=32386, path=admin, comp=admin/aiProvider/index)
+[C] article (id=32387, path=admin, comp=admin/article/index)
+[C] call Record (id=32388, path=admin, comp=admin/callRecord/index)
+[C] commission Record (id=32389, path=admin, comp=admin/commissionRecord/index)
+[C] consume Record (id=32390, path=admin, comp=admin/consumeRecord/index)
+[C] course (id=32391, path=admin, comp=admin/course/index)
+[C] crm (id=32392, path=admin, comp=admin/crm/index)
+[C] live (id=32393, path=admin, comp=admin/live/index)
+[C] live Video (id=32394, path=admin, comp=admin/liveVideo/index)
+[C] module Usage (id=32395, path=admin, comp=admin/moduleUsage/index)
+[C] product (id=32396, path=admin, comp=admin/product/index)
+[C] proxy (id=32397, path=admin, comp=admin/proxy/index)
+[C] qw External Contact (id=32398, path=admin, comp=admin/qwExternalContact/index)
+[C] recharge Record (id=32399, path=admin, comp=admin/rechargeRecord/index)
+[C] store Order (id=32401, path=admin, comp=admin/storeOrder/index)
+[C] sys Company (id=32402, path=admin, comp=admin/sysCompany/index)
+[C] sys User (id=32403, path=admin, comp=admin/sysUser/index)
+[C] video Resource (id=32404, path=admin, comp=admin/videoResource/index)
+[C] withdrawal Manage (id=32405, path=admin, comp=admin/withdrawalManage/index)
+[C] module Usage (id=32698, path=proxy, comp=proxy/moduleUsage/index)
+[C] quota (id=32699, path=proxy, comp=proxy/quota/index)
+[C] service Price (id=32700, path=proxy, comp=proxy/servicePrice/index)
+[C] tenant (id=32701, path=proxy, comp=proxy/tenant/index)
+[C] tenant Rel (id=32702, path=proxy, comp=proxy/tenantRel/index)
+[C] withdraw (id=32703, path=proxy, comp=proxy/withdraw/index)
+[C] billing (id=32756, path=saas, comp=saas/billing/index)
+[C] billing Admin (id=32757, path=saas, comp=saas/billingAdmin/index)
+[C] billing Tenant (id=32758, path=saas, comp=saas/billingTenant/index)
+[C] record (id=32759, path=saas, comp=saas/record/index)
+[C] config (id=32760, path=saas, comp=saas/tenant/config/index)
+[C] 租户管理 (id=32761, path=saas, comp=saas/tenant/index)
+[C] tenant Company (id=32762, path=saas, comp=saas/tenantCompany/index)
+[C] 租户菜单 (id=32763, path=saas, comp=saas/tenantMenu/index)
+[C] tenant (id=32837, path=tenant, comp=tenant/index/index)
+[C] 构建工具 (id=32839, path=tool, comp=tool/build/index)
+[C] 代码生成 (id=32840, path=tool, comp=tool/gen/index)
+[C] 接口文档 (id=32841, path=tool, comp=tool/swagger/index)
+[M] 组织管理 (id=35100, path=sysOrg, comp=)
+  [C] member (id=32769, path=statistics, comp=statistics/member/index)
+  [C] report (id=32770, path=statistics, comp=statistics/report/index)
+  [C] 分组统计 (id=32771, path=statistics, comp=statistics/section/index)
+  [C] 统计中心 (id=29194, path=statistics, comp=statistics/index)
+[M] 权限管理 (id=35101, path=sysPerm, comp=)
+[M] 通信管理 (id=35102, path=sysVoice, comp=)
+[M] 日志管理 (id=35105, path=sysLog, comp=)
+[M] 系统设置 (id=35106, path=sysConfig, comp=)
+  [C] inbound Call Manage (id=32427, path=company, comp=company/aiModel/inboundCallManage/index)
+  [C] AI工作流 (id=32430, path=company, comp=company/aiWorkflow/index)
+  [C] company Apply (id=32431, path=company, comp=company/companyApply/index)
+  [C] company Bind User (id=32432, path=company, comp=company/companyBindUser/index)
+  [C] company Client (id=32433, path=company, comp=company/companyClient/index)
+  [C] company Config (id=32434, path=company, comp=company/companyConfig/index)
+  [C] company Deduct (id=32435, path=company, comp=company/companyDeduct/index)
+  [C] company Dept (id=32436, path=company, comp=company/companyDept/index)
+  [C] company Domain (id=32437, path=company, comp=company/companyDomain/index)
+  [C] company Domain Bind (id=32438, path=company, comp=company/companyDomainBind/index)
+  [C] company Logininfor (id=32439, path=company, comp=company/companyLogininfor/index)
+  [C] 企业菜单 (id=32440, path=company, comp=company/companyMenu/index)
+  [C] 资金流水 (id=32441, path=company, comp=company/companyMoneyLogs/index)
+  [C] company Oper Log (id=32442, path=company, comp=company/companyOperLog/index)
+  [C] company Post (id=32443, path=company, comp=company/companyPost/index)
+  [C] 分账记录 (id=32444, path=company, comp=company/companyProfit/index)
+  [C] 充值记录 (id=32445, path=company, comp=company/companyRecharge/index)
+  [C] company Red Packet Balance Logs (id=32446, path=company, comp=company/companyRedPacketBalanceLogs/index)
+  [C] 企业角色 (id=32447, path=company, comp=company/companyRole/index)
+  [C] company Role Dept (id=32448, path=company, comp=company/companyRoleDept/index)
+  [C] company Role Menu (id=32449, path=company, comp=company/companyRoleMenu/index)
+  [C] company Sms Logs (id=32451, path=company, comp=company/companySmsLogs/index)
+  [C] company Sms Order (id=32452, path=company, comp=company/companySmsOrder/index)
+  [C] company Sms Package (id=32453, path=company, comp=company/companySmsPackage/index)
+  [C] company Sms Temp (id=32454, path=company, comp=company/companySmsTemp/index)
+  [C] card (id=32455, path=company, comp=company/companyUser/card/index)
+  [C] profile (id=32456, path=company, comp=company/companyUser/profile/index)
+  [C] company User Post (id=32457, path=company, comp=company/companyUserPost/index)
+  [C] AI外呼工作流 (id=32470, path=company, comp=company/companyWorkflow/index)
+  [C] company Workflow Manage (id=32471, path=company, comp=company/companyWorkflowManage/index)
+  [C] company Wx (id=32472, path=company, comp=company/companyWx/index)
+  [C] company (id=32473, path=company, comp=company/index/index)
+  [C] red Package (id=32474, path=company, comp=company/redPackage/index)
+  [C] schedule (id=32475, path=company, comp=company/schedule/index)
+  [C] schedule Report (id=32476, path=company, comp=company/scheduleReport/index)
+  [C] tcm Schedule Report (id=32477, path=company, comp=company/tcmScheduleReport/index)
+  [C] traffic (id=32478, path=company, comp=company/traffic/index)
+  [C] traffic Log (id=32479, path=company, comp=company/trafficLog/index)
+  [C] workflow External Api (id=32480, path=company, comp=company/workflowExternalApi/index)
+  [C] 龙虾工作流 (id=32481, path=company, comp=company/workflowLobster/index)
+  [C] 个微账号 (id=32482, path=company, comp=company/wxAccount/index)
+  [C] wx Dialog (id=32483, path=company, comp=company/wxDialog/index)
+  [C] 个微用户 (id=32484, path=company, comp=company/wxUser/index)
+  [C] wx User Group (id=32485, path=company, comp=company/wxUserGroup/index)
+  [C] set (id=32832, path=system, comp=system/set/index/index)
+  [C] profile (id=32833, path=system, comp=system/user/profile/index)
+[M] SaaS管理 (id=35108, path=sysSaas, comp=)
+
+## 财务管理 [order=13, path=bill]
+[C] wallet (id=32422, path=billing, comp=billing/wallet/index)
+[M] 钱包管理 (id=35110, path=finWallet, comp=)
+[M] 充值管理 (id=35111, path=finRecharge, comp=)
+[M] 扣费管理 (id=35112, path=finDeduct, comp=)
+[M] 利润管理 (id=35113, path=finProfit, comp=)
+[M] 资金日志 (id=35114, path=finLog, comp=)
+[M] 流量管理 (id=35115, path=finTraffic, comp=)
+[M] 使用统计 (id=35116, path=finUsage, comp=)
+
+## 日程管理 [order=14, path=calendar]
+[C] my Calendar (id=32423, path=calendar, comp=calendar/myCalendar/index)
+
+## 数据统计 [order=15, path=statistics]
+[C] module Usage (id=32693, path=moduleUsage, comp=moduleUsage/index/index)
+[C] 通话日志 (id=32834, path=taskStatistics, comp=taskStatistics/callLog/index)
+[C] 发信日志 (id=32835, path=taskStatistics, comp=taskStatistics/sendMsgLog/index)
+[C] 模块消费统计 (id=32859, path=consumeReport, comp=company/consumeReport/index)
+[C] 模块用量统计 (id=29227, path=moduleUsage, comp=moduleUsage/index)
+
+## 监控管理 [order=16, path=watch]
+[C] doctorOperLog (id=32695, path=monitor, comp=monitor/doctorOperLog/index)
+[C] 数据监控 (id=32696, path=monitor, comp=monitor/druid/index)
+[C] 定时任务 (id=32697, path=monitor, comp=monitor/job/index)
+
+## 微信管理 [order=2, path=wx]
+[C] 网关账户 (id=32540, path=gw, comp=gw/gwAccount/index)
+[M] 微信账号 (id=35010, path=wxAccount, comp=)
+[M] 微信对话 (id=35011, path=wxDialog, comp=)
+[M] 微信用户 (id=35012, path=wxUser, comp=)
+[M] 微信机器人 (id=35013, path=wxRobot, comp=)
+[M] 网关管理 (id=35015, path=gwMgmt, comp=)
+
+## CRM客户 [order=3, path=crm]
+[M] 客户管理 (id=35020, path=crmCustomer, comp=)
+  [C] customer Ai Chat (id=32521, path=crm, comp=crm/customerAiChat/index)
+  [C] customer Assign (id=32522, path=crm, comp=crm/customerAssign/index/index)
+  [C] customer Business (id=32523, path=crm, comp=crm/customerBusiness/index)
+  [C] customer Contacts (id=32524, path=crm, comp=crm/customerContacts/index)
+  [C] customer Ext (id=32525, path=crm, comp=crm/customerExt/index)
+  [C] customer Level (id=32526, path=crm, comp=crm/customerLevel/index/index)
+  [C] customer Logs (id=32527, path=crm, comp=crm/customerLogs/index)
+[M] 商机管理 (id=35021, path=crmBusiness, comp=)
+[M] AI辅助 (id=35023, path=crmAi, comp=)
+
+## 会员管理 [order=4, path=member]
+[C] 黑名单 (id=32842, path=user, comp=user/blacklist/index)
+[C] category (id=32843, path=user, comp=user/complaint/category/index)
+[C] 小黑屋 (id=32844, path=user, comp=user/darkRoom/index)
+[C] 积分管理 (id=32845, path=user, comp=user/integral/index)
+[C] msg (id=32846, path=user, comp=user/msg/index/index)
+[C] 充值模板 (id=32847, path=user, comp=user/rechargeTemplate/index)
+[C] 转接管理 (id=32848, path=user, comp=user/transfer/index)
+
+## 诊所管理 [order=5, path=his]
+[C] record (id=32539, path=food, comp=food/record/index)
+[M] 用户管理 (id=35033, path=hisUser, comp=)
+[M] 门店管理 (id=35034, path=hisStore, comp=)
+[M] 导出与日志 (id=35035, path=hisExport, comp=)
+
+## 商城管理 [order=6, path=store]
+[C] adv (id=32591, path=hisStore, comp=hisStore/adv/index)
+[C] company User (id=32592, path=hisStore, comp=hisStore/companyUser/index)
+[C] express (id=32593, path=hisStore, comp=hisStore/express/index)
+[C] integral Goods (id=32594, path=hisStore, comp=hisStore/integralGoods/index)
+[C] integral Order (id=32595, path=hisStore, comp=hisStore/integralOrder/index)
+[C] menu (id=32596, path=hisStore, comp=hisStore/menu/index)
+[C] prescribe (id=32597, path=hisStore, comp=hisStore/prescribe/index)
+[C] prescribe Drug (id=32598, path=hisStore, comp=hisStore/prescribeDrug/index)
+[C] shipping Templates (id=32599, path=hisStore, comp=hisStore/shippingTemplates/index)
+[C] shipping Templates Free (id=32600, path=hisStore, comp=hisStore/shippingTemplatesFree/index)
+[C] shipping Templates Region (id=32601, path=hisStore, comp=hisStore/shippingTemplatesRegion/index)
+[C] store (id=32602, path=hisStore, comp=hisStore/store/index)
+[C] store Activity (id=32603, path=hisStore, comp=hisStore/storeActivity/index)
+[C] store After Sales (id=32604, path=hisStore, comp=hisStore/storeAfterSales/index)
+[C] store After Sales Item (id=32605, path=hisStore, comp=hisStore/storeAfterSalesItem/index)
+[C] store After Sales Status (id=32606, path=hisStore, comp=hisStore/storeAfterSalesStatus/index)
+[C] store Canvas (id=32607, path=hisStore, comp=hisStore/storeCanvas/index)
+[C] store Cart (id=32608, path=hisStore, comp=hisStore/storeCart/index)
+[C] store Coupon (id=32609, path=hisStore, comp=hisStore/storeCoupon/index)
+[C] store Coupon Issue (id=32610, path=hisStore, comp=hisStore/storeCouponIssue/index)
+[C] store Coupon Issue User (id=32611, path=hisStore, comp=hisStore/storeCouponIssueUser/index)
+[C] store Coupon User (id=32612, path=hisStore, comp=hisStore/storeCouponUser/index)
+[C] store Instan Discount Issue (id=32613, path=hisStore, comp=hisStore/storeInstanDiscountIssue/index)
+[C] store Instant Discount (id=32614, path=hisStore, comp=hisStore/storeInstantDiscount/index)
+[C] store Instant Discount User (id=32615, path=hisStore, comp=hisStore/storeInstantDiscountUser/index)
+[C] dimension Statistics (id=32616, path=hisStore, comp=hisStore/storeOrder/dimensionStatistics/index)
+[C] 门店订单 (id=32617, path=hisStore, comp=hisStore/storeOrder/index)
+[C] 订单审核 (id=32618, path=hisStore, comp=hisStore/storeOrderAudit/index)
+[C] store Order Notice (id=32619, path=hisStore, comp=hisStore/storeOrderNotice/index)
+[C] 线下订单 (id=32620, path=hisStore, comp=hisStore/storeOrderOffline/index)
+[C] store Order Status (id=32621, path=hisStore, comp=hisStore/storeOrderStatus/index)
+[C] store Payment (id=32622, path=hisStore, comp=hisStore/storePayment/index)
+[C] store Product (id=32623, path=hisStore, comp=hisStore/storeProduct/index)
+[C] store Product Attr (id=32624, path=hisStore, comp=hisStore/storeProductAttr/index)
+[C] store Product Attr Value (id=32625, path=hisStore, comp=hisStore/storeProductAttrValue/index)
+[C] store Product Audit (id=32626, path=hisStore, comp=hisStore/storeProductAudit/index)
+[C] store Product Category (id=32627, path=hisStore, comp=hisStore/storeProductCategory/index)
+[C] store Product Details (id=32628, path=hisStore, comp=hisStore/storeProductDetails/index)
+[C] store Product Group (id=32629, path=hisStore, comp=hisStore/storeProductGroup/index)
+[C] store Product Relation (id=32631, path=hisStore, comp=hisStore/storeProductRelation/index)
+[C] store Product Reply (id=32632, path=hisStore, comp=hisStore/storeProductReply/index)
+[C] store Product Rule (id=32633, path=hisStore, comp=hisStore/storeProductRule/index)
+[C] store Product Template (id=32634, path=hisStore, comp=hisStore/storeProductTemplate/index)
+[C] store Product Yuyue (id=32635, path=hisStore, comp=hisStore/storeProductYuyue/index)
+[C] 冗余销售 (id=32636, path=hisStore, comp=hisStore/storeRedundSales/index)
+[C] store Shop (id=32637, path=hisStore, comp=hisStore/storeShop/index)
+[C] store Shop Staff (id=32638, path=hisStore, comp=hisStore/storeShopStaff/index)
+[C] store Visit (id=32639, path=hisStore, comp=hisStore/storeVisit/index)
+[C] user Bill (id=32640, path=hisStore, comp=hisStore/userBill/index)
+[C] user Extract (id=32641, path=hisStore, comp=hisStore/userExtract/index)
+[C] 用户在线状态 (id=32642, path=hisStore, comp=hisStore/userOnlineState/index)
+[C] user Promoter Apply (id=32643, path=hisStore, comp=hisStore/userPromoterApply/index)
+[C] msg (id=32766, path=shop, comp=shop/msg/index/index)
+[C] records (id=32767, path=shop, comp=shop/records/index/index)
+[C] role (id=32768, path=shop, comp=shop/role/index/index)
+[C] store (id=32826, path=storeOrderOfflineItem, comp=storeOrderOfflineItem/store/index/index)
+[M] 订单管理 (id=35040, path=storeOrder, comp=)
+  [C] Fs Follow Report (id=32772, path=store, comp=store/FsFollowReport/index)
+  [C] Promotion Order (id=32773, path=store, comp=store/PromotionOrder/index/index)
+  [C] adv (id=32774, path=store, comp=store/adv/index/index)
+  [C] collection Schedule (id=32775, path=store, comp=store/collectionSchedule/index)
+  [C] coupon (id=32776, path=store, comp=store/coupon/index)
+  [C] drug Report (id=32777, path=store, comp=store/drugReport/index)
+  [C] drug Report Count (id=32778, path=store, comp=store/drugReportCount/index)
+  [C] export Task (id=32779, path=store, comp=store/exportTask/index)
+  [C] health Record (id=32780, path=store, comp=store/healthRecord/index)
+  [C] health Store Order (id=32781, path=store, comp=store/healthStoreOrder/index/index)
+  [C] health Tongue (id=32782, path=store, comp=store/healthTongue/index)
+  [C] home Article (id=32783, path=store, comp=store/homeArticle/index/index)
+  [C] home Category (id=32784, path=store, comp=store/homeCategory/index/index)
+  [C] home View (id=32785, path=store, comp=store/homeView/index/index)
+  [C] store (id=32786, path=store, comp=store/index/index)
+  [C] inquiry Order Report (id=32787, path=store, comp=store/inquiryOrderReport/index)
+  [C] menu (id=32788, path=store, comp=store/menu/index/index)
+  [C] my Health Tongue (id=32789, path=store, comp=store/myHealthTongue/index)
+  [C] package (id=32790, path=store, comp=store/package/index)
+  [C] prescribe (id=32791, path=store, comp=store/prescribe/index/index)
+  [C] prescribe Drug (id=32792, path=store, comp=store/prescribeDrug/index/index)
+  [C] recommend (id=32793, path=store, comp=store/recommend/index/index)
+  [C] shipping Templates (id=32794, path=store, comp=store/shippingTemplates/index/index)
+  [C] shipping Templates Free (id=32795, path=store, comp=store/shippingTemplatesFree/index/index)
+  [C] shipping Templates Region (id=32796, path=store, comp=store/shippingTemplatesRegion/index/index)
+  [C] store Activity (id=32797, path=store, comp=store/storeActivity/index/index)
+  [C] 售后 (id=32798, path=store, comp=store/storeAfterSales/index/index)
+  [C] store After Sales Item (id=32799, path=store, comp=store/storeAfterSalesItem/index/index)
+  [C] store After Sales Status (id=32800, path=store, comp=store/storeAfterSalesStatus/index/index)
+  [C] store Cart (id=32801, path=store, comp=store/storeCart/index/index)
+  [C] 优惠券 (id=32802, path=store, comp=store/storeCoupon/index/index)
+  [C] store Coupon Issue (id=32803, path=store, comp=store/storeCouponIssue/index/index)
+  [C] store Coupon Issue User (id=32804, path=store, comp=store/storeCouponIssueUser/index/index)
+  [C] store Coupon User (id=32805, path=store, comp=store/storeCouponUser/index/index)
+  [C] 订单管理 (id=32806, path=store, comp=store/storeOrder/index/index)
+  [C] store Order Audit (id=32807, path=store, comp=store/storeOrderAudit/index/index)
+  [C] store Order Item (id=32808, path=store, comp=store/storeOrderItem/index/index)
+  [C] store Order Notice (id=32809, path=store, comp=store/storeOrderNotice/index/index)
+  [C] store Order Offline (id=32810, path=store, comp=store/storeOrderOffline/index/index)
+  [C] store Order Status (id=32811, path=store, comp=store/storeOrderStatus/index/index)
+  [C] store Product Attr (id=32812, path=store, comp=store/storeProductAttr/index/index)
+  [C] store Product Attr Value (id=32813, path=store, comp=store/storeProductAttrValue/index/index)
+  [C] store Product Category (id=32814, path=store, comp=store/storeProductCategory/index/index)
+  [C] store Product Details (id=32815, path=store, comp=store/storeProductDetails/index/index)
+  [C] store Product Group (id=32816, path=store, comp=store/storeProductGroup/index/index)
+  [C] store Product Relation (id=32817, path=store, comp=store/storeProductRelation/index/index)
+  [C] store Product Reply (id=32818, path=store, comp=store/storeProductReply/index/index)
+  [C] store Product Rule (id=32819, path=store, comp=store/storeProductRule/index/index)
+  [C] store Product Template (id=32820, path=store, comp=store/storeProductTemplate/index/index)
+  [C] store Shop (id=32821, path=store, comp=store/storeShop/index/index)
+  [C] store Shop Staff (id=32822, path=store, comp=store/storeShopStaff/index/index)
+  [C] store Visit (id=32823, path=store, comp=store/storeVisit/index/index)
+  [C] user Coupon (id=32824, path=store, comp=store/userCoupon/index)
+  [C] user Promoter Apply (id=32825, path=store, comp=store/userPromoterApply/index/index)
+[M] 商品管理 (id=35041, path=storeProduct, comp=)
+[M] 门店运营 (id=35042, path=storeOps, comp=)
+
+## 直播管理 [order=7, path=live]
+[C] live Data (id=32676, path=liveData, comp=liveData/index/index)
+[M] 直播运营 (id=35050, path=liveOps, comp=)
+  [C] comment (id=32645, path=live, comp=live/comment/index)
+  [C] health Live Order (id=32646, path=live, comp=live/healthLiveOrder/index/index)
+  [C] live (id=32647, path=live, comp=live/index/index)
+  [C] issue (id=32648, path=live, comp=live/issue/index/index)
+  [C] live (id=32649, path=live, comp=live/live/index)
+  [C] live After Sales (id=32650, path=live, comp=live/liveAfterSales/index/index)
+  [C] live Aftera Sales (id=32651, path=live, comp=live/liveAfteraSales/index)
+  [C] live Config (id=32652, path=live, comp=live/liveConfig/index)
+  [C] live Console (id=32653, path=live, comp=live/liveConsole/index)
+  [C] live Coupon Issue (id=32654, path=live, comp=live/liveCouponIssue/index)
+  [C] live Coupon Issue User (id=32655, path=live, comp=live/liveCouponIssueUser/index)
+  [C] live Coupon User (id=32656, path=live, comp=live/liveCouponUser/index)
+  [C] live Data (id=32657, path=live, comp=live/liveData/index)
+  [C] live Lottery Product Conf (id=32658, path=live, comp=live/liveLotteryProductConf/index)
+  [C] live Order Status (id=32659, path=live, comp=live/liveOrderStatus/index)
+  [C] live Orderitems (id=32660, path=live, comp=live/liveOrderitems/index)
+  [C] live Profit (id=32661, path=live, comp=live/liveProfit/index)
+  [C] live Question (id=32662, path=live, comp=live/liveQuestion/index)
+  [C] live Question Bank (id=32663, path=live, comp=live/liveQuestionBank/index)
+  [C] live Reward Record (id=32664, path=live, comp=live/liveRewardRecord/index)
+  [C] live Traffic Log (id=32665, path=live, comp=live/liveTrafficLog/index)
+  [C] live User Favorite (id=32666, path=live, comp=live/liveUserFavorite/index/index)
+  [C] live User Follow (id=32667, path=live, comp=live/liveUserFollow/index/index)
+  [C] live User Like (id=32668, path=live, comp=live/liveUserLike/index/index)
+  [C] live Watch Log (id=32669, path=live, comp=live/liveWatchLog/index)
+  [C] live Watch User (id=32670, path=live, comp=live/liveWatchUser/index)
+  [C] order (id=32671, path=live, comp=live/order/index)
+  [C] record (id=32672, path=live, comp=live/record/index/index)
+  [C] talent Live Info (id=32673, path=live, comp=live/talentLiveInfo/index)
+  [C] task (id=32674, path=live, comp=live/task/index/index)
+  [C] traffic Log (id=32675, path=live, comp=live/trafficLog/index/index)
+[M] 直播互动 (id=35051, path=liveInteract, comp=)
+[M] 直播订单 (id=35052, path=liveOrder, comp=)
+[M] 直播数据 (id=35053, path=liveData, comp=)
+
+## 课程管理 [order=8, path=course]
+[C] course (id=32520, path=courseFinishTemp, comp=courseFinishTemp/course/index/index)
+[M] 课程内容 (id=35060, path=courseContent, comp=)
+  [C] Material (id=32486, path=course, comp=course/Material/index)
+  [C] course Answer Log (id=32487, path=course, comp=course/courseAnswerLog/index/index)
+  [C] course Answerlogs (id=32488, path=course, comp=course/courseAnswerlogs/index)
+  [C] 结课模板 (id=32489, path=course, comp=course/courseFinishTemp/index)
+  [C] course Play Source Config (id=32490, path=course, comp=course/coursePlaySourceConfig/index)
+  [C] course Question Category (id=32491, path=course, comp=course/courseQuestionCategory/index/index)
+  [C] course Red Packet Statistics (id=32492, path=course, comp=course/courseRedPacketStatistics/index)
+  [C] course User Statistics (id=32493, path=course, comp=course/courseUserStatistics/index)
+  [C] qw (id=32494, path=course, comp=course/courseUserStatistics/qw/index)
+  [C] course Watch Comment (id=32495, path=course, comp=course/courseWatchComment/index)
+  [C] course Watch Log (id=32496, path=course, comp=course/courseWatchLog/index)
+  [C] qw (id=32497, path=course, comp=course/courseWatchLog/qw/index)
+  [C] huawei Cloud Statistics (id=32498, path=course, comp=course/huaweiCloudStatistics/index)
+  [C] course (id=32499, path=course, comp=course/index/index)
+  [C] period (id=32500, path=course, comp=course/period/index/index)
+  [C] play Source Config (id=32501, path=course, comp=course/playSourceConfig/index/index)
+  [C] push (id=32502, path=course, comp=course/push/index)
+  [C] training Camp (id=32504, path=course, comp=course/trainingCamp/index/index)
+  [C] user Course Comment Like (id=32505, path=course, comp=course/userCourseCommentLike/index/index)
+  [C] user Course Favorite (id=32506, path=course, comp=course/userCourseFavorite/index/index)
+  [C] user Course Note Like (id=32507, path=course, comp=course/userCourseNoteLike/index/index)
+  [C] user Course Period (id=32508, path=course, comp=course/userCoursePeriod/index)
+  [C] user Course Video (id=32509, path=course, comp=course/userCourseVideo/index/index)
+  [C] user Talent Follow (id=32510, path=course, comp=course/userTalentFollow/index/index)
+  [C] user Video Comment Like (id=32511, path=course, comp=course/userVideoCommentLike/index/index)
+  [C] user Video Favorite (id=32512, path=course, comp=course/userVideoFavorite/index/index)
+  [C] user Video Like (id=32513, path=course, comp=course/userVideoLike/index/index)
+  [C] user Video Tags (id=32514, path=course, comp=course/userVideoTags/index)
+  [C] user Video View (id=32515, path=course, comp=course/userVideoView/index/index)
+  [C] user Watch Course Statistics (id=32516, path=course, comp=course/userWatchCourseStatistics/index)
+  [C] user Watch Course Total Statistics (id=32517, path=course, comp=course/userWatchCourseTotalStatistics/index)
+  [C] user Watch Statistics (id=32518, path=course, comp=course/userWatchStatistics/index)
+  [C] video Tags (id=32519, path=course, comp=course/videoTags/index/index)
+[M] 课程资源 (id=35061, path=courseResource, comp=)
+[M] 学习管理 (id=35062, path=courseStudy, comp=)
+[M] 课程统计 (id=35063, path=courseStat, comp=)
+
+## AI聊天 [order=9, path=fastGpt]
+[C] Fast Gpt Ext User Tag (id=32381, path=FastGptExtUserTag, comp=FastGptExtUserTag/index/index)
+[C] 消息日志 (id=32425, path=chat, comp=chat/chatMsgLogs/index)
+[M] 对话管理 (id=35070, path=aiChat, comp=)
+  [C] AI关键词管理 (id=32528, path=fastGpt, comp=fastGpt/fastGptChatKeyword/index)
+  [C] AI对话消息 (id=32529, path=fastGpt, comp=fastGpt/fastGptChatMsg/index)
+  [C] AI对话消息日志 (id=32530, path=fastGpt, comp=fastGpt/fastGptChatMsgLogs/index)
+  [C] fast Gpt Chat Replace Text (id=32531, path=fastGpt, comp=fastGpt/fastGptChatReplaceText/index/index)
+  [C] AI会话记录 (id=32532, path=fastGpt, comp=fastGpt/fastGptChatSession/index)
+  [C] 知识采集 (id=32533, path=fastGpt, comp=fastGpt/fastGptCollection/index)
+  [C] 采集数据 (id=32534, path=fastGpt, comp=fastGpt/fastGptCollentionData/index)
+  [C] 数据集 (id=32535, path=fastGpt, comp=fastGpt/fastGptDataset/index)
+  [C] AI用户 (id=32537, path=fastGpt, comp=fastGpt/fastGptUser/index)
+[M] 角色管理 (id=35071, path=aiRole, comp=)
+[C] AI聊天质检 (id=29186, path=aiChatQuality, comp=aiChatQuality/index)
+[M] 知识管理 (id=35072, path=aiKnowledge, comp=)
+[M] 关键词管理 (id=35073, path=aiKeyword, comp=)
+[M] AI质检 (id=35074, path=aiQuality, comp=)
+[M] 统计分析 (id=35075, path=aiStat, comp=)
+

+ 9 - 0
sql/verify_final.py

@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+import pymysql
+conn = pymysql.connect(host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220, user='root', password='Ylrz_1q2w3e4r5t6y', database='ylrz_saas', charset='utf8mb4')
+cur = conn.cursor()
+cur.execute("SELECT visible, COUNT(*) FROM tenant_sys_menu WHERE parent_id=32372 GROUP BY visible")
+print('system_children_by_visible', cur.fetchall())
+cur.execute("SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id IN (35001,35002,35003,35004,35005,35006,35007) AND menu_type <> 'F' AND visible='0' GROUP BY parent_id, path HAVING COUNT(*)>1")
+print('qw_dup', cur.fetchall())
+cur.close(); conn.close()

+ 36 - 0
sql/verify_menu_ids.py

@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+conn = pymysql.connect(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+    user='root', password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas', charset='utf8mb4',
+)
+cur = conn.cursor()
+
+sample_ids = [32431,32440,32704,32755,32806,32591,32482,29194,35100]
+cur.execute('SELECT menu_id, menu_name, parent_id, visible, component FROM tenant_sys_menu WHERE menu_id IN (%s)' % ','.join(map(str, sample_ids)))
+print('samples:')
+for r in cur.fetchall():
+    print(r)
+
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu')
+print('total', cur.fetchone()[0])
+
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu_bak')
+try:
+    print('backup_total', cur.fetchone()[0])
+except:
+    pass
+
+cur.execute("SELECT parent_id, COUNT(*) FROM tenant_sys_menu WHERE menu_id BETWEEN 32427 AND 32485 GROUP BY parent_id ORDER BY COUNT(*) DESC LIMIT 10")
+print('company_menu_parents', cur.fetchall())
+
+cur.execute("SELECT parent_id, COUNT(*) FROM tenant_sys_menu WHERE menu_id BETWEEN 32704 AND 32755 GROUP BY parent_id ORDER BY COUNT(*) DESC LIMIT 10")
+print('qw_menu_parents', cur.fetchall())
+
+cur.execute("SELECT menu_id, parent_id FROM tenant_sys_menu WHERE menu_id IN (32431,32440,32439,32704,32806)")
+print('target_rows', cur.fetchall())
+
+cur.close()
+conn.close()

+ 26 - 0
sql/verify_menu_organize.py

@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+conn = pymysql.connect(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com', port=27220,
+    user='root', password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas', charset='utf8mb4',
+)
+cur = conn.cursor()
+
+queries = [
+    ('groups', 'SELECT menu_id, menu_name, parent_id, visible FROM tenant_sys_menu WHERE menu_id IN (35100,35101,35102,35105,35106,32372) ORDER BY menu_id'),
+    ('child_counts', 'SELECT parent_id, COUNT(*) c FROM tenant_sys_menu WHERE parent_id IN (35100,35101,35102,35105,35106,32372,35001,35002,35040,35041,35042) GROUP BY parent_id ORDER BY parent_id'),
+    ('system_visible_children', "SELECT menu_id, menu_name, parent_id, path, visible FROM tenant_sys_menu WHERE parent_id=32372 AND visible='0' LIMIT 20"),
+    ('qw_msg_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35001 AND visible='0'"),
+    ('store_order_children', "SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35040 AND visible='0'"),
+    ('hidden_hisstore', "SELECT COUNT(*) FROM tenant_sys_menu WHERE menu_id BETWEEN 32591 AND 32643 AND visible='1'"),
+]
+
+for name, sql in queries:
+    cur.execute(sql)
+    rows = cur.fetchall()
+    print(name + ':', rows)
+
+cur.close()
+conn.close()

+ 33 - 0
sql/verify_other_menu.py

@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+cur.execute(
+    "SELECT menu_id, menu_name, parent_id, order_num, path, visible, menu_type "
+    "FROM tenant_sys_menu WHERE menu_id=35300"
+)
+print('35300', cur.fetchone())
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=35300')
+print('children', cur.fetchone()[0])
+cur.execute(
+    "SELECT menu_id, menu_name, order_num, path, visible "
+    "FROM tenant_sys_menu WHERE parent_id=0 AND visible='0' AND menu_type='M' "
+    "ORDER BY order_num"
+)
+print('visible roots:')
+for r in cur.fetchall():
+    print(' ', r)
+cur.execute('SELECT COUNT(*) FROM tenant_sys_menu WHERE parent_id=32333')
+print('still under 32333', cur.fetchone()[0])
+cur.close()
+c.close()

+ 38 - 0
sql/verify_other_visible.py

@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+import pymysql
+
+M = dict(
+    host='cq-cdb-8fjmemkb.sql.tencentcdb.com',
+    port=27220,
+    user='root',
+    password='Ylrz_1q2w3e4r5t6y',
+    database='ylrz_saas',
+    charset='utf8mb4',
+)
+
+c = pymysql.connect(**M)
+cur = c.cursor()
+cur.execute(
+    'SELECT visible, COUNT(*) FROM tenant_sys_menu WHERE parent_id=35300 GROUP BY visible'
+)
+print('direct children visible', cur.fetchall())
+cur.execute(
+    "SELECT parent_id, path, COUNT(*) c FROM tenant_sys_menu "
+    "WHERE menu_type<>'F' AND visible='0' GROUP BY parent_id, path HAVING c>1"
+)
+print('path dup', cur.fetchall())
+
+# simulate API visible=0 - count children returned for 35300
+cur.execute(
+    "SELECT menu_id, menu_name, menu_type FROM tenant_sys_menu "
+    "WHERE visible='0' AND parent_id=35300 ORDER BY order_num LIMIT 5"
+)
+print('sample visible children under 35300:')
+for r in cur.fetchall():
+    print(' ', r)
+cur.execute(
+    "SELECT COUNT(*) FROM tenant_sys_menu WHERE visible='0' AND parent_id=35300"
+)
+print('total visible direct children', cur.fetchone()[0])
+cur.close()
+c.close()