权限模块设计说明.md 18 KB

权限模块设计说明

1. 权限架构总览

本系统采用双层次权限控制架构

层级 控制点 实现方式 范围
第一层 - 前端 路由访问、按钮显示 路由守卫(meta.roles)+ Auth 组件 / v-auth 指令 菜单可见性、按钮/操作可见性
第二层 - 后端 API 接口 @RequirePermission 注解 + AOP 切面 接口访问权限校验

两个层级独立校验,前端控制用户体验(隐藏无权限的元素),后端控制数据安全(阻止越权请求)。


2. 后端权限实现

2.1 核心注解

@RequirePermission

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequirePermission {
    String value();       // 权限编码,格式: module:operation
    String message() default "无操作权限";  // 无权限时的提示信息
}

使用位置:Controller 方法上,标注该接口所需的权限编码。

@SuperAdmin

public @interface SuperAdmin {
    String message() default "仅超级管理员可访问";
}

使用位置:Controller 方法上,标注仅超级管理员可访问的接口。

2.2 权限校验原理(PermissionAspect)

使用 Spring AOP @Around 切面拦截所有带有 @RequirePermission 的方法,执行流程:

  1. 通过 Sa-Token StpUtil.getLoginId() 获取当前登录用户
  2. 从 Session 中获取用户的角色 ID 列表
  3. 超级管理员豁免:如果用户角色包含 roleId=1(超级管理员),直接放行
  4. 通过 DataPermissionService.getPermissionCodesByRoleIds() 查询用户拥有的所有权限编码
  5. 检查用户权限列表中是否包含接口所需的权限编码
  6. 包含则放行,不包含则返回 Result.error(403, "无操作权限")

2.3 数据模型

t_data_permission(权限定义表)

字段 类型 说明
id BIGINT 主键(雪花算法)
permission_code VARCHAR 权限编码,如 product:create
permission_name VARCHAR 权限名称,如 商品创建
module_code VARCHAR 模块编码,如 product
module_name VARCHAR 模块名称,如 商品管理
operation_type VARCHAR 操作类型: create/read/update/delete/execute
description VARCHAR 权限描述
sort_order INT 排序
status INT 状态: 1-启用, 0-禁用
create_time DATETIME 创建时间
update_time DATETIME 更新时间

t_role(角色表)

角色通过 role_idt_role_permission 关联,实现角色-权限多对多关系。

t_role_permission(角色权限关联表)

关联角色与权限的多对多关系。

2.4 权限编码规则

格式:{module_code}:{operation_type}

操作类型 适用场景 说明
read 查询类操作 列表、详情、统计、导出
create 创建类操作 新增记录
update 更新类操作 编辑、修改状态、发布/下线、审核
delete 删除类操作 删除、批量删除
export 导出操作 导出数据
import 导入操作 导入数据
execute 执行操作 同步、手动执行
distribute 发放操作 发放优惠券
review 审核操作 审核提现
generate 生成操作 生成报表

2.5 权限编码清单

系统管理

权限编码 权限名称 所属模块
admin:read 管理员查询 管理员管理
admin:create 管理员新增 管理员管理
admin:update 管理员编辑 管理员管理
admin:delete 管理员删除 管理员管理
role:read 角色查询 角色管理
role:create 角色新增 角色管理
role:update 角色编辑 角色管理
role:delete 角色删除 角色管理
dict:read 字典查询 字典管理
dict:create 字典新增 字典管理
dict:update 字典编辑 字典管理
dict:delete 字典删除 字典管理
dict:export 字典导出 字典管理
dict:import 字典导入 字典管理

运营监控

权限编码 权限名称 所属模块
operation-log:read 操作日志查询 操作日志
operation-log:delete 操作日志删除 操作日志
sync:read 同步记录查询 数据同步
sync:execute 执行数据同步 数据同步

公告管理

权限编码 权限名称 所属模块
announcement:read 公告查询 公告管理
announcement:create 公告新增 公告管理
announcement:update 公告编辑 公告管理
announcement:delete 公告删除 公告管理

