diff --git a/Server/application/api/controller/MessageController.php b/Server/application/api/controller/MessageController.php index da0337413..12d732c15 100644 --- a/Server/application/api/controller/MessageController.php +++ b/Server/application/api/controller/MessageController.php @@ -425,15 +425,31 @@ class MessageController extends BaseController } } } - - - - - - - // 创建新记录 - WechatMessageModel::create($data); + $res = WechatMessageModel::create($data); + + // 1 文字 3图片 47动态图片 34语言 43视频 42名片 40/20链接 49文件 + if (!empty($res) && empty($item['isSend']) && in_array($item['msgType'],[1,3,20,34,40,42,43,47,49])){ + $friend = Db::name('wechat_friendship')->where('id',$item['wechatFriendId'])->find(); + if (!empty($friend)){ + $trafficPoolId = Db::name('traffic_pool')->where('identifier',$friend['wechatId'])->value('id'); + if (!empty($trafficPoolId)){ + $data = [ + 'type' => 4, + 'companyId' => $friend['companyId'], + 'trafficPoolId' => $trafficPoolId, + 'source' => 0, + 'uniqueId' => $res['id'], + 'sourceData' => json_encode([]), + 'remark' => '用户发送了消息', + 'createTime' => time(), + 'updateTime' => time() + ]; + Db::name('user_portrait')->insert($data); + } + } + } + } /** diff --git a/Server/application/command.php b/Server/application/command.php index 2dcd31788..570c76a4c 100644 --- a/Server/application/command.php +++ b/Server/application/command.php @@ -32,4 +32,5 @@ return [ 'sync:wechatData' => 'app\command\SyncWechatDataToCkbTask', // 同步微信数据到存客宝 'sync:allFriends' => 'app\command\SyncAllFriendsCommand', // 同步所有在线好友 'workbench:trafficDistribute' => 'app\command\WorkbenchTrafficDistributeCommand', // 工作台流量分发任务 + 'switch:friends' => 'app\command\SwitchFriendsCommand', ]; diff --git a/Server/application/command/SwitchFriendsCommand.php b/Server/application/command/SwitchFriendsCommand.php index d153f3728..2ea775121 100644 --- a/Server/application/command/SwitchFriendsCommand.php +++ b/Server/application/command/SwitchFriendsCommand.php @@ -26,6 +26,9 @@ class SwitchFriendsCommand extends Command protected function execute(Input $input, Output $output) { + // 清理可能损坏的缓存数据 + $this->clearCorruptedCache($output); + //处理流量分过期数据 $expUserData = Db::name('workbench_traffic_config_item') ->where('expTime','<=',time()) @@ -122,7 +125,15 @@ class SwitchFriendsCommand extends Command $output->writeln('开始执行好友切换任务...'); do { - $friends = Cache::get($cacheKey, []); + try { + $friends = Cache::get($cacheKey, []); + } catch (\Exception $e) { + // 如果缓存数据损坏,清空缓存并记录错误 + $output->writeln('缓存数据损坏,正在清空缓存: ' . $e->getMessage()); + Cache::rm($cacheKey); + $friends = []; + } + $toSwitch = []; foreach ($friends as $friend) { if (isset($friend['time']) && $friend['time'] < $now) { @@ -196,7 +207,15 @@ class SwitchFriendsCommand extends Command } // 过滤掉已切换的,保留未切换和新进来的 - $newFriends = Cache::get($cacheKey, []); + try { + $newFriends = Cache::get($cacheKey, []); + } catch (\Exception $e) { + // 如果缓存数据损坏,清空缓存并记录错误 + $output->writeln('缓存数据损坏,正在清空缓存: ' . $e->getMessage()); + Cache::rm($cacheKey); + $newFriends = []; + } + $updated = []; foreach ($newFriends as $friend) { $friendId = !empty($friend['friendId']) ? $friend['friendId'] : $friend['id']; @@ -210,7 +229,13 @@ class SwitchFriendsCommand extends Command return ($a['time'] ?? 0) <=> ($b['time'] ?? 0); }); - $success = Cache::set($cacheKey, $updated); + try { + $success = Cache::set($cacheKey, $updated); + } catch (\Exception $e) { + // 如果缓存设置失败,记录错误并继续 + $output->writeln('缓存设置失败: ' . $e->getMessage()); + $success = false; + } $retry++; } while (!$success && $retry < $maxRetry); @@ -222,4 +247,24 @@ class SwitchFriendsCommand extends Command $output->writeln('缓存已更新并排序'); } + /** + * 清理损坏的缓存数据 + * @param Output $output + */ + private function clearCorruptedCache(Output $output) + { + $cacheKey = 'allotWechatFriend'; + try { + // 尝试读取缓存,如果失败则清空 + $testData = Cache::get($cacheKey, []); + if (!is_array($testData)) { + $output->writeln('缓存数据格式错误,正在清空缓存'); + Cache::rm($cacheKey); + } + } catch (\Exception $e) { + $output->writeln('检测到损坏的缓存数据,正在清空: ' . $e->getMessage()); + Cache::rm($cacheKey); + } + } + } \ No newline at end of file diff --git a/Server/application/common.php b/Server/application/common.php index d412b53a7..5b6987ae2 100644 --- a/Server/application/common.php +++ b/Server/application/common.php @@ -526,3 +526,29 @@ function dump() { call_user_func_array(['app\\common\\helper\\Debug', 'dump'], func_get_args()); } + +if (!function_exists('artificialAllotWechatFriend')) { + function artificialAllotWechatFriend($friend = []) + { + if (empty($friend)) { + return false; + } + + //记录切换好友 + $cacheKey = 'allotWechatFriend'; + $cacheFriend = $friend; + $cacheFriend['time'] = time() + 120; + $maxRetry = 5; + $retry = 0; + do { + $cacheFriendData = Cache::get($cacheKey, []); + // 去重:移除同friendId的旧数据 + $cacheFriendData = array_filter($cacheFriendData, function($item) use ($cacheFriend) { + return $item['friendId'] !== $cacheFriend['friendId']; + }); + $cacheFriendData[] = $cacheFriend; + $success = Cache::set($cacheKey, $cacheFriendData); + $retry++; + } while (!$success && $retry < $maxRetry); + } +} \ No newline at end of file diff --git a/Server/application/common/controller/PasswordLoginController.php b/Server/application/common/controller/PasswordLoginController.php index c5cce3d4d..74058fe4a 100644 --- a/Server/application/common/controller/PasswordLoginController.php +++ b/Server/application/common/controller/PasswordLoginController.php @@ -53,7 +53,11 @@ class PasswordLoginController extends BaseController throw new \Exception('用户不存在或已禁用', 403); } - if ($user->passwordMd5 !== md5($password)) { + + $password = md5($password); + + + if ($user->passwordMd5 !== $password) { throw new \Exception('账号或密码错误', 403); } diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index ba1ed01e6..69290e148 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -40,7 +40,7 @@ Route::group('v1/', function () { Route::get('scenes-detail', 'app\cunkebao\controller\plan\GetPlanSceneListV1Controller@detail'); Route::post('create', 'app\cunkebao\controller\plan\PostCreateAddFriendPlanV1Controller@index'); Route::get('list', 'app\cunkebao\controller\plan\PlanSceneV1Controller@index'); - Route::get('copy', 'app\cunkebao\controller\plan\PlanSceneV1Controller@copy'); + Route::get('copy', 'app\cunkebao\controller\plan\GetCreateAddFriendPlanV1Controller@copy'); Route::delete('delete', 'app\cunkebao\controller\plan\PlanSceneV1Controller@delete'); Route::post('updateStatus', 'app\cunkebao\controller\plan\PlanSceneV1Controller@updateStatus'); Route::get('detail', 'app\cunkebao\controller\plan\GetAddFriendPlanDetailV1Controller@index'); @@ -56,6 +56,9 @@ Route::group('v1/', function () { Route::get('types', 'app\cunkebao\controller\traffic\GetPotentialTypeSectionV1Controller@index'); Route::get('sources', 'app\cunkebao\controller\traffic\GetTrafficSourceSectionV1Controller@index'); Route::get('statistics', 'app\cunkebao\controller\traffic\GetPoolStatisticsV1Controller@index'); + + + Route::get('list', 'app\cunkebao\controller\TrafficController@getList'); }); // 工作台相关 @@ -102,6 +105,7 @@ Route::group('v1/', function () { }); + //数据统计相关 Route::group('dashboard',function (){ Route::get('', 'app\cunkebao\controller\StatsController@baseInfoStats'); Route::get('plan-stats', 'app\cunkebao\controller\StatsController@planStats'); diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 6c522a6d1..0d28937c7 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -415,7 +415,7 @@ class ContentLibraryController extends Controller // 关键词搜索 if (!empty($keyword)) { - $where[] = ['content', 'like', '%' . $keyword . '%']; + $where[] = ['content|title', 'like', '%' . $keyword . '%']; } // 查询数据 @@ -440,22 +440,22 @@ class ContentLibraryController extends Controller } // 获取发送者信息 - if ($item['type'] == 'moment' && $item['friendId']) { + if ($item['type'] == 'moment' && !empty($item['friendId'])) { $friendInfo = Db::name('wechat_friendship') ->alias('wf') ->join('wechat_account wa', 'wf.wechatId = wa.wechatId') ->where('wf.id', $item['friendId']) ->field('wa.nickname, wa.avatar') ->find(); - $item['senderNickname'] = $friendInfo['nickname'] ?: ''; - $item['senderAvatar'] = $friendInfo['avatar'] ?: ''; - }else if ($item['type'] == 'group_message' && $item['wechatChatroomId']) { + $item['senderNickname'] = !empty($friendInfo['nickname']) ? $friendInfo['nickname'] : ''; + $item['senderAvatar'] = !empty( $friendInfo['avatar']) ? $friendInfo['avatar'] : ''; + }else if ($item['type'] == 'group_message' && !empty($item['wechatChatroomId'])) { $friendInfo = Db::table('s2_wechat_chatroom_member') ->field('nickname, avatar') ->where('wechatId', $item['wechatId']) ->find(); - $item['senderNickname'] = $friendInfo['nickname'] ?: ''; - $item['senderAvatar'] = $friendInfo['avatar'] ?: ''; + $item['senderNickname'] = !empty($friendInfo['nickname']) ? $friendInfo['nickname'] : ''; + $item['senderAvatar'] = !empty($friendInfo['avatar']) ? $friendInfo['avatar'] : ''; } } unset($item); diff --git a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php index 055cf9ea7..c4cd7e081 100644 --- a/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php +++ b/Server/application/cunkebao/controller/plan/PlanSceneV1Controller.php @@ -407,7 +407,13 @@ class PlanSceneV1Controller extends BaseController $posterWeChatMiniProgram = new PosterWeChatMiniProgram(); $result = $posterWeChatMiniProgram->generateMiniProgramCodeWithScene($taskId); - return ResponseHelper::success($result, '获取小程序码成功'); + $result = json_decode($result, true); + if ($result['code'] == 200){ + return ResponseHelper::success($result['data'], '获取小程序码成功'); + }else{ + return ResponseHelper::error('获取小程序失败:' . $result['msg']); + } + } diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index 753beed25..b05b981f0 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -25,36 +25,37 @@ class PosterWeChatMiniProgram extends Controller // 生成小程序码,存客宝-操盘手调用 public function generateMiniProgramCodeWithScene($taskId = '') { - $taskId = request()->param('id'); - - $app = Factory::miniProgram(self::MINI_PROGRAM_CONFIG); - - // scene参数长度限制为32位 - // $scene = 'taskId=' . $taskId; - $scene = 'id=' . $taskId; - - // 调用接口生成小程序码 - $response = $app->app_code->getUnlimit($scene, [ - 'page' => 'pages/poster/index', // 必须是已经发布的小程序页面 - 'width' => 430, // 二维码的宽度,默认430 - // 'auto_color' => false, // 自动配置线条颜色 - // 'line_color' => ['r' => 0, 'g' => 0, 'b' => 0], // 颜色设置 - // 'is_hyaline' => false, // 是否需要透明底色 - ]); - - // 保存小程序码到文件 - 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; + if (empty($taskId)){ + return json_encode(['code' => 500,'data' => '','msg' => '任务id不能为空']); } - // return false; - return null; + + try { + $app = Factory::miniProgram(self::MINI_PROGRAM_CONFIG); + // scene参数长度限制为32位 + //$scene = 'taskId=' . $taskId; + $scene = sprintf("%s", $taskId); + // 调用接口生成小程序码 + $response = $app->app_code->getUnlimit($scene, [ + 'page' => 'pages/poster/index2', // 必须是已经发布的小程序页面 + 'width' => 430, // 二维码的宽度,默认430 + // 'auto_color' => false, // 自动配置线条颜色 + // 'line_color' => ['r' => 0, 'g' => 0, 'b' => 0], // 颜色设置 + // 'is_hyaline' => false, // 是否需要透明底色 + ]); + // 保存小程序码到文件 + 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 json_encode(['code' => 200, 'data' => $img_base64]); + } + }catch (\Exception $e) { + return json_encode(['code' => 500,'data' => '','msg' => $e->getMessage()]); + } } // getPhoneNumber @@ -90,7 +91,8 @@ class PosterWeChatMiniProgram extends Controller if (!$trafficPool) { Db::name('traffic_pool')->insert([ 'identifier' => $result['phone_info']['phoneNumber'], - 'mobile' => $result['phone_info']['phoneNumber'] + 'mobile' => $result['phone_info']['phoneNumber'], + 'createTime' => time() ]); } // 2. 写入 ck_task_customer: 以 task_id ~~identifier~~ phone 为条件,如果存在则忽略,使用类似laravel的firstOrcreate(但我不知道thinkphp5.1里的写法) diff --git a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php index e41cdfc68..15f1714b5 100644 --- a/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php +++ b/Server/application/cunkebao/controller/wechat/GetWechatsOnDevicesV1Controller.php @@ -196,7 +196,7 @@ class GetWechatsOnDevicesV1Controller extends BaseController // 关键词搜索(同时搜索微信号和昵称) if (!empty($keyword = $this->request->param('keyword'))) { - $where[] = ['exp', "w.alias LIKE '%{$keyword}%' OR w.nickname LIKE '%{$keyword}%'"]; + $where[] = ["w.wechatId|w.alias|w.nickname", 'LIKE', '%' . $keyword . '%']; } $where['w.wechatId'] = array('in', implode(',', $wechatIds));