menuRule($data,false); if(! $status) return [$status, $msg]; $del_button_id = $msg; DB::beginTransaction(); try{ $model = SysMenu::where('id',$data['id'])->first(); $model->title = $data['title']; $model->icon = $data['icon'] ?? ''; $model->uri = $data['uri']; $model->parent_id = $data['parent_id']; $model->sort = $data['sort'] ?? 0; $model->save(); $time = time(); //按钮 $this->saveDetail($model->id, time(), $data); if(! empty($del_button_id)){ SysMenuButton::where('del_time',0) ->whereIn('id',$del_button_id) ->update(['del_time' => $time]); RoleMenuButton::where('del_time',0) ->whereIn('button_id', $del_button_id) ->update(['del_time' => $time]); } DB::commit(); }catch (\Exception $exception){ DB::rollBack(); return [false,$exception->getMessage()]; } return [true,'']; } public function add($data,$user){ list($status,$msg) = $this->menuRule($data); if(! $status) return [$status,$msg]; DB::beginTransaction(); try{ $model = new SysMenu(); $sort = $model->where('parent_id',$data['parent_id'])->max('sort'); $model->title = $data['title']; $model->icon = $data['icon'] ?? ''; $model->uri = $data['uri']; $model->parent_id = $data['parent_id']; $model->sort = $sort ? $sort + 1 : 1; $model->crt_id = $user['id']; $model->save(); //按钮 $this->saveDetail($model->id, time(), $data); DB::commit(); }catch (\Exception $exception){ DB::rollBack(); return [false,$exception->getMessage()]; } return [true,'']; } private function saveDetail($id, $time, $data){ if (! empty($data['button'])) { $toUpdate = []; $toInsert = []; foreach ($data['button'] as $key => $value) { $row = [ 'menu_id' => $id, 'title' => $value['title'], 'sort' => $key, 'func' => $value['func'], ]; if (!empty($value['id'])) { $row['id'] = $value['id']; $toUpdate[] = $row; } else { $row['crt_time'] = $time; $toInsert[] = $row; } } // 1. 批量插入 if (! empty($toInsert)) SysMenuButton::insert($toInsert); // 2. 批量更新 if(! empty($toUpdate)){ foreach ($toUpdate as $updateRow) { $id = $updateRow['id']; unset($updateRow['id']); SysMenuButton::where('id', $id)->update($updateRow); } } } } public function del($data){ if($this->isEmpty($data,'id')) return [false,'菜单ID不能为空']; DB::beginTransaction(); try { $time = time(); SysMenu::where('id',$data['id'])->update([ 'del_time' => $time ]); SysMenuButton::where('del_time',0)->where('menu_id',$data['id'])->update([ 'del_time' => $time ]); RoleMenu::where('del_time',0)->where('menu_id',$data['id'])->update([ 'del_time' => $time ]); RoleMenuButton::where('del_time',0)->where('menu_id',$data['id'])->update([ 'del_time' => $time ]); DB::commit(); }catch (\Exception $exception){ DB::rollBack(); return [false,$exception->getMessage()]; } return [true,'']; } public function menuList($data, $user){ $return = []; $type = $data['type'] ?? ""; $sysList = SysMenu::where('del_time',0) ->select('title','icon','uri','parent_id','sort','id','is_authority', 'state') ->orderBy('sort','desc') ->get() ->toArray(); $button = SysMenuButton::where('del_time',0) ->select('id','title','sort','func','menu_id') ->get()->toArray(); if(empty($type)){ $return = $this->fillMenuButton($button,$sysList, $user); }elseif($type == "all"){ $return_one = $this->fillMenuButton($button, $sysList, $user); $return_two = $this->returnTwo($sysList, $user); $return_three = $this->fillMenuButton($button, $sysList, $user,2); $return = [ 'one' => $return_one, 'two' => $return_two, 'three' => $return_three, ]; } return [true, $return]; } public function menuRule($data, $is_check = true){ if($this->isEmpty($data,'title')) return [false,'名称不能为空!']; if($this->isEmpty($data,'parent_id')) return [false,'父级不存在!']; //菜单 if($is_check){ $bool = SysMenu::where('title',$data['title']) ->where('del_time',0) ->exists(); }else{ if($this->isEmpty($data,'id')) return [false,'ID不能为空!']; $bool = SysMenu::where('title',$data['title']) ->where('id','<>',$data['id']) ->where('del_time',0) ->exists(); $menu_button = SysMenuButton::where('del_time',0) ->where('menu_id',$data['id']) ->pluck('id')->all(); } if($bool) return [false,'菜单名称已经存在']; //按钮 if(! empty($data['button'])){ $title = array_column($data['button'],'title'); $title = array_map(function($val) { return $val !== null ? $val : ""; }, $title); $title_count = array_count_values($title); foreach ($title as $value){ if(empty($value)) return [false,'按钮名称不能为空!']; if($title_count[$value] > 1) return [false,'按钮名称不能重复']; } } $del = []; if(! empty($menu_button)){ $submit = array_column($data['button'],'id'); foreach ($menu_button as $value){ if(! in_array($value, $submit)) $del[] = $value; } } return [true, $del]; } public function menuMove($data){ if($this->isEmpty($data,'id')) return [false,'ID不能为空!']; if($this->isEmpty($data,'move')) return [false,'移动不能能为空!']; //移动项 $model = new SysMenu(); $res = $model->where('id', $data['id'])->first(); if($data['move'] == 1 || $data['move'] == -1){ //替项目 $moveModel = $model->where('del_time',0)->where('parent_id',$res->parent_id); //下移-1 上移1 $data['move'] == 1 ? $moveModel->orderby('sort','desc')->where('sort','<', $res['sort']) : $moveModel->orderby('sort','asc')->where('sort','>', $res['sort']); $moveRes = $moveModel->first(); if(! $moveRes) return [false, '移动失败']; $weightOne = $res->sort; $weightTwo = $moveRes->sort; $res->sort = $weightTwo; $res->save(); $moveRes->sort = $weightOne; $moveRes->save(); }elseif($data['move'] == 'top' || $data['move'] == 'bottom'){ if($data['move'] == 'top'){ $sort = $model->where('del_time',0)->where('parent_id',$res->parent_id)->max('sort'); if($sort == $res->sort) return [false,'已经置顶,移动失败!']; $res->sort = $sort + 1; }elseif($data['move'] == 'bottom'){ $sort = $model->where('del_time',0)->where('parent_id',$res->parent_id)->min('sort'); if($sort == $res->sort) return [false,'已经置底部,移动失败!']; $res->sort = $sort - 1; } $res->save(); }else{ return [false, '异常参数']; } return [true,'']; } public function fillMenuButton($button, $menu, $user, $type = 1) { // 1. 预处理所有按钮池(合并配置中的特殊按钮) $allButtons = collect($button)->concat(config('specialButton') ?? [])->groupBy('menu_id'); // 2. 获取权限基础数据(如果是超管,这两个值为空,逻辑依然兼容) $isSuper = ($user['is_admin'] == Employee::IS_ADMIN_TWO); $roleButtons = $isSuper ? [] : (new EmployeeService())->fillRoleButton($user['role_ids'] ?? []); $allowedMenuIds = $isSuper ? [] : $this->getMenuIDByRoleInList($user); $result = []; foreach ($menu as $m) { $menuId = $m['id']; // 权限过滤:非超管且不在权限内,跳过 if (!$isSuper && !in_array($menuId, $allowedMenuIds)) continue; // 计算当前菜单拥有的按钮 if ($isSuper) { $btns = $allButtons->get($menuId) ?? []; } else { // 取交集:只返回该角色拥有的按钮数据 $myBtnIds = $roleButtons[$menuId] ?? []; $btnPool = collect($allButtons->get($menuId))->keyBy('id'); $btns = collect($myBtnIds)->map(fn($id) => $btnPool->get($id))->filter()->values(); } // 3. 根据 type 返回不同的数据结构 if ($type == 1) { // 完整模式:保留原菜单所有字段 $m['button'] = $btns; $result[] = $m; } else { // 精简模式:只给前端路由用的字段 $result[] = [ 'id' => $menuId, 'uri' => $m['uri'] ?? '', 'button' => $btns, ]; } } return $result; } private function returnTwo($sysList, $user){ //人员所拥有的菜单 $menu = $this->getMenuIDByRoleInList($user); foreach ($sysList as $key => $value){ if($value['state'] <= 0) unset($sysList[$key]); if($user['is_admin'] != Employee::IS_ADMIN_TWO && ! in_array($value['id'], $menu)) unset($sysList[$key]); } $list = array_values($sysList); $return = $this->makeTree(0,$list); return $this->set_sort_circle($return);; } //通过角色获取菜单ID public function getMenuIDByRoleInList($user){ $role_id = $user['role_ids'] ?? []; if(empty($role_id)) return []; return RoleMenu::whereIn('role_id', $role_id) ->where('del_time',0) ->pluck('menu_id') ->all(); } public function getMenuDataByRoleInList($user){ $role_id = $user['role_ids'] ?? []; if(empty($role_id)) return []; return RoleMenu::whereIn('role_id',$role_id) ->where('del_time',0) ->select('menu_id','type') ->get()->toArray(); } public function getMap($menu_id){ $menu_id = array_filter((array)$menu_id); if (empty($menu_id)) return []; return SysMenu::whereIn('id', $menu_id) ->pluck('title', 'id') ->toArray(); } }