'desc', ]; /** * 允许修改的字段. * @var array */ protected $allowModifyFields = [ 'status', 'sort', 'remark', 'is_delete', 'is_auth', 'title', ]; /** * 不导出的字段信息. * @var array */ protected $noExportFields = ['delete_time', 'update_time']; /** * 下拉选择条件. * @var array */ protected $selectWhere = []; /** * 是否关联查询. * @var bool */ protected $relationSearch = false; /** * 模板布局, false取消. * @var string|bool */ protected $layout = 'layout/default'; /** * 是否为演示环境. * @var bool */ protected $isDemo = false; /** * 多元传参 * * @var array */ private $dataBrage = []; private $internalDataFields = []; protected $validateRule = null; protected $validateMessage = []; protected $batchValidate = false; /** * 导出文件的名称,支持中文,为空则获取模型名称. * * @var string */ protected $exportFileName = null; /** * 当前登陆的管理员. * @var SystemAdmin */ protected $sessionAdmin; /** * 初始化方法. */ protected function initialize() { if (empty($this->pageKeyName)) { $this->pageKeyName = $this->request->controller() . '_' . $this->request->action(); } parent::initialize(); $this->layout && $this->app->view->engine()->layout($this->layout); $this->isDemo = Env::get('adminsystem.is_demo', false); $this->viewInit(); $this->checkAuth(); $this->initSort(); } public function initSort() { $sort = $this->request->param('sort'); if (!empty($sort)) { $this->sort = $sort; } } /** * 模板变量赋值 * @param string|array $name 模板变量 * @param mixed $value 变量值 * @return mixed */ public function assign($name, $value = null, $isAppendToDataBrage = false, $forceObject = false) { if (is_array($name)) { $forceObject = $isAppendToDataBrage; $isAppendToDataBrage = $value; if ($isAppendToDataBrage === true) { foreach ($name as $k => $v) { $this->setDataBrage($k, $v, $forceObject); } } elseif ($isAppendToDataBrage === -1) { $this->internalDataFields = array_merge($this->internalDataFields, array_keys($name)); } } else { if ($isAppendToDataBrage === true) { $this->setDataBrage($name, $value, $forceObject); } elseif ($isAppendToDataBrage === -1) { $this->internalDataFields[] = $name; } } return $this->app->view->assign($name, $value); } public function fetchJS($template = '') { $content_js = ''; $common_template = '_common'; if (!empty($template)) { $template_arr = explode('/', $template); unset($template_arr[count($template_arr) - 1]); $template_arr[] = '_common'; $common_template = implode('/', $template_arr); } try { $content_js .= View::layout(false)->fetchJS($common_template); $content_js .= View::layout(false)->fetchJS($template); } catch (TemplateNotFoundException $th) { if (Env::get('adminsystem.strict_view_js', true)) { throw $th; } } return ""; } /** * 解析和获取模板内容 用于输出. * @param string $template * @param array $vars * @return mixed */ public function fetch($template = '', $vars = []) { $this->assign('data_brage', json_encode($this->dataBrage)); $this->assign('content_js', $this->fetchJS($template), -1); $content_main = View::layout($this->layout) ->config([ 'view_suffix' => 'html', ])->fetch($template, $vars); $html = ''; $html .= $content_main; if ($this->checkParseApi()) { $data = $this->parseInternalDataFields(View::fetchData()); $r = json_message($data); return $r; } return $html; } public function checkParseApi() { if (Config::get('app.auto_parse_api')) { if ($this->request->isJson() && $this->request->param('get_page_data')) { return true; } } return false; } /** * 处理数据,过滤内部字段. * @param array $data 内部数据 * @return array */ public function parseInternalDataFields($data) { foreach ($this->internalDataFields as $field) { if (isset($data[$field])) { unset($data[$field]); } } if (isset($data['data_brage'])) { $data_brage = json_decode($data['data_brage'], true); // 如果data_brage中的key在data中存在,则删掉data_brage中的 foreach ($data as $key => $value) { if (isset($data_brage[$key])) { unset($data_brage[$key]); } } $data['data_brage'] = $data_brage; } return $data; } /** * 设置dataBrage数据. * * @param string $name 键 * @param mixed $value 值 * @param bool $forceObject 强制转为对象 * @return void */ public function setDataBrage($name, $value, $forceObject = false) { if (is_array($name)) { foreach ($name as $k => $v) { $this->setDataBrage($k, $v, $forceObject); } return $this; } if ($forceObject && !is_object($value)) { $value = (object) $value; } $this->dataBrage[$name] = $value; return $this; } /** * 重写验证规则. * @param array $data * @param array|string $validate * @param array $message * @param bool|null $batch * @return array|bool|string|true */ public function validate(array $data, $validate, array $message = [], bool $batch = null) { try { $message = array_merge($this->validateMessage, $message); if (is_null($batch)) { $batch = $this->batchValidate; } if ($this->validateRule instanceof Validate) { $this->validateRule->message($message); // 是否批量验证 if ($batch) { $this->validateRule->batch(true); } $this->validateRule->failException(true)->check($data); } elseif (is_array($this->validateRule)) { parent::validate($data, $this->validateRule, $message, $batch); } else { parent::validate($data, $validate, $message, $batch); } } catch (\Exception $e) { $this->error($e->getMessage()); } return true; } /** * 构建请求参数. * @param array $excludeFields 忽略构建搜索的字段 * @return array */ protected function buildTableParames($excludeFields = []) { $get = $this->request->get('', null); $page = isset($get['page']) && !empty($get['page']) ? $get['page'] : 1; $limit = isset($get['limit']) && !empty($get['limit']) ? $get['limit'] : 15; $group = isset($get['group']) && !empty($get['group']) ? $get['group'] : null; $filters = isset($get['filter']) && !empty($get['filter']) ? $get['filter'] : '{}'; $ops = isset($get['op']) && !empty($get['op']) ? $get['op'] : '{}'; // json转数组 $filters = json_decode($filters, true) ?? []; $ops = json_decode($ops, true); $where = []; $excludes = []; $request_options = []; // 判断是否关联查询 $tableName = \think\helper\Str::snake(lcfirst($this->model->getName())); foreach ($filters as $key => $val) { if (in_array($key, $excludeFields)) { $excludes[$key] = $val; continue; } $op = isset($ops[$key]) && !empty($ops[$key]) ? $ops[$key] : '%*%'; if (strpos($key, '[') === 0) { $key = str_replace('[', '', $key); $key = explode(']', $key)[0]; } if ($this->relationSearch && count(explode('.', $key)) == 1) { $key = "{$tableName}.{$key}"; } switch (strtolower($op)) { case '=': $where[] = [$key, '=', $val]; break; case '%*%': $where[] = [$key, 'LIKE', "%{$val}%"]; break; case '*%': $where[] = [$key, 'LIKE', "{$val}%"]; break; case '%*': $where[] = [$key, 'LIKE', "%{$val}"]; case 'in': $where[] = [$key, 'IN', "{$val}"]; break; case 'min': $where[] = [$key, '>=', $val]; break; case 'max': $where[] = [$key, '<=', $val]; break; case 'min_date': $where[] = [$key, '>=', strtotime($val)]; break; case 'max_date': $where[] = [$key, '<=', strtotime($val)]; break; case 'range': [$beginTime, $endTime] = explode(' - ', $val); $where[] = [$key, '>=', strtotime($beginTime)]; $where[] = [$key, '<=', strtotime($endTime)]; break; case 'none': $request_options[$key] = $val; break; default: $where[] = [$key, $op, "%{$val}"]; } } return [$page, $limit, $where, $excludes, $request_options, $group]; } /** * 下拉选择列表. * @return Json */ public function selectList() { $fields = input('selectFields'); $data = $this->model ->where($this->selectWhere) ->field($fields) ->select(); $this->success(null, $data); } /** * 初始化视图参数. */ private function viewInit() { $request = app()->request; list($thisModule, $thisController, $thisAction) = [app('http')->getName(), app()->request->controller(), $request->action()]; list($thisControllerArr, $jsPath) = [explode('.', $thisController), null]; foreach ($thisControllerArr as $vo) { empty($jsPath) ? $jsPath = parse_name($vo) : $jsPath .= '/' . parse_name($vo); } $autoloadJs = file_exists(root_path('public') . "static/{$thisModule}/js/{$jsPath}.js") ? true : false; $thisControllerJsPath = "{$thisModule}/js/{$jsPath}.js"; $adminModuleName = config('app.admin_alias_name'); $isSuperAdmin = session('admin.id') == AdminConstant::SUPER_ADMIN_ID ? true : false; $data = [ 'adminModuleName' => $adminModuleName, 'thisController' => parse_name($thisController), 'thisAction' => $thisAction, 'thisRequest' => parse_name("{$thisModule}/{$thisController}/{$thisAction}"), 'thisControllerJsPath' => "{$thisControllerJsPath}", 'autoloadJs' => $autoloadJs, 'isSuperAdmin' => $isSuperAdmin, 'version' => env('app_debug') ? time() : sysconfig('site', 'site_version'), 'pageKeyName' => $this->pageKeyName, ]; $this->assign($data, -1); } /** * 检测权限. * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ protected function checkAuth($currentNode = null, $haltRequest = true) { $adminConfig = config('admin'); $header_authorization = $this->request->header('Authorization'); if (!empty($header_authorization)) { $token = explode(' ', $header_authorization)[1]; $admin = Cache::get($token); } else { $admin = session('admin'); } $back_url = $this->request->url(); if (empty($admin)) { $this->error('请先登录后台', [], __url('admin/login/index', ['back_url' => $back_url])); } $adminId = $admin['id']; $expireTime = $admin['expire_time']; /** @var AuthService $authService */ $authService = app(AuthService::class, ['adminId' => $adminId]); $currentNode = $authService->getCurrentNode(); if (is_null($currentNode)) { $currentNode = $authService->getCurrentNode(); } $currentController = parse_name(app()->request->controller()); // 验证登录 if ( !in_array($currentController, $adminConfig['no_login_controller']) && !in_array($currentNode, $adminConfig['no_login_node']) ) { empty($adminId) && $this->error('请先登录后台', [], __url('admin/login/index', ['back_url' => $back_url])); // 判断是否登录过期 if ($expireTime !== true && time() > $expireTime) { session('admin', null); $this->error('登录已过期,请重新登录', [], __url('admin/login/index', ['back_url' => $back_url])); } } // 验证权限 if ( !in_array($currentController, $adminConfig['no_auth_controller']) && !in_array($currentNode, $adminConfig['no_auth_node']) ) { $check = $authService->checkNode($currentNode); if ($haltRequest) { if (!$check) { $this->error('无权限访问'); } } else { return $check; } // 判断是否为演示环境 if (env('adminsystem.is_demo', false) && app()->request->isPost()) { $this->error('演示环境下不允许修改'); } } $model_admin = SystemAdmin::autoCache('read', $adminId)->find($adminId); $this->sessionAdmin = $model_admin; $this->assign('session_admin', $model_admin, -1); } /** * 严格校验接口是否为POST请求 */ protected function checkPostRequest() { if (!$this->request->isPost()) { $this->error('当前请求不合法!'); } } }