tp/app/admin/controller/MenuController.php
2026-01-26 15:06:56 +08:00

449 lines
14 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace app\admin\controller;
use app\admin\BaseController;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Session;
use think\response\Json;
use think\db\exception\DbException;
use app\model\SystemMenu;
use app\model\AdminUser;
use app\model\AdminUserGroup;
class MenuController extends BaseController
{
/**
* 获取用户菜单接口需要传入用户ID
* @return \think\response\Json
*/
public function getMenus(int $id)
{
try {
$authHeader = $this->request->header('Authorization', '');
if (!preg_match('/Bearer\s+(.+)/i', $authHeader, $matches)) {
return json([
'code' => 401,
'msg' => '未登录,请先登录',
'data' => null
]);
}
$tokenData = $this->verifyTokenFromHeader($matches[1]);
if (!$tokenData || !isset($tokenData['user'])) {
return json([
'code' => 401,
'msg' => 'Token无效请重新登录',
'data' => null
]);
}
$userInfo = (array)$tokenData['user'];
if (!$userInfo || !isset($userInfo['id']) || $userInfo['id'] == 0) {
return json([
'code' => 401,
'msg' => '用户ID不存在请重新登录',
'data' => null
]);
}
$user = AdminUser::where('id', $id)
->where('id', $id)
->find();
if (!$user) {
return json([
'code' => 404,
'msg' => '用户不存在',
'data' => null
]);
}
// 获取用户组权限信息
$userGroup = AdminUserGroup::where('id', $user['group_id'])
->find();
// var_dump($userGroup);
if (!$userGroup) {
return json([
'code' => 404,
'msg' => '用户组不存在',
'data' => null
]);
}
// 解析权限数组
$menuIds = [];
if (!empty($userGroup['rights'])) {
$menuIds = is_array($userGroup['rights']) ? $userGroup['rights'] : json_decode($userGroup['rights'], true);
}
// var_dump($menuIds);
// 如果权限为空,返回空数组
if (empty($menuIds)) {
return json([
'code' => 200,
'msg' => 'success',
'data' => []
]);
}
// 获取有权限的菜单
$menus = SystemMenu::where('delete_time', null)
->where('status', 1)
->whereIn('id', $menuIds)
->field('id,pid,title,path,component_path,icon,sort')
->order('sort', 'asc')
->select();
// 将菜单转换为树形结构
$treeMenus = $this->buildMenuTree($menus->toArray());
return json([
'code' => 200,
'msg' => 'success',
'data' => $treeMenus
]);
} catch (DbException $e) {
return json([
'code' => 500,
'msg' => 'fail' . $e->getMessage(),
'data' => $e->getTraceAsString()
]);
}
}
/**
* 获取所有菜单接口
* @return \think\response\Json
*/
public function getAllMenus()
{
try {
// 获取所有未删除的菜单
$menus = SystemMenu::where('delete_time', null)
->order('sort', 'asc')
->select()
->toArray(); // 转换为数组
// 构建树形结构
$tree = [];
$map = [];
// 首先创建所有菜单的映射
foreach ($menus as $menu) {
$menu['children'] = []; // 初始化子菜单数组
$map[$menu['id']] = $menu;
}
// 构建树形结构
foreach ($menus as $menu) {
$pid = $menu['pid'];
if ($pid == 0) {
// 顶级菜单
$tree[] = &$map[$menu['id']];
} else {
// 子菜单
if (isset($map[$pid])) {
$map[$pid]['children'][] = &$map[$menu['id']];
}
}
}
// 递归函数:对所有层级的菜单按 sort 降序排序
$sortChildren = function (&$items) use (&$sortChildren) {
// 再递归处理每个节点的子菜单
foreach ($items as &$item) {
if (!empty($item['children'])) {
$sortChildren($item['children']);
}
}
};
// 对整个树形结构进行排序(包括顶级菜单)
$sortChildren($tree);
return json([
'code' => 200,
'msg' => 'success',
'data' => $tree
]);
} catch (DbException $e) {
return json([
'code' => 500,
'msg' => 'fail' . $e->getMessage(),
'data' => $e->getTraceAsString()
]);
}
}
/**
* 更新菜单状态
* @param int $id 菜单ID
* @return \think\response\Json
*/
public function updateMenuStatus(int $id)
{
try {
// 获取请求参数
$data = $this->request->param();
// 验证参数
$this->validate($data, [
'status|菜单状态' => 'require|in:0,1'
]);
// 更新菜单状态
$result = SystemMenu::where('id', $id)
->where('delete_time', null)
->update([
'status' => $data['status'],
'update_time' => time()
]);
if ($result === false) {
return json([
'code' => 500,
'msg' => 'fail'
]);
}
// 记录操作日志
$this->logSuccess('菜单管理', '更新菜单状态', ['id' => $id]);
return json([
'code' => 200,
'msg' => 'success'
]);
} catch (ValidateException $e) {
// 记录失败日志
$this->logFail('菜单管理', '更新菜单状态', $e->getMessage());
return json([
'code' => 400,
'msg' => $e->getError()
]);
} catch (DbException $e) {
// 记录失败日志
$this->logFail('菜单管理', '更新菜单状态', $e->getMessage());
return json([
'code' => 500,
'msg' => 'fail' . $e->getMessage()
]);
}
}
/**
* 创建新菜单
* @return \think\response\Json
*/
public function createMenu()
{
try {
// 获取请求参数
$data = $this->request->param();
// 验证参数
$this->validate($data, [
'title|菜单名称' => 'require|max:50',
'type|菜单类型' => 'require|in:1,2,3',
'status|菜单状态' => 'require|in:0,1',
'sort|排序号' => 'integer',
'path|路由路径' => 'max:200',
'icon|菜单图标' => 'max:100',
'permission|权限标识' => 'max:100',
'remark|备注' => 'max:500'
]);
// 准备菜单数据
$menuData = [
'pid' => $data['pid'] ?? 0,
'title' => $data['title'],
'type' => $data['type'],
'status' => $data['status'] ?? 1,
'sort' => $data['sort'] ?? 0,
'path' => $data['path'] ?? '',
'component_path' => $data['component_path'] ?? '',
'icon' => $data['icon'] ?? '',
'permission' => $data['permission'] ?? '',
'remark' => $data['remark'] ?? '',
'creater' => Session::get('name') ?? 'system',
'create_time' => date('Y-m-d H:i:s')
];
// 创建菜单
$result = SystemMenu::insertGetId($menuData);
if ($result) {
// 记录操作日志
$this->logSuccess('菜单管理', '创建菜单', ['id' => $result]);
return json([
'code' => 200,
'msg' => '创建成功',
'data' => ['id' => $result]
]);
} else {
throw new \Exception('创建菜单失败');
}
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('菜单管理', '创建菜单', $e->getMessage());
return json([
'code' => 500,
'msg' => '创建失败:' . $e->getMessage(),
'data' => []
]);
}
}
/**
* 更新菜单信息
* @param int $id 菜单ID
* @return \think\response\Json
*/
public function updateMenu(int $id)
{
try {
// 获取请求参数
$data = $this->request->param();
// 验证参数
$this->validate($data, [
'title|菜单名称' => 'require|max:50',
'pid|上级菜单ID' => 'integer',
'type|菜单类型' => 'require|in:1,2,3',
'status|菜单状态' => 'require|in:0,1',
'sort|排序号' => 'integer',
'path|路由路径' => 'max:200',
'icon|菜单图标' => 'max:100',
'permission|权限标识' => 'max:100',
'remark|备注' => 'max:500'
]);
// 准备更新数据
$updateData = [
'title' => $data['title'],
'pid' => $data['pid'] ?? null,
'type' => $data['type'],
'path' => $data['path'] ?? null,
'component_path' => $data['component_path'] ?? null,
'icon' => $data['icon'] ?? null,
'sort' => $data['sort'] ?? 0,
'status' => $data['status'],
'permission' => $data['permission'] ?? null,
'remark' => $data['remark'] ?? null,
'update_time' => date('Y-m-d H:i:s')
];
// 执行更新
SystemMenu::where('id', $id)->update($updateData);
// 获取更新后的菜单信息
$menu = SystemMenu::where('id', $id)->find();
// 记录操作日志
$this->logSuccess('菜单管理', '更新菜单信息', ['id' => $id]);
return json([
'code' => 200,
'msg' => 'success',
'data' => $menu ? $menu->toArray() : []
]);
} catch (ValidateException $e) {
// 记录失败日志
$this->logFail('菜单管理', '更新菜单信息', $e->getMessage());
return json([
'code' => 400,
'msg' => $e->getError()
]);
} catch (DbException $e) {
// 记录失败日志
$this->logFail('菜单管理', '更新菜单信息', $e->getMessage());
return json([
'code' => 500,
'msg' => 'fail' . $e->getMessage()
]);
}
}
/**
* 删除菜单
* @param int $id 菜单ID
* @return \think\response\Json
*/
public function deleteMenu(int $id)
{
try {
// 检查是否有子菜单
$hasChildren = SystemMenu::where('pid', $id)
->where('delete_time', null)
->count() > 0;
if ($hasChildren) {
return json([
'code' => 400,
'msg' => '该菜单下有子菜单,无法删除'
]);
}
// 逻辑删除菜单
$result = SystemMenu::where('id', $id)
->where('delete_time', null)
->update([
'delete_time' => time(),
'update_time' => time()
]);
if ($result === false) {
return json([
'code' => 500,
'msg' => 'fail'
]);
}
// 记录操作日志
$this->logSuccess('菜单管理', '删除菜单', ['id' => $id]);
return json([
'code' => 200,
'msg' => 'success'
]);
} catch (DbException $e) {
// 记录失败日志
$this->logFail('菜单管理', '删除菜单', $e->getMessage());
return json([
'code' => 500,
'msg' => 'fail' . $e->getMessage()
]);
}
}
/**
* 构建菜单树形结构
* @param array $menus 菜单列表
* @param int $pid 父菜单ID
* @return array
*/
private function buildMenuTree(array $menus, int $pid = 0): array
{
$tree = [];
foreach ($menus as $menu) {
// 将null的pid视为0处理
$menuPid = is_null($menu['pid']) ? 0 : $menu['pid'];
if ($menuPid == $pid) {
$children = $this->buildMenuTree($menus, $menu['id']);
if (!empty($children)) {
$menu['children'] = $children;
}
$tree[] = $menu;
}
}
return $tree;
}
}