1、豆包新增生成图片功能

2、消息优化
3、场景获客新增全局配置
4、工作台新增全局配置
This commit is contained in:
wong
2026-01-15 14:31:12 +08:00
parent 1566f8fb7c
commit a20794366a
17 changed files with 1287 additions and 158 deletions

View File

@@ -30,143 +30,191 @@ class MessageController extends BaseController
return ResponseHelper::error('请先登录');
}
// 直接查询好友ID列表
$ids = Db::table('s2_wechat_friend')
->where(['accountId' => $accountId, 'isDeleted' => 0])
->column('id');
$friendIds = empty($ids) ? [0] : $ids; // 避免 IN 查询为空
// 直接查询好友信息
$friends = Db::table('s2_wechat_friend')
->where(['accountId' => $accountId, 'isDeleted' => 0])
->column('id,nickname,avatar,conRemark,labels,groupId,wechatAccountId,wechatId,extendFields,phone,region,isTop');
// 构建好友子查询
$friendSubQuery = Db::table('s2_wechat_friend')
// 直接查询群聊信息
$chatrooms = Db::table('s2_wechat_chatroom')
->where(['accountId' => $accountId, 'isDeleted' => 0])
->field('id')
->buildSql();
->column('id,nickname,chatroomAvatar,chatroomId,isTop');
// 优化后的查询使用MySQL兼容的查询方式
$unionQuery = "
(SELECT m.id, m.content, m.wechatFriendId, m.wechatChatroomId, m.createTime, m.wechatTime,m.wechatAccountId, 2 as msgType, wc.nickname, wc.chatroomAvatar as avatar, wc.chatroomId, wc.isTop
FROM s2_wechat_chatroom wc
INNER JOIN s2_wechat_message m ON wc.id = m.wechatChatroomId AND m.type = 2
INNER JOIN (
SELECT wechatChatroomId, MAX(wechatTime) as maxTime, MAX(id) as maxId
FROM s2_wechat_message
WHERE type = 2
GROUP BY wechatChatroomId
) latest ON m.wechatChatroomId = latest.wechatChatroomId AND m.wechatTime = latest.maxTime AND m.id = latest.maxId
WHERE wc.accountId = {$accountId} AND wc.isDeleted = 0
)
UNION ALL
(SELECT m.id, m.content, m.wechatFriendId, m.wechatChatroomId, m.createTime, m.wechatTime, 1 as msgType, 1 as nickname, 1 as avatar, 1 as chatroomId, 1 as wechatAccountId, 0 as isTop
FROM s2_wechat_message m
INNER JOIN (
SELECT wechatFriendId, MAX(wechatTime) as maxTime, MAX(id) as maxId
FROM s2_wechat_message
WHERE type = 1 AND wechatFriendId IN {$friendSubQuery}
GROUP BY wechatFriendId
) latest ON m.wechatFriendId = latest.wechatFriendId AND m.wechatTime = latest.maxTime AND m.id = latest.maxId
WHERE m.type = 1 AND m.wechatFriendId IN {$friendSubQuery}
)
ORDER BY wechatTime DESC
LIMIT " . (($page - 1) * $limit) . ", {$limit}
";
// 获取群聊ID列表
$chatroomIds = array_keys($chatrooms);
if (empty($chatroomIds)) {
$chatroomIds = [0];
}
// 1. 查询群聊最新消息
$chatroomMessages = [];
if (!empty($chatroomIds) && $chatroomIds[0] != 0) {
$chatroomIdsStr = implode(',', array_map('intval', $chatroomIds));
$chatroomLatestQuery = "
SELECT wc.id as chatroomId, m.id, m.content, m.wechatChatroomId, m.createTime, m.wechatTime, m.wechatAccountId,
wc.nickname, wc.chatroomAvatar as avatar, wc.chatroomId, wc.isTop, 2 as msgType
FROM s2_wechat_chatroom wc
INNER JOIN (
SELECT wechatChatroomId, MAX(wechatTime) as maxTime, MAX(id) as maxId
FROM s2_wechat_message
WHERE type = 2 AND wechatChatroomId IN ({$chatroomIdsStr})
GROUP BY wechatChatroomId
) latest ON wc.id = latest.wechatChatroomId
INNER JOIN s2_wechat_message m ON m.wechatChatroomId = latest.wechatChatroomId
AND m.wechatTime = latest.maxTime AND m.id = latest.maxId
WHERE wc.accountId = {$accountId} AND wc.isDeleted = 0
";
$chatroomMessages = Db::query($chatroomLatestQuery);
}
$list = Db::query($unionQuery);
// 2. 查询好友最新消息
$friendMessages = [];
if (!empty($friendIds) && $friendIds[0] != 0) {
$friendIdsStr = implode(',', array_map('intval', $friendIds));
$friendLatestQuery = "
SELECT m.wechatFriendId, m.id, m.content, m.createTime, m.wechatTime,
f.wechatAccountId, 1 as msgType, 0 as isTop
FROM s2_wechat_message m
INNER JOIN (
SELECT wechatFriendId, MAX(wechatTime) as maxTime, MAX(id) as maxId
FROM s2_wechat_message
WHERE type = 1 AND wechatFriendId IN ({$friendIdsStr})
GROUP BY wechatFriendId
) latest ON m.wechatFriendId = latest.wechatFriendId
AND m.wechatTime = latest.maxTime AND m.id = latest.maxId
INNER JOIN s2_wechat_friend f ON f.id = m.wechatFriendId
WHERE m.type = 1 AND m.wechatFriendId IN ({$friendIdsStr})
";
$friendMessages = Db::query($friendLatestQuery);
}
// 对分页后的结果进行排序按wechatTime降序
usort($list, function ($a, $b) {
// 合并结果并排序
$allMessages = array_merge($chatroomMessages, $friendMessages);
usort($allMessages, function ($a, $b) {
return $b['wechatTime'] <=> $a['wechatTime'];
});
// 批量统计未读数量isRead=0按好友/群聊分别聚合
$friendIds = [];
$chatroomIds = [];
// 计算总数
$totalCount = count($allMessages);
// 分页处理
$list = array_slice($allMessages, ($page - 1) * $limit, $limit);
// 收集需要查询的ID
$queryFriendIds = [];
$queryChatroomIds = [];
foreach ($list as $row) {
if (!empty($row['wechatFriendId'])) {
$friendIds[] = $row['wechatFriendId'];
$queryFriendIds[] = $row['wechatFriendId'];
}
if (!empty($row['wechatChatroomId'])) {
$chatroomIds[] = $row['wechatChatroomId'];
$queryChatroomIds[] = $row['wechatChatroomId'];
}
}
$friendIds = array_values(array_unique(array_filter($friendIds)));
$chatroomIds = array_values(array_unique(array_filter($chatroomIds)));
$queryFriendIds = array_unique($queryFriendIds);
$queryChatroomIds = array_unique($queryChatroomIds);
$friendUnreadMap = [];
if (!empty($friendIds)) {
// 获取未读消息数量
$friendUnreadMap = Db::table('s2_wechat_message')
->where(['isRead' => 0])
->whereIn('wechatFriendId', $friendIds)
// 批量查询未读数量(优化:合并查询)
$unreadMap = [];
if (!empty($queryFriendIds)) {
$friendUnreads = Db::table('s2_wechat_message')
->where(['isRead' => 0, 'type' => 1])
->whereIn('wechatFriendId', $queryFriendIds)
->field('wechatFriendId, COUNT(*) as cnt')
->group('wechatFriendId')
->column('COUNT(*) AS cnt', 'wechatFriendId');
->select();
foreach ($friendUnreads as $item) {
$unreadMap['friend_' . $item['wechatFriendId']] = (int)$item['cnt'];
}
}
$chatroomUnreadMap = [];
if (!empty($chatroomIds)) {
// 获取未读消息数量
$chatroomUnreadMap = Db::table('s2_wechat_message')
->where(['isRead' => 0])
->whereIn('wechatChatroomId', $chatroomIds)
if (!empty($queryChatroomIds)) {
$chatroomUnreads = Db::table('s2_wechat_message')
->where(['isRead' => 0, 'type' => 2])
->whereIn('wechatChatroomId', $queryChatroomIds)
->field('wechatChatroomId, COUNT(*) as cnt')
->group('wechatChatroomId')
->column('COUNT(*) AS cnt', 'wechatChatroomId');
->select();
foreach ($chatroomUnreads as $item) {
$unreadMap['chatroom_' . $item['wechatChatroomId']] = (int)$item['cnt'];
}
}
// 批量查询AI类型
$aiTypeData = [];
if (!empty($friendIds)) {
$aiTypeData = FriendSettings::where('friendId', 'in', $friendIds)->column('friendId,type');
if (!empty($queryFriendIds)) {
$aiTypeData = FriendSettings::where('friendId', 'in', $queryFriendIds)->column('friendId,type');
}
// 格式化数据
foreach ($list as $k => &$v) {
$createTime = !empty($v['createTime']) ? date('Y-m-d H:i:s', $v['createTime']) : '';
$wechatTime = !empty($v['wechatTime']) ? date('Y-m-d H:i:s', $v['wechatTime']) : '';
$unreadCount = 0;
$v['aiType'] = 0;
if (!empty($v['wechatFriendId'])) {
$v['nickname'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['nickname'] : '';
$v['avatar'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['avatar'] : '';
$v['conRemark'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['conRemark'] : '';
$v['groupId'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['groupId'] : '';
$v['wechatAccountId'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['wechatAccountId'] : '';
$v['wechatId'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['wechatId'] : '';
$v['extendFields'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['extendFields'] : [];
$v['region'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['region'] : '';
$v['phone'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['phone'] : '';
$v['isTop'] = !empty($friends[$v['wechatFriendId']]) ? $friends[$v['wechatFriendId']]['isTop'] : 0;
$v['labels'] = !empty($friends[$v['wechatFriendId']]) ? json_decode($friends[$v['wechatFriendId']]['labels'], true) : [];
// 好友消息
$friendId = $v['wechatFriendId'];
$friend = $friends[$friendId] ?? null;
$v['nickname'] = $friend['nickname'] ?? '';
$v['avatar'] = $friend['avatar'] ?? '';
$v['conRemark'] = $friend['conRemark'] ?? '';
$v['groupId'] = $friend['groupId'] ?? '';
$v['wechatAccountId'] = $friend['wechatAccountId'] ?? '';
$v['wechatId'] = $friend['wechatId'] ?? '';
$v['extendFields'] = $friend['extendFields'] ?? [];
$v['region'] = $friend['region'] ?? '';
$v['phone'] = $friend['phone'] ?? '';
$v['isTop'] = $friend['isTop'] ?? 0;
$v['labels'] = !empty($friend['labels']) ? json_decode($friend['labels'], true) : [];
$unreadCount = isset($friendUnreadMap[$v['wechatFriendId']]) ? (int)$friendUnreadMap[$v['wechatFriendId']] : 0;
$v['aiType'] = isset($aiTypeData[$v['wechatFriendId']]) ? $aiTypeData[$v['wechatFriendId']] : 0;
$unreadCount = $unreadMap['friend_' . $friendId] ?? 0;
$v['aiType'] = $aiTypeData[$friendId] ?? 0;
$v['id'] = $friendId;
unset($v['chatroomId']);
}
if (!empty($v['wechatChatroomId'])) {
} elseif (!empty($v['wechatChatroomId'])) {
// 群聊消息
$chatroomId = $v['wechatChatroomId'];
$chatroom = $chatrooms[$chatroomId] ?? null;
$v['nickname'] = $chatroom['nickname'] ?? '';
$v['avatar'] = $chatroom['chatroomAvatar'] ?? '';
$v['conRemark'] = '';
$unreadCount = isset($chatroomUnreadMap[$v['wechatChatroomId']]) ? (int)$chatroomUnreadMap[$v['wechatChatroomId']] : 0;
$v['isTop'] = $chatroom['isTop'] ?? 0;
$v['chatroomId'] = $chatroom['chatroomId'] ?? '';
$unreadCount = $unreadMap['chatroom_' . $chatroomId] ?? 0;
$v['id'] = $chatroomId;
unset($v['wechatFriendId']);
}
$v['id'] = !empty($v['wechatFriendId']) ? $v['wechatFriendId'] : $v['wechatChatroomId'];
$v['config'] = [
'top' => !empty($v['isTop']) ? true : false,
'unreadCount' => $unreadCount,
'chat' => true,
'msgTime' => $v['wechatTime'],
'msgTime' => $wechatTime,
];
$v['createTime'] = $createTime;
$v['lastUpdateTime'] = $wechatTime;
// 最新消息内容已经在UNION查询中获取直接使用
$v['latestMessage'] = [
'content' => $v['content'],
'content' => $v['content'] ?? '',
'wechatTime' => $wechatTime
];
unset($v['wechatFriendId'], $v['wechatChatroomId'],$v['isTop']);
unset($v['wechatChatroomId'], $v['isTop'], $v['msgType']);
}
unset($v);
return ResponseHelper::success($list);
return ResponseHelper::success(['list' => $list, 'total' => $totalCount]);
}