ComposerUpdate

This commit is contained in:
Anyon 2020-01-07 10:40:48 +08:00
parent 191c59d543
commit 76e78af89b
17 changed files with 316 additions and 96 deletions

View File

@ -19,6 +19,7 @@ use library\Controller;
use library\service\AdminService; use library\service\AdminService;
use library\service\CaptchaService; use library\service\CaptchaService;
use library\service\SystemService; use library\service\SystemService;
use library\tools\Data;
use think\Db; use think\Db;
use think\facade\Request; use think\facade\Request;
@ -45,11 +46,10 @@ class Login extends Controller
$this->redirect('@admin'); $this->redirect('@admin');
} else { } else {
$this->title = '系统登录'; $this->title = '系统登录';
if (!($this->loginskey = session('loginskey'))) { $this->captcha_type = 'login_captcha';
session('loginskey', $this->loginskey = uniqid()); $this->captcha_token = Data::uniqidDateCode(18);
} $this->app->session->set($this->captcha_type, $this->captcha_token);
$this->devmode = SystemService::instance()->checkRunMode('dev'); $this->devmode = SystemService::instance()->checkRunMode('dev');
$this->captcha = CaptchaService::instance()->getAttrs();
$this->fetch(); $this->fetch();
} }
} else { } else {
@ -59,7 +59,7 @@ class Login extends Controller
'password.require' => '登录密码不能为空!', 'password.require' => '登录密码不能为空!',
'password.min:4' => '登录密码长度不能少于4位有效字符', 'password.min:4' => '登录密码长度不能少于4位有效字符',
'verify.require' => '图形验证码不能为空!', 'verify.require' => '图形验证码不能为空!',
'uniqid.require' => '图形验证标识不能为空!' 'uniqid.require' => '图形验证标识不能为空!',
]); ]);
if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) { if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
$this->error('图形验证码验证失败,请重新输入!'); $this->error('图形验证码验证失败,请重新输入!');
@ -67,22 +67,44 @@ class Login extends Controller
// 用户信息验证 // 用户信息验证
$map = ['is_deleted' => '0', 'username' => $data['username']]; $map = ['is_deleted' => '0', 'username' => $data['username']];
$user = Db::name('SystemUser')->where($map)->order('id desc')->find(); $user = Db::name('SystemUser')->where($map)->order('id desc')->find();
if (empty($user)) $this->error('登录账号或密码错误,请重新输入!'); if (empty($user)) {
if (md5($user['password'] . session('loginskey')) !== $data['password']) { $this->error('登录账号或密码错误请重新输入1!');
$this->error('登录账号或密码错误,请重新输入!'); }
if (md5("{$user['password']}{$data['uniqid']}") !== $data['password']) {
$this->error('登录账号或密码错误请重新输入2!');
}
if (empty($user['status'])) {
$this->error('账号已经被禁用,请联系管理员!');
} }
if (empty($user['status'])) $this->error('账号已经被禁用,请联系管理员!');
Db::name('SystemUser')->where(['id' => $user['id']])->update([ Db::name('SystemUser')->where(['id' => $user['id']])->update([
'login_at' => Db::raw('now()'), 'login_ip' => Request::ip(), 'login_num' => Db::raw('login_num+1'), 'login_ip' => Request::ip(),
'login_at' => Db::raw('now()'),
'login_num' => Db::raw('login_num+1'),
]); ]);
session('user', $user); $this->app->session->set('user', $user);
session('loginskey', null);
AdminService::instance()->apply(true); AdminService::instance()->apply(true);
sysoplog('系统管理', '用户登录系统成功'); sysoplog('系统管理', '用户登录系统后台成功');
$this->success('登录成功', url('@admin')); $this->success('登录成功', url('@admin'));
} }
} }
/**
* 生成验证码
* 需要指定类型及令牌
*/
public function captcha()
{
$image = CaptchaService::instance();
$this->type = input('type', 'captcha-type');
$this->token = input('token', 'captcha-token');
$captcha = ['image' => $image->getData(), 'uniqid' => $image->getUniqid()];
if ($this->app->session->get($this->type) === $this->token) {
$captcha['code'] = $image->getCode();
$this->app->session->delete($this->type);
}
$this->success('生成验证码成功', $captcha);
}
/** /**
* 退出登录 * 退出登录
*/ */

