CrontabLogic.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | saiadmin [ saiadmin快速开发框架 ]
  4. // +----------------------------------------------------------------------
  5. // | Author: sai <1430792918@qq.com>
  6. // +----------------------------------------------------------------------
  7. namespace plugin\saiadmin\app\logic\tool;
  8. use Exception;
  9. use GuzzleHttp\Client;
  10. use GuzzleHttp\Exception\GuzzleException;
  11. use Webman\Channel\Client as ChannelClient;
  12. use plugin\saiadmin\app\model\tool\Crontab;
  13. use plugin\saiadmin\app\model\tool\CrontabLog;
  14. use plugin\saiadmin\basic\think\BaseLogic;
  15. use plugin\saiadmin\exception\ApiException;
  16. /**
  17. * 定时任务逻辑层
  18. */
  19. class CrontabLogic extends BaseLogic
  20. {
  21. /**
  22. * 构造函数
  23. */
  24. public function __construct()
  25. {
  26. $this->model = new Crontab();
  27. }
  28. /**
  29. * 添加任务
  30. */
  31. public function add($data): bool
  32. {
  33. $second = $data['second'];
  34. $minute = $data['minute'];
  35. $hour = $data['hour'];
  36. $week = $data['week'];
  37. $day = $data['day'];
  38. $month = $data['month'];
  39. // 规则处理
  40. $rule = match ($data['task_style']) {
  41. 1 => "0 {$minute} {$hour} * * *",
  42. 2 => "0 {$minute} * * * *",
  43. 3 => "0 {$minute} */{$hour} * * *",
  44. 4 => "0 */{$minute} * * * *",
  45. 5 => "*/{$second} * * * * *",
  46. 6 => "0 {$minute} {$hour} * * {$week}",
  47. 7 => "0 {$minute} {$hour} {$day} * *",
  48. 8 => "0 {$minute} {$hour} {$day} {$month} *",
  49. default => throw new ApiException("任务类型异常"),
  50. };
  51. // 定时任务模型新增
  52. $model = Crontab::create([
  53. 'name' => $data['name'],
  54. 'type' => $data['type'],
  55. 'task_style' => $data['task_style'],
  56. 'rule' => $rule,
  57. 'target' => $data['target'],
  58. 'parameter' => $data['parameter'],
  59. 'status' => $data['status'],
  60. 'remark' => $data['remark'],
  61. ]);
  62. $id = $model->getKey();
  63. // 连接到Channel服务
  64. ChannelClient::connect();
  65. ChannelClient::publish('crontab', ['args' => $id]);
  66. return true;
  67. }
  68. /**
  69. * 修改任务
  70. */
  71. public function edit($id, $data): bool
  72. {
  73. $second = $data['second'];
  74. $minute = $data['minute'];
  75. $hour = $data['hour'];
  76. $week = $data['week'];
  77. $day = $data['day'];
  78. $month = $data['month'];
  79. // 规则处理
  80. $rule = match ($data['task_style']) {
  81. 1 => "0 {$minute} {$hour} * * *",
  82. 2 => "0 {$minute} * * * *",
  83. 3 => "0 {$minute} */{$hour} * * *",
  84. 4 => "0 */{$minute} * * * *",
  85. 5 => "*/{$second} * * * * *",
  86. 6 => "0 {$minute} {$hour} * * {$week}",
  87. 7 => "0 {$minute} {$hour} {$day} * *",
  88. 8 => "0 {$minute} {$hour} {$day} {$month} *",
  89. default => throw new ApiException("任务类型异常"),
  90. };
  91. // 查询任务数据
  92. $model = $this->model->findOrEmpty($id);
  93. if ($model->isEmpty()) {
  94. throw new ApiException('数据不存在');
  95. }
  96. $result = $model->save([
  97. 'name' => $data['name'],
  98. 'type' => $data['type'],
  99. 'task_style' => $data['task_style'],
  100. 'rule' => $rule,
  101. 'target' => $data['target'],
  102. 'parameter' => $data['parameter'],
  103. 'status' => $data['status'],
  104. 'remark' => $data['remark'],
  105. ]);
  106. if ($result) {
  107. // 连接到Channel服务
  108. ChannelClient::connect();
  109. ChannelClient::publish('crontab', ['args' => $id]);
  110. }
  111. // 修改任务数据
  112. return $result;
  113. }
  114. /**
  115. * 删除定时任务
  116. * @param $ids
  117. * @return bool
  118. * @throws Exception
  119. */
  120. public function destroy($ids): bool
  121. {
  122. if (is_array($ids)) {
  123. if (count($ids) > 1) {
  124. throw new ApiException('禁止批量删除操作');
  125. }
  126. $ids = $ids[0];
  127. }
  128. $result = parent::destroy($ids);
  129. if ($result) {
  130. // 连接到Channel服务
  131. ChannelClient::connect();
  132. ChannelClient::publish('crontab', ['args' => $ids]);
  133. }
  134. return $result;
  135. }
  136. /**
  137. * 修改状态
  138. * @param $id
  139. * @param $status
  140. * @return bool
  141. */
  142. public function changeStatus($id, $status): bool
  143. {
  144. $model = $this->model->findOrEmpty($id);
  145. if ($model->isEmpty()) {
  146. throw new ApiException('数据不存在');
  147. }
  148. $result = $model->save(['status' => $status]);
  149. if ($result) {
  150. // 连接到Channel服务
  151. ChannelClient::connect();
  152. ChannelClient::publish('crontab', ['args' => $id]);
  153. }
  154. return $result;
  155. }
  156. /**
  157. * 执行定时任务
  158. * @param $id
  159. * @return bool
  160. */
  161. public function run($id): bool
  162. {
  163. $info = $this->model->where('status', 1)->findOrEmpty($id);
  164. if ($info->isEmpty()) {
  165. return false;
  166. }
  167. $data['crontab_id'] = $info->id;
  168. $data['name'] = $info->name;
  169. $data['target'] = $info->target;
  170. $data['parameter'] = $info->parameter;
  171. switch ($info->type) {
  172. case 1:
  173. // URL任务GET
  174. $httpClient = new Client([
  175. 'timeout' => 5,
  176. 'verify' => false,
  177. ]);
  178. try {
  179. $httpClient->request('GET', $info->target);
  180. $data['status'] = 1;
  181. CrontabLog::create($data);
  182. return true;
  183. } catch (GuzzleException $e) {
  184. $data['status'] = 2;
  185. $data['exception_info'] = $e->getMessage();
  186. CrontabLog::create($data);
  187. return false;
  188. }
  189. case 2:
  190. // URL任务POST
  191. $httpClient = new Client([
  192. 'timeout' => 5,
  193. 'verify' => false,
  194. ]);
  195. try {
  196. $res = $httpClient->request('POST', $info->target, [
  197. 'form_params' => json_decode($info->parameter ?? '', true)
  198. ]);
  199. $data['status'] = 1;
  200. $data['exception_info'] = $res->getBody();
  201. CrontabLog::create($data);
  202. return true;
  203. } catch (GuzzleException $e) {
  204. $data['status'] = 2;
  205. $data['exception_info'] = $e->getMessage();
  206. CrontabLog::create($data);
  207. return false;
  208. }
  209. case 3:
  210. // 类任务
  211. $class_name = $info->target;
  212. $method_name = 'run';
  213. $class = new $class_name;
  214. if (method_exists($class, $method_name)) {
  215. $return = $class->$method_name($info->parameter);
  216. $data['status'] = 1;
  217. $data['exception_info'] = $return;
  218. CrontabLog::create($data);
  219. return true;
  220. } else {
  221. $data['status'] = 2;
  222. $data['exception_info'] = '类:' . $class_name . ',方法:run,未找到';
  223. CrontabLog::create($data);
  224. return false;
  225. }
  226. default:
  227. return false;
  228. }
  229. }
  230. }