From 0bbb9c127355bffb29e7a1c5c6ba779b8377a95c Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 14:07:11 +0800 Subject: [PATCH 01/24] =?UTF-8?q?=E6=B5=B7=E6=8A=A5=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Server/application/cunkebao/config/route.php | 13 +++++++++++++ .../controller/ContentLibraryController.php | 7 +++---- .../chatroom/GetChatroomListV1Controller.php | 14 ++++++++++---- .../controller/plan/PosterWeChatMiniProgram.php | 5 ++--- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index fc6f5588..88a0ce1b 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -100,4 +100,17 @@ Route::group('v1/', function () { }); })->middleware(['jwt']); + + +Route::group('v1/frontend', function () { + + Route::group('business/poster', function () { + Route::get('getone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPosterTaskData'); + }); +}); + + + + + return []; \ No newline at end of file diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 3aea2a28..ee45f729 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -419,7 +419,7 @@ class ContentLibraryController extends Controller // 查询数据 $list = ContentItem::where($where) - ->order('createTime', 'desc') + ->order('createMomentTime DESC,createTime DESC') ->page($page, $limit) ->select(); @@ -763,7 +763,6 @@ class ContentLibraryController extends Controller $where = [ ['isDel', '=', 0], // 未删除 ['status', '=', 1], // 已开启 - ['id', '=', 27] ]; // 查询符合条件的内容库 @@ -1405,10 +1404,10 @@ class ContentLibraryController extends Controller $coverImage = $resUrls[0]; } - // 判断内容类型 (0=未知, 1=图片, 2=链接, 3=视频, 4=文本, 5=小程序, 6=图文) + // 判断内容类型 (0=未知, 1=图片, 2=链接, 3=视频, 4=文本, 5=小程序) if($moment['type'] == 1) { //图文 - $contentType = 6; + $contentType = 1; }elseif ($moment['type'] == 3){ //链接 $contentType = 2; diff --git a/Server/application/cunkebao/controller/chatroom/GetChatroomListV1Controller.php b/Server/application/cunkebao/controller/chatroom/GetChatroomListV1Controller.php index 83e50ee3..a08a5db9 100644 --- a/Server/application/cunkebao/controller/chatroom/GetChatroomListV1Controller.php +++ b/Server/application/cunkebao/controller/chatroom/GetChatroomListV1Controller.php @@ -21,25 +21,31 @@ class GetChatroomListV1Controller extends BaseController $limit = $this->request->param('limit', 20); $keyword = $this->request->param('keyword', ''); try { + + $wechatIds = Db::name('device')->alias('d') + ->join('device_wechat_login dwl','dwl.deviceId=d.id AND dwl.companyId='.$this->getUserInfo('companyId')) + ->where(['d.companyId' => $this->getUserInfo('companyId'),'d.deleteTime' => 0]) + ->column('dwl.wechatId'); + $where = []; if ($this->getUserInfo('isAdmin') == 1) { - $where[] = ['g.companyId', '=', $this->getUserInfo('companyId')]; $where[] = ['g.deleteTime', '=', 0]; + $where[] = ['g.ownerWechatId', 'in', $wechatIds]; } else { - $where[] = ['g.companyId', '=', $this->getUserInfo('companyId')]; $where[] = ['g.deleteTime', '=', 0]; + $where[] = ['g.ownerWechatId', 'in', $wechatIds]; //$where[] = ['g.userId', '=', $this->getUserInfo('id')]; } if(!empty($keyword)){ $where[] = ['g.name', 'like', '%'.$keyword.'%']; } - + $data = WechatChatroom::alias('g') ->field(['g.id', 'g.chatroomId', 'g.name', 'g.avatar','g.ownerWechatId', 'g.identifier', 'g.createTime', 'wa.nickname as ownerNickname','wa.avatar as ownerAvatar','wa.alias as ownerAlias']) - ->Join('wechat_account wa', 'g.ownerWechatId = wa.wechatId', 'LEFT') + ->join('wechat_account wa', 'g.ownerWechatId = wa.wechatId', 'LEFT') ->where($where); $total = $data->count(); diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index 3c766e47..fbf910d4 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -16,9 +16,8 @@ class PosterWeChatMiniProgram extends Controller } const MINI_PROGRAM_CONFIG = [ - 'app_id' => 'wx12345678', - 'secret' => 'your-app-secret', - + 'app_id' => 'wx789850448e26c91d', + 'secret' => 'd18f75b3a3623cb40da05648b08365a1', 'response_type' => 'array' ]; From 6392b99e13ceb2706c0bcc356b4d5df86a26f6f5 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 14:57:32 +0800 Subject: [PATCH 02/24] =?UTF-8?q?=E6=B5=B7=E6=8A=A5=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Server/application/cunkebao/config/route.php | 3 +- .../plan/PosterWeChatMiniProgram.php | 39 +++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 88a0ce1b..59d4ec15 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -105,7 +105,8 @@ Route::group('v1/', function () { Route::group('v1/frontend', function () { Route::group('business/poster', function () { - Route::get('getone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPosterTaskData'); + Route::post('getone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPosterTaskData'); + Route::post('decryptphone', 'app\cunkebao\controller\plan\PosterWeChatMiniProgram@getPhoneNumber'); }); }); diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index fbf910d4..236354ea 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -124,12 +124,45 @@ class PosterWeChatMiniProgram extends Controller // todo 获取海报获客任务的任务/海报数据 -- 表还没设计好,不急 ck_customer_acquisition_task public function getPosterTaskData() { $id = request()->param('id'); - $task = Db::name('customer_acquisition_task')->where('id', $id)->find(); + $task = Db::name('customer_acquisition_task')->where(['id' => $id,'deleteTime' => 0])->find(); + if (!$task) { + return json([ + 'code' => 400, + 'message' => '任务不存在' + ]); + } + + if($task['status'] == 0) { + return json([ + 'code' => 400, + 'message' => '任务已结束' + ]); + } + + $sceneConf = json_decode($task['sceneConf'], true); + + if(isset($sceneConf['posters'][0]['preview'])) { + $posterUrl = $sceneConf['posters'][0]['preview']; + } else { + $posterUrl = ''; + } + + + + + $data = [ + 'id' => $task['id'], + 'name' => $task['name'], + 'poster' => ['sUrl' => $posterUrl], + 'sTip' => '啦啦啦啦', + ]; + + // todo 只需 返回 poster_url success_tip return json([ - 'code' => 0, + 'code' => 10000, 'message' => '获取海报获客任务数据成功', - 'data' => $task + 'data' => $data ]); } From 7276f787d8cd2a38fd224e9fb49c2d08b4d1072c Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 17:23:46 +0800 Subject: [PATCH 03/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Server/application/cunkebao/config/route.php | 1 + .../controller/plan/PlanSceneV1Controller.php | 33 +++++++++++++++++++ .../plan/PosterWeChatMiniProgram.php | 10 +++--- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 59d4ec15..48afe0fd 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -45,6 +45,7 @@ Route::group('v1/', function () { Route::post('updateStatus', 'app\cunkebao\controller\plan\PlanSceneV1Controller@updateStatus'); Route::get('detail', 'app\cunkebao\controller\plan\GetAddFriendPlanDetailV1Controller@index'); Route::PUT('update', 'app\cunkebao\controller\plan\PostUpdateAddFriendPlanV1Controller@index'); + Route::get('getWxMinAppCode', 'app\cunkebao\controller\plan\PlanSceneV1Controller@getWxMinAppCode'); }); // 流量池相关 diff --git a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php index f43428e3..b937f72b 100644 --- a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php @@ -5,6 +5,8 @@ namespace app\cunkebao\controller\plan; use library\ResponseHelper; use think\Db; use app\cunkebao\controller\BaseController; +use app\cunkebao\controller\plan\PosterWeChatMiniProgram; + /** * 获取计划任务列表控制器 */ @@ -375,4 +377,35 @@ class PlanSceneV1Controller extends BaseController 'completion_rate' => $totalTasks > 0 ? round(($completedTasks / $totalTasks) * 100, 2) : 0 ]; } + + + + public function getWxMinAppCode() + { + $params = $this->request->param(); + $taskId = isset($params['taskId']) ? intval($params['taskId']) : 0; + + if($taskId <= 0) { + return ResponseHelper::error('任务ID或场景ID不能为空', 400); + } + + $task = Db::name('customer_acquisition_task')->where(['id' => $taskId, 'deleteTime' => 0])->find(); + if(!$task) { + return ResponseHelper::error('任务不存在', 400); + } + + $posterWeChatMiniProgram = new PosterWeChatMiniProgram(); + $result = $posterWeChatMiniProgram->generateMiniProgramCodeWithScene($taskId); + if($result['code'] != 200) { + return ResponseHelper::error($result['message'], 400); + } + + return ResponseHelper::success($result['data'], '获取小程序码成功'); + + + + + + } + } \ No newline at end of file diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index 236354ea..38cbbfb3 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -23,9 +23,11 @@ class PosterWeChatMiniProgram extends Controller // 生成小程序码,存客宝-操盘手调用 - public function generateMiniProgramCodeWithScene() { + public function generateMiniProgramCodeWithScene($taskId = '') { - $taskId = request()->param('id'); + if(empty($taskId)) { + $taskId = request()->param('id'); + } $app = Factory::miniProgram(self::MINI_PROGRAM_CONFIG); @@ -105,7 +107,7 @@ class PosterWeChatMiniProgram extends Controller } // return $result['phone_info']['phoneNumber']; return json([ - 'code' => 0, + 'code' => 200, 'message' => '获取手机号成功', 'data' => $result['phone_info']['phoneNumber'] ]); @@ -160,7 +162,7 @@ class PosterWeChatMiniProgram extends Controller // todo 只需 返回 poster_url success_tip return json([ - 'code' => 10000, + 'code' => 200, 'message' => '获取海报获客任务数据成功', 'data' => $data ]); From be9a5a44c96d1c062b03f9a51499d353f438c294 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 17:26:24 +0800 Subject: [PATCH 04/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cunkebao/controller/plan/PlanSceneV1Controller.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php index b937f72b..c3c0c1a1 100644 --- a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php @@ -396,11 +396,9 @@ class PlanSceneV1Controller extends BaseController $posterWeChatMiniProgram = new PosterWeChatMiniProgram(); $result = $posterWeChatMiniProgram->generateMiniProgramCodeWithScene($taskId); - if($result['code'] != 200) { - return ResponseHelper::error($result['message'], 400); - } + - return ResponseHelper::success($result['data'], '获取小程序码成功'); + return ResponseHelper::success($result, '获取小程序码成功'); From 72e8c12dce9045ec5024fcfea6744380ae61b913 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 17:41:03 +0800 Subject: [PATCH 05/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/plan/PosterWeChatMiniProgram.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index 38cbbfb3..c6550be8 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -50,9 +50,14 @@ class PosterWeChatMiniProgram extends Controller // $response->saveAs('path/to/codes', $filename); // return 'path/to/codes/' . $filename; - $img = $response->getBody()->getContents();//获取图片二进制流 - $img_base64 = 'data:image/png;base64,' .base64_encode($img);//转化base64 - return $img_base64; + // $img = $response->getBody()->getContents();//获取图片二进制流 + // $img_base64 = 'data:image/png;base64,' .base64_encode($img);//转化base64 + // return $img_base64; + + + $filename = $response->saveAs('/www/wwwroot/mckb_quwanzhi_com/Server/runtime/img', 'appcode_'.$taskId.'.png'); + return $filename; + } // return false; From 381006ddbe6be6e5df25028900075ac474094a58 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 17:52:01 +0800 Subject: [PATCH 06/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan/PosterWeChatMiniProgram.php | 58 +++++++++++++++---- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index c6550be8..1fa0fe0f 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -8,6 +8,7 @@ use EasyWeChat\Factory; // use EasyWeChat\Kernel\Exceptions\DecryptException; use EasyWeChat\Kernel\Http\StreamResponse; use think\Db; +use app\common\util\AliyunOSS; class PosterWeChatMiniProgram extends Controller { public function index() @@ -46,17 +47,23 @@ class PosterWeChatMiniProgram extends Controller // 保存小程序码到文件 if ($response instanceof StreamResponse) { - // $filename = 'minicode_' . $taskId . '.png'; - // $response->saveAs('path/to/codes', $filename); - // return 'path/to/codes/' . $filename; - - // $img = $response->getBody()->getContents();//获取图片二进制流 - // $img_base64 = 'data:image/png;base64,' .base64_encode($img);//转化base64 - // return $img_base64; - - - $filename = $response->saveAs('/www/wwwroot/mckb_quwanzhi_com/Server/runtime/img', 'appcode_'.$taskId.'.png'); - return $filename; + $savePath = ROOT_PATH . 'runtime/img'; + // 确保目录存在 + if (!is_dir($savePath)) { + mkdir($savePath, 0755, true); + } + $filename = $response->saveAs($savePath, 'appcode_'.$taskId.'.png'); + + // 上传到OSS + if ($filename) { + $ossUrl = $this->uploadToOSS($filename); + // 删除本地文件 + if (file_exists($filename)) { + unlink($filename); + } + // 如果OSS上传成功,返回OSS URL;否则返回本地文件路径 + return $ossUrl ?: $filename; + } } @@ -64,6 +71,35 @@ class PosterWeChatMiniProgram extends Controller return null; } + /** + * 上传文件到OSS + * @param string $filePath 本地文件路径 + * @return string|false 成功返回OSS URL,失败返回false + */ + private function uploadToOSS($filePath) + { + try { + // 生成OSS对象名称 + $objectName = AliyunOSS::generateObjectName('appcode_' . time() . '.png'); + + // 上传到OSS + $result = AliyunOSS::uploadFile($filePath, $objectName); + + if ($result['success']) { + // 返回完整的OSS URL + return AliyunOSS::ossUrl . '/' . $objectName; + } else { + // 记录错误日志 + \think\facade\Log::error('OSS上传失败: ' . $result['error'] . ' 文件: ' . $filePath); + return false; + } + } catch (\Exception $e) { + // 记录错误日志 + \think\facade\Log::error('OSS上传异常: ' . $e->getMessage() . ' 文件: ' . $filePath); + return false; + } + } + // getPhoneNumber public function getPhoneNumber() { From d242ddee022f13812885b24f072212d7aa4116f9 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 17:53:42 +0800 Subject: [PATCH 07/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cunkebao/controller/plan/PosterWeChatMiniProgram.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index 1fa0fe0f..a03f1677 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -47,7 +47,7 @@ class PosterWeChatMiniProgram extends Controller // 保存小程序码到文件 if ($response instanceof StreamResponse) { - $savePath = ROOT_PATH . 'runtime/img'; + $savePath = ROOT_PATH . '/runtime/img'; // 确保目录存在 if (!is_dir($savePath)) { mkdir($savePath, 0755, true); From 02ff5fdd75826c0196f58212fae7bf73459c3663 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 17:58:31 +0800 Subject: [PATCH 08/24] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E4=B8=8A=E4=BC=A0oss?= =?UTF-8?q?=E7=9A=84=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/plan/PlanSceneV1Controller.php | 1 + .../plan/PosterWeChatMiniProgram.php | 57 +++---------------- 2 files changed, 8 insertions(+), 50 deletions(-) diff --git a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php index c3c0c1a1..cee62016 100644 --- a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php @@ -397,6 +397,7 @@ class PlanSceneV1Controller extends BaseController $posterWeChatMiniProgram = new PosterWeChatMiniProgram(); $result = $posterWeChatMiniProgram->generateMiniProgramCodeWithScene($taskId); + return $result; return ResponseHelper::success($result, '获取小程序码成功'); diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index a03f1677..075a5217 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -8,7 +8,6 @@ use EasyWeChat\Factory; // use EasyWeChat\Kernel\Exceptions\DecryptException; use EasyWeChat\Kernel\Http\StreamResponse; use think\Db; -use app\common\util\AliyunOSS; class PosterWeChatMiniProgram extends Controller { public function index() @@ -26,9 +25,7 @@ class PosterWeChatMiniProgram extends Controller // 生成小程序码,存客宝-操盘手调用 public function generateMiniProgramCodeWithScene($taskId = '') { - if(empty($taskId)) { - $taskId = request()->param('id'); - } + $taskId = request()->param('id'); $app = Factory::miniProgram(self::MINI_PROGRAM_CONFIG); @@ -47,59 +44,19 @@ class PosterWeChatMiniProgram extends Controller // 保存小程序码到文件 if ($response instanceof StreamResponse) { - $savePath = ROOT_PATH . '/runtime/img'; - // 确保目录存在 - if (!is_dir($savePath)) { - mkdir($savePath, 0755, true); - } - $filename = $response->saveAs($savePath, 'appcode_'.$taskId.'.png'); - - // 上传到OSS - if ($filename) { - $ossUrl = $this->uploadToOSS($filename); - // 删除本地文件 - if (file_exists($filename)) { - unlink($filename); - } - // 如果OSS上传成功,返回OSS URL;否则返回本地文件路径 - return $ossUrl ?: $filename; - } + // $filename = 'minicode_' . $taskId . '.png'; + // $response->saveAs('path/to/codes', $filename); + // return 'path/to/codes/' . $filename; + $img = $response->getBody()->getContents();//获取图片二进制流 + $img_base64 = 'data:image/png;base64,' .base64_encode($img);//转化base64 + return $img_base64; } // return false; return null; } - /** - * 上传文件到OSS - * @param string $filePath 本地文件路径 - * @return string|false 成功返回OSS URL,失败返回false - */ - private function uploadToOSS($filePath) - { - try { - // 生成OSS对象名称 - $objectName = AliyunOSS::generateObjectName('appcode_' . time() . '.png'); - - // 上传到OSS - $result = AliyunOSS::uploadFile($filePath, $objectName); - - if ($result['success']) { - // 返回完整的OSS URL - return AliyunOSS::ossUrl . '/' . $objectName; - } else { - // 记录错误日志 - \think\facade\Log::error('OSS上传失败: ' . $result['error'] . ' 文件: ' . $filePath); - return false; - } - } catch (\Exception $e) { - // 记录错误日志 - \think\facade\Log::error('OSS上传异常: ' . $e->getMessage() . ' 文件: ' . $filePath); - return false; - } - } - // getPhoneNumber public function getPhoneNumber() { From 0a91a5b4e203f77f19cdd67dac86384d4e1578d0 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Thu, 10 Jul 2025 18:01:43 +0800 Subject: [PATCH 09/24] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E7=A0=81=E6=9C=80=E7=BB=88=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cunkebao/controller/plan/PlanSceneV1Controller.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php index cee62016..d9bc41c3 100644 --- a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php @@ -396,15 +396,7 @@ class PlanSceneV1Controller extends BaseController $posterWeChatMiniProgram = new PosterWeChatMiniProgram(); $result = $posterWeChatMiniProgram->generateMiniProgramCodeWithScene($taskId); - - return $result; - return ResponseHelper::success($result, '获取小程序码成功'); - - - - - } } \ No newline at end of file From bd5e06182dc8e1e7ae9f4cbc59630105c48473b3 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 11:09:48 +0800 Subject: [PATCH 10/24] =?UTF-8?q?=E6=9C=8B=E5=8F=8B=E5=9C=88=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E5=BA=93=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/WorkbenchController.php | 17 ++++++++-- .../application/job/WorkbenchMomentsJob.php | 31 ++++++++++--------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Server/application/cunkebao/controller/WorkbenchController.php b/Server/application/cunkebao/controller/WorkbenchController.php index 67eb0b9b..5bf682a6 100644 --- a/Server/application/cunkebao/controller/WorkbenchController.php +++ b/Server/application/cunkebao/controller/WorkbenchController.php @@ -244,9 +244,10 @@ class WorkbenchController extends Controller $lastTime = Db::name('workbench_moments_sync_item')->where(['workbenchId' => $item->id])->order('id DESC')->value('createTime'); $item->lastSyncTime = !empty($lastTime) ? date('Y-m-d H:i',$lastTime) : '--'; + // 获取内容库名称 if (!empty($item->config->contentLibraries)) { - $libraryNames = ContentLibrary::where('id', 'in', $item->config->contentLibraries) + $libraryNames = ContentLibrary::whereIn('id', $item->config->contentLibraries) ->column('name'); $item->config->contentLibraryNames = $libraryNames; } else { @@ -678,6 +679,18 @@ class WorkbenchController extends Controller case self::TYPE_MOMENTS_SYNC: $config = WorkbenchMomentsSync::where('workbenchId', $param['id'])->find(); if ($config) { + if (!empty($param['contentLibraries'])){ + foreach ($param['contentLibraries'] as $library){ + if(isset($library['id']) && !empty($library['id'])){ + $contentLibraries[] = $library['id']; + }else{ + $contentLibraries[] = $library; + } + } + }else{ + $contentLibraries = []; + } + $config->syncInterval = $param['syncInterval']; $config->syncCount = $param['syncCount']; $config->syncType = $param['syncType']; @@ -685,7 +698,7 @@ class WorkbenchController extends Controller $config->endTime = $param['endTime']; $config->accountType = $param['accountType']; $config->devices = json_encode($param['devices']); - $config->contentLibraries = json_encode($param['contentLibraries'] ?? []); + $config->contentLibraries = json_encode($contentLibraries); $config->updateTime = time(); $config->save(); } diff --git a/Server/application/job/WorkbenchMomentsJob.php b/Server/application/job/WorkbenchMomentsJob.php index a24baf8a..a62ca783 100644 --- a/Server/application/job/WorkbenchMomentsJob.php +++ b/Server/application/job/WorkbenchMomentsJob.php @@ -85,6 +85,7 @@ class WorkbenchMomentsJob // 获取设备 $devices = $this->getDevice($workbench, $config); + if (empty($devices)) { continue; } @@ -94,7 +95,6 @@ class WorkbenchMomentsJob if (empty($contentLibrary)) { continue; } - // 处理内容发送 $this->handleContentSend($workbench, $config, $devices, $contentLibrary); } @@ -234,27 +234,30 @@ class WorkbenchMomentsJob $newList = []; foreach ($list as $val) { - // 检查今日发送次数 + // 检查发送间隔(新逻辑:根据startTime、endTime、syncCount动态计算) + $today = date('Y-m-d'); + $startTimestamp = strtotime($today . ' ' . $config['startTime'] . ':00'); + $endTimestamp = strtotime($today . ' ' . $config['endTime'] . ':00'); + $totalSeconds = $endTimestamp - $startTimestamp; + if ($totalSeconds <= 0 || empty($config['syncCount'])) { + continue; + } + $interval = floor($totalSeconds / $config['syncCount']); + + // 查询今日已同步次数 $count = Db::name('workbench_moments_sync_item') ->where('workbenchId', $workbench->id) ->where('deviceId', $val['deviceId']) - ->whereTime('createTime', 'between', [ - strtotime(date('Y-m-d') . '00:00:00'), - strtotime(date('Y-m-d') . '23:59:59') - ])->count(); + ->whereTime('createTime', 'between', [$startTimestamp, $endTimestamp]) + ->count(); if ($count >= $config['syncCount']) { continue; } - // 检查发送间隔 - $prevSend = Db::name('workbench_moments_sync_item') - ->where('workbenchId', $workbench->id) - ->where('deviceId', $val['deviceId']) - ->order('createTime DESC') - ->find(); - - if (!empty($prevSend) && ($prevSend['createTime'] + $config['syncInterval'] * 60) > time()) { + // 计算本次同步的最早允许时间 + $nextSyncTime = $startTimestamp + $count * $interval; + if (time() < $nextSyncTime) { continue; } From ea1de883d835f5fe115abe016d1ba5524276d91e Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 16:15:45 +0800 Subject: [PATCH 11/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ContentLibraryController.php | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index ee45f729..0b648a9c 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -4,6 +4,7 @@ namespace app\cunkebao\controller; use app\cunkebao\model\ContentLibrary; use app\cunkebao\model\ContentItem; +use library\s2\titleFavicon; use think\Controller; use think\Db; use app\api\controller\WebSocketController; @@ -330,7 +331,7 @@ class ContentLibraryController extends Controller $library->timeEnd = isset($param['endTime']) ? strtotime($param['endTime']) : 0; $library->status = isset($param['status']) ? $param['status'] : 0; $library->updateTime = time(); - + $library->save(); @@ -752,7 +753,26 @@ class ContentLibraryController extends Controller /************************************ * 数据采集相关功能 ************************************/ - + + function getExternalPageDetails($url) + { + $html = file_get_contents($url); + $dom = new \DOMDocument(); + @$dom->loadHTML($html); + $xpath = new \DOMXPath($dom); + + // 获取标题 + $titleNode = $xpath->query('//title'); + $title = $titleNode->length > 0 ? $titleNode->item(0)->nodeValue : ''; + + // 获取图标链接 + $iconNode = $xpath->query('//link[@rel="shortcut icon"]/@href'); + $icon = $iconNode->length > 0 ? $iconNode->item(0)->nodeValue : ''; + + return ['title' => $title, 'icon' => $icon]; + } + + /** * 执行朋友圈采集任务 * @return \think\response\Json @@ -1414,22 +1434,33 @@ class ContentLibraryController extends Controller $urls = []; $url = is_string($moment['urls']) ? json_decode($moment['urls'], true) : $moment['urls'] ?? []; $url = $url[0]; - if(strpos($url, 'feishu.cn') !== false){ + + // 检查是否是飞书链接 + if (strpos($url, 'feishu.cn') !== false) { + // 飞书文档需要登录,无法直接获取内容,返回默认信息 $urls[] = [ 'url' => $url, 'image' => 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/3db2a5d7fe49011ab68175a42a5094ce.jpeg', - 'desc' => '点击查看详情' + 'desc' => '飞书文档' ]; }else{ - $urls[] = [ - 'url' => $url, - 'image' => 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/ec039d96fad6eab1d960f207d3d9ca9f.jpeg', - 'desc' => '点击查看详情' - ]; + $getUrlDetails = $this->getExternalPageDetails($url); + $icon = 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/ec039d96fad6eab1d960f207d3d9ca9f.jpeg'; + if (!empty($getUrlDetails['title'])) { + $urls[] = [ + 'url' => $url, + 'image' => $icon, + 'desc' => '点击查看详情' + ]; + }else{ + $urls[] = [ + 'url' => $url, + 'image' => !empty($getUrlDetails['icon']) ? $getUrlDetails['icon'] : $icon, + 'desc' => $getUrlDetails['title'] + ]; + } } $moment['urls'] = $urls; - - }elseif ($moment['type'] == 15){ //视频 $contentType = 3; From 894efc20ff3cdcee75036c27aad382fcc9f1e0c0 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 16:16:10 +0800 Subject: [PATCH 12/24] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friend/GetFriendListV1Controller.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php b/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php index a6d12d6e..89abde8c 100644 --- a/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php +++ b/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php @@ -38,23 +38,21 @@ class GetFriendListV1Controller extends BaseController $where[] = ['isDeleted','=',0]; } - if(!empty($keyword)){ $where[] = ['nickname|alias|wechatId','like','%'.$keyword.'%']; } + $wechatIds = Db::name('device')->alias('d') + ->join('device_wechat_login dwl','dwl.deviceId=d.id AND dwl.companyId='.$this->getUserInfo('companyId')) + ->where(['d.companyId' => $this->getUserInfo('companyId'),'d.deleteTime' => 0]); - $devices = Db::name('device_wechat_login') - ->where(['companyId' => $this->getUserInfo('companyId'),'alive' => 1]) - ->order('id desc') - ->group('wechatId'); - - if(!empty($deviceIds) && is_array($deviceIds)){ - $devices = $devices->whereIn('deviceId',$deviceIds); + if (!empty($deviceIds)){ + $wechatIds = $wechatIds->where('d.deviceId','in',$deviceIds); } - $devices = $devices->column('wechatId'); + $wechatIds = $wechatIds->column('dwl.wechatId'); - $where[] = ['ownerWechatId','in',$devices]; + + $where[] = ['ownerWechatId','in',$wechatIds]; $data = Db::table('s2_wechat_friend') ->field(['nickname','avatar','alias','id','wechatId','ownerNickname','ownerAlias','ownerWechatId','createTime']) From 9193004c54d7ef21248303cb49ca0980324f19dd Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 16:34:50 +0800 Subject: [PATCH 13/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/AutomaticAssign.php | 43 +++++++++- .../command/SwitchFriendsCommand.php | 79 ++++++++++++++++--- 2 files changed, 109 insertions(+), 13 deletions(-) diff --git a/Server/application/api/controller/AutomaticAssign.php b/Server/application/api/controller/AutomaticAssign.php index 66b0d3d5..5fc04565 100644 --- a/Server/application/api/controller/AutomaticAssign.php +++ b/Server/application/api/controller/AutomaticAssign.php @@ -205,7 +205,7 @@ class AutomaticAssign extends BaseController // 设置请求头 $headerData = ['client:system']; $header = setHeader($headerData, $authorization, 'json'); - + // 发送请求 $url = $this->baseUrl . 'api/WechatFriend/allot?wechatFriendId='.$wechatFriendId.'¬ifyReceiver='.$notifyReceiver.'&comment='.$comment.'&toAccountId='.$toAccountId.'&optFrom='.$optFrom; $result = requestCurl($url, [], 'PUT', $header, 'json'); @@ -231,4 +231,45 @@ class AutomaticAssign extends BaseController } } } + + + + public function multiAllotFriendToAccount($data = []){ + // 获取授权token + $authorization = $this->authorization; + if (empty($authorization)) { + return json_encode(['code'=>500,'msg'=>'缺少授权信息']); + } + + $wechatFriendIds = !empty($data['wechatFriendIds']) ? $data['wechatFriendIds'] : input('wechatFriendIds', []); + $toAccountId = !empty($data['toAccountId']) ? $data['toAccountId'] : input('toAccountId', 0); + $notifyReceiver = !empty($data['notifyReceiver']) ? $data['notifyReceiver'] : input('notifyReceiver', false); + + // 参数验证 + if (empty($wechatFriendId)) { + return errorJson('微信好友ID不能为空'); + } + + if (empty($toAccountId)) { + return errorJson('目标账号ID不能为空'); + } + + + // 设置请求头 + $headerData = ['client:system']; + $header = setHeader($headerData, $authorization, 'json'); + + // 发送请求 + $url = $this->baseUrl . 'api/WechatFriend/multiAllotFriendToAccount?wechatFriendIds='.$wechatFriendIds.'&toAccountId='.$toAccountId.'¬ifyReceiver='.$notifyReceiver; + $result = requestCurl($url, [], 'PUT', $header, 'json'); + + if (empty($result)) { + return json_encode(['code'=>200,'msg'=>'微信好友分配成功']); + } else { + return json_encode(['code'=>500,'msg'=> $result]); + } + + } + + } \ No newline at end of file diff --git a/Server/application/command/SwitchFriendsCommand.php b/Server/application/command/SwitchFriendsCommand.php index c1035cb0..ffcc2098 100644 --- a/Server/application/command/SwitchFriendsCommand.php +++ b/Server/application/command/SwitchFriendsCommand.php @@ -30,7 +30,11 @@ class SwitchFriendsCommand extends Command $maxRetry = 5; $retry = 0; $switchedIds = []; + $totalProcessed = 0; + $totalSuccess = 0; + $totalFailed = 0; + $output->writeln('开始执行好友切换任务...'); do { $friends = Cache::get($cacheKey, []); @@ -47,20 +51,66 @@ class SwitchFriendsCommand extends Command return; } + $output->writeln('找到 ' . count($toSwitch) . ' 个需要切换的好友'); + $automaticAssign = new AutomaticAssign(); + + // 根据accountId对数组进行归类 + $groupedByAccount = []; foreach ($toSwitch as $friend) { - $friendId = !empty($friend['friendId']) ? $friend['friendId'] : $friend['id']; - $res = $automaticAssign->allotWechatFriend([ - 'wechatFriendId' => $friendId, - 'toAccountId' => $friend['accountId'], - ], true); - $res = json_decode($res, true); - if ($res['code'] == 200){ - $output->writeln('切换好友:' . $friendId . ' 到账号:' . $friend['accountId']); - $switchedIds[] = $friendId; - }else{ - $output->writeln('切换好友:' . $friendId . ' 到账号:' . $friend['accountId'] .' 结果:' .$res['msg']); + $accountId = $friend['accountId']; + if (!isset($groupedByAccount[$accountId])) { + $groupedByAccount[$accountId] = []; } + $friendId = !empty($friend['friendId']) ? $friend['friendId'] : $friend['id']; + $groupedByAccount[$accountId][] = $friendId; + } + + // 对每个账号的好友进行20个为一组的分组 + foreach ($groupedByAccount as $accountId => $accountFriends) { + $chunks = array_chunk($accountFriends, 20); + $output->writeln('账号 ' . $accountId . ' 共有 ' . count($accountFriends) . ' 个好友,分为 ' . count($chunks) . ' 组'); + + $accountSuccess = 0; + $accountFailed = 0; + + foreach ($chunks as $chunkIndex => $chunk) { + $output->writeln('处理账号 ' . $accountId . ' 第 ' . ($chunkIndex + 1) . ' 组,共 ' . count($chunk) . ' 个好友'); + + try { + $friendIds = implode(',', $chunk); + $res = $automaticAssign->multiAllotFriendToAccount([ + 'wechatFriendIds' => $friendIds, + 'toAccountId' => $accountId, + ]); + + $res = json_decode($res, true); + if ($res['code'] == 200){ + $output->writeln('✓ 成功切换好友:' . $friendIds . ' 到账号:' . $accountId); + $switchedIds = array_merge($switchedIds, $chunk); + $accountSuccess += count($chunk); + $totalSuccess += count($chunk); + } else { + $output->writeln('✗ 切换失败 - 好友:' . $friendIds . ' 到账号:' . $accountId . ' 结果:' . $res['msg']); + $accountFailed += count($chunk); + $totalFailed += count($chunk); + } + } catch (\Exception $e) { + $output->writeln('✗ 切换异常 - 好友:' . implode(',', $chunk) . ' 到账号:' . $accountId . ' 错误:' . $e->getMessage()); + Log::error('切换好友异常: ' . $e->getMessage() . ' 好友IDs: ' . implode(',', $chunk) . ' 账号ID: ' . $accountId); + $accountFailed += count($chunk); + $totalFailed += count($chunk); + } + + $totalProcessed += count($chunk); + + // 每组处理完后稍作延迟,避免请求过于频繁 + if ($chunkIndex < count($chunks) - 1) { + sleep(1); + } + } + + $output->writeln('账号 ' . $accountId . ' 处理完成 - 成功:' . $accountSuccess . ',失败:' . $accountFailed); } // 过滤掉已切换的,保留未切换和新进来的 @@ -82,7 +132,12 @@ class SwitchFriendsCommand extends Command $retry++; } while (!$success && $retry < $maxRetry); - $output->writeln('切换完成,缓存已更新并排序'); + $output->writeln('=== 切换任务完成 ==='); + $output->writeln('总处理数量:' . $totalProcessed); + $output->writeln('成功切换:' . $totalSuccess); + $output->writeln('切换失败:' . $totalFailed); + $output->writeln('成功率:' . ($totalProcessed > 0 ? round(($totalSuccess / $totalProcessed) * 100, 2) : 0) . '%'); + $output->writeln('缓存已更新并排序'); } } \ No newline at end of file From 66c6455a449f64d085fcc4d42593abb05fe6785b Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 16:47:50 +0800 Subject: [PATCH 14/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ContentLibraryController.php | 17 ++++---------- Server/application/job/WechatMomentsJob.php | 14 ++++-------- .../application/job/WorkbenchAutoLikeJob.php | 22 +++++-------------- 3 files changed, 13 insertions(+), 40 deletions(-) diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 0b648a9c..3a445cfc 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -916,17 +916,14 @@ class ContentLibraryController extends Controller //执行切换好友命令 $automaticAssign = new AutomaticAssign(); $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'],'toAccountId' => $toAccountId],true); + //存入缓存 + $friendData['friendId'] = $friend['id']; + artificialAllotWechatFriend($friendData); //执行采集朋友圈命令 $webSocket = new WebSocketController(['userName' => $username,'password' => $password,'accountId' => $toAccountId]); $webSocket->getMoments(['wechatFriendId' => $friend['id'],'wechatAccountId' => $friend['wechatAccountId']]); //采集完毕切换 - $res = $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'],'toAccountId' => $friend['accountId']],true); - $res = json_decode($res, true); - if($res == '无效路径或登录状态失效'){ - $cacheFriend = $friend; - $cacheFriend['friendId'] = $friend['id']; - artificialAllotWechatFriend($friend); - } + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'],'toAccountId' => $friend['accountId']],true); } @@ -1035,12 +1032,6 @@ class ContentLibraryController extends Controller ]; } catch (\Exception $e) { - - $cacheFriend = $friendData; - $cacheFriend['friendId'] = $friend['id']; - artificialAllotWechatFriend($friend); - - return [ 'status' => 'error', 'message' => '采集过程发生错误: ' . $e->getMessage() diff --git a/Server/application/job/WechatMomentsJob.php b/Server/application/job/WechatMomentsJob.php index 88d380d2..ad9f5345 100644 --- a/Server/application/job/WechatMomentsJob.php +++ b/Server/application/job/WechatMomentsJob.php @@ -46,26 +46,20 @@ class WechatMomentsJob // 执行切换好友命令 $automaticAssign = new AutomaticAssign(); $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $toAccountId], true); + //存入缓存 + artificialAllotWechatFriend($friend); // 执行采集朋友圈命令 $webSocket = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]); $webSocket->getMoments(['wechatFriendId' => $friend['friendId'], 'wechatAccountId' => $friend['wechatAccountId']]); // 处理完毕切换回原账号 - $res = $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); - $res = json_decode($res, true); - if ($res == '无效路径或登录状态失效'){ - artificialAllotWechatFriend($friend); - } + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); } catch (\Exception $e) { // 发生异常时也要切换回原账号 - $res = $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); - $res = json_decode($res, true); - if ($res == '无效路径或登录状态失效'){ - artificialAllotWechatFriend($friend); - } + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); Log::error("采集好友 {$friend['id']} 的朋友圈失败:" . $e->getMessage()); continue; } diff --git a/Server/application/job/WorkbenchAutoLikeJob.php b/Server/application/job/WorkbenchAutoLikeJob.php index b0f489de..5f656025 100644 --- a/Server/application/job/WorkbenchAutoLikeJob.php +++ b/Server/application/job/WorkbenchAutoLikeJob.php @@ -219,7 +219,8 @@ class WorkbenchAutoLikeJob // 执行切换好友命令 $automaticAssign = new AutomaticAssign(); $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $toAccountId], true); - + //存入缓存 + artificialAllotWechatFriend($friend); // 创建WebSocket链接 $webSocket = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]); @@ -234,12 +235,7 @@ class WorkbenchAutoLikeJob if (empty($moments) || count($moments) == 0) { // 处理完毕切换回原账号 - $res = $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); - $res = json_decode($res, true); - if($res == '无效路径或登录状态失效'){ - artificialAllotWechatFriend($friend); - } - + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); Log::info("好友 {$friend['friendId']} 没有需要点赞的朋友圈"); return; } @@ -263,19 +259,11 @@ class WorkbenchAutoLikeJob } // 处理完毕切换回原账号 - $res = $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); - $res = json_decode($res, true); - if($res == '无效路径或登录状态失效'){ - artificialAllotWechatFriend($friend); - } + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); } catch (\Exception $e) { // 异常情况下也要确保切换回原账号 $automaticAssign = new AutomaticAssign(); - $res = $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); - $res = json_decode($res, true); - if($res == '无效路径或登录状态失效'){ - artificialAllotWechatFriend($friend); - } + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['friendId'], 'toAccountId' => $friend['accountId']], true); Log::error("处理好友 {$friend['friendId']} 朋友圈失败异常: " . $e->getMessage()); } } From a3a3b12e65d723530e9b6af9f8f65e5440aad2a8 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 16:56:16 +0800 Subject: [PATCH 15/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/api/controller/WechatChatroomController.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Server/application/api/controller/WechatChatroomController.php b/Server/application/api/controller/WechatChatroomController.php index 43a33654..1fb4938d 100644 --- a/Server/application/api/controller/WechatChatroomController.php +++ b/Server/application/api/controller/WechatChatroomController.php @@ -72,7 +72,11 @@ class WechatChatroomController extends BaseController return successJson($response); } } catch (\Exception $e) { - return errorJson('获取微信群聊列表失败:' . $e->getMessage()); + if($isInner){ + return json_encode(['code'=>200,'msg'=>'获取微信群聊列表失败' . $e->getMessage()]); + }else{ + return errorJson('获取微信群聊列表失败:' . $e->getMessage()); + } } } From 80b52ce8c975ed899f1193e58304f1ca20b5fcd4 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 17:01:48 +0800 Subject: [PATCH 16/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Server/application/api/controller/AutomaticAssign.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Server/application/api/controller/AutomaticAssign.php b/Server/application/api/controller/AutomaticAssign.php index 5fc04565..64be22e0 100644 --- a/Server/application/api/controller/AutomaticAssign.php +++ b/Server/application/api/controller/AutomaticAssign.php @@ -194,11 +194,12 @@ class AutomaticAssign extends BaseController // 参数验证 if (empty($wechatFriendId)) { - return errorJson('微信好友ID不能为空'); + return json_encode(['code'=>500,'msg'=>'微信好友ID不能为空']); + } if (empty($toAccountId)) { - return errorJson('目标账号ID不能为空'); + return json_encode(['code'=>500,'msg'=>'目标账号ID不能为空']); } @@ -246,12 +247,12 @@ class AutomaticAssign extends BaseController $notifyReceiver = !empty($data['notifyReceiver']) ? $data['notifyReceiver'] : input('notifyReceiver', false); // 参数验证 - if (empty($wechatFriendId)) { - return errorJson('微信好友ID不能为空'); + if (empty($wechatFriendIds)) { + return json_encode(['code'=>500,'msg'=>'微信好友ID不能为空']); } if (empty($toAccountId)) { - return errorJson('目标账号ID不能为空'); + return json_encode(['code'=>500,'msg'=>'目标账号ID不能为空']); } From ce4beab2011c965c10434d0c8d0c9d7968bd0835 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 17:38:44 +0800 Subject: [PATCH 17/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/AutomaticAssign.php | 15 ++++++--------- .../application/command/SwitchFriendsCommand.php | 16 ++++++++++------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Server/application/api/controller/AutomaticAssign.php b/Server/application/api/controller/AutomaticAssign.php index 64be22e0..6ea68560 100644 --- a/Server/application/api/controller/AutomaticAssign.php +++ b/Server/application/api/controller/AutomaticAssign.php @@ -189,7 +189,7 @@ class AutomaticAssign extends BaseController $wechatFriendId = !empty($data['wechatFriendId']) ? $data['wechatFriendId'] : input('wechatFriendId', 0); $toAccountId = !empty($data['toAccountId']) ? $data['toAccountId'] : input('toAccountId', 0); $comment = !empty($data['comment']) ? $data['comment'] : input('comment', ''); - $notifyReceiver = !empty($data['notifyReceiver']) ? $data['notifyReceiver'] : input('notifyReceiver', false); + $notifyReceiver = !empty($data['notifyReceiver']) ? $data['notifyReceiver'] : input('notifyReceiver', 'false'); $optFrom = !empty($data['optFrom']) ? $data['optFrom'] : input('optFrom', 4); // 默认操作来源为4 // 参数验证 @@ -234,7 +234,6 @@ class AutomaticAssign extends BaseController } - public function multiAllotFriendToAccount($data = []){ // 获取授权token $authorization = $this->authorization; @@ -244,16 +243,15 @@ class AutomaticAssign extends BaseController $wechatFriendIds = !empty($data['wechatFriendIds']) ? $data['wechatFriendIds'] : input('wechatFriendIds', []); $toAccountId = !empty($data['toAccountId']) ? $data['toAccountId'] : input('toAccountId', 0); - $notifyReceiver = !empty($data['notifyReceiver']) ? $data['notifyReceiver'] : input('notifyReceiver', false); - + $notifyReceiver = !empty($data['notifyReceiver']) ? $data['notifyReceiver'] : input('notifyReceiver', 'false'); // 参数验证 if (empty($wechatFriendIds)) { return json_encode(['code'=>500,'msg'=>'微信好友ID不能为空']); - } + } - if (empty($toAccountId)) { - return json_encode(['code'=>500,'msg'=>'目标账号ID不能为空']); - } + if (empty($toAccountId)) { + return json_encode(['code'=>500,'msg'=>'目标账号ID不能为空']); + } // 设置请求头 @@ -263,7 +261,6 @@ class AutomaticAssign extends BaseController // 发送请求 $url = $this->baseUrl . 'api/WechatFriend/multiAllotFriendToAccount?wechatFriendIds='.$wechatFriendIds.'&toAccountId='.$toAccountId.'¬ifyReceiver='.$notifyReceiver; $result = requestCurl($url, [], 'PUT', $header, 'json'); - if (empty($result)) { return json_encode(['code'=>200,'msg'=>'微信好友分配成功']); } else { diff --git a/Server/application/command/SwitchFriendsCommand.php b/Server/application/command/SwitchFriendsCommand.php index ffcc2098..488e39a2 100644 --- a/Server/application/command/SwitchFriendsCommand.php +++ b/Server/application/command/SwitchFriendsCommand.php @@ -37,7 +37,13 @@ class SwitchFriendsCommand extends Command $output->writeln('开始执行好友切换任务...'); do { - $friends = Cache::get($cacheKey, []); + //$friends = Cache::get($cacheKey, []); + + $friends = [ + ['time' => 1111,'accountId' => 6222,'friendId' => 21075650], + ['time' => 1111,'accountId' => 6222,'friendId' => 20112769], + ]; + $toSwitch = []; foreach ($friends as $friend) { @@ -65,25 +71,23 @@ class SwitchFriendsCommand extends Command $friendId = !empty($friend['friendId']) ? $friend['friendId'] : $friend['id']; $groupedByAccount[$accountId][] = $friendId; } - + + // 对每个账号的好友进行20个为一组的分组 foreach ($groupedByAccount as $accountId => $accountFriends) { $chunks = array_chunk($accountFriends, 20); $output->writeln('账号 ' . $accountId . ' 共有 ' . count($accountFriends) . ' 个好友,分为 ' . count($chunks) . ' 组'); - $accountSuccess = 0; $accountFailed = 0; - + foreach ($chunks as $chunkIndex => $chunk) { $output->writeln('处理账号 ' . $accountId . ' 第 ' . ($chunkIndex + 1) . ' 组,共 ' . count($chunk) . ' 个好友'); - try { $friendIds = implode(',', $chunk); $res = $automaticAssign->multiAllotFriendToAccount([ 'wechatFriendIds' => $friendIds, 'toAccountId' => $accountId, ]); - $res = json_decode($res, true); if ($res['code'] == 200){ $output->writeln('✓ 成功切换好友:' . $friendIds . ' 到账号:' . $accountId); From 3c39b1e2bdc316561d30eda2f94bbd89faa0d216 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Fri, 11 Jul 2025 17:45:49 +0800 Subject: [PATCH 18/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Server/application/command/SwitchFriendsCommand.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Server/application/command/SwitchFriendsCommand.php b/Server/application/command/SwitchFriendsCommand.php index 488e39a2..d7bf89ce 100644 --- a/Server/application/command/SwitchFriendsCommand.php +++ b/Server/application/command/SwitchFriendsCommand.php @@ -37,14 +37,7 @@ class SwitchFriendsCommand extends Command $output->writeln('开始执行好友切换任务...'); do { - //$friends = Cache::get($cacheKey, []); - - $friends = [ - ['time' => 1111,'accountId' => 6222,'friendId' => 21075650], - ['time' => 1111,'accountId' => 6222,'friendId' => 20112769], - ]; - - + $friends = Cache::get($cacheKey, []); $toSwitch = []; foreach ($friends as $friend) { if (isset($friend['time']) && $friend['time'] < $now) { From acdaa7825829a61920a369b600a7cf0285d55b63 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Mon, 14 Jul 2025 09:31:23 +0800 Subject: [PATCH 19/24] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cunkebao/controller/ContentLibraryController.php | 4 ++-- .../cunkebao/controller/friend/GetFriendListV1Controller.php | 2 +- Server/application/job/WechatMomentsJob.php | 4 ++-- Server/application/job/WorkbenchAutoLikeJob.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 3a445cfc..6c522a6d 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -886,8 +886,8 @@ class ContentLibraryController extends Controller $friendData = []; try { $toAccountId = ''; - $username = Env::get('api.username', ''); - $password = Env::get('api.password', ''); + $username = Env::get('api.username2', ''); + $password = Env::get('api.password2', ''); if (!empty($username) || !empty($password)) { $toAccountId = Db::name('users')->where('account',$username)->value('s2_accountId'); } diff --git a/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php b/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php index 89abde8c..86965d79 100644 --- a/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php +++ b/Server/application/cunkebao/controller/friend/GetFriendListV1Controller.php @@ -47,7 +47,7 @@ class GetFriendListV1Controller extends BaseController ->where(['d.companyId' => $this->getUserInfo('companyId'),'d.deleteTime' => 0]); if (!empty($deviceIds)){ - $wechatIds = $wechatIds->where('d.deviceId','in',$deviceIds); + $wechatIds = $wechatIds->where('d.id','in',$deviceIds); } $wechatIds = $wechatIds->column('dwl.wechatId'); diff --git a/Server/application/job/WechatMomentsJob.php b/Server/application/job/WechatMomentsJob.php index ad9f5345..2aabff4f 100644 --- a/Server/application/job/WechatMomentsJob.php +++ b/Server/application/job/WechatMomentsJob.php @@ -18,8 +18,8 @@ class WechatMomentsJob public function fire(Job $job, $data) { $toAccountId = ''; - $username = Env::get('api.username', ''); - $password = Env::get('api.password', ''); + $username = Env::get('api.username2', ''); + $password = Env::get('api.password2', ''); if (!empty($username) || !empty($password)) { $toAccountId = Db::name('users')->where('account',$username)->value('s2_accountId'); }else{ diff --git a/Server/application/job/WorkbenchAutoLikeJob.php b/Server/application/job/WorkbenchAutoLikeJob.php index 5f656025..11c8d84c 100644 --- a/Server/application/job/WorkbenchAutoLikeJob.php +++ b/Server/application/job/WorkbenchAutoLikeJob.php @@ -209,8 +209,8 @@ class WorkbenchAutoLikeJob protected function processFriendMoments($workbench, $config, $friend) { $toAccountId = ''; - $username = Env::get('api.username', ''); - $password = Env::get('api.password', ''); + $username = Env::get('api.username2', ''); + $password = Env::get('api.password2', ''); if (!empty($username) || !empty($password)) { $toAccountId = Db::name('users')->where('account',$username)->value('s2_accountId'); } From d21db1c6a6ffb2d2567348ce252d498f62b9b116 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Mon, 14 Jul 2025 11:59:32 +0800 Subject: [PATCH 20/24] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A5=BD=E5=8F=8B?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php b/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php index cd164828..495b7ae7 100644 --- a/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php +++ b/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php @@ -153,9 +153,10 @@ class Adapter implements WeChatServiceInterface public function handleCustomerTaskWithStatusIsNew(int $current_worker_id, int $process_count_for_status_0) { - $task = Db::name('customer_acquisition_task') ->where(['status' => 1,'deleteTime' => 0]) + ->whereRaw("id % $process_count_for_status_0 = {$current_worker_id}") + ->order('id desc') ->select(); if (empty($task)) { @@ -164,11 +165,16 @@ class Adapter implements WeChatServiceInterface $taskData = []; foreach ($task as $item) { + $reqConf = json_decode($item['reqConf'], true); + $device = $reqConf['device'] ?? []; + $deviceCount = count($device); + if ($deviceCount <= 0){ + continue; + } $tasks = Db::name('task_customer') ->where(['status'=> 0,'task_id'=>$item['id']]) - ->whereRaw("id % $process_count_for_status_0 = {$current_worker_id}") ->order('id DESC') - ->limit(5) + ->limit($deviceCount) ->select(); $taskData = array_merge($taskData, $tasks); } From e0583db19a65a9a94c37bbde9a48f5d1b948f743 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Mon, 14 Jul 2025 14:26:20 +0800 Subject: [PATCH 21/24] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E5=A5=BD=E5=8F=8B=E6=97=A0=E6=B3=95=E5=88=87=E6=8D=A2=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/AutomaticAssign.php | 17 +++++++++++++++-- .../api/controller/WebSocketController.php | 6 +++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Server/application/api/controller/AutomaticAssign.php b/Server/application/api/controller/AutomaticAssign.php index 6ea68560..3fad358f 100644 --- a/Server/application/api/controller/AutomaticAssign.php +++ b/Server/application/api/controller/AutomaticAssign.php @@ -172,7 +172,7 @@ class AutomaticAssign extends BaseController * @param int $optFrom 操作来源 * @return \think\response\Json */ - public function allotWechatFriend($data = [],$isInner = false) + public function allotWechatFriend($data = [],$isInner = false,$errorNum = 0) { // 获取授权token $authorization = $this->authorization; @@ -228,13 +228,20 @@ class AutomaticAssign extends BaseController if($isInner){ return json_encode(['code'=>500,'msg'=>'微信好友分配失败:' . $e->getMessage()]); }else{ + Cache::rm('system_authorization_token'); + Cache::rm('system_refresh_token'); + $errorNum ++; + if ($errorNum <= 3) { + $this->allotWechatFriend($data,$isInner,$errorNum); + } + return json_encode(['code'=>500,'msg'=> $result]); return errorJson('微信好友分配失败:' . $e->getMessage()); } } } - public function multiAllotFriendToAccount($data = []){ + public function multiAllotFriendToAccount($data = [],$errorNum = 0){ // 获取授权token $authorization = $this->authorization; if (empty($authorization)) { @@ -264,6 +271,12 @@ class AutomaticAssign extends BaseController if (empty($result)) { return json_encode(['code'=>200,'msg'=>'微信好友分配成功']); } else { + Cache::rm('system_authorization_token'); + Cache::rm('system_refresh_token'); + $errorNum ++; + if ($errorNum <= 3) { + $this->multiAllotFriendToAccount($data,$errorNum); + } return json_encode(['code'=>500,'msg'=> $result]); } diff --git a/Server/application/api/controller/WebSocketController.php b/Server/application/api/controller/WebSocketController.php index 15f5fdfa..8400183d 100644 --- a/Server/application/api/controller/WebSocketController.php +++ b/Server/application/api/controller/WebSocketController.php @@ -62,11 +62,11 @@ class WebSocketController extends BaseController 'username' => $userData['userName'], 'password' => $userData['password'] ]; - + // 调用登录接口获取token - $headerData = ['client:kefu-client']; + $headerData = ['client:kefu-client']; $header = setHeader($headerData, '', 'plain'); - $result = requestCurl('https://kf.quwanzhi.com:9991/token', $params, 'POST', $header); + $result = requestCurl('https://kf.quwanzhi.com:9991/token', $params, 'POST', $header); $result_array = handleApiResponse($result); if (isset($result_array['access_token']) && !empty($result_array['access_token'])) { From 9736416fffc6ba4f9fc1679061ce7a452f71fe74 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Mon, 14 Jul 2025 18:16:36 +0800 Subject: [PATCH 22/24] =?UTF-8?q?=E6=B5=81=E9=87=8F=E5=88=86=E5=8F=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/AccountController.php | 18 ++-- .../api/controller/MessageController.php | 46 ++++++++++ .../command/SwitchFriendsCommand.php | 85 +++++++++++++++++++ Server/application/job/AccountListJob.php | 2 +- .../job/WorkbenchTrafficDistributeJob.php | 6 +- 5 files changed, 149 insertions(+), 8 deletions(-) diff --git a/Server/application/api/controller/AccountController.php b/Server/application/api/controller/AccountController.php index aeadb752..30345292 100644 --- a/Server/application/api/controller/AccountController.php +++ b/Server/application/api/controller/AccountController.php @@ -23,9 +23,15 @@ class AccountController extends BaseController * @param bool $isInner 是否为定时任务调用 * @return \think\response\Json */ - public function getlist($pageIndex = '', $pageSize = '', $isInner = false) + public function getlist($data = [], $isInner = false) { + $pageIndex = !empty($data['pageIndex']) ? $data['pageIndex'] : 0; + $pageSize = !empty($data['pageSize']) ? $data['pageSize'] : 20; + $showNormalAccount = !empty($data['showNormalAccount']) ? $data['showNormalAccount'] : ''; + $keyword = !empty($data['keyword']) ? $data['keyword'] : ''; + $departmentId = !empty($data['departmentId']) ? $data['departmentId'] : ''; + // 获取授权token $authorization = trim($this->request->header('authorization', $this->authorization)); if (empty($authorization)) { @@ -39,11 +45,11 @@ class AccountController extends BaseController try { // 构建请求参数 $params = [ - 'showNormalAccount' => $this->request->param('showNormalAccount', ''), - 'keyword' => $this->request->param('keyword', ''), - 'departmentId' => $this->request->param('departmentId', ''), - 'pageIndex' => !empty($pageIndex) ? $pageIndex : $this->request->param('pageIndex', 0), - 'pageSize' => !empty($pageSize) ? $pageSize : $this->request->param('pageSize', 20) + 'showNormalAccount' => $showNormalAccount, + 'keyword' => $keyword, + 'departmentId' => $departmentId, + 'pageIndex' => $pageIndex, + 'pageSize' => $pageSize ]; // 设置请求头 diff --git a/Server/application/api/controller/MessageController.php b/Server/application/api/controller/MessageController.php index 2cb39682..da033741 100644 --- a/Server/application/api/controller/MessageController.php +++ b/Server/application/api/controller/MessageController.php @@ -3,6 +3,7 @@ namespace app\api\controller; use app\api\model\WechatMessageModel; +use think\Db; use think\facade\Request; class MessageController extends BaseController @@ -386,6 +387,51 @@ class MessageController extends BaseController 'wechatTime' => $wechatTime ]; + //已被删除 + if ($item['msgType'] == 10000 && strpos($item['content'],'开启了朋友验证') !== false) { + Db::table('s2_wechat_friend')->where('id',$item['wechatFriendId'])->update(['isDeleted'=> 1,'deleteTime' => $wechatTime]); + }else{ + //优先分配在线客服 + $friend = Db::table('s2_wechat_friend')->where('id',$item['wechatFriendId'])->find(); + if (!empty($friend)){ + $accountId = $item['accountId']; + $accountData = Db::table('s2_company_account')->where('id',$accountId)->find(); + if (!empty($accountData)){ + $account = new AccountController(); + $account->getlist(['pageIndex' => 0,'pageSize' => 100,'departmentId' => $accountData['departmentId']]); + $accountIds = Db::table('s2_company_account')->where(['id' => $accountId,'alive' => 1])->column('id'); + if (!empty($accountIds)){ + if (!in_array($friend['accountId'],$accountData)){ + // 执行切换好友命令 + $randomKey = array_rand($accountIds, 1); + $toAccountId = $accountIds[$randomKey]; + $toAccountData = Db::table('s2_company_account')->where('id',$toAccountId)->find(); + $automaticAssign = new AutomaticAssign(); + $automaticAssign->allotWechatFriend([ + 'wechatFriendId' => $friend['id'], + 'toAccountId' => $toAccountId + ], true); + Db::table('s2_wechat_friend') + ->where('id',$friend['id']) + ->update([ + 'accountId' => $toAccountId, + 'accountUserName' => $toAccountData['userName'], + 'accountRealName' => $toAccountData['realName'], + 'accountNickname' => $toAccountData['nickname'], + ]); + } + } + + } + } + } + + + + + + + // 创建新记录 WechatMessageModel::create($data); } diff --git a/Server/application/command/SwitchFriendsCommand.php b/Server/application/command/SwitchFriendsCommand.php index d7bf89ce..d153f372 100644 --- a/Server/application/command/SwitchFriendsCommand.php +++ b/Server/application/command/SwitchFriendsCommand.php @@ -7,6 +7,7 @@ use think\console\Command; use think\console\Input; use think\console\input\Option; use think\console\Output; +use think\Db; use think\facade\Cache; use think\facade\Log; use think\Queue; @@ -25,6 +26,90 @@ class SwitchFriendsCommand extends Command protected function execute(Input $input, Output $output) { + //处理流量分过期数据 + $expUserData = Db::name('workbench_traffic_config_item') + ->where('expTime','<=',time()) + ->where('isRecycle',0) + ->select(); + + // 根据accountId对数组进行归类 + $groupedByAccount = []; + foreach ($expUserData as $friend) { + $accountId = $friend['wechatAccountId']; + if (!isset($groupedByAccount[$accountId])) { + $groupedByAccount[$accountId] = []; + } + $friendId = $friend['wechatFriendId']; + $groupedByAccount[$accountId][] = $friendId; + } + + // 对每个账号的好友进行20个为一组的分组 + foreach ($groupedByAccount as $accountId => $accountFriends) { + //检索主账号 + $account = Db::name('users')->where('s2_accountId',$accountId)->find(); + if (empty($account)) { + continue; + } + $account2 = Db::name('users') + ->where('s2_accountId','>',0) + ->where('companyId',$account['companyId']) + ->order('s2_accountId ASC') + ->find(); + if (empty($account2)) { + continue; + } + $newaAccountId = $account2['s2_accountId']; + + $chunks = array_chunk($accountFriends, 20); + $output->writeln('账号 ' . $newaAccountId . ' 共有 ' . count($accountFriends) . ' 个好友,分为 ' . count($chunks) . ' 组'); + + $automaticAssign = new AutomaticAssign(); + foreach ($chunks as $chunkIndex => $chunk) { + $output->writeln('处理账号 ' . $newaAccountId . ' 第 ' . ($chunkIndex + 1) . ' 组,共 ' . count($chunk) . ' 个好友'); + try { + $friendIds = implode(',', $chunk); + $res = $automaticAssign->multiAllotFriendToAccount([ + 'wechatFriendIds' => $friendIds, + 'toAccountId' => $newaAccountId, + ]); + $res = json_decode($res, true); + if ($res['code'] == 200){ + //修改数据库 + Db::table('s2_wechat_friend') + ->where('id',$friendIds) + ->update([ + 'accountId' => $account2['s2_accountId'], + 'accountUserName' => $account2['account'], + 'accountRealName' => $account2['username'], + 'accountNickname' => $account2['username'], + ]); + + Db::name('workbench_traffic_config_item') + ->whereIn('wechatFriendId',$friendIds) + ->where('wechatAccountId',$accountId) + ->update([ + 'isRecycle' => 1, + 'recycleTime' => time(), + ]); + $output->writeln('✓ 成功切换好友:' . $friendIds . ' 到账号:' . $newaAccountId); + } else { + $output->writeln('✗ 切换失败 - 好友:' . $friendIds . ' 到账号:' . $newaAccountId . ' 结果:' . $res['msg']); + } + } catch (\Exception $e) { + $output->writeln('✗ 切换异常 - 好友:' . implode(',', $chunk) . ' 到账号:' . $newaAccountId . ' 错误:' . $e->getMessage()); + } + + // 每组处理完后稍作延迟,避免请求过于频繁 + if ($chunkIndex < count($chunks) - 1) { + sleep(1); + } + } + } + + + + + $cacheKey = 'allotWechatFriend'; $now = time(); $maxRetry = 5; diff --git a/Server/application/job/AccountListJob.php b/Server/application/job/AccountListJob.php index 08f23142..6d76ab3d 100644 --- a/Server/application/job/AccountListJob.php +++ b/Server/application/job/AccountListJob.php @@ -73,7 +73,7 @@ class AccountListJob $request->withGet($params); // 调用公司账号列表获取方法 - $result = $accountController->getlist($pageIndex,$pageSize,true); + $result = $accountController->getlist(['pageIndex' => $pageIndex,'pageSize' => $pageSize],true); $response = json_decode($result,true); diff --git a/Server/application/job/WorkbenchTrafficDistributeJob.php b/Server/application/job/WorkbenchTrafficDistributeJob.php index 674a54a0..de457812 100644 --- a/Server/application/job/WorkbenchTrafficDistributeJob.php +++ b/Server/application/job/WorkbenchTrafficDistributeJob.php @@ -152,7 +152,9 @@ class WorkbenchTrafficDistributeJob 'deviceId' => $friend['deviceId'], 'wechatFriendId' => $friend['id'], 'wechatAccountId' => $account['id'], - 'createTime' => time() + 'createTime' => time(), + 'exp' => $config['exp'], + 'expTime' => time() + 86400 * $config['exp'], ]); Log::info("流量分发工作台 {$workbench->id} 好友[{$friend['id']}]分配给客服[{$account['id']}] 成功"); $i++; @@ -206,9 +208,11 @@ class WorkbenchTrafficDistributeJob ->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left') ->join('workbench_traffic_config_item wtci', 'wtci.wechatFriendId = wf.id AND wtci.workbenchId = ' . $config['workbenchId'], 'left') ->where([ + ['wf.isDeleted', '=', 0], ['wf.isDeleted', '=', 0], ['wf.isPassed', '=', 1], //['sa.departmentId', '=', $workbench->companyId], + ['wtci.expTime', '>', time()], ['wtci.id', 'null', null] ]) ->whereIn('wa.currentDeviceId', $devices) From c08b9b0b26c842968f7af9adcae31e0cdfa8f6cb Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Tue, 15 Jul 2025 11:06:52 +0800 Subject: [PATCH 23/24] =?UTF-8?q?=E6=B5=81=E9=87=8F=E5=88=86=E5=8F=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../job/WorkbenchTrafficDistributeJob.php | 56 +++++++++---------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/Server/application/job/WorkbenchTrafficDistributeJob.php b/Server/application/job/WorkbenchTrafficDistributeJob.php index de457812..53e26d54 100644 --- a/Server/application/job/WorkbenchTrafficDistributeJob.php +++ b/Server/application/job/WorkbenchTrafficDistributeJob.php @@ -58,7 +58,7 @@ class WorkbenchTrafficDistributeJob protected function processSingleWorkbench($workbench) { $page = 1; - $pageSize = 100; + $pageSize = 20; $config = WorkbenchTrafficConfig::where('workbenchId', $workbench->id)->find(); if (!$config) { @@ -89,8 +89,6 @@ class WorkbenchTrafficDistributeJob ->group('a.id') ->having('todayCount <= ' . $config['maxPerDay']) ->select(); - - $accountNum = count($accounts); if ($accountNum < 1) { Log::info("流量分发工作台 {$workbench->id} 可分配账号少于1个"); @@ -134,29 +132,33 @@ class WorkbenchTrafficDistributeJob } // 执行切换好友命令 - $automaticAssign->allotWechatFriend([ + $res = $automaticAssign->allotWechatFriend([ 'wechatFriendId' => $friend['id'], 'toAccountId' => $account['id'] ], true); - Db::table('s2_wechat_friend') - ->where('id',$friend['id']) - ->update([ - 'accountId' => $account['id'], - 'accountUserName' => $account['userName'], - 'accountRealName' => $account['realName'], - 'accountNickname' => $account['nickname'], + + $res = json_decode($res,true); + if ($res['code'] == 200){ + Db::table('s2_wechat_friend') + ->where('id',$friend['id']) + ->update([ + 'accountId' => $account['id'], + 'accountUserName' => $account['userName'], + 'accountRealName' => $account['realName'], + 'accountNickname' => $account['nickname'], ]); - // 写入分配记录表 - Db::name('workbench_traffic_config_item')->insert([ - 'workbenchId' => $workbench->id, - 'deviceId' => $friend['deviceId'], - 'wechatFriendId' => $friend['id'], - 'wechatAccountId' => $account['id'], - 'createTime' => time(), - 'exp' => $config['exp'], - 'expTime' => time() + 86400 * $config['exp'], - ]); - Log::info("流量分发工作台 {$workbench->id} 好友[{$friend['id']}]分配给客服[{$account['id']}] 成功"); + // 写入分配记录表 + Db::name('workbench_traffic_config_item')->insert([ + 'workbenchId' => $workbench->id, + 'deviceId' => $friend['deviceId'], + 'wechatFriendId' => $friend['id'], + 'wechatAccountId' => $account['id'], + 'createTime' => time(), + 'exp' => $config['exp'], + 'expTime' => time() + 86400 * $config['exp'], + ]); + Log::info("流量分发工作台 {$workbench->id} 好友[{$friend['id']}]分配给客服[{$account['id']}] 成功"); + } $i++; } break; @@ -206,24 +208,16 @@ class WorkbenchTrafficDistributeJob $query = Db::table('s2_wechat_friend')->alias('wf') ->join(['s2_company_account' => 'sa'], 'sa.id = wf.accountId', 'left') ->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left') - ->join('workbench_traffic_config_item wtci', 'wtci.wechatFriendId = wf.id AND wtci.workbenchId = ' . $config['workbenchId'], 'left') + ->join('workbench_traffic_config_item wtci', 'wtci.isRecycle = 0 and wtci.wechatFriendId = wf.id AND wtci.workbenchId = ' . $config['workbenchId'], 'left') ->where([ - ['wf.isDeleted', '=', 0], ['wf.isDeleted', '=', 0], ['wf.isPassed', '=', 1], //['sa.departmentId', '=', $workbench->companyId], - ['wtci.expTime', '>', time()], ['wtci.id', 'null', null] ]) ->whereIn('wa.currentDeviceId', $devices) ->field('wf.id,wf.wechatAccountId,wf.wechatId,wf.labels,sa.userName,wa.currentDeviceId as deviceId'); - //lllll - if($workbench->id == 65){ - $query->where('wf.accountId',1602); - } - - if(!empty($labels)){ $query->where(function ($q) use ($labels) { From b8b86598d8f38731cbd633f442e7ee365856832d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AC=94=E8=AE=B0=E6=9C=AC=E9=87=8C=E7=9A=84=E6=B0=B8?= =?UTF-8?q?=E5=B9=B3?= Date: Wed, 16 Jul 2025 11:06:09 +0800 Subject: [PATCH 24/24] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nkebao/src/api/utils.ts | 33 +++- .../scenarios/new/steps/BasicSettings.tsx | 148 +++++++++--------- 2 files changed, 110 insertions(+), 71 deletions(-) diff --git a/nkebao/src/api/utils.ts b/nkebao/src/api/utils.ts index 585d6395..c678120c 100644 --- a/nkebao/src/api/utils.ts +++ b/nkebao/src/api/utils.ts @@ -161,4 +161,35 @@ class RequestCancelManager { // 导出单例实例 export const requestDeduplicator = new RequestDeduplicator(); -export const requestCancelManager = new RequestCancelManager(); \ No newline at end of file +export const requestCancelManager = new RequestCancelManager(); + +/** + * 通用文件上传方法(支持图片、文件) + * @param {File} file - 要上传的文件对象 + * @param {string} [uploadUrl='/v1/attachment/upload'] - 上传接口地址 + * @returns {Promise} - 上传成功后返回文件url + */ +export async function uploadFile(file: File, uploadUrl: string = '/v1/attachment/upload'): Promise { + const formData = new FormData(); + formData.append('file', file); + const token = typeof window !== 'undefined' ? localStorage.getItem('token') : ''; + const headers: Record = {}; + if (token) headers['Authorization'] = `Bearer ${token}`; + try { + const response = await fetch(uploadUrl, { + method: 'POST', + headers, + body: formData, + }); + const res = await response.json(); + if (res?.url) { + return res.url; + } + if (res?.data?.url) { + return res.data.url; + } + throw new Error(res?.msg || '文件上传失败'); + } catch (e: any) { + throw new Error(e?.message || '文件上传失败'); + } +} \ No newline at end of file diff --git a/nkebao/src/pages/scenarios/new/steps/BasicSettings.tsx b/nkebao/src/pages/scenarios/new/steps/BasicSettings.tsx index 704af472..b62d7064 100644 --- a/nkebao/src/pages/scenarios/new/steps/BasicSettings.tsx +++ b/nkebao/src/pages/scenarios/new/steps/BasicSettings.tsx @@ -304,6 +304,7 @@ export function BasicSettings({ // 新增:用于文件选择的ref const uploadInputRef = useRef(null); + const uploadOrderInputRef = useRef(null); // 更新电话获客设置 const handlePhoneSettingsUpdate = () => { @@ -648,6 +649,9 @@ export function BasicSettings({ transition: "border 0.2s", textAlign: "center", position: "relative", + height: 180 + 12, // 图片高度180+上下padding + overflow: "hidden", + minHeight: 192, }} onClick={() => handleMaterialSelect(material)} > @@ -675,40 +679,31 @@ export function BasicSettings({ {/* 删除自定义海报按钮 */} {isCustom && ( - + × + )}
{material.name} @@ -753,7 +751,7 @@ export function BasicSettings({ flexDirection: "column", alignItems: "center", justifyContent: "center", - height: 220, + height: 190, }} onClick={() => uploadInputRef.current?.click()} > @@ -801,62 +799,75 @@ export function BasicSettings({ index={0} />
- {/* 订单导入区块 */} + {/* 订单导入区块优化 */}
- - -
- 导入订单 -
-
- +
订单表格上传
+
+ +
- {importedTags.length > 0 && ( - - )} - + + +
+ 支持 CSV、Excel 格式,上传后将文件保存到服务器 +
+ {/* 已导入数据表格可复用原有Table渲染 */} + {importedTags.length > 0 && ( +
+ )} {/* 电话获客设置区块,仅在选择电话获客场景时显示 */} - {formData.scenario === "phone" && ( + {formData.scenario === 5 && (
- - -
+
电话获客设置
-
+
-
-
+
)} {/* 微信群设置区块,仅在选择微信群场景时显示 */} - {formData.scenario === "weixinqun" && ( + {formData.scenario === 7 && (
)} -