View File

@ -1,4 +1,4 @@
{extend name="admin@index/index"} {extend name="index/index"}
{block name="body"} {block name="body"}
<div class="login-container" data-supersized="__ROOT__/static/theme/img/login/bg1.jpg,__ROOT__/static/theme/img/login/bg2.jpg"> <div class="login-container" data-supersized="__ROOT__/static/theme/img/login/bg1.jpg,__ROOT__/static/theme/img/login/bg2.jpg">
@ -28,13 +28,11 @@
<li class="verify layui-hide"> <li class="verify layui-hide">
<label class="inline-block relative"> <label class="inline-block relative">
<i class="layui-icon layui-icon-picture-fine"></i> <i class="layui-icon layui-icon-picture-fine"></i>
<input class="layui-input" required pattern="^\S{4,}$" name="verify" value="{$captcha.code}" maxlength="4" autocomplete="off" placeholder="验证码" title="请输入验证码"> <input class="layui-input" required pattern="^\S{4,}$" name="verify" maxlength="4" autocomplete="off" placeholder="验证码" title="请输入验证码">
</label> </label>
<img data-refresh-captcha alt="img" src="{$captcha.data}"> <label data-captcha="{:url('admin/login/captcha',[],false)}" data-field-verify="verify" data-field-uniqid="uniqid" data-captcha-type="{$captcha_type}" data-captcha-token="{$captcha_token}"></label>
<input type="hidden" name="uniqid" value="{$captcha.uniqid}">
</li> </li>
<li class="text-center padding-top-20"> <li class="text-center padding-top-20">
<input type="hidden" name="skey" value="{$loginskey|default=''}">
<button type="submit" class="layui-btn layui-disabled full-width" data-form-loaded="立即登入">正在载入</button> <button type="submit" class="layui-btn layui-disabled full-width" data-form-loaded="立即登入">正在载入</button>
</li> </li>
</ul> </ul>
@ -54,5 +52,6 @@
{/block} {/block}
{block name='script'} {block name='script'}
<script src="__ROOT__/static/login.js"></script>
<script src="__ROOT__/static/plugs/supersized/supersized.3.2.7.min.js"></script> <script src="__ROOT__/static/plugs/supersized/supersized.3.2.7.min.js"></script>
{/block} {/block}

View File

