|
|
@@ -6,6 +6,7 @@ use App\Model\TodoList;
|
|
|
use App\Model\WxEmployeeOfficial;
|
|
|
use App\Service\Weixin\WxTemplateMessageService;
|
|
|
use Illuminate\Console\Command;
|
|
|
+use Illuminate\Support\Facades\Cache;
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
@@ -49,7 +50,7 @@ class ToDoReminder extends Command
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public function handleReminders()
|
|
|
+ public function handleReminders1()
|
|
|
{
|
|
|
$now = time();
|
|
|
|
|
|
@@ -109,6 +110,92 @@ class ToDoReminder extends Command
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ public function handleReminders()
|
|
|
+ {
|
|
|
+ $now = time();
|
|
|
+ $appid = config("wx_msg.f_appid");
|
|
|
+ $wxSrv = new WxTemplateMessageService();
|
|
|
+
|
|
|
+ // 推荐按提醒时间来排序
|
|
|
+ TodoList::where('status', '<', TodoList::status_two)
|
|
|
+ ->where('del_time', 0)
|
|
|
+ ->where('remind_start', '<=', $now)
|
|
|
+ ->orderBy('remind_start')
|
|
|
+ ->chunkById(20, function ($list) use ($now, $appid, $wxSrv) {
|
|
|
+ // 批量拿创建人 ID
|
|
|
+ $crtIds = array_unique($list->pluck('crt_id')->toArray());
|
|
|
+
|
|
|
+ // 批量查询 openid(统一用字符串 key)
|
|
|
+ $wxInfo = WxEmployeeOfficial::where('employee_id', $crtIds)
|
|
|
+ ->where('type', WxEmployeeOfficial::login_type_two)
|
|
|
+ ->where('appid', $appid)
|
|
|
+ ->pluck('openid','employee_id')
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ // 处理每一条
|
|
|
+ foreach ($list as $todo) {
|
|
|
+
|
|
|
+ // 分布式锁(避免并发重复提醒)
|
|
|
+ $lockKey = "todo_remind_lock:" . $todo->id;
|
|
|
+ if (! Cache::lock($lockKey, 5)->get()) {
|
|
|
+ continue; // 已有别的任务在处理本记录
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 1. 判断是否应提醒
|
|
|
+ if (! $this->shouldRemind($todo, $now)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 发送消息
|
|
|
+ list($ok, $msg) = $this->sendReminder($todo, $wxSrv, $wxInfo);
|
|
|
+
|
|
|
+ if (! $ok) {
|
|
|
+ Log::warning("发送待办提醒失败 todo_id={$todo->id}", ['msg' => $msg]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->updateTodoStatus($todo, $now, $msg);
|
|
|
+
|
|
|
+ } catch (\Throwable $e) {
|
|
|
+ Log::error("提醒异常 todo_id={$todo->id}", ['msg' => $e->getMessage()]);
|
|
|
+ } finally {
|
|
|
+ Cache::lock($lockKey)->release();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function shouldRemind($todo, $now)
|
|
|
+ {
|
|
|
+ // 首次提醒
|
|
|
+ if ($todo->remind_interval == 0 && empty($todo->last_remind_time)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 间隔提醒
|
|
|
+ if ($todo->remind_interval > 0) {
|
|
|
+ if (empty($todo->last_remind_time)) return true;
|
|
|
+ return ($now - $todo->last_remind_time) >= $todo->remind_interval;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function updateTodoStatus($todo, $now, $msg)
|
|
|
+ {
|
|
|
+ // 防止 msg 是数组,写入数据库报错
|
|
|
+ $msg = is_scalar($msg) ? $msg : json_encode($msg, JSON_UNESCAPED_UNICODE);
|
|
|
+
|
|
|
+ // 乐观锁,防重复写
|
|
|
+ TodoList::where('id', $todo->id)
|
|
|
+ ->where('last_remind_time', $todo->last_remind_time ?? 0)
|
|
|
+ ->update([
|
|
|
+ 'last_remind_time' => $now,
|
|
|
+ 'status' => TodoList::status_one,
|
|
|
+ 'last_time_result' => $msg,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
protected function sendReminder($todo, $wxService, $wxInfo)
|
|
|
{
|
|
|
// 查找关联员工 openid
|