From 2b67bd6b77495aa458da8ba6d74e0d9418e21847 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Tue, 29 Jul 2025 17:04:00 +0800 Subject: [PATCH] =?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/WechatFriendController.php | 4 +- Server/application/cunkebao/config/route.php | 4 +- .../controller/ContentLibraryController.php | 68 ++++---- ...PotentialListWithInCompanyV1Controller.php | 149 ++++++++++++++---- .../Adapters/ChuKeBao/Adapter.php | 39 +++-- 5 files changed, 194 insertions(+), 70 deletions(-) diff --git a/Server/application/api/controller/WechatFriendController.php b/Server/application/api/controller/WechatFriendController.php index 6a3d3f61..2d747689 100644 --- a/Server/application/api/controller/WechatFriendController.php +++ b/Server/application/api/controller/WechatFriendController.php @@ -123,6 +123,7 @@ class WechatFriendController extends BaseController 'region' => $item['region'], 'addFrom' => $item['addFrom'], 'labels' => is_array($item['labels']) ? json_encode($item['labels']) : json_encode([]), + 'siteLabels' => json_encode([]), 'signature' => $item['signature'], 'isDeleted' => $item['isDeleted'], 'isPassed' => $item['isPassed'], @@ -153,7 +154,8 @@ class WechatFriendController extends BaseController $friend = WechatFriendModel::where('id', $item['id'])->find(); if ($friend) { - $result = $friend->save($data); + unset($data['siteLabels']); + $friend->save($data); return true; } else { WechatFriendModel::create($data); diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index c0dfc22e..8f7777f8 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -57,6 +57,8 @@ Route::group('v1/', function () { Route::group('traffic/pool', function () { Route::get('', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@index'); Route::get('getUserJourney', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getUserJourney'); + Route::get('getUserTags', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getUserTags'); + Route::get('getUserInfo', 'app\cunkebao\controller\traffic\GetPotentialListWithInCompanyV1Controller@getUser'); @@ -99,7 +101,7 @@ Route::group('v1/', function () { Route::delete('delete-item', 'app\cunkebao\controller\ContentLibraryController@deleteItem'); // 删除内容库素材 Route::get('get-item-detail', 'app\cunkebao\controller\ContentLibraryController@getItemDetail'); // 获取内容库素材详情 Route::post('update-item', 'app\cunkebao\controller\ContentLibraryController@updateItem'); // 更新内容库素材 - Route::get('aiEditContent', 'app\cunkebao\controller\ContentLibraryController@aiEditContent'); + Route::any('aiEditContent', 'app\cunkebao\controller\ContentLibraryController@aiEditContent'); }); // 好友相关 diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 1002e7ae..5e6b6956 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -216,7 +216,7 @@ class ContentLibraryController extends Controller ->find(); if (empty($library)) { - return json(['code' => 404, 'msg' => '内容库不存在']); + return json(['code' => 500, 'msg' => '内容库不存在']); } // 处理JSON字段转数组 @@ -306,7 +306,7 @@ class ContentLibraryController extends Controller ])->find(); if (!$library) { - return json(['code' => 404, 'msg' => '内容库不存在']); + return json(['code' => 500, 'msg' => '内容库不存在']); } Db::startTrans(); @@ -361,7 +361,7 @@ class ContentLibraryController extends Controller ])->find(); if (empty($library)) { - return json(['code' => 404, 'msg' => '内容库不存在']); + return json(['code' => 500, 'msg' => '内容库不存在']); } try { @@ -403,7 +403,7 @@ class ContentLibraryController extends Controller ])->find(); if (empty($library)) { - return json(['code' => 404, 'msg' => '内容库不存在或无权限访问']); + return json(['code' => 500, 'msg' => '内容库不存在或无权限访问']); } // 构建查询条件 @@ -520,7 +520,7 @@ class ContentLibraryController extends Controller ])->find(); if (!$library) { - return json(['code' => 404, 'msg' => '内容库不存在']); + return json(['code' => 500, 'msg' => '内容库不存在']); } try { @@ -568,7 +568,7 @@ class ContentLibraryController extends Controller ->find(); if (!$item) { - return json(['code' => 404, 'msg' => '内容项目不存在或无权限操作']); + return json(['code' => 500, 'msg' => '内容项目不存在或无权限操作']); } try { @@ -608,7 +608,7 @@ class ContentLibraryController extends Controller ->find(); if (empty($item)) { - return json(['code' => 404, 'msg' => '内容项目不存在或无权限访问']); + return json(['code' => 500, 'msg' => '内容项目不存在或无权限访问']); } // 处理数据 @@ -691,7 +691,7 @@ class ContentLibraryController extends Controller ])->find(); if (!$item) { - return json(['code' => 404, 'msg' => '内容项目不存在或无权限操作']); + return json(['code' => 500, 'msg' => '内容项目不存在或无权限操作']); } try { @@ -754,36 +754,50 @@ class ContentLibraryController extends Controller { $id = Request::param('id', ''); - + $aiPrompt = Request::param('aiPrompt', ''); + $content = Request::param('content', ''); + $companyId = $this->request->userInfo['companyId']; // 简单验证 if (empty($id)) { return json(['code' => 400, 'msg' => '参数错误']); } // 查询内容项目是否存在并检查权限 - $item = ContentItem::where([ - ['id', '=', $id], - ['isDel', '=', 0] - ])->find(); + $item = ContentItem::alias('ci') + ->join('content_library cl', 'ci.libraryId = cl.id') + ->where(['ci.id' => $id, 'ci.isDel' => 0, 'cl.isDel' => 0, 'cl.companyId' => $companyId]) + ->field('ci.*') + ->find(); if (empty($item)) { - return json(['code' => 404, 'msg' => '内容项目不存在或无权限操作']); + return json(['code' => 500, 'msg' => '内容项目不存在或无权限操作']); } if (empty($item['content'])) { - return json(['code' => 404, 'msg' => '内容不能为空']); + return json(['code' => 500, 'msg' => '内容不能为空']); } - - try { - $contentAi = $this->aiRewrite(['aiEnabled' => true], $item['content']); - if (!empty($contentAi)) { - ContentItem::where(['id' => $item['id']])->update(['contentAi' => $contentAi, 'updateTime' => time()]); - return json(['code' => 200, 'msg' => 'ai编写成功', 'data' => ['editAfter' => $contentAi, 'editFront' => $item['content']]]); - } else { - return json(['code' => 500, 'msg' => 'ai编写失败']); + $contentFront = !empty($item['contentAi']) ? $item['contentAi'] : $item['content']; + if (!$this->request->isPost()) { + try { + $contentAi = $this->aiRewrite(['aiEnabled' => true, 'aiPrompt' => $aiPrompt], $contentFront); + if (!empty($contentAi)) { + return json(['code' => 200, 'msg' => 'ai编写成功', 'data' => ['contentAfter' => $contentAi, 'contentFront' => $contentFront]]); + } else { + return json(['code' => 500, 'msg' => 'ai编写失败']); + } + } catch (\Exception $e) { + return json(['code' => 500, 'msg' => 'ai编写失败:' . $e->getMessage()]); + } + } else { + if (empty($content)) { + return json(['code' => 500, 'msg' => '新内容不能为空']); + } + $res = ContentItem::where(['id' => $item['id']])->update(['contentAi' => $content, 'updateTime' => time()]); + if (!empty($res)) { + return json(['code' => 200, 'msg' => '更新成功']); + } else { + return json(['code' => 500, 'msg' => '更新失败']); } - } catch (\Exception $e) { - return json(['code' => 500, 'msg' => 'ai编写失败:' . $e->getMessage()]); } } @@ -1505,10 +1519,10 @@ class ContentLibraryController extends Controller ]; } } - }else{ + } else { if (strpos($url, 'feishu.cn') !== false) { $coverImage = 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/3db2a5d7fe49011ab68175a42a5094ce.jpeg'; - }else{ + } else { $coverImage = 'http://karuosiyujzk.oss-cn-shenzhen.aliyuncs.com/2025/07/09/ec039d96fad6eab1d960f207d3d9ca9f.jpeg'; } diff --git a/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php b/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php index 0ebfe936..0bcd7b10 100644 --- a/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php +++ b/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php @@ -23,7 +23,7 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController protected function makeWhere(array $params = []): array { if (!empty($keyword = $this->request->param('keyword'))) { - $where[] = ['p.identifier|wa.nickname|wa.phone|wa.wechatId|wa.alias','like', '%'. $keyword .'%']; + $where[] = ['p.identifier|wa.nickname|wa.phone|wa.wechatId|wa.alias', 'like', '%' . $keyword . '%']; } // 状态筛选 @@ -35,10 +35,10 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController // 来源的筛选 if ($fromd = $this->request->param('packageId')) { - if ($fromd != -1){ + if ($fromd != -1) { $where['tsp.id'] = $fromd; - }else{ - $where[] = ['tsp.id',null]; + } else { + $where[] = ['tsp.id', null]; } } @@ -48,7 +48,6 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController } - $where['s.companyId'] = $this->getUserInfo('companyId'); return array_merge($where, $params); @@ -65,16 +64,16 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController $query = TrafficPoolModel::alias('p') ->field( [ - 'p.id','p.identifier', 'p.mobile', 'p.wechatId', 'p.identifier', - 's.fromd', 's.status', 's.createTime','s.companyId','s.sourceId','s.type', + 'p.id', 'p.identifier', 'p.mobile', 'p.wechatId', 'p.identifier', + 's.fromd', 's.status', 's.createTime', 's.companyId', 's.sourceId', 's.type', 'wa.nickname', 'wa.avatar', 'wa.gender', 'wa.phone', ] ) - ->join('traffic_source s', 'p.identifier=s.identifier','left') - ->join('wechat_account wa', 'p.identifier=wa.wechatId','left') - ->join('traffic_source_package_item tspi', 'p.identifier = tspi.identifier AND s.companyId = tspi.companyId','left') - ->join('traffic_source_package tsp', 'tspi.packageId=tsp.id','left') - ->join('device_wechat_login d', 's.sourceId=d.wechatId','left') + ->join('traffic_source s', 'p.identifier=s.identifier', 'left') + ->join('wechat_account wa', 'p.identifier=wa.wechatId', 'left') + ->join('traffic_source_package_item tspi', 'p.identifier = tspi.identifier AND s.companyId = tspi.companyId', 'left') + ->join('traffic_source_package tsp', 'tspi.packageId=tsp.id', 'left') + ->join('device_wechat_login d', 's.sourceId=d.wechatId', 'left') ->order('p.id DESC,s.id DESC') ->group('p.identifier'); @@ -90,7 +89,7 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController $query->where($key, $value); } - $result = $query->paginate($this->request->param('limit/d', 10), false, ['page' => $this->request->param('page/d', 1)]); + $result = $query->paginate($this->request->param('limit/d', 10), false, ['page' => $this->request->param('page/d', 1)]); $list = $result->items(); $total = $result->total(); @@ -98,29 +97,29 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController //流量池筛选 $package = Db::name('traffic_source_package_item')->alias('tspi') ->join('traffic_source_package p', 'tspi.packageId=p.id AND tspi.companyId=p.companyId') - ->where(['tspi.companyId' => $item->companyId,'tspi.identifier' => $item->identifier]) + ->where(['tspi.companyId' => $item->companyId, 'tspi.identifier' => $item->identifier]) ->column('p.name'); $package2 = Db::name('traffic_source_package_item')->alias('tspi') ->join('traffic_source_package p', 'tspi.packageId=p.id') - ->where(['tspi.companyId' => $item->companyId,'tspi.identifier' => $item->identifier,'p.isSys' => 1]) + ->where(['tspi.companyId' => $item->companyId, 'tspi.identifier' => $item->identifier, 'p.isSys' => 1]) ->column('p.name'); $packages = array_merge($package, $package2); $item['packages'] = $packages; - if ($item->type == 1){ + if ($item->type == 1) { $tag = Db::name('wechat_friendship')->where(['wechatId' => $item->wechatId])->column('tags'); $tags = []; foreach ($tag as $k => $v) { - $v = json_decode($v,true); - $tags = array_merge($tags, $v); + $v = json_decode($v, true); + if (!empty($v)) { + $tags = array_merge($tags, $v); + } } $item['tags'] = $tags; } - - } unset($item); $data = ['list' => $list, 'total' => $total]; @@ -135,11 +134,11 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController public function index() { try { - $result = $this->getPoolListByCompanyId( $this->makeWhere() ); + $result = $this->getPoolListByCompanyId($this->makeWhere()); $result = json_decode($result, true); return ResponseHelper::success( [ - 'list' => $result['list'], + 'list' => $result['list'], 'total' => $result['total'], ] ); @@ -148,7 +147,62 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController } } + public function getUser() + { + $userId = $this->request->param('userId', ''); + if (empty($userId)) { + return json_encode(['code' => 500, 'msg' => '用户id不能为空']); + } + + + $item = TrafficPoolModel::alias('p') + ->field( + [ + 'p.id', 'p.identifier', 'p.mobile', 'p.wechatId', 'p.identifier', + 's.fromd', 's.status', 's.createTime', 's.companyId', 's.sourceId', 's.type', + 'wa.nickname', 'wa.avatar', 'wa.gender', 'wa.phone', + ] + ) + ->join('traffic_source s', 'p.identifier=s.identifier', 'left') + ->join('wechat_account wa', 'p.identifier=wa.wechatId', 'left') + ->join('traffic_source_package_item tspi', 'p.identifier = tspi.identifier AND s.companyId = tspi.companyId', 'left') + ->join('traffic_source_package tsp', 'tspi.packageId=tsp.id', 'left') + ->join('device_wechat_login d', 's.sourceId=d.wechatId', 'left') + ->order('p.id DESC,s.id DESC') + ->where(['p.id' => $userId]) + ->group('p.identifier') + ->find(); + + + //流量池筛选 + $package = Db::name('traffic_source_package_item')->alias('tspi') + ->join('traffic_source_package p', 'tspi.packageId=p.id AND tspi.companyId=p.companyId') + ->where(['tspi.companyId' => $item->companyId, 'tspi.identifier' => $item->identifier]) + ->column('p.name'); + + $package2 = Db::name('traffic_source_package_item')->alias('tspi') + ->join('traffic_source_package p', 'tspi.packageId=p.id') + ->where(['tspi.companyId' => $item->companyId, 'tspi.identifier' => $item->identifier, 'p.isSys' => 1]) + ->column('p.name'); + $packages = array_merge($package, $package2); + $item['packages'] = $packages; + + + if ($item->type == 1) { + $tag = Db::name('wechat_friendship')->where(['wechatId' => $item->wechatId])->column('tags'); + $tags = []; + foreach ($tag as $k => $v) { + $v = json_decode($v, true); + if (!empty($v)) { + $tags = array_merge($tags, $v); + } + } + $item['tags'] = $tags; + } + + + } /** @@ -160,10 +214,10 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController */ public function getUserJourney() { - $page = $this->request->param('page',1); - $pageSize = $this->request->param('pageSize',10); - $userId = $this->request->param('userId',''); - if(empty($userId)){ + $page = $this->request->param('page', 1); + $pageSize = $this->request->param('pageSize', 10); + $userId = $this->request->param('userId', ''); + if (empty($userId)) { return json_encode(['code' => 500, 'msg' => '用户id不能为空']); } @@ -174,16 +228,49 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController $total = $query->count(); $list = $query->order('createTime desc') - ->page($page,$pageSize) + ->page($page, $pageSize) ->select(); - foreach ($list as $k=>$v){ - $list[$k]['createTime'] = date('Y-m-d H:i:s',$v['createTime']); - $list[$k]['updateTime'] = date('Y-m-d H:i:s',$v['updateTime']); + foreach ($list as $k => $v) { + $list[$k]['createTime'] = date('Y-m-d H:i:s', $v['createTime']); + $list[$k]['updateTime'] = date('Y-m-d H:i:s', $v['updateTime']); } - return ResponseHelper::success(['list' => $list,'total'=>$total]); + return ResponseHelper::success(['list' => $list, 'total' => $total]); } + + public function getUserTags() + { + $userId = $this->request->param('userId', ''); + if (empty($userId)) { + return json_encode(['code' => 500, 'msg' => '用户id不能为空']); + } + $data = Db::name('traffic_pool')->alias('tp') + ->join(['s2_wechat_friend' => 'wf'], 'tp.wechatId=wf.wechatId', 'left') + ->where(['tp.id' => $userId]) + ->order('tp.createTime desc') + ->column('wf.id,wf.labels,wf.siteLabels'); + + $tags = []; + $siteLabels = []; + foreach ($data as $k => $v) { + $tag = json_decode($v['labels'], true); + $tag2 = json_decode($v['siteLabels'], true); + if (!empty($tag)) { + $tags = array_merge($tags, $tag); + } + if (!empty($tag2)) { + $siteLabels = array_merge($siteLabels, $tag2); + } + } + $tags = array_unique($tags); + $tags = array_values($tags); + $siteLabels = array_unique($siteLabels); + $siteLabels = array_values($siteLabels); + return ResponseHelper::success(['wechat' => $tags, 'siteLabels' => $siteLabels]); + } + + } \ No newline at end of file diff --git a/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php b/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php index feed3dee..2dbded4d 100644 --- a/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php +++ b/Server/extend/WeChatDeviceApi/Adapters/ChuKeBao/Adapter.php @@ -155,7 +155,7 @@ class Adapter implements WeChatServiceInterface { $task = Db::name('customer_acquisition_task') ->where(['status' => 1,'deleteTime' => 0]) - ->whereRaw("id % $process_count_for_status_0 = {$current_worker_id}") +// ->whereRaw("id % $process_count_for_status_0 = {$current_worker_id}") ->order('id desc') ->select(); @@ -179,7 +179,6 @@ class Adapter implements WeChatServiceInterface $taskData = array_merge($taskData, $tasks); } - if ($taskData) { foreach ($taskData as $task) { @@ -197,9 +196,9 @@ class Adapter implements WeChatServiceInterface $friendAddTaskCreated = false; foreach ($wechatIdAccountIdMap as $accountId => $wechatId) { - // 是否已经是好友的判断,如果已经是好友,直接break; 但状态还是维持1,让另外一个进程处理发消息的逻辑 - $isFriend = $this->checkIfIsWeChatFriendByPhone($wechatId, $task['phone']); + $wechatTags = json_decode($task['tags'], true); + $isFriend = $this->checkIfIsWeChatFriendByPhone($wechatId, $task['phone'],$task['siteTags']); if (!empty($isFriend)) { $friendAddTaskCreated = true; $task['processed_wechat_ids'] = $task['processed_wechat_ids'] . ',' . $wechatId; // 处理失败任务用,用于过滤已处理的微信号 @@ -221,10 +220,15 @@ class Adapter implements WeChatServiceInterface // 采取乐观尝试的策略,假设第一个可以添加的人可以添加成功的; 回头再另外一个任务进程去判断 // 创建好友添加任务, 对接触客宝 - $tags = array_merge($task_info['tagConf']['customTags'],$task_info['tagConf']['scenarioTags']); + if (!empty($wechatTags)){ + $tags = array_merge($tags,$wechatTags); + } + $tags = array_unique($tags); + $tags = array_values($tags); $conf = array_merge($task_info['reqConf'], ['task_name' => $task_info['name'],'tags' => $tags]); + $this->createFriendAddTask($accountId, $task['phone'], $conf); $friendAddTaskCreated = true; $task['processed_wechat_ids'] = $task['processed_wechat_ids'] . ',' . $wechatId; // 处理失败任务用,用于过滤已处理的微信号 @@ -459,21 +463,36 @@ class Adapter implements WeChatServiceInterface } // 检查是否是好友关系 - public function checkIfIsWeChatFriendByPhone(string $wxId, string $phone): bool + public function checkIfIsWeChatFriendByPhone(string $wxId, string $phone,string $siteTags): bool { if (empty($wxId) || empty($phone)) { return false; } try { - $id = Db::table('s2_wechat_friend') + $friend = Db::table('s2_wechat_friend') ->where('ownerWechatId', $wxId) ->where(['isPassed' => 1,'isDeleted' => 0]) ->where('phone|alias|wechatId', 'like', $phone . '%') ->order('createTime', 'desc') - ->value('id'); - - return (bool)$id; + ->find(); + if (!empty($friend)) { + if (!empty($siteTags)) { + $siteTags = json_decode($siteTags, true); + $siteLabels = json_decode($friend['siteLabels'], true); + $tags = array_merge($siteTags,$siteLabels); + $tags = array_unique($tags); + $tags = array_values($tags); + if (empty($tags)){ + $tags = []; + } + $tags = json_encode($tags,256); + Db::table('s2_wechat_friend')->where(['id' => $friend['id']])->update(['siteLabels' => $tags,'updateTime' => time()]); + } + return true; + }else{ + return false; + } } catch (\Exception $e) { Log::error("Error in checkIfIsWeChatFriendByPhone (wxId: {$wxId}, phone: {$phone}): " . $e->getMessage()); return false;