TodoRemindJob.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. namespace App\Jobs;
  3. use App\Model\TodoList;
  4. use App\Model\WxEmployeeOfficial;
  5. use App\Service\Weixin\WxTemplateMessageService;
  6. use Illuminate\Bus\Queueable;
  7. use Illuminate\Contracts\Queue\ShouldQueue;
  8. use Illuminate\Foundation\Bus\Dispatchable;
  9. use Illuminate\Queue\InteractsWithQueue;
  10. use Illuminate\Queue\SerializesModels;
  11. use Illuminate\Support\Facades\Cache;
  12. use Illuminate\Support\Facades\DB;
  13. use Illuminate\Support\Facades\Log;
  14. use Illuminate\Support\Facades\Redis;
  15. use MongoDB\Driver\Exception\Exception;
  16. use Symfony\Component\Console\Output\ConsoleOutput;
  17. use Symfony\Component\Console\Output\OutputInterface;
  18. class TodoRemindJob implements ShouldQueue
  19. {
  20. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  21. public $todoId;
  22. public $tries = 1;
  23. public function __construct($todoId)
  24. {
  25. $this->todoId = $todoId;
  26. }
  27. public function handle()
  28. {
  29. $this->doJob();
  30. }
  31. private function doJob(){
  32. $now = time();
  33. $appid = config("wx_msg.f_appid");
  34. $wxSrv = new WxTemplateMessageService();
  35. $todo = TodoList::find($this->todoId);
  36. if (!$todo || $todo->del_time != 0 || $todo->status >= TodoList::status_two) {
  37. return;
  38. }
  39. // 分布式锁
  40. $lockKey = "todo_remind_lock:" . $todo->id;
  41. $lock = Cache::lock($lockKey, 5);
  42. if (! $lock->get()) {
  43. return; // 其他进程在处理,直接跳过
  44. }
  45. try {
  46. // ======================
  47. // 1. 是否应该提醒
  48. // ======================
  49. if (! $this->shouldRemind($todo, $now)) {
  50. return;
  51. }
  52. // 查 openid
  53. $openid = WxEmployeeOfficial::where('employee_id', $todo->crt_id)
  54. ->where('type', WxEmployeeOfficial::login_type_two)
  55. ->where('appid', $appid)
  56. ->value('openid');
  57. if (!$openid) {
  58. $this->updateTodoStatus($todo, $now, '无openid');
  59. return;
  60. }
  61. // ======================
  62. // 2. 调微信接口发送
  63. // ======================
  64. list($ok, $msg) = $wxSrv->sendTemplateMessage('to_do', [
  65. 'title' => $todo->title ?? '待办提醒',
  66. 'time' => date('Y-m-d H:i:00', $todo->remind_start),
  67. ], [
  68. 'openid' => $openid,
  69. 'pagepath' => 'pages/todoManage/add?type=4&id=' . $todo->id,
  70. ]);
  71. $this->updateTodoStatus($todo, $now, $msg);
  72. } finally {
  73. $lock->release();
  74. }
  75. }
  76. private function shouldRemind($todo, $now)
  77. {
  78. if ($todo->remind_interval == 0 && empty($todo->last_remind_time)) {
  79. return true;
  80. }
  81. if ($todo->remind_interval > 0) {
  82. if (empty($todo->last_remind_time)) return true;
  83. return ($now - $todo->last_remind_time) >= $todo->remind_interval;
  84. }
  85. return false;
  86. }
  87. private function updateTodoStatus($todo, $now, $msg)
  88. {
  89. $msg = is_scalar($msg) ? $msg : json_encode($msg, JSON_UNESCAPED_UNICODE);
  90. TodoList::where('id', $todo->id)
  91. ->where('last_remind_time', $todo->last_remind_time ?? 0)
  92. ->update([
  93. 'last_remind_time' => $now,
  94. 'status' => TodoList::status_one,
  95. 'last_time_result' => $msg,
  96. ]);
  97. }
  98. protected function echoMessage(OutputInterface $output)
  99. {
  100. //输出消息
  101. $output->writeln(json_encode($this->data));
  102. }
  103. }