2026-06-20-web-permission-system-design.md 8.9 KB

Web 管理端权限系统设计

日期: 2026-06-20 状态: 设计稿

1. 目标

将 Web 管理端从单角色互斥权限模式(v-if="isPlanner"/v-else-if="isVendor"/v-else)升级为多角色权限合并模式,支持以下角色:

角色 标识 职责
管理员 admin 系统全功能管理
成长规划师 teacher 家庭教育相关服务
营养师 nutritionist 家庭健康相关服务
文章管理员 article_manager 文章内容管理
活动管理员 activity_manager 活动发布和管理

核心约束: 一个用户可以拥有多个角色(如同时是营养师 + 文章管理员),其有效权限为所有角色权限的并集。

2. 现有状态分析

2.1 后端现状

  • User 实体已有 roles 字段(JSON 数组格式,支持多角色存储)
  • UserService.hasRole() 已支持解析多角色
  • 但 JWT 只存单 role 字段,登录仅返回单角色
  • 后端 Controller 对应关系:
    • GrowthRecordController / GrowthPlanController/api/growth/*(成长档案)
    • HealthReportController/api/health/*(健康报告)
    • HealthCheckinController/api/health/checkin/*(健康打卡)
    • ActivityController/api/activity/*(活动管理)
    • 其余管理端 API 均可用

2.2 前端现状

  • Layout.vue: 三选一互斥分支(v-if="isPlanner" / v-else-if="isVendor" / v-else
  • Router: 硬编码 teacherRoutes / adminRoutes 名单判断
  • 认证: localStorage 存单 role 字段
  • 现有页面: 文章管理页面已有;成长档案/健康档案/活动管理页面需新建

2.3 需新建的前端页面

页面 路径 对应角色 后端 API
我的家庭 /my-families teacher, nutritionist 现有 /api/guide/*
成长记录 /growth-records teacher GrowthRecordController
成长计划 /growth-plans teacher GrowthPlanController
健康报告 /health-reports nutritionist HealthReportController
健康指标 /health-indicators nutritionist HealthReportController
健康打卡 /health-checkins nutritionist HealthCheckinController
活动列表 /activities activity_manager ActivityController
活动审核 /activity-review activity_manager ActivityController

3. 架构设计

3.1 权限模型

采用 Permission-based 方案。定义两层权限标识:

  • 通配级: 'assessment:*' 匹配所有 assessment: 开头的权限
  • 原子级: 'articles:manage' 精确匹配单个功能

角色→权限映射

// src/utils/permissions.js
const ROLE_PERMISSIONS = {
  admin:            ['*'],
  teacher:          ['dashboard', 'service:*', 'growth:*', 'biz:*', 'assessment:*', 'messages'],
  nutritionist:     ['dashboard', 'service:family', 'health:*', 'assessment:dan', 'energy'],
  article_manager:  ['dashboard', 'articles:*'],
  activity_manager: ['dashboard', 'activity:*'],
}

菜单→权限映射

首页 /dashboard                              → dashboard
家庭管理 (system) /families /children /points  → family:*
任务管理 /tasks /task-templates               → task:*
奖励管理 /rewards                             → reward:*
系统管理 /users /sys-config /...               → system:*
我的家庭 /my-families                         → service:family
成长记录 /growth-records                      → growth:records
成长计划 /growth-plans                        → growth:plans
套餐管理 /teacher-packages                    → biz:packages
订单佣金 /teacher-orders                      → biz:orders
DAN测评 /teacher-assessment                   → assessment:dan
家长咨询 /teacher-consult                     → assessment:consult
消息中心 /teacher-messages                    → messages
健康报告 /health-reports                      → health:reports
健康指标 /health-indicators                   → health:indicators
健康打卡 /health-checkins                     → health:checkins
五维能量 /energy-sandbox                      → energy
文章分类 /article-categories                  → articles:categories
文章管理 /article-manage                      → articles:manage
文章编辑 /article-edit                        → articles:edit
活动列表 /activities                          → activity:list
活动审核 /activity-review                     → activity:review

3.2 后端变更

JWT 变更

当前: generateToken(userId, role) → JWT payload 含 role: "admin"

改为: generateToken(userId, roles) → JWT payload 含 roles: ["admin", "article_manager"]

API 变更

POST /api/admin-auth/login 响应增加 roles 数组:

{
  "code": 200,
  "data": {
    "token": "...",
    "adminId": 1,
    "username": "admin",
    "realName": "管理员",
    "role": "admin",
    "roles": ["admin", "article_manager"]
  }
}

POST /api/admin-auth/info 响应同样增加 roles 数组。

无需迁移: User 表 roles 字段已存在,仅前端新增的角色值(nutritionist, article_manager, activity_manager)需要在用户管理后台可设置。

3.3 前端变更

3.3.1 权限工具模块

新增 src/utils/permissions.js

// 角色→权限映射表
const ROLE_PERMISSIONS = { ... }

// 菜单定义(每个菜单项带权限标识)
const MENU_DEFINITIONS = [ ... ]

// 核心函数
function getEffectivePermissions(roles) { /* 合并所有角色的权限 */ }
function hasPermission(userPerms, required) { /* 前缀匹配 + 通配 * 支持 */ }

