Browse Source

增加任务进度显示

邹景立 5 years ago
parent
commit
cb2f92772e

+ 19 - 0
app/admin/controller/api/Queue.php

@@ -0,0 +1,19 @@
+<?php
+
+
+namespace app\admin\controller\api;
+
+
+use think\admin\Controller;
+use think\admin\service\QueueService;
+
+class Queue extends Controller
+{
+    public function progress()
+    {
+        $input = $this->_vali(['code.require' => '任务编号不能为空!']);
+        $result = QueueService::instance()->progress($input['code']);
+        $this->success('获取任务进度成功!', $result);
+    }
+
+}

+ 19 - 0
app/index/controller/Index.php

@@ -16,6 +16,7 @@
 namespace app\index\controller;
 
 use think\admin\Controller;
+use think\admin\service\QueueService;
 
 /**
  * Class Index
@@ -27,4 +28,22 @@ class Index extends Controller
     {
         $this->redirect(url('@admin/login'));
     }
+
+    /**
+     * 创建测试进度任务
+     * @param null $code
+     * @throws \think\Exception
+     * @throws \think\admin\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function test($code = null)
+    {
+        if (empty($code)) {
+            $code = sysqueue('测试', 'xadmin:tests');
+            $this->redirect(url("@index/index/test/code/{$code}"));
+        }
+        dump(QueueService::instance()->progress($code));
+    }
 }

+ 7 - 8
app/wechat/command/Fans.php

@@ -17,7 +17,7 @@ namespace app\wechat\command;
 
 use app\wechat\service\FansService;
 use app\wechat\service\WechatService;
-use think\console\Command;
+use think\admin\Command;
 use think\console\Input;
 use think\console\Output;
 
@@ -46,7 +46,7 @@ class Fans extends Command
      * 执行指令
      * @param Input $input
      * @param Output $output
-     * @throws \think\Exception
+     * @throws \think\admin\Exception
      */
     protected function execute(Input $input, Output $output)
     {
@@ -56,9 +56,7 @@ class Fans extends Command
                 $message .= $this->$fun();
             }
         }
