diff --git a/.gitignore b/.gitignore index d49298bc4..c8a149561 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ /database/migrations/20221013031925_install_admin.php /database/migrations/20221013031926_install_admin_data.php +/database/migrations/20221013031927_install_admin20230325.php /database/migrations/20221013045829_install_wechat.php /database/migrations/20221013045830_install_wechat_data.php /database/migrations/20221013045838_install_user.php @@ -37,4 +38,4 @@ /database/migrations/20221215000001_install_center_data.php /database/migrations/20230209000001_install_wechat_service.php /database/migrations/20230224000001_install_account.php -database/migrations/20230225000001_install_payment.php +database/migrations/20230225000001_install_payment.php diff --git a/app/admin/Service.php b/app/admin/Service.php index 25155629e..1bcd930dc 100644 --- a/app/admin/Service.php +++ b/app/admin/Service.php @@ -20,7 +20,7 @@ use think\admin\Plugin; /** * 插件服务注册 - * Class Service + * @class Service * @package app\admin */ class Service extends Plugin diff --git a/app/admin/controller/Auth.php b/app/admin/controller/Auth.php index 856a04d0a..dfac958ec 100644 --- a/app/admin/controller/Auth.php +++ b/app/admin/controller/Auth.php @@ -24,7 +24,7 @@ use think\admin\service\AdminService; /** * 系统权限管理 - * Class Auth + * @class Auth * @package app\admin\controller */ class Auth extends Controller diff --git a/app/admin/controller/Base.php b/app/admin/controller/Base.php index 3557a2421..9ae1bad09 100644 --- a/app/admin/controller/Base.php +++ b/app/admin/controller/Base.php @@ -22,7 +22,7 @@ use think\admin\model\SystemBase; /** * 数据字典管理 - * Class Base + * @class Base * @package app\admin\controller */ class Base extends Controller diff --git a/app/admin/controller/Config.php b/app/admin/controller/Config.php index 5aaa583c0..a88878012 100644 --- a/app/admin/controller/Config.php +++ b/app/admin/controller/Config.php @@ -27,7 +27,7 @@ use think\admin\storage\TxcosStorage; /** * 系统参数配置 - * Class Config + * @class Config * @package app\admin\controller */ class Config extends Controller diff --git a/app/admin/controller/File.php b/app/admin/controller/File.php index c380c37ec..2f54fa4c7 100644 --- a/app/admin/controller/File.php +++ b/app/admin/controller/File.php @@ -24,7 +24,7 @@ use think\admin\Storage; /** * 系统文件管理 - * Class File + * @class File * @package app\admin\controller */ class File extends Controller @@ -99,6 +99,7 @@ class File extends Controller * 清理重复文件 * @auth true * @return void + * @throws \think\db\exception\DbException */ public function distinct() { diff --git a/app/admin/controller/Index.php b/app/admin/controller/Index.php index 675ec897c..720058438 100644 --- a/app/admin/controller/Index.php +++ b/app/admin/controller/Index.php @@ -23,7 +23,7 @@ use think\admin\service\MenuService; /** * 后台界面入口 - * Class Index + * @class Index * @package app\admin\controller */ class Index extends Controller @@ -31,6 +31,7 @@ class Index extends Controller /** * 显示后台首页 * @throws \ReflectionException + * @throws \think\admin\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException @@ -58,9 +59,7 @@ class Index extends Controller * 后台主题切换 * @login true * @return void - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException + * @throws \think\admin\Exception */ public function theme() { diff --git a/app/admin/controller/Login.php b/app/admin/controller/Login.php index dd66b0869..0e1038e1a 100644 --- a/app/admin/controller/Login.php +++ b/app/admin/controller/Login.php @@ -26,7 +26,7 @@ use think\admin\service\SystemService; /** * 用户登录管理 - * Class Login + * @class Login * @package app\admin\controller */ class Login extends Controller @@ -35,9 +35,7 @@ class Login extends Controller /** * 后台登录入口 * @return void - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException + * @throws \think\admin\Exception */ public function index() { diff --git a/app/admin/controller/Menu.php b/app/admin/controller/Menu.php index 7e3d1a046..ce71f7e41 100644 --- a/app/admin/controller/Menu.php +++ b/app/admin/controller/Menu.php @@ -25,7 +25,7 @@ use think\admin\service\NodeService; /** * 系统菜单管理 - * Class Menu + * @class Menu * @package app\admin\controller */ class Menu extends Controller diff --git a/app/admin/controller/Oplog.php b/app/admin/controller/Oplog.php index e6650a092..0783224cd 100644 --- a/app/admin/controller/Oplog.php +++ b/app/admin/controller/Oplog.php @@ -25,7 +25,7 @@ use think\exception\HttpResponseException; /** * 系统日志管理 - * Class Oplog + * @class Oplog * @package app\admin\controller */ class Oplog extends Controller diff --git a/app/admin/controller/Queue.php b/app/admin/controller/Queue.php index c4ba22096..ce5c61671 100644 --- a/app/admin/controller/Queue.php +++ b/app/admin/controller/Queue.php @@ -27,7 +27,7 @@ use think\exception\HttpResponseException; /** * 系统任务管理 - * Class Queue + * @class Queue * @package app\admin\controller */ class Queue extends Controller diff --git a/app/admin/controller/User.php b/app/admin/controller/User.php index ef9bf19f0..0ea78aa0e 100644 --- a/app/admin/controller/User.php +++ b/app/admin/controller/User.php @@ -25,7 +25,7 @@ use think\admin\service\AdminService; /** * 系统用户管理 - * Class User + * @class User * @package app\admin\controller */ class User extends Controller diff --git a/app/admin/controller/api/Plugs.php b/app/admin/controller/api/Plugs.php index 22f888787..3fbabf2d2 100644 --- a/app/admin/controller/api/Plugs.php +++ b/app/admin/controller/api/Plugs.php @@ -21,8 +21,8 @@ use think\admin\service\AdminService; use think\Response; /** - * 通用插件管理 - * Class Plugs + * 扩展插件管理 + * @class Plugs * @package app\admin\controller\api */ class Plugs extends Controller @@ -42,17 +42,17 @@ class Plugs extends Controller /** * 前端脚本变量 * @return \think\Response - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException + * @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)), + sprintf("window.taAdmin = '%s';", sysuri('admin/index/index', [], false, $domain)), sprintf("window.taEditor = '%s';", sysconf('base.editor|raw') ?: 'ckeditor4'), - ]))->contentType('application/x-javascript'); + ]))->contentType('application/javascript'); } /** @@ -65,7 +65,7 @@ class Plugs extends Controller sysoplog('系统运维管理', '创建数据库优化任务'); $this->_queue('优化数据库所有数据表', 'xadmin:database optimize'); } else { - $this->error('只有超级管理员才能操作!'); + $this->error('请使用超管账号操作!'); } } } \ No newline at end of file diff --git a/app/admin/controller/api/Queue.php b/app/admin/controller/api/Queue.php index 28a0fa29b..cd8b47cbb 100644 --- a/app/admin/controller/api/Queue.php +++ b/app/admin/controller/api/Queue.php @@ -24,25 +24,25 @@ use think\admin\service\QueueService; use think\exception\HttpResponseException; /** - * 后台任务通用接口 - * Class Queue + * 任务监听服务管理 + * @class Queue * @package app\admin\controller\api */ class Queue extends Controller { /** - * WIN停止监听进程 + * 停止监听服务 * @login true */ public function stop() { - try { + if (AdminService::isSuper()) try { $message = $this->app->console->call('xadmin:queue', ['stop'])->fetch(); if (stripos($message, 'sent end signal to process')) { - sysoplog('系统运维管理', '尝试停止后台服务主进程'); - $this->success('停止后台服务主进程成功!'); + sysoplog('系统运维管理', '尝试停止任务监听服务'); + $this->success('停止任务监听服务成功!'); } elseif (stripos($message, 'processes to stop')) { - $this->success('没有找到需要停止的进程!'); + $this->success('没有找到需要停止的服务!'); } else { $this->error(nl2br($message)); } @@ -51,22 +51,24 @@ class Queue extends Controller } catch (Exception $exception) { trace_file($exception); $this->error($exception->getMessage()); + } else { + $this->error('请使用超管账号操作!'); } } /** - * WIN创建监听进程 + * 启动监听服务 * @login true */ public function start() { - try { + if (AdminService::isSuper()) try { $message = $this->app->console->call('xadmin:queue', ['start'])->fetch(); if (stripos($message, 'daemons started successfully for pid')) { - sysoplog('系统运维管理', '尝试启动后台服务主进程'); - $this->success('后台服务主进程启动成功!'); + sysoplog('系统运维管理', '尝试启动任务监听服务'); + $this->success('任务监听服务启动成功!'); } elseif (stripos($message, 'daemons already exist for pid')) { - $this->success('后台服务主进程已经存在!'); + $this->success('任务监听服务已经启动!'); } else { $this->error(nl2br($message)); } @@ -75,11 +77,13 @@ class Queue extends Controller } catch (Exception $exception) { trace_file($exception); $this->error($exception->getMessage()); + } else { + $this->error('请使用超管账号操作!'); } } /** - * 检查任务状态 + * 检查监听服务 * @login true */ public function status() @@ -99,7 +103,7 @@ class Queue extends Controller } /** - * 任务进度查询 + * 查询任务进度 * @login true * @throws \think\admin\Exception */ diff --git a/app/admin/controller/api/System.php b/app/admin/controller/api/System.php index 5785f9bb8..970b07587 100644 --- a/app/admin/controller/api/System.php +++ b/app/admin/controller/api/System.php @@ -23,8 +23,8 @@ use think\admin\service\RuntimeService; use think\exception\HttpResponseException; /** - * 系统运行控制管理 - * Class System + * 系统运行管理 + * @class System * @package app\admin\controller\api */ class System extends Controller @@ -45,7 +45,7 @@ class System extends Controller trace_file($exception); $this->error($exception->getMessage()); } else { - $this->error('只有超级管理员才能操作!'); + $this->error('请使用超管账号操作!'); } } @@ -64,7 +64,7 @@ class System extends Controller trace_file($exception); $this->error($exception->getMessage()); } else { - $this->error('只有超级管理员才能操作!'); + $this->error('请使用超管账号操作!'); } } @@ -83,7 +83,7 @@ class System extends Controller sysoplog('系统运维管理', '生产模式切换为开发模式'); $this->success('已切换为开发模式!', 'javascript:location.reload()'); } else { - $this->error('只有超级管理员才能操作!'); + $this->error('请使用超管账号操作!'); } } @@ -102,7 +102,7 @@ class System extends Controller sysoplog('系统运维管理', "切换编辑器为{$editor}"); $this->success('已切换后台编辑器!', 'javascript:location.reload()'); } else { - $this->error('只有超级管理员才能操作!'); + $this->error('请使用超管账号操作!'); } } @@ -132,7 +132,7 @@ class System extends Controller trace_file($exception); $this->error($exception->getMessage()); } else { - $this->error('只有超级管理员才能操作!'); + $this->error('请使用超管账号操作!'); } } } \ No newline at end of file diff --git a/app/admin/controller/api/Upload.php b/app/admin/controller/api/Upload.php index af96e9817..52c5cc319 100644 --- a/app/admin/controller/api/Upload.php +++ b/app/admin/controller/api/Upload.php @@ -32,25 +32,23 @@ use think\Response; /** * 文件上传接口 - * Class Upload + * @class Upload * @package app\admin\controller\api */ class Upload extends Controller { - /** * 文件上传脚本 * @return Response - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException + * @throws \think\admin\Exception */ public function index(): Response { $data = ['exts' => []]; - foreach (str2arr(sysconf('storage.allow_exts|raw')) as $ext) { - $data['exts'][$ext] = Storage::mime($ext); - } + [$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); $template = realpath(__DIR__ . '/../../view/api/upload.js'); $data['exts'] = json_encode($data['exts'], JSON_UNESCAPED_UNICODE); $data['nameType'] = sysconf('storage.name_type|raw') ?: 'xmd5'; @@ -58,21 +56,42 @@ class Upload extends Controller } /** - * 文件上传检查 - * @login true - * @throws \think\admin\Exception + * 文件选择器 * @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'); + }); + } + + /** + * 文件上传检查 + * @throws \think\admin\Exception + */ public function state() { + [$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' => AdminService::getUserId(), + 'uuid.value' => $uuid, + 'unid.value' => $unid, 'name.require' => '名称不能为空!', 'hash.require' => '哈希不能为空!', 'xext.require' => '后缀不能为空!', @@ -80,9 +99,10 @@ class Upload extends Controller 'mime.default' => '', 'status.value' => 1, ])); - if (empty($file['mime'])) $file['mime'] = Storage::mime($file['xext']); + $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 (is_array($info) && isset($info['url']) && isset($info['key'])) { + 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); @@ -110,7 +130,7 @@ class Upload extends Controller $data['q-sign-algorithm'] = $token['q-sign-algorithm']; $data['server'] = TxcosStorage::instance()->upload(); } elseif ('upyun' === $data['uptype']) { - $token = UpyunStorage::instance()->buildUploadToken($data['key'], 3600, $name, input('size'), input('hash')); + $token = UpyunStorage::instance()->buildUploadToken($data['key'], 3600, $name, input('hash', '')); $data['url'] = $token['siteurl']; $data['policy'] = $token['policy']; $data['authorization'] = $token['authorization']; @@ -122,15 +142,16 @@ class Upload extends Controller /** * 更新文件状态 - * @login true * @return void */ public function done() { + [$uuid, $unid] = $this->initUnid(); $data = $this->_vali([ 'id.require' => '编号不能为空!', 'hash.require' => '哈希不能为空!', - 'uuid.value' => AdminService::getUserId(), + 'uuid.value' => $uuid, + 'unid.value' => $unid, ]); $file = SystemFile::mk()->where($data)->findOrEmpty(); if ($file->isEmpty()) $this->error('文件不存在!'); @@ -141,75 +162,63 @@ class Upload extends Controller } } - /** - * 文件选择器 - * @login true - * @return void - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException - */ - public function image() - { - SystemFile::mQuery()->layTable(function () { - $this->title = '文件选择器'; - }, function (QueryHelper $query) { - $query->where(['status' => 2, 'issafe' => 0, 'uuid' => AdminService::getUserId()]); - $query->like('name,hash')->in('xext#type')->dateBetween('create_at')->order('id desc'); - }); - } - /** * 文件上传入口 - * @login true - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException + * @throws \think\admin\Exception */ public function file() { - if (!($file = $this->getFile())->isValid()) { - $this->error('文件上传异常,文件过大或未上传!'); - } - $safeMode = $this->getSafe(); + [$uuid, $unid, $unexts] = $this->initUnid(); + // 开始处理文件上传 + $file = $this->getFile(); $extension = strtolower($file->getOriginalExtension()); - $saveName = input('key') ?: Storage::name($file->getPathname(), $extension, '', 'md5_file'); + $saveFileName = input('key') ?: Storage::name($file->getPathname(), $extension, '', 'md5_file'); // 检查文件名称是否合法 - if (strpos($saveName, '../') !== false) { + if (strpos($saveFileName, '../') !== false) { $this->error('文件路径不能出现跳级操作!'); } // 检查文件后缀是否被恶意修改 - if (strtolower(pathinfo(parse_url($saveName, PHP_URL_PATH), PATHINFO_EXTENSION)) !== $extension) { + 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 { - if ($this->getType() === 'local') { + $safeMode = $this->getSafe(); + if (($type = $this->getType()) === 'local') { $local = LocalStorage::instance(); - $distName = $local->path($saveName, $safeMode); - $file->move(dirname($distName), basename($distName)); - $info = $local->info($saveName, $safeMode, $file->getOriginalName()); + $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($saveName)) { + if ($this->imgNotSafe($distName) && $local->del($saveFileName)) { $this->error('图片未通过安全检查!'); } [$width, $height] = getimagesize($distName); - if (($width < 1 || $height < 1) && $local->del($saveName)) { + if (($width < 1 || $height < 1) && $local->del($saveFileName)) { $this->error('读取图片的尺寸失败!'); } } } else { $bina = file_get_contents($file->getPathname()); - $info = Storage::instance($this->getType())->set($saveName, $bina, $safeMode, $file->getOriginalName()); + $info = Storage::instance($type)->set($saveFileName, $bina, $safeMode, $file->getOriginalName()); } if (isset($info['url'])) { - $this->success('文件上传成功!', ['url' => $safeMode ? $saveName : $info['url']]); + $this->success('文件上传成功!', ['url' => $safeMode ? $saveFileName : $info['url']]); } else { $this->error('文件处理失败,请稍候再试!'); } @@ -222,7 +231,7 @@ class Upload extends Controller } /** - * 获取文件上传类型 + * 获取上传类型 * @return boolean */ private function getSafe(): bool @@ -231,11 +240,9 @@ class Upload extends Controller } /** - * 获取文件上传方式 + * 获取上传方式 * @return string - * @throws \think\db\exception\DataNotFoundException - * @throws \think\db\exception\DbException - * @throws \think\db\exception\ModelNotFoundException + * @throws \think\admin\Exception */ private function getType(): string { @@ -248,7 +255,7 @@ class Upload extends Controller } /** - * 获取本地文件对象 + * 获取文件对象 * @return UploadedFile|void */ private function getFile(): UploadedFile @@ -268,6 +275,22 @@ class Upload extends Controller } } + /** + * 初始化用户状态 + * @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 diff --git a/app/admin/view/api/icon.html b/app/admin/view/api/icon.html index 5a17622f2..88d2ddcd0 100644 --- a/app/admin/view/api/icon.html +++ b/app/admin/view/api/icon.html @@ -11,85 +11,86 @@ - + ul li div { + color: #333; + height: 35px; + font-size: 13px; + line-height: 35px; + white-space: nowrap + }
diff --git a/app/admin/view/api/upload.js b/app/admin/view/api/upload.js index 4f99b7d5d..69001aadf 100644 --- a/app/admin/view/api/upload.js +++ b/app/admin/view/api/upload.js @@ -32,7 +32,7 @@ define(['md5', 'notify'], function (SparkMD5, Notify, allowMime) { /*! 初始化上传组件 */ this.adapter = new Adapter(this.option, layui.upload.render({ - url: '{:url("admin/api.upload/file")}', auto: false, elem: elem, accept: 'file', multiple: this.option.mult, exts: this.option.exts.join('|'), acceptMime: this.option.mimes.join(','), choose: function (obj) { + url: '{:url("admin/api.upload/file",[],false,true)}', auto: false, elem: elem, accept: 'file', multiple: this.option.mult, exts: this.option.exts.join('|'), acceptMime: this.option.mimes.join(','), choose: function (obj) { obj.items = [], obj.files = obj.pushFile(); layui.each(obj.files, function (idx, file) { obj.items.push(file); @@ -108,7 +108,7 @@ define(['md5', 'notify'], function (SparkMD5, Notify, allowMime) { Adapter.prototype.request = function (file, done) { var that = this, data = {key: file.xkey, safe: that.option.safe, uptype: that.option.type}; data.size = file.size, data.name = file.name, data.hash = file.xmd5, data.mime = file.type, data.xext = file.xext; - jQuery.ajax("{:url('admin/api.upload/state')}", { + jQuery.ajax("{:url('admin/api.upload/state',[],false,true)}", { data: data, method: 'post', success: function (ret) { file.id = ret.data.id || 0, file.xurl = ret.data.url; file.xsafe = ret.data.safe, file.xpath = ret.data.key, file.xtype = ret.data.uptype; @@ -192,7 +192,7 @@ define(['md5', 'notify'], function (SparkMD5, Notify, allowMime) { /*! 检查单个文件上传返回的结果 */ if (ret.code < 1) return $.msg.tips(ret.info || '文件上传失败!'); if (typeof file.xurl !== 'string') return $.msg.tips('无效的文件上传对象!'); - jQuery.post("{:url('admin/api.upload/done')}", {id: file.id, hash: file.xmd5}); + jQuery.post("{:url('admin/api.upload/done',[],false,true)}", {id: file.id, hash: file.xmd5}); /*! 单个文件上传成功结果处理 */ if (typeof done === 'function') { done.call(this.option.elem, file.xurl, this.files['id']); diff --git a/app/admin/view/api/upload/image.html b/app/admin/view/api/upload/image.html index deeee9dd4..9248ff09a 100644 --- a/app/admin/view/api/upload/image.html +++ b/app/admin/view/api/upload/image.html @@ -109,7 +109,7 @@ loadPage: function () { this.params = {page: this.page, limit: this.limit, output: 'layui.table', name: this.keys || ''}; this.params.type = '{$get.type|default="gif,png,jpg,jpeg"}'; - $.form.load('{:url("image")}', this.params, 'get', function (ret) { + $.form.load('{:url("image",[],false,true)}', this.params, 'get', function (ret) { return app.setList(ret.data, ret.count), false; }); }, diff --git a/app/admin/view/queue/index.html b/app/admin/view/queue/index.html index 412f181d6..920fa628b 100644 --- a/app/admin/view/queue/index.html +++ b/app/admin/view/queue/index.html @@ -1,22 +1,26 @@ {extend name='table'} {block name="button"} - -优化数据库 - - +{if isset($super) and $super} + +优化数据库 + +{if isset($iswin) and ($iswin or php_sapi_name() eq 'cli')} - +{/if} - +{if auth("clean")} - +{/if} - +{/if} + +{if auth("remove")} - +{/if} + {/block} {block name="content"} diff --git a/app/wechat/controller/Menu.php b/app/wechat/controller/Menu.php index 4be1ffa47..e50add75d 100644 --- a/app/wechat/controller/Menu.php +++ b/app/wechat/controller/Menu.php @@ -78,7 +78,7 @@ class Menu extends Controller { try { WechatService::WeChatMenu()->delete(); - $this->success('菜单取消成功,重新订阅可立即生效!'); + $this->success('公众号菜单取消成功!'); } catch (HttpResponseException $exception) { sysoplog('微信管理', '取消微信菜单成功'); throw $exception; diff --git a/app/wechat/controller/api/Login.php b/app/wechat/controller/api/Login.php index c9505bc2f..c6005d100 100644 --- a/app/wechat/controller/api/Login.php +++ b/app/wechat/controller/api/Login.php @@ -16,45 +16,29 @@ namespace app\wechat\controller\api; -use app\wechat\service\MediaService; -use app\wechat\service\WechatService; +use app\wechat\service\LoginService; use think\admin\Controller; /** - * 微信扫码授权登录 + * 微信扫码登录 * Class Login * @package app\wechat\controller\api */ class Login extends Controller { /** - * 数据缓存时间 - * @var integer - */ - protected $expire = 3600; - - /** - * 授权码前缀 - * @var string - */ - protected $prefix = 'wxlogin'; - - /** - * 扫描显示二维码 + * 显示二维码 * @return void */ public function qrc() { $mode = intval(input('mode', '0')); - $code = $this->prefix . md5(uniqid('t', true) . rand(10000, 99999)); - $text = url('wechat/api.login/oauth', [], false, true) . "?code={$code}&mode={$mode}"; - // 生成二维码并返回结果 - $qrcode = MediaService::getQrcode($text); - $this->success('获取二维码成功', ['code' => $code, 'image' => $qrcode->getDataUri()]); + $data = LoginService::qrcode(LoginService::gcode(), $mode); + $this->success('登录二维码', $data); } /** - * 微信授权结果处理 + * 微信授权处理 * @throws \WeChat\Exceptions\InvalidResponseException * @throws \WeChat\Exceptions\LocalCacheException * @throws \think\admin\Exception @@ -64,41 +48,25 @@ class Login extends Controller */ public function oauth() { - $this->code = input('code', ''); - $this->mode = input('mode', '0'); - if (stripos($this->code, $this->prefix) === 0) { - $this->url = $this->request->url(true); - $this->fans = WechatService::getWebOauthInfo($this->url, $this->mode); - if (isset($this->fans['openid'])) { - $this->fans['token'] = md5(uniqid('t', true) . rand(10000, 99999)); - $this->app->cache->set("wxlogin{$this->code}", $this->fans, $this->expire); - $this->app->cache->set($this->fans['openid'], $this->fans['token'], $this->expire); - $this->message = '授权成功'; - $this->fetch('success'); - } else { - $this->message = '授权失败'; - $this->fetch('failed'); - } + $data = $this->_vali(['auth.default' => '', 'mode.default' => '0']); + if (LoginService::oauth($data['auth'], intval($data['mode']))) { + $this->fetch('success', ['message' => '授权成功']); } else { - $this->message = '授权失败'; - $this->fetch('failed'); + $this->fetch('failed', ['message' => '授权失败']); } } /** * 获取授权信息 * 用定时器请求这个接口 - * @throws \think\exception\HttpResponseException */ public function query() { - $this->code = input('code', ''); - if (stripos($this->code, $this->prefix) === 0) { - $this->ckey = "wxlogin{$this->code}"; - $this->fans = $this->app->cache->get($this->ckey, new \stdClass()); - $this->success('获取授权信息', $this->fans); + $data = $this->_vali(['code.require' => '编号不能为空!']); + if ($fans = LoginService::query($data['code'])) { + $this->success('获取授权信息', $fans); } else { - $this->error("授权CODE不能为空!"); + $this->error('未获取到授权!'); } } } \ No newline at end of file diff --git a/app/wechat/service/LoginService.php b/app/wechat/service/LoginService.php new file mode 100644 index 000000000..ee44bd186 --- /dev/null +++ b/app/wechat/service/LoginService.php @@ -0,0 +1,107 @@ + +// +---------------------------------------------------------------------- +// | 官方网站: https://thinkadmin.top +// +---------------------------------------------------------------------- +// | 开源协议 ( https://mit-license.org ) +// | 免责声明 ( https://thinkadmin.top/disclaimer ) +// +---------------------------------------------------------------------- +// | gitee 代码仓库:https://gitee.com/zoujingli/think-plugs-wechat +// | github 代码仓库:https://github.com/zoujingli/think-plugs-wechat +// +---------------------------------------------------------------------- + +namespace app\wechat\service; + +use think\admin\Library; + +/** + * 微信扫码登录服务 + * @class LoginService + * @package app\wechat\service + */ +class LoginService +{ + private const expire = 3600; + private const prefix = 'wxlogin'; + + /** + * 生成请求编号 + * @return string + */ + public static function gcode(): string + { + return md5(uniqid(strval(rand(0, 10000)), true)); + } + + /** + * 生成授权码 + * @param string $code 请求编号 + * @return string + */ + public static function gauth(string $code): string + { + return self::prefix . md5($code); + } + + /** + * 生成授权二维码 + * @param string $code 请求编号 + * @param integer $mode 授权模式 + * @return array + */ + public static function qrcode(string $code, int $mode = 0): array + { + $data = ['auth' => self::gauth($code), 'mode' => $mode]; + $image = MediaService::getQrcode(sysuri('wechat/api.login/oauth', $data, false, true)); + return ['code' => $code, 'auth' => $data['auth'], 'image' => $image->getDataUri()]; + } + + /** + * 发起网页授权处理 + * @param string $auth 授权编号 + * @param integer $mode 授权模式 + * @return boolean + * @throws \WeChat\Exceptions\InvalidResponseException + * @throws \WeChat\Exceptions\LocalCacheException + * @throws \think\admin\Exception + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public static function oauth(string $auth = '', int $mode = 0): bool + { + if (stripos($auth, self::prefix) === 0) { + $url = Library::$sapp->request->url(true); + $fans = WechatService::getWebOauthInfo($url, $mode); + if (isset($fans['openid'])) { + Library::$sapp->cache->set($auth, $fans, self::expire); + return true; + } + } + return false; + } + + /** + * 检查是否授权 + * @param string $code 请求编号 + * @return ?array + */ + public static function query(string $code): ?array + { + return Library::$sapp->cache->get(self::gauth($code)); + } + + /** + * 删除授权缓存 + * @param string $code + * @return bool + */ + public static function remove(string $code): bool + { + return Library::$sapp->cache->delete(self::gauth($code)); + } +} \ No newline at end of file diff --git a/app/wechat/view/menu/index.html b/app/wechat/view/menu/index.html index e7eeab325..7c312c22d 100644 --- a/app/wechat/view/menu/index.html +++ b/app/wechat/view/menu/index.html @@ -34,60 +34,64 @@请在左侧创建菜单...