mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-07 02:22:48 +08:00
引入easyadmin'
This commit is contained in:
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
namespace app\common;
|
||||
|
||||
use think\migration\db\Column;
|
||||
|
||||
class ColumnFormat
|
||||
{
|
||||
public static function timestamp($name){
|
||||
return Column::make($name,'integer')
|
||||
->setLimit(10)
|
||||
->setSigned(false)
|
||||
->setDefault(0);
|
||||
}
|
||||
|
||||
public static function stringLong($name)
|
||||
{
|
||||
return Column::make($name,'string')
|
||||
->setLimit(500)
|
||||
->setDefault('');
|
||||
}
|
||||
public static function stringNormal($name)
|
||||
{
|
||||
return Column::make($name,'string')
|
||||
->setLimit(100)
|
||||
->setDefault('');
|
||||
}
|
||||
|
||||
public static function stringUrl($name)
|
||||
{
|
||||
return Column::make($name,'string')
|
||||
->setLimit(300)
|
||||
->setDefault('');
|
||||
}
|
||||
|
||||
public static function stringMd5($name)
|
||||
{
|
||||
return Column::make($name,'string')
|
||||
->setLimit(32)
|
||||
->setDefault('');
|
||||
}
|
||||
|
||||
public static function stringShort($name)
|
||||
{
|
||||
return Column::make($name,'string')
|
||||
->setLimit(30)
|
||||
->setDefault('');
|
||||
}
|
||||
public static function stringTypeStatus($name = 'type')
|
||||
{
|
||||
return Column::make($name,'string')
|
||||
->setLimit(80)
|
||||
->setDefault('');
|
||||
}
|
||||
|
||||
public static function integerTypeStatus($name = 'type',$default = 0)
|
||||
{
|
||||
return Column::make($name,'integer')
|
||||
->setLimit(10)
|
||||
->setSigned(false)
|
||||
->setDefault($default);
|
||||
}
|
||||
|
||||
public static function integer($name)
|
||||
{
|
||||
return Column::make($name,'integer')
|
||||
->setDefault(0)
|
||||
->setLimit(20)
|
||||
->setSigned(false);
|
||||
}
|
||||
|
||||
public static function text($name)
|
||||
{
|
||||
return Column::make($name,'text')
|
||||
->setDefault('');
|
||||
}
|
||||
public static function textLong($name)
|
||||
{
|
||||
return Column::longText($name)
|
||||
->setDefault('');
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\common;
|
||||
|
||||
class TextFormat
|
||||
{
|
||||
public static function br($content){
|
||||
$content = str_replace("\n",'<br/>',$content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
174
app/common/command/Curd.php
Normal file
174
app/common/command/Curd.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\command;
|
||||
|
||||
|
||||
use app\admin\model\SystemNode;
|
||||
use EasyAdmin\console\CliEcho;
|
||||
use EasyAdmin\curd\BuildCurd;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use EasyAdmin\auth\Node as NodeService;
|
||||
use think\Exception;
|
||||
|
||||
class Curd extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('curd')
|
||||
->addOption('table', 't', Option::VALUE_REQUIRED, '主表名', null)
|
||||
->addOption('controllerFilename', 'c', Option::VALUE_REQUIRED, '控制器文件名', null)
|
||||
->addOption('modelFilename', 'm', Option::VALUE_REQUIRED, '主表模型文件名', null)
|
||||
#
|
||||
->addOption('checkboxFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '复选框字段后缀', null)
|
||||
->addOption('radioFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '单选框字段后缀', null)
|
||||
->addOption('imageFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '单图片字段后缀', null)
|
||||
->addOption('imagesFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '多图片字段后缀', null)
|
||||
->addOption('fileFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '单文件字段后缀', null)
|
||||
->addOption('filesFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '多文件字段后缀', null)
|
||||
->addOption('dateFieldSuffix', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '时间字段后缀', null)
|
||||
->addOption('switchFields', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '开关的字段', null)
|
||||
->addOption('selectFileds', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '下拉的字段', null)
|
||||
->addOption('editorFields', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '富文本的字段', null)
|
||||
->addOption('sortFields', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '排序的字段', null)
|
||||
->addOption('ignoreFields', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '忽略的字段', null)
|
||||
#
|
||||
->addOption('relationTable', 'r', Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '关联表名', null)
|
||||
->addOption('foreignKey', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '关联外键', null)
|
||||
->addOption('primaryKey', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '关联主键', null)
|
||||
->addOption('relationModelFilename', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '关联模型文件名', null)
|
||||
->addOption('relationOnlyFileds', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '关联模型中只显示的字段', null)
|
||||
->addOption('relationBindSelect', null, Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, '关联模型中的字段用于主表外键的表单下拉选择', null)
|
||||
#
|
||||
->addOption('force', 'f', Option::VALUE_REQUIRED, '强制覆盖模式', 0)
|
||||
->addOption('delete', 'd', Option::VALUE_REQUIRED, '删除模式', 0)
|
||||
->setDescription('一键curd命令服务');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
|
||||
$table = $input->getOption('table');
|
||||
$controllerFilename = $input->getOption('controllerFilename');
|
||||
$modelFilename = $input->getOption('modelFilename');
|
||||
|
||||
$checkboxFieldSuffix = $input->getOption('checkboxFieldSuffix');
|
||||
$radioFieldSuffix = $input->getOption('radioFieldSuffix');
|
||||
$imageFieldSuffix = $input->getOption('imageFieldSuffix');
|
||||
$imagesFieldSuffix = $input->getOption('imagesFieldSuffix');
|
||||
$fileFieldSuffix = $input->getOption('fileFieldSuffix');
|
||||
$filesFieldSuffix = $input->getOption('filesFieldSuffix');
|
||||
$dateFieldSuffix = $input->getOption('dateFieldSuffix');
|
||||
$switchFields = $input->getOption('switchFields');
|
||||
$selectFileds = $input->getOption('selectFileds');
|
||||
$sortFields = $input->getOption('sortFields');
|
||||
$ignoreFields = $input->getOption('ignoreFields');
|
||||
|
||||
$relationTable = $input->getOption('relationTable');
|
||||
$foreignKey = $input->getOption('foreignKey');
|
||||
$primaryKey = $input->getOption('primaryKey');
|
||||
$relationModelFilename = $input->getOption('relationModelFilename');
|
||||
$relationOnlyFileds = $input->getOption('relationOnlyFileds');
|
||||
$relationBindSelect = $input->getOption('relationBindSelect');
|
||||
|
||||
$force = $input->getOption('force');
|
||||
$delete = $input->getOption('delete');
|
||||
|
||||
$relations = [];
|
||||
foreach ($relationTable as $key => $val) {
|
||||
$relations[] = [
|
||||
'table' => $relationTable[$key],
|
||||
'foreignKey' => isset($foreignKey[$key]) ? $foreignKey[$key] : null,
|
||||
'primaryKey' => isset($primaryKey[$key]) ? $primaryKey[$key] : null,
|
||||
'modelFilename' => isset($relationModelFilename[$key]) ? $relationModelFilename[$key] : null,
|
||||
'onlyFileds' => isset($relationOnlyFileds[$key]) ? explode(",", $relationOnlyFileds[$key]) : [],
|
||||
'relationBindSelect' => isset($relationBindSelect[$key]) ? $relationBindSelect[$key] : null,
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($table)) {
|
||||
CliEcho::error('请设置主表');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$build = (new BuildCurd())
|
||||
->setTable($table)
|
||||
->setForce($force);
|
||||
|
||||
!empty($controllerFilename) && $build = $build->setControllerFilename($controllerFilename);
|
||||
!empty($modelFilename) && $build = $build->setModelFilename($modelFilename);
|
||||
|
||||
!empty($checkboxFieldSuffix) && $build = $build->setCheckboxFieldSuffix($checkboxFieldSuffix);
|
||||
!empty($radioFieldSuffix) && $build = $build->setRadioFieldSuffix($radioFieldSuffix);
|
||||
!empty($imageFieldSuffix) && $build = $build->setImageFieldSuffix($imageFieldSuffix);
|
||||
!empty($imagesFieldSuffix) && $build = $build->setImagesFieldSuffix($imagesFieldSuffix);
|
||||
!empty($fileFieldSuffix) && $build = $build->setFileFieldSuffix($fileFieldSuffix);
|
||||
!empty($filesFieldSuffix) && $build = $build->setFilesFieldSuffix($filesFieldSuffix);
|
||||
!empty($dateFieldSuffix) && $build = $build->setDateFieldSuffix($dateFieldSuffix);
|
||||
!empty($switchFields) && $build = $build->setSwitchFields($switchFields);
|
||||
!empty($selectFileds) && $build = $build->setSelectFileds($selectFileds);
|
||||
!empty($sortFields) && $build = $build->setSortFields($sortFields);
|
||||
!empty($ignoreFields) && $build = $build->setIgnoreFields($ignoreFields);
|
||||
|
||||
foreach ($relations as $relation) {
|
||||
$build = $build->setRelation($relation['table'], $relation['foreignKey'], $relation['primaryKey'], $relation['modelFilename'], $relation['onlyFileds'],$relation['relationBindSelect']);
|
||||
}
|
||||
|
||||
$build = $build->render();
|
||||
$fileList = $build->getFileList();
|
||||
|
||||
if (!$delete) {
|
||||
$result = $build->create();
|
||||
if($force){
|
||||
$output->info(">>>>>>>>>>>>>>>");
|
||||
foreach ($fileList as $key => $val) {
|
||||
$output->info($key);
|
||||
}
|
||||
$output->info(">>>>>>>>>>>>>>>");
|
||||
$output->info("确定强制生成上方所有文件? 如果文件存在会直接覆盖。 请输入 'yes' 按回车键继续操作: ");
|
||||
$line = fgets(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'));
|
||||
if (trim($line) != 'yes') {
|
||||
throw new Exception("取消文件CURD生成操作");
|
||||
}
|
||||
}
|
||||
CliEcho::success('自动生成CURD成功');
|
||||
} else {
|
||||
$output->info(">>>>>>>>>>>>>>>");
|
||||
foreach ($fileList as $key => $val) {
|
||||
$output->info($key);
|
||||
}
|
||||
$output->info(">>>>>>>>>>>>>>>");
|
||||
$output->info("确定删除上方所有文件? 请输入 'yes' 按回车键继续操作: ");
|
||||
$line = fgets(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'));
|
||||
if (trim($line) != 'yes') {
|
||||
throw new Exception("取消删除文件操作");
|
||||
}
|
||||
$result = $build->delete();
|
||||
CliEcho::success('>>>>>>>>>>>>>>>');
|
||||
CliEcho::success('删除自动生成CURD文件成功');
|
||||
}
|
||||
CliEcho::success('>>>>>>>>>>>>>>>');
|
||||
foreach ($result as $vo) {
|
||||
CliEcho::success($vo);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
CliEcho::error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
75
app/common/command/Node.php
Normal file
75
app/common/command/Node.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\command;
|
||||
|
||||
|
||||
use app\admin\model\SystemNode;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use app\admin\service\NodeService;
|
||||
|
||||
class Node extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('node')
|
||||
->addOption('force', null, Option::VALUE_REQUIRED, '是否强制刷新', 0)
|
||||
->setDescription('系统节点刷新服务');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$force = $input->getOption('force');
|
||||
$output->writeln("========正在刷新节点服务:=====" . date('Y-m-d H:i:s'));
|
||||
$check = $this->refresh($force);
|
||||
$check !== true && $output->writeln("节点刷新失败:" . $check);
|
||||
$output->writeln("刷新完成:" . date('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
protected function refresh($force)
|
||||
{
|
||||
$nodeList = (new NodeService())->getNodelist();
|
||||
if (empty($nodeList)) {
|
||||
return true;
|
||||
}
|
||||
$model = new SystemNode();
|
||||
try {
|
||||
if ($force == 1) {
|
||||
$updateNodeList = $model->whereIn('node', array_column($nodeList, 'node'))->select();
|
||||
$formatNodeList = array_format_key($nodeList, 'node');
|
||||
foreach ($updateNodeList as $vo) {
|
||||
isset($formatNodeList[$vo['node']]) && $model->where('id', $vo['id'])->update([
|
||||
'title' => $formatNodeList[$vo['node']]['title'],
|
||||
'is_auth' => $formatNodeList[$vo['node']]['is_auth'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
$existNodeList = $model->field('node,title,type,is_auth')->select();
|
||||
foreach ($nodeList as $key => $vo) {
|
||||
foreach ($existNodeList as $v) {
|
||||
if ($vo['node'] == $v->node) {
|
||||
unset($nodeList[$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$model->insertAll($nodeList);
|
||||
} catch (\Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
58
app/common/command/OssStatic.php
Normal file
58
app/common/command/OssStatic.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\command;
|
||||
|
||||
|
||||
use EasyAdmin\console\CliEcho;
|
||||
use EasyAdmin\tool\CommonTool;
|
||||
use EasyAdmin\upload\driver\alioss\Oss;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class OssStatic extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('OssStatic')
|
||||
->setDescription('将静态资源上传到oss上');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$output->writeln("========正在上传静态资源到OSS上:========" . date('Y-m-d H:i:s'));
|
||||
$dir = root_path() . 'public' . DIRECTORY_SEPARATOR . 'static';
|
||||
$list = CommonTool::readDirAllFiles($dir);
|
||||
$uploadConfig = sysconfig('upload');
|
||||
$uploadPrefix = config('app.oss_static_prefix', 'oss_static_prefix');
|
||||
foreach ($list as $key => $val) {
|
||||
list($objectName, $filePath) = [$uploadPrefix . DIRECTORY_SEPARATOR . $key, $val];
|
||||
try {
|
||||
$upload = Oss::instance($uploadConfig)
|
||||
->save($objectName, $filePath);
|
||||
} catch (\Exception $e) {
|
||||
CliEcho::error('文件上传失败:' . $filePath . '。错误信息:' . $e->getMessage());
|
||||
continue;
|
||||
}
|
||||
if ($upload['save'] == true) {
|
||||
CliEcho::success('文件上传成功:' . $filePath . '。上传地址:' . $upload['url']);
|
||||
} else {
|
||||
CliEcho::error('文件上传失败:' . $filePath . '。错误信息:' . $upload['msg']);
|
||||
}
|
||||
}
|
||||
$output->writeln("========已完成静态资源上传到OSS上:========" . date('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
}
|
||||
28
app/common/constants/AdminConstant.php
Normal file
28
app/common/constants/AdminConstant.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\constants;
|
||||
|
||||
/**
|
||||
* 管理员常量
|
||||
* Class AdminConstant
|
||||
* @package app\common\constants
|
||||
*/
|
||||
class AdminConstant
|
||||
{
|
||||
|
||||
/**
|
||||
* 超级管理员,不受权限控制
|
||||
*/
|
||||
const SUPER_ADMIN_ID = 1;
|
||||
|
||||
}
|
||||
33
app/common/constants/MenuConstant.php
Normal file
33
app/common/constants/MenuConstant.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\constants;
|
||||
|
||||
/**
|
||||
* 菜单常量
|
||||
* Class MenuConstant
|
||||
* @package app\common\constants
|
||||
*/
|
||||
class MenuConstant
|
||||
{
|
||||
|
||||
/**
|
||||
* 首页的PID
|
||||
*/
|
||||
const HOME_PID = 99999999;
|
||||
|
||||
/**
|
||||
* 模块名前缀
|
||||
*/
|
||||
const MODULE_PREFIX = 'easyadmin_';
|
||||
|
||||
}
|
||||
293
app/common/controller/AdminController.php
Normal file
293
app/common/controller/AdminController.php
Normal file
@@ -0,0 +1,293 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace app\common\controller;
|
||||
|
||||
|
||||
use app\admin\service\ConfigService;
|
||||
use app\BaseController;
|
||||
use app\common\constants\AdminConstant;
|
||||
use app\common\service\AuthService;
|
||||
use EasyAdmin\tool\CommonTool;
|
||||
use think\facade\Env;
|
||||
use think\facade\View;
|
||||
use think\Model;
|
||||
|
||||
/**
|
||||
* Class AdminController
|
||||
* @package app\common\controller
|
||||
*/
|
||||
class AdminController extends BaseController
|
||||
{
|
||||
|
||||
use \app\common\traits\JumpTrait;
|
||||
|
||||
/**
|
||||
* 当前模型
|
||||
* @Model
|
||||
* @var object
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* 字段排序
|
||||
* @var array
|
||||
*/
|
||||
protected $sort = [
|
||||
'id' => '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;
|
||||
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
$this->layout && $this->app->view->engine()->layout($this->layout);
|
||||
$this->isDemo = Env::get('easyadmin.is_demo', false);
|
||||
$this->viewInit();
|
||||
$this->checkAuth();
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板变量赋值
|
||||
* @param string|array $name 模板变量
|
||||
* @param mixed $value 变量值
|
||||
* @return mixed
|
||||
*/
|
||||
public function assign($name, $value = null)
|
||||
{
|
||||
return $this->app->view->assign($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析和获取模板内容 用于输出
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetch($template = '', $vars = [])
|
||||
{
|
||||
return $this->app->view->fetch($template, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写验证规则
|
||||
* @param array $data
|
||||
* @param array|string $validate
|
||||
* @param array $message
|
||||
* @param bool $batch
|
||||
* @return array|bool|string|true
|
||||
*/
|
||||
public function validate(array $data, $validate, array $message = [], bool $batch = false)
|
||||
{
|
||||
try {
|
||||
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, null);
|
||||
$page = isset($get['page']) && !empty($get['page']) ? $get['page'] : 1;
|
||||
$limit = isset($get['limit']) && !empty($get['limit']) ? $get['limit'] : 15;
|
||||
$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 = [];
|
||||
|
||||
// 判断是否关联查询
|
||||
$tableName = CommonTool::humpToLine(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 ($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}"];
|
||||
break;
|
||||
case 'range':
|
||||
[$beginTime, $endTime] = explode(' - ', $val);
|
||||
$where[] = [$key, '>=', strtotime($beginTime)];
|
||||
$where[] = [$key, '<=', strtotime($endTime)];
|
||||
break;
|
||||
default:
|
||||
$where[] = [$key, $op, "%{$val}"];
|
||||
}
|
||||
}
|
||||
return [$page, $limit, $where, $excludes];
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉选择列表
|
||||
* @return \think\response\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() : ConfigService::getVersion(),
|
||||
];
|
||||
|
||||
View::assign($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测权限
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
private function checkAuth(){
|
||||
$adminConfig = config('admin');
|
||||
$adminId = session('admin.id');
|
||||
$expireTime = session('admin.expire_time');
|
||||
/** @var AuthService $authService */
|
||||
$authService = app(AuthService::class, ['adminId' => $adminId]);
|
||||
$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'));
|
||||
|
||||
// 判断是否登录过期
|
||||
if ($expireTime !== true && time() > $expireTime) {
|
||||
session('admin', null);
|
||||
$this->error('登录已过期,请重新登录', [], __url('admin/login/index'));
|
||||
}
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!in_array($currentController, $adminConfig['no_auth_controller']) &&
|
||||
!in_array($currentNode, $adminConfig['no_auth_node'])) {
|
||||
$check = $authService->checkNode($currentNode);
|
||||
!$check && $this->error('无权限访问');
|
||||
|
||||
// 判断是否为演示环境
|
||||
if(env('easyadmin.is_demo', false) && app()->request->isPost()){
|
||||
$this->error('演示环境下不允许修改');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 严格校验接口是否为POST请求
|
||||
*/
|
||||
protected function checkPostRequest(){
|
||||
if (!$this->request->isPost()) {
|
||||
$this->error("当前请求不合法!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
52
app/common/model/TimeModel.php
Normal file
52
app/common/model/TimeModel.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
|
||||
use think\Model;
|
||||
use think\model\concern\SoftDelete;
|
||||
|
||||
/**
|
||||
* 有关时间的模型
|
||||
* Class TimeModel
|
||||
* @package app\common\model
|
||||
*/
|
||||
class TimeModel extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* 自动时间戳类型
|
||||
* @var string
|
||||
*/
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
/**
|
||||
* 添加时间
|
||||
* @var string
|
||||
*/
|
||||
protected $createTime = 'create_time';
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
* @var string
|
||||
*/
|
||||
protected $updateTime = 'update_time';
|
||||
|
||||
/**
|
||||
* 软删除
|
||||
*/
|
||||
use SoftDelete;
|
||||
protected $deleteTime = false;
|
||||
|
||||
}
|
||||
215
app/common/service/AuthService.php
Normal file
215
app/common/service/AuthService.php
Normal file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\constants\AdminConstant;
|
||||
use EasyAdmin\tool\CommonTool;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 权限验证服务
|
||||
* Class AuthService
|
||||
* @package app\common\service
|
||||
*/
|
||||
class AuthService
|
||||
{
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
* @var null
|
||||
*/
|
||||
protected $adminId = null;
|
||||
|
||||
/**
|
||||
* 默认配置
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [
|
||||
'auth_on' => true, // 权限开关
|
||||
'system_admin' => 'system_admin', // 用户表
|
||||
'system_auth' => 'system_auth', // 权限表
|
||||
'system_node' => 'system_node', // 节点表
|
||||
'system_auth_node' => 'system_auth_node',// 权限-节点表
|
||||
];
|
||||
|
||||
/**
|
||||
* 管理员信息
|
||||
* @var array|\think\Model|null
|
||||
*/
|
||||
protected $adminInfo;
|
||||
|
||||
/**
|
||||
* 所有节点信息
|
||||
* @var array
|
||||
*/
|
||||
protected $nodeList;
|
||||
|
||||
/**
|
||||
* 管理员所有授权节点
|
||||
* @var array
|
||||
*/
|
||||
protected $adminNode;
|
||||
|
||||
/***
|
||||
* 构造方法
|
||||
* AuthService constructor.
|
||||
* @param null $adminId
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function __construct($adminId = null)
|
||||
{
|
||||
$this->adminId = $adminId;
|
||||
$this->adminInfo = $this->getAdminInfo();
|
||||
$this->nodeList = $this->getNodeList();
|
||||
$this->adminNode = $this->getAdminNode();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测检测权限
|
||||
* @param null $node
|
||||
* @return bool
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function checkNode($node = null)
|
||||
{
|
||||
// 判断是否为超级管理员
|
||||
if ($this->adminId == AdminConstant::SUPER_ADMIN_ID) {
|
||||
return true;
|
||||
}
|
||||
// 判断权限验证开关
|
||||
if ($this->config['auth_on'] == false) {
|
||||
return true;
|
||||
}
|
||||
// 判断是否需要获取当前节点
|
||||
if (empty($node)) {
|
||||
$node = $this->getCurrentNode();
|
||||
} else {
|
||||
$node = $this->parseNodeStr($node);
|
||||
}
|
||||
// 判断是否加入节点控制,优先获取缓存信息
|
||||
if (!isset($this->nodeList[$node])) {
|
||||
return false;
|
||||
}
|
||||
$nodeInfo = $this->nodeList[$node];
|
||||
if ($nodeInfo['is_auth'] == 0) {
|
||||
return true;
|
||||
}
|
||||
// 用户验证,优先获取缓存信息
|
||||
if (empty($this->adminInfo) || $this->adminInfo['status'] != 1 || empty($this->adminInfo['auth_ids'])) {
|
||||
return false;
|
||||
}
|
||||
// 判断该节点是否允许访问
|
||||
if (in_array($node, $this->adminNode)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前节点
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentNode()
|
||||
{
|
||||
$node = $this->parseNodeStr(request()->controller() . '/' . request()->action());
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前管理员所有节点
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getAdminNode()
|
||||
{
|
||||
$nodeList = [];
|
||||
$adminInfo = Db::name($this->config['system_admin'])
|
||||
->where([
|
||||
'id' => $this->adminId,
|
||||
'status' => 1,
|
||||
])->find();
|
||||
if (!empty($adminInfo) && !empty($adminInfo['auth_ids'])) {
|
||||
$buildAuthSql = Db::name($this->config['system_auth'])
|
||||
->distinct(true)
|
||||
->whereIn('id', $adminInfo['auth_ids'])
|
||||
->field('id')
|
||||
->buildSql(true);
|
||||
$buildAuthNodeSql = Db::name($this->config['system_auth_node'])
|
||||
->distinct(true)
|
||||
->where("auth_id IN {$buildAuthSql}")
|
||||
->field('node_id')
|
||||
->buildSql(true);
|
||||
$nodeList = Db::name($this->config['system_node'])
|
||||
->distinct(true)
|
||||
->where("id IN {$buildAuthNodeSql}")
|
||||
->column('node');
|
||||
}
|
||||
return $nodeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有节点信息
|
||||
* @time 2021-01-07
|
||||
* @return array
|
||||
* @author zhongshaofa <shaofa.zhong@happy-seed.com>
|
||||
*/
|
||||
public function getNodeList(){
|
||||
return Db::name($this->config['system_node'])
|
||||
->column('id,node,title,type,is_auth','node');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员信息
|
||||
* @time 2021-01-07
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @author zhongshaofa <shaofa.zhong@happy-seed.com>
|
||||
*/
|
||||
public function getAdminInfo(){
|
||||
return Db::name($this->config['system_admin'])
|
||||
->where('id', $this->adminId)
|
||||
->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线规则
|
||||
* @param string $node
|
||||
* @return string
|
||||
*/
|
||||
public function parseNodeStr($node)
|
||||
{
|
||||
$array = explode('/', $node);
|
||||
foreach ($array as $key => $val) {
|
||||
if ($key == 0) {
|
||||
$val = explode('.', $val);
|
||||
foreach ($val as &$vo) {
|
||||
$vo = CommonTool::humpToLine(lcfirst($vo));
|
||||
}
|
||||
$val = implode('.', $val);
|
||||
$array[$key] = $val;
|
||||
}
|
||||
}
|
||||
$node = implode('/', $array);
|
||||
return $node;
|
||||
}
|
||||
|
||||
}
|
||||
109
app/common/service/MenuService.php
Normal file
109
app/common/service/MenuService.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | PHP交流群: 763822524
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 https://mit-license.org
|
||||
// +----------------------------------------------------------------------
|
||||
// | github开源项目:https://github.com/zhongshaofa/EasyAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\service;
|
||||
|
||||
use app\common\constants\MenuConstant;
|
||||
use think\facade\Db;
|
||||
|
||||
class MenuService
|
||||
{
|
||||
|
||||
/**
|
||||
* 管理员ID
|
||||
* @var integer
|
||||
*/
|
||||
protected $adminId;
|
||||
|
||||
public function __construct($adminId)
|
||||
{
|
||||
$this->adminId = $adminId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取首页信息
|
||||
* @return array|\think\Model|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getHomeInfo()
|
||||
{
|
||||
$data = Db::name('system_menu')
|
||||
->field('title,icon,href')
|
||||
->where("delete_time is null")
|
||||
->where('pid', MenuConstant::HOME_PID)
|
||||
->find();
|
||||
!empty($data) && $data['href'] = __url($data['href']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后台菜单树信息
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getMenuTree()
|
||||
{
|
||||
/** @var AuthService $authService */
|
||||
$authServer = app(AuthService::class, ['adminId' => $this->adminId]);
|
||||
return $this->buildMenuChild(0, $this->getMenuData(),$authServer);
|
||||
}
|
||||
|
||||
private function buildMenuChild($pid, $menuList, AuthService $authServer)
|
||||
{
|
||||
$treeList = [];
|
||||
foreach ($menuList as &$v) {
|
||||
$check = empty($v['href']) ? true : $authServer->checkNode($v['href']);
|
||||
!empty($v['href']) && $v['href'] = __url($v['href']);
|
||||
if ($pid == $v['pid'] && $check) {
|
||||
$node = $v;
|
||||
$child = $this->buildMenuChild($v['id'], $menuList, $authServer);
|
||||
if (!empty($child)) {
|
||||
$node['child'] = $child;
|
||||
}
|
||||
if (!empty($v['href']) || !empty($child)) {
|
||||
$treeList[] = $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $treeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有菜单数据
|
||||
* @return \think\Collection
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
protected function getMenuData()
|
||||
{
|
||||
$menuData = Db::name('system_menu')
|
||||
->field('id,pid,title,icon,href,target')
|
||||
->where("delete_time is null")
|
||||
->where([
|
||||
['status', '=', '1'],
|
||||
['pid', '<>', MenuConstant::HOME_PID],
|
||||
])
|
||||
->order([
|
||||
'sort' => 'desc',
|
||||
'id' => 'asc',
|
||||
])
|
||||
->select();
|
||||
return $menuData;
|
||||
}
|
||||
|
||||
}
|
||||
59
app/common/tpl/dispatch_jump.tpl
Normal file
59
app/common/tpl/dispatch_jump.tpl
Normal file
@@ -0,0 +1,59 @@
|
||||
{__NOLAYOUT__}<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>跳转提示</title>
|
||||
<style type="text/css">
|
||||
*{box-sizing:border-box;margin:0;padding:0;font-family:Lantinghei SC,Open Sans,Arial,Hiragino Sans GB,Microsoft YaHei,"微软雅黑",STHeiti,WenQuanYi Micro Hei,SimSun,sans-serif;-webkit-font-smoothing:antialiased}
|
||||
body{padding:70px 0;background:#edf1f4;font-weight:400;font-size:1pc;-webkit-text-size-adjust:none;color:#333}
|
||||
a{outline:0;color:#3498db;text-decoration:none;cursor:pointer}
|
||||
.system-message{margin:20px 5%;padding:40px 20px;background:#fff;box-shadow:1px 1px 1px hsla(0,0%,39%,.1);text-align:center}
|
||||
.system-message h1{margin:0;margin-bottom:9pt;color:#444;font-weight:400;font-size:40px}
|
||||
.system-message .jump,.system-message .image{margin:20px 0;padding:0;padding:10px 0;font-weight:400}
|
||||
.system-message .jump{font-size:14px}
|
||||
.system-message .jump a{color:#333}
|
||||
.system-message p{font-size:9pt;line-height:20px}
|
||||
.system-message .btn{display:inline-block;margin-right:10px;width:138px;height:2pc;border:1px solid #44a0e8;border-radius:30px;color:#44a0e8;text-align:center;font-size:1pc;line-height:2pc;margin-bottom:5px;}
|
||||
.success .btn{border-color:#69bf4e;color:#69bf4e}
|
||||
.error .btn{border-color:#ff8992;color:#ff8992}
|
||||
.info .btn{border-color:#3498db;color:#3498db}
|
||||
.copyright p{width:100%;color:#919191;text-align:center;font-size:10px}
|
||||
.system-message .btn-grey{border-color:#bbb;color:#bbb}
|
||||
.clearfix:after{clear:both;display:block;visibility:hidden;height:0;content:"."}
|
||||
@media (max-width:768px){body {padding:20px 0;}}
|
||||
@media (max-width:480px){.system-message h1{font-size:30px;}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
$codeText = $code == 1 ? 'success' : ($code == 0 ? 'error' : 'info');
|
||||
?>
|
||||
<div class="system-message {$codeText}">
|
||||
<div class="image">
|
||||
<img src="/static/common/images/{$codeText}.svg" alt="" width="150" />
|
||||
</div>
|
||||
<h1><?php echo(strip_tags($msg));?></h1>
|
||||
<p class="jump">
|
||||
页面将在 <span id="wait"><?php echo($wait);?></span> 秒后自动跳转
|
||||
</p>
|
||||
<p class="clearfix">
|
||||
<a href="#" onClick="javascript :history.back(-1);" class="btn btn-grey">返回上一页</a>
|
||||
<a id="href" href="{$url}" class="btn btn-primary">立即跳转</a>
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
(function(){
|
||||
var wait = document.getElementById('wait'),
|
||||
href = document.getElementById('href').href;
|
||||
var interval = setInterval(function(){
|
||||
var time = --wait.innerHTML;
|
||||
if(time <= 0) {
|
||||
location.href = href;
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, 1000);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
101
app/common/tpl/think_exception.tpl
Normal file
101
app/common/tpl/think_exception.tpl
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
$cdnurl = function_exists('config') ? config('view_replace_str.__CDN__') : '';
|
||||
$publicurl = function_exists('config') ? config('view_replace_str.__PUBLIC__') : '/';
|
||||
$debug = function_exists('config') ? config('app_debug') : false;
|
||||
|
||||
$lang = [
|
||||
'An error occurred' => '发生错误',
|
||||
'Home' => '返回主页',
|
||||
'Feedback' => '反馈错误',
|
||||
'The page you are looking for is temporarily unavailable' => '你所浏览的页面暂时无法访问',
|
||||
'You can return to the previous page and try again' => '你可以返回上一页重试,或直接向我们反馈错误报告'
|
||||
];
|
||||
|
||||
$langSet = '';
|
||||
|
||||
if (isset($_GET['lang'])) {
|
||||
$langSet = strtolower($_GET['lang']);
|
||||
} elseif (isset($_COOKIE['think_var'])) {
|
||||
$langSet = strtolower($_COOKIE['think_var']);
|
||||
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
|
||||
$langSet = strtolower($matches[1]);
|
||||
}
|
||||
$langSet = $langSet && in_array($langSet, ['zh-cn', 'en']) ? $langSet : 'zh-cn';
|
||||
$langSet == 'en' && $lang = array_combine(array_keys($lang), array_keys($lang));
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<title><?=$lang['An error occurred']?></title>
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<link rel="shortcut icon" href="<?php echo $cdnurl;?>/assets/img/favicon.ico" />
|
||||
<style>
|
||||
* {-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;}
|
||||
html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,abbr,address,cite,code,del,dfn,em,img,ins,kbd,q,samp,small,strong,sub,sup,var,b,i,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,figcaption,figure,footer,header,hgroup,menu,nav,section,summary,time,mark,audio,video {margin:0;padding:0;border:0;outline:0;vertical-align:baseline;background:transparent;}
|
||||
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section {display:block;}
|
||||
html {font-size:16px;line-height:24px;width:100%;height:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;overflow-y:scroll;overflow-x:hidden;}
|
||||
img {vertical-align:middle;max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic;}
|
||||
body {min-height:100%;background:#edf1f4;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:"Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",微软雅黑,Arial,sans-serif;}
|
||||
.clearfix {clear:both;zoom:1;}
|
||||
.clearfix:before,.clearfix:after {content:"\0020";display:block;height:0;visibility:hidden;}
|
||||
.clearfix:after {clear:both;}
|
||||
body.error-page-wrapper,.error-page-wrapper.preview {background-position:center center;background-repeat:no-repeat;background-size:cover;position:relative;}
|
||||
.error-page-wrapper .content-container {border-radius:2px;text-align:center;box-shadow:1px 1px 1px rgba(99,99,99,0.1);padding:50px;background-color:#fff;width:100%;max-width:560px;position:absolute;left:50%;top:50%;margin-top:-220px;margin-left:-280px;}
|
||||
.error-page-wrapper .content-container.in {left:0px;opacity:1;}
|
||||
.error-page-wrapper .head-line {transition:color .2s linear;font-size:40px;line-height:60px;letter-spacing:-1px;margin-bottom:20px;color:#777;}
|
||||
.error-page-wrapper .subheader {transition:color .2s linear;font-size:32px;line-height:46px;color:#494949;}
|
||||
.error-page-wrapper .hr {height:1px;background-color:#eee;width:80%;max-width:350px;margin:25px auto;}
|
||||
.error-page-wrapper .context {transition:color .2s linear;font-size:16px;line-height:27px;color:#aaa;}
|
||||
.error-page-wrapper .context p {margin:0;}
|
||||
.error-page-wrapper .context p:nth-child(n+2) {margin-top:16px;}
|
||||
.error-page-wrapper .buttons-container {margin-top:35px;overflow:hidden;}
|
||||
.error-page-wrapper .buttons-container a {transition:text-indent .2s ease-out,color .2s linear,background-color .2s linear;text-indent:0px;font-size:14px;text-transform:uppercase;text-decoration:none;color:#fff;background-color:#2ecc71;border-radius:99px;padding:8px 0 8px;text-align:center;display:inline-block;overflow:hidden;position:relative;width:45%;}
|
||||
.error-page-wrapper .buttons-container a:hover {text-indent:15px;}
|
||||
.error-page-wrapper .buttons-container a:nth-child(1) {float:left;}
|
||||
.error-page-wrapper .buttons-container a:nth-child(2) {float:right;}
|
||||
@media screen and (max-width:580px) {
|
||||
.error-page-wrapper {padding:30px 5%;}
|
||||
.error-page-wrapper .content-container {padding:37px;position:static;left:0;margin-top:0;margin-left:0;}
|
||||
.error-page-wrapper .head-line {font-size:36px;}
|
||||
.error-page-wrapper .subheader {font-size:27px;line-height:37px;}
|
||||
.error-page-wrapper .hr {margin:30px auto;width:215px;}
|
||||
}
|
||||
@media screen and (max-width:450px) {
|
||||
.error-page-wrapper {padding:30px;}
|
||||
.error-page-wrapper .head-line {font-size:32px;}
|
||||
.error-page-wrapper .hr {margin:25px auto;width:180px;}
|
||||
.error-page-wrapper .context {font-size:15px;line-height:22px;}
|
||||
.error-page-wrapper .context p:nth-child(n+2) {margin-top:10px;}
|
||||
.error-page-wrapper .buttons-container {margin-top:29px;}
|
||||
.error-page-wrapper .buttons-container a {float:none !important;width:65%;margin:0 auto;font-size:13px;padding:9px 0;}
|
||||
.error-page-wrapper .buttons-container a:nth-child(2) {margin-top:12px;}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="error-page-wrapper">
|
||||
<div class="content-container">
|
||||
<div class="head-line">
|
||||
<img src="/static/common/images/error.svg" alt="" width="150" />
|
||||
</div>
|
||||
<div class="subheader">
|
||||
<?=$debug?$message:$lang['The page you are looking for is temporarily unavailable']?>
|
||||
</div>
|
||||
<div class="hr"></div>
|
||||
<div class="context">
|
||||
|
||||
<p>
|
||||
<?=$lang['You can return to the previous page and try again']?>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<div class="buttons-container">
|
||||
<a href="/"><?=$lang['Home']?></a>
|
||||
<a href="/"><?=$lang['Feedback']?></a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
141
app/common/traits/JumpTrait.php
Normal file
141
app/common/traits/JumpTrait.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\traits;
|
||||
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* Trait JumpTrait
|
||||
* @package app\common\traits
|
||||
*/
|
||||
trait JumpTrait
|
||||
{
|
||||
|
||||
/**
|
||||
* 操作成功跳转的快捷方法
|
||||
* @access protected
|
||||
* @param mixed $msg 提示信息
|
||||
* @param mixed $data 返回的数据
|
||||
* @param string $url 跳转的 URL 地址
|
||||
* @param int $wait 跳转等待时间
|
||||
* @param array $header 发送的 Header 信息
|
||||
* @return void
|
||||
* @throws HttpResponseException
|
||||
*/
|
||||
protected function success($msg = '', $data = '', $url = null, $wait = 3, array $header = [])
|
||||
{
|
||||
if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
|
||||
$url = $_SERVER["HTTP_REFERER"];
|
||||
} elseif ($url) {
|
||||
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url)->__toString();
|
||||
}
|
||||
|
||||
$result = [
|
||||
'code' => 1,
|
||||
'msg' => $msg,
|
||||
'data' => $data,
|
||||
'url' => $url,
|
||||
'wait' => $wait,
|
||||
];
|
||||
|
||||
$type = $this->getResponseType();
|
||||
if ($type == 'html') {
|
||||
$response = view(app('config')->get('app.dispatch_success_tmpl'), $result);
|
||||
} elseif ($type == 'json') {
|
||||
$response = json($result);
|
||||
}
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作错误跳转的快捷方法
|
||||
* @access protected
|
||||
* @param mixed $msg 提示信息
|
||||
* @param mixed $data 返回的数据
|
||||
* @param string $url 跳转的 URL 地址
|
||||
* @param int $wait 跳转等待时间
|
||||
* @param array $header 发送的 Header 信息
|
||||
* @return void
|
||||
* @throws HttpResponseException
|
||||
*/
|
||||
protected function error($msg = '', $data = '', $url = null, $wait = 3, array $header = [])
|
||||
{
|
||||
if (is_null($url)) {
|
||||
$url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
|
||||
} elseif ($url) {
|
||||
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url)->__toString();
|
||||
}
|
||||
|
||||
$type = $this->getResponseType();
|
||||
$result = [
|
||||
'code' => 0,
|
||||
'msg' => $msg,
|
||||
'data' => $data,
|
||||
'url' => $url,
|
||||
'wait' => $wait,
|
||||
];
|
||||
if ($type == 'html') {
|
||||
$response = view(app('config')->get('app.dispatch_error_tmpl'), $result);
|
||||
} elseif ($type == 'json') {
|
||||
$response = json($result);
|
||||
}
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回封装后的 API 数据到客户端
|
||||
* @access protected
|
||||
* @param mixed $data 要返回的数据
|
||||
* @param int $code 返回的 code
|
||||
* @param mixed $msg 提示信息
|
||||
* @param string $type 返回数据格式
|
||||
* @param array $header 发送的 Header 信息
|
||||
* @return void
|
||||
* @throws HttpResponseException
|
||||
*/
|
||||
protected function result($data, $code = 0, $msg = '', $type = '', array $header = [])
|
||||
{
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'msg' => $msg,
|
||||
'time' => time(),
|
||||
'data' => $data,
|
||||
];
|
||||
$type = $type ?: $this->getResponseType();
|
||||
$response = Response::create($result, $type)->header($header);
|
||||
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL 重定向
|
||||
* @access protected
|
||||
* @param string $url 跳转的 URL 表达式
|
||||
* @param array|int $params 其它 URL 参数
|
||||
* @param int $code http code
|
||||
* @param array $with 隐式传参
|
||||
* @return void
|
||||
* @throws HttpResponseException
|
||||
*/
|
||||
protected function redirect($url = [], $params = [], $code = 302)
|
||||
{
|
||||
if (is_integer($params)) {
|
||||
$code = $params;
|
||||
$params = [];
|
||||
}
|
||||
|
||||
$response = Response::create($url, 'redirect', $code);
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的 response 输出类型
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function getResponseType()
|
||||
{
|
||||
return (request()->isJson() || request()->isAjax() || request()->isPost()) ? 'json' : 'html';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user