-        if (defined('WorkQueueCall')) {
-            throw new \think\Exception($message, 3);
-        }
+        $this->endQueueMessage(3, $message);
     }
 
     /**
@@ -82,6 +80,7 @@ class Fans extends Command
                 if (is_array($list = WechatService::WeChatUser()->getBatchUserInfo($openids)) && !empty($list['user_info_list'])) {
                     foreach ($list['user_info_list'] as $user) {
                         $string = str_pad(++$done, strlen($result['total']), '0', STR_PAD_LEFT);
+                        $this->setQueuePropress(2, "{$user['openid']} {$user['nickname']}", $done * 100 / $result['total']);
                         $this->output->writeln("({$string}/{$result['total']}) -> {$user['openid']} {$user['nickname']}");
                         FansService::instance()->set($user, $appid);
                     }
@@ -106,16 +105,16 @@ class Fans extends Command
     public function _black($next = '', $done = 0)
     {
         $wechat = WechatService::WeChatUser();
-        $this->output->comment('--> Start to synchronize wechat blacklist users');
+        $this->output->comment('--> Start to synchronize wechat blacklist data');
         while (!is_null($next) && is_array($result = $wechat->getBlackList($next)) && !empty($result['data']['openid'])) {
             $done += $result['count'];
             foreach (array_chunk($result['data']['openid'], 100) as $chunk) {
                 $this->app->db->name('WechatFans')->where(['is_black' => '0'])->whereIn('openid', $chunk)->update(['is_black' => '1']);
             }
-            $this->output->writeln("--> Successfully synchronized {$result['total']} wechat blacklist users in total");
+            $this->output->writeln("--> 共计同步微信黑名单{$result['total']}人");
             $next = $result['total'] > $done ? $result['next_openid'] : null;
         }
-        $this->output->comment('--> Wechat blacklist users synchronization completed');
+        $this->output->comment('--> Wechat blacklist data synchronization completed');
         $this->output->newLine();
         if (empty($result['total'])) {
             return ',其中黑名单0人';

+ 30 - 0
app/wechat/command/Tests.php

@@ -0,0 +1,30 @@
+<?php
+
+
+namespace app\wechat\command;
+
+use think\admin\service\QueueService;
+use think\console\Command;
+use think\console\Input;
+use think\console\Output;
+
+class Tests extends Command
+{
+    protected function configure()
+    {
+        $this->setName('xadmin:tests')->setDescription('指令类任务测试');
+    }
+
+    protected function execute(Input $input, Output $output)
+    {
+        $max = 100;
+        for ($i = 0; $i < $max; $i++) {
+            echo $i . PHP_EOL;
+            if (defined('WorkQueueCode')) {
+                QueueService::instance()->progress(WorkQueueCode, 2, "已经完成了 $i 的计算", $i / $max * 100);
+            }
+            sleep(1);
+        }
+    }
+
+}

+ 2 - 2
app/wechat/controller/Fans.php

@@ -71,8 +71,8 @@ class Fans extends Controller
     public function sync()
     {
         try {
-            sysqueue('同步微信用户数据', "xadmin:fansall", 1, [], 0);
-            $this->success('创建任务成功,请等待完成!');
+            $code = sysqueue('同步微信用户数据', "xadmin:fansall", 1, [], 0);
+            $this->success('创建任务成功,请等待完成!', $code);
         } catch (HttpResponseException $exception) {
             throw $exception;
         } catch (\Exception $exception) {

+ 1 - 0
app/wechat/sys.php

@@ -4,4 +4,5 @@ use think\Console;
 
 Console::starting(function (Console $console) {
     $console->addCommand('app\wechat\command\Fans');
+    $console->addCommand('app\wechat\command\Tests');
 });

+ 1 - 1
app/wechat/view/fans/index.html

@@ -11,7 +11,7 @@
 {/if}
 
 {if auth("sync")}
-<button data-load='{:url("sync")}' data-confirm="是否要创建后台任务同步用户数据?" class='layui-btn layui-btn-sm layui-btn-primary'>同步用户数据</button>
+<button data-queue='{:url("sync")}' data-confirm="是否要创建后台任务同步用户数据?" class='layui-btn layui-btn-sm layui-btn-primary'>同步用户数据</button>
 {/if}
 
 {/block}

+ 9 - 9
composer.lock

@@ -74,16 +74,16 @@
         },
         {
             "name": "league/flysystem",
-            "version": "1.0.65",
+            "version": "1.0.66",
             "source": {
                 "type": "git",
                 "url": "https://github.com/thephpleague/flysystem.git",
-                "reference": "8f17b3ba67097aafb8318cd5c553b1acf7c891c8"
+                "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8f17b3ba67097aafb8318cd5c553b1acf7c891c8",
-                "reference": "8f17b3ba67097aafb8318cd5c553b1acf7c891c8",
+                "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/021569195e15f8209b1c4bebb78bd66aa4f08c21",
+                "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21",
                 "shasum": "",
                 "mirrors": [
                     {
@@ -160,7 +160,7 @@
                 "sftp",
                 "storage"
             ],
-            "time": "2020-03-08T18:53:20+00:00"
+            "time": "2020-03-17T18:58:12+00:00"
         },
         {
             "name": "league/flysystem-cached-adapter",
@@ -909,12 +909,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/zoujingli/ThinkLibrary.git",
-                "reference": "40ecfc8d32b1aff78de297c28ec7886b6dbf6643"
+                "reference": "3283e44ab0cce56c4054623497ff4f4fec195374"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/40ecfc8d32b1aff78de297c28ec7886b6dbf6643",
-                "reference": "40ecfc8d32b1aff78de297c28ec7886b6dbf6643",
+                "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/3283e44ab0cce56c4054623497ff4f4fec195374",
+                "reference": "3283e44ab0cce56c4054623497ff4f4fec195374",
                 "shasum": "",
                 "mirrors": [
                     {
@@ -958,7 +958,7 @@
             ],
             "description": "ThinkPHP v6.0 Development Library",
             "homepage": "http://framework.thinkadmin.top",
-            "time": "2020-03-12T02:42:38+00:00"
+            "time": "2020-03-22T13:13:51+00:00"
         },
         {
             "name": "zoujingli/wechat-developer",

+ 60 - 0
public/static/admin.js

@@ -735,6 +735,66 @@ $(function () {
         })
     });
 
+    /*! 异步任务状态监听与展示 */
+    $body.on('click', '[data-queue]', function () {
+        this.action = this.getAttribute('data-queue') || '';
+        if (this.action.length < 1) return $.msg.tips('任务地址不能为空!');
+        $.form.load(this.action, {}, 'post', function (ret) {
+            if (typeof ret.data === 'string' && ret.data.indexOf('Q') === 0) {
+                $.msg.tips(ret.msg);
+                return $.loadQueue(ret.data), false;
+            }
+        });
+    });
+    $.loadQueue = function (code) {
+        //自定页
+        layer.open({
+            type: 1, title: false, area: [500, 300], anim: 2, shadeClose: false, content: '' +
+                '<div class="padding-30" data-queue-code-loading="' + code + '" style="width:500px;height:300px">' +
+                '   <div class="margin-top-15" data-message-state></div>' +
+                '   <div class="margin-top-15" data-message-title></div>' +
+                '   <div class="margin-top-15 layui-progress layui-progress-big" lay-showPercent="yes">' +
+                '       <div class="layui-progress-bar" lay-percent="0.00%"></div>' +
+                '   </div>' +
+                '   <textarea class="margin-top-15 layui-textarea transition color-text" disabled style="resize:none"></textarea>' +
+                '</div>'
+        });
+        (function loadprocess(code, $box) {
+            $box = $('[data-queue-code-loading=' + code + ']');
+            if ($box.length < 1) return false;
+            $.form.load(window.ROOT_URL + '?s=admin/api.queue/progress', {code: code}, 'post', function (ret) {
+                if (ret.code) {
+                    (function (lines) {
+                        this.lines = [];
+                        for (this.i in lines) {
+                            this.lines.push('[ ' + lines[this.i].progress + '% ] ' + lines[this.i].message);
+                        }
+                        this.$textarea = $box.find('textarea').val(this.lines.join("\n"));
+                        this.$textarea.animate({scrollTop: this.$textarea[0].scrollHeight + 'px'}, 800)
+                    })(ret.data.history);
+                    $box.find('.layui-progress div').attr('lay-percent', ret.data.progress + '%');
+                    $box.find('[data-message-title]').html(ret.data.message);
+                    layui.element.render();
+                    this.status = parseInt(ret.data.status);
+                    if (this.status === 1) {
+                        $box.find('[data-message-state]').html('处理状态:<b>任务创建成功</b>');
+                    } else if (this.status === 2) {
+                        $box.find('[data-message-state]').html('处理状态:<b class="color-blue">任务正在处理</b>');
+                    } else if (this.status === 3) {
+                        $box.find('[data-message-state]').html('处理状态:<b class="color-green">任务处理完成</b>');
+                        return false;
+                    } else if (this.status === 4) {
+                        $box.find('[data-message-state]').html('处理状态:<b class="color-red">任务处理失败</b>');
+                        return false;
+                    }
+                }
+                return setTimeout(function () {
+                    loadprocess(code);
+                }, 1000), false;
+            }, false);
+        })(code)
+    };
+
     /*! 表单元素失去焦点处理 */
     $body.on('blur', '[data-blur-number]', function (fiexd) {
         fiexd = this.getAttribute('data-blur-number') || 0;

+ 4 - 0
vendor/composer/autoload_classmap.php

@@ -198,10 +198,12 @@ return array(
     'app\\admin\\controller\\Queue' => $baseDir . '/app/admin/controller/Queue.php',
     'app\\admin\\controller\\User' => $baseDir . '/app/admin/controller/User.php',
     'app\\admin\\controller\\api\\Plugs' => $baseDir . '/app/admin/controller/api/Plugs.php',
+    'app\\admin\\controller\\api\\Queue' => $baseDir . '/app/admin/controller/api/Queue.php',
     'app\\admin\\controller\\api\\Update' => $baseDir . '/app/admin/controller/api/Update.php',
     'app\\admin\\controller\\api\\Upload' => $baseDir . '/app/admin/controller/api/Upload.php',
     'app\\index\\controller\\Index' => $baseDir . '/app/index/controller/Index.php',
     'app\\wechat\\command\\Fans' => $baseDir . '/app/wechat/command/Fans.php',
+    'app\\wechat\\command\\Tests' => $baseDir . '/app/wechat/command/Tests.php',
     'app\\wechat\\controller\\Config' => $baseDir . '/app/wechat/controller/Config.php',
     'app\\wechat\\controller\\Fans' => $baseDir . '/app/wechat/controller/Fans.php',
     'app\\wechat\\controller\\Keys' => $baseDir . '/app/wechat/controller/Keys.php',
@@ -246,7 +248,9 @@ return array(
     'think\\Template' => $vendorDir . '/topthink/think-template/src/Template.php',
     'think\\Validate' => $vendorDir . '/topthink/framework/src/think/Validate.php',
     'think\\View' => $vendorDir . '/topthink/framework/src/think/View.php',
+    'think\\admin\\Command' => $vendorDir . '/zoujingli/think-library/src/Command.php',
     'think\\admin\\Controller' => $vendorDir . '/zoujingli/think-library/src/Controller.php',
+    'think\\admin\\Exception' => $vendorDir . '/zoujingli/think-library/src/Exception.php',
     'think\\admin\\Helper' => $vendorDir . '/zoujingli/think-library/src/Helper.php',
     'think\\admin\\Library' => $vendorDir . '/zoujingli/think-library/src/Library.php',
     'think\\admin\\Service' => $vendorDir . '/zoujingli/think-library/src/Service.php',

+ 4 - 0
vendor/composer/autoload_static.php

@@ -331,10 +331,12 @@ class ComposerStaticInit9eebf462f38fc6a0db482795c8caf813
         'app\\admin\\controller\\Queue' => __DIR__ . '/../..' . '/app/admin/controller/Queue.php',
         'app\\admin\\controller\\User' => __DIR__ . '/../..' . '/app/admin/controller/User.php',
         'app\\admin\\controller\\api\\Plugs' => __DIR__ . '/../..' . '/app/admin/controller/api/Plugs.php',
+        'app\\admin\\controller\\api\\Queue' => __DIR__ . '/../..' . '/app/admin/controller/api/Queue.php',
         'app\\admin\\controller\\api\\Update' => __DIR__ . '/../..' . '/app/admin/controller/api/Update.php',
         'app\\admin\\controller\\api\\Upload' => __DIR__ . '/../..' . '/app/admin/controller/api/Upload.php',
         'app\\index\\controller\\Index' => __DIR__ . '/../..' . '/app/index/controller/Index.php',
         'app\\wechat\\command\\Fans' => __DIR__ . '/../..' . '/app/wechat/command/Fans.php',
+        'app\\wechat\\command\\Tests' => __DIR__ . '/../..' . '/app/wechat/command/Tests.php',
         'app\\wechat\\controller\\Config' => __DIR__ . '/../..' . '/app/wechat/controller/Config.php',
         'app\\wechat\\controller\\Fans' => __DIR__ . '/../..' . '/app/wechat/controller/Fans.php',
         'app\\wechat\\controller\\Keys' => __DIR__ . '/../..' . '/app/wechat/controller/Keys.php',
@@ -379,7 +381,9 @@ class ComposerStaticInit9eebf462f38fc6a0db482795c8caf813
         'think\\Template' => __DIR__ . '/..' . '/topthink/think-template/src/Template.php',
         'think\\Validate' => __DIR__ . '/..' . '/topthink/framework/src/think/Validate.php',
         'think\\View' => __DIR__ . '/..' . '/topthink/framework/src/think/View.php',
+        'think\\admin\\Command' => __DIR__ . '/..' . '/zoujingli/think-library/src/Command.php',
         'think\\admin\\Controller' => __DIR__ . '/..' . '/zoujingli/think-library/src/Controller.php',
+        'think\\admin\\Exception' => __DIR__ . '/..' . '/zoujingli/think-library/src/Exception.php',
         'think\\admin\\Helper' => __DIR__ . '/..' . '/zoujingli/think-library/src/Helper.php',
         'think\\admin\\Library' => __DIR__ . '/..' . '/zoujingli/think-library/src/Library.php',
         'think\\admin\\Service' => __DIR__ . '/..' . '/zoujingli/think-library/src/Service.php',

+ 10 - 10
vendor/composer/installed.json

@@ -69,17 +69,17 @@
     },
     {
         "name": "league/flysystem",
-        "version": "1.0.65",
-        "version_normalized": "1.0.65.0",
+        "version": "1.0.66",
+        "version_normalized": "1.0.66.0",
         "source": {
             "type": "git",
             "url": "https://github.com/thephpleague/flysystem.git",
-            "reference": "8f17b3ba67097aafb8318cd5c553b1acf7c891c8"
+            "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8f17b3ba67097aafb8318cd5c553b1acf7c891c8",
-            "reference": "8f17b3ba67097aafb8318cd5c553b1acf7c891c8",
+            "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/021569195e15f8209b1c4bebb78bd66aa4f08c21",
+            "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21",
             "shasum": "",
             "mirrors": [
                 {
@@ -115,7 +115,7 @@
             "spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
             "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
         },
-        "time": "2020-03-08T18:53:20+00:00",
+        "time": "2020-03-17T18:58:12+00:00",
         "type": "library",
         "extra": {
             "branch-alias": {
@@ -935,12 +935,12 @@
         "source": {
             "type": "git",
             "url": "https://github.com/zoujingli/ThinkLibrary.git",
-            "reference": "40ecfc8d32b1aff78de297c28ec7886b6dbf6643"
+            "reference": "3283e44ab0cce56c4054623497ff4f4fec195374"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/40ecfc8d32b1aff78de297c28ec7886b6dbf6643",
-            "reference": "40ecfc8d32b1aff78de297c28ec7886b6dbf6643",
+            "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/3283e44ab0cce56c4054623497ff4f4fec195374",
+            "reference": "3283e44ab0cce56c4054623497ff4f4fec195374",
             "shasum": "",
             "mirrors": [
                 {
@@ -956,7 +956,7 @@
             "ext-json": "*",
             "topthink/framework": "^6.0"
         },
-        "time": "2020-03-12T02:42:38+00:00",
+        "time": "2020-03-22T13:13:51+00:00",
         "type": "library",
         "extra": {
             "think": {

+ 6 - 0
vendor/league/flysystem/composer.json

@@ -7,6 +7,12 @@
         "abstraction", "s3", "ftp", "sftp", "remote", "webdav",
         "file systems", "cloud", "cloud files", "rackspace", "copy.com"
     ],
+    "funding": [
+        {
+            "type": "other",
+            "url": "https://offset.earth/frankdejonge"
+        }
+    ],
     "license": "MIT",
     "authors": [
         {

+ 3 - 3
vendor/league/flysystem/src/Adapter/Ftp.php

@@ -131,9 +131,9 @@ class Ftp extends AbstractFtpAdapter
     public function connect()
     {
         if ($this->ssl) {
-            $this->connection = ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
+            $this->connection = @ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
         } else {
-            $this->connection = ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
+            $this->connection = @ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
         }
 
         if ( ! $this->connection) {
@@ -230,7 +230,7 @@ class Ftp extends AbstractFtpAdapter
     public function disconnect()
     {
         if (is_resource($this->connection)) {
-            ftp_close($this->connection);
+            @ftp_close($this->connection);
         }
 
         $this->connection = null;

+ 1 - 1
vendor/services.php

@@ -1,5 +1,5 @@
 <?php 
-// This file is automatically generated at:2020-03-17 13:25:46
+// This file is automatically generated at:2020-03-22 21:37:43
 declare (strict_types = 1);
 return array (
   0 => 'think\\app\\Service',

+ 82 - 0
vendor/zoujingli/think-library/src/Command.php

@@ -0,0 +1,82 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | Library for ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2020 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: https://gitee.com/zoujingli/ThinkLibrary
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 仓库地址 :https://gitee.com/zoujingli/ThinkLibrary
+// | github 仓库地址 :https://github.com/zoujingli/ThinkLibrary
+// +----------------------------------------------------------------------
+
+namespace think\admin;
+
+use think\admin\service\ProcessService;
+use think\admin\service\QueueService;
+use think\console\Command as ThinkCommand;
+use think\console\Input;
+use think\console\Output;
+
+/**
+ * 自定义指令基类
+ * Class Command
+ * @package think\admin
+ */
+class Command extends ThinkCommand
+{
+    /**
+     * @var QueueService
+     */
+    protected $queue;
+
+    /**
+     * @var ProcessService
+     */
+    protected $process;
+
+    /**
+     * 初始化指令变量
+     * @param Input $input
+     * @param Output $output
+     */
+    protected function initialize(Input $input, Output $output)
+    {
+        $this->queue = QueueService::instance();
+        $this->process = ProcessService::instance();
+    }
+
+    /**
+     * 设置当前任务进度
+     * @param null|integer $status 任务状态
+     * @param null|string $message 进度消息
+     * @param null|integer $progress 进度数值
+     * @return Command
+     */
+    protected function setQueuePropress($status = null, $message = null, $progress = null)
+    {
+        if (defined('WorkQueueCode')) {
+            $this->queue->progress(WorkQueueCode, $status, $message, $progress);
+        }
+        return $this;
+    }
+
+    /**
+     * 结束任务并设置状态消息
+     * @param integer $status 任务状态
+     * @param string $message 消息内容
+     * @return Command
+     * @throws Exception
+     */
+    protected function endQueueMessage($status, $message)
+    {
+        if (defined('WorkQueueCode')) {
+            throw new Exception($message, $status);
+        }
+        return $this;
+    }
+
+}

+ 45 - 0
vendor/zoujingli/think-library/src/Exception.php

@@ -0,0 +1,45 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | Library for ThinkAdmin
+// +----------------------------------------------------------------------
+// | 版权所有 2014~2020 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
+// +----------------------------------------------------------------------
+// | 官方网站: https://gitee.com/zoujingli/ThinkLibrary
+// +----------------------------------------------------------------------
+// | 开源协议 ( https://mit-license.org )
+// +----------------------------------------------------------------------
+// | gitee 仓库地址 :https://gitee.com/zoujingli/ThinkLibrary
+// | github 仓库地址 :https://github.com/zoujingli/ThinkLibrary
+// +----------------------------------------------------------------------
+
+namespace think\admin;
+
+/**
+ * 自定义数据异常
+ * Class Exception
+ * @package think\admin
+ */
+class Exception extends \Exception
+{
+    /**
+     * 异常数据对象
+     * @var array
+     */
+    protected $data = [];
+
+    /**
+     * Exception constructor.
+     * @param string $message
+     * @param integer $code
+     * @param array $data
+     */
+    public function __construct($message = "", $code = 0, $data = [])
+    {
+        $this->data = $data;
+        $this->code = $code;
+        $this->message = $message;
+        parent::__construct($message, $code);
+    }
+
+}

+ 3 - 1
vendor/zoujingli/think-library/src/Library.php

@@ -36,6 +36,8 @@ class Library extends Service
         // 加载中文语言
         $this->app->lang->load(__DIR__ . '/lang/zh-cn.php', 'zh-cn');
         $this->app->lang->load(__DIR__ . '/lang/en-us.php', 'en-us');
+        // 输入变量默认过滤
+        $this->app->request->filter(['trim']);
         // 判断访问模式,兼容 CLI 访问控制器
         if ($this->app->request->isCli()) {
             if (empty($_SERVER['REQUEST_URI']) && isset($_SERVER['argv'][1])) {
@@ -59,7 +61,7 @@ class Library extends Service
                 if ($request->isOptions()) {
                     return response()->code(204)->header($header);
                 } elseif (AdminService::instance()->check()) {
-                    return $next($request)->code(200)->header($header);
+                    return $next($request)->header($header);
                 } elseif (AdminService::instance()->isLogin()) {
                     return json(['code' => 0, 'msg' => lang('think_library_not_auth')])->header($header);
                 } else {

+ 1 - 1
vendor/zoujingli/think-library/src/command/Queue.php

@@ -15,8 +15,8 @@
 
 namespace think\admin\command;
 
+use think\admin\Command;
 use think\admin\service\ProcessService;
-use think\console\Command;
 use think\console\Input;
 use think\console\Output;
 

+ 1 - 3
vendor/zoujingli/think-library/src/command/queue/CleanQueue.php

@@ -63,9 +63,7 @@ class CleanQueue extends Queue
             $count2 = $this->app->db->name($this->table)->where($map)->update(['status' => '4', 'exec_desc' => '执行等待超过60分钟无响应']);
             $this->output->info("Successfully processed {$count2} unresponsive records waiting for more than 1 hour");
             // 返回消息到任务状态描述
-            if (defined('WorkQueueCall')) {
-                throw new \think\Exception("清理七天前{$count1}条记录,标志{$count2}条超60分钟无响应的任务", 3);
-            }
+            if (defined('WorkQueueCall')) throw new \think\Exception("清理 {$count1} 条 + 无响应 {$count2} 条", 3);
         }
     }
 }

+ 12 - 1
vendor/zoujingli/think-library/src/command/queue/WorkQueue.php

@@ -74,11 +74,14 @@ class WorkQueue extends Queue
                     'enter_time' => microtime(true), 'attempts' => $this->app->db->raw('attempts+1'),
                     'outer_time' => '0', 'exec_pid' => getmypid(), 'exec_desc' => '', 'status' => '2',
                 ]);
+                QueueService::instance()->progress($this->code, 2, '>>> 任务处理开始!', 0);
                 // 设置进程标题
                 if ($this->process->iswin()) {
                     $this->setProcessTitle("ThinkAdmin {$this->process->version()} Queue - {$this->queue['title']}");
                 }
                 // 执行任务内容
+                defined('WorkQueueCall') or define('WorkQueueCall', true);
+                defined('WorkQueueCode') or define('WorkQueueCode', $this->code);
                 if (class_exists($command = $this->queue['command'])) {
                     // 自定义服务,支持返回消息(支持异常结束,异常码可选择 3|4 设置任务状态)
                     if ($command instanceof QueueService) {
@@ -89,7 +92,6 @@ class WorkQueue extends Queue
                     }
                 } else {
                     // 自定义指令,不支持返回消息(支持异常结束,异常码可选择 3|4 设置任务状态)
-                    defined('WorkQueueCall') or define('WorkQueueCall', true);
                     $attr = explode(' ', trim(preg_replace('|\s+|', ' ', $this->queue['command'])));
                     $this->update('3', $this->app->console->call(array_shift($attr), $attr)->fetch(), false);
                 }
@@ -117,6 +119,15 @@ class WorkQueue extends Queue
             'status' => $status, 'outer_time' => microtime(true), 'exec_pid' => getmypid(), 'exec_desc' => $desc[0],
         ]);
         $this->output->writeln(is_string($message) ? $message : '');
+        // 任务进度标记
+        if (!empty($desc[0])) {
+            QueueService::instance()->progress($this->code, $status, ">>> {$desc[0]}");
+        }
+        if ($status == 3) {
+            QueueService::instance()->progress($this->code, $status, '>>> 任务处理完成!', 100);
+        } elseif ($status == 4) {
+            QueueService::instance()->progress($this->code, $status, '>>> 任务处理失败!');
+        }
         // 注册循环任务
         if (isset($this->queue['loops_time']) && $this->queue['loops_time'] > 0) {
             try {

+ 3 - 2
vendor/zoujingli/think-library/src/common.php

@@ -92,15 +92,16 @@ if (!function_exists('sysqueue')) {
      * @param array $data 任务附加数据
      * @param integer $rscript 任务类型(0单例,1多例)
      * @param integer $loops 循环等待时间
-     * @return QueueService
+     * @return string
      * @throws \think\Exception
+     * @throws \think\admin\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
     function sysqueue($title, $command, $later = 0, $data = [], $rscript = 1, $loops = 0)
     {
-        return QueueService::instance()->register($title, $command, $later, $data, $rscript, $loops);
+        return QueueService::instance()->register($title, $command, $later, $data, $rscript, $loops)->code;
     }
 }
 if (!function_exists('systoken')) {

+ 15 - 2
vendor/zoujingli/think-library/src/service/ExpressService.php

@@ -38,14 +38,27 @@ class ExpressService extends Service
     protected $options;
 
     /**
+     * 会话Cookie文件
+     * @var string
+     */
+    protected $cookies = '';
+
+    /**
      * 快递服务初始化
      * @return $this
      */
     protected function initialize()
     {
+        $this->cookies = "{$this->app->getRuntimePath()}_express_cookie.txt";
+        if (file_exists($this->cookies) && filemtime($this->cookies) + 10 < time()) {
+            @unlink($this->cookies);
+        }
         $this->options = [
-            'cookie_file' => $this->app->getRuntimePath() . '_express_cookie.txt',
-            'headers'     => ['Host' => 'express.baidu.com', 'X-FORWARDED-FOR' => $this->app->request->ip()],
+            'cookie_file' => $this->cookies, 'headers' => [
+                'Host'            => 'express.baidu.com',
+                'CLIENT-IP'       => $this->app->request->ip(),
+                'X-FORWARDED-FOR' => $this->app->request->ip(),
+            ],
         ];
         $this->token = $this->getExpressToken();
         return $this;

+ 63 - 5
vendor/zoujingli/think-library/src/service/QueueService.php

@@ -15,8 +15,10 @@
 
 namespace think\admin\service;
 
+use think\admin\Exception;
 use think\admin\extend\CodeExtend;
 use think\admin\Service;
+use think\exception\InvalidArgumentException;
 
 /**
  * 任务基础服务
@@ -28,7 +30,7 @@ class QueueService extends Service
 
     /**
      * 当前任务编号
-     * @var integer
+     * @var string
      */
     protected $code = 0;
 
@@ -76,6 +78,18 @@ class QueueService extends Service
     }
 
     /**
+     * 获取当前对象值
+     * @param string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        if (isset($this->$name)) {
+            return $this->$name;
+        }
+    }
+
+    /**
      * 判断是否WIN环境
      * @return boolean
      */
@@ -108,6 +122,7 @@ class QueueService extends Service
 
     /**
      * 添加清理7天前的记录及超时任务
+     * @throws Exception
      * @throws \think\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
@@ -121,12 +136,13 @@ class QueueService extends Service
     /**
      * 注册异步处理任务
      * @param string $title 任务名称
-     * @param string $command 执行内容
+     * @param string $command 执行脚本
      * @param integer $later 延时时间
      * @param array $data 任务附加数据
      * @param integer $rscript 任务类型(0单例,1多例)
      * @param integer $loops 循环等待时间
      * @return $this
+     * @throws Exception
      * @throws \think\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DbException
@@ -135,11 +151,11 @@ class QueueService extends Service
     public function register($title, $command, $later = 0, $data = [], $rscript = 1, $loops = 0)
     {
         $map = [['title', '=', $title], ['status', 'in', ['1', '2']]];
-        if (empty($rscript) && $this->app->db->name('SystemQueue')->where($map)->count() > 0) {
-            throw new \think\Exception(lang('think_library_queue_exist'));
+        if (empty($rscript) && ($queue = $this->app->db->name('SystemQueue')->where($map)->find())) {
+            throw new Exception(lang('think_library_queue_exist'), 0, $queue);
         }
         $this->app->db->name('SystemQueue')->strict(false)->failException(true)->insert([
-            'code'       => $this->code = 'QE' . CodeExtend::uniqidDate(16),
+            'code'       => $this->code = CodeExtend::uniqidDate(16, 'Q'),
             'title'      => $title,
             'command'    => $command,
             'attempts'   => '0',
@@ -150,10 +166,52 @@ class QueueService extends Service
             'outer_time' => '0',
             'loops_time' => $loops,
         ]);
+        $this->progress($this->code, 1, '>>> 任务创建成功!', 0.00);
         return $this->initialize($this->code);
     }
 
     /**
+     * 更新任务进度信息
+     * @param string $code 任务编号
+     * @param null|integer $status 任务状态
+     * @param null|string $message 进度消息
+     * @param null|integer $progress 进度数值
+     * @return array
+     */
+    public function progress($code, $status = null, $message = null, $progress = null)
+    {
+        $ckey = "queue_{$code}_progress";
+        $data = $this->app->cache->get($ckey, [
+            'code'     => $code,
+            'status'   => $status,
+            'message'  => $message,
+            'progress' => $progress,
+            'history'  => [],
+        ]);
+        if (is_numeric($progress)) {
+            $progress = sprintf("%.2f", $progress);
+        }
+        if (is_string($message) && is_null($progress)) {
+            $data['message'] = $message;
+            $data['history'][] = ['message' => $message, 'progress' => $data['progress']];
+        } elseif (is_null($message) && is_numeric($progress)) {
+            $data['progress'] = $progress;
+            $data['history'][] = ['message' => $data['message'], 'progress' => $progress];
+        } elseif (is_string($message) && is_numeric($progress)) {
+            $data['message'] = $message;
+            $data['progress'] = $progress;
+            $data['history'][] = ['message' => $message, 'progress' => $progress];
+        }
+        if (is_numeric($status)) {
+            $data['status'] = intval($status);
+        }
+        if (is_string($message) || is_numeric($progress)) {
+            $this->app->cache->set($ckey, $data);
+        }
+        return $data;
+    }
+
+    /**
      * 执行任务处理
      * @param array $data 任务参数
      * @return mixed