1111
This commit is contained in:
@@ -7,6 +7,7 @@ use app\chukebao\model\FriendSettings;
|
||||
use library\ResponseHelper;
|
||||
use think\Db;
|
||||
use think\facade\Env;
|
||||
use think\facade\Cache;
|
||||
use app\common\service\AuthService;
|
||||
|
||||
class MessageController extends BaseController
|
||||
@@ -30,174 +31,221 @@ class MessageController extends BaseController
|
||||
return ResponseHelper::error('请先登录');
|
||||
}
|
||||
|
||||
$friends = Db::table('s2_wechat_friend')
|
||||
->where(['accountId' => $accountId, 'isDeleted' => 0])
|
||||
->column('id,nickname,avatar,conRemark,labels,groupId,wechatAccountId,wechatId,extendFields,phone,region,isTop');
|
||||
// 缓存键
|
||||
$cacheKeyFriends = 'message_list_friends_' . $accountId;
|
||||
$cacheKeyChatrooms = 'message_list_chatrooms_' . $accountId;
|
||||
$cacheKeyMessages = 'message_list_messages_' . $accountId;
|
||||
|
||||
// 缓存时间:好友和群聊信息5分钟,消息列表30秒
|
||||
$cacheTimeFriends = 300; // 5分钟
|
||||
$cacheTimeChatrooms = 300; // 5分钟
|
||||
$cacheTimeMessages = 30; // 30秒
|
||||
|
||||
// 从缓存获取好友ID列表
|
||||
$friendIds = Cache::get($cacheKeyFriends . '_ids');
|
||||
if ($friendIds === false) {
|
||||
$ids = Db::table('s2_wechat_friend')
|
||||
->where(['accountId' => $accountId, 'isDeleted' => 0])
|
||||
->column('id');
|
||||
$friendIds = empty($ids) ? [0] : $ids; // 避免 IN 查询为空
|
||||
Cache::set($cacheKeyFriends . '_ids', $friendIds, $cacheTimeFriends);
|
||||
}
|
||||
|
||||
// 构建好友子查询
|
||||
$friendSubQuery = Db::table('s2_wechat_friend')
|
||||
->where(['accountId' => $accountId, 'isDeleted' => 0])
|
||||
->field('id')
|
||||
->buildSql();
|
||||
// 从缓存获取好友信息
|
||||
$friends = Cache::get($cacheKeyFriends);
|
||||
if ($friends === false) {
|
||||
$friends = Db::table('s2_wechat_friend')
|
||||
->where(['accountId' => $accountId, 'isDeleted' => 0])
|
||||
->column('id,nickname,avatar,conRemark,labels,groupId,wechatAccountId,wechatId,extendFields,phone,region,isTop');
|
||||
Cache::set($cacheKeyFriends, $friends, $cacheTimeFriends);
|
||||
}
|
||||
|
||||
// 计算总数:群聊数量 + 好友数量
|
||||
// 使用与 UNION 查询相同的逻辑来计算总数
|
||||
$countQuery = "
|
||||
SELECT COUNT(*) as total FROM (
|
||||
(SELECT DISTINCT wc.id
|
||||
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 DISTINCT m.wechatFriendId as id
|
||||
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}
|
||||
)
|
||||
) as combined
|
||||
";
|
||||
$totalResult = Db::query($countQuery);
|
||||
$total = !empty($totalResult) ? (int)$totalResult[0]['total'] : 0;
|
||||
// 从缓存获取群聊信息
|
||||
$chatrooms = Cache::get($cacheKeyChatrooms);
|
||||
if ($chatrooms === false) {
|
||||
$chatrooms = Db::table('s2_wechat_chatroom')
|
||||
->where(['accountId' => $accountId, 'isDeleted' => 0])
|
||||
->column('id,nickname,chatroomAvatar,chatroomId,isTop');
|
||||
Cache::set($cacheKeyChatrooms, $chatrooms, $cacheTimeChatrooms);
|
||||
}
|
||||
|
||||
// 优化后的查询:使用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}
|
||||
";
|
||||
// 优化:分别查询群聊和好友的最新消息,使用缓存
|
||||
// 从缓存获取最新消息列表(短时间缓存,保证消息实时性)
|
||||
$allMessages = Cache::get($cacheKeyMessages);
|
||||
if ($allMessages === false) {
|
||||
// 获取群聊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) {
|
||||
return $b['wechatTime'] <=> $a['wechatTime'];
|
||||
});
|
||||
// 合并结果并排序
|
||||
$allMessages = array_merge($chatroomMessages, $friendMessages);
|
||||
usort($allMessages, function ($a, $b) {
|
||||
return $b['wechatTime'] <=> $a['wechatTime'];
|
||||
});
|
||||
|
||||
// 存入缓存
|
||||
Cache::set($cacheKeyMessages, $allMessages, $cacheTimeMessages);
|
||||
}
|
||||
|
||||
// 批量统计未读数量(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' => $list, 'total' => $total]);
|
||||
|
||||
return ResponseHelper::success(['list' => $list, 'total' => $totalCount]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user