diff --git a/docs/superpowers/specs/2026-09-11-mini-db-menu-permission-design.md b/docs/superpowers/specs/2026-09-11-mini-db-menu-permission-design.md new file mode 100644 index 000000000..8c79b2473 --- /dev/null +++ b/docs/superpowers/specs/2026-09-11-mini-db-menu-permission-design.md @@ -0,0 +1,141 @@ +# 小程序地磅工作台:移动端菜单与权限过滤 + +**日期**:2026-09-11 +**状态**:待审阅 +**对齐**:`openspec/changes/zkxw-engineering-standards/specs/permission-conventions/spec.md`(Web 与小程序双菜单树) +**范围**:`sys_menu` 移动端地磅子树、测试库授权、`miniprogram` 工作台按权限码过滤 + +--- + +## 1. 背景与目标 + +小程序工作台「地磅管理」四入口当前由 `miniprogram/config/workbench-menus.js` **前端写死**,不读 `sys_menu` / 角色权限。库内已有: + +- 根菜单 `id=1`「移动端」、`id=2`「Web端」 +- Web 地磅树(`DB000…`,`perms` 为 `db:*`)挂在 Web 端下 +- **移动端根下尚无地磅业务菜单** + +### 目标 + +1. 在「移动端」下插入「地磅管理」及四个叶子菜单,权限码独立为 `mini:db:*`。 +2. 测试环境仅为 `super_admin` 写入 `sys_role_menu`;其它角色在「角色管理」手工勾选。 +3. 小程序工作台按用户菜单权限码过滤展示;无权限则不展示对应入口(无子项则隐藏整块「地磅管理」)。 +4. 实现路径采用 **方案 1**:插库 + 复用 `GET /web/auth/menu-codes` + 静态菜单映射过滤(不新建 `/mini/auth/menu-codes`,不改地磅 API 硬鉴权)。 + +### 非目标 + +- 地磅业务 API 增加 `require_menu_code('mini:…')` +- 仪表盘页内三快捷入口按权限裁剪 +- CRM / 报销 / 运输等其它移动端子树 +- 新建独立 `/mini/auth/menu-codes` +- 变更 Web 侧 `DB000…` 地磅菜单或 Web 侧栏逻辑 + +--- + +## 2. 已确认产品决策 + +| # | 决策 | +|---|------| +| D1 | 权限码方案 **A**:独立移动端 `mini:db:*`,与 Web `db:*` 分离授权 | +| D2 | 测试库默认授权:仅 **`super_admin`** | +| D3 | 工作台方案 **X**:保留静态 `workbench-menus.js`,用 `menu-codes` 过滤;`perms` ↔ `code` 一一映射 | +| D4 | 实现深度 **方案 1**:UI 可见性;API 硬鉴权与仪表盘裁剪留后续 | +| D5 | 接口复用现有 `GET /web/auth/menu-codes`(小程序登录已走 `/web/auth/*`) | + +--- + +## 3. 数据模型(sys_menu) + +挂载父节点:已有 `id = '1'`,`menu_name = '移动端'`。 + +| 建议 id(稳定、幂等) | menu_name | parent | menu_type | path | perms | 工作台 code | +|----------------------|-----------|--------|-----------|------|-------|-------------| +| `MINI_DB_ROOT` | 地磅管理 | `1` | M | `/mini/db` | (空) | 模块 `db` | +| `MINI_DB_DASHBOARD` | 仪表盘 | `MINI_DB_ROOT` | C | `dashboard` | `mini:db:dashboard` | `db-dashboard` | +| `MINI_DB_PLANS` | 计划管理 | `MINI_DB_ROOT` | C | `plans` | `mini:db:plan:list` | `db-plans` | +| `MINI_DB_INVENTORY` | 出入库管理 | `MINI_DB_ROOT` | C | `inventory` | `mini:db:inventory:list` | `db-inventory` | +| `MINI_DB_WEIGHING` | 地磅单管理 | `MINI_DB_ROOT` | C | `weighing` | `mini:db:weighing:list` | `db-weighing` | + +公共字段约定:`tenant_no = 'shanxia2.0'`,`visible = '1'`,`status = '1'`,`is_frame = 1`,`del_flag = 0`,`component` 可空(小程序不走 Web component)。 + +**角色授权** + +- 定位超级管理员角色:`sys_role.role_name = '超级管理员'`(快照 id 多为 `097bd2c6-4e72-11f1-9f47-00163e3bdd96`;SQL 以 `role_name` + `tenant_no` 查询为准,勿写死依赖仅本地存在的 id)。 +- Web 运行时将该名称映射为 `super_admin`(见 `web_auth_roles._map_role_name_to_web`)。 +- 向该角色的 `sys_role_menu` 写入上述 5 个菜单 id(含父节点,避免有子无父)。 +- 其它角色不写。 +- SQL **幂等**:按菜单 `id` / `sys_role_menu` 唯一性用 `NOT EXISTS` 或等价写法。 + +交付脚本路径:`docs/sql/migrations/2026-09-11-mini-db-menus.sql`(实现阶段创建并在测试库执行)。 + +--- + +## 4. 运行时行为 + +### 4.1 后端 + +- 无新业务逻辑;`menu-codes` 对 `super_admin` 返回 `isSuperAdmin: true`、`all: true`、`menuCodes: []`(现有行为)。 +- 非超管返回角色并集下的 `sys_menu.perms` 列表。 + +### 4.2 小程序 + +1. `user` store 增加并缓存:`menuAll`(对应 `all`)、`menuCodes`(string[])。 +2. 登录成功后、工作台 `onShow` 时请求 `GET /web/auth/menu-codes` 并更新缓存。 +3. `workbench-menus.js` 每个叶子增加 `perms` 字段(与上表一致)。 +4. 过滤规则: + - `menuAll === true` → 当前 `visible !== false` 的模块与已 `enabled` 叶子照常展示(本期仅地磅模块可见)。 + - 否则叶子需 `perms` 属于 `menuCodes`;模块下过滤后无叶子 → **不渲染该模块块**。 +5. 无地磅权限时工作台可为空区域;不因此强制登出。 + +### 4.3 Web 管理端 + +- 菜单管理 / 角色管理已支撑移动端树;插库后即可勾选。无需新页面。 + +--- + +## 5. 架构示意 + +``` +┌─────────────┐ GET /web/auth/menu-codes ┌──────────────┐ +│ miniprogram│ ─────────────────────────────────▶│ backend │ +│ workbench │◀──── { all, menuCodes } ──────────│ sys_role_* │ +└──────┬──────┘ │ sys_menu │ + │ filter by perms └──────────────┘ + ▼ + workbench-menus.js (static + perms) + │ + ▼ + 地磅管理宫格(有权限才显示) +``` + +--- + +## 6. 验收标准 + +1. 测试库「菜单管理」:移动端 → 地磅管理 → 四个叶子,`perms` 为 `mini:db:*`。 +2. `super_admin` 角色默认勾选上述节点;其它角色默认不勾。 +3. 超管小程序:工作台可见四入口且可跳转。 +4. 无任何 `mini:db:*` 的普通用户:工作台不显示地磅块。 +5. 仅部分叶子授权:只显示对应入口。 +6. 迁移 SQL 可重复执行不产生重复行。 + +--- + +## 7. 风险与后续 + +| 风险 | 缓解 | +|------|------| +| UI 隐藏 ≠ 接口鉴权;直链仍可能打开业务页 | 方案 1 明确接受;后续方案 2 再加 API `mini:*` 鉴权 | +| 超管依赖 `all: true`,不依赖 `menuCodes` 列表 | 与 Web 一致;`sys_role_menu` 仍写入以便角色树展示勾选 | + +后续可选:仪表盘快捷入口裁剪(方案 3)、API 硬鉴权(方案 2)、其它业务移动端子树。 + +--- + +## 8. 实现清单(供 writing-plans) + +1. 编写并审阅幂等 SQL,对测试库执行。 +2. `workbench-menus.js` 增加 `perms`。 +3. `user` store + 工作台过滤逻辑。 +4. 手工验收 §6 场景。 +