订单管理

权限编码 权限名称 所属模块
order:read 订单查询 订单管理
order:update 订单编辑/退款审核 订单管理

商品管理

权限编码 权限名称 所属模块
product:read 商品查询 商品管理
product:create 商品新增 商品管理
product:update 商品编辑/同步 商品管理
product:delete 商品删除 商品管理
product-apply:read 新品申请查询 新品申请
product-apply:create 新品申请提交 新品申请
product-apply:update 新品申请更新 新品申请
product-apply:delete 新品申请删除 新品申请

门店管理

权限编码 权限名称 所属模块
shop:read 门店查询 门店管理
shop:create 门店新增 门店管理
shop:update 门店编辑/设备关联/补货员管理 门店管理
shop:delete 门店删除 门店管理

设备管理

权限编码 权限名称 所属模块
device:read 设备查询/详情/统计 设备管理
device:update 设备远程控制/配置 设备管理

设备告警

权限编码 权限名称 所属模块
device-alert:read 告警记录查询/统计 设备告警

库存管理

权限编码 权限名称 所属模块
inventory:read 库存查询/日志/统计 库存管理
inventory:create 创建上货记录 库存管理
inventory:update 库存调整/上货完成 库存管理

客户管理

权限编码 权限名称 所属模块
user:read 客户查询/详情/统计 客户管理
user:update 客户状态/信用分更新 客户管理

营销中心

权限编码 权限名称 所属模块
dashboard:read 数据概览 数据概览
marketing:activity:read 活动查询 营销活动
marketing:activity:create 活动创建 营销活动
marketing:activity:edit 活动编辑/暂停/恢复 营销活动
marketing:activity:publish 活动发布 营销活动
marketing:activity:delete 活动删除 营销活动
marketing:activity:list 统一活动列表 统一活动
marketing:coupon:read 优惠券查询 优惠券管理
marketing:coupon:create 优惠券创建 优惠券管理
marketing:coupon:edit 优惠券编辑 优惠券管理
marketing:coupon:delete 优惠券删除 优惠券管理
marketing:coupon:distribute 优惠券发放 优惠券管理
marketing:invite:read 邀请活动查询 邀请活动
marketing:invite:create 邀请活动创建 邀请活动
marketing:invite:edit 邀请活动编辑 邀请活动
timed-discount:read 定时折扣查询 定时折扣
timed-discount:create 定时折扣创建 定时折扣
timed-discount:edit 定时折扣编辑 定时折扣
timed-discount:delete 定时折扣删除 定时折扣
timed-discount:execute 定时折扣执行 定时折扣

分销管理

权限编码 权限名称 所属模块
distribution:distributor:create 分销员创建 分销管理
distribution:distributor:read 分销员查询 分销管理
distribution:distributor:update 分销员编辑/激活/停用 分销管理
distribution:distributor:delete 分销员删除 分销管理
distribution:referral:read 推荐记录查询 分销管理
distribution:commission:read 佣金记录查询 分销管理
distribution:withdrawal:read 提现记录查询 分销管理
distribution:withdrawal:review 提现审核/确认到账 分销管理
distribution:report:read 月度报表查询 分销管理
distribution:report:generate 生成月度报表 分销管理
distribution:report:export 导出月度报表 分销管理
distribution:dashboard:read 分销概览 分销管理
distribution:config:read 分销配置查询 分销管理
distribution:config:update 分销配置更新 分销管理

统计报表

权限编码 权限名称 所属模块
statistics:read 统计概览 统计报表
statistics:category 品类统计 统计报表
statistics:product 商品统计 统计报表
statistics:device 设备统计 统计报表
statistics:shop 门店统计 统计报表
statistics:profit 利润统计 统计报表
statistics:repurchase 复购统计 统计报表
statistics:export 统计导出 统计报表

设备层模版

权限编码 权限名称 所属模块
layer-template:read 层模版查询 层模版管理
layer-template:create 层模版创建 层模版管理
layer-template:update 层模版编辑/同步 层模版管理
layer-template:delete 层模版删除 层模版管理

