135 lines
3.9 KiB
Markdown
135 lines
3.9 KiB
Markdown
# 6.3 菜单管理
|
|
|
|
:::tip 概述
|
|
菜单管理负责维护系统的菜单树和权限节点,是 RBAC 权限体系的基础数据。
|
|
:::
|
|
|
|
## 模块特点
|
|
|
|
| 特性 | 说明 |
|
|
|------|------|
|
|
| 基类 | BaseLogic(系统共享,不隔离) |
|
|
| 树形结构 | treeParentField='parent_id',支持树形列表 |
|
|
| 菜单类型 | type: 0=目录/页面(可导航) 1=权限按钮(仅权限校验,不显示在菜单树) |
|
|
|
|
## API 接口
|
|
|
|
| 方法 | 路径 | 权限码 | 说明 |
|
|
|------|------|--------|------|
|
|
| GET | `/api/menu/list` | sys:menu:page | 树形列表 |
|
|
| GET | `/api/menu/detail/:id` | sys:menu:detail | 详情 |
|
|
| POST | `/api/menu/add` | sys:menu:add | 新增 |
|
|
| PUT | `/api/menu/update` | sys:menu:update | 修改 |
|
|
| DELETE | `/api/menu/delete/:id` | sys:menu:delete | 删除 |
|
|
|
|
## 菜单数据结构
|
|
|
|
```json
|
|
{
|
|
"id": 100,
|
|
"parentId": 0,
|
|
"name": "系统管理",
|
|
"type": 0,
|
|
"path": "/system",
|
|
"icon": "SettingOutlined",
|
|
"sort": 10,
|
|
"permission": "",
|
|
"component": "",
|
|
"target": 0,
|
|
"hide": false,
|
|
"children": [
|
|
{
|
|
"id": 101,
|
|
"parentId": 100,
|
|
"name": "用户管理",
|
|
"type": 1,
|
|
"path": "/user",
|
|
"component": "system/user/index",
|
|
"permission": "sys:user:page",
|
|
"children": [
|
|
{
|
|
"id": 102,
|
|
"parentId": 101,
|
|
"name": "添加用户",
|
|
"type": 2,
|
|
"permission": "sys:user:add"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## 字段说明
|
|
|
|
| 字段 | 说明 |
|
|
|------|------|
|
|
| `type` | 0=菜单/目录(可导航) 1=权限节点 |
|
|
| `path` | 路由路径 |
|
|
| `component` | 前端组件路径(type=1 时必填) |
|
|
| `permission` | 权限标识(type=1,2 时填写) |
|
|
| `target` | 打开方式:0=组件 1=内链 2=外链 |
|
|
| `hide` | 是否隐藏 |
|
|
|
|
## 核心代码
|
|
|
|
### Controller
|
|
|
|
```php
|
|
// app/controller/MenuController.php
|
|
|
|
class MenuController extends BaseController
|
|
{
|
|
protected MenuLogic $logic;
|
|
|
|
protected function initialize(): void
|
|
{
|
|
$this->logic = new MenuLogic();
|
|
}
|
|
|
|
// 树形列表(支持 status 参数过滤)
|
|
#[Log('菜单管理-查询树形列表', Log::TYPE_QUERY)]
|
|
#[Permission('sys:menu:page', '菜单列表')]
|
|
public function list(): Json
|
|
{
|
|
$where = [];
|
|
$status = $this->getParam('status');
|
|
if ($status !== null && $status !== '') {
|
|
$where['status'] = $status;
|
|
}
|
|
return parent::_list($this->logic, $where);
|
|
}
|
|
|
|
#[Log('菜单管理-新增记录', Log::TYPE_ADD, '新增菜单:{name}')]
|
|
#[Permission('sys:menu:add', '添加菜单')]
|
|
public function add(): Json
|
|
{
|
|
return parent::_add($this->logic, $this->getJsonBody());
|
|
}
|
|
|
|
#[Log('菜单管理-修改记录', Log::TYPE_UPDATE, '修改菜单ID:{id}')]
|
|
#[Permission('sys:menu:update', '修改菜单')]
|
|
public function update(): Json
|
|
{
|
|
$data = $this->getJsonBody();
|
|
$id = $data['id'] ?? 0;
|
|
if (empty($id)) return $this->fail('缺少id参数');
|
|
return parent::_edit($this->logic, $id, $data);
|
|
}
|
|
|
|
#[Log('菜单管理-删除记录', Log::TYPE_DELETE, '删除菜单ID:{id}')]
|
|
#[Permission('sys:menu:delete', '删除菜单')]
|
|
public function delete(int $id): Json
|
|
{
|
|
return parent::_remove($this->logic, $id);
|
|
}
|
|
}
|
|
```
|
|
|
|
:::tip 菜单类型
|
|
菜单使用 `_list()` 而非 `_index()`,返回全量树形数据。`type` 字段区分:0=目录、1=菜单、2=按钮。前端只渲染 type=0 和 type=1 的节点。
|
|
:::
|
|
|
|
:::warning 删除前校验
|
|
删除菜单时,`MenuLogic::beforeDelete` 会检查是否存在子菜单(`think_menu` 中 `parent_id` 等于当前 ID 且未删除的记录),如有子菜单则抛出异常阻止删除。需先删除子菜单再删除父菜单。
|
|
::: |