Compare commits

...

8 Commits

7 changed files with 377 additions and 160 deletions

View File

@ -1,6 +1,7 @@
<script>
import dbStore from "@/store/db";
import accountStore from "@/store/account";
import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js";
export default {
async onLaunch() {
@ -38,6 +39,8 @@ export default {
const success = await account.initIMAfterLogin();
if (success) {
console.log("IM 初始化成功");
// IM
globalUnreadListenerManager.setup();
} else {
console.warn("IM 初始化失败");
}

View File

@ -6,17 +6,24 @@ $text-color-sub: #999;
$primary-color: #0877F1;
.chat-page {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
height: 100vh;
background-color: #f5f5f5;
overflow: hidden;
transition: padding-bottom 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 患者信息栏样式 */
.patient-info-bar {
position: sticky;
position: fixed;
top: 0;
left: 0;
right: 0;
background: #fff;
border-bottom: 1rpx solid #f0f0f0;
padding: 20rpx 32rpx;
@ -110,11 +117,15 @@ $primary-color: #0877F1;
}
.chat-content {
flex: 1;
position: fixed;
top: 100rpx; /* 患者信息栏高度,根据实际调整 */
left: 0;
right: 0;
bottom: 120rpx; /* 输入框高度,根据实际调整 */
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto;
min-height: 0;
transition: bottom 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.chat-content-compressed {
@ -379,18 +390,24 @@ $primary-color: #0877F1;
}
.input-section {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #fff;
border-top: 1rpx solid #e0e0e0;
position: relative;
z-index: 200;
padding-bottom: env(safe-area-inset-bottom);
flex-shrink: 0;
transform: translateZ(0); /* 开启硬件加速,提升性能 */
transition: bottom 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
will-change: bottom;
}
.input-toolbar {
display: flex;
align-items: center;
padding: 16rpx 20rpx;
padding: 12rpx 20rpx;
padding-bottom: env(safe-area-inset-bottom);
gap: 12rpx;
}
@ -496,7 +513,8 @@ $primary-color: #0877F1;
justify-content: flex-start;
background: #fff;
border-top: 1rpx solid #eee;
padding: 20rpx 0 40rpx 60rpx;
padding: 20rpx 0 20rpx 60rpx;
padding-bottom: env(safe-area-inset-bottom);
gap: 40rpx 50rpx;
flex-wrap: wrap;
background-color: #f5f5f5;

View File

@ -1,5 +1,5 @@
<template>
<view class="input-section">
<view class="input-section" :style="{ bottom: props.keyboardHeight + 'px' }">
<view class="input-toolbar">
<view @click="toggleVoiceInput" class="voice-toggle-btn">
<image v-if="showVoiceInput" src="/static/jianpan.png" class="voice-toggle-icon" mode="aspectFit"></image>
@ -8,7 +8,7 @@
<view class="input-area">
<textarea v-if="!showVoiceInput" class="text-input" v-model="inputText" placeholder="我来说两句..."
@confirm="sendTextMessage" @focus="handleInputFocus" @input="handleInput"
:auto-height="true" :show-confirm-bar="false" :adjust-position="true" :cursor-spacing="40" />
:auto-height="true" :show-confirm-bar="false" :adjust-position="false" :hold-keyboard="true" />
<input v-else class="voice-input-btn" :class="{ recording: isRecording }" @touchstart="startRecord"
@touchmove="onRecordTouchMove" @touchend="stopRecord" @touchcancel="cancelRecord" :placeholder="isRecording ? '松开发送' : '按住说话'" disabled>
</input>
@ -77,6 +77,7 @@ const props = defineProps({
groupId: { type: String, default: '' },
userId: { type: String, default: '' },
corpId: { type: String, default: '' },
keyboardHeight: { type: Number, default: 0 },
});
// Emits
@ -150,11 +151,15 @@ const initRecorderManager = () => {
const sendTextMessage = async () => {
if (!inputText.value.trim()) return;
await sendMessage("text", inputText.value);
const textToSend = inputText.value;
inputText.value = "";
//
uni.hideKeyboard();
await sendMessage("text", textToSend);
//
nextTick(() => {
// hold-keyboard
});
};

View File

@ -1,5 +1,6 @@
<template>
<view class="chat-page">
<page-meta :page-style="'overflow:' + (keyboardHeight > 0 ? 'hidden' : 'visible')"></page-meta>
<view class="chat-page" :style="{ paddingBottom: keyboardHeight + 'px' }">
<!-- 患者信息栏 -->
<view class="patient-info-bar" v-if="patientInfo.name">
<view class="patient-info-content">
@ -22,6 +23,7 @@
<!-- 聊天消息区域 -->
<scroll-view
class="chat-content"
:style="{ bottom: (keyboardHeight > 0 ? keyboardHeight + 60 : 60) + 'px' }"
scroll-y="true"
enhanced="true"
bounces="false"
@ -146,6 +148,7 @@
"
:userId="openid"
:corpId="corpId.value"
:keyboardHeight="keyboardHeight"
@scrollToBottom="() => scrollToBottom(true)"
@messageSent="() => scrollToBottom(true)"
/>
@ -158,6 +161,7 @@ import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import { storeToRefs } from "pinia";
import useAccountStore from "@/store/account.js";
import { globalTimChatManager } from "@/utils/tim-chat.js";
import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js";
import {
startIMMonitoring,
stopIMMonitoring,
@ -212,6 +216,9 @@ const chatInfo = ref({
avatar: "/static/home/avatar.svg",
});
//
const keyboardHeight = ref(0);
//
const isEvaluationPopupOpen = ref(false);
@ -442,6 +449,22 @@ onLoad((options) => {
chatInfo.value.userID = options.userID;
}
//
uni.onKeyboardHeightChange((res) => {
console.log("键盘高度变化:", res.height);
const oldHeight = keyboardHeight.value;
keyboardHeight.value = res.height;
// 00
if (oldHeight === 0 && res.height > 0) {
nextTick(() => {
setTimeout(() => {
scrollToBottom(true);
}, 100);
});
}
});
checkLoginAndInitTIM();
updateNavigationTitle();
});
@ -527,9 +550,10 @@ const initTIMCallbacks = async () => {
.setMessageRead({
conversationID: chatInfo.value.conversationID,
})
.then(() => {
.then(async () => {
console.log("✓ 收到新消息后已标记为已读");
// tabBar
// tabBar
await globalUnreadListenerManager.refreshBadge();
})
.catch((error) => {
console.error("✗ 标记已读失败:", error);
@ -680,9 +704,10 @@ const loadMessageList = async () => {
.setMessageRead({
conversationID: chatInfo.value.conversationID,
})
.then(() => {
.then(async () => {
console.log("✓ 会话已标记为已读:", chatInfo.value.conversationID);
// tabBar
// tabBar
await globalUnreadListenerManager.refreshBadge();
})
.catch((error) => {
console.error("✗ 标记会话已读失败:", error);
@ -845,6 +870,11 @@ onHide(() => {
// ID
timChatManager.currentConversationID = null;
console.log("✓ 页面隐藏已清空当前会话ID");
// tabBar
if (globalUnreadListenerManager.isInitialized) {
globalUnreadListenerManager.refreshBadge();
}
});
//
@ -990,6 +1020,9 @@ const handleApplyConsult = async () => {
onUnmounted(() => {
clearMessageCache();
//
uni.offKeyboardHeightChange();
timChatManager.setCallback("onSDKReady", null);
timChatManager.setCallback("onSDKNotReady", null);
timChatManager.setCallback("onMessageReceived", null);

View File

@ -76,12 +76,13 @@
</template>
<script setup>
import { ref, computed } from "vue";
import { ref, computed, onUnmounted } from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import { storeToRefs } from "pinia";
import useAccountStore from "@/store/account.js";
import { globalTimChatManager } from "@/utils/tim-chat.js";
import { mergeConversationWithGroupDetails } from "@/utils/conversation-merger.js";
import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js";
import useGroupAvatars from "./hooks/use-group-avatars.js";
import GroupAvatar from "@/components/group-avatar.vue";
@ -251,125 +252,143 @@ const loadConversationList = async () => {
//
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;
//
const handleConversationListUpdate = async (eventData) => {
console.log("【消息列表页】会话列表更新事件:", eventData);
//
if (eventData && !Array.isArray(eventData) && eventData.conversationID) {
const conversationID = eventData.conversationID;
const existingIndex = conversationList.value.findIndex(
(conv) => conv.conversationID === conversationID
);
if (existingIndex !== -1) {
//
if (eventData.unreadCount !== undefined) {
conversationList.value[existingIndex].unreadCount =
eventData.unreadCount;
console.log(
`【消息列表页】已更新会话未读数: ${conversationList.value[existingIndex].name}, unreadCount: ${eventData.unreadCount}`
);
}
//
if (eventData.lastMessage) {
conversationList.value[existingIndex].lastMessage = eventData.lastMessage.messageForShow || '';
conversationList.value[existingIndex].lastMessageTime = eventData.lastMessage.lastTime || Date.now();
//
conversationList.value.sort((a, b) => b.lastMessageTime - a.lastMessageTime);
}
}
return;
}
// eventData
if (!eventData || !Array.isArray(eventData)) {
console.warn("【消息列表页】会话列表更新事件数据格式错误");
return;
}
//
if (updateTimer) {
clearTimeout(updateTimer);
}
updateTimer = setTimeout(async () => {
//
const groupConversations = eventData.filter(
(conv) => conv.conversationID && conv.conversationID.startsWith("GROUP")
);
console.log(`【消息列表页】收到 ${groupConversations.length} 个群聊会话更新`);
// 使 TimChatManager
const formattedConversations = groupConversations.map((conv) =>
globalTimChatManager.formatConversationData(conv)
);
//
const mergedConversations = await mergeConversationWithGroupDetails(
formattedConversations
);
if (!mergedConversations || mergedConversations.length === 0) {
console.log("【消息列表页】合并后的会话数据为空,跳过更新");
return;
}
let needSort = false;
//
mergedConversations.forEach((conversationData) => {
const conversationID = conversationData.conversationID;
const existingIndex = conversationList.value.findIndex(
(conv) => conv.conversationID === conversationID
);
if (existingIndex !== -1) {
//
if (eventData.unreadCount !== undefined) {
conversationList.value[existingIndex].unreadCount =
eventData.unreadCount;
const existing = conversationList.value[existingIndex];
//
if (
existing.lastMessage !== conversationData.lastMessage ||
existing.lastMessageTime !== conversationData.lastMessageTime ||
existing.unreadCount !== conversationData.unreadCount
) {
//
conversationList.value[existingIndex] = {
...conversationData,
//
avatar: existing.avatar || conversationData.avatar,
// 使 TIM SDK
unreadCount: conversationData.unreadCount || 0
};
needSort = true;
console.log(
`已清空会话未读数: ${conversationList.value[existingIndex].name}, unreadCount: ${eventData.unreadCount}`
`【消息列表页】已更新会话: ${conversationData.name}, unreadCount: ${conversationList.value[existingIndex].unreadCount}`
);
}
} else {
//
conversationList.value.push(conversationData);
needSort = true;
console.log(`【消息列表页】已添加新会话: ${conversationData.name}`);
}
return;
}
});
// eventData
if (!eventData || !Array.isArray(eventData)) {
console.warn("会话列表更新事件数据格式错误");
return;
}
//
if (updateTimer) {
clearTimeout(updateTimer);
}
updateTimer = setTimeout(async () => {
//
const groupConversations = eventData.filter(
(conv) => conv.conversationID && conv.conversationID.startsWith("GROUP")
//
if (needSort) {
conversationList.value.sort(
(a, b) => b.lastMessageTime - a.lastMessageTime
);
}
}, 100); // 100ms
};
console.log(`收到 ${groupConversations.length} 个群聊会话更新`);
//
const handleMessageReceived = (message) => {
console.log("【消息列表页】收到新消息:", message);
// TIM SDK onConversationListUpdated
//
};
// 使 TimChatManager
const formattedConversations = groupConversations.map((conv) =>
globalTimChatManager.formatConversationData(conv)
);
//
const mergedConversations = await mergeConversationWithGroupDetails(
formattedConversations
);
if (!mergedConversations || mergedConversations.length === 0) {
console.log("合并后的会话数据为空,跳过更新");
return;
}
let needSort = false;
//
mergedConversations.forEach((conversationData) => {
const conversationID = conversationData.conversationID;
const existingIndex = conversationList.value.findIndex(
(conv) => conv.conversationID === conversationID
);
if (existingIndex !== -1) {
const existing = conversationList.value[existingIndex];
//
if (
existing.lastMessage !== conversationData.lastMessage ||
existing.lastMessageTime !== conversationData.lastMessageTime ||
existing.unreadCount !== conversationData.unreadCount
) {
//
conversationList.value[existingIndex] = {
...conversationData,
//
avatar: existing.avatar || conversationData.avatar,
// 使 TIM SDK 使 Math.max
// unreadCount N 0
unreadCount: conversationData.unreadCount || 0
};
needSort = true;
console.log(
`已更新会话: ${conversationData.name}, unreadCount: ${conversationList.value[existingIndex].unreadCount}`
);
}
} else {
//
conversationList.value.push(conversationData);
needSort = true;
console.log(`已添加新会话: ${conversationData.name}`);
}
});
//
if (needSort) {
conversationList.value.sort(
(a, b) => b.lastMessageTime - a.lastMessageTime
);
}
}, 100); // 100ms
});
//
globalTimChatManager.setCallback("onMessageReceived", (message) => {
console.log("消息列表页面收到新消息:", message);
//
// TIM SDK onConversationListUpdated
// +1
//
// onConversationListUpdated
//
});
//
const setupConversationListener = () => {
if (!globalTimChatManager) return;
console.log("【消息列表页】设置会话监听器");
//
//
if (globalUnreadListenerManager.isInitialized) {
globalUnreadListenerManager.addCallback("onConversationListUpdated", handleConversationListUpdate);
globalUnreadListenerManager.addCallback("onMessageReceived", handleMessageReceived);
console.log("【消息列表页】已添加回调到全局监听器回调链");
} else {
console.warn("【消息列表页】全局未读监听器未初始化,使用直接回调方式");
//
globalTimChatManager.setCallback("onConversationListUpdated", handleConversationListUpdate);
globalTimChatManager.setCallback("onMessageReceived", handleMessageReceived);
}
};
//
@ -417,6 +436,8 @@ const formatMessageTime = (timestamp) => {
//
const handleClickConversation = async (conversation) => {
console.log("点击会话:", conversation);
//
const conversationIndex = conversationList.value.findIndex(
(conv) => conv.conversationID === conversation.conversationID
);
@ -424,6 +445,21 @@ const handleClickConversation = async (conversation) => {
conversationList.value[conversationIndex].unreadCount = 0;
}
//
if (globalTimChatManager && globalTimChatManager.tim) {
try {
await globalTimChatManager.tim.setMessageRead({
conversationID: conversation.conversationID,
});
console.log("✓ 已标记会话为已读:", conversation.conversationID);
// tabBar
await globalUnreadListenerManager.refreshBadge();
} catch (error) {
console.error("✗ 标记会话已读失败:", error);
}
}
//
uni.navigateTo({
url: `/pages/message/index?conversationID=${conversation.conversationID}&groupID=${conversation.groupID}`,
@ -477,19 +513,42 @@ const cleanMessageText = (text) => {
//
onShow(async () => {
// tabBar
if (globalUnreadListenerManager.isInitialized) {
await globalUnreadListenerManager.refreshBadge();
}
});
//
onHide(() => {
console.log("【消息列表页】页面隐藏");
//
if (updateTimer) {
clearTimeout(updateTimer);
updateTimer = null;
}
if (globalTimChatManager) {
globalTimChatManager.setCallback("onConversationListUpdated", null);
globalTimChatManager.setCallback("onMessageReceived", null);
// globalTimChatManager
//
//
});
//
onUnmounted(() => {
console.log("【消息列表页】页面卸载,清理回调");
//
if (updateTimer) {
clearTimeout(updateTimer);
updateTimer = null;
}
//
if (globalUnreadListenerManager.isInitialized) {
globalUnreadListenerManager.removeCallback("onConversationListUpdated", handleConversationListUpdate);
globalUnreadListenerManager.removeCallback("onMessageReceived", handleMessageReceived);
console.log("【消息列表页】已从回调链移除回调");
}
});
</script>

View File

@ -3,6 +3,7 @@ import { defineStore } from "pinia";
import api from '@/utils/api';
import { toast } from '@/utils/widget';
import { initGlobalTIM, globalTimChatManager } from "@/utils/tim-chat.js";
import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js";
const env = __VITE_ENV__;
export default defineStore("accountStore", () => {
@ -76,6 +77,10 @@ export default defineStore("accountStore", () => {
isIMInitialized.value = true;
console.log('IM 初始化成功');
// IM 初始化成功后,设置全局未读消息监听
globalUnreadListenerManager.setup();
return true;
} catch (error) {
console.log('IM初始化异常跳过 IM 初始化:', error.message);
@ -91,6 +96,11 @@ export default defineStore("accountStore", () => {
await globalTimChatManager.destroy();
console.log('腾讯IM退出成功');
}
// 清除全局未读监听
if (globalUnreadListenerManager.isInitialized) {
globalUnreadListenerManager.destroy();
}
} catch (error) {
console.error('退出腾讯IM失败:', error);
}
@ -103,6 +113,11 @@ export default defineStore("accountStore", () => {
// 清除本地存储
uni.removeStorageSync('account');
uni.removeStorageSync('openid');
// 清除 tabBar 徽章
uni.removeTabBarBadge({
index: 1
});
}
async function getExternalUserId(corpId) {

View File

@ -7,8 +7,11 @@ import { globalTimChatManager } from './tim-chat.js';
class GlobalUnreadListenerManager {
constructor() {
this.isInitialized = false;
this.originalConversationListCallback = null;
this.originalMessageReceivedCallback = null;
this.callbackChain = {
onConversationListUpdated: [],
onMessageReceived: []
};
this.updateTimer = null; // 防抖定时器
}
/**
@ -25,39 +28,76 @@ class GlobalUnreadListenerManager {
return;
}
// 保存原始回调(在覆盖前保存)
this.originalConversationListCallback = globalTimChatManager.callbacks.onConversationListUpdated;
this.originalMessageReceivedCallback = globalTimChatManager.callbacks.onMessageReceived;
// 保存原始回调到回调链
const originalConversationListCallback = globalTimChatManager.callbacks.onConversationListUpdated;
const originalMessageReceivedCallback = globalTimChatManager.callbacks.onMessageReceived;
console.log('保存原始回调:', {
hasConversationListCallback: !!this.originalConversationListCallback,
hasMessageReceivedCallback: !!this.originalMessageReceivedCallback
if (originalConversationListCallback && typeof originalConversationListCallback === 'function') {
this.callbackChain.onConversationListUpdated.push(originalConversationListCallback);
}
if (originalMessageReceivedCallback && typeof originalMessageReceivedCallback === 'function') {
this.callbackChain.onMessageReceived.push(originalMessageReceivedCallback);
}
console.log('全局未读监听初始化,回调链长度:', {
onConversationListUpdated: this.callbackChain.onConversationListUpdated.length,
onMessageReceived: this.callbackChain.onMessageReceived.length
});
// 监听会话列表更新事件(包括消息接收和已读状态变化)
globalTimChatManager.setCallback('onConversationListUpdated', (eventData) => {
console.log('onConversationListUpdated 触发,调用原始回调');
// 调用原始回调(如果存在)
if (this.originalConversationListCallback && typeof this.originalConversationListCallback === 'function') {
this.originalConversationListCallback(eventData);
}
// 更新 tabBar 徽章
this.updateTabBarBadge();
console.log('【全局未读监听】onConversationListUpdated 触发,回调链长度:', this.callbackChain.onConversationListUpdated.length);
// 执行回调链中的所有回调
this.callbackChain.onConversationListUpdated.forEach((callback, index) => {
try {
console.log(`【全局未读监听】执行回调链 #${index + 1}`);
callback(eventData);
} catch (error) {
console.error(`【全局未读监听】执行 onConversationListUpdated 回调 #${index + 1} 失败:`, error);
}
});
// 防抖更新 tabBar 徽章
this.debouncedUpdateTabBarBadge();
});
// 监听消息接收事件
globalTimChatManager.setCallback('onMessageReceived', (message) => {
console.log('onMessageReceived 触发,调用原始回调');
// 调用原始回调(如果存在)
if (this.originalMessageReceivedCallback && typeof this.originalMessageReceivedCallback === 'function') {
this.originalMessageReceivedCallback(message);
}
// 更新 tabBar 徽章
this.updateTabBarBadge();
console.log('【全局未读监听】onMessageReceived 触发,回调链长度:', this.callbackChain.onMessageReceived.length);
// 执行回调链中的所有回调
this.callbackChain.onMessageReceived.forEach((callback, index) => {
try {
console.log(`【全局未读监听】执行回调链 #${index + 1}`);
callback(message);
} catch (error) {
console.error(`【全局未读监听】执行 onMessageReceived 回调 #${index + 1} 失败:`, error);
}
});
// 防抖更新 tabBar 徽章
this.debouncedUpdateTabBarBadge();
});
this.isInitialized = true;
console.log('全局未读消息监听已设置');
// 初始化时立即更新一次徽章
this.updateTabBarBadge();
}
/**
* 防抖更新 tabBar 徽章
* 避免频繁更新导致性能问题
*/
debouncedUpdateTabBarBadge() {
if (this.updateTimer) {
clearTimeout(this.updateTimer);
}
this.updateTimer = setTimeout(() => {
this.updateTabBarBadge();
}, 200); // 减少到 200ms 防抖延迟,提高响应速度
}
/**
@ -67,21 +107,22 @@ class GlobalUnreadListenerManager {
async updateTabBarBadge() {
try {
if (!globalTimChatManager || !globalTimChatManager.tim) {
console.warn('globalTimChatManager 或 tim 未初始化');
console.warn('【全局未读监听】globalTimChatManager 或 tim 未初始化');
return;
}
const response = await globalTimChatManager.tim.getConversationList();
if (!response || !response.data || !response.data.conversationList) {
console.warn('获取会话列表返回数据异常');
console.warn('【全局未读监听】获取会话列表返回数据异常');
return;
}
const totalUnreadCount = this.calculateGroupUnreadCount(response.data.conversationList);
console.log('【全局未读监听】计算总未读数:', totalUnreadCount);
this.setTabBarBadge(totalUnreadCount);
} catch (error) {
console.error('更新 tabBar 徽章失败:', error);
console.error('【全局未读监听】更新 tabBar 徽章失败:', error);
}
}
@ -107,25 +148,68 @@ class GlobalUnreadListenerManager {
index: tabIndex,
text: count > 99 ? '99+' : String(count)
});
console.log(`已更新 tabBar 徽章(索引 ${tabIndex}:`, count);
console.log(`已更新 tabBar 徽章(索引 ${tabIndex}:`, count);
} else {
// uni.removeTabBarBadge({
// index: tabIndex
// });
console.log(`已移除 tabBar 徽章(索引 ${tabIndex}`);
uni.removeTabBarBadge({
index: tabIndex
});
console.log(`已移除 tabBar 徽章(索引 ${tabIndex}`);
}
}
/**
* 手动刷新徽章
* 用于页面显示时强制刷新
*/
async refreshBadge() {
console.log('手动刷新 tabBar 徽章');
await this.updateTabBarBadge();
}
/**
* 添加回调到回调链
* @param {string} eventName - 事件名称
* @param {Function} callback - 回调函数
*/
addCallback(eventName, callback) {
if (this.callbackChain[eventName] && typeof callback === 'function') {
// 避免重复添加同一个回调
if (!this.callbackChain[eventName].includes(callback)) {
this.callbackChain[eventName].push(callback);
console.log(`✓ 已添加回调到 ${eventName} 回调链,当前链长度:`, this.callbackChain[eventName].length);
} else {
console.log(`⚠️ 回调已存在于 ${eventName} 回调链中,跳过添加`);
}
}
}
/**
* 从回调链中移除回调
* @param {string} eventName - 事件名称
* @param {Function} callback - 回调函数
*/
removeCallback(eventName, callback) {
if (this.callbackChain[eventName]) {
const index = this.callbackChain[eventName].indexOf(callback);
if (index > -1) {
this.callbackChain[eventName].splice(index, 1);
console.log(`✓ 已从 ${eventName} 回调链移除回调,当前链长度:`, this.callbackChain[eventName].length);
}
}
}
/**
* 清除监听可选
*/
destroy() {
if (this.updateTimer) {
clearTimeout(this.updateTimer);
this.updateTimer = null;
}
this.callbackChain = {
onConversationListUpdated: [],
onMessageReceived: []
};
this.isInitialized = false;
console.log('全局未读消息监听已清除');
}