Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

76
addons/cron/Cron.php Executable file
View File

@ -0,0 +1,76 @@
<?php
namespace addons\cron; // 注意命名空间规范
use think\addons\Addons;
use addons\cron\model\Crons as DM;
/**
* 计划任务功能
* @author HSF
*/
class Cron extends Addons{
// 该插件的基础信息
public $info = [
'name' => 'Cron', // 插件标识
'title' => '计划任务', // 插件名称
'description' => '计划任务管理,若用户没有在系统里配置定时任务则建议开启该插件', // 插件简介
'status' => 0, // 状态
'author' => 'HSF',
'version' => '1.0.0'
];
/**
* 插件安装方法
* @return bool
*/
public function install(){
$m = new DM();
$flag = $m->install();
WSTClearHookCache();
return $flag;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall(){
$m = new DM();
$flag = $m->uninstall();
WSTClearHookCache();
return $flag;
}
/**
* 插件启用方法
* @return bool
*/
public function enable(){
WSTClearHookCache();
return true;
}
/**
* 插件禁用方法
* @return bool
*/
public function disable(){
WSTClearHookCache();
return true;
}
/**
* 插件设置方法
* @return bool
*/
public function saveConfig(){
WSTClearHookCache();
return true;
}
public function initCronHook($params){
echo "<img style='display:none' src='".request()->root(true)."/addon/cron-cron-runCrons.html'>";
}
}

5
addons/cron/config.php Executable file
View File

@ -0,0 +1,5 @@
<?php
return array(
);

56
addons/cron/controller/Cron.php Executable file
View File

@ -0,0 +1,56 @@
<?php
namespace addons\cron\controller;
use think\addons\Controller;
use addons\cron\model\Crons as M;
/**
* ============================================================================
* 计划任务控制器
*/
class Cron extends Controller{
public function index(){
return $this->fetch("admin/list");
}
/**
* 获取分页
*/
public function pageQuery(){
$m = new M();
return WSTGrid($m->pageQuery());
}
public function toEdit(){
$m = new M();
$rs = $m->getById(Input("id/d",0));
$this->assign("data",$rs);
return $this->fetch("admin/edit");
}
/**
* 修改
*/
public function edit(){
$m = new M();
return $m->edit();
}
/**
* 执行计划任务
*/
public function runCron(){
$m = new M();
return $m->runCron();
}
public function runCrons(){
$m = new M();
return $m->runCrons();
}
/**
* 停用计划任务
*/
public function changeEnableStatus(){
$m = new M();
return $m->changeEnableStatus();
}
}

0
addons/cron/install.sql Executable file
View File

318
addons/cron/model/Crons.php Executable file
View File

@ -0,0 +1,318 @@
<?php
namespace addons\cron\model;
use think\addons\BaseModel as Base;
use think\Db;
/**
* ============================================================================
* 计划任务业务处理
*/
class Crons extends Base{
/***
* 安装插件
*/
public function install(){
Db::startTrans();
try{
$hooks = ['initCronHook'];
$this->bindHoods("Cron", $hooks);
//管理员后台
$rs = Db::name('menus')->insert(["parentId"=>2,"menuName"=>"计划任务","menuSort"=>11,"dataFlag"=>1,"isShow"=>1,"menuMark"=>"cron"]);
if($rs!==false){
$datas = [];
$parentId = Db::name('menus')->getLastInsID();
$datas[] = ["menuId"=>$parentId,"privilegeCode"=>"CRON_JHRW_00","privilegeName"=>"查看计划任务","isMenuPrivilege"=>1,"privilegeUrl"=>"/addon/cron-cron-index","otherPrivilegeUrl"=>"/addon/cron-cron-pageQuery","dataFlag"=>1,"isEnable"=>1];
$datas[] = ["menuId"=>$parentId,"privilegeCode"=>"CRON_JHRW_04","privilegeName"=>"操作计划任务","isMenuPrivilege"=>0,"privilegeUrl"=>"/addon/cron-cron-toEdit","otherPrivilegeUrl"=>"/addon/cron-cron-edit,/addon/cron-cron-changeEnableStatus,/addon/cron-cron-runCron","dataFlag"=>1,"isEnable"=>1];
Db::name('privileges')->insertAll($datas);
}
installSql("cron");
Db::commit();
return true;
}catch (\Exception $e) {
Db::rollback();
return false;
}
}
/**
* 删除菜单
*/
public function uninstall(){
Db::startTrans();
try{
$hooks = ['initCronHook'];
$this->unbindHoods("Cron", $hooks);
Db::name('menus')->where(["menuMark"=>"cron"])->delete();
Db::name('privileges')->where(["privilegeCode"=>array("like","CRON_%")])->delete();
uninstallSql("cron");//传入插件名
Db::commit();
return true;
}catch (\Exception $e) {
Db::rollback();
return false;
}
}
/**
* 分页
*/
public function pageQuery(){
return $this->order('id desc')->paginate(input('limit/d'));
}
/**
* 列表
*/
public function listQuery(){
return $this->order('id desc')->select();
}
public function getById($id){
$rs = $this->get($id);
if($rs['cronJson']!='')$rs['cronJson'] = unserialize($rs['cronJson']);
return $rs;
}
/**
* 编辑
*/
public function edit(){
$data = input('post.');
$data['cronMinute'] = str_replace('',',',$data['cronMinute']);
if($data['cronMinute']=='')$data['cronMinute'] = '0';
Db::startTrans();
try{
$corn = $this->get((int)$data['id']);
$corn->cronCycle = (int)$data['cronCycle'];
if(!in_array($corn->cronCycle,[0,1,2]))return WSTReturn('无效的计划时间');
if($corn->cronCycle==0)$corn->cronDay = $data['cronDay'];
if($corn->cronDay<=0 || $corn->cronDay>=32)return WSTReturn('无效的计划日期');
if($corn->cronCycle==1)$corn->cronWeek = $data['cronWeek'];
if($corn->cronWeek<0 || $corn->cronWeek>6)return WSTReturn('无效的计划星期');
$corn->cronHour = $data['cronHour'];
if($corn->cronCycle<0 || $corn->cronCycle>23)return WSTReturn('无效的计划时间');
$corn->cronMinute = $data['cronMinute'];
$json = unserialize($corn->cronJson);
if(!empty($json)){
foreach ($json as $key => $v) {
$json[$key]['fieldVal'] = input('post.'.$v['fieldCode']);
}
}
$corn->cronJson = serialize($json);
$corn->isEnable = (int)input('post.isEnable');
$corn->nextTime = $this->getNextRunTime($corn);
$result = $corn->save();
if(false !== $result){
cache('WST_CRONS',null);
Db::commit();
return WSTReturn("编辑成功", 1);
}
}catch (\Exception $e) {
Db::rollback();
}
return WSTReturn('编辑失败',-1);
}
/**
* 删除
*/
public function changeEnableStatus(){
$id = (int)input('post.id/d');
$status = ((int)input('post.status/d')==1)?1:0;
Db::startTrans();
try{
$result = $this->setField(['isEnable'=>$status,'id'=>$id]);
if(false !== $result){
cache('WST_CRONS',null);
Db::commit();
return WSTReturn("操作成功", 1);
}
}catch (\Exception $e) {
Db::rollback();
}
return WSTReturn('操作失败',-1);
}
/**
* 执行计划任务
*/
public function runCron(){
$id = (int)input('post.id');
$cron = $this->get($id);
if(!$cron)return WSTReturn('计划任务不存在,跳过此次执行',1);
if($cron->isEnable==0)return WSTReturn('任务执行未开启中,跳过此次执行',1);
if($cron->isRunning==1)return WSTReturn('已有任务执行中,跳过此次执行',1);
$cron->runTime = date('Y-m-d H:i:s');
$cron->nextTime = $this->getNextRunTime($cron);
Db::startTrans();
try{
$cron->isRunning = 1;
$cron->save();
$domain = request()->root(true);
$domain = $domain."/".$cron->cronUrl;
$data = $this->http($domain);
$data = json_decode($data,true);
$cron->isRunning = 0;
if($data['status']==1){
$cron->isRunSuccess = 1;
}else{
$cron->isRunSuccess = 0;
}
$cron->save();
Db::commit();
}catch (\Exception $e) {
Db::rollback();
$cron->isRunning = 0;
$cron->isRunSuccess = 0;
$cron->save();
return WSTReturn('执行失败');
}
return WSTReturn('执行成功',1);
}
public function http($url){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置否输出到页面
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30 ); //设置连接等待时间
curl_setopt($ch, CURLOPT_ENCODING, "gzip" );
$data=curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return $data;
}
/**
* 执行所有定时任务
*/
public function runCrons(){
$cons = $this->where('isEnable',1)->select();
$day = date('d');
$hour = date('H');
$minute = date('i');
$week = date('w');
foreach($cons as $key =>$cron){
if($cron->isRunning==1)contnie;
//判断能否执行
if(strtotime($cron->nextTime)>time())continue;
Db::startTrans();
try{
//fopen(time().'_'.rand(0,10000)."_auctionEnd.txt", "w");
$cron->isRunning = 1;
$cron->runTime = date('Y-m-d H:i:s');
$cron->nextTime = $this->getNextRunTime($cron);
$cron->save();
$domain = request()->root(true);
$domain = $domain."/".$cron->cronUrl;
$data = $this->http($domain);
$data = json_decode($data,true);
$cron->isRunning = 0;
if($data['status']==1){
$cron->isRunSuccess = 1;
}else{
$cron->isRunSuccess = 0;
}
$cron->save();
Db::commit();
}catch (\Exception $e) {
Db::rollback();
$cron->isRunning = 0;
$cron->isRunSuccess = 0;
$cron->save();
}
}
echo "done";
}
public function getNextRunTime($cron){
$monthDay = date("t");
$today = date('j');
$thisWeek = date('w');
$thisHour = date('H');
$thisMinute = date('i');
$nextDay = date('Y-m-d');
$nextHour = 0;
$nextMinute = 0;
$isFurther = false;//标记是否要往前进一位
$tmpMinute = [];
if($cron->cronMinute==-1){
$nextMinute = date('i',strtotime('+1 Minute'));
if($nextMinute<$thisMinute)$isFurther = true;
$tmpMinute[] = $nextMinute;
}else{
$tmpMinute = explode(',',$cron->cronMinute);
sort($tmpMinute);
$isFind = false;
foreach($tmpMinute as $key => $v){
if((int)$v>59)continue;
if($thisMinute<(int)$v){
$nextMinute = (int)$v;
$isFind = true;
break;
}
}
if(!$isFind){
$nextMinute = (int)$tmpMinute[0];
$isFurther = true;
}
}
if($cron->cronHour==-1){
$nextHour = date("H",time()+($isFurther?3200:0));
$isFurther = false;
if($nextHour<$thisHour)$isFurther = true;
}else{
$nextHour = $cron->cronHour;
$isFurther = false;
}
if(time()>strtotime(date('Y-m-d')." ".$nextHour.":".$nextMinute.":00"))$isFurther = true;
if($cron->cronCycle==0){
if($isFurther){
$today = date('j',strtotime('+1 day'));
}
if($today<$cron->cronDay){
$nextDay = date('Y-m-'.$cron->cronDay);
}else{
$nextDay = date("Y-m",strtotime(" +1 month"))."-".$cron->cronDay;
}
if(date('j',strtotime($nextDay))!=$today){
if($cron->cronHour==-1){
$nextHour = 0;
}else{
$nextHour = $cron->cronHour;
}
if($cron->cronMinute==-1){
$nextMinute = 0;
}else{
$nextMinute = (int)$tmpMinute[0];
}
}
}
if($cron->cronCycle==1){
if($isFurther){
$thisWeek = date('w',strtotime('+1 day'));
}
$num = 0;
if($cron->cronWeek>$thisWeek){
$num = $cron->cronWeek - $thisWeek;
}else{
$num = $cron->cronWeek - $thisWeek + 7;
}
$nextDay = date("Y-m-d",strtotime("+".$num." day"));
if(date('j',strtotime($nextDay))!=$today){
if($cron->cronHour==-1){
$nextHour = 0;
}else{
$nextHour = $cron->cronHour;
}
if($cron->cronMinute==-1){
$nextMinute = 0;
}else{
$nextMinute = (int)$tmpMinute[0];
}
}
}
if($cron->cronCycle==2){
if($isFurther){
$nextDay = date('Y-m-d',strtotime('+1 day'));
}else{
$nextDay = date('Y-m-d');
}
}
return date('Y-m-d H:i:s',strtotime($nextDay." ".$nextHour.":".$nextMinute.":00"));
}
}

