This project adopts the RBAC (Role-Based Access Control) permission model, which includes three dimensions: menu permissions, button permissions, and data permissions.
Core Principles
Important: Each time a new feature module is created,you must simultaneously create the corresponding menu permission migration SQL file; otherwise, the feature will not work properly.
I. Permission System Architecture
┌─────────────────────────────────────────────────────────────┐
│ 权限体系架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户 (sys_user) │
│ │ │
│ └── 拥有多个 ──→ 角色 (sys_role) │
│ │ │
│ ├── 拥有多个 ──→ 菜单权限 (sys_menu) │
│ │ ├─ 目录 (type=0) │
│ │ ├─ 菜单 (type=1) │
│ │ └─ 按钮 (type=2) │
│ │ │
│ └── 数据权限 (data_scope) │
│ ├─ 全部数据 (1) │
│ ├─ 本部门 (2) │
│ ├─ 本部门及下级 (3) │
│ ├─ 仅本人 (4) │
│ └─ 自定义部门 (5) │
│ │
└─────────────────────────────────────────────────────────────┘
II. Database Table Structure
2.1 Menu Table (sys_menu)
| Field | Type | Description |
|---|---|---|
| id | bigint | Primary Key |
| parent_id | bigint | Parent Menu ID (0=Top Level) |
| menu_name | varchar(50) | Menu Name |
| menu_type | tinyint | Type: 0=Directory, 1=Menu, 2=Button |
| path | varchar(200) | Route Path |
| component | varchar(255) | Component Path |
| permission | varchar(100) | Permission Identifier |
| icon | varchar(100) | Icon |
| sort | int | Sort Order |
| visible | tinyint | Whether to Display: 0=Hidden, 1=Visible |
| status | tinyint | Status: 0=Disabled, 1=Enabled |
2.2 Role Table (sys_role)
| Field | Type | Description |
|---|---|---|
| id | bigint | Primary Key |
| role_name | varchar(30) | Role Name |
| role_code | varchar(100) | Role Code |
| data_scope | tinyint | Data Permission Scope (1-5) |
| sort | int | Sort Order |
| status | tinyint | Status |
2.3 Association Tables
sys_user_role: User-Role Associationsys_role_menu: Role-Menu Associationsys_role_dept: Role-Department Association (Custom Data Permissions)
III. Permission Identifier Naming Convention
3.1 Format
{模块}:{实体}:{操作}
3.2 Standard Operations
| Operation | Permission Identifier | Description |
|---|---|---|
| List | xxx:entity:list |
View List |
| Details | xxx:entity:detail |
View Details |
| Create | xxx:entity:add |
Create Data |
| Edit | xxx:entity:edit |
Edit Data |
| Delete | xxx:entity:delete |
Delete Data |
| Export | xxx:entity:export |
Export Data |
| Import | xxx:entity:import |
Import Data |
3.3 Examples
# 系统管理模块
sys:user:list # 用户列表
sys:user:add # 新增用户
sys:role:assign # 分配角色权限
# 业务模块示例
emergency:event:list # 应急事件列表
emergency:event:handle # 处理事件
emergency:plan:approve # 审批预案
IV. Data Permission Types
| Type | Value | Description | Implementation Method |
|---|---|---|---|
| All Data | 1 | No Restrictions | Do not add filter conditions |
| Own Department | 2 | Only view own department | WHERE dept_id = 用户部门ID |
| Own Department and Subordinates | 3 | Own department tree | WHERE dept_id IN (部门及子部门ID) |
| Only Self | 4 | Only view self-created | WHERE create_by = 用户ID |
| Custom | 5 | Specified departments | WHERE dept_id IN (角色配置的部门) |
V. CX Command Integration Specification
5.1 Mandatory Requirements
When executing /cx:do or /cx:plan to create a new feature module,you must simultaneously:
- Create a Flyway migration SQL file
- Include menu data insertion statements
- Contains statements for assigning menu permissions to the administrator role
5.2 Migration File Naming
V{版本号}__{描述}.sql
示例:
V4__add_emergency_module_menu.sql
V5__add_monitor_module_menu.sql
5.3 Migration SQL Template
-- 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;
VI. Complete Example: Adding an Emergency Event Module
6.1 Migration File: V4__add_emergency_event_menu.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 Backend Controller Permission Annotations
@RestController
@RequestMapping("/api/emergency/event")
@RequiredArgsConstructor
@Tag(name = "应急事件管理")
public class EmergencyEventController {
private final EmergencyEventService eventService;
@GetMapping
@SaCheckPermission("emergency:event:list")
@Operation(summary = "事件列表")
public ApiResponse<Page<EventVO>> list(EventQueryDTO query) {
return ApiResponse.success(eventService.findPage(query));
}
@PostMapping
@SaCheckPermission("emergency:event:add")
@Operation(summary = "新增事件")
public ApiResponse<EventVO> create(@Valid @RequestBody EventCreateDTO dto) {
return ApiResponse.success(eventService.create(dto));
}
@PutMapping("/{id}")
@SaCheckPermission("emergency:event:edit")
@Operation(summary = "编辑事件")
public ApiResponse<EventVO> update(@PathVariable Long id, @Valid @RequestBody EventUpdateDTO dto) {
return ApiResponse.success(eventService.update(id, dto));
}
@DeleteMapping("/{id}")
@SaCheckPermission("emergency:event:delete")
@Operation(summary = "删除事件")
public ApiResponse<Void> delete(@PathVariable Long id) {
eventService.delete(id);
return ApiResponse.success();
}
@PutMapping("/{id}/handle")
@SaCheckPermission("emergency:event:handle")
@Operation(summary = "处理事件")
public ApiResponse<EventVO> handle(@PathVariable Long id, @Valid @RequestBody EventHandleDTO dto) {
return ApiResponse.success(eventService.handle(id, dto));
}
}
6.3 Frontend Route Configuration (dynamically returned by the backend)
The frontend does not need to manually configure routes; menu data is provided by the backend /api/auth/routes interface and returned dynamically.
VII. Using Data Permissions
7.1 Adding Data Permission Annotations at the Service Layer
@Service
@RequiredArgsConstructor
public class EmergencyEventServiceImpl implements EmergencyEventService {
private final EmergencyEventRepository eventRepository;
private final DataScopeHelper dataScopeHelper;
@Override
@DataScope(deptAlias = "", userAlias = "")
public Page<EventVO> findPage(EventQueryDTO query) {
Specification<EmergencyEvent> spec = (root, criteriaQuery, cb) -> {
List<Predicate> predicates = new ArrayList<>();
// 业务查询条件...
// 数据权限过滤 (必须添加)
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);
}
}
VIII. Common Icon Reference
| Icon | Icon Name | Applicable Scenario |
|---|---|---|
| ⚙️ | ant-design:setting-outlined | System Settings |
| 👤 | ant-design:user-outlined | User Management |
| 👥 | ant-design:team-outlined | Role/Team |
| 📋 | ant-design:menu-outlined | Menu Management |
| 🏢 | ant-design:apartment-outlined | Department/Organization |
| ⚠️ | ant-design:alert-outlined | Alert/Emergency |
| 📄 | ant-design:file-outlined | File/Document |
| 📊 | ant-design:bar-chart-outlined | Statistics/Report |
| 🔔 | ant-design:bell-outlined | Notification/Message |
| 📁 | ant-design:folder-outlined | Directory/Category |
| 🔐 | ant-design:safety-outlined | Security/Permission |
| 📝 | ant-design:form-outlined | Form |
IX. Checklist
When creating a new feature module, please confirm the following items:
- Create a Flyway migration SQL file (V{N}_add{module}_menu.sql)
- Menu ID uses
@max_menu_id + NAvoid conflicts - Include the three-level structure of directory, menu, and button
- Permission identifier conforms to the
{module}:{entity}:{action}specification - Assign new menu permissions to the super administrator role
- Add to the Controller method
@SaCheckPermissionannotation - Add to queries that require data permissions
DataScopeHelperfiltering - The frontend page component path matches the menu component field
Project: Emergency Management System Creation Time: 2026-01-13 Update Time: 2026-01-13