@ -746,35 +746,6 @@ $(function () {
this.value = (parseFloat(this.value) || 0).toFixed(fiexd); this.value = (parseFloat(this.value) || 0).toFixed(fiexd);
}); });
/*! 后台加密登录处理 */
$body.find('[data-login-form]').map(function (that) {
that = this;
require(["md5"], function (md5) {
$("form").vali(function (data) {
data['password'] = md5.hash(md5.hash(data['password']) + data['skey']);
if (data['skey']) delete data['skey'];
$.form.load(location.href, data, "post", function (ret) {
if (parseInt(ret.code) !== 1) {
$(that).find('.verify.layui-hide').removeClass('layui-hide');
$(that).find('[data-refresh-captcha]').trigger('click');
}
}, null, null, 'false');
});
});
});
/*! 后台图形验证码刷新 */
$body.on('click', '[data-refresh-captcha]', function (image, verify, uniqid) {
image = this, uniqid = this.getAttribute('data-uniqid-field') || 'uniqid';
verify = this.getAttribute('data-refresh-captcha') || this.getAttribute('data-verify-field') || 'verify';
$.form.load('?s=think/admin/captcha', {}, 'get', function (ret) {
image.src = ret.data.image;
$(image).parents('form').find('[name=' + verify + ']').attr('value', '');
$(image).parents('form').find('[name=' + uniqid + ']').val(ret.data.uniqid);
return false;
}, false);
});
/*! 图片加载异常处理 */ /*! 图片加载异常处理 */
document.addEventListener('error', function (e, elem) { document.addEventListener('error', function (e, elem) {
elem = e.target; elem = e.target;

62
public/static/login.js Normal file
View File

@ -0,0 +1,62 @@
// +----------------------------------------------------------------------
// | ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: http://demo.thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/ThinkAdmin
// | github 代码仓库https://github.com/zoujingli/ThinkAdmin
// +----------------------------------------------------------------------
$(function () {
window.$body = $('body');
/*! 后台加密登录处理 */
$body.find('[data-login-form]').map(function (that) {
that = this;
require(["md5"], function (md5) {
$("form").vali(function (data) {
data['password'] = md5.hash(md5.hash(data['password']) + data['uniqid']);
$.form.load(location.href, data, "post", function (ret) {
if (parseInt(ret.code) !== 1) {
$(that).find('.verify.layui-hide').removeClass('layui-hide');
$(that).find('[data-captcha]').trigger('click');
}
}, null, null, 'false');
});
});
});
/*! 登录图形验证码刷新 */
$body.on('click', '[data-captcha]', function () {
var type, token, verify, uniqid, action, $that = $(this);
action = this.getAttribute('data-captcha') || location.href;
if (action.length < 5) return $.msg.tips('请设置验证码请求地址');
type = this.getAttribute('data-captcha-type') || 'captcha-type';
token = this.getAttribute('data-captcha-token') || 'captcha-token';
uniqid = this.getAttribute('data-field-uniqid') || 'uniqid';
verify = this.getAttribute('data-field-verify') || 'verify';
$.form.load(action, {type: type, token: token}, 'post', function (ret) {
if (ret.code) {
$that.html('');
$that.append($('<img alt="img" src="">').attr('src', ret.data.image));
$that.append($('<input type="hidden">').attr('name', uniqid).val(ret.data.uniqid));
if (ret.data.code) {
$that.parents('form').find('[name=' + verify + ']').attr('value', ret.data.code);
} else {
$that.parents('form').find('[name=' + verify + ']').attr('value', '');
}
return false;
}
}, false);
});
$('[data-captcha]').map(function () {
$(this).trigger('click')
});
});

View File

@ -166,6 +166,7 @@ return array(
'WeMini\\Image' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Image.php', 'WeMini\\Image' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Image.php',
'WeMini\\Logistics' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Logistics.php', 'WeMini\\Logistics' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Logistics.php',
'WeMini\\Message' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Message.php', 'WeMini\\Message' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Message.php',
'WeMini\\Newtmpl' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Newtmpl.php',
'WeMini\\Ocr' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Ocr.php', 'WeMini\\Ocr' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Ocr.php',
'WeMini\\Plugs' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Plugs.php', 'WeMini\\Plugs' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Plugs.php',
'WeMini\\Poi' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Poi.php', 'WeMini\\Poi' => $vendorDir . '/zoujingli/wechat-developer/WeMini/Poi.php',

View File

@ -259,6 +259,7 @@ class ComposerStaticInit0ac7cd5b2cda0031cee9c92b2dc93c50
'WeMini\\Image' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Image.php', 'WeMini\\Image' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Image.php',
'WeMini\\Logistics' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Logistics.php', 'WeMini\\Logistics' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Logistics.php',
'WeMini\\Message' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Message.php', 'WeMini\\Message' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Message.php',
'WeMini\\Newtmpl' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Newtmpl.php',
'WeMini\\Ocr' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Ocr.php', 'WeMini\\Ocr' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Ocr.php',
'WeMini\\Plugs' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Plugs.php', 'WeMini\\Plugs' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Plugs.php',
'WeMini\\Poi' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Poi.php', 'WeMini\\Poi' => __DIR__ . '/..' . '/zoujingli/wechat-developer/WeMini/Poi.php',

View File

@ -401,12 +401,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/zoujingli/ThinkLibrary.git", "url": "https://github.com/zoujingli/ThinkLibrary.git",
"reference": "bc3a7d6203955f36f401e8286884a9aa7e6a4133" "reference": "bc77d2ff2e4ff7fb18a3a5bb6436633fe3f6b4ad"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/bc3a7d6203955f36f401e8286884a9aa7e6a4133", "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/bc77d2ff2e4ff7fb18a3a5bb6436633fe3f6b4ad",
"reference": "bc3a7d6203955f36f401e8286884a9aa7e6a4133", "reference": "bc77d2ff2e4ff7fb18a3a5bb6436633fe3f6b4ad",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
@ -426,7 +426,7 @@
"qiniu/php-sdk": "^7.2", "qiniu/php-sdk": "^7.2",
"topthink/framework": "5.1.*" "topthink/framework": "5.1.*"
}, },
"time": "2019-12-30T09:51:14+00:00", "time": "2020-01-07T02:14:58+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -446,17 +446,17 @@
}, },
{ {
"name": "zoujingli/wechat-developer", "name": "zoujingli/wechat-developer",
"version": "v1.2.15", "version": "v1.2.16",
"version_normalized": "1.2.15.0", "version_normalized": "1.2.16.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/zoujingli/WeChatDeveloper.git", "url": "https://github.com/zoujingli/WeChatDeveloper.git",
"reference": "4b81e72cff7a3acfde2cca919bd8e173355bc53c" "reference": "01fa1479e8c4d7a0875de96787a2bcaeacc755e9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/zoujingli/WeChatDeveloper/zipball/4b81e72cff7a3acfde2cca919bd8e173355bc53c", "url": "https://api.github.com/repos/zoujingli/WeChatDeveloper/zipball/01fa1479e8c4d7a0875de96787a2bcaeacc755e9",
"reference": "4b81e72cff7a3acfde2cca919bd8e173355bc53c", "reference": "01fa1479e8c4d7a0875de96787a2bcaeacc755e9",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
@ -474,7 +474,7 @@
"ext-simplexml": "*", "ext-simplexml": "*",
"php": ">=5.4" "php": ">=5.4"
}, },
"time": "2019-11-25T10:40:50+00:00", "time": "2020-01-04T08:51:50+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {

View File

@ -32,7 +32,7 @@ class Sess extends Command
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xclean:session')->setDescription('[清理]删除失效的会话文件'); $this->setName('xclean:session')->setDescription('Clean up invalid session files');
} }
/** /**
@ -42,15 +42,15 @@ class Sess extends Command
*/ */
protected function execute(Input $input, Output $output) protected function execute(Input $input, Output $output)
{ {
$output->comment('=== 准备清理无效的会话文件 ==='); $output->comment('Start cleaning up invalid session files');
foreach (glob(config('session.path') . 'sess_*') as $file) { foreach (glob(config('session.path') . 'sess_*') as $file) {
list($fileatime, $filesize) = [fileatime($file), filesize($file)]; list($fileatime, $filesize) = [fileatime($file), filesize($file)];
if ($filesize < 1 || $fileatime < time() - 3600) { if ($filesize < 1 || $fileatime < time() - 3600) {
$output->info('移除会话文件 -> [ ' . date('Y-m-d H:i:s', $fileatime) . ' ] ' . basename($file) . " {$filesize}"); $output->info('Remove session file -> [ ' . date('Y-m-d H:i:s', $fileatime) . ' ] ' . basename($file) . " {$filesize}");
@unlink($file); @unlink($file);
} }
} }
$output->comment('=== 成功清理无效的会话文件 ==='); $output->comment('Cleaning up invalid session files complete');
} }
} }