签到管理

权限编码 权限名称 所属模块
checkin:read 签到记录查询 签到管理
checkin:create 签到提交/同步 签到管理

2.6 业务异常抛出

// 使用 ResponseEnum 枚举
throw new BusinessException(ResponseEnum.ORDER_NOT_FOUND);

// 自定义消息
throw new BusinessException(404, "订单不存在");

// 仅消息(默认500)
throw new BusinessException("操作失败");

2.7 操作日志注解 @Log

写操作(增/删/改)必须添加操作日志注解:

@Log(module = "模块名", operation = OperationType.XXX, summary = "操作描述")
OperationType 说明
INSERT 新增操作
UPDATE 更新操作
DELETE 删除操作
SYNC 同步操作
EXPORT 导出操作
IMPORT 导入操作
LOGIN 登录操作
LOGOUT 登出操作
OTHER 其他操作

3. 前端权限实现

3.1 路由级权限控制

路由配置:在 src/router/modules/ 下的路由配置文件中,通过 meta.roles 指定允许访问的角色:

meta: {
  title: "管理员管理",
  roles: ["admin"]  // 仅 admin 角色可访问
}

路由守卫src/router/utils.ts 中的 filterTreeinitRouter 函数根据用户角色动态过滤路由。

3.2 按钮级权限控制

提供两种方式:

v-auth 指令(基于路由 meta 中的 auth 配置)

<el-button v-auth="['btn.add']">新增</el-button>

在路由配置中定义按钮级权限码:

meta: {
  auths: ["btn.add", "btn.edit", "btn.delete"]
}

v-perms 指令(基于用户 permissions 列表)

<el-button v-perms="['product:create']">新增商品</el-button>

用户的 permissions 在登录时从后端获取并存储到 userStore 中。如果用户拥有 *:*:*(超级管理员权限),则所有操作均可执行。

