--- name: bricks-menu-dspy-pitfalls description: Bricks Menu/DSPY/语言切换/CRUD stub 实战教训——PCCS 踩坑总结 version: 1.0.0 tags: [bricks, menu, dspy, pitfall, pccs, language, stub] --- ## 用户菜单(👤)聚合机制:user_menu.ui + 模块 usermenu.ui Sage 平台用户头像菜单不是各模块直接改共享文件,而是**聚合**: - **应用级**:应用 `wwwroot/` 下放 `user_menu.ui`(带下划线)= 聚合入口。 - **模块级**:每个模块要往用户菜单加项,就在**自己模块 `wwwroot/` 下放 `usermenu.ui`**(无下划线),Sage 自动聚合所有模块的 usermenu.ui。 **铁律:绝不往 rbac 的 usermenu.ui 加应用专属菜单项。** rbac 是通用模块(所有应用共用),加"绑定微信"这类产线专属项会让所有应用都出现该菜单。应用专属项放该应用自己模块的 wwwroot/usermenu.ui。 **入口链路**:Header 👤 → urlwidget 加载 `/rbac/user/user_panel.ui` → `user.ui` → `userinfo.ui` → 点击弹 Popup 加载 `/user_menu.ui`(应用级聚合入口)。**关键:应用 `wwwroot/` 必须存在 `user_menu.ui` 文件,否则 `/user_menu.ui` 返回 500 invalid path**——这正是用户头像菜单打不开的根因,补上应用级 user_menu.ui 后 500→200。user_menu.ui 是 Menu widget,items 里每项 `label` + `submenu: entire_url('/模块/usermenu.ui')` 指向各模块(例:`我`→`/rbac/usermenu.ui`、`充值`→`/unipay/usermenu.ui`)。模块级 `/rbac/usermenu.ui` 需 permission 表有该路径的 `any` 权限条目,否则 403。 ⚠️ 别把 `userinfo.ui` 的引用路径改成 `/rbac/usermenu.ui`——那会绕过应用级聚合,直接加载单个模块菜单。正确是保留 `/user_menu.ui` 并补应用级 user_menu.ui 文件。 ## TabPanel 动态 Tab(菜单项点击添加/切换 tab) ### bricks.Html 的 `` 会**提前终止 HTML shell 的外层 `