3.3.2 状态管理

Login.vue 登录后存储:

localStorage.setItem('roles', JSON.stringify(res.data.roles))

新增 Vuex store 或全局 computed 读取 roles

3.3.3 Layout.vue 菜单渲染

从目前的硬编码三层分支改为:

<template v-for="item in menuItems">
  <el-submenu v-if="item.children && hasPerm(item.perm)">
    ...子项统一渲染...
  </el-submenu>
  <el-menu-item v-else-if="hasPerm(item.perm)">
    ...
  </el-menu-item>
</template>

3.3.4 Router 守卫

路由 meta 增加 perm 字段:

{
  path: 'article-manage',
  component: ...,
  meta: { title: '文章管理', perm: 'articles:manage' }
}

路由守卫检查逻辑:

if (to.meta.perm) {
  const perms = getEffectivePermissions(userRoles)
  if (!hasPermission(perms, to.meta.perm)) {
    return next({ path: '/403', replace: true })
  }
}

保留现有 requiresTeacher 兼容过渡,逐步替换为 perm

4. 菜单结构(最终效果)

管理员登录

首页 | 家庭管理 | 任务管理 | 奖励管理 | 系统管理(全部子项)

成长规划师登录

首页
我的家庭 → 家庭详情 → 成长档案tab / 成长计划tab / 家庭成员tab
成长记录
成长计划
业务管理 → 套餐管理 / 订单佣金
测评管理 → DAN测评 / 家长咨询
消息中心

营养师登录

首页
我的家庭 → 家庭详情 → 健康报告tab / 健康指标tab / 健康打卡tab
健康报告
健康指标
健康打卡
五维能量

文章管理员登录

首页
文章分类
文章管理

活动管理员登录

首页
活动列表
活动审核

多角色合并(示例:营养师 + 文章管理员)

首页
我的家庭 | 健康报告 | 健康指标 | 健康打卡 | 五维能量
文章分类 | 文章管理

5. 新建页面骨架

每个新建页面仅创建 Vue 文件 + 路由注册,内容为一个带 el-table 骨架的占位页:

  • /my-families — 授权家庭列表(复用教师端现有 TeacherFamilies.vue 逻辑)
  • /growth-records — 成长记录列表,依赖 GrowthRecordController
  • /growth-plans — 成长计划列表,依赖 GrowthPlanController
  • /health-reports — 健康报告列表,依赖 HealthReportController
  • /health-indicators — 健康指标管理,依赖 HealthReportController
  • /health-checkins — 健康打卡列表,依赖 HealthCheckinController
  • /activities — 活动列表管理,依赖 ActivityController
  • /activity-review — 活动审核,依赖 ActivityController

6. 实施步骤

  1. 后端:JWT 及 API 多角色支持
  2. 新增 src/utils/permissions.js 权限引擎
  3. 重构 Layout.vue 菜单渲染(权限驱动)
  4. 重构 Router 守卫(权限检查)
  5. Login.vue 适配多角色存储
  6. 新建 8 个页面骨架 + 路由注册
  7. 验证:admin/teacher 现有功能不受影响

7. 未纳入范围

  • 用户管理后台的角色编辑界面(已有 User.roles 字段,未来可通过管理接口直接编辑)
  • 「我的家庭」进入后的 tab 式详情页设计(本期只搭路由和菜单入口)
  • 小程序端权限(仅 Web 管理端)