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