2019-09-06 23:53:10 +08:00

319 lines
9.7 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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"));
}
}