From 3b12d6befd9af686332c774b1525fb64d2945492 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 25 Apr 2025 09:28:52 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E8=A7=A6=E5=AE=A2=E5=AE=9D=E3=80=91?= =?UTF-8?q?=20=E8=87=AA=E5=8A=A8=E5=88=86=E9=85=8D=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E6=A0=B9=E7=BE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/AutomaticAssign.php | 144 ++++++++++++++++++ .../command/AllotChatroomCommand.php | 102 +++++++++++++ .../command/AllotFriendCommand.php | 102 +++++++++++++ Server/application/job/AllotChatroomJob.php | 96 ++++++++++++ Server/application/job/AllotFriendJob.php | 96 ++++++++++++ 5 files changed, 540 insertions(+) create mode 100644 Server/application/api/controller/AutomaticAssign.php create mode 100644 Server/application/command/AllotChatroomCommand.php create mode 100644 Server/application/command/AllotFriendCommand.php create mode 100644 Server/application/job/AllotChatroomJob.php create mode 100644 Server/application/job/AllotFriendJob.php diff --git a/Server/application/api/controller/AutomaticAssign.php b/Server/application/api/controller/AutomaticAssign.php new file mode 100644 index 00000000..2c1957a2 --- /dev/null +++ b/Server/application/api/controller/AutomaticAssign.php @@ -0,0 +1,144 @@ +request->header('authorization', $this->authorization)); + if (empty($authorization)) { + return errorJson('缺少授权信息'); + } + + try { + // 获取请求参数 + $toAccountId = !empty($toAccountId) ? $toAccountId : input('toAccountId', ''); + $wechatAccountKeyword = !empty($wechatAccountKeyword) ? $wechatAccountKeyword : input('wechatAccountKeyword', ''); + $isDeleted = !empty($isDeleted) ? $isDeleted : input('isDeleted', false); + + if (empty($toAccountId)) { + return errorJson('目标账号ID不能为空'); + } + + $params = [ + 'accountKeyword' => '', + 'addFrom' => [], + 'allotAccountId' => '', + 'containAllLabel' => false, + 'containSubDepartment' => false, + 'departmentId' => '', + 'extendFields' => [], + 'friendKeyword' => '', + 'friendPhoneKeyword' => '', + 'friendPinYinKeyword' => '', + 'friendRegionKeyword' => '', + 'friendRemarkKeyword' => '', + 'gender' => '', + 'groupId' => null, + 'isByRule' => false, + 'isDeleted' => $isDeleted, + 'isPass' => true, + 'keyword' => '', + 'labels' => [], + 'pageIndex' => 0, + 'pageSize' => 100, + 'preFriendId' => '', + 'toAccountId' => $toAccountId, + 'wechatAccountKeyword' => $wechatAccountKeyword + ]; + + // 设置请求头 + $headerData = ['client:system']; + $header = setHeader($headerData, $authorization, 'json'); + + // 发送请求 + $result = requestCurl($this->baseUrl . 'api/WechatFriend/allotSearchResult', $params, 'PUT', $header,'json'); + $response = handleApiResponse($result); + + if($response){ + return successJson([],'微信好友自动分配成功'); + }else{ + return errorJson($response); + } + + } catch (\Exception $e) { + return errorJson('微信好友自动分配失败:' . $e->getMessage()); + } + } + + + /** + * 自动分配微信群聊 + * @param string $toAccountId 目标账号ID + * @param string $wechatAccountKeyword 微信账号关键字 + * @param bool $isDeleted 是否已删除 + * @return \think\response\Json + */ + public function autoAllotWechatChatroom($toAccountId = '', $wechatAccountKeyword = '', $isDeleted = false) + { + // 获取授权token + $authorization = trim($this->request->header('authorization', $this->authorization)); + if (empty($authorization)) { + return errorJson('缺少授权信息'); + } + + try { + // 获取请求参数 + $toAccountId = !empty($toAccountId) ? $toAccountId : input('toAccountId', ''); + $wechatAccountKeyword = !empty($wechatAccountKeyword) ? $wechatAccountKeyword : input('wechatAccountKeyword', ''); + $isDeleted = !empty($isDeleted) ? $isDeleted : input('isDeleted', false); + + if (empty($toAccountId)) { + return errorJson('目标账号ID不能为空'); + } + + $params = [ + 'AllotBySearch' => true, + 'byRule' => false, + 'comment' => '', + 'groupId' => null, + 'isDeleted' => $isDeleted, + 'keyword' => '', + 'memberKeyword' => '', + 'notifyReceiver' => false, + 'toAccountId' => $toAccountId, + 'wechatAccountKeyword' => $wechatAccountKeyword, + 'wechatChatroomId' => 0, + 'wechatChatroomIds' => [] + ]; + + // 设置请求头 + $headerData = ['client:system']; + $header = setHeader($headerData, $authorization, 'json'); + + // 发送请求 + $result = requestCurl($this->baseUrl . 'api/WechatChatroom/allotChatroom', $params, 'PUT', $header, 'json'); + $response = handleApiResponse($result); + + if($response){ + return successJson([], '微信群聊自动分配成功'); + }else{ + return errorJson($response); + } + } catch (\Exception $e) { + return errorJson('微信群聊自动分配失败:' . $e->getMessage()); + } + } +} \ No newline at end of file diff --git a/Server/application/command/AllotChatroomCommand.php b/Server/application/command/AllotChatroomCommand.php new file mode 100644 index 00000000..e0a76845 --- /dev/null +++ b/Server/application/command/AllotChatroomCommand.php @@ -0,0 +1,102 @@ +setName('allotChatroom:run') + ->setDescription('自动分配微信群聊') + ->addOption('toAccountId', null, Option::VALUE_REQUIRED, '目标账号ID') + ->addOption('wechatAccountKeyword', null, Option::VALUE_REQUIRED, '微信账号关键字') + ->addOption('isDeleted', null, Option::VALUE_OPTIONAL, '是否已删除状态: 0=未删除(false), 1=已删除(true)', 0) + ->addOption('jobId', null, Option::VALUE_OPTIONAL, '任务ID,用于区分不同实例', date('YmdHis') . rand(1000, 9999)); + } + + protected function execute(Input $input, Output $output) + { + $output->writeln('开始处理微信群聊自动分配任务...'); + + try { + // 获取命令参数 + $toAccountId = $input->getOption('toAccountId'); + $wechatAccountKeyword = $input->getOption('wechatAccountKeyword'); + $isDeleted = $input->getOption('isDeleted'); + $jobId = $input->getOption('jobId'); + + // 验证必填参数 + if (empty($toAccountId)) { + $output->writeln('错误: 目标账号ID不能为空'); + return false; + } + + if (empty($wechatAccountKeyword)) { + $output->writeln('错误: 微信账号关键字不能为空'); + return false; + } + + $output->writeln('目标账号ID: ' . $toAccountId); + $output->writeln('微信账号关键字: ' . $wechatAccountKeyword); + $output->writeln('删除状态: ' . ($isDeleted ? '已删除' : '未删除')); + $output->writeln('任务ID: ' . $jobId); + + // 检查队列是否已经在运行 + $queueLockKey = "queue_lock:{$this->queueName}:{$wechatAccountKeyword}"; + if (Cache::get($queueLockKey)) { + $output->writeln("队列 {$this->queueName} 已经在运行中,wechatAccountKeyword:{$wechatAccountKeyword},跳过执行"); + Log::warning("队列 {$this->queueName} 已经在运行中,wechatAccountKeyword:{$wechatAccountKeyword},跳过执行"); + return false; + } + + // 设置队列运行锁,有效期1小时 + Cache::set($queueLockKey, $jobId, 3600); + $output->writeln("已设置队列运行锁,键名:{$queueLockKey},值:{$jobId},有效期:1小时"); + + // 将任务添加到队列 + $this->addToQueue($toAccountId, $wechatAccountKeyword, $isDeleted, $jobId, $queueLockKey); + + $output->writeln('微信群聊自动分配任务已添加到队列'); + } catch (\Exception $e) { + Log::error('微信群聊自动分配任务添加失败:' . $e->getMessage()); + $output->writeln('微信群聊自动分配任务添加失败:' . $e->getMessage()); + return false; + } + + return true; + } + + /** + * 添加任务到队列 + * @param string $toAccountId 目标账号ID + * @param string $wechatAccountKeyword 微信账号关键字 + * @param bool $isDeleted 是否已删除状态 + * @param string $jobId 任务ID + * @param string $queueLockKey 队列锁键名 + */ + public function addToQueue($toAccountId, $wechatAccountKeyword, $isDeleted = false, $jobId = '', $queueLockKey = '') + { + $data = [ + 'toAccountId' => $toAccountId, + 'wechatAccountKeyword' => $wechatAccountKeyword, + 'isDeleted' => $isDeleted, + 'jobId' => $jobId, + 'queueLockKey' => $queueLockKey + ]; + + // 添加到队列 + Queue::push(AllotChatroomJob::class, $data, $this->queueName); + } +} \ No newline at end of file diff --git a/Server/application/command/AllotFriendCommand.php b/Server/application/command/AllotFriendCommand.php new file mode 100644 index 00000000..d8d34b81 --- /dev/null +++ b/Server/application/command/AllotFriendCommand.php @@ -0,0 +1,102 @@ +setName('allotFriends:run') + ->setDescription('自动分配微信好友') + ->addOption('toAccountId', null, Option::VALUE_REQUIRED, '目标账号ID') + ->addOption('wechatAccountKeyword', null, Option::VALUE_REQUIRED, '微信账号关键字') + ->addOption('isDeleted', null, Option::VALUE_OPTIONAL, '是否已删除状态: 0=未删除(false), 1=已删除(true)', 0) + ->addOption('jobId', null, Option::VALUE_OPTIONAL, '任务ID,用于区分不同实例', date('YmdHis') . rand(1000, 9999)); + } + + protected function execute(Input $input, Output $output) + { + $output->writeln('开始处理微信好友自动分配任务...'); + + try { + // 获取命令参数 + $toAccountId = $input->getOption('toAccountId'); + $wechatAccountKeyword = $input->getOption('wechatAccountKeyword'); + $isDeleted = $input->getOption('isDeleted'); + $jobId = $input->getOption('jobId'); + + // 验证必填参数 + if (empty($toAccountId)) { + $output->writeln('错误: 目标账号ID不能为空'); + return false; + } + + if (empty($wechatAccountKeyword)) { + $output->writeln('错误: 微信账号关键字不能为空'); + return false; + } + + $output->writeln('目标账号ID: ' . $toAccountId); + $output->writeln('微信账号关键字: ' . $wechatAccountKeyword); + $output->writeln('删除状态: ' . ($isDeleted ? '已删除' : '未删除')); + $output->writeln('任务ID: ' . $jobId); + + // 检查队列是否已经在运行 + $queueLockKey = "queue_lock:{$this->queueName}:{$wechatAccountKeyword}"; + if (Cache::get($queueLockKey)) { + $output->writeln("队列 {$this->queueName} 已经在运行中,wechatAccountKeyword:{$wechatAccountKeyword},跳过执行"); + Log::warning("队列 {$this->queueName} 已经在运行中,wechatAccountKeyword:{$wechatAccountKeyword},跳过执行"); + return false; + } + + // 设置队列运行锁,有效期1小时 + Cache::set($queueLockKey, $jobId, 3600); + $output->writeln("已设置队列运行锁,键名:{$queueLockKey},值:{$jobId},有效期:1小时"); + + // 将任务添加到队列 + $this->addToQueue($toAccountId, $wechatAccountKeyword, $isDeleted, $jobId, $queueLockKey); + + $output->writeln('微信好友自动分配任务已添加到队列'); + } catch (\Exception $e) { + Log::error('微信好友自动分配任务添加失败:' . $e->getMessage()); + $output->writeln('微信好友自动分配任务添加失败:' . $e->getMessage()); + return false; + } + + return true; + } + + /** + * 添加任务到队列 + * @param string $toAccountId 目标账号ID + * @param string $wechatAccountKeyword 微信账号关键字 + * @param bool $isDeleted 是否已删除状态 + * @param string $jobId 任务ID + * @param string $queueLockKey 队列锁键名 + */ + public function addToQueue($toAccountId, $wechatAccountKeyword, $isDeleted = false, $jobId = '', $queueLockKey = '') + { + $data = [ + 'toAccountId' => $toAccountId, + 'wechatAccountKeyword' => $wechatAccountKeyword, + 'isDeleted' => $isDeleted, + 'jobId' => $jobId, + 'queueLockKey' => $queueLockKey + ]; + + // 添加到队列 + Queue::push(AllotFriendJob::class, $data, $this->queueName); + } +} \ No newline at end of file diff --git a/Server/application/job/AllotChatroomJob.php b/Server/application/job/AllotChatroomJob.php new file mode 100644 index 00000000..96c01b19 --- /dev/null +++ b/Server/application/job/AllotChatroomJob.php @@ -0,0 +1,96 @@ + $toAccountId, + 'wechatAccountKeyword' => $wechatAccountKeyword, + 'isDeleted' => $isDeleted, + 'jobId' => $jobId, + 'queueLockKey' => $queueLockKey + ])); + + // 如果没有提供队列锁键,生成一个 + if (empty($queueLockKey)) { + $queueLockKey = "queue_lock:allot_chatroom:{$wechatAccountKeyword}"; + } + + // 实例化控制器 + $automaticAssignController = new AutomaticAssign(); + + // 调用微信群聊自动分配方法 + $result = $automaticAssignController->autoAllotWechatChatroom($toAccountId, $wechatAccountKeyword, $isDeleted); + $response = json_decode($result, true); + + // 判断是否成功 + if ($response['code'] == 1) { + Log::info("微信群聊自动分配成功: toAccountId={$toAccountId}, wechatAccountKeyword={$wechatAccountKeyword}"); + + // 释放队列锁 + Cache::rm($queueLockKey); + Log::info("任务完成,释放队列锁: {$queueLockKey}"); + + $job->delete(); + return true; + } else { + // API调用出错,记录错误 + $errorMsg = isset($response['msg']) ? $response['msg'] : '未知错误'; + Log::error("微信群聊自动分配失败: {$errorMsg}"); + + if ($job->attempts() > 3) { + // 超过重试次数,删除任务并释放队列锁 + Cache::rm($queueLockKey); + Log::info("由于错误多次尝试失败,释放队列锁: {$queueLockKey}"); + $job->delete(); + } else { + // 任务失败,重新放回队列 + Log::warning("微信群聊自动分配任务执行失败,重试次数: " . $job->attempts()); + $job->release(10); // 延迟10秒后重试 + } + + return false; + } + } catch (\Exception $e) { + // 出现异常,记录错误并释放队列锁 + Log::error('微信群聊自动分配任务异常: ' . $e->getMessage()); + + if (!empty($queueLockKey)) { + Cache::rm($queueLockKey); + Log::info("由于异常释放队列锁: {$queueLockKey}"); + } + + if ($job->attempts() > 3) { + $job->delete(); + } else { + $job->release(10); + } + + return false; + } + } +} \ No newline at end of file diff --git a/Server/application/job/AllotFriendJob.php b/Server/application/job/AllotFriendJob.php new file mode 100644 index 00000000..baeeb6ef --- /dev/null +++ b/Server/application/job/AllotFriendJob.php @@ -0,0 +1,96 @@ + $toAccountId, + 'wechatAccountKeyword' => $wechatAccountKeyword, + 'isDeleted' => $isDeleted, + 'jobId' => $jobId, + 'queueLockKey' => $queueLockKey + ])); + + // 如果没有提供队列锁键,生成一个 + if (empty($queueLockKey)) { + $queueLockKey = "queue_lock:allot_friends:{$wechatAccountKeyword}"; + } + + // 实例化控制器 + $automaticAssignController = new AutomaticAssign(); + + // 调用微信好友自动分配方法 + $result = $automaticAssignController->autoAllotWechatFriend($toAccountId, $wechatAccountKeyword, $isDeleted); + $response = json_decode($result, true); + + // 判断是否成功 + if ($response['code'] == 1) { + Log::info("微信好友自动分配成功: toAccountId={$toAccountId}, wechatAccountKeyword={$wechatAccountKeyword}"); + + // 释放队列锁 + Cache::rm($queueLockKey); + Log::info("任务完成,释放队列锁: {$queueLockKey}"); + + $job->delete(); + return true; + } else { + // API调用出错,记录错误 + $errorMsg = isset($response['msg']) ? $response['msg'] : '未知错误'; + Log::error("微信好友自动分配失败: {$errorMsg}"); + + if ($job->attempts() > 3) { + // 超过重试次数,删除任务并释放队列锁 + Cache::rm($queueLockKey); + Log::info("由于错误多次尝试失败,释放队列锁: {$queueLockKey}"); + $job->delete(); + } else { + // 任务失败,重新放回队列 + Log::warning("微信好友自动分配任务执行失败,重试次数: " . $job->attempts()); + $job->release(10); // 延迟10秒后重试 + } + + return false; + } + } catch (\Exception $e) { + // 出现异常,记录错误并释放队列锁 + Log::error('微信好友自动分配任务异常: ' . $e->getMessage()); + + if (!empty($queueLockKey)) { + Cache::rm($queueLockKey); + Log::info("由于异常释放队列锁: {$queueLockKey}"); + } + + if ($job->attempts() > 3) { + $job->delete(); + } else { + $job->release(10); + } + + return false; + } + } +} \ No newline at end of file