Compare commits

...

4 Commits

Author SHA1 Message Date
huxuejian
6878ad5834 Merge remote-tracking branch 'origin/dev-wdb' 2026-02-09 15:18:01 +08:00
62b03f8343 no message 2026-02-09 14:07:55 +08:00
91db27cca7 Merge commit 'cecb26e762fe652537571972fecca17a576e7cf1' into dev-wdb 2026-02-09 09:19:28 +08:00
1058af4f84 no message 2026-02-09 09:18:33 +08:00
6 changed files with 285 additions and 69 deletions

View File

@ -1,6 +1,6 @@
// SCSS 变量定义
$font-size-text: 28rpx;
$font-size-tip: 24rpx;
$font-size-text: 30rpx;
$font-size-tip: 28rpx;
$font-size-title: 32rpx;
$text-color-sub: #999;
$primary-color: #0877F1;
@ -15,7 +15,8 @@ $primary-color: #0877F1;
/* 患者信息栏样式 */
.patient-info-bar {
position: relative;
position: sticky;
top: 0;
background: #fff;
border-bottom: 1rpx solid #f0f0f0;
padding: 20rpx 32rpx;
@ -112,6 +113,7 @@ $primary-color: #0877F1;
flex: 1;
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto;
min-height: 0;
}
@ -356,7 +358,7 @@ $primary-color: #0877F1;
}
.message-text {
font-size: $font-size-text;
font-size: 30rpx;
line-height: 1.4;
word-wrap: break-word;
word-break: break-all;

View File

@ -524,6 +524,7 @@ const initTIMCallbacks = async () => {
})
.then(() => {
console.log("✓ 收到新消息后已标记为已读");
// tabBar
})
.catch((error) => {
console.error("✗ 标记已读失败:", error);
@ -677,6 +678,7 @@ const loadMessageList = async () => {
})
.then(() => {
console.log("✓ 会话已标记为已读:", chatInfo.value.conversationID);
// tabBar
})
.catch((error) => {
console.error("✗ 标记会话已读失败:", error);
@ -825,6 +827,12 @@ onShow(() => {
checkLoginAndInitTIM();
} else if (timChatManager.tim && !timChatManager.isLoggedIn) {
timChatManager.ensureIMConnection();
} else if (timChatManager.tim && timChatManager.isLoggedIn && chatInfo.value.conversationID) {
messageList.value = [];
isCompleted.value = false;
lastFirstMessageId.value = "";
loadMessageList();
}
startIMMonitoring(30000);

View File

@ -1,5 +1,10 @@
<template>
<view class="message-page">
<!-- 标题栏 -->
<view class="message-header">
<text class="header-title">咨询</text>
</view>
<!-- 消息列表 -->
<scroll-view
class="message-list"
@ -49,7 +54,7 @@
</view>
<view class="message-preview">
<text class="preview-text">{{
conversation.lastMessage || "暂无消息"
cleanMessageText(conversation.lastMessage) || "暂无消息"
}}</text>
</view>
</view>
@ -75,7 +80,7 @@
</template>
<script setup>
import { ref } from "vue";
import { ref, computed } from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import { storeToRefs } from "pinia";
import useAccountStore from "@/store/account.js";
@ -98,6 +103,57 @@ const refreshing = ref(false);
//
const { loadGroupAvatars, getAvatarList } = useGroupAvatars();
//
const totalUnreadCount = computed(() => {
return conversationList.value.reduce(
(sum, conv) => sum + (conv.unreadCount || 0),
0
);
});
//
const updateUnreadBadgeImmediately = async () => {
try {
if (!globalTimChatManager || !globalTimChatManager.tim) {
console.warn("TIM实例不存在无法更新徽章");
return;
}
const response = await globalTimChatManager.tim.getConversationList();
if (!response || !response.data || !response.data.conversationList) {
console.warn("获取会话列表返回数据异常");
return;
}
//
const totalUnreadCount = response.data.conversationList
.filter(
(conv) => conv.conversationID && conv.conversationID.startsWith("GROUP")
)
.reduce((sum, conv) => sum + (conv.unreadCount || 0), 0);
try {
if (totalUnreadCount > 0) {
uni.setTabBarBadge({
index: 1,
text: totalUnreadCount > 99 ? "99+" : String(totalUnreadCount),
});
console.log("已更新 tabBar 徽章:", totalUnreadCount);
} else {
uni.setTabBarBadge({
index: 1,
text: "",
});
console.log("已清除 tabBar 徽章");
}
} catch (badgeError) {
console.error("更新TabBar徽章失败:", badgeError);
}
} catch (error) {
console.error("更新未读徽章失败:", error);
}
};
// IM
const initIM = async () => {
console.log("=== message.vue initIM 开始 ===");
@ -110,22 +166,12 @@ const initIM = async () => {
);
if (!isIMInitialized.value) {
uni.showLoading({
title: "连接中...",
});
console.log("开始调用 initIMAfterLogin");
const success = await initIMAfterLogin();
console.log("initIMAfterLogin 返回:", success);
uni.hideLoading();
if (!success) {
console.error("initIMAfterLogin 失败");
uni.showToast({
title: "IM连接失败请重试",
icon: "none",
});
console.log("initIMAfterLogin 失败,跳过 IM 初始化");
return false;
}
@ -141,14 +187,10 @@ const initIM = async () => {
);
} else if (globalTimChatManager && !globalTimChatManager.isLoggedIn) {
console.log("IM 已初始化但未登录,尝试重连");
uni.showLoading({
title: "重连中...",
});
const reconnected = await globalTimChatManager.ensureIMConnection();
uni.hideLoading();
if (!reconnected) {
console.error("重连失败");
console.log("重连失败");
return false;
}
}
@ -167,19 +209,22 @@ const loadConversationList = async () => {
// IM TIM
if (!globalTimChatManager) {
throw new Error("IM管理器未初始化");
console.log("IM管理器未初始化跳过加载");
return;
}
if (!globalTimChatManager.tim) {
console.error("TIM实例不存在尝试重新初始化");
console.log("TIM实例不存在尝试重新初始化");
const imReady = await initIM();
if (!imReady || !globalTimChatManager.tim) {
throw new Error("TIM实例初始化失败");
console.log("TIM实例初始化失败跳过加载");
return;
}
}
if (!globalTimChatManager.getGroupList) {
throw new Error("getGroupList 方法不存在");
console.log("getGroupList 方法不存在,跳过加载");
return;
}
// getGroupListSDK
@ -198,18 +243,10 @@ const loadConversationList = async () => {
//
await loadGroupAvatars(conversationList.value);
} else {
console.error("加载群聊列表失败:", result);
uni.showToast({
title: "加载失败,请重试",
icon: "none",
});
console.log("加载群聊列表失败或返回数据为空");
}
} catch (error) {
console.error("加载会话列表失败:", error);
uni.showToast({
title: error.message || "加载失败,请重试",
icon: "none",
});
console.log("加载会话列表异常:", error.message);
} finally {
loading.value = false;
}
@ -221,11 +258,9 @@ let updateTimer = null;
//
const setupConversationListener = () => {
if (!globalTimChatManager) return;
//
globalTimChatManager.setCallback("onConversationListUpdated", (eventData) => {
console.log("会话列表更新事件:", eventData);
//
if (eventData && !Array.isArray(eventData) && eventData.conversationID) {
const conversationID = eventData.conversationID;
@ -414,16 +449,13 @@ const formatMessageTime = (timestamp) => {
};
//
const handleClickConversation = (conversation) => {
const handleClickConversation = async (conversation) => {
console.log("点击会话:", conversation);
//
const conversationIndex = conversationList.value.findIndex(
(conv) => conv.conversationID === conversation.conversationID
);
if (conversationIndex !== -1) {
conversationList.value[conversationIndex].unreadCount = 0;
console.log("已清空本地未读数:", conversation.name);
}
//
@ -459,24 +491,26 @@ onLoad(() => {
console.log("消息列表页面加载");
});
//
const cleanMessageText = (text) => {
if (!text) return "";
return text.replace(/[\r\n]+/g, " ").trim();
};
//
onShow(async () => {
try {
console.log("消息列表页面显示,开始初始化");
// IM
const imReady = await initIM();
if (!imReady) initIMAfterLogin();
if (!imReady) {
console.log("IM初始化失败继续加载列表");
}
//
await loadConversationList();
//
setupConversationListener();
} catch (error) {
console.error("页面初始化失败:", error);
uni.showToast({
title: error.message || "初始化失败,请重试",
icon: "none",
});
console.log("页面初始化异常:", error.message);
}
});
@ -487,8 +521,6 @@ onHide(() => {
clearTimeout(updateTimer);
updateTimer = null;
}
//
if (globalTimChatManager) {
globalTimChatManager.setCallback("onConversationListUpdated", null);
globalTimChatManager.setCallback("onMessageReceived", null);
@ -501,11 +533,46 @@ onHide(() => {
width: 100%;
height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
}
.message-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 32rpx;
background-color: #fff;
border-bottom: 1rpx solid #f0f0f0;
}
.header-title {
font-size: 36rpx;
font-weight: 600;
color: #000;
}
.total-unread-badge {
min-width: 40rpx;
height: 40rpx;
padding: 0 12rpx;
background-color: #ff4d4f;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.badge-text {
font-size: 24rpx;
color: #fff;
font-weight: 600;
line-height: 1;
}
.message-list {
flex: 1;
width: 100%;
height: 100%;
}
.loading-container,

View File

@ -58,7 +58,7 @@ export default defineStore("accountStore", () => {
// 使用 openid 作为 userID 初始化 IM
const userID = openid.value || uni.getStorageSync('openid');
if (!userID) {
console.error('无法获取 openidIM 初始化失败');
console.log('未获取到有效的 userId跳过 IM 初始化');
return false;
}
@ -66,13 +66,13 @@ export default defineStore("accountStore", () => {
const success = await initGlobalTIM(userID);
if (!success) {
console.error('initGlobalTIM 返回失败');
console.log('initGlobalTIM 返回失败,跳过 IM 初始化');
return false;
}
// 验证 TIM 实例是否真正创建成功
if (!globalTimChatManager || !globalTimChatManager.tim) {
console.error('IM 初始化后 TIM 实例不存在');
console.log('IM 初始化后 TIM 实例不存在,跳过 IM 初始化');
return false;
}
@ -80,7 +80,7 @@ export default defineStore("accountStore", () => {
console.log('IM 初始化成功');
return true;
} catch (error) {
console.error('IM初始化失败:', error);
console.log('IM初始化异常跳过 IM 初始化:', error.message);
return false;
}
}

View File

@ -0,0 +1,135 @@
import { globalTimChatManager } from './tim-chat.js';
/**
* 全局未读消息监听管理器
* 负责监听会话列表更新和消息接收事件实时更新 tabBar 徽章
*/
class GlobalUnreadListenerManager {
constructor() {
this.isInitialized = false;
this.originalConversationListCallback = null;
this.originalMessageReceivedCallback = null;
}
/**
* 初始化全局未读消息监听
* 监听会话列表更新消息接收和消息已读事件
*/
setup() {
if (this.isInitialized) {
console.warn('全局未读消息监听已初始化,跳过重复初始化');
return;
}
if (!globalTimChatManager) {
console.warn('globalTimChatManager 未初始化');
return;
}
// 保存原始回调(在覆盖前保存)
this.originalConversationListCallback = globalTimChatManager.callbacks.onConversationListUpdated;
this.originalMessageReceivedCallback = globalTimChatManager.callbacks.onMessageReceived;
console.log('保存原始回调:', {
hasConversationListCallback: !!this.originalConversationListCallback,
hasMessageReceivedCallback: !!this.originalMessageReceivedCallback
});
// 监听会话列表更新事件(包括消息接收和已读状态变化)
globalTimChatManager.setCallback('onConversationListUpdated', (eventData) => {
console.log('onConversationListUpdated 触发,调用原始回调');
// 调用原始回调(如果存在)
if (this.originalConversationListCallback && typeof this.originalConversationListCallback === 'function') {
this.originalConversationListCallback(eventData);
}
// 更新 tabBar 徽章
this.updateTabBarBadge();
});
// 监听消息接收事件
globalTimChatManager.setCallback('onMessageReceived', (message) => {
console.log('onMessageReceived 触发,调用原始回调');
// 调用原始回调(如果存在)
if (this.originalMessageReceivedCallback && typeof this.originalMessageReceivedCallback === 'function') {
this.originalMessageReceivedCallback(message);
}
// 更新 tabBar 徽章
this.updateTabBarBadge();
});
this.isInitialized = true;
console.log('全局未读消息监听已设置');
}
/**
* 更新 tabBar 徽章
* 获取所有群聊会话的未读数并更新对应的 tabBar 徽章
*/
async updateTabBarBadge() {
try {
if (!globalTimChatManager || !globalTimChatManager.tim) {
console.warn('globalTimChatManager 或 tim 未初始化');
return;
}
const response = await globalTimChatManager.tim.getConversationList();
if (!response || !response.data || !response.data.conversationList) {
console.warn('获取会话列表返回数据异常');
return;
}
const totalUnreadCount = this.calculateGroupUnreadCount(response.data.conversationList);
this.setTabBarBadge(totalUnreadCount);
} catch (error) {
console.error('更新 tabBar 徽章失败:', error);
}
}
/**
* 计算群聊会话的总未读数
* @param {Array} conversationList - 会话列表
* @returns {number} 总未读数
*/
calculateGroupUnreadCount(conversationList) {
return conversationList
.filter((conv) => conv.conversationID && conv.conversationID.startsWith('GROUP'))
.reduce((sum, conv) => sum + (conv.unreadCount || 0), 0);
}
/**
* 设置 tabBar 徽章
* @param {number} count - 未读数
* @param {number} tabIndex - tabBar 索引默认为 1消息页
*/
setTabBarBadge(count, tabIndex = 1) {
if (count > 0) {
uni.setTabBarBadge({
index: tabIndex,
text: count > 99 ? '99+' : String(count)
});
console.log(`已更新 tabBar 徽章(索引 ${tabIndex}:`, count);
} else {
// uni.removeTabBarBadge({
// index: tabIndex
// });
console.log(`已移除 tabBar 徽章(索引 ${tabIndex}`);
}
}
async refreshBadge() {
console.log('手动刷新 tabBar 徽章');
await this.updateTabBarBadge();
}
/**
* 清除监听可选
*/
destroy() {
this.isInitialized = false;
console.log('全局未读消息监听已清除');
}
}
// 导出单例
export const globalUnreadListenerManager = new GlobalUnreadListenerManager();

View File

@ -193,7 +193,12 @@ class TimChatManager {
// 获取用户信息并登录
console.log('开始获取用户信息并登录...')
await this.getUserInfoAndLogin(userID)
const loginSuccess = await this.getUserInfoAndLogin(userID)
if (!loginSuccess) {
console.log('获取用户信息失败,跳过 IM 初始化')
await this.cleanupOldInstance()
return false
}
console.log('用户信息获取并登录成功')
// 等待SDK Ready
@ -206,11 +211,7 @@ class TimChatManager {
return true
} catch (error) {
console.error('=== IM初始化失败 ===', error)
console.error('错误详情:', error.message || error)
console.error('错误堆栈:', error.stack)
this.triggerCallback('onError', `初始化失败: ${error.message || error}`)
console.log('=== IM初始化异常 ===', error.message)
// 初始化失败时清理资源
console.log('初始化失败,开始清理资源...')
await this.cleanupOldInstance()
@ -390,7 +391,8 @@ class TimChatManager {
console.log('本地存储的 userInfo:', userInfo)
if (!userInfo?.userID) {
throw new Error('未找到用户信息,请先登录')
console.log('未找到用户信息,跳过 IM 初始化')
return false
}
this.currentUserID = userInfo.userID
console.log('从本地存储获取到 userID:', this.currentUserID)
@ -403,11 +405,10 @@ class TimChatManager {
console.log('开始登录 TIM...')
await this.loginTIM()
console.log('TIM 登录成功')
return true
} catch (error) {
console.error('获取用户信息失败:', error)
console.error('错误详情:', error.message || error)
this.triggerCallback('onError', `登录失败: ${error.message || error}`)
throw error // 重新抛出错误,让调用者知道登录失败
console.log('获取用户信息异常:', error.message)
return false
}
}
@ -2739,11 +2740,14 @@ class TimChatManager {
conversationID: formattedConversationID,
unreadCount: 0
})
} catch (error) {
console.error('✗ 标记会话已读异常:', error)
}
}
// 更新会话列表
updateConversationListOnNewMessage(message) {
try {