121 lines
4.1 KiB
Markdown
121 lines
4.1 KiB
Markdown
:::tip 菜单管理
|
||
菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。支持目录/菜单(type=0)和权限按钮节点(type=1)两种类型,通过树形结构组织。
|
||
:::
|
||
|
||
## 菜单类型
|
||
|
||
| type | 名称 | 说明 | 用途 |
|
||
|------|------|------|------|
|
||
| `0` | 目录/菜单 | 页面路由 | 前端侧边栏分组 + 路由生成 |
|
||
| `1` | 节点 | 权限按钮 | 控制操作权限 |
|
||
|
||
## 菜单模型
|
||
|
||
```python
|
||
# application/menu/models.py
|
||
from application.models import BaseModel
|
||
|
||
class Menu(BaseModel):
|
||
"""菜单模型类"""
|
||
class Meta:
|
||
db_table = 'django_menu'
|
||
|
||
name = models.CharField(max_length=150, verbose_name='菜单名称')
|
||
icon = models.CharField(max_length=50, null=True, blank=True, verbose_name='菜单图标')
|
||
parent_id = models.IntegerField(default=0, verbose_name='上级ID')
|
||
path = models.CharField(max_length=255, null=True, blank=True, verbose_name='菜单路径')
|
||
component = models.CharField(max_length=255, null=True, blank=True, verbose_name='菜单组件')
|
||
permission = models.CharField(max_length=150, null=True, blank=True, verbose_name='权限节点')
|
||
target = models.IntegerField(default=1, verbose_name='打开方式:0-组件 1-内链 2-外链')
|
||
type = models.IntegerField(default=0, verbose_name='菜单类型:0-菜单 1-节点')
|
||
status = models.IntegerField(default=0, verbose_name='菜单状态:0-正常 1-停用')
|
||
hide = models.IntegerField(default=1, verbose_name='是否可见:0-可见 1-不可见')
|
||
sort = models.IntegerField(default=0, verbose_name='排序')
|
||
note = models.CharField(max_length=255, null=True, blank=True, verbose_name='备注')
|
||
```
|
||
|
||
## 权限节点格式
|
||
|
||
权限节点采用 `sys:module:action` 三段式命名:
|
||
|
||
```
|
||
1 -> 查询(sys:{module}:page)
|
||
5 -> 添加(sys:{module}:add)
|
||
10 -> 修改(sys:{module}:update)
|
||
15 -> 删除(sys:{module}:delete)
|
||
20 -> 详情(sys:{module}:detail)
|
||
25 -> 设置状态(sys:{module}:status)
|
||
30 -> 批量删除(sys:{module}:batchDelete)
|
||
```
|
||
|
||
## 菜单树构建
|
||
|
||
使用 children_map 字典实现非递归树构建:
|
||
|
||
```python
|
||
# application/menu/services.py
|
||
def get_tree(data, parent_id):
|
||
"""获取树状结构(非递归,children_map 分组)"""
|
||
children_map = {}
|
||
for item in data:
|
||
pid = item["parentId"]
|
||
if pid not in children_map:
|
||
children_map[pid] = []
|
||
children_map[pid].append(item)
|
||
|
||
def build(pid):
|
||
result = []
|
||
for item in children_map.get(pid, []):
|
||
item["children"] = build(item["id"])
|
||
result.append(item)
|
||
return result
|
||
|
||
return build(parent_id)
|
||
```
|
||
|
||
## 用户权限查询
|
||
|
||
权限查询通过 ORM 关联实现:
|
||
|
||
```python
|
||
# application/menu/services.py
|
||
def get_user_permissions(user_id):
|
||
"""获取用户的权限节点列表"""
|
||
if user_id == 1:
|
||
# 超管拥有全部权限
|
||
menu_list = Menu.objects.filter(type=1, is_delete=False)
|
||
else:
|
||
# 通过 user -> role -> menu 关联查询
|
||
menu_list = Menu.objects.filter(
|
||
type=1,
|
||
is_delete=False,
|
||
status=0,
|
||
rolemenu__role__userrole__user_id=user_id,
|
||
rolemenu__role__is_delete=False,
|
||
).distinct()
|
||
|
||
return [item.permission for item in menu_list]
|
||
```
|
||
|
||
## API 接口
|
||
|
||
| 接口 | 方法 | 权限节点 | 说明 |
|
||
|------|------|---------|------|
|
||
| `/menu/list` | GET | `sys:menu:list` | 菜单列表 |
|
||
| `/menu/detail/<int:menu_id>` | GET | `sys:menu:detail` | 菜单详情 |
|
||
| `/menu/add` | POST | `sys:menu:add` | 新增菜单 |
|
||
| `/menu/update` | POST | `sys:menu:update` | 编辑菜单 |
|
||
| `/menu/delete/<int:menu_id>` | POST | `sys:menu:delete` | 删除菜单 |
|
||
|
||
## 总结
|
||
|
||
菜单管理模块具备以下特点:
|
||
|
||
```
|
||
1. 树形结构:通过 parent_id 形成多级菜单树,非递归构建
|
||
2. 权限节点:type=1 按钮节点,sys:module:action 格式
|
||
3. 缓存联动:菜单增删改后清理权限缓存
|
||
4. 环路防护:编辑时检测父级不能是自身或下级
|
||
5. 级联删除:删除菜单时一并清理权限节点和 role_menu 关联
|
||
```
|