Files
ulthon_admin/extend/base/common/controller/AdminControllerBase.php
2025-03-20 16:57:05 +08:00

541 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace base\common\controller;
use app\admin\model\SystemAdmin;
use app\BaseController;
use app\common\constants\AdminConstant;
use app\common\service\AuthService;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Env;
use think\facade\View;
use think\Model;
use think\response\Json;
use think\template\exception\TemplateNotFoundException;
use think\Validate;
/**
* Class AdminController.
*/
class AdminControllerBase extends BaseController
{
use \app\common\traits\JumpTrait;
protected $pageKeyName = null;
/**
* 当前模型.
* @Model
* @var object
*/
protected $model;
/**
* 字段排序.
* @var array
*/
protected $sort = [
'id' => 'desc',
];
/**
* 允许修改的字段.
* @var array
*/
protected $allowModifyFields = [
'status',
'sort',
'remark',
'is_delete',
'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 "<script>{$content_js}</script>";
}
/**
* 解析和获取模板内容 用于输出.
* @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();
$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('当前请求不合法!');
}
}
}