View File

@ -28,12 +28,18 @@ use think\Db;
*/ */
class ListenQueue extends Command class ListenQueue extends Command
{ {
/**
* 当前任务服务
* @var ProcessService
*/
protected $process;
/** /**
* 配置指定信息 * 配置指定信息
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xtask:listen')->setDescription('[监听]启动任务监听主进程'); $this->setName('xtask:listen')->setDescription('Start task listening main process');
} }
/** /**
@ -48,23 +54,26 @@ class ListenQueue extends Command
*/ */
protected function execute(Input $input, Output $output) protected function execute(Input $input, Output $output)
{ {
set_time_limit(0);
Db::name('SystemQueue')->count(); Db::name('SystemQueue')->count();
if (($process = ProcessService::instance())->iswin() && function_exists('cli_set_process_title')) { if (($process = ProcessService::instance())->iswin() && function_exists('cli_set_process_title')) {
cli_set_process_title("ThinkAdmin 监听主进程 {$process->version()}"); cli_set_process_title("ThinkAdmin {$process->version()} Queue Listen");
} }
$output->comment('============ 任务监听中 ============'); $output->writeln('============ LISTENING ============');
while (true) { while (true) {
foreach (Db::name('SystemQueue')->where([['status', 'eq', '1'], ['time', '<=', time()]])->order('time asc')->select() as $item) { $map = [['status', 'eq', '1'], ['time', '<=', time()]];
foreach (Db::name('SystemQueue')->where($map)->order('time asc')->select() as $vo) {
try { try {
if ($process->query($command = $process->think("xtask:_work {$item['id']} -"))) { $command = $process->think("xtask:_work {$vo['id']} -");
$output->comment("正在执行 -> [{$item['id']}] {$item['title']}"); if (count($process->query($command)) > 0) {
$this->output->writeln("Already in progress -> [{$vo['id']}] {$vo['title']}");
} else { } else {
$process->create($command); $process->create($command);
$output->info("创建成功 -> [{$item['id']}] {$item['title']}"); $this->output->writeln("Created new process -> [{$vo['id']}] {$vo['title']}");
} }
} catch (\Exception $e) { } catch (\Exception $e) {
Db::name('SystemQueue')->where(['id' => $item['id']])->update(['status' => '4', 'desc' => $e->getMessage()]); Db::name('SystemQueue')->where(['id' => $vo['id']])->update(['status' => '4', 'desc' => $e->getMessage()]);
$output->error("创建处理任务的子进程失败 --> [{$item['id']}] {$item['title']}{$e->getMessage()}"); $output->error("Execution failed -> [{$vo['id']}] {$vo['title']}{$e->getMessage()}");
} }
} }
sleep(1); sleep(1);

View File

@ -32,7 +32,7 @@ class QueryQueue extends Command
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xtask:query')->setDescription('[控制]查询正在运行的进程'); $this->setName('xtask:query')->setDescription('Query all running task processes');
} }
/** /**
@ -47,7 +47,7 @@ class QueryQueue extends Command
if (count($result) > 0) foreach ($result as $item) { if (count($result) > 0) foreach ($result as $item) {
$output->writeln("{$item['pid']}\t{$item['cmd']}"); $output->writeln("{$item['pid']}\t{$item['cmd']}");
} else { } else {
$output->writeln('没有查询到相关任务进程'); $output->writeln('No related task process found');
} }
} }
} }

View File

@ -34,7 +34,7 @@ class StartQueue extends Command
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xtask:start')->setDescription('[控制]创建守护监听主进程'); $this->setName('xtask:start')->setDescription('Create daemons to listening main process');
} }
/** /**
@ -48,14 +48,14 @@ class StartQueue extends Command
$process = ProcessService::instance(); $process = ProcessService::instance();
$command = $process->think("xtask:listen"); $command = $process->think("xtask:listen");
if (count($result = $process->query($command)) > 0) { if (count($result = $process->query($command)) > 0) {
$output->info("监听主进程{$result['0']['pid']}已经启动!"); $output->info("Listening main process {$result['0']['pid']} has started");
} else { } else {
$process->create($command); $process->create($command);
sleep(1); sleep(1);
if (count($result = $process->query($command)) > 0) { if (count($result = $process->query($command)) > 0) {
$output->info("监听主进程{$result['0']['pid']}启动成功!"); $output->info("Listening main process {$result['0']['pid']} started successfully");
} else { } else {
$output->error('监听主进程创建失败!'); $output->error('Failed to create listening main process');
} }
} }
} }

View File

@ -32,7 +32,7 @@ class StateQueue extends Command
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xtask:state')->setDescription('[控制]查看监听主进程状态'); $this->setName('xtask:state')->setDescription('Check listening main process status');
} }
/** /**
@ -45,9 +45,9 @@ class StateQueue extends Command
$process = ProcessService::instance(); $process = ProcessService::instance();
$command = $process->think('xtask:listen'); $command = $process->think('xtask:listen');
if (count($result = $process->query($command)) > 0) { if (count($result = $process->query($command)) > 0) {
$output->info("异步任务监听主进程{$result[0]['pid']}正在运行..."); $output->info("Listening for main process {$result[0]['pid']} running");
} else { } else {
$output->error("异步任务监听主进程没有运行哦!"); $output->error("The Listening main process is not running");
} }
} }
} }

View File

@ -33,7 +33,7 @@ class StopQueue extends Command
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xtask:stop')->setDescription('[控制]平滑停止所有的进程'); $this->setName('xtask:stop')->setDescription('Smooth stop of all task processes');
} }
/** /**
@ -46,10 +46,10 @@ class StopQueue extends Command
$process = ProcessService::instance(); $process = ProcessService::instance();
$command = $process->think('xtask:'); $command = $process->think('xtask:');
if (count($result = $process->query($command)) < 1) { if (count($result = $process->query($command)) < 1) {
$output->writeln("没有需要结束的任务进程哦!"); $output->writeln("There is no task process to finish");
} else foreach ($result as $item) { } else foreach ($result as $item) {
$process->close($item['pid']); $process->close($item['pid']);
$output->writeln("发送结束进程{$item['pid']}信号成功!"); $output->writeln("Sending end process {$item['pid']} signal succeeded");
} }
} }
} }

View File

@ -49,9 +49,9 @@ class WorkQueue extends Command
*/ */
protected function configure() protected function configure()
{ {
$this->setName('xtask:_work')->setDescription('[执行]创建执行任务的进程'); $this->setName('xtask:_work')->setDescription('Create a process to execute a task');
$this->addArgument('id', Argument::OPTIONAL, '指定任务ID'); $this->addArgument('id', Argument::OPTIONAL, 'TaskNumber');
$this->addArgument('sp', Argument::OPTIONAL, '指令结束符'); $this->addArgument('sp', Argument::OPTIONAL, 'Separator');
} }
/** /**
@ -65,18 +65,18 @@ class WorkQueue extends Command
{ {
$this->id = trim($input->getArgument('id')); $this->id = trim($input->getArgument('id'));
if (empty($this->id)) { if (empty($this->id)) {
$this->output->error("执行任务需要指定任务编号!"); $this->output->error('Task number needs to be specified for task execution');
} else try { } else try {
$queue = Db::name('SystemQueue')->where(['id' => $this->id, 'status' => '1'])->find(); $queue = Db::name('SystemQueue')->where(['id' => $this->id, 'status' => '1'])->find();
if (empty($queue)) { if (empty($queue)) {
// 这里不做任何处理(该任务可能在其它地方已经在执行) // 这里不做任何处理(该任务可能在其它地方已经在执行)
$this->output->warning("执行任务{$this->id}的信息或状态异常!"); $this->output->warning("The or status of task {$this->id} is abnormal");
} else { } else {
// 锁定任务状态 // 锁定任务状态
Db::name('SystemQueue')->where(['id' => $queue['id']])->update(['status' => '2', 'start_at' => date('Y-m-d H:i:s')]); Db::name('SystemQueue')->where(['id' => $queue['id']])->update(['status' => '2', 'start_at' => date('Y-m-d H:i:s')]);
// 设置进程标题 // 设置进程标题
if (($process = ProcessService::instance())->iswin() && function_exists('cli_set_process_title')) { if (($process = ProcessService::instance())->iswin() && function_exists('cli_set_process_title')) {
cli_set_process_title("ThinkAdmin {$process->version()} 执行任务 - {$queue['title']}"); cli_set_process_title("ThinkAdmin {$process->version()} Queue - {$queue['title']}");
} }
// 执行任务内容 // 执行任务内容
if (class_exists($queue['preload'])) { if (class_exists($queue['preload'])) {
@ -87,7 +87,7 @@ class WorkQueue extends Command
if (isset($class->title)) $class->title = $queue['title']; if (isset($class->title)) $class->title = $queue['title'];
$this->update('3', $class->execute($input, $output, is_array($data) ? $data : [])); $this->update('3', $class->execute($input, $output, is_array($data) ? $data : []));
} else { } else {
throw new Exception("任务处理类 {$queue['preload']} 未定义 execute 入口!"); throw new Exception("Task processing class {$queue['preload']} not defined execute");
} }
} else { } else {
// 自定义指令,不支持返回消息(支持异常结束,异常码可选择 3|4 设置任务状态) // 自定义指令,不支持返回消息(支持异常结束,异常码可选择 3|4 设置任务状态)
@ -114,9 +114,9 @@ class WorkQueue extends Command
*/ */
protected function update($status, $message) protected function update($status, $message)
{ {
$desc = explode("\n", trim(is_string($message) ? $message : ''));
$result = Db::name('SystemQueue')->where(['id' => $this->id])->update([ $result = Db::name('SystemQueue')->where(['id' => $this->id])->update([
'status' => $status, 'end_at' => date('Y-m-d H:i:s'), 'status' => $status, 'end_at' => date('Y-m-d H:i:s'), 'desc' => $desc[0],
'desc' => is_string($message) ? $message : '',
]); ]);
$this->output->writeln(is_string($message) ? $message : ''); $this->output->writeln(is_string($message) ? $message : '');
return $result !== false; return $result !== false;

View File

@ -108,9 +108,13 @@ class CaptchaService extends Service
public function check($code, $uniqid = null) public function check($code, $uniqid = null)
{ {
$_uni = is_string($uniqid) ? $uniqid : input('uniqid', '-'); $_uni = is_string($uniqid) ? $uniqid : input('uniqid', '-');
$_val = $this->app->cache->get($_uni); $_val = $this->app->cache->get($_uni, '');
$this->app->cache->rm($_uni); if (is_string($_val) && strtolower($_val) === strtolower($code)) {
return is_string($_val) && strtolower($_val) === strtolower($code); $this->app->cache->rm($_uni);
return true;
} else {
return false;
}
} }
/** /**

View File

@ -88,7 +88,7 @@ class ProcessService extends Service
/** /**
* 关闭任务进程 * 关闭任务进程
* @param integer $pid 进程号 * @param integer $pid 进程号
* @return boolean * @return $this
*/ */
public function close($pid) public function close($pid)
{ {
@ -97,7 +97,7 @@ class ProcessService extends Service
} else { } else {
$this->exec("kill -9 {$pid}"); $this->exec("kill -9 {$pid}");
} }
return true; return $this;
} }
/** /**

View File

@ -0,0 +1,151 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: http://think.ctolog.com
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | github开源项目https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 公众号小程序订阅消息支持
* Class Mini
* @package WeChat
*/
class Newtmpl extends BasicWeChat
{
/**
* 获取小程序账号的类目
* @param array $data 类目信息列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addCategory($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/addcategory?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 获取小程序账号的类目
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getCategory()
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/getcategory?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callGetApi($url);
}
/**
* 获取小程序账号的类目
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function deleteCategory()
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/deletecategory?access_token=TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, [], true);
}
/**
* 获取帐号所属类目下的公共模板标题
* @param string $ids 类目 id多个用逗号隔开
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPubTemplateTitleList($ids)
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['ids'=>$ids,'start' => '0', 'limit' => '30'], true);
}
/**
* 获取模板标题下的关键词列表
* @param string $tid 模板标题 id可通过接口获取
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPubTemplateKeyWordsById($tid)
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['tid' => $tid], true);
}
/**
* 组合模板并添加至帐号下的个人模板库
* @param string $tid 模板标题 id可通过接口获取也可登录小程序后台查看获取
* @param array $kidList 开发者自行组合好的模板关键词列表,关键词顺序可以自由搭配(例如 [3,5,4] [4,5,3]最多支持5个最少2个关键词组合
* @param string $sceneDesc 服务场景描述15个字以内
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addTemplate($tid, array $kidList, $sceneDesc = '')
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['tid' => $tid, 'kidList' => $kidList, 'sceneDesc' => $sceneDesc], false);
}
/**
* 获取当前帐号下的个人模板列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getTemplateList()
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, [], true);
}
/**
* 删除帐号下的个人模板
* @param string $priTmplId 要删除的模板id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delTemplate($priTmplId)
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['priTmplId' => $priTmplId], true);
}
/**
* 发送订阅消息
* @param array $data 发送的消息对象数组
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function send(array $data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
}