permission-system
🎯Skillfrom m19803261706/springboot-vben-admin
Enforces RBAC permission management with mandatory menu permission SQL migration for new system modules and features.
Installation
npx skills add https://github.com/m19803261706/springboot-vben-admin --skill permission-systemSkill Details
应急管理系统权限体系开发规范。当创建新功能模块、配置菜单权限、设置数据权限时必须使用此 Skill。CX 命令执行时强制要求生成菜单权限迁移 SQL。
Overview
# 权限系统开发规范
本项目采用 RBAC (基于角色的访问控制) 权限模型,包含菜单权限、按钮权限和数据权限三个维度。
核心原则
> 重要: 每次创建新功能模块时,必须 同时创建对应的菜单权限迁移 SQL 文件,否则功能将无法正常使用。
一、权限体系架构
```
┌─────────────────────────────────────────────────────────────┐
│ 权限体系架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户 (sys_user) │
│ │ │
│ └── 拥有多个 ──→ 角色 (sys_role) │
│ │ │
│ ├── 拥有多个 ──→ 菜单权限 (sys_menu) │
│ │ ├─ 目录 (type=0) │
│ │ ├─ 菜单 (type=1) │
│ │ └─ 按钮 (type=2) │
│ │ │
│ └── 数据权限 (data_scope) │
│ ├─ 全部数据 (1) │
│ ├─ 本部门 (2) │
│ ├─ 本部门及下级 (3) │
│ ├─ 仅本人 (4) │
│ └─ 自定义部门 (5) │
│ │
└─────────────────────────────────────────────────────────────┘
```
二、数据库表结构
2.1 菜单表 (sys_menu)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | bigint | 主键 |
| parent_id | bigint | 父菜单ID (0=顶级) |
| menu_name | varchar(50) | 菜单名称 |
| menu_type | tinyint | 类型: 0=目录, 1=菜单, 2=按钮 |
| path | varchar(200) | 路由路径 |
| component | varchar(255) | 组件路径 |
| permission | varchar(100) | 权限标识 |
| icon | varchar(100) | 图标 |
| sort | int | 排序 |
| visible | tinyint | 是否显示: 0=隐藏, 1=显示 |
| status | tinyint | 状态: 0=禁用, 1=启用 |
2.2 角色表 (sys_role)
| 字段 | 类型 | 说明 |
|------|------|------|
| id | bigint | 主键 |
| role_name | varchar(30) | 角色名称 |
| role_code | varchar(100) | 角色编码 |
| data_scope | tinyint | 数据权限范围 (1-5) |
| sort | int | 排序 |
| status | tinyint | 状态 |
2.3 关联表
sys_user_role: 用户-角色关联sys_role_menu: 角色-菜单关联sys_role_dept: 角色-部门关联 (自定义数据权限)
三、权限标识命名规范
3.1 格式
```
{模块}:{实体}:{操作}
```
3.2 标准操作
| 操作 | 权限标识 | 说明 |
|------|----------|------|
| 列表 | xxx:entity:list | 查看列表 |
| 详情 | xxx:entity:detail | 查看详情 |
| 新增 | xxx:entity:add | 新增数据 |
| 编辑 | xxx:entity:edit | 编辑数据 |
| 删除 | xxx:entity:delete | 删除数据 |
| 导出 | xxx:entity:export | 导出数据 |
| 导入 | xxx:entity:import | 导入数据 |
3.3 示例
```
# 系统管理模块
sys:user:list # 用户列表
sys:user:add # 新增用户
sys:role:assign # 分配角色权限
# 业务模块示例
emergency:event:list # 应急事件列表
emergency:event:handle # 处理事件
emergency:plan:approve # 审批预案
```
四、数据权限类型
| 类型 | 值 | 说明 | 实现方式 |
|------|---|------|----------|
| 全部数据 | 1 | 无限制 | 不添加过滤条件 |
| 本部门 | 2 | 只看本部门 | WHERE dept_id = 用户部门ID |
| 本部门及下级 | 3 | 本部门树 | WHERE dept_id IN (部门及子部门ID) |
| 仅本人 | 4 | 只看自己创建的 | WHERE create_by = 用户ID |
| 自定义 | 5 | 指定部门 | WHERE dept_id IN (角色配置的部门) |
五、CX 命令集成规范
5.1 强制要求
当执行 /cx:do 或 /cx:plan 创建新功能模块时,必须 同时:
- 创建 Flyway 迁移 SQL 文件
- 包含菜单数据插入语句
- 包含管理员角色菜单权限分配语句
5.2 迁移文件命名
```
V{版本号}__{描述}.sql
示例:
V4__add_emergency_module_menu.sql
V5__add_monitor_module_menu.sql
```
5.3 迁移 SQL 模板
```sql
-- V{N}__add_{module}_menu.sql
-- 作者: CX
-- 日期: {日期}
-- 描述: 添加{模块名}模块菜单和权限
-- =============================================
-- 获取当前最大菜单ID
-- =============================================
SET @max_menu_id = (SELECT COALESCE(MAX(id), 100) FROM sys_menu);
-- =============================================
-- 添加{模块名}目录
-- =============================================
INSERT INTO sys_menu (id, parent_id, menu_name, menu_type, path, component, permission, icon, sort, visible, status) VALUES
(@max_menu_id + 1, 0, '{模块中文名}', 0, '/{module}', NULL, NULL, '{icon}', {sort}, 1, 1);
-- =============================================
-- 添加{功能名}菜单
-- =============================================
INSERT INTO sys_menu (id, parent_id, menu_name, menu_type, path, component, permission, icon, sort, visible, status) VALUES
(@max_menu_id + 2, @max_menu_id + 1, '{功能中文名}', 1, '/{module}/{entity}', '/{module}/{entity}/index', '{module}:{entity}:list', '{icon}', 1, 1, 1),
(@max_menu_id + 3, @max_menu_id + 2, '{功能}新增', 2, NULL, NULL, '{module}:{entity}:add', NULL, 1, 1, 1),
(@max_menu_id + 4, @max_menu_id + 2, '{功能}编辑', 2, NULL, NULL, '{module}:{entity}:edit', NULL, 2, 1, 1),
(@max_menu_id + 5, @max_menu_id + 2, '{功能}删除', 2, NULL, NULL, '{module}:{entity}:delete', NULL, 3, 1, 1);
-- =============================================
-- 为超级管理员分配新菜单权限
-- =============================================
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT 1, id FROM sys_menu WHERE id > @max_menu_id;
```
六、完整示例:添加应急事件模块
6.1 迁移文件: V4__add_emergency_event_menu.sql
```sql
-- V4__add_emergency_event_menu.sql
-- 作者: CX
-- 日期: 2026-01-13
-- 描述: 添加应急事件管理模块菜单和权限
-- =============================================
-- 获取当前最大菜单ID (避免ID冲突)
-- =============================================
SET @max_menu_id = (SELECT COALESCE(MAX(id), 100) FROM sys_menu);
-- =============================================
-- 添加应急管理目录
-- =============================================
INSERT INTO sys_menu (id, parent_id, menu_name, menu_type, path, component, permission, icon, sort, visible, status) VALUES
(@max_menu_id + 1, 0, '应急管理', 0, '/emergency', NULL, NULL, 'ant-design:alert-outlined', 10, 1, 1);
-- =============================================
-- 添加事件管理菜单及按钮
-- =============================================
INSERT INTO sys_menu (id, parent_id, menu_name, menu_type, path, component, permission, icon, sort, visible, status) VALUES
-- 事件管理菜单
(@max_menu_id + 2, @max_menu_id + 1, '事件管理', 1, '/emergency/event', '/emergency/event/index', 'emergency:event:list', 'ant-design:file-exclamation-outlined', 1, 1, 1),
-- 事件管理按钮
(@max_menu_id + 3, @max_menu_id + 2, '事件新增', 2, NULL, NULL, 'emergency:event:add', NULL, 1, 1, 1),
(@max_menu_id + 4, @max_menu_id + 2, '事件编辑', 2, NULL, NULL, 'emergency:event:edit', NULL, 2, 1, 1),
(@max_menu_id + 5, @max_menu_id + 2, '事件删除', 2, NULL, NULL, 'emergency:event:delete', NULL, 3, 1, 1),
(@max_menu_id + 6, @max_menu_id + 2, '事件处理', 2, NULL, NULL, 'emergency:event:handle', NULL, 4, 1, 1),
(@max_menu_id + 7, @max_menu_id + 2, '事件导出', 2, NULL, NULL, 'emergency:event:export', NULL, 5, 1, 1);
-- =============================================
-- 添加预案管理菜单及按钮
-- =============================================
INSERT INTO sys_menu (id, parent_id, menu_name, menu_type, path, component, permission, icon, sort, visible, status) VALUES
-- 预案管理菜单
(@max_menu_id + 8, @max_menu_id + 1, '预案管理', 1, '/emergency/plan', '/emergency/plan/index', 'emergency:plan:list', 'ant-design:solution-outlined', 2, 1, 1),
-- 预案管理按钮
(@max_menu_id + 9, @max_menu_id + 8, '预案新增', 2, NULL, NULL, 'emergency:plan:add', NULL, 1, 1, 1),
(@max_menu_id + 10, @max_menu_id + 8, '预案编辑', 2, NULL, NULL, 'emergency:plan:edit', NULL, 2, 1, 1),
(@max_menu_id + 11, @max_menu_id + 8, '预案删除', 2, NULL, NULL, 'emergency:plan:delete', NULL, 3, 1, 1),
(@max_menu_id + 12, @max_menu_id + 8, '预案审批', 2, NULL, NULL, 'emergency:plan:approve', NULL, 4, 1, 1);
-- =============================================
-- 为超级管理员角色分配新菜单权限
-- =============================================
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT 1, id FROM sys_menu WHERE id > @max_menu_id;
```
6.2 后端 Controller 权限注解
```java
@RestController
@RequestMapping("/api/emergency/event")
@RequiredArgsConstructor
@Tag(name = "应急事件管理")
public class EmergencyEventController {
private final EmergencyEventService eventService;
@GetMapping
@SaCheckPermission("emergency:event:list")
@Operation(summary = "事件列表")
public ApiResponse
return ApiResponse.success(eventService.findPage(query));
}
@PostMapping
@SaCheckPermission("emergency:event:add")
@Operation(summary = "新增事件")
public ApiResponse
return ApiResponse.success(eventService.create(dto));
}
@PutMapping("/{id}")
@SaCheckPermission("emergency:event:edit")
@Operation(summary = "编辑事件")
public ApiResponse
return ApiResponse.success(eventService.update(id, dto));
}
@DeleteMapping("/{id}")
@SaCheckPermission("emergency:event:delete")
@Operation(summary = "删除事件")
public ApiResponse
eventService.delete(id);
return ApiResponse.success();
}
@PutMapping("/{id}/handle")
@SaCheckPermission("emergency:event:handle")
@Operation(summary = "处理事件")
public ApiResponse
return ApiResponse.success(eventService.handle(id, dto));
}
}
```
6.3 前端路由配置 (由后端动态返回)
前端无需手动配置路由,菜单数据由后端 /api/auth/routes 接口动态返回。
七、数据权限使用
7.1 Service 层添加数据权限注解
```java
@Service
@RequiredArgsConstructor
public class EmergencyEventServiceImpl implements EmergencyEventService {
private final EmergencyEventRepository eventRepository;
private final DataScopeHelper dataScopeHelper;
@Override
@DataScope(deptAlias = "", userAlias = "")
public Page
Specification
List
// 业务查询条件...
// 数据权限过滤 (必须添加)
Predicate dataScopePredicate = dataScopeHelper.buildDataScopePredicate(
root, cb, "deptId", "createBy");
if (dataScopePredicate != null) {
predicates.add(dataScopePredicate);
}
return cb.and(predicates.toArray(new Predicate[0]));
};
return eventRepository.findAll(spec, pageRequest).map(this::convertToVO);
}
}
```
八、常用图标参考
| 图标 | 图标名称 | 适用场景 |
|------|----------|----------|
| ⚙️ | ant-design:setting-outlined | 系统设置 |
| 👤 | ant-design:user-outlined | 用户管理 |
| 👥 | ant-design:team-outlined | 角色/团队 |
| 📋 | ant-design:menu-outlined | 菜单管理 |
| 🏢 | ant-design:apartment-outlined | 部门/组织 |
| ⚠️ | ant-design:alert-outlined | 告警/应急 |
| 📄 | ant-design:file-outlined | 文件/文档 |
| 📊 | ant-design:bar-chart-outlined | 统计/报表 |
| 🔔 | ant-design:bell-outlined | 通知/消息 |
| 📁 | ant-design:folder-outlined | 目录/分类 |
| 🔐 | ant-design:safety-outlined | 安全/权限 |
| 📝 | ant-design:form-outlined | 表单 |
九、检查清单
创建新功能模块时,请确认以下事项:
- [ ] 创建 Flyway 迁移 SQL 文件 (V{N}__add_{module}_menu.sql)
- [ ] 菜单 ID 使用
@max_menu_id + N避免冲突 - [ ] 包含目录、菜单、按钮三级结构
- [ ] 权限标识符合
{module}:{entity}:{action}规范 - [ ] 为超级管理员角色分配新菜单权限
- [ ] Controller 方法添加
@SaCheckPermission注解 - [ ] 需要数据权限的查询添加
DataScopeHelper过滤 - [ ] 前端页面组件路径与菜单 component 字段一致
---
> 项目: 应急管理系统
> 创建时间: 2026-01-13
> 更新时间: 2026-01-13
More from this repository3
vben-admin skill from m19803261706/springboot-vben-admin
sa-token skill from m19803261706/springboot-vben-admin
Generates standardized Spring Boot 4 backend development specifications and templates for creating Controllers, Services, Entities, Repositories, and APIs.