From 0912a0067e7da2cef0de72d669a4af6de6b1d3dc Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Wed, 19 Nov 2025 15:28:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=85=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/ContentLibraryController.php | 655 ++++++++++++------ 1 file changed, 446 insertions(+), 209 deletions(-) diff --git a/Server/application/cunkebao/controller/ContentLibraryController.php b/Server/application/cunkebao/controller/ContentLibraryController.php index 9dbc438b..d77c12d8 100644 --- a/Server/application/cunkebao/controller/ContentLibraryController.php +++ b/Server/application/cunkebao/controller/ContentLibraryController.php @@ -121,15 +121,20 @@ class ContentLibraryController extends Controller $page = $this->request->param('page', 1); $limit = $this->request->param('limit', 10); $keyword = $this->request->param('keyword', ''); - $sourceType = $this->request->param('sourceType', ''); // 新增:来源类型,1=好友,2=群 + $sourceType = $this->request->param('sourceType', ''); // 来源类型,1=好友,2=群 + $companyId = $this->request->userInfo['companyId']; + $userId = $this->request->userInfo['id']; + $isAdmin = !empty($this->request->userInfo['isAdmin']); + // 构建基础查询条件 $where = [ - ['companyId', '=', $this->request->userInfo['companyId']], + ['companyId', '=', $companyId], ['isDel', '=', 0] // 只查询未删除的记录 ]; - if (empty($this->request->userInfo['isAdmin'])) { - $where[] = ['userId', '=', $this->request->userInfo['id']]; + // 非管理员只能查看自己的内容库 + if (!$isAdmin) { + $where[] = ['userId', '=', $userId]; } // 添加名称模糊搜索 @@ -137,12 +142,15 @@ class ContentLibraryController extends Controller $where[] = ['name', 'like', '%' . $keyword . '%']; } - // 添加名称模糊搜索 + // 添加来源类型筛选 if (!empty($sourceType)) { $where[] = ['sourceType', '=', $sourceType]; } + // 获取总记录数 + $total = ContentLibrary::where($where)->count(); + // 获取分页数据 $list = ContentLibrary::where($where) ->field('id,name,sourceFriends,sourceGroups,keywordInclude,keywordExclude,aiEnabled,aiPrompt,timeEnabled,timeStart,timeEnd,status,sourceType,userId,createTime,updateTime') ->with(['user' => function ($query) { @@ -152,56 +160,120 @@ class ContentLibraryController extends Controller ->page($page, $limit) ->select(); - // 处理JSON字段 - foreach ($list as &$item) { + // 收集所有需要查询的ID + $libraryIds = []; + $friendIdsByLibrary = []; + $groupIdsByLibrary = []; + + foreach ($list as $item) { + $libraryIds[] = $item['id']; + + // 解析JSON字段 $item['sourceFriends'] = json_decode($item['sourceFriends'] ?: '[]', true); $item['sourceGroups'] = json_decode($item['sourceGroups'] ?: '[]', true); $item['keywordInclude'] = json_decode($item['keywordInclude'] ?: '[]', true); $item['keywordExclude'] = json_decode($item['keywordExclude'] ?: '[]', true); + + // 收集好友和群组ID + if (!empty($item['sourceFriends']) && $item['sourceType'] == 1) { + $friendIdsByLibrary[$item['id']] = $item['sourceFriends']; + } + + if (!empty($item['sourceGroups']) && $item['sourceType'] == 2) { + $groupIdsByLibrary[$item['id']] = $item['sourceGroups']; + } + } + + // 批量查询内容项数量 + $itemCounts = []; + if (!empty($libraryIds)) { + $counts = Db::name('content_item') + ->field('libraryId, COUNT(*) as count') + ->whereIn('libraryId', $libraryIds) + ->where('isDel', 0) + ->group('libraryId') + ->select(); + + foreach ($counts as $count) { + $itemCounts[$count['libraryId']] = $count['count']; + } + } + + // 批量查询好友信息 + $friendsInfoMap = []; + $allFriendIds = []; + foreach ($friendIdsByLibrary as $libraryId => $friendIds) { + if (!empty($friendIds)) { + $allFriendIds = array_merge($allFriendIds, $friendIds); + } + } + + if (!empty($allFriendIds)) { + $allFriendIds = array_unique($allFriendIds); + $friendsInfo = Db::name('wechat_friendship')->alias('wf') + ->field('wf.id,wf.wechatId, wa.nickname, wa.avatar') + ->join('wechat_account wa', 'wf.wechatId = wa.wechatId') + ->whereIn('wf.id', $allFriendIds) + ->select(); + + foreach ($friendsInfo as $friend) { + $friendsInfoMap[$friend['id']] = $friend; + } + } + + // 批量查询群组信息 + $groupsInfoMap = []; + $allGroupIds = []; + foreach ($groupIdsByLibrary as $libraryId => $groupIds) { + if (!empty($groupIds)) { + $allGroupIds = array_merge($allGroupIds, $groupIds); + } + } + + if (!empty($allGroupIds)) { + $allGroupIds = array_unique($allGroupIds); + $groupsInfo = Db::name('wechat_group')->alias('g') + ->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId') + ->whereIn('g.id', $allGroupIds) + ->select(); + + foreach ($groupsInfo as $group) { + $groupsInfoMap[$group['id']] = $group; + } + } + + // 处理每个内容库的数据 + foreach ($list as &$item) { // 添加创建人名称 $item['creatorName'] = $item['user']['username'] ?? ''; - $item['itemCount'] = Db::name('content_item')->where('libraryId', $item['id'])->count(); - - // 获取好友详细信息 - if (!empty($item['sourceFriends'] && $item['sourceType'] == 1)) { - $friendIds = $item['sourceFriends']; - $friendsInfo = []; - - if (!empty($friendIds)) { - // 查询好友信息,使用wechat_friendship表 - $friendsInfo = Db::name('wechat_friendship')->alias('wf') - ->field('wf.id,wf.wechatId, wa.nickname, wa.avatar') - ->join('wechat_account wa', 'wf.wechatId = wa.wechatId') - ->whereIn('wf.id', $friendIds) - ->select(); + + // 添加内容项数量 + $item['itemCount'] = $itemCounts[$item['id']] ?? 0; + + // 处理好友信息 + if (!empty($friendIdsByLibrary[$item['id']])) { + $selectedFriends = []; + foreach ($friendIdsByLibrary[$item['id']] as $friendId) { + if (isset($friendsInfoMap[$friendId])) { + $selectedFriends[] = $friendsInfoMap[$friendId]; + } } - - // 将好友信息添加到返回数据中 - $item['selectedFriends'] = $friendsInfo; + $item['selectedFriends'] = $selectedFriends; } - - - if (!empty($item['sourceGroups']) && $item['sourceType'] == 2) { - $groupIds = $item['sourceGroups']; - $groupsInfo = []; - - if (!empty($groupIds)) { - // 查询群组信息 - $groupsInfo = Db::name('wechat_group')->alias('g') - ->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId') - ->whereIn('g.id', $groupIds) - ->select(); + + // 处理群组信息 + if (!empty($groupIdsByLibrary[$item['id']])) { + $selectedGroups = []; + foreach ($groupIdsByLibrary[$item['id']] as $groupId) { + if (isset($groupsInfoMap[$groupId])) { + $selectedGroups[] = $groupsInfoMap[$groupId]; + } } - - // 将群组信息添加到返回数据中 - $item['selectedGroups'] = $groupsInfo; + $item['selectedGroups'] = $selectedGroups; } - + unset($item['user']); // 移除关联数据 } - unset($item); - - $total = ContentLibrary::where($where)->count(); return json([ 'code' => 200, @@ -221,20 +293,26 @@ class ContentLibraryController extends Controller public function detail() { $id = $this->request->param('id', 0); + $companyId = $this->request->userInfo['companyId']; + $userId = $this->request->userInfo['id']; + $isAdmin = !empty($this->request->userInfo['isAdmin']); + if (empty($id)) { return json(['code' => 400, 'msg' => '参数错误']); } + // 构建查询条件 $where = [ - ['companyId', '=', $this->request->userInfo['companyId']], + ['id', '=', $id], + ['companyId', '=', $companyId], ['isDel', '=', 0] // 只查询未删除的记录 ]; - if (empty($this->request->userInfo['isAdmin'])) { - $where[] = ['userId', '=', $this->request->userInfo['id']]; + if (!$isAdmin) { + $where[] = ['userId', '=', $userId]; } - + // 查询内容库信息 $library = ContentLibrary::where($where) ->field('id,name,sourceType,sourceFriends,sourceGroups,keywordInclude,keywordExclude,aiEnabled,aiPrompt,timeEnabled,timeStart,timeEnd,status,userId,companyId,createTime,updateTime,groupMembers,catchType') ->find(); @@ -260,45 +338,35 @@ class ContentLibraryController extends Controller $library['timeEnd'] = date('Y-m-d', $library['timeEnd']); } - // 获取好友详细信息 + // 初始化选项数组 + $library['friendsGroupsOptions'] = []; + $library['wechatGroupsOptions'] = []; + + // 批量查询好友信息 if (!empty($library['friendsGroups'])) { $friendIds = $library['friendsGroups']; - $friendsInfo = []; - if (!empty($friendIds)) { // 查询好友信息,使用wechat_friendship表 - $friendsInfo = Db::name('wechat_friendship')->alias('wf') + $library['friendsGroupsOptions'] = Db::name('wechat_friendship')->alias('wf') ->field('wf.id,wf.wechatId, wa.nickname, wa.avatar') ->join('wechat_account wa', 'wf.wechatId = wa.wechatId') ->order('wa.id DESC') ->whereIn('wf.id', $friendIds) ->select(); } - - // 将好友信息添加到返回数据中 - $library['friendsGroupsOptions'] = $friendsInfo; - } else { - $library['friendsGroupsOptions'] = []; } - // 获取群组详细信息 + // 批量查询群组信息 if (!empty($library['wechatGroups'])) { $groupIds = $library['wechatGroups']; - $groupsInfo = []; - if (!empty($groupIds)) { // 查询群组信息 - $groupsInfo = Db::name('wechat_group')->alias('g') - ->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId,wa.nickname as ownerNickname,wa.avatar as ownerAvatar,wa.alias as ownerAlias') - ->join('wechat_account wa', 'g.ownerWechatId = wa.wechatId') + $library['wechatGroupsOptions'] = Db::name('wechat_group')->alias('g') + ->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId, wa.nickname as ownerNickname, wa.avatar as ownerAvatar, wa.alias as ownerAlias') + ->join('wechat_account wa', 'g.ownerWechatId = wa.wechatId', 'LEFT') // 使用LEFT JOIN避免因群主不存在导致查询失败 ->whereIn('g.id', $groupIds) ->select(); } - - // 将群组信息添加到返回数据中 - $library['wechatGroupsOptions'] = $groupsInfo; - } else { - $library['wechatGroupsOptions'] = []; } return json([ @@ -433,22 +501,26 @@ class ContentLibraryController extends Controller $limit = $this->request->param('limit', 10); $libraryId = $this->request->param('libraryId', 0); $keyword = $this->request->param('keyword', ''); // 搜索关键词 + $companyId = $this->request->userInfo['companyId']; + $userId = $this->request->userInfo['id']; + $isAdmin = !empty($this->request->userInfo['isAdmin']); if (empty($libraryId)) { return json(['code' => 400, 'msg' => '内容库ID不能为空']); } - $where = [ + // 验证内容库权限 + $libraryWhere = [ ['id', '=', $libraryId], - ['companyId', '=', $this->request->userInfo['companyId']], + ['companyId', '=', $companyId], ['isDel', '=', 0] ]; - if (empty($this->request->userInfo['isAdmin'])) { - $where[] = ['userId', '=', $this->request->userInfo['id']]; + + if (!$isAdmin) { + $libraryWhere[] = ['userId', '=', $userId]; } - // 验证内容库权限 - $library = ContentLibrary::where($where)->find(); + $library = ContentLibrary::where($libraryWhere)->find(); if (empty($library)) { return json(['code' => 500, 'msg' => '内容库不存在或无权限访问']); @@ -460,60 +532,104 @@ class ContentLibraryController extends Controller ['isDel', '=', 0] ]; - // 关键词搜索 if (!empty($keyword)) { $where[] = ['content|title', 'like', '%' . $keyword . '%']; } + // 获取总数 + $total = ContentItem::where($where)->count(); + // 查询数据 $list = ContentItem::where($where) + ->field('id,libraryId,type,title,content,contentAi,contentType,resUrls,urls,friendId,wechatId,wechatChatroomId,createTime,createMomentTime,createMessageTime,coverImage') ->order('createMomentTime DESC,createTime DESC') ->page($page, $limit) ->select(); + // 收集需要查询的ID + $friendIds = []; + $chatroomIds = []; + $wechatIds = []; + + foreach ($list as $item) { + if ($item['type'] == 'moment' && !empty($item['friendId'])) { + $friendIds[] = $item['friendId']; + } else if ($item['type'] == 'group_message' && !empty($item['wechatChatroomId'])) { + $chatroomIds[] = $item['wechatChatroomId']; + if (!empty($item['wechatId'])) { + $wechatIds[] = $item['wechatId']; + } + } + } + + // 批量查询好友信息 + $friendInfoMap = []; + if (!empty($friendIds)) { + $friendIds = array_unique($friendIds); + $friendInfos = Db::table('s2_wechat_friend') + ->whereIn('id', $friendIds) + ->field('id, nickname, avatar') + ->select(); + + foreach ($friendInfos as $info) { + $friendInfoMap[$info['id']] = $info; + } + } + + // 批量查询群成员信息 + $memberInfoMap = []; + if (!empty($wechatIds)) { + $wechatIds = array_unique($wechatIds); + $memberInfos = Db::table('s2_wechat_chatroom_member') + ->whereIn('wechatId', $wechatIds) + ->field('wechatId, nickname, avatar') + ->select(); + + foreach ($memberInfos as $info) { + $memberInfoMap[$info['wechatId']] = $info; + } + } + // 处理数据 foreach ($list as &$item) { + // 使用AI内容(如果有) $item['content'] = !empty($item['contentAi']) ? $item['contentAi'] : $item['content']; - - // 处理资源URL + + // 处理JSON字段 $item['resUrls'] = json_decode($item['resUrls'] ?: '[]', true); $item['urls'] = json_decode($item['urls'] ?: '[]', true); - // 格式化时间 - //$item['createTime'] = date('Y-m-d H:i:s', $item['createTime']); if ($item['createMomentTime']) { $item['time'] = date('Y-m-d H:i:s', $item['createMomentTime']); - } - if ($item['createMessageTime']) { + } elseif ($item['createMessageTime']) { $item['time'] = date('Y-m-d H:i:s', $item['createMessageTime']); + } else { + $item['time'] = date('Y-m-d H:i:s', $item['createTime']); } - // 获取发送者信息 + // 设置发送者信息 + $item['senderNickname'] = ''; + $item['senderAvatar'] = ''; + + // 从映射表获取发送者信息 if ($item['type'] == 'moment' && !empty($item['friendId'])) { - $friendInfo = Db::table('s2_wechat_friend') - ->where('id', $item['friendId']) - ->field('nickname, avatar') - ->order('id desc') - ->find(); - $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'] = !empty($friendInfo['nickname']) ? $friendInfo['nickname'] : ''; - $item['senderAvatar'] = !empty($friendInfo['avatar']) ? $friendInfo['avatar'] : ''; + if (isset($friendInfoMap[$item['friendId']])) { + $friendInfo = $friendInfoMap[$item['friendId']]; + $item['senderNickname'] = $friendInfo['nickname'] ?? ''; + $item['senderAvatar'] = $friendInfo['avatar'] ?? ''; + } + } else if ($item['type'] == 'group_message' && !empty($item['wechatId'])) { + if (isset($memberInfoMap[$item['wechatId']])) { + $memberInfo = $memberInfoMap[$item['wechatId']]; + $item['senderNickname'] = $memberInfo['nickname'] ?? ''; + $item['senderAvatar'] = $memberInfo['avatar'] ?? ''; + } } unset($item['contentAi']); } - unset($item); - - // 获取总数 - $total = ContentItem::where($where)->count(); return json([ 'code' => 200, @@ -650,18 +766,28 @@ class ContentLibraryController extends Controller public function getItemDetail() { $id = $this->request->param('id', 0); + $userId = $this->request->userInfo['id']; + $isAdmin = !empty($this->request->userInfo['isAdmin']); + if (empty($id)) { return json(['code' => 400, 'msg' => '参数错误']); } + // 构建查询条件 + $where = [ + ['i.id', '=', $id], + ['i.isDel', '=', 0] + ]; + + // 非管理员只能查看自己的内容项 + if (!$isAdmin) { + $where[] = ['l.userId', '=', $userId]; + } + // 查询内容项目是否存在并检查权限 $item = ContentItem::alias('i') ->join('content_library l', 'i.libraryId = l.id') - ->where([ - ['i.id', '=', $id], - ['l.userId', '=', $this->request->userInfo['id']], - ['i.isDel', '=', 0] - ]) + ->where($where) ->field('i.*') ->find(); @@ -669,8 +795,7 @@ class ContentLibraryController extends Controller return json(['code' => 500, 'msg' => '内容项目不存在或无权限访问']); } - // 处理数据 - // 处理资源URL + // 处理JSON字段 $item['resUrls'] = json_decode($item['resUrls'] ?: '[]', true); $item['urls'] = json_decode($item['urls'] ?: '[]', true); @@ -687,34 +812,71 @@ class ContentLibraryController extends Controller $item['contentTypeName'] = $contentTypeMap[$item['contentType'] ?? 0] ?? '未知'; // 格式化时间 - if ($item['createMomentTime']) { - $item['createMomentTimeFormatted'] = date('Y-m-d H:i:s', $item['createMomentTime']); + if (!empty($item['createMomentTime']) && is_numeric($item['createMomentTime'])) { + $item['createMomentTimeFormatted'] = date('Y-m-d H:i:s', (int)$item['createMomentTime']); } - if ($item['createMessageTime']) { - $item['createMessageTimeFormatted'] = date('Y-m-d H:i:s', $item['createMessageTime']); + if (!empty($item['createMessageTime']) && is_numeric($item['createMessageTime'])) { + $item['createMessageTimeFormatted'] = date('Y-m-d H:i:s', (int)$item['createMessageTime']); + } + if (!empty($item['createTime']) && is_numeric($item['createTime'])) { + $item['createTimeFormatted'] = date('Y-m-d H:i:s', (int)$item['createTime']); } // 格式化发送时间 - if ($item['sendTime']) { - $item['sendTime'] = date('Y-m-d H:i:s', $item['sendTime']); + if (!empty($item['sendTime']) && is_numeric($item['sendTime'])) { + $item['sendTimeFormatted'] = date('Y-m-d H:i:s', (int)$item['sendTime']); + // 保持原字段兼容 + $item['sendTime'] = $item['sendTimeFormatted']; } - // 获取发送者信息 - if ($item['type'] == 'moment' && $item['friendId']) { + // 初始化发送者和群组信息 + $item['senderInfo'] = []; + $item['groupInfo'] = []; + + // 批量获取关联信息 + if ($item['type'] == 'moment' && !empty($item['friendId'])) { + // 获取朋友圈发送者信息 $friendInfo = Db::name('wechat_friendship') ->alias('wf') - ->join('wechat_account wa', 'wf.wechatId = wa.wechatId') + ->join('wechat_account wa', 'wf.wechatId = wa.wechatId', 'LEFT') ->where('wf.id', $item['friendId']) - ->field('wa.nickname, wa.avatar') + ->field('wf.id, wf.wechatId, wa.nickname, wa.avatar') ->find(); - $item['senderInfo'] = $friendInfo ?: []; - } elseif ($item['type'] == 'group_message' && $item['wechatChatroomId']) { + + if ($friendInfo) { + $item['senderInfo'] = $friendInfo; + } + } elseif ($item['type'] == 'group_message' && !empty($item['wechatChatroomId'])) { // 获取群组信息 $groupInfo = Db::name('wechat_group') ->where('id', $item['wechatChatroomId']) - ->field('name, avatar') + ->field('id, chatroomId, name, avatar, ownerWechatId') ->find(); - $item['groupInfo'] = $groupInfo ?: []; + + if ($groupInfo) { + $item['groupInfo'] = $groupInfo; + + // 如果有发送者信息,也获取发送者详情 + if (!empty($item['wechatId'])) { + $senderInfo = Db::name('wechat_chatroom_member') + ->where([ + 'chatroomId' => $groupInfo['chatroomId'], + 'wechatId' => $item['wechatId'] + ]) + ->field('wechatId, nickname, avatar') + ->find(); + + if ($senderInfo) { + $item['senderInfo'] = $senderInfo; + } + } + } + } + + // 如果有AI内容,添加到返回数据中 + if (!empty($item['contentAi'])) { + $item['contentOriginal'] = $item['content']; + $item['content'] = $item['contentAi']; } return json([ @@ -896,35 +1058,48 @@ class ContentLibraryController extends Controller // 查询条件:未删除且已开启的内容库 $where = [ ['isDel', '=', 0], // 未删除 - ['status', '=', 1], // 已开启 -// ['id', '=', 61], // 已开启 + ['status', '=', 1], // 已开启 ]; // 查询符合条件的内容库 $libraries = ContentLibrary::where($where) - ->field('id,name,sourceType,sourceFriends,sourceGroups,keywordInclude,keywordExclude,aiEnabled,aiPrompt,timeEnabled,timeStart,timeEnd,status,userId,companyId,createTime,updateTime,groupMembers') + ->field('id,name,sourceType,sourceFriends,sourceGroups,keywordInclude,keywordExclude,aiEnabled,aiPrompt,timeEnabled,timeStart,timeEnd,status,userId,companyId,createTime,updateTime,groupMembers,catchType') ->order('id', 'desc') ->select()->toArray(); if (empty($libraries)) { return json(['code' => 200, 'msg' => '没有可用的内容库配置']); } + $successCount = 0; $failCount = 0; $results = []; + $processedLibraries = 0; + $totalLibraries = count($libraries); + + // 预处理内容库数据 + foreach ($libraries as &$library) { + // 解析JSON字段 + $library['sourceFriends'] = json_decode($library['sourceFriends'] ?: '[]', true); + $library['sourceGroups'] = json_decode($library['sourceGroups'] ?: '[]', true); + $library['keywordInclude'] = json_decode($library['keywordInclude'] ?: '[]', true); + $library['keywordExclude'] = json_decode($library['keywordExclude'] ?: '[]', true); + $library['groupMembers'] = json_decode($library['groupMembers'] ?: '[]', true); + $library['catchType'] = json_decode($library['catchType'] ?: '[]', true); + } + unset($library); // 解除引用 // 处理每个内容库的采集任务 foreach ($libraries as $library) { try { - // 解析JSON字段 - $library['sourceFriends'] = json_decode($library['sourceFriends'] ?: '[]', true); - $library['sourceGroups'] = json_decode($library['sourceGroups'] ?: '[]', true); - $library['keywordInclude'] = json_decode($library['keywordInclude'] ?: '[]', true); - $library['keywordExclude'] = json_decode($library['keywordExclude'] ?: '[]', true); - $library['groupMembers'] = json_decode($library['groupMembers'] ?: '[]', true); - + $processedLibraries++; + // 根据数据来源类型执行不同的采集逻辑 - $collectResult = []; + $collectResult = [ + 'status' => 'skipped', + 'message' => '没有配置数据来源' + ]; + switch ($library['sourceType']) { case 1: // 好友类型 if (!empty($library['sourceFriends'])) { @@ -945,39 +1120,51 @@ class ContentLibraryController extends Controller ]; } + // 统计成功和失败数量 if ($collectResult['status'] == 'success') { $successCount++; - } else { + } elseif ($collectResult['status'] == 'failed' || $collectResult['status'] == 'error') { $failCount++; } + // 记录结果 $results[] = [ 'library_id' => $library['id'], 'library_name' => $library['name'], + 'source_type' => $library['sourceType'] == 1 ? '好友' : ($library['sourceType'] == 2 ? '群组' : '未知'), 'status' => $collectResult['status'], 'message' => $collectResult['message'] ?? '', 'data' => $collectResult['data'] ?? [] ]; + // 每处理5个内容库,释放一次内存 + if ($processedLibraries % 5 == 0 && $processedLibraries < $totalLibraries) { + gc_collect_cycles(); + } } catch (\Exception $e) { $failCount++; $results[] = [ 'library_id' => $library['id'], 'library_name' => $library['name'], + 'source_type' => $library['sourceType'] == 1 ? '好友' : ($library['sourceType'] == 2 ? '群组' : '未知'), 'status' => 'error', 'message' => $e->getMessage() ]; + + // 记录错误日志 + \think\facade\Log::error('内容库采集错误: ' . $e->getMessage() . ' [库ID: ' . $library['id'] . ']'); } } // 返回采集结果 - return json_encode([ + return json([ 'code' => 200, 'msg' => '采集任务执行完成', 'data' => [ - 'total' => count($libraries), + 'total' => $totalLibraries, 'success' => $successCount, 'fail' => $failCount, + 'skipped' => $totalLibraries - $successCount - $failCount, 'results' => $results ] ]); @@ -997,22 +1184,27 @@ class ContentLibraryController extends Controller 'message' => '没有指定要采集的好友' ]; } - $friendData = []; + try { + // 获取API配置 $toAccountId = ''; $username = Env::get('api.username2', ''); $password = Env::get('api.password2', ''); - if (!empty($username) || !empty($password)) { + $needFetch = false; + + // 检查是否需要主动获取朋友圈 + if (!empty($username) && !empty($password)) { $toAccountId = Db::name('users')->where('account', $username)->value('s2_accountId'); + $needFetch = !empty($toAccountId); } - - // 查询好友信息 + // 批量查询好友信息 $friends = Db::table('s2_wechat_friend') - ->field('id, wechatAccountId, wechatId,accountId') + ->field('id, wechatAccountId, wechatId, accountId, nickname, avatar') ->whereIn('id', $friendIds) ->where('isDeleted', 0) ->select(); + if (empty($friends)) { return [ 'status' => 'failed', @@ -1023,103 +1215,100 @@ class ContentLibraryController extends Controller // 从朋友圈采集内容 $collectedData = []; $totalMomentsCount = 0; - + $processedFriends = 0; + $totalFriends = count($friends); + + // 获取采集类型限制 + $catchTypes = $library['catchType'] ?? []; + foreach ($friends as $friend) { - $friendData = $friend; - if (!empty($username) && !empty($password)) { - //执行切换好友命令 - $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']]); - //采集完毕切换 - $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'], 'toAccountId' => $friend['accountId']], true); + $processedFriends++; + + // 如果配置了API并且需要主动获取朋友圈 + if ($needFetch) { + try { + // 执行切换好友命令 + $automaticAssign = new AutomaticAssign(); + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'], 'toAccountId' => $toAccountId], true); + + // 存入缓存 + $friendData = $friend; + $friendData['friendId'] = $friend['id']; + artificialAllotWechatFriend($friendData); + + // 执行采集朋友圈命令 + $webSocket = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]); + $webSocket->getMoments(['wechatFriendId' => $friend['id'], 'wechatAccountId' => $friend['wechatAccountId']]); + + // 采集完毕切换回原账号 + $automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'], 'toAccountId' => $friend['accountId']], true); + } catch (\Exception $e) { + \think\facade\Log::error('采集朋友圈失败: ' . $e->getMessage() . ' [好友ID: ' . $friend['id'] . ']'); + // 继续处理下一个好友,不中断整个流程 + } } // 从s2_wechat_moments表获取朋友圈数据 - $moments = Db::table('s2_wechat_moments') + $query = Db::table('s2_wechat_moments') ->where([ 'userName' => $friend['wechatId'], 'wechatAccountId' => $friend['wechatAccountId'] ]) - ->order('createTime', 'desc') - //->where('create_time', '>=', time() - 86400) - ->page(1, 20) - ->select(); - + ->order('createTime', 'desc'); + + // 如果启用了时间限制 + if ($library['timeEnabled'] && $library['timeStart'] > 0 && $library['timeEnd'] > 0) { + $query->whereBetween('createTime', [$library['timeStart'], $library['timeEnd']]); + } + + // 如果指定了采集类型,进行过滤 + if (!empty($catchTypes)) { + $query->whereIn('type', $catchTypes); + } + + // 获取最近20条朋友圈 + $moments = $query->page(1, 20)->select(); if (empty($moments)) { continue; } - // 获取好友详细信息 - $friendInfo = Db::table('s2_wechat_friend') - ->where('wechatId', $friend['wechatId']) - ->field('nickname, avatar') - ->find(); - - $nickname = $friendInfo['nickname'] ?? '未知好友'; + $nickname = $friend['nickname'] ?? '未知好友'; $friendMomentsCount = 0; + $filteredMoments = []; // 处理每条朋友圈数据 foreach ($moments as $moment) { // 处理关键词过滤 $content = $moment['content'] ?? ''; - - // 如果启用了关键词过滤 - $includeKeywords = $library['keywordInclude']; - $excludeKeywords = $library['keywordExclude']; - - // 检查是否包含必须关键词 - $includeMatch = empty($includeKeywords); - if (!empty($includeKeywords)) { - foreach ($includeKeywords as $keyword) { - if (strpos($content, $keyword) !== false) { - $includeMatch = true; - break; - } - } - } - - // 如果不满足包含条件,跳过 - if (!$includeMatch) { - continue; - } - - // 检查是否包含排除关键词 - $excludeMatch = false; - if (!empty($excludeKeywords)) { - foreach ($excludeKeywords as $keyword) { - if (strpos($content, $keyword) !== false) { - $excludeMatch = true; - break; - } - } - } - - // 如果满足排除条件,跳过 - if ($excludeMatch) { + + // 应用关键词过滤 + if (!$this->passKeywordFilter($content, $library['keywordInclude'], $library['keywordExclude'])) { continue; } // 如果启用了AI处理 if (!empty($library['aiEnabled']) && !empty($content)) { - $contentAi = $this->aiRewrite($library, $content); - if (!empty($content)) { - $moment['contentAi'] = $contentAi; - } else { + try { + $contentAi = $this->aiRewrite($library, $content); + if (!empty($contentAi)) { + $moment['contentAi'] = $contentAi; + } + } catch (\Exception $e) { + \think\facade\Log::error('AI处理失败: ' . $e->getMessage() . ' [朋友圈ID: ' . ($moment['id'] ?? 'unknown') . ']'); $moment['contentAi'] = ''; } } // 保存到内容库的content_item表 - $this->saveMomentToContentItem($moment, $library['id'], $friend, $nickname); - - $friendMomentsCount++; + if ($this->saveMomentToContentItem($moment, $library['id'], $friend, $nickname)) { + $friendMomentsCount++; + $filteredMoments[] = [ + 'id' => $moment['id'] ?? '', + 'content' => mb_substr($content, 0, 50) . (mb_strlen($content) > 50 ? '...' : ''), + 'time' => date('Y-m-d H:i:s', $moment['createTime'] ?? time()) + ]; + } } if ($friendMomentsCount > 0) { @@ -1127,14 +1316,19 @@ class ContentLibraryController extends Controller $collectedData[$friend['wechatId']] = [ 'friendId' => $friend['id'], 'nickname' => $nickname, - 'count' => $friendMomentsCount + 'count' => $friendMomentsCount, + 'samples' => array_slice($filteredMoments, 0, 3) // 只保留前3条示例 ]; $totalMomentsCount += $friendMomentsCount; } + + // 每处理5个好友,释放一次内存 + if ($processedFriends % 5 == 0 && $processedFriends < $totalFriends) { + gc_collect_cycles(); + } } - if (empty($collectedData)) { return [ 'status' => 'warning', @@ -1153,12 +1347,55 @@ class ContentLibraryController extends Controller ]; } catch (\Exception $e) { + \think\facade\Log::error('从好友采集朋友圈失败: ' . $e->getMessage() . ' [内容库ID: ' . ($library['id'] ?? 'unknown') . ']'); return [ 'status' => 'error', 'message' => '采集过程发生错误: ' . $e->getMessage() ]; } } + + /** + * 应用关键词过滤规则 + * @param string $content 内容文本 + * @param array $includeKeywords 包含关键词 + * @param array $excludeKeywords 排除关键词 + * @return bool 是否通过过滤 + */ + private function passKeywordFilter($content, $includeKeywords, $excludeKeywords) + { + // 如果内容为空,跳过 + if (empty($content)) { + return false; + } + + // 检查是否包含必须关键词 + $includeMatch = empty($includeKeywords); + if (!empty($includeKeywords)) { + foreach ($includeKeywords as $keyword) { + if (strpos($content, $keyword) !== false) { + $includeMatch = true; + break; + } + } + } + + // 如果不满足包含条件,跳过 + if (!$includeMatch) { + return false; + } + + // 检查是否包含排除关键词 + if (!empty($excludeKeywords)) { + foreach ($excludeKeywords as $keyword) { + if (strpos($content, $keyword) !== false) { + return false; // 包含排除关键词,不通过过滤 + } + } + } + + return true; // 通过所有过滤条件 + } /** * 从群组采集消息内容