3.3 登录与权限加载流程

  1. 调用 /login API 登录
  2. 后端返回 accessTokenrefreshToken、用户信息(包含角色和权限列表)
  3. 前端存储 Token 到 Cookie(authorized-token)和 localStorage(user-info
  4. useUserStoreHook().SET_ROLES/SET_PERMS 存储角色和权限到 Pinia store
  5. 路由守卫 initRouter() 根据用户角色动态过滤可访问的路由
  6. 401 响应自动触发登出流程

3.4 Token 管理

  • Token 存储在 Cookie 和 localStorage 双保险
  • 请求头格式:Authorization: Bearer {token}
  • 无感刷新机制:Token 过期时自动调用刷新接口
  • 401 响应自动清除 Token 并跳转登录页

4. 完整权限校验流程图

用户请求
  |
  v
[前端路由守卫] ── 检查 meta.roles
  |  无权限 → 跳转 403 页面
  |  有权限 → 加载页面
  v
[前端按钮级 v-perms/v-auth]
  |  无权限 → DOM 元素被移除
  |  有权限 → 显示按钮
  v
[前端发起 API 请求] ── 携带 Bearer Token
  |
  v
[Sa-Token 拦截器] ── 验证 Token 有效性
  |  无效 → 返回 401
  |  有效 → 继续
  v
[AOP @RequirePermission 切面]
  |  无注解 → 放行
  |  有注解:
  |    获取用户角色列表
  |    是超级管理员(roleId=1) → 放行
  |    检查用户权限列表是否包含所需权限
  |      不包含 → 返回 403
  |      包含 → 放行
  v
[Controller 执行业务逻辑]

5. 注意事项与最佳实践

5.1 权限编码命名规范

  • 格式:{module_code}:{operation_type}
  • module_code 使用小写字母,多词用中划线连接(如 timed-discountoperation-log
  • operation_type 使用小写字母

5.2 新增功能权限纳入规范

开发新功能时,必须按以下流程确保权限控制完整:

  1. Controller 中所有接口必须添加 @RequirePermission 注解
  2. 写操作接口(增/删/改)必须添加 @Log 注解
  3. t_data_permission 表中添加对应的权限记录
  4. 前端菜单配置中添加 meta.roles 和按钮级权限码
  5. 本文档中补充新增的权限编码

5.3 常见错误

  • UserController 缺少权限注解(已修复)—— 客户管理模块完全缺失 @RequirePermission
  • DeviceAlertController 缺少权限注解(已修复)—— 设备告警模块完全缺失 @RequirePermission
  • LayerTemplateController 临时移除权限(已修复)—— 三个接口的 @RequirePermission 被注释并标注 TODO
  • 辅助查询接口缺少权限(已修复)—— 部分下拉选择接口未加权限注解

5.4 接口分类与权限策略

接口类型 权限策略 示例
查询列表 module:read @RequirePermission("order:read")
查询详情 module:read @RequirePermission("order:read")
新增 module:create @RequirePermission("product:create")
编辑 module:update @RequirePermission("product:update")
删除 module:delete @RequirePermission("product:delete")
状态变更 module:update @RequirePermission("shop:update")
审核 module:review @RequirePermission("distribution:withdrawal:review")
同步 module:update @RequirePermission("layer-template:update")
导出 module:export @RequirePermission("statistics:export")
登录 无需权限(@SaIgnore AdminLoginController.login()

6. 前端菜单与后端权限映射

前端菜单 后端 Controller 权限前缀
数据概览 DashboardController dashboard:read
订单管理 OrderController order:read/update
退款管理 RefundApplicationController order:read/update
门店管理 ShopController shop:read/create/update/delete
设备管理 DeviceController device:read/update
门店分布地图 (ShopController 复用) shop:read
商品列表 ProductController product:read/create/update/delete
新品申请 NewProductApplyController product-apply:read/create/update/delete
库存管理 InventoryController inventory:read/create/update
客户管理 UserController user:read/update
营销活动 MarketingActivityController / UnifiedActivityController marketing:activity:*
优惠券管理 CouponController marketing:coupon:*
定时折扣 TimedDiscountController timed-discount:*
邀请活动 InviteActivityAdminController marketing:invite:*
分销管理 DistributorAdminController distribution:*
统计报表 StatisticsController statistics:*
管理员管理 AdminController admin:read/create/update/delete
角色管理 RoleController role:read/create/update/delete
权限管理 DataPermissionController role:read/update
公告管理 AnnouncementController announcement:*
操作日志 OperationLogController operation-log:read/delete
数据同步 DataSyncController sync:read/execute
字典管理 DictController dict:read/create/update/delete/export/import
签到管理 CheckinController checkin:read/create
设备告警 DeviceAlertController device-alert:read
层模版管理 LayerTemplateController layer-template:*

7. 权限修复记录

2026-04-29 修复清单

文件 问题 修复内容
UserController.java 5个接口完全缺失@RequirePermission 新增 user:read(列表/详情/统计), user:update(状态/信用分)
DeviceAlertController.java 2个接口完全缺失@RequirePermission 新增 device-alert:read(列表/统计)
LayerTemplateController.java 3个接口TEMP注释移除权限 恢复 layer-template:read(list), layer-template:update(sync/batchSync)
DictController.java getDictDataList缺少@RequirePermission 新增 dict:read
DictController.java refreshCache缺少@RequirePermission@Log 新增 dict:update + 操作日志
RolePermissionMapper.xml 自定义batchInsert未包含id列,雪花ID不生效 改为实体insert方式,利用@TableId自动生成ID
haha-admin, haha-miniapp application.yml 全局缺少db-config.id-type兜底配置 新增 db-config.id-type: ASSIGN_ID
MarketingActivityController.java getOngoingActivities缺少@RequirePermission 新增 marketing:activity:read
TimedDiscountController.java getEnabledActivities缺少@RequirePermission 新增 timed-discount:read
CouponController.java getAvailableTemplates缺少@RequirePermission 新增 marketing:coupon:read
ShopController.java getEnabledShops缺少@RequirePermission 新增 shop:read