v3 改了什么(长官 9-28 三条意见 + 用户页自检):
1. 撤掉 v2 新加的「机构工作台」「数据与模型」两个分组:那 8 个旧页面只有超管在用,这次不开放给客户,原样不动
2. 原「设置管理」改名「系统管理」(长官 9-28 定):「权限配置」换成「角色管理」,「用户管理」挪进来;平台员工仍可编辑页面勾选(v3.1 自检补:旧页面的这个能力不能丢)
3. 角色的功能权限改成标准树状勾选:分组 → 页面 → 功能,每一层都能勾
4. 用户页自检改了 8 处(见第五节末尾「用户页自检」)功能清单:20 个菜单页面逐个盘点(~/reports/phase86-permission-inventory-20260928.md)
左侧菜单
├─ 平台管理 看板 / 机构管理 / 机构洞察 / 席位活动 / 子席位管理 / 题库审核(不变)
├─ 结算管理 9 个页面(不变)
├─ 系统管理 ← 原「设置管理」改名,里面调整
│ ├─ 用户管理 ← 从「平台管理」挪过来(8-08 起被隐藏,现在恢复)
│ ├─ 角色管理 ← 新增,替代原来的「权限配置」
│ ├─ 审计日志 (原有)
│ ├─ 系统监控 (原有)
│ └─ 个人设置 (原有,所有账号默认都有)
└─ 导演台管理 Skill 制造机(不变)
原「设置管理」放的是:系统监控、审计日志、个人设置,还有只有超管看得到的「权限配置」(web/app/(dashboard)/admin/AdminConsoleShell.tsx:73-80)。
为什么「权限配置」要换成「角色管理」:旧的权限配置页只能给「平台员工」这一种角色开关菜单(app/core/menu_registry.py:14 写死只有 admin 和 platform_staff 两种)。新的角色管理能建任意多个角色,每个角色自己勾页面和功能,旧页面能做的事它全包了。两个页面同时留着,同一件事有两个地方改,容易改乱,所以合并成一个。
没被授权的菜单直接不显示;手输网址进入,显示第六节的「无权限」页。
┌────────────────────────────────────────────────────────────────────────┐
│ 角色管理 [ + 新建角色 ] │
├────────────────────────────────────────────────────────────────────────┤
│ 搜索角色名 [____________] │
├────────────┬────────┬────────┬──────┬────┬──────────────┬───────────────┤
│ 角色名称 │数据范围│可用页面│用户数│状态│ 最后修改 │ 操作 │
├────────────┼────────┼────────┼──────┼────┼──────────────┼───────────────┤
│ 超级管理员 │全部机构│ 全部 │ 2 │启用│ — │ 内置·不可改 │
│ 平台员工 │全部机构│ 10 个 │ 1 │启用│ 09-28 admin │ 编辑(只勾页面)│
│ 门店客户 │指定机构│ 4 个 │ 12 › │启用│ 09-27 admin │ 编辑 停用 │
│ 品牌方 │指定机构│ 6 个 │ 0 │停用│ 09-26 admin │ 编辑 启用 删除│
└────────────┴────────┴────────┴──────┴────┴──────────────┴───────────────┘
用户数可点(›),跳到用户列表并按这个角色筛好
共 4 条 < 1 >
┌────────────────────────────────────────────────────────────────────────┐
│ 系统管理 / 角色管理 / 新建角色 │
├────────────────────────────────────────────────────────────────────────┤
│ 角色名称 * [门店客户______________] │
│ 说明 [给合作门店老板用的账号____________________] │
│ │
│ 数据范围 * (●) 全部机构 能看所有机构的数据 │
│ ( ) 指定机构 只能看用户账号上勾选的机构 │
│ │
│ 功能权限 * [展开全部] [收起全部] [全选] [清空] │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ ▼ ◧ 平台管理 │ │
│ │ ▼ ☑ 看板 │ │
│ │ ☑ 查看 │ │
│ │ ▼ ◧ 机构管理 │ │
│ │ ☑ 查看 │ │
│ │ ☐ 新增机构 │ │
│ │ ☑ 改基本资料 │ │
│ │ ☐ 改功能开关 │ │
│ │ ☐ 启用 / 停用 │ │
│ │ ☐ 删除 │ │
│ │ ☐ 访问链接与凭证 │ │
│ │ ☐ 家长端头图 │ │
│ │ ☐ 品牌码 │ │
│ │ ☐ 子席位前缀 │ │
│ │ ▼ ◧ 席位 │ │
│ │ ☑ 查看 │ │
│ │ ☐ 生成席位 │ │
│ │ ☐ 编辑 / 延期 │ │
│ │ ☐ 启用 / 停用 │ │
│ │ ▶ ☐ 机构洞察 指定机构暂不可用 │ │
│ │ ▶ ☑ 席位活动 │ │
│ │ ▶ ◧ 子席位管理 │ │
│ │ ▶ ☐ 题库审核 数据不分机构 │ │
│ │ ▶ ◧ 结算管理 │ │
│ │ ▶ ☐ 系统管理 │ │
│ │ ▶ ☐ 导演台管理 │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ 已选 4 个页面、7 个功能 │
│ │
│ [ 取消 ] [ 保存 ] │
└────────────────────────────────────────────────────────────────────────┘
☑ 全选 ◧ 选了一部分 ☐ 没选
树的勾选规则:
- 勾上一层,下面全部跟着勾上;取消上一层,下面全部取消
- 下面只勾了一部分,上一层显示「◧」
- 勾任何一个功能,同一页面的「查看」自动勾上;取消「查看」,这一页的功能全部取消(没有查看就进不了页面)
- 页面右侧的灰字说明它在「指定机构」下的表现(见下表);选了「指定机构」时,标「暂不可用」的页面整行灰掉、勾不上
每个页面在「指定机构」下的表现(按代码逐页核过)
| 类型 | 页面 | 「指定机构」下 |
|---|---|---|
| ① 按机构筛(9 页) | 机构管理(含席位、品牌码)、席位活动、子席位管理、机构签约、收款管理、收益账本、转发记录、用户管理、审计日志 | 只显示选中机构的数据;改网址里的编号也看不到别家 |
| ② 暂不可用(5 页) | 看板、结算总览、机构洞察、结算列表、渠道管理 | 这几页把多家机构混在一起算(例如一张结算单里有好几家店的钱),直接给会露出别家数据。先做「本机构版」再放开 |
| ③ 数据不分机构(6 页) | 题库审核、价格管理、客服设置、Skill 制造机、系统监控、角色管理 | 能勾,看到的是全平台那一份(例如价格表本来就只有一份) |
表单校验:角色名称不能空、不能重名;至少勾一个功能;保存失败时在按钮上方显示原因,已填内容保留。
┌────────────────────────────────────────────────────────────────────────┐
│ 用户管理 [ + 新增用户 ] │
├────────────────────────────────────────────────────────────────────────┤
│ 搜索账号/姓名/手机 [________] 角色 [全部▼] 机构 [全部▼] 状态 [全部▼] │
├──────────┬──────┬──────────┬──────────────────┬────────┬────────┬──────┤
│ 账号 │ 姓名 │ 角色 │ 可看机构 │ 状态 │最后登录│ 操作 │
├──────────┼──────┼──────────┼──────────────────┼────────┼────────┼──────┤
│ admin │ 平台 │ 超级管理员│ 全部 │ ●正常 │ 09-28 │ 详情 │
│ zhangsan │ 张三 │ 门店客户 │ 示例眼视光 │ ●待改密│ 从未 │ 详情 │
│ brand01 │ 李四 │ 品牌方 │ 示例眼视光 等3家 │ ●锁定 │ 09-27 │ 详情 │
│ wangwu │ 王五 │ 门店客户 │ 示例·银泰店 │ ●停用 │ 09-01 │ 详情 │
└──────────┴──────┴──────────┴──────────────────┴────────┴────────┴──────┘
users/page.tsx:273-287)┌────────────────────────────────────────────────────────────────────────┐
│ 系统管理 / 用户管理 / 新增用户 │
├────────────────────────────────────────────────────────────────────────┤
│ 登录账号 * [brand01_________] 1-64 位,不能和已有账号重复 │
│ 姓名 * [李四____________] │
│ 手机号 [138xxxxxxxx_____] 选填 │
│ │
│ 角色 * [品牌方 ▼] 数据范围:指定机构 │
│ │
│ 可看机构 * (角色是「指定机构」时才出现) │
│ ┌──────────────────────────────────────────────┐ │
│ │ 搜索机构名 [示例______] │ │
│ │ ☑ 示例眼视光 │ │
│ │ ☑ 示例·万达店 │ │
│ │ ☐ 示例·银泰店 │ │
│ └──────────────────────────────────────────────┘ │
│ 已选 2 家:示例眼视光 ✕ 示例·万达店 ✕ │
│ │
│ 密码:保存后系统自动生成,只显示一次;首次登录必须修改 │
│ │
│ [ 取消 ] [ 保存 ] │
└────────────────────────────────────────────────────────────────────────┘
用户页自检(v3):
| # | 上一版的问题 | 代码事实 | 改法 |
|---|---|---|---|
| 1 | 客户账号打算用现成的「机构管理员」类型 | 这个类型在代码里直接绑了 5 类接口(机构配置、API Key、企微、Excel 导入、机构知识库),不经过角色勾选就能调(如 app/api/org_config.py:49 require_role("org_admin"))。而且它强制绑一家机构,没法做「全部机构」的自定义角色 |
新增一种账号类型「后台账号」,权限只来自角色勾选,没勾就什么都没有。生产现有「机构管理员」账号 0 个,不影响任何人 |
| 2 | 状态只画了正常 / 停用 | 现有页面还有「锁定」「待改密」(users/page.tsx:273-287) |
补上 |
| 3 | 编辑页同时有「删除」和「停用」 | 现有「删除」其实就是停用(user_mgmt_service.py:247 软删除,只改 is_active=False) |
只留「停用 / 启用」 |
| 4 | 写了「账号只能用字母、数字、下划线」 | 代码只限长度 1-64(admin_users.py:57),这条规则是我编的 |
按现状写「1-64 位,不能重复」 |
| 5 | 初始密码画成下拉可选 | 后台只会自动生成(admin_users.py:68 返回 temporary_password) |
改成一行说明 |
| 6 | 姓名画成必填 | 现有建号接口没有姓名字段(admin_users.py:56-63),数据库有 real_name 列 |
保留必填,接口补这个字段 |
| 7 | 手机号没说会撞号 | 手机号在「非门店席位」这一类里全局唯一(phase74_001_parent_subseat_foundation.py:91-93),家长在 H5 注册过的手机号,再用来开后台账号会失败 |
手机号选填;撞号时提示「该手机号已被其他账号使用」 |
| 8 | 列表没有按机构筛 | 客户账号多了以后找人难 | 加「机构」筛选 |
另两条保护(技术上必须做):不能停用自己、不能改自己的角色(现有停用接口没拦,user_mgmt_service.py:247-256)。
┌────────────────────────────────────────────────────────────────────────┐
│ (左侧菜单只显示被授权的页面) │
│ │
│ 你没有这个页面的权限 │
│ 如需开通,请联系平台管理员 │
│ [ 返回首页 ] │
└────────────────────────────────────────────────────────────────────────┘
web/app/login/page.tsx:137)。改成跳到他有权限的第一个页面,避免客户一登录就撞无权限页角色管理
| 字段 / 行为 | 结论 | 依据 |
|---|---|---|
| 角色名称 | 必填,最多 20 字,不能重名 | 列表列宽放得下;重名会在用户页下拉里分不清 |
| 说明 | 选填,最多 100 字 | —— |
| 列表加「最后修改」(时间 + 修改人) | 新增 | 角色改了会影响一批人,要能看出是谁、什么时候改的 |
| 用户数可点,跳到用户列表 | 新增 | 想知道「这个角色给了谁」时不用再去翻 |
| 改权限 / 改数据范围时保存前弹确认 | 新增:「这个角色下有 N 个用户,保存后立即生效」 | 一改影响一批人 |
| 「指定机构」改成「全部机构」 | 新增强提示:「这 N 个用户将能看到所有机构的数据」 | 这是最容易误操作造成数据外泄的一步 |
| 「全部机构」改成「指定机构」 | 已勾的「暂不可用」页面自动取消并提示;角色下还没选机构的用户,列出名字提醒去补 | 不补的话这些人登录后什么数据都看不到 |
用户管理
| 字段 / 行为 | 结论 | 依据 |
|---|---|---|
| 登录账号 | 1-64 位,不区分大小写(Abc 和 abc 算同一个),创建后不能改 | 现在区分大小写,能建出 Abc、abc 两个号,容易混(app/models/user.py:33 无大小写处理,服务层无 lower);现有详情页账号本就不可改 |
| 姓名 | 必填 | 数据库有 real_name 列;建号接口缺这个字段,要补(admin_users.py:56-63) |
| 邮箱 | 不做 | 现有建号接口收邮箱,但数据库没有这一列,填了会被悄悄丢掉(user_mgmt_service.py:155)。本期不加,接口里这个假字段一并去掉 |
| 手机号 | 选填;撞号提示「该手机号已被其他账号使用」 | 和家长 H5 账号共用一个唯一范围(phase74_001_parent_subseat_foundation.py:91-93) |
| 角色 | 必填,建号后可以改 | 现有详情页角色是灰的、不能改(users/[id]/page.tsx:272-283),换角色是常见操作 |
| 可看机构 | 多选;机构名后标「品牌方」;已停用的机构灰显 | 机构下拉接口一次返回全部机构,带品牌码开关字段(api_v1.py:310、brand_code_enabled) |
| 状态 | 正常 / 待改密 / 锁定 / 停用 | 「锁定」是连续输错 15 次后的短暂冷却(1-5 分钟,auth_service.py:60-66),不是永久锁 |
| 详情页「软删除」按钮 | 改名「停用」 | 它实际就是停用(user_mgmt_service.py:247-256),叫软删除让人以为数据没了 |
| 重置密码弹窗「7 天有效」 | 删掉这几个字 | 初始密码 7 天有效的机制 9-04 已取消,文案没跟着改(users/[id]/page.tsx:365) |
其他页面
| 页面 | 结论 |
|---|---|
| 个人设置 | 加两行只读信息:「我的角色」「我能看的机构」,客户自己知道权限范围 |
| 审计日志 | 现在只记 5 种登录类事件(app/models/audit.py:48-52),要新增:角色新建/修改/停用、用户换角色、换机构、停用/启用;并加「操作人」一列(现在操作人藏在明细里) |
| 结算页面左侧菜单 | 结算是另一个独立前端,它的 9 个菜单写死、不按权限过滤(settlement/web/.../minicup-admin-shell.tsx:77-91),没权限也能看到菜单、点进去才报错 → 第 1 批一起改成按权限显示 |
| 登录后去哪 | 跳到有权限的第一个页面(见第六节) |
| # | 问题 | 出处 | 严重度 |
|---|---|---|---|
| 1 | 标注审核 4 个接口连登录都不查:校验那一行被注释掉了,不登录也能调;按医生编号查数据,不分机构 | app/api/annotations.py:19/36/56/84(# current_user = Depends(verify_token)),main.py:191 挂在 /api 下 |
🔴 高 |
| 2 | 题库审核 4 个接口只查登录、不查角色,家长登录后也能审核题目 | app/api/admin_rumor_questions.py:84/109/131/161 |
🟠 中 |
| 3 | 席位活动的「按机构筛」没生效,改编号能看别家席位记录(现在只有超管能进,还没出事) | app/api/admin_activity.py:266-278 |
🟡 开放前必修 |
方向:可行。「建角色 → 勾页面和功能 → 选数据范围 → 建用户选角色和机构」是后台通用做法,现有代码也有一半底子(菜单开关表、菜单注册表、前端按权限显示菜单)。
真正的难点不在两个新页面,在后面 20 个老页面:
| 要做的事 | 规模(按代码数过) | 风险 |
|---|---|---|
| 把「只认超管」改成「认勾选」 | 核心后台 88 处 + 结算后台 77 处,约 165 处检查点 | 机械活,量大;漏一处 = 那个按钮勾了也用不了 |
| 「指定机构」按机构过滤 | ①类 9 个页面,每个列表加过滤、每个带编号的接口查归属 | 最危险:漏一处 = 客户能看到别家数据 |
| 结算页面按钮隐藏 | 结算页面是另一个独立前端(嵌在后台里),两边都要改 | 工作量翻倍 |
控制风险的办法:
- 默认全部拒绝,只有勾了才放行
- 写一套自动测试:用两个不同机构的账号互相调对方的数据,所有接口都必须被拒;这套测试不过不许发版
建议分批(每批单独发 test 验):
| 批 | 做什么 | 做完客户能用什么 |
|---|---|---|
| 0 | 修第八节 3 个漏洞 | —— |
| 1 | 角色管理 + 用户管理 + 20 个页面的按钮权限生效 | 「全部机构」的角色能用(例如给内部员工分权) |
| 2 | ①类 9 个页面支持「指定机构」 | 客户账号能用这 9 页,只看自己的店 |
| 3 | ②类 5 个页面做「本机构版」 | 客户也能用看板、结算列表等 |
本期不含:平台手机端、旧侧栏 8 个老页面、家长端和门店平板(它们各自有账号体系,不受影响)。
确认后出高保真效果图。