1
addons/cron/uninstall.sql Executable file
View File

@ -0,0 +1 @@
update hyh_crons set isEnable=0;

113
addons/cron/view/admin/crons.js Executable file
View File

@ -0,0 +1,113 @@
var mmg;
function initGrid(){
var h = WST.pageHeight();
var cols = [
{title:'计划任务名称', name:'cronName', width: 80},
{title:'计划任务描述', name:'cronDesc', width: 150},
{title:'上次执行时间', name:'runTime', width: 70, renderer: function(val,item,rowIndex){
return (item['runTime']==0)?'-':item['runTime'];
}},
{title:'执行状态', name:'isEnable', width: 20, renderer: function(val,item,rowIndex){
return (item['isRunSuccess']==1)?'<span class="statu-yes"><i class="fa fa-check-circle"></i> 成功</span>':'<span class="statu-no"><i class="fa fa-times-circle"></i> 失败</span>';
}},
{title:'下次执行时间', name:'nextTime', width: 70, renderer: function(val,item,rowIndex){
return (item['nextTime']==0)?'-':item['nextTime'];
}},
{title:'作者', name:'auchor', width: 20, renderer: function(val,item,rowIndex){
return '<a href="'+item['authorUrl']+'" target="_blank">'+item['author']+'</a>';
}},
{title:'计划状态', name:'isEnable', width: 20, renderer: function(val,item,rowIndex){
return (item['isEnable']==1)?'<span class="statu-yes"><i class="fa fa-check-circle"></i> 启用</span>':'<span class="statu-wait"><i class="fa fa-ban"></i> 停用</span>';
}},
{title:'操作', name:'' ,width:120, align:'center', renderer: function(val,item,rowIndex){
var h="";
if(WST.GRANT.CRON_JHRW_04){
h += "<a class='btn btn-blue' href='javascript:toEdit(" + item['id'] + ")'><i class='fa fa-pencil'></i>修改</a> ";
if(item['isEnable']==0){
h += "<a class='btn btn-green' href='javascript:changgeEnableStatus(" + item['id'] + ",1)'><i class='fa fa-check'></i>启用</a> ";
}else{
h += "<a class='btn btn-red' href='javascript:changgeEnableStatus(" + item['id'] + ",0)'><i class='fa fa-ban'></i>停用</a> ";
h += '<a class="btn btn-blue" href="javascript:run(\'' + item['id'] + '\')"><i class="fa fa-refresh"></i>执行</a>';
}
}
return h;
}}
];
mmg = $('.mmg').mmGrid({height: h-115,indexCol: true, cols: cols,method:'POST',
url: WST.AU('cron://cron/pageQuery'), fullWidthRows: true, autoLoad: true,
plugins: [
$('#pg').mmPaginator({})
]
});
$('#headTip').WSTTips({width:90,height:35,callback:function(v){
var diff = v?115:88;
mmg.resize({height:h-diff})
}});
}
function toEdit(id){
location.href=WST.AU('cron://cron/toEdit','id='+id);
}
function checkType(v){
$('.cycle').hide();
$('.cycle'+v).show();
}
function run(id){
var box = WST.confirm({content:'你确定要执行该任务吗?',yes:function(){
var loading = WST.msg('正在执行计划任务,请稍后...',{icon: 16,time:6000000000});
$.post(WST.AU('cron://cron/runCron'),{id:id},function(data,textStatus){
layer.close(loading);
var json = WST.toAdminJson(data);
if(json.status=='1'){
WST.msg(json.msg,{icon:1});
layer.close(box);
mmg.load();
}else{
WST.msg(json.msg,{icon:2});
}
})
}});
}
function edit(id){
var params = WST.getParams('.ipt');
params.id = id;
var loading = WST.msg('正在提交数据,请稍后...', {icon: 16,time:60000});
$.post(WST.AU('cron://cron/edit'),params,function(data,textStatus){
layer.close(loading);
var json = WST.toAdminJson(data);
if(json.status=='1'){
WST.msg("操作成功",{icon:1},function(){
location.href=WST.AU('cron://cron/index');
});
}else{
WST.msg(json.msg,{icon:2});
}
});
}
function changgeEnableStatus(id,type){
var msg = (type==1)?"您确定要启用该计划任务吗?":"您确定要停用该计划任务吗?"
var box = WST.confirm({content:msg,yes:function(){
var loading = WST.msg('正在提交数据,请稍后...', {icon: 16,time:60000});
$.post(WST.AU('cron://cron/changeEnableStatus'),{id:id,status:type},function(data,textStatus){
layer.close(loading);
var json = WST.toAdminJson(data);
if(json.status=='1'){
WST.msg(json.msg,{icon:1});
layer.close(box);
mmg.load();
}else{
WST.msg(json.msg,{icon:2});
}
});
}});
}

