adminId = $adminId; return $this; } /** * 获取首页信息. * @return array|\think\Model|null * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getHomeInfo() { $data = Db::name('system_menu') ->field('title,icon,href') ->where('delete_time', 0) ->where('pid', MenuConstant::HOME_PID) ->find(); !empty($data) && $data['href'] = __url($data['href']); $data['mb_title'] = '菜单'; $data['mb_href'] = (string)url('admin/Index/mobile'); return $data; } /** * 获取后台菜单树信息. * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getMenuTree() { /** @var AuthService $authService */ $authServer = app(AuthService::class, ['adminId' => $this->adminId]); return $this->buildMenuChild(0, $this->getMenuData(), $authServer); } private function buildMenuChild($pid, $menuList, AuthService $authServer) { $treeList = []; foreach ($menuList as &$v) { $check = false; if (!empty($v['auth_node'])) { $check = $authServer->checkNode($v['auth_node']); } elseif (!empty($v['href'])) { $check = $authServer->checkNode($v['href']); } else { $check = true; } !empty($v['href']) && $v['href'] = __url($v['href']); if ($pid == $v['pid'] && $check) { $node = $v; $child = $this->buildMenuChild($v['id'], $menuList, $authServer); if (!empty($child)) { $node['child'] = $child; } if (!empty($v['href']) || !empty($child)) { $treeList[] = $node; } } } return $treeList; } /** * 获取所有菜单数据. * @return \think\Collection * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ protected function getMenuData() { $menuData = Db::name('system_menu') ->field('id,pid,title,icon,href,target,auth_node') ->where('delete_time', 0) ->where([ ['status', '=', '1'], ['pid', '<>', MenuConstant::HOME_PID], ]) ->order([ 'sort' => 'desc', 'id' => 'asc', ]) ->select(); return $menuData; } /** * 创建菜单 * * @param array $data 菜单数据 * @return int 返回新创建的菜单ID * @throws \Exception */ public function create(array $data): int { $menu = Db::name('system_menu'); // 准备数据 $insertData = [ 'pid' => $data['parent_id'] ?? 0, 'title' => $data['title'] ?? '', 'icon' => $data['icon'] ?? '', 'href' => $data['path'] ?? '', 'auth_node' => $data['node'] ?? '', 'sort' => $data['sort'] ?? 100, 'status' => 1, 'target' => '_self', 'remark' => $data['remark'] ?? '', 'create_time' => time(), 'update_time' => time(), 'delete_time' => 0, ]; // 验证必填字段 if (empty($insertData['title'])) { throw new \Exception('菜单标题不能为空'); } // 验证父菜单是否存在 if ($insertData['pid'] > 0) { $parentMenu = Db::name('system_menu') ->where('id', $insertData['pid']) ->where('delete_time', 0) ->find(); if (empty($parentMenu)) { throw new \Exception("父菜单ID {$insertData['pid']} 不存在"); } } // 插入数据 $menuId = $menu->insertGetId($insertData); if (!$menuId) { throw new \Exception('菜单创建失败'); } return (int)$menuId; } /** * 更新菜单 * * @param int $menuId 菜单ID * @param array $data 更新数据 * @return bool 是否更新成功 * @throws \Exception */ public function update(int $menuId, array $data): bool { // 验证菜单是否存在 $menu = Db::name('system_menu') ->where('id', $menuId) ->where('delete_time', 0) ->find(); if (empty($menu)) { throw new \Exception("菜单ID {$menuId} 不存在"); } // 准备更新数据 $updateData = [ 'update_time' => time(), ]; if (isset($data['title'])) { $updateData['title'] = $data['title']; } if (isset($data['parent_id'])) { $updateData['pid'] = $data['parent_id']; } if (isset($data['icon'])) { $updateData['icon'] = $data['icon']; } if (isset($data['path'])) { $updateData['href'] = $data['path']; } if (isset($data['node'])) { $updateData['auth_node'] = $data['node']; } if (isset($data['sort'])) { $updateData['sort'] = $data['sort']; } if (isset($data['status'])) { $updateData['status'] = $data['status']; } if (isset($data['remark'])) { $updateData['remark'] = $data['remark']; } if (isset($data['target'])) { $updateData['target'] = $data['target']; } // 验证必填字段 if (empty($menu['title']) && empty($updateData['title'])) { throw new \Exception('菜单标题不能为空'); } // 验证父菜单是否存在(如果修改了父菜单) if (isset($updateData['pid']) && $updateData['pid'] > 0) { // 不能将自己设置为父菜单 if ($updateData['pid'] == $menuId) { throw new \Exception('不能将自己设置为父菜单'); } $parentMenu = Db::name('system_menu') ->where('id', $updateData['pid']) ->where('delete_time', 0) ->find(); if (empty($parentMenu)) { throw new \Exception("父菜单ID {$updateData['pid']} 不存在"); } } // 更新数据 $result = Db::name('system_menu') ->where('id', $menuId) ->update($updateData); return $result !== false; } /** * 删除菜单 * * @param int $menuId 菜单ID * @return bool 是否删除成功 * @throws \Exception */ public function delete(int $menuId): bool { // 验证菜单是否存在 $menu = Db::name('system_menu') ->where('id', $menuId) ->where('delete_time', 0) ->find(); if (empty($menu)) { throw new \Exception("菜单ID {$menuId} 不存在"); } // 检查是否有子菜单 $hasChildren = Db::name('system_menu') ->where('pid', $menuId) ->where('delete_time', 0) ->count(); if ($hasChildren > 0) { throw new \Exception('该菜单下存在子菜单,请先删除子菜单'); } // 软删除 $result = Db::name('system_menu') ->where('id', $menuId) ->update([ 'delete_time' => time(), 'update_time' => time(), ]); return $result !== false; } /** * 获取菜单详情 * * @param int $menuId 菜单ID * @return array|null 菜单数据 * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getMenu(int $menuId): ?array { $menu = Db::name('system_menu') ->where('id', $menuId) ->where('delete_time', 0) ->find(); return $menu ? $menu : null; } }