内容库优化
This commit is contained in:
@@ -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; // 通过所有过滤条件
|
||||
}
|
||||
|
||||
/**
|
||||
* 从群组采集消息内容
|
||||
|
||||
Reference in New Issue
Block a user