109
addons/cron/view/admin/edit.html Executable file
View File

@ -0,0 +1,109 @@
{extend name="../../../hyhproject/admin/view/base" /}
{block name="js"}
<script src="__ROOT__/addons/cron/view/admin/crons.js?v={$v}" type="text/javascript"></script>
{/block}
{block name="main"}
<form id="editForm">
<table class='wst-form wst-box-top'>
<tr>
<th width='150'>计划任务名称:</th>
<td style='line-height:30px;'>
{$data['cronName']}
</td>
</tr>
<tr>
<th>计划任务描述:</th>
<td style='line-height:30px;'>
{$data['cronDesc']}
</td>
</tr>
<tr>
<th>定时任务网址:</th>
<td style='line-height:30px;'>
{$data['cronUrl']}
</td>
</tr>
{if $data['cronJson']!=''}
{volist name="$data['cronJson']" id='vj'}
<tr>
<th>{$vj['fieldLabel']}</th>
<td>
<input type="text" id="{$vj['fieldCode']}" class="ipt" style='width:70%;' maxLength="255" value='{$vj['fieldVal']}' />
</td>
</tr>
{/volist}
{/if}
<tr>
<th>计划时间<font color='red'></font></th>
<td class='layui-form'>
<label>
<input type='radio' name='cronCycle' value='0' id='cronCycle0' class='ipt' onclick='javascript:checkType(0)' {if $data['cronCycle']==0}checked{/if} title='每月'/>
</label>
<label>
<input type='radio' name='cronCycle' value='1' id='cronCycle1' class='ipt' onclick='javascript:checkType(1)' {if $data['cronCycle']==1}checked{/if} title='每周'/>
</label>
<label>
<input type='radio' name='cronCycle' value='2' id='cronCycle2' class='ipt' onclick='javascript:checkType(2)' {if $data['cronCycle']==2}checked{/if} title='每日'/>
</label>
</td>
</tr>
<tr class='cycle0 cycle' {if $data['cronCycle']!=0}style='display:none'{/if}>
<th>日期<font color='red'></font></th>
<td>
<select id='cronDay' class='ipt'>
{for start="1" end="32"}
<option value='{$i}' {if $data['cronDay']==$i}selected{/if}>{$i}日</option>
}
{/for}
</select>
</td>
</tr>
<tr class='cycle1 cycle' {if $data['cronCycle']!=1}style='display:none'{/if}>
<th>星期<font color='red'></font></th>
<td>
<select id='cronWeek' class='ipt'>
<option value='1' {if $data['cronWeek']==1}selected{/if}>星期一</option>
<option value='2' {if $data['cronWeek']==2}selected{/if}>星期二</option>
<option value='3' {if $data['cronWeek']==3}selected{/if}>星期三</option>
<option value='4' {if $data['cronWeek']==4}selected{/if}>星期四</option>
<option value='5' {if $data['cronWeek']==5}selected{/if}>星期五</option>
<option value='6' {if $data['cronWeek']==6}selected{/if}>星期六</option>
<option value='0' {if $data['cronWeek']==0}selected{/if}>星期日</option>
</select>
</td>
</tr>
<tr>
<th>小时<font color='red'></font></th>
<td>
<select id='cronHour' class='ipt'>
<option value='-1' {if $data['cronHour']==-1}selected{/if}>每小时</option>
{for start="0" end="24"}
<option value='{$i}' {if $data['cronHour']==$i}selected{/if}>{$i}时</option>
}
{/for}
</select>
</td>
</tr>
<tr>
<th>分钟<font color='red'></font></th>
<td>
<input type="text" id="cronMinute" class="ipt" style='width:70%' maxLength="255" value='{$data['cronMinute']}' />(如多个分钟则以,分隔,-1表示每分钟)
</td>
</tr>
<tr>
<th>计划任务状态<font color='red'></font></th>
<td class='layui-form'>
<input type="checkbox" style='width:80px;' {if $data['isEnable']=='1'}checked{/if} class="ipt" name="isEnable" id='isEnable' lay-skin="switch" title="开关" value='1' lay-text="启用|停用">
</td>
</tr>
<tr>
<td colspan='2' align='center'>
<button type="button" onclick='javascript:edit({$data['id']+0})' style='margin-right:15px;' class='btn btn-primary btn-mright'><i class="fa fa-check"></i>提交</button>
<button type="button" onclick='javascript:history.go(-1)' class='btn'><i class="fa fa-angle-double-left"></i>返回</button>
</td>
</tr>
</table>
</form>
{/block}

View File

@ -0,0 +1,23 @@
{extend name="../../../hyhproject/admin/view/base" /}
{block name="css"}
<link rel="stylesheet" type="text/css" href="__ADMIN__/js/mmgrid/mmGrid.css?v={$v}" />
{/block}
{block name="js"}
<script src="__ADMIN__/js/mmgrid/mmGrid.js?v={$v}" type="text/javascript"></script>
<script src="__ROOT__/addons/cron/view/admin/crons.js?v={$v}" type="text/javascript"></script>
{/block}
{block name="main"}
<div id='alertTips' class='alert alert-success alert-tips fade in'>
<div id='headTip' class='head'><i class='fa fa-lightbulb-o'></i>操作说明</div>
<ul class='body'>
<li>本功能主要提供定时任务功能,该通过用户访问页面触发实现,具有一定延时性,若用户有自行设置操作系统计划任务则不必开启本系统的计划任务。</li>
</ul>
</div>
<div class='wst-grid'>
<div id="mmg" class="mmg"></div>
<div id="pg" style="text-align: right;"></div>
</div>
<script>
$(function(){initGrid()});
</script>
{/block}