内容库优化

This commit is contained in:
wong
2025-11-19 15:28:24 +08:00
parent 5faf83e437
commit 0912a0067e

View File

@@ -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; // 通过所有过滤条件
}
/**
* 从群组采集消息内容