auth->isSuperAdmin()) { $this->error(__('Access is allowed only to the super management group')); } $this->model = model('AuthRule'); // 必须将结果集转换为数组 $ruleList = \think\Db::name("auth_rule")->field('type,condition,remark,createtime,updatetime', true)->order('weigh DESC,id ASC')->select(); foreach ($ruleList as $k => &$v) { $v['title'] = __($v['title']); } unset($v); Tree::instance()->init($ruleList)->icon = ['    ', '    ', '    ']; $this->rulelist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title'); $ruledata = [0 => __('None')]; foreach ($this->rulelist as $k => &$v) { if (!$v['ismenu']) { continue; } $ruledata[$v['id']] = $v['title']; unset($v['spacer']); } unset($v); $this->view->assign('ruledata', $ruledata); $this->view->assign("menutypeList", $this->model->getMenutypeList()); } /** * 查看 */ public function index() { if ($this->request->isAjax()) { $list = $this->assignSeq($this->filterRuleList($this->rulelist)); $total = count($list); $result = array("total" => $total, "rows" => $list); return json($result); } return $this->view->fetch(); } /** * 按筛选条件过滤规则树 * * 支持:仅菜单 / 仅权限节点 / 全部、状态、关键词(标题或规则名)。 * 命中节点的父级会一并保留,避免树形层级断裂。 * * @param array $list * @return array */ protected function filterRuleList(array $list) { $type = (string)$this->request->request('rule_filter', 'menu'); $status = (string)$this->request->request('rule_status', ''); $keyword = trim((string)$this->request->request('rule_keyword', '')); $type = in_array($type, ['menu', 'node', 'all'], true) ? $type : 'all'; $status = in_array($status, ['normal', 'hidden'], true) ? $status : ''; if ($type === 'all' && $status === '' && $keyword === '') { return $list; } $byId = []; foreach ($list as $row) { $byId[(int)$row['id']] = $row; } $keep = []; foreach ($list as $row) { $match = true; if ($type === 'menu' && !$row['ismenu']) { $match = false; } if ($type === 'node' && $row['ismenu']) { $match = false; } if ($status !== '' && $row['status'] !== $status) { $match = false; } if ($keyword !== '' && stripos($row['title'], $keyword) === false && stripos($row['name'], $keyword) === false) { $match = false; } if (!$match) { continue; } // 保留命中节点的所有父级 $id = (int)$row['id']; $guard = 0; while ($id && isset($byId[$id]) && $guard++ < 20) { $keep[$id] = true; $id = (int)$byId[$id]['pid']; } } $result = []; foreach ($list as $row) { if (isset($keep[(int)$row['id']])) { $result[] = $row; } } return $result; } /** * 生成层级序号:1、1.1、1.2、2、2.1…… * * 树形列表默认会隐藏子行,若按行号显示序号会出现 1/7/28 这类跳号; * 这里按父子层级编号,展开/收起都稳定可读。 * * @param array $list * @return array */ protected function assignSeq(array $list) { $byId = []; foreach ($list as $row) { $byId[(int)$row['id']] = $row; } $seqById = []; $counters = []; foreach ($list as &$row) { $depth = 0; $pid = (int)$row['pid']; $guard = 0; while ($pid && isset($byId[$pid]) && $guard++ < 20) { $depth++; $pid = (int)$byId[$pid]['pid']; } $counters[$depth] = isset($counters[$depth]) ? $counters[$depth] + 1 : 1; if ($depth === 0) { $seq = (string)$counters[$depth]; } else { $parentSeq = isset($seqById[(int)$row['pid']]) ? $seqById[(int)$row['pid']] : ''; $seq = ($parentSeq !== '' ? $parentSeq . '.' : '') . $counters[$depth]; } // 进入新分支后,重置更深的层级计数 for ($i = $depth + 1; $i <= 10; $i++) { unset($counters[$i]); } $row['seq'] = $seq; $seqById[(int)$row['id']] = $seq; } unset($row); return $list; } /** * 添加 */ public function add() { if ($this->request->isPost()) { $this->token(); $params = $this->request->post("row/a", [], 'strip_tags'); if ($params) { if (!$params['ismenu'] && !$params['pid']) { $this->error(__('The non-menu rule must have parent')); } $result = $this->model->validate()->save($params); if ($result === false) { $this->error($this->model->getError()); } $this->success(); } $this->error(); } return $this->view->fetch(); } /** * 编辑 */ public function edit($ids = null) { $row = $this->model->get(['id' => $ids]); if (!$row) { $this->error(__('No Results were found')); } if ($this->request->isPost()) { $this->token(); $params = $this->request->post("row/a", [], 'strip_tags'); if ($params) { if (!$params['ismenu'] && !$params['pid']) { $this->error(__('The non-menu rule must have parent')); } if ($params['pid'] == $row['id']) { $this->error(__('Can not change the parent to self')); } if ($params['pid'] != $row['pid']) { $childrenIds = Tree::instance()->init(collection(AuthRule::select())->toArray())->getChildrenIds($row['id']); if (in_array($params['pid'], $childrenIds)) { $this->error(__('Can not change the parent to child')); } } $params = $this->preExcludePrimaryKey($params); //这里需要针对name做唯一验证 $ruleValidate = \think\Loader::validate('AuthRule'); $ruleValidate->rule([ 'name' => 'require|unique:AuthRule,name,' . $row->id, ]); $result = $row->validate()->save($params); if ($result === false) { $this->error($row->getError()); } $this->success(); } $this->error(); } $this->view->assign("row", $row); return $this->view->fetch(); } /** * 删除 */ public function del($ids = "") { if (!$this->request->isPost()) { $this->error(__("Invalid parameters")); } $ids = $ids ? $ids : $this->request->post("ids"); if ($ids) { $delIds = []; foreach (explode(',', $ids) as $k => $v) { $delIds = array_merge($delIds, Tree::instance()->getChildrenIds($v, true)); } $delIds = array_unique($delIds); $count = $this->model->where('id', 'in', $delIds)->delete(); if ($count) { Cache::rm('__menu__'); $this->success(); } } $this->error(); } }