签入版本
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
:::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 关联
|
||||
```
|
||||
Reference in New Issue
Block a user