初始化提交
This commit is contained in:
134
app/admin/controller/Auth.php
Normal file
134
app/admin/controller/Auth.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemAuth;
|
||||
use think\admin\model\SystemNode;
|
||||
use think\admin\Plugin;
|
||||
use think\admin\service\AdminService;
|
||||
|
||||
/**
|
||||
* 系统权限管理
|
||||
* @class Auth
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Auth extends Controller
|
||||
{
|
||||
/**
|
||||
* 系统权限管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
SystemAuth::mQuery()->layTable(function () {
|
||||
$this->title = '系统权限管理';
|
||||
}, static function (QueryHelper $query) {
|
||||
$query->like('title,desc')->equal('status,utype')->dateBetween('create_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改权限状态
|
||||
* @auth true
|
||||
*/
|
||||
public function state()
|
||||
{
|
||||
SystemAuth::mSave($this->_vali([
|
||||
'status.in:0,1' => '状态值范围异常!',
|
||||
'status.require' => '状态值不能为空!',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统权限
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
SystemAuth::mDelete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加系统权限
|
||||
* @auth true
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
SystemAuth::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑系统权限
|
||||
* @auth true
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
SystemAuth::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单后置数据处理
|
||||
* @param array $data
|
||||
*/
|
||||
protected function _form_filter(array $data)
|
||||
{
|
||||
if ($this->request->isGet()) {
|
||||
$this->title = empty($data['title']) ? "添加访问授权" : "编辑【{$data['title']}】授权";
|
||||
} elseif ($this->request->post('action') === 'json') {
|
||||
if ($this->app->isDebug()) AdminService::clear();
|
||||
$ztree = AdminService::getTree(empty($data['id']) ? [] : SystemNode::mk()->where(['auth' => $data['id']])->column('node'));
|
||||
usort($ztree, static function ($a, $b) {
|
||||
if (explode('-', $a['node'])[0] !== explode('-', $b['node'])[0]) {
|
||||
if (stripos($a['node'], 'plugin-') === 0) return 1;
|
||||
}
|
||||
return $a['node'] === $b['node'] ? 0 : ($a['node'] > $b['node'] ? 1 : -1);
|
||||
});
|
||||
[$ps, $cs] = [Plugin::get(), (array)$this->app->config->get('app.app_names', [])];
|
||||
foreach ($ztree as &$n) $n['title'] = lang($cs[$n['node']] ?? (($ps[$n['node']] ?? [])['name'] ?? $n['title']));
|
||||
$this->success('获取权限节点成功!', $ztree);
|
||||
} elseif (empty($data['nodes'])) {
|
||||
$this->error('未配置功能节点!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点更新处理
|
||||
* @param boolean $state
|
||||
* @param array $post
|
||||
* @return void
|
||||
*/
|
||||
protected function _form_result(bool $state, array $post)
|
||||
{
|
||||
if ($state && $this->request->post('action') === 'save') {
|
||||
[$map, $data] = [['auth' => $post['id']], []];
|
||||
foreach ($post['nodes'] ?? [] as $node) $data[] = $map + ['node' => $node];
|
||||
SystemNode::mk()->where($map)->delete();
|
||||
count($data) > 0 && SystemNode::mk()->insertAll($data);
|
||||
sysoplog('系统权限管理', "配置系统权限[{$map['auth']}]授权成功");
|
||||
$this->success('权限修改成功!', 'javascript:history.back()');
|
||||
}
|
||||
}
|
||||
}
|
||||
113
app/admin/controller/Base.php
Normal file
113
app/admin/controller/Base.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemBase;
|
||||
|
||||
/**
|
||||
* 数据字典管理
|
||||
* @class Base
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Base extends Controller
|
||||
{
|
||||
/**
|
||||
* 数据字典管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
SystemBase::mQuery()->layTable(function () {
|
||||
$this->title = '数据字典管理';
|
||||
$this->types = SystemBase::types();
|
||||
$this->type = $this->get['type'] ?? ($this->types[0] ?? '-');
|
||||
}, static function (QueryHelper $query) {
|
||||
$query->where(['deleted' => 0])->equal('type');
|
||||
$query->like('code,name,status')->dateBetween('create_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加数据字典
|
||||
* @auth true
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
SystemBase::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑数据字典
|
||||
* @auth true
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
SystemBase::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单数据处理
|
||||
* @param array $data
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
protected function _form_filter(array &$data)
|
||||
{
|
||||
if ($this->request->isGet()) {
|
||||
$this->types = SystemBase::types();
|
||||
$this->types[] = '--- ' . lang('新增类型') . ' ---';
|
||||
$this->type = $this->get['type'] ?? ($this->types[0] ?? '-');
|
||||
} else {
|
||||
$map = [];
|
||||
$map[] = ['deleted', '=', 0];
|
||||
$map[] = ['code', '=', $data['code']];
|
||||
$map[] = ['type', '=', $data['type']];
|
||||
$map[] = ['id', '<>', $data['id'] ?? 0];
|
||||
if (SystemBase::mk()->where($map)->count() > 0) {
|
||||
$this->error("数据编码已经存在!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据状态
|
||||
* @auth true
|
||||
*/
|
||||
public function state()
|
||||
{
|
||||
SystemBase::mSave($this->_vali([
|
||||
'status.in:0,1' => '状态值范围异常!',
|
||||
'status.require' => '状态值不能为空!',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据记录
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
SystemBase::mDelete();
|
||||
}
|
||||
}
|
||||
146
app/admin/controller/Config.php
Normal file
146
app/admin/controller/Config.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\Plugin;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\service\ModuleService;
|
||||
use think\admin\service\RuntimeService;
|
||||
use think\admin\service\SystemService;
|
||||
use think\admin\Storage;
|
||||
use think\admin\storage\AliossStorage;
|
||||
use think\admin\storage\QiniuStorage;
|
||||
use think\admin\storage\TxcosStorage;
|
||||
|
||||
/**
|
||||
* 系统参数配置
|
||||
* @class Config
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Config extends Controller
|
||||
{
|
||||
const themes = [
|
||||
'default' => '默认色0',
|
||||
'white' => '简约白0',
|
||||
'red-1' => '玫瑰红1',
|
||||
'blue-1' => '深空蓝1',
|
||||
'green-1' => '小草绿1',
|
||||
'black-1' => '经典黑1',
|
||||
'red-2' => '玫瑰红2',
|
||||
'blue-2' => '深空蓝2',
|
||||
'green-2' => '小草绿2',
|
||||
'black-2' => '经典黑2',
|
||||
];
|
||||
|
||||
/**
|
||||
* 系统参数配置
|
||||
* @auth true
|
||||
* @menu true
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->title = '系统参数配置';
|
||||
$this->files = Storage::types();
|
||||
$this->plugins = Plugin::get(null, true);
|
||||
$this->issuper = AdminService::isSuper();
|
||||
$this->systemid = ModuleService::getRunVar('uni');
|
||||
$this->framework = ModuleService::getLibrarys('topthink/framework');
|
||||
$this->thinkadmin = ModuleService::getLibrarys('zoujingli/think-library');
|
||||
if (AdminService::isSuper() && $this->app->session->get('user.password') === md5('admin')) {
|
||||
$url = url('admin/index/pass', ['id' => AdminService::getUserId()]);
|
||||
$this->showErrorMessage = lang("超级管理员账号的密码未修改,建议立即<a data-modal='%s'>修改密码</a>!", [$url]);
|
||||
}
|
||||
uasort($this->plugins, static function ($a, $b) {
|
||||
if ($a['space'] === $b['space']) return 0;
|
||||
return $a['space'] > $b['space'] ? 1 : -1;
|
||||
});
|
||||
$this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改系统参数
|
||||
* @auth true
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function system()
|
||||
{
|
||||
if ($this->request->isGet()) {
|
||||
$this->title = '修改系统参数';
|
||||
$this->themes = static::themes;
|
||||
$this->fetch();
|
||||
} else {
|
||||
$post = $this->request->post();
|
||||
// 修改网站后台入口路径
|
||||
if (!empty($post['xpath'])) {
|
||||
if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $post['xpath'])) {
|
||||
$this->error('后台入口格式错误!');
|
||||
}
|
||||
if ($post['xpath'] !== 'admin') {
|
||||
if (is_dir(syspath("app/{$post['xpath']}")) || !empty(Plugin::get($post['xpath']))) {
|
||||
$this->error(lang('已存在 %s 应用!', [$post['xpath']]));
|
||||
}
|
||||
}
|
||||
RuntimeService::set(null, [$post['xpath'] => 'admin']);
|
||||
}
|
||||
// 修改网站 ICON 图标,替换 public/favicon.ico
|
||||
if (preg_match('#^https?://#', $post['site_icon'] ?? '')) try {
|
||||
SystemService::setFavicon($post['site_icon'] ?? '');
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
}
|
||||
// 数据数据到系统配置表
|
||||
foreach ($post as $k => $v) sysconf($k, $v);
|
||||
sysoplog('系统配置管理', "修改系统参数成功");
|
||||
$this->success('数据保存成功!', admuri('admin/config/index'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改文件存储
|
||||
* @auth true
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function storage()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
if ($this->request->isGet()) {
|
||||
$this->type = input('type', 'local');
|
||||
if ($this->type === 'alioss') {
|
||||
$this->points = AliossStorage::region();
|
||||
} elseif ($this->type === 'qiniu') {
|
||||
$this->points = QiniuStorage::region();
|
||||
} elseif ($this->type === 'txcos') {
|
||||
$this->points = TxcosStorage::region();
|
||||
}
|
||||
$this->fetch("storage-{$this->type}");
|
||||
} else {
|
||||
$post = $this->request->post();
|
||||
if (!empty($post['storage']['allow_exts'])) {
|
||||
$deny = ['sh', 'asp', 'bat', 'cmd', 'exe', 'php'];
|
||||
$exts = array_unique(str2arr(strtolower($post['storage']['allow_exts'])));
|
||||
if (count(array_intersect($deny, $exts)) > 0) $this->error('禁止上传可执行的文件!');
|
||||
$post['storage']['allow_exts'] = join(',', $exts);
|
||||
}
|
||||
foreach ($post as $name => $value) sysconf($name, $value);
|
||||
sysoplog('系统配置管理', "修改系统存储参数");
|
||||
$this->success('修改文件存储成功!');
|
||||
}
|
||||
}
|
||||
}
|
||||
118
app/admin/controller/File.php
Normal file
118
app/admin/controller/File.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemFile;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\Storage;
|
||||
|
||||
/**
|
||||
* 系统文件管理
|
||||
* @class File
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class File extends Controller
|
||||
{
|
||||
/**
|
||||
* 存储类型
|
||||
* @var array
|
||||
*/
|
||||
protected $types;
|
||||
|
||||
/**
|
||||
* 控制器初始化
|
||||
* @return void
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
$this->types = Storage::types();
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统文件管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
SystemFile::mQuery()->layTable(function () {
|
||||
$this->title = '系统文件管理';
|
||||
$this->xexts = SystemFile::mk()->distinct()->column('xext');
|
||||
}, static function (QueryHelper $query) {
|
||||
$query->like('name,hash,xext')->equal('type')->dateBetween('create_at');
|
||||
$query->where(['issafe' => 0, 'status' => 2, 'uuid' => AdminService::getUserId()]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据列表处理
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
protected function _page_filter(array &$data)
|
||||
{
|
||||
foreach ($data as &$vo) {
|
||||
$vo['ctype'] = $this->types[$vo['type']] ?? $vo['type'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑系统文件
|
||||
* @auth true
|
||||
* @return void
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
SystemFile::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统文件
|
||||
* @auth true
|
||||
* @return void
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
if (!AdminService::isSuper()) {
|
||||
$where = ['uuid' => AdminService::getUserId()];
|
||||
}
|
||||
SystemFile::mDelete('', $where ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理重复文件
|
||||
* @auth true
|
||||
* @return void
|
||||
* @throws \think\db\exception\DbException
|
||||
*/
|
||||
public function distinct()
|
||||
{
|
||||
$map = ['uuid' => AdminService::getUserId()];
|
||||
$db1 = SystemFile::mk()->fieldRaw('max(id) id')->where($map)->group('type,xkey');
|
||||
$db2 = $this->app->db->table($db1->buildSql())->alias('dt')->field('id');
|
||||
SystemFile::mk()->whereRaw("id not in {$db2->buildSql()}")->delete();
|
||||
SystemFile::mk()->where($map)->where(['status' => 1])->delete();
|
||||
$this->success('清理重复文件成功!');
|
||||
}
|
||||
}
|
||||
157
app/admin/controller/Index.php
Normal file
157
app/admin/controller/Index.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\model\SystemUser;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\service\MenuService;
|
||||
|
||||
/**
|
||||
* 后台界面入口
|
||||
* @class Index
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Index extends Controller
|
||||
{
|
||||
/**
|
||||
* 显示后台首页
|
||||
* @throws \think\admin\Exception
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
/*! 根据运行模式刷新权限 */
|
||||
AdminService::apply($this->app->isDebug());
|
||||
/*! 读取当前用户权限菜单树 */
|
||||
$this->menus = MenuService::getTree();
|
||||
/*! 判断当前用户的登录状态 */
|
||||
$this->login = AdminService::isLogin();
|
||||
/*! 菜单为空且未登录跳转到登录页 */
|
||||
if (empty($this->menus) && empty($this->login)) {
|
||||
$this->redirect(sysuri('admin/login/index'));
|
||||
} else {
|
||||
$this->title = '系统管理后台';
|
||||
$this->super = AdminService::isSuper();
|
||||
$this->theme = AdminService::getUserTheme();
|
||||
$this->fetch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台主题切换
|
||||
* @login true
|
||||
* @return void
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function theme()
|
||||
{
|
||||
if ($this->request->isGet()) {
|
||||
$this->theme = AdminService::getUserTheme();
|
||||
$this->themes = Config::themes;
|
||||
$this->fetch();
|
||||
} else {
|
||||
$data = $this->_vali(['site_theme.require' => '主题名称不能为空!']);
|
||||
if (AdminService::setUserTheme($data['site_theme'])) {
|
||||
$this->success('主题配置保存成功!');
|
||||
} else {
|
||||
$this->error('主题配置保存失败!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户资料
|
||||
* @login true
|
||||
* @param mixed $id 用户ID
|
||||
*/
|
||||
public function info($id = 0)
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
if (AdminService::getUserId() === intval($id)) {
|
||||
SystemUser::mForm('user/form', 'id', [], ['id' => $id]);
|
||||
} else {
|
||||
$this->error('只能修改自己的资料!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 资料修改表单处理
|
||||
* @param array $data
|
||||
*/
|
||||
protected function _info_form_filter(array &$data)
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
unset($data['username'], $data['authorize']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 资料修改结果处理
|
||||
* @param bool $status
|
||||
*/
|
||||
protected function _info_form_result(bool $status)
|
||||
{
|
||||
if ($status) {
|
||||
$this->success('用户资料修改成功!', 'javascript:location.reload()');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改当前用户密码
|
||||
* @login true
|
||||
* @param mixed $id
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function pass($id = 0)
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
if (AdminService::getUserId() !== intval($id)) {
|
||||
$this->error('禁止修改他人密码!');
|
||||
}
|
||||
if ($this->app->request->isGet()) {
|
||||
$this->verify = true;
|
||||
SystemUser::mForm('user/pass', 'id', [], ['id' => $id]);
|
||||
} else {
|
||||
$data = $this->_vali([
|
||||
'password.require' => '登录密码不能为空!',
|
||||
'repassword.require' => '重复密码不能为空!',
|
||||
'oldpassword.require' => '旧的密码不能为空!',
|
||||
'password.confirm:repassword' => '两次输入的密码不一致!',
|
||||
]);
|
||||
$user = SystemUser::mk()->find($id);
|
||||
if (empty($user)) $this->error('用户不存在!');
|
||||
if (md5($data['oldpassword']) !== $user['password']) {
|
||||
$this->error('旧密码验证失败,请重新输入!');
|
||||
}
|
||||
if ($user->save(['password' => md5($data['password'])])) {
|
||||
sysoplog('系统用户管理', "修改用户[{$user['id']}]密码成功");
|
||||
// 修改密码同步事件处理
|
||||
$this->app->event->trigger('PluginAdminChangePassword', [
|
||||
'uuid' => intval($user['id']), 'pass' => $data['password']
|
||||
]);
|
||||
$this->success('密码修改成功,下次请使用新密码登录!', '');
|
||||
} else {
|
||||
$this->error('密码修改失败,请稍候再试!');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
137
app/admin/controller/Login.php
Normal file
137
app/admin/controller/Login.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\extend\CodeExtend;
|
||||
use think\admin\model\SystemUser;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\service\CaptchaService;
|
||||
use think\admin\service\RuntimeService;
|
||||
use think\admin\service\SystemService;
|
||||
|
||||
/**
|
||||
* 用户登录管理
|
||||
* @class Login
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Login extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* 后台登录入口
|
||||
* @return void
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->app->request->isGet()) {
|
||||
if (AdminService::isLogin()) {
|
||||
$this->redirect(sysuri('admin/index/index'));
|
||||
} else {
|
||||
// 加载登录模板
|
||||
$this->title = '系统登录';
|
||||
// 登录验证令牌
|
||||
$this->captchaType = 'LoginCaptcha';
|
||||
$this->captchaToken = CodeExtend::uuid();
|
||||
// 当前运行模式
|
||||
$this->runtimeMode = RuntimeService::check();
|
||||
// 后台背景处理
|
||||
$images = str2arr(sysconf('login_image|raw') ?: '', '|');
|
||||
if (empty($images)) $images = [
|
||||
SystemService::uri('/static/theme/img/login/bg1.jpg'),
|
||||
SystemService::uri('/static/theme/img/login/bg2.jpg'),
|
||||
];
|
||||
$this->loginStyle = sprintf('style="background-image:url(%s)" data-bg-transition="%s"', $images[0], join(',', $images));
|
||||
// 更新后台主域名,用于部分无法获取域名的场景调用
|
||||
if ($this->request->domain() !== sysconf('base.site_host|raw')) {
|
||||
sysconf('base.site_host', $this->request->domain());
|
||||
}
|
||||
$this->fetch();
|
||||
}
|
||||
} else {
|
||||
$data = $this->_vali([
|
||||
'username.require' => '登录账号不能为空!',
|
||||
'username.min:4' => '账号不能少于4位字符!',
|
||||
'password.require' => '登录密码不能为空!',
|
||||
'password.min:4' => '密码不能少于4位字符!',
|
||||
'verify.require' => '图形验证码不能为空!',
|
||||
'uniqid.require' => '图形验证标识不能为空!',
|
||||
]);
|
||||
if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
|
||||
$this->error('图形验证码验证失败,请重新输入!');
|
||||
}
|
||||
/*! 用户信息验证 */
|
||||
$map = ['username' => $data['username'], 'is_deleted' => 0];
|
||||
$user = SystemUser::mk()->where($map)->findOrEmpty();
|
||||
if ($user->isEmpty()) {
|
||||
$this->app->session->set('LoginInputSessionError', true);
|
||||
$this->error('登录账号或密码错误,请重新输入!');
|
||||
}
|
||||
if (empty($user['status'])) {
|
||||
$this->app->session->set('LoginInputSessionError', true);
|
||||
$this->error('账号已经被禁用,请联系管理员!');
|
||||
}
|
||||
if (md5("{$user['password']}{$data['uniqid']}") !== $data['password']) {
|
||||
$this->app->session->set('LoginInputSessionError', true);
|
||||
$this->error('登录账号或密码错误,请重新输入!');
|
||||
}
|
||||
$user->hidden(['sort', 'status', 'password', 'is_deleted']);
|
||||
$this->app->session->set('user', $user->toArray());
|
||||
$this->app->session->delete('LoginInputSessionError');
|
||||
// 更新登录次数
|
||||
$user->where(['id' => $user->getAttr('id')])->inc('login_num')->update([
|
||||
'login_at' => date('Y-m-d H:i:s'), 'login_ip' => $this->app->request->ip(),
|
||||
]);
|
||||
// 刷新用户权限
|
||||
AdminService::apply(true);
|
||||
sysoplog('系统用户登录', '登录系统后台成功');
|
||||
$this->success('登录成功', sysuri('admin/index/index'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
* @return void
|
||||
*/
|
||||
public function captcha()
|
||||
{
|
||||
$input = $this->_vali([
|
||||
'type.require' => '类型不能为空!',
|
||||
'token.require' => '标识不能为空!',
|
||||
]);
|
||||
$image = CaptchaService::instance()->initialize();
|
||||
$captcha = ['image' => $image->getData(), 'uniqid' => $image->getUniqid()];
|
||||
// 未发生异常时,直接返回验证码内容
|
||||
if (!$this->app->session->get('LoginInputSessionError')) {
|
||||
$captcha['code'] = $image->getCode();
|
||||
}
|
||||
$this->success('生成验证码成功', $captcha);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* @return void
|
||||
*/
|
||||
public function out()
|
||||
{
|
||||
$this->app->session->destroy();
|
||||
$this->success('退出登录成功!', sysuri('admin/login/index'));
|
||||
}
|
||||
}
|
||||
147
app/admin/controller/Menu.php
Normal file
147
app/admin/controller/Menu.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\extend\DataExtend;
|
||||
use think\admin\model\SystemMenu;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\service\MenuService;
|
||||
use think\admin\service\NodeService;
|
||||
|
||||
/**
|
||||
* 系统菜单管理
|
||||
* @class Menu
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Menu extends Controller
|
||||
{
|
||||
/**
|
||||
* 系统菜单管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->title = '系统菜单管理';
|
||||
$this->type = $this->get['type'] ?? 'index';
|
||||
SystemMenu::mQuery()->layTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表数据处理
|
||||
* @param array $data
|
||||
*/
|
||||
protected function _index_page_filter(array &$data)
|
||||
{
|
||||
$data = DataExtend::arr2tree($data);
|
||||
// 回收站过滤有效菜单
|
||||
if ($this->type === 'recycle') foreach ($data as $k1 => &$p1) {
|
||||
if (!empty($p1['sub'])) foreach ($p1['sub'] as $k2 => &$p2) {
|
||||
if (!empty($p2['sub'])) foreach ($p2['sub'] as $k3 => $p3) {
|
||||
if ($p3['status'] > 0) unset($p2['sub'][$k3]);
|
||||
}
|
||||
if (empty($p2['sub']) && ($p2['url'] === '#' or $p2['status'] > 0)) unset($p1['sub'][$k2]);
|
||||
}
|
||||
if (empty($p1['sub']) && ($p1['url'] === '#' or $p1['status'] > 0)) unset($data[$k1]);
|
||||
}
|
||||
// 菜单数据树数据变平化
|
||||
$data = DataExtend::arr2table($data);
|
||||
foreach ($data as &$vo) {
|
||||
if ($vo['url'] !== '#' && !preg_match('/^(https?:)?(\/\/|\\\\)/i', $vo['url'])) {
|
||||
$vo['url'] = trim(url($vo['url']) . ($vo['params'] ? "?{$vo['params']}" : ''), '\\/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加系统菜单
|
||||
* @auth true
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
SystemMenu::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑系统菜单
|
||||
* @auth true
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
SystemMenu::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单数据处理
|
||||
* @param array $vo
|
||||
*/
|
||||
protected function _form_filter(array &$vo)
|
||||
{
|
||||
if ($this->request->isGet()) {
|
||||
$debug = $this->app->isDebug();
|
||||
/* 清理权限节点 */
|
||||
$debug && AdminService::clear();
|
||||
/* 读取系统功能节点 */
|
||||
$this->auths = [];
|
||||
$this->nodes = MenuService::getList($debug);
|
||||
foreach (NodeService::getMethods($debug) as $node => $item) {
|
||||
if ($item['isauth'] && substr_count($node, '/') >= 2) {
|
||||
$this->auths[] = ['node' => $node, 'title' => $item['title']];
|
||||
}
|
||||
}
|
||||
/* 选择自己上级菜单 */
|
||||
$vo['pid'] = $vo['pid'] ?? input('pid', '0');
|
||||
/* 列出可选上级菜单 */
|
||||
$menus = SystemMenu::mk()->order('sort desc,id asc')->column('id,pid,icon,url,node,title,params', 'id');
|
||||
$this->menus = DataExtend::arr2table(array_merge($menus, [['id' => '0', 'pid' => '-1', 'url' => '#', 'title' => '顶部菜单']]));
|
||||
if (isset($vo['id'])) foreach ($this->menus as $menu) if ($menu['id'] === $vo['id']) $vo = $menu;
|
||||
foreach ($this->menus as $key => $menu) if ($menu['spt'] >= 3 || $menu['url'] !== '#') unset($this->menus[$key]);
|
||||
if (isset($vo['spt']) && isset($vo['spc']) && in_array($vo['spt'], [1, 2]) && $vo['spc'] > 0) {
|
||||
foreach ($this->menus as $key => $menu) if ($vo['spt'] <= $menu['spt']) unset($this->menus[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改菜单状态
|
||||
* @auth true
|
||||
*/
|
||||
public function state()
|
||||
{
|
||||
SystemMenu::mSave($this->_vali([
|
||||
'status.in:0,1' => '状态值范围异常!',
|
||||
'status.require' => '状态值不能为空!',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统菜单
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
SystemMenu::mDelete();
|
||||
}
|
||||
}
|
||||
95
app/admin/controller/Oplog.php
Normal file
95
app/admin/controller/Oplog.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use Ip2Region;
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemOplog;
|
||||
use think\exception\HttpResponseException;
|
||||
|
||||
/**
|
||||
* 系统日志管理
|
||||
* @class Oplog
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Oplog extends Controller
|
||||
{
|
||||
/**
|
||||
* 系统日志管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
SystemOplog::mQuery()->layTable(function () {
|
||||
$this->title = '系统日志管理';
|
||||
$columns = SystemOplog::mk()->column('action,username', 'id');
|
||||
$this->users = array_unique(array_column($columns, 'username'));
|
||||
$this->actions = array_unique(array_column($columns, 'action'));
|
||||
}, static function (QueryHelper $query) {
|
||||
$query->dateBetween('create_at')->equal('username,action')->like('content,geoip,node');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表数据处理
|
||||
* @param array $data
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function _index_page_filter(array &$data)
|
||||
{
|
||||
$region = new Ip2Region();
|
||||
foreach ($data as &$vo) try {
|
||||
$vo['geoisp'] = $region->simple($vo['geoip']);
|
||||
} catch (\Exception $exception) {
|
||||
$vo['geoip'] = $exception->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理系统日志
|
||||
* @auth true
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
try {
|
||||
SystemOplog::mQuery()->empty();
|
||||
sysoplog('系统运维管理', '成功清理所有日志');
|
||||
$this->success('日志清理成功!');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error(lang("日志清理失败,%s", [$exception->getMessage()]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统日志
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
SystemOplog::mDelete();
|
||||
}
|
||||
}
|
||||
117
app/admin/controller/Queue.php
Normal file
117
app/admin/controller/Queue.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemQueue;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\service\ProcessService;
|
||||
use think\admin\service\QueueService;
|
||||
use think\exception\HttpResponseException;
|
||||
|
||||
/**
|
||||
* 系统任务管理
|
||||
* @class Queue
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Queue extends Controller
|
||||
{
|
||||
/**
|
||||
* 系统任务管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
SystemQueue::mQuery()->layTable(function () {
|
||||
$this->title = '系统任务管理';
|
||||
$this->iswin = ProcessService::iswin();
|
||||
if ($this->super = AdminService::isSuper()) {
|
||||
$this->command = ProcessService::think('xadmin:queue start');
|
||||
if (!$this->iswin && !empty($_SERVER['USER'])) {
|
||||
$this->command = "sudo -u {$_SERVER['USER']} {$this->command}";
|
||||
}
|
||||
}
|
||||
}, static function (QueryHelper $query) {
|
||||
$query->equal('status')->like('code|title#title,command');
|
||||
$query->timeBetween('enter_time,exec_time')->dateBetween('create_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页数据回调处理
|
||||
* @param array $data
|
||||
* @param array $result
|
||||
* @return void
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
protected function _index_page_filter(array $data, array &$result)
|
||||
{
|
||||
$result['extra'] = ['dos' => 0, 'pre' => 0, 'oks' => 0, 'ers' => 0];
|
||||
SystemQueue::mk()->field('status,count(1) count')->group('status')->select()->map(static function ($item) use (&$result) {
|
||||
if (intval($item['status']) === 1) $result['extra']['pre'] = $item['count'];
|
||||
if (intval($item['status']) === 2) $result['extra']['dos'] = $item['count'];
|
||||
if (intval($item['status']) === 3) $result['extra']['oks'] = $item['count'];
|
||||
if (intval($item['status']) === 4) $result['extra']['ers'] = $item['count'];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重启系统任务
|
||||
* @auth true
|
||||
*/
|
||||
public function redo()
|
||||
{
|
||||
try {
|
||||
$data = $this->_vali(['code.require' => '任务编号不能为空!']);
|
||||
$queue = QueueService::instance()->initialize($data['code'])->reset();
|
||||
$queue->progress(1, '>>> 任务重置成功 <<<', '0.00');
|
||||
$this->success('任务重置成功!', $queue->code);
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理运行数据
|
||||
* @auth true
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
$this->_queue('定时清理系统运行数据', "xadmin:queue clean", 0, [], 0, 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统任务
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
SystemQueue::mDelete();
|
||||
}
|
||||
}
|
||||
182
app/admin/controller/User.php
Normal file
182
app/admin/controller/User.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemAuth;
|
||||
use think\admin\model\SystemBase;
|
||||
use think\admin\model\SystemUser;
|
||||
use think\admin\service\AdminService;
|
||||
|
||||
/**
|
||||
* 系统用户管理
|
||||
* @class User
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class User extends Controller
|
||||
{
|
||||
/**
|
||||
* 系统用户管理
|
||||
* @auth true
|
||||
* @menu true
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->type = $this->get['type'] ?? 'index';
|
||||
SystemUser::mQuery()->layTable(function () {
|
||||
$this->title = '系统用户管理';
|
||||
$this->bases = SystemBase::items('身份权限');
|
||||
}, function (QueryHelper $query) {
|
||||
|
||||
// 加载对应数据列表
|
||||
$query->where(['is_deleted' => 0, 'status' => intval($this->type === 'index')]);
|
||||
|
||||
// 关联用户身份资料
|
||||
/** @var \think\model\Relation|\think\db\Query $query */
|
||||
$query->with(['userinfo' => static function ($query) {
|
||||
$query->field('code,name,content');
|
||||
}]);
|
||||
|
||||
// 数据列表搜索过滤
|
||||
$query->equal('status,usertype')->dateBetween('login_at,create_at');
|
||||
$query->like('username|nickname#username,contact_phone#phone,contact_mail#mail');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加系统用户
|
||||
* @auth true
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
SystemUser::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑系统用户
|
||||
* @auth true
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
SystemUser::mForm('form');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户密码
|
||||
* @auth true
|
||||
*/
|
||||
public function pass()
|
||||
{
|
||||
$this->_applyFormToken();
|
||||
if ($this->request->isGet()) {
|
||||
$this->verify = false;
|
||||
SystemUser::mForm('pass');
|
||||
} else {
|
||||
$data = $this->_vali([
|
||||
'id.require' => '用户ID不能为空!',
|
||||
'password.require' => '登录密码不能为空!',
|
||||
'repassword.require' => '重复密码不能为空!',
|
||||
'repassword.confirm:password' => '两次输入的密码不一致!',
|
||||
]);
|
||||
$user = SystemUser::mk()->findOrEmpty($data['id']);
|
||||
if ($user->isExists() && $user->save(['password' => md5($data['password'])])) {
|
||||
// 修改密码同步事件处理
|
||||
$this->app->event->trigger('PluginAdminChangePassword', [
|
||||
'uuid' => $data['id'], 'pass' => $data['password']
|
||||
]);
|
||||
sysoplog('系统用户管理', "修改用户[{$data['id']}]密码成功");
|
||||
$this->success('密码修改成功,请使用新密码登录!', '');
|
||||
} else {
|
||||
$this->error('密码修改失败,请稍候再试!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单数据处理
|
||||
* @param array $data
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
protected function _form_filter(array &$data)
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
// 检查资料是否完整
|
||||
empty($data['username']) && $this->error('登录账号不能为空!');
|
||||
if ($data['username'] !== AdminService::getSuperName()) {
|
||||
empty($data['authorize']) && $this->error('未配置权限!');
|
||||
}
|
||||
// 处理上传的权限格式
|
||||
$data['authorize'] = arr2str($data['authorize'] ?? []);
|
||||
if (empty($data['id'])) {
|
||||
// 检查账号是否重复
|
||||
$map = ['username' => $data['username'], 'is_deleted' => 0];
|
||||
if (SystemUser::mk()->where($map)->count() > 0) {
|
||||
$this->error("账号已经存在,请使用其它账号!");
|
||||
}
|
||||
// 新添加的用户密码与账号相同
|
||||
$data['password'] = md5($data['username']);
|
||||
} else {
|
||||
unset($data['username']);
|
||||
}
|
||||
} else {
|
||||
// 权限绑定处理
|
||||
$data['authorize'] = str2arr($data['authorize'] ?? '');
|
||||
$this->auths = SystemAuth::items();
|
||||
$this->bases = SystemBase::items('身份权限');
|
||||
$this->super = AdminService::getSuperName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户状态
|
||||
* @auth true
|
||||
*/
|
||||
public function state()
|
||||
{
|
||||
$this->_checkInput();
|
||||
SystemUser::mSave($this->_vali([
|
||||
'status.in:0,1' => '状态值范围异常!',
|
||||
'status.require' => '状态值不能为空!',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统用户
|
||||
* @auth true
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
$this->_checkInput();
|
||||
SystemUser::mDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查输入变量
|
||||
*/
|
||||
private function _checkInput()
|
||||
{
|
||||
if (in_array('10000', str2arr(input('id', '')))) {
|
||||
$this->error('系统超级账号禁止删除!');
|
||||
}
|
||||
}
|
||||
}
|
||||
114
app/admin/controller/api/Mail.php
Normal file
114
app/admin/controller/api/Mail.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
|
||||
/**
|
||||
* 邮箱配置接口
|
||||
*/
|
||||
class Mail extends Controller
|
||||
{
|
||||
/**
|
||||
* 邮箱配置列表
|
||||
*/
|
||||
private $mailConfigs = [
|
||||
[
|
||||
'name' => '默认配置1',
|
||||
'config' => [
|
||||
'DOMAIN' => '586vip.cn',
|
||||
'TEMP_MAIL' => 'ademyyk',
|
||||
'TEMP_MAIL_EXT' => '@mailto.plus',
|
||||
'BROWSER_USER_AGENT' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36',
|
||||
// 'BROWSER_PROXY' => 'http://127.0.0.1:2080',
|
||||
// 'BROWSER_HEADLESS' => 'True',
|
||||
'MAIL_SERVER' => 'https://tempmail.plus'
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => '备用配置1',
|
||||
'config' => [
|
||||
'DOMAIN' => 'nosqli.com',
|
||||
'TEMP_MAIL' => 'ademyyk',
|
||||
'TEMP_MAIL_EXT' => '@mailto.plus',
|
||||
'BROWSER_USER_AGENT' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36',
|
||||
'MAIL_SERVER' => 'https://tempmail.plus'
|
||||
]
|
||||
]
|
||||
// ,
|
||||
// [
|
||||
// 'name' => 'IMAP配置',
|
||||
// 'config' => [
|
||||
// 'DOMAIN' => 'wuen.site',
|
||||
// 'TEMP_MAIL' => null,
|
||||
// 'IMAP_SERVER' => 'imap.163.com',
|
||||
// 'IMAP_PORT' => 993,
|
||||
// 'IMAP_USER' => 'maticarmy@163.com',
|
||||
// 'IMAP_PASS' => 'LQer6rsSWan6vtuz',
|
||||
// 'BROWSER_USER_AGENT' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.92 Safari/537.36',
|
||||
// 'MAIL_SERVER' => 'https://tempmail.plus'
|
||||
// ]
|
||||
// ]
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取所有配置
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => $this->mailConfigs
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机配置
|
||||
*/
|
||||
public function getRandom()
|
||||
{
|
||||
// 随机获取一个配置
|
||||
$config = $this->mailConfigs[array_rand($this->mailConfigs)];
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'name' => $config['name'],
|
||||
'env' => $config['config']
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定配置
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
$name = input('name', '');
|
||||
|
||||
// 如果未指定名称,返回随机配置
|
||||
if (empty($name)) {
|
||||
return $this->getRandom();
|
||||
}
|
||||
|
||||
// 查找指定配置
|
||||
foreach ($this->mailConfigs as $config) {
|
||||
if ($config['name'] === $name) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'name' => $config['name'],
|
||||
'env' => $config['config']
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 未找到指定配置,返回随机配置
|
||||
return $this->getRandom();
|
||||
}
|
||||
}
|
||||
85
app/admin/controller/api/Member.php
Normal file
85
app/admin/controller/api/Member.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use app\manager\model\Member as MemberModel;
|
||||
use think\admin\Controller;
|
||||
|
||||
|
||||
/**
|
||||
* 会员接口管理
|
||||
*/
|
||||
class Member extends Controller
|
||||
{
|
||||
/**
|
||||
* 验证会员状态
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// 接收参数
|
||||
$keyword = trim(input('keyword', ''));
|
||||
if (empty($keyword)) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '请输入查询关键字'
|
||||
]);
|
||||
}
|
||||
|
||||
// 查询会员信息 (email = xxx OR order_id = xxx)
|
||||
$member = MemberModel::whereOr('email', '=', $keyword)
|
||||
->whereOr('order_id', '=', $keyword)
|
||||
->find();
|
||||
|
||||
if (empty($member)) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '会员不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查会员状态
|
||||
if ($member['status'] != 1) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '会员已被禁用'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查有效期
|
||||
if (strtotime($member['expire_time']) < time()) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '会员已过期'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查使用次数
|
||||
if ($member['usage_limit'] > 0 && $member['used_count'] >= $member['usage_limit']) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '使用次数已达上限'
|
||||
]);
|
||||
}
|
||||
|
||||
// 更新使用次数和最后登录信息
|
||||
$member->used_count = $member->used_count + 1;
|
||||
$member->last_login_time = date('Y-m-d H:i:s');
|
||||
$member->last_login_ip = $this->request->ip();
|
||||
$member->save();
|
||||
|
||||
// 返回成功
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '验证通过',
|
||||
'data' => [
|
||||
'email' => $member['email'],
|
||||
'order_id' => $member['order_id'],
|
||||
'expire_time' => $member['expire_time'],
|
||||
'usage_limit' => $member['usage_limit'],
|
||||
'used_count' => $member['used_count'],
|
||||
'last_login_time' => $member['last_login_time']
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
91
app/admin/controller/api/Plugs.php
Normal file
91
app/admin/controller/api/Plugs.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\service\AdminService;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* 扩展插件管理
|
||||
* @class Plugs
|
||||
* @package app\admin\controller\api
|
||||
*/
|
||||
class Plugs extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* 图标选择器
|
||||
* @login true
|
||||
*/
|
||||
public function icon()
|
||||
{
|
||||
$this->title = '图标选择器';
|
||||
// 读取 layui 字体图标
|
||||
if (empty($this->layuiIcons = $this->app->cache->get('LayuiIcons', []))) {
|
||||
$style = file_get_contents(syspath('public/static/plugs/layui/css/layui.css'));
|
||||
if (preg_match_all('#\.(layui-icon-[\w-]+):#', $style, $matches)) {
|
||||
if (count($this->layuiIcons = $matches[1]) > 0) {
|
||||
$this->app->cache->set('LayuiIcons', $this->layuiIcons, 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 读取自定义字体图标
|
||||
if (empty($this->thinkIcons = $this->app->cache->get('ThinkAdminSelfIcons', []))) {
|
||||
$style = file_get_contents(syspath('public/static/theme/css/iconfont.css'));
|
||||
if (preg_match_all('#\.(iconfont-[\w-]+):#', $style, $matches)) {
|
||||
if (count($this->thinkIcons = $matches[1]) > 0) {
|
||||
$this->app->cache->set('ThinkAdminSelfIcons', $this->thinkIcons, 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->field = $this->app->request->get('field', 'icon');
|
||||
$this->fetch(dirname(__DIR__, 2) . '/view/api/icon.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* 前端脚本变量
|
||||
* @return \think\Response
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function script(): Response
|
||||
{
|
||||
$token = $this->request->get('uptoken', '');
|
||||
$domain = boolval(AdminService::withUploadUnid($token));
|
||||
return response(join("\r\n", [
|
||||
sprintf("window.taDebug = %s;", $this->app->isDebug() ? 'true' : 'false'),
|
||||
sprintf("window.taAdmin = '%s';", sysuri('admin/index/index', [], false, $domain)),
|
||||
sprintf("window.taEditor = '%s';", sysconf('base.editor|raw') ?: 'ckeditor4'),
|
||||
]))->contentType('application/javascript');
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化数据库
|
||||
* @login true
|
||||
*/
|
||||
public function optimize()
|
||||
{
|
||||
if (AdminService::isSuper()) {
|
||||
sysoplog('系统运维管理', '创建数据库优化任务');
|
||||
$this->_queue('优化数据库所有数据表', 'xadmin:database optimize');
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
}
|
||||
91
app/admin/controller/api/Program.php
Normal file
91
app/admin/controller/api/Program.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
|
||||
/**
|
||||
* 程序更新接口
|
||||
*/
|
||||
class Program extends Controller
|
||||
{
|
||||
/**
|
||||
* 程序目录配置
|
||||
*/
|
||||
private $programPath = 'program/';
|
||||
|
||||
/**
|
||||
* 获取程序信息
|
||||
*/
|
||||
public function info()
|
||||
{
|
||||
$path = public_path() . $this->programPath;
|
||||
if (!is_dir($path)) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '程序目录不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取目录中最新的文件
|
||||
$files = glob($path . '*');
|
||||
if (empty($files)) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '暂无可用程序'
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取最新文件
|
||||
$latest = array_reduce($files, function($carry, $file) {
|
||||
return (!$carry || filemtime($file) > filemtime($carry)) ? $file : $carry;
|
||||
});
|
||||
|
||||
$name = basename($latest);
|
||||
$size = filesize($latest);
|
||||
$md5 = md5_file($latest);
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'name' => $name,
|
||||
'size' => $size,
|
||||
'md5' => $md5,
|
||||
'url' => request()->domain() . '/' . $this->programPath . $name,
|
||||
'time' => date('Y-m-d H:i:s', filemtime($latest))
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载程序
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$path = public_path() . $this->programPath;
|
||||
if (!is_dir($path)) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '程序目录不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取目录中最新的文件
|
||||
$files = glob($path . '*');
|
||||
if (empty($files)) {
|
||||
return json([
|
||||
'code' => 1,
|
||||
'msg' => '暂无可用程序'
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取最新文件
|
||||
$latest = array_reduce($files, function($carry, $file) {
|
||||
return (!$carry || filemtime($file) > filemtime($carry)) ? $file : $carry;
|
||||
});
|
||||
|
||||
return download($latest, basename($latest));
|
||||
}
|
||||
}
|
||||
118
app/admin/controller/api/Queue.php
Normal file
118
app/admin/controller/api/Queue.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use Psr\Log\NullLogger;
|
||||
use think\admin\Controller;
|
||||
use think\admin\model\SystemQueue;
|
||||
use think\admin\service\AdminService;
|
||||
use think\exception\HttpResponseException;
|
||||
|
||||
/**
|
||||
* 任务监听服务管理
|
||||
* @class Queue
|
||||
* @package app\admin\controller\api
|
||||
*/
|
||||
class Queue extends Controller
|
||||
{
|
||||
/**
|
||||
* 停止监听服务
|
||||
* @login true
|
||||
*/
|
||||
public function stop()
|
||||
{
|
||||
if (AdminService::isSuper()) try {
|
||||
$message = $this->app->console->call('xadmin:queue', ['stop'])->fetch();
|
||||
if (stripos($message, 'sent end signal to process')) {
|
||||
sysoplog('系统运维管理', '尝试停止任务监听服务');
|
||||
$this->success('停止任务监听服务成功!');
|
||||
} elseif (stripos($message, 'processes to stop')) {
|
||||
$this->success('没有找到需要停止的服务!');
|
||||
} else {
|
||||
$this->error(nl2br($message));
|
||||
}
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动监听服务
|
||||
* @login true
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
if (AdminService::isSuper()) try {
|
||||
$message = $this->app->console->call('xadmin:queue', ['start'])->fetch();
|
||||
if (stripos($message, 'daemons started successfully for pid')) {
|
||||
sysoplog('系统运维管理', '尝试启动任务监听服务');
|
||||
$this->success('任务监听服务启动成功!');
|
||||
} elseif (stripos($message, 'daemons already exist for pid')) {
|
||||
$this->success('任务监听服务已经启动!');
|
||||
} else {
|
||||
$this->error(nl2br($message));
|
||||
}
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查监听服务
|
||||
* @login true
|
||||
*/
|
||||
public function status()
|
||||
{
|
||||
if (AdminService::isSuper()) try {
|
||||
$message = $this->app->console->call('xadmin:queue', ['status'])->fetch();
|
||||
if (preg_match('/process.*?\d+.*?running/', $message)) {
|
||||
echo "<span class='color-green pointer' data-tips-text='{$message}'>{$this->app->lang->get('已启动')}</span>";
|
||||
} else {
|
||||
echo "<span class='color-red pointer' data-tips-text='{$message}'>{$this->app->lang->get('未启动')}</span>";
|
||||
}
|
||||
} catch (\Error|\Exception $exception) {
|
||||
echo "<span class='color-red pointer' data-tips-text='{$exception->getMessage()}'>{$this->app->lang->get('异 常')}</span>";
|
||||
} else {
|
||||
$message = lang('只有超级管理员才能操作!');
|
||||
echo "<span class='color-red pointer' data-tips-text='{$message}'>{$this->app->lang->get('无权限')}</span>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务进度
|
||||
* @login true
|
||||
*/
|
||||
public function progress()
|
||||
{
|
||||
$input = $this->_vali(['code.require' => '任务编号不能为空!']);
|
||||
$this->app->db->setLog(new NullLogger()); /* 关闭数据库请求日志 */
|
||||
$message = SystemQueue::mk()->where($input)->value('message', '');
|
||||
$this->success('获取任务进度成功d!', json_decode($message, true));
|
||||
}
|
||||
}
|
||||
138
app/admin/controller/api/System.php
Normal file
138
app/admin/controller/api/System.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\model\SystemConfig;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\service\RuntimeService;
|
||||
use think\exception\HttpResponseException;
|
||||
|
||||
/**
|
||||
* 系统运行管理
|
||||
* @class System
|
||||
* @package app\admin\controller\api
|
||||
*/
|
||||
class System extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* 网站压缩发布
|
||||
* @login true
|
||||
*/
|
||||
public function push()
|
||||
{
|
||||
if (AdminService::isSuper()) try {
|
||||
RuntimeService::push() && sysoplog('系统运维管理', '刷新发布运行缓存');
|
||||
$this->success('网站缓存加速成功!', 'javascript:location.reload()');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理运行缓存
|
||||
* @login true
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
if (AdminService::isSuper()) try {
|
||||
RuntimeService::clear() && sysoplog('系统运维管理', '清理网站日志缓存');
|
||||
$this->success('清空日志缓存成功!', 'javascript:location.reload()');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前运行模式
|
||||
* @login true
|
||||
*/
|
||||
public function debug()
|
||||
{
|
||||
if (AdminService::isSuper()) if (input('state')) {
|
||||
RuntimeService::set('product');
|
||||
sysoplog('系统运维管理', '开发模式切换为生产模式');
|
||||
$this->success('已切换为生产模式!', 'javascript:location.reload()');
|
||||
} else {
|
||||
RuntimeService::set('debug');
|
||||
sysoplog('系统运维管理', '生产模式切换为开发模式');
|
||||
$this->success('已切换为开发模式!', 'javascript:location.reload()');
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改富文本编辑器
|
||||
* @return void
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function editor()
|
||||
{
|
||||
if (AdminService::isSuper()) {
|
||||
$editor = input('editor', 'auto');
|
||||
sysconf('base.editor', $editor);
|
||||
sysoplog('系统运维管理', "切换编辑器为{$editor}");
|
||||
$this->success('已切换后台编辑器!', 'javascript:location.reload()');
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理系统配置
|
||||
* @login true
|
||||
*/
|
||||
public function config()
|
||||
{
|
||||
if (AdminService::isSuper()) try {
|
||||
[$tmpdata, $newdata] = [[], []];
|
||||
foreach (SystemConfig::mk()->order('type,name asc')->cursor() as $item) {
|
||||
$tmpdata[$item['type']][$item['name']] = $item['value'];
|
||||
}
|
||||
foreach ($tmpdata as $type => $items) foreach ($items as $name => $value) {
|
||||
$newdata[] = ['type' => $type, 'name' => $name, 'value' => $value];
|
||||
}
|
||||
$this->app->db->transaction(static function () use ($newdata) {
|
||||
SystemConfig::mQuery()->empty()->insertAll($newdata);
|
||||
});
|
||||
$this->app->cache->delete('SystemConfig');
|
||||
sysoplog('系统运维管理', '清理系统配置参数');
|
||||
$this->success('清理系统配置成功!', 'javascript:location.reload()');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
} else {
|
||||
$this->error('请使用超管账号操作!');
|
||||
}
|
||||
}
|
||||
}
|
||||
336
app/admin/controller/api/Upload.php
Normal file
336
app/admin/controller/api/Upload.php
Normal file
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | Admin Plugin for ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2024 ThinkAdmin [ thinkadmin.top ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: https://thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// | 免责声明 ( https://thinkadmin.top/disclaimer )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-admin
|
||||
// | github 代码仓库:https://github.com/zoujingli/think-plugs-admin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin\controller\api;
|
||||
|
||||
use think\admin\Controller;
|
||||
use think\admin\helper\QueryHelper;
|
||||
use think\admin\model\SystemFile;
|
||||
use think\admin\service\AdminService;
|
||||
use think\admin\Storage;
|
||||
use think\admin\storage\AliossStorage;
|
||||
use think\admin\storage\AlistStorage;
|
||||
use think\admin\storage\LocalStorage;
|
||||
use think\admin\storage\QiniuStorage;
|
||||
use think\admin\storage\TxcosStorage;
|
||||
use think\admin\storage\UpyunStorage;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\file\UploadedFile;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* 文件上传接口
|
||||
* @class Upload
|
||||
* @package app\admin\controller\api
|
||||
*/
|
||||
class Upload extends Controller
|
||||
{
|
||||
/**
|
||||
* 文件上传脚本
|
||||
* @return Response
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function index(): Response
|
||||
{
|
||||
$data = ['exts' => []];
|
||||
[$uuid, $unid, $exts] = $this->initUnid(false);
|
||||
$allows = str2arr(sysconf('storage.allow_exts|raw'));
|
||||
if (empty($uuid) && $unid > 0) $allows = array_intersect($exts, $allows);
|
||||
foreach ($allows as $ext) $data['exts'][$ext] = Storage::mime($ext);
|
||||
$data['exts'] = json_encode($data['exts'], JSON_UNESCAPED_UNICODE);
|
||||
$data['nameType'] = sysconf('storage.name_type|raw') ?: 'xmd5';
|
||||
return view(dirname(__DIR__, 2) . '/view/api/upload.js', $data)->contentType('application/x-javascript');
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件选择器
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function image()
|
||||
{
|
||||
[$uuid, $unid] = $this->initUnid();
|
||||
SystemFile::mQuery()->layTable(function () {
|
||||
$this->title = '文件选择器';
|
||||
}, function (QueryHelper $query) use ($unid, $uuid) {
|
||||
if ($unid && $uuid) $query->where(function ($query) use ($uuid, $unid) {
|
||||
/** @var \think\db\Query $query */
|
||||
$query->whereOr([['uuid', '=', $uuid], ['unid', '=', $unid]]);
|
||||
}); else {
|
||||
$query->where($unid ? ['unid' => $unid] : ['uuid' => $uuid]);
|
||||
}
|
||||
$query->where(['status' => 2, 'issafe' => 0])->in('xext#type');
|
||||
$query->like('name,hash')->dateBetween('create_at')->order('id desc');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传检查
|
||||
*/
|
||||
public function state()
|
||||
{
|
||||
try {
|
||||
[$uuid, $unid] = $this->initUnid();
|
||||
[$name, $safe] = [input('name'), $this->getSafe()];
|
||||
$data = ['uptype' => $this->getType(), 'safe' => intval($safe), 'key' => input('key')];
|
||||
$file = SystemFile::mk()->data($this->_vali([
|
||||
'xkey.value' => $data['key'],
|
||||
'type.value' => $this->getType(),
|
||||
'uuid.value' => $uuid,
|
||||
'unid.value' => $unid,
|
||||
'name.require' => '名称不能为空!',
|
||||
'hash.require' => '哈希不能为空!',
|
||||
'xext.require' => '后缀不能为空!',
|
||||
'size.require' => '大小不能为空!',
|
||||
'mime.default' => '',
|
||||
'status.value' => 1,
|
||||
]));
|
||||
$mime = $file->getAttr('mime');
|
||||
if (empty($mime)) $file->setAttr('mime', Storage::mime($file->getAttr('xext')));
|
||||
$info = Storage::instance($data['uptype'])->info($data['key'], $safe, $name);
|
||||
if (isset($info['url']) && isset($info['key'])) {
|
||||
$file->save(['xurl' => $info['url'], 'isfast' => 1, 'issafe' => $data['safe']]);
|
||||
$extr = ['id' => $file->id ?? 0, 'url' => $info['url'], 'key' => $info['key']];
|
||||
$this->success('文件已经上传', array_merge($data, $extr), 200);
|
||||
} elseif ('local' === $data['uptype']) {
|
||||
$local = LocalStorage::instance();
|
||||
$data['url'] = $local->url($data['key'], $safe, $name);
|
||||
$data['server'] = $local->upload();
|
||||
} elseif ('qiniu' === $data['uptype']) {
|
||||
$qiniu = QiniuStorage::instance();
|
||||
$data['url'] = $qiniu->url($data['key'], $safe, $name);
|
||||
$data['token'] = $qiniu->token($data['key'], 3600, $name);
|
||||
$data['server'] = $qiniu->upload();
|
||||
} elseif ('alioss' === $data['uptype']) {
|
||||
$alioss = AliossStorage::instance();
|
||||
$token = $alioss->token($data['key'], 3600, $name);
|
||||
$data['url'] = $token['siteurl'];
|
||||
$data['policy'] = $token['policy'];
|
||||
$data['signature'] = $token['signature'];
|
||||
$data['OSSAccessKeyId'] = $token['keyid'];
|
||||
$data['server'] = $alioss->upload();
|
||||
} elseif ('txcos' === $data['uptype']) {
|
||||
$txcos = TxcosStorage::instance();
|
||||
$token = $txcos->token($data['key'], 3600, $name);
|
||||
$data['url'] = $token['siteurl'];
|
||||
$data['q-ak'] = $token['q-ak'];
|
||||
$data['policy'] = $token['policy'];
|
||||
$data['q-key-time'] = $token['q-key-time'];
|
||||
$data['q-signature'] = $token['q-signature'];
|
||||
$data['q-sign-algorithm'] = $token['q-sign-algorithm'];
|
||||
$data['server'] = $txcos->upload();
|
||||
} elseif ('upyun' === $data['uptype']) {
|
||||
$upyun = UpyunStorage::instance();
|
||||
$token = $upyun->token($data['key'], 3600, $name, input('hash', ''));
|
||||
$data['url'] = $token['siteurl'];
|
||||
$data['policy'] = $token['policy'];
|
||||
$data['server'] = $upyun->upload();
|
||||
$data['authorization'] = $token['authorization'];
|
||||
} elseif ('alist' === $data['uptype']) {
|
||||
$alist = AlistStorage::instance();
|
||||
$data['url'] = $alist->url($data['key']);
|
||||
$data['server'] = $alist->upload();
|
||||
$data['filepath'] = $alist->real($data['key']);
|
||||
$data['authorization'] = $alist->token();
|
||||
} else {
|
||||
$this->error('未知的存储引擎!');
|
||||
}
|
||||
$file->save(['xurl' => $data['url'], 'isfast' => 0, 'issafe' => $data['safe']]);
|
||||
$this->success('获取上传授权参数', array_merge($data, ['id' => $file->id ?? 0]), 404);
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
$this->error($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新文件状态
|
||||
* @return void
|
||||
*/
|
||||
public function done()
|
||||
{
|
||||
[$uuid, $unid] = $this->initUnid();
|
||||
$data = $this->_vali([
|
||||
'id.require' => '编号不能为空!',
|
||||
'hash.require' => '哈希不能为空!',
|
||||
'uuid.value' => $uuid,
|
||||
'unid.value' => $unid,
|
||||
]);
|
||||
$file = SystemFile::mk()->where($data)->findOrEmpty();
|
||||
if ($file->isEmpty()) $this->error('文件不存在!');
|
||||
if ($file->save(['status' => 2])) {
|
||||
$this->success('更新成功!');
|
||||
} else {
|
||||
$this->error('更新失败!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传入口
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
public function file()
|
||||
{
|
||||
[$uuid, $unid, $unexts] = $this->initUnid();
|
||||
// 开始处理文件上传
|
||||
$file = $this->getFile();
|
||||
$extension = strtolower($file->getOriginalExtension());
|
||||
$saveFileName = input('key') ?: Storage::name($file->getPathname(), $extension, '', 'md5_file');
|
||||
// 检查文件名称是否合法
|
||||
if (strpos($saveFileName, '..') !== false) {
|
||||
$this->error('文件路径不能出现跳级操作!');
|
||||
}
|
||||
// 检查文件后缀是否被恶意修改
|
||||
if (strtolower(pathinfo(parse_url($saveFileName, PHP_URL_PATH), PATHINFO_EXTENSION)) !== $extension) {
|
||||
$this->error('文件后缀异常,请重新上传文件!');
|
||||
}
|
||||
// 屏蔽禁止上传指定后缀的文件
|
||||
if (!in_array($extension, str2arr(sysconf('storage.allow_exts|raw')))) {
|
||||
$this->error('文件类型受限,请在后台配置规则!');
|
||||
}
|
||||
// 前端用户上传后缀检查处理
|
||||
if (empty($uuid) && $unid > 0 && !in_array($extension, $unexts)) {
|
||||
$this->error('文件类型受限,请上传允许的文件类型!');
|
||||
}
|
||||
if (in_array($extension, ['sh', 'asp', 'bat', 'cmd', 'exe', 'php'])) {
|
||||
$this->error('文件安全保护,禁止上传可执行文件!');
|
||||
}
|
||||
try {
|
||||
$safeMode = $this->getSafe();
|
||||
if (($type = $this->getType()) === 'local') {
|
||||
$local = LocalStorage::instance();
|
||||
$distName = $local->path($saveFileName, $safeMode);
|
||||
if (PHP_SAPI === 'cli') {
|
||||
is_dir(dirname($distName)) || mkdir(dirname($distName), 0777, true);
|
||||
rename($file->getPathname(), $distName);
|
||||
} else {
|
||||
$file->move(dirname($distName), basename($distName));
|
||||
}
|
||||
$info = $local->info($saveFileName, $safeMode, $file->getOriginalName());
|
||||
if (in_array($extension, ['jpg', 'gif', 'png', 'bmp', 'jpeg', 'wbmp'])) {
|
||||
if ($this->imgNotSafe($distName) && $local->del($saveFileName)) {
|
||||
$this->error('图片未通过安全检查!');
|
||||
}
|
||||
[$width, $height] = getimagesize($distName);
|
||||
if (($width < 1 || $height < 1) && $local->del($saveFileName)) {
|
||||
$this->error('读取图片的尺寸失败!');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$bina = file_get_contents($file->getPathname());
|
||||
$info = Storage::instance($type)->set($saveFileName, $bina, $safeMode, $file->getOriginalName());
|
||||
}
|
||||
if (isset($info['url'])) {
|
||||
$this->success('文件上传成功!', ['url' => $safeMode ? $saveFileName : $info['url']]);
|
||||
} else {
|
||||
$this->error('文件处理失败,请稍候再试!');
|
||||
}
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传类型
|
||||
* @return boolean
|
||||
*/
|
||||
private function getSafe(): bool
|
||||
{
|
||||
return boolval(input('safe', '0'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传方式
|
||||
* @return string
|
||||
* @throws \think\admin\Exception
|
||||
*/
|
||||
private function getType(): string
|
||||
{
|
||||
$type = strtolower(input('uptype', ''));
|
||||
if (in_array($type, array_keys(Storage::types()))) {
|
||||
return $type;
|
||||
} else {
|
||||
return strtolower(sysconf('storage.type|raw'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件对象
|
||||
* @return UploadedFile|void
|
||||
*/
|
||||
private function getFile(): UploadedFile
|
||||
{
|
||||
try {
|
||||
$file = $this->request->file('file');
|
||||
if ($file instanceof UploadedFile) {
|
||||
return $file;
|
||||
} else {
|
||||
$this->error('读取临时文件失败!');
|
||||
}
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
trace_file($exception);
|
||||
$this->error(lang($exception->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化用户状态
|
||||
* @param boolean $check
|
||||
* @return array
|
||||
*/
|
||||
private function initUnid(bool $check = true): array
|
||||
{
|
||||
$uuid = AdminService::getUserId();
|
||||
[$unid, $exts] = AdminService::withUploadUnid();
|
||||
if ($check && empty($uuid) && empty($unid)) {
|
||||
$this->error('未登录,禁止使用文件上传!');
|
||||
} else {
|
||||
return [$uuid, $unid, $exts];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查图片是否安全
|
||||
* @param string $filename
|
||||
* @return boolean
|
||||
*/
|
||||
private function imgNotSafe(string $filename): bool
|
||||
{
|
||||
$source = fopen($filename, 'rb');
|
||||
if (($size = filesize($filename)) > 512) {
|
||||
$hexs = bin2hex(fread($source, 512));
|
||||
fseek($source, $size - 512);
|
||||
$hexs .= bin2hex(fread($source, 512));
|
||||
} else {
|
||||
$hexs = bin2hex(fread($source, $size));
|
||||
}
|
||||
if (is_resource($source)) fclose($source);
|
||||
$bins = hex2bin($hexs);
|
||||
/* 匹配十六进制中的 <% ( ) %> 或 <? ( ) ?> 或 <script | /script> */
|
||||
foreach (['<?php ', '<% ', '<script '] as $key) if (stripos($bins, $key) !== false) return true;
|
||||
$result = preg_match("/(3c25.*?28.*?29.*?253e)|(3c3f.*?28.*?29.*?3f3e)|(3C534352495054)|(2F5343524950543E)|(3C736372697074)|(2F7363726970743E)/is", $hexs);
|
||||
return $result === false || $result > 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user