'desc', 'id' => 'desc', ]; public function __construct(App $app) { parent::__construct($app); $this->model = new SystemAuth(); } /** * @NodeAnotation(title="授权") */ public function authorize($id) { $row = $this->model->find($id); empty($row) && $this->error('数据不存在'); $checkNodeList = (new SystemAuthNode()) ->where('auth_id', $id) ->column('node'); $module_list = (new NodeService())->getNodeTree(); foreach ($module_list as $module_key => $module) { foreach ($module['children'] as $controllerKey => $controller) { foreach ($controller['children'] as $actionKey => $action) { $checked = in_array($action['node'], $checkNodeList); $checked_string = $checked? 'checked' : ''; $disabled_string = ''; if(!$action['auth']){ $checked_string = 'checked'; $disabled_string = 'disabled'; } $module_list[$module_key]['children'][$controllerKey]['children'][$actionKey]['checked'] = $checked_string; $module_list[$module_key]['children'][$controllerKey]['children'][$actionKey]['disabled'] = $disabled_string; } } } $this->assign('row', $row); $this->assign('checked_node_list', $checkNodeList); $this->assign('module_list', $module_list); return $this->fetch(); } /** * @NodeAnotation(title="授权保存") */ public function saveAuthorize() { $this->checkPostRequest(); $id = $this->request->post('id'); $node = $this->request->post('node', []); $row = $this->model->find($id); empty($row) && $this->error('数据不存在'); try { $authNode = new SystemAuthNode(); $authNode->where('auth_id', $id)->delete(); if (!empty($node)) { $saveAll = []; foreach ($node as $vo) { $saveAll[] = [ 'auth_id' => $id, 'node' => $vo, ]; } $authNode->saveAll($saveAll); } TriggerService::updateMenu(); } catch (\Exception $e) { $this->error('保存失败'); } $this->success('保存成功'); } /** * @NodeAnotation(title="分配用户") * * 兼容 layui table 的 filter 传参:ua.table 把 where:{id:roleId} 放入 * filter JSON(filter={"id":"xxx"})而非顶层 query 参数。若 $id 无默认值, * ThinkPHP 方法参数绑定会从顶层 query 找 id 失败报"方法参数错误:id"。 * 这里给默认值 null,再从 query / filter 兜底解析;Ajax 时从 filter/op * 移除 id(角色ID不是用户搜索条件),防 buildTableParames 误用。 */ public function assignUsers($id = null) { if (empty($id)) { // 优先从顶层 query 取(iframe 页面加载时的 ?id=xxx) $id = $this->request->param('id'); // 再从 filter JSON 取(table Ajax 请求时的 filter={"id":"xxx"}) if (empty($id) && $this->request->isAjax()) { $filter = json_decode($this->request->param('filter', '{}'), true) ?: []; $id = $filter['id'] ?? ''; } if (empty($id)) { $this->error('参数错误:缺少角色ID'); } } // Ajax 时从 filter/op 移除 id(它是角色ID,不是用户搜索条件), // 防止 buildTableParames 把它当用户 id 的 WHERE 条件。 // 注意:Request::withGet 是整体覆盖($this->get = $get)而非合并, // 必须先取全量 GET 再写回,否则 page/limit 丢失导致翻页失效。 if ($this->request->isAjax()) { $get = $this->request->get('', null); $filter = isset($get['filter']) ? (json_decode($get['filter'], true) ?: []) : []; unset($filter['id']); $get['filter'] = json_encode($filter, JSON_UNESCAPED_UNICODE); $op = isset($get['op']) ? (json_decode($get['op'], true) ?: []) : []; unset($op['id']); $get['op'] = json_encode($op, JSON_UNESCAPED_UNICODE); $this->request->withGet($get); } $row = $this->model->find($id); empty($row) && $this->error('数据不存在'); if ($this->request->isAjax()) { list($page, $limit, $where) = $this->buildTableParames(); $count = SystemAdmin::where($where) ->where('delete_time', 0) ->count(); $list = SystemAdmin::where($where) ->withoutField('password') ->fieldRaw('FIND_IN_SET(' . intval($id) . ', auth_ids) AS has_role') ->where('delete_time', 0) ->page($page, $limit) ->order('id desc') ->select(); $data = [ 'code' => 0, 'msg' => '', 'count' => $count, 'data' => $list, ]; return json($data); } $this->assign('row', $row); return $this->fetch(); } /** * @NodeAnotation(title="分配用户切换") */ public function toggleUser() { $this->checkPostRequest(); $userId = intval($this->request->post('user_id')); $roleId = intval($this->request->post('role_id')); if ($userId == AdminConstant::SUPER_ADMIN_ID) { $this->error('超级管理员不支持此操作'); } $user = SystemAdmin::find($userId); if (empty($user)) { $this->error('用户不存在'); } $role = SystemAuth::where('id', $roleId)->where('delete_time', 0)->find(); if (empty($role)) { $this->error('角色不存在'); } Db::startTrans(); try { // FOR UPDATE 行锁,防止并发下读-改-写丢失逗号串的其它角色 $userRow = Db::name('system_admin')->where('id', $userId)->lock(true)->find(); $existing = empty($userRow['auth_ids']) ? [] : array_filter(explode(',', $userRow['auth_ids'])); $existing = array_values(array_map('strval', $existing)); $roleIdStr = (string) $roleId; if (in_array($roleIdStr, $existing)) { // 撤回:仅移除该角色,保留其它角色 $newArr = array_values(array_diff($existing, [$roleIdStr])); } else { // 分配:新增该角色,保留其它角色 $newArr = array_values(array_unique(array_merge($existing, [$roleIdStr]))); } Db::name('system_admin')->where('id', $userId)->update([ 'auth_ids' => empty($newArr) ? '' : implode(',', $newArr), ]); Db::commit(); } catch (\Exception $e) { Db::rollback(); $this->error('操作失败:' . $e->getMessage()); } TriggerService::updateMenu($userId); $this->success('操作成功'); } }