Apache 2.0 License Code // +---------------------------------------------------------------------- namespace app; use think\facade\Db; use think\facade\Log; use think\facade\Session; use app\admin\library\Auth; use Throwable; // 后台全局控制器基类 class AdminController extends BaseController { /** * 接口权限 * @var object */ public object $auth; /** * 数据表名称 * @var mixed */ public mixed $tableName; /** * 控制器/类名 * @var string */ public string $controller; /** * 控制器方法 * @var string */ public string $action; /** * 控制器/方法名 * @var string */ public string $method; /** * 操作状态 * @var mixed */ public mixed $status = false; /** * 管理员信息 * @var mixed */ public mixed $admin; /** * 管理员会话标识 * @var string */ public string $sename = 'AdminLogin'; /** * 获取模板 * @access protected * @var string */ public string $template; /** * 共享模板 * @var string */ public string $tplsharing = 'add'; /** * 当前表字段 * * @var array */ protected array $tableFields = []; /** * 默认开关 * * @var string */ protected string $keepField = 'status'; /** * 开启数据限制 * 默认关闭 * @var bool */ protected bool $dataLimit = false; /** * 数据限制字段 * * @var string */ protected string $dataLimitField = 'admin_id'; /** * 需要排除的字段 * * @var mixed */ protected mixed $ruleOutFields = ""; /** * 查询过滤字段 * * @var array */ protected array $filterWhere = ['page', 'limit']; /** * 查询转换字段 * * @var array */ protected array $converTime = ['create_time', 'update_time', 'delete_time']; /** * 不需要鉴权的方法 * @var array */ protected array $noNeedLogin = [ '/index/index', // 后台首页 ]; /** * 跳转URL地址 * @var string */ protected string $JumpUrl = '/'; // 后台应用全局初始化 protected function initialize() { $this->admin = Session::get($this->sename); if (!isset($this->admin['id'])) { // 非登录跳转页面 return $this->redirect(url('/login')->suffix(false)); } $this->controller = request()->controller(); $this->action = request()->action(); $this->method = '/' . $this->controller . '/' . $this->action; // 校验权限 $this->auth = Auth::instance(); if (!in_array($this->method, $this->noNeedLogin) && !in_array('*', $this->noNeedLogin)) { if (!$this->auth->SuperAdmin() && !$this->auth->check($this->method, $this->admin['id'])) { if (request()->isAjax()) { return $this->error('没有权限!'); } else { $this->retResponseError('没有权限!', 401); } } } // 分配前端变量 $this->app->view->assign([ 'app' => request()->root(), 'controller' => $this->controller, 'action' => $this->action, 'AdminLogin' => $this->admin ]); } /** * 获取资源 */ public function index() { if (request()->isAjax()) { $page = input('page/d',1); $limit = input('limit/d',100); $where = $this->buildSelectParams(); // var_dump($where); $count = $this->model->where($where)->count(); $limit = is_empty($limit) ? 15 : $limit; $page = $count <= $limit ? 1 : $page; $fieldList = $this->model->getFields(); $order = !array_key_exists('sort', $fieldList) ? 'id' : 'sort'; $relation = []; $relListKey = []; try { $refClass = new \ReflectionClass($this->model); foreach ($refClass->getMethods() as $method) { $doc = $method->getDocComment(); preg_match('/@localKey\s+(\w+)/',(string) $doc, $localKey); preg_match('/@bind\s+(\w+)/',(string) $doc, $bind); if (!empty($localKey) && !empty($bind)) { $relation[] = $method->getName(); $expBind = explode(',', $bind[1]); $relListKey[] = ['key' => $localKey[1], 'value' => $expBind[0]]; } } // throw new \Exception('dbg-admincontroller->index():relation->'.$relation[0].' relListKey->'.$relListKey[0]['key'].'-'.$relListKey[0]['value']); } catch (\Throwable $th) { Log::info($th->getMessage()); return $this->error('dgb-查询失败:'.$th->getMessage()); } $subQuery = $this->model->field('id')->where($where)->order($order, 'desc')->limit($limit)->page($page)->buildSql(); $subQuery = '( SELECT object.id FROM ' . $subQuery . ' AS object )'; $list = $this->model->with($relation)->where('id in' . $subQuery)->order($order, 'desc')->select()->toArray(); try { // throw new \Exception('dbg-admincontrolindex:relation->'.$relation[0].' $list[0]'.$list[0][$relListKey[0]['value']]); foreach ($list as $key => $value) { foreach ($relation as $index => $item) { if (isset($value[$relListKey[$index]['key']])) { $list[$key][$relListKey[$index]['key']] = $value[$relListKey[$index]['value']]; } } } }catch (\Throwable $th) { // Log::info($th->getMessage()); return $this->error('dgb-查询失败:'.$th->getMessage()); } return $this->success('查询成功', null, $list, $count); } return view(); } /** * 添加资源 */ public function add() { if (request()->isPost()) { $post = $this->preruleOutFields(input()); if ($this->dataLimit) { $post[$this->dataLimitField] = $this->admin['id']; } $validate = $this->isValidate ? get_class($this->model) : $this->isValidate; $post = request_validate_rules($post, $validate, $this->scene); if (empty($post) || !is_array($post)) { return $this->error($post); } Db::startTrans(); try { $this->status = $this->model->create($post); Db::commit(); } catch (\PDOException $e) { Db::rollback(); return $this->error($e->getMessage()); } catch (Throwable $th) { Db::rollback(); return $this->error($th->getMessage()); } return $this->status ? $this->success() : $this->error(); } return view('', ['data' => $this->getTableFields()]); } /** * 编辑资源 */ public function edit() { $id = input('id/d'); $data = $this->model->find($id); // 限制数据调用 if ( !$this->auth->SuperAdmin() && $this->dataLimit && in_array($this->dataLimitField, $this->model->getFields()) ) { if ($data[$this->dataLimitField] != $this->admin['id']) { return $this->error('无权访问'); } } if (request()->isPost()) { $post = $this->preruleOutFields(input()); $validate = $this->isValidate ? get_class($this->model) : $this->isValidate; $post = request_validate_rules($post, $validate, $this->scene); if (empty($post) || !is_array($post)) { return $this->error($post); } Db::startTrans(); try { $this->status = $this->model->update($post); Db::commit(); } catch (\PDOException $e) { Db::rollback(); return $this->error($e->getMessage()); } catch (Throwable $th) { Db::rollback(); return $this->error($th->getMessage()); } return $this->status ? $this->success() : $this->error(); } return View($this->tplsharing, ['data' => $data]); } /** * 删除资源 */ public function del() { $id = input('id'); !is_array($id) && ($id = array($id)); if (!empty($id) && is_array($id)) { Db::startTrans(); try { $where[] = ['id', 'in', implode(',', $id)]; $list = $this->model->where($where)->select(); foreach ($list as $key => $item) { if ( !$this->auth->SuperAdmin() && $this->dataLimit && in_array($this->dataLimitField, $this->model->getFields()) ) { if ($item[$this->dataLimitField] != $this->admin['id']) { continue; } } // 过滤字段 if (isset($item->isSystem) && $item->isSystem) { throw new \Exception('禁止删除系统级字段'); } $this->status += $item->delete(); } Db::commit(); } catch (\PDOException $e) { Db::rollback(); return $this->error($e->getMessage()); } catch (Throwable $th) { Db::rollback(); return $this->error($th->getMessage()); } $this->status && $this->success(); } return $this->error(); } /** * 修改资源状态 * * @return void */ public function status() { if (request()->isAjax()) { $where[] = ['id', '=', input('id/d')]; if ( !$this->auth->SuperAdmin() && $this->dataLimit && in_array($this->dataLimitField, $this->model->getFields()) ) { $where[] = [$this->dataLimitField, '=', $this->admin['id']]; } Db::startTrans(); try { $this->status = $this->model->where($where)->update(['status' => input('status/d')]); Db::commit(); } catch (\PDOException $e) { Db::rollback(); return $this->error($e->getMessage()); } catch (Throwable $th) { Db::rollback(); return $this->error($th->getMessage()); } $this->status && $this->success(); } return $this->error(); } /** * 排除特定字段 * * @param [type] $params */ protected function preruleOutFields($params = '') { if (is_array($this->ruleOutFields)) { foreach ($this->ruleOutFields as $field) { if (key_exists($field, $params)) { unset($params[$field]); } } } else { if (key_exists($this->ruleOutFields, $params)) { unset($params[$this->ruleOutFields]); } } return $params; } /** * 获取查询参数 * * @param array $searchFields * @return array|false */ protected function buildSelectParams(array $searchFields = []) { $params = request()->param(); if (!empty($params) && is_array($params)) { $where = []; // 获取模型字段 $this->tableFields = $this->model->getFields(); foreach ($params as $field => $value) { // 过滤字段 if (in_array($field, $this->filterWhere)) { continue; } // 非表内字段 if (!array_key_exists($field, $this->tableFields)) { continue; } // 默认状态字段 if ($field == $this->keepField) { $where[] = [$field, '=', intval((int)$value - 1)]; continue; } // 获取类型 $type = $this->tableFields[$field]['type']; $type = explode('(', $type)[0]; $value = str_replace('/\s+/', '', $value); switch ($type) { case 'char': case 'text': case 'varchar': case 'tinytext': case 'longtext': $where[] = [$field, 'like', '%' . $value . '%']; break; case 'int': case 'bigint': case 'integer': case 'tinyint': case 'smallint': case 'mediumint': case 'float': case 'double': case 'timestamp': case 'year': $value = str_replace(',', '-', $value); if (strpos($value, '-')) { $arr = explode(' - ', $value); if (empty($arr)) { continue 2; } if (in_array($field, $this->converTime)) { if (isset($arr[0])) { $arr[0] = strtotime($arr[0]); } if (isset($arr[1])) { $arr[1] = strtotime($arr[1]); } } $exp = 'between'; if ($arr[0] === '') { $exp = '<='; $arr = $arr[1]; } elseif ($arr[1] === '') { $exp = '>='; $arr = $arr[0]; } $where[] = [$field, $exp, $arr]; } else { $where[] = [$field, '=', $value]; } break; case 'set'; $where[] = [$field, 'find in set', $value]; break; case 'enum'; $where[] = [$field, '=', $value]; break; case 'date'; case 'time'; case 'datetime'; $value = str_replace(',', '-', $value); if (strpos($value, '-')) { $arr = explode(' - ', $value); if (!array_filter($arr)) { continue 2; } $exp = '='; if ($arr[0] === '') { $exp = '<= TIME'; $arr = $arr[1]; } elseif ($arr[1] === '') { $exp = '>= TIME'; $arr = $arr[0]; } $where[] = [$field, $exp, $arr]; } else { $where[] = [$field, '=', $value]; } break; case 'blob'; break; default: // 默认值 break; } } // 限制数据字段 if (!$this->auth->SuperAdmin() && $this->dataLimit) { if (in_array($this->dataLimitField, $this->tableFields)) { $where[] = [$this->dataLimitField, '=', $this->admin['id']]; } } // 默认加载非禁用数据 if (array_key_exists($this->keepField, $this->tableFields) && !array_key_exists($this->keepField, $params)) { $where[] = [$this->keepField, '=', 1]; } return $where; } return false; } /** * 数据表排序 * @return mixed|void */ public function sort() { if (request()->isPost()) { if (array_search('sort', $this->model->getTableFields())) { try { $ids = request()->param('ids'); $list = $this->model->where('id', 'in', $ids)->orderRaw('field(id,'.implode(',',$ids).')')->select()->toArray(); $newSort = array_column($list, 'sort'); rsort($newSort); $array = []; // 循环处理排序字段 foreach ($list as $key => $value) { $array[] = [ 'id' => $value['id'], 'sort' => $newSort[$key], ]; } $this->model->saveAll($array); } catch (\Throwable $th) { return $this->error($th->getMessage()); } } else { return $this->error('数据表未包含排序字段'); } return $this->success(); } } /** * 数据预处理 * @access public * @param array $where 查询条件 * @return array */ public function buildBeforeWhere(array $where = []): array { $ids = input('id') ?? 'all'; if (is_array($ids) && !empty($ids)) { $where[] = ['id', 'in', implode(',', $ids)]; } else if ($ids == 'all') { $where[] = ['id', '<>', 'null']; } else if (is_numeric($ids)) { $where[] = ['id', '=', $ids]; } return $where; } /** * 递归查询父节点 * @access public * @param int $pid 查询条件 * @param array $array 返回数组 * @return array */ public function parentNode(int $pid, array &$array = []): array { $result = $this->model->where('id', $pid)->find()->toArray(); if (!empty($result)) { /** * 多语言字段 */ if (isset($result['title'])) { $result['title'] = __($result['title']); } $array[] = $result; if ($result['pid'] !== 0) { $this->parentNode($result['pid'], $array); } } return $array; } }