|
@@ -0,0 +1,487 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * 基于 WebSocket + 腾讯 IM 的用户在线状态管理器
|
|
|
|
|
+ * 核心思路:
|
|
|
|
|
+ * 1. 利用腾讯 IM SDK 感知自身和好友的 IM 连接状态
|
|
|
|
|
+ * 2. 通过 WebSocket 向服务端上报 IM 状态变更
|
|
|
|
|
+ * 3. 通过 WebSocket 接收服务端推送的其他用户状态变更
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+import timManager from './tim-manager.js';
|
|
|
|
|
+
|
|
|
|
|
+class TIMPresenceManager {
|
|
|
|
|
+ constructor() {
|
|
|
|
|
+ this.ws = null;
|
|
|
|
|
+ this.heartbeatTimer = null;
|
|
|
|
|
+ this.reconnectTimer = null;
|
|
|
|
|
+ this.heartbeatInterval = 30000; // 30秒心跳
|
|
|
|
|
+ this.reconnectInterval = 5000; // 5秒重连
|
|
|
|
|
+ this.isConnected = false;
|
|
|
|
|
+ this.userId = null;
|
|
|
|
|
+ this.statusCallbacks = new Map(); // 存储状态变化回调
|
|
|
|
|
+ this.onlineStatusCache = new Map(); // 缓存在线状态
|
|
|
|
|
+
|
|
|
|
|
+ // WebSocket服务器地址
|
|
|
|
|
+ this.wsUrl = 'ws://localhost:8083/ws/chat';
|
|
|
|
|
+
|
|
|
|
|
+ // TIM 状态监听器引用(用于清理)
|
|
|
|
|
+ this.timStatusListener = null;
|
|
|
|
|
+ this.timConnectListener = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 初始化并连接
|
|
|
|
|
+ * @param {String} userId 当前用户ID
|
|
|
|
|
+ */
|
|
|
|
|
+ async init(userId) {
|
|
|
|
|
+ if (this.isConnected || !userId) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.userId = userId;
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 建立 WebSocket 连接
|
|
|
|
|
+ this.connectWebSocket();
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 监听 TIM 连接状态变更
|
|
|
|
|
+ this.listenTIMConnectionStatus();
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 监听 TIM 用户状态更新
|
|
|
|
|
+ this.listenTIMUserStatus();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 建立 WebSocket 连接
|
|
|
|
|
+ */
|
|
|
|
|
+ connectWebSocket() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.ws = uni.connectSocket({
|
|
|
|
|
+ url: `${this.wsUrl}?userId=${this.userId}`,
|
|
|
|
|
+ success: () => {
|
|
|
|
|
+ console.log('🔌 WebSocket连接请求已发送');
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.error('❌ WebSocket连接失败:', err);
|
|
|
|
|
+ this.scheduleReconnect();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 监听连接打开
|
|
|
|
|
+ uni.onSocketOpen(() => {
|
|
|
|
|
+ console.log('✅ WebSocket已连接');
|
|
|
|
|
+ this.isConnected = true;
|
|
|
|
|
+ this.startHeartbeat();
|
|
|
|
|
+
|
|
|
|
|
+ // 连接成功后,立即上报当前 TIM 连接状态
|
|
|
|
|
+ this.reportCurrentTIMStatus();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 监听消息
|
|
|
|
|
+ uni.onSocketMessage((res) => {
|
|
|
|
|
+ this.handleMessage(res.data);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 监听错误
|
|
|
|
|
+ uni.onSocketError((err) => {
|
|
|
|
|
+ console.error('❌ WebSocket错误:', err);
|
|
|
|
|
+ this.isConnected = false;
|
|
|
|
|
+ this.scheduleReconnect();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 监听关闭
|
|
|
|
|
+ uni.onSocketClose(() => {
|
|
|
|
|
+ console.log('🔌 WebSocket已关闭');
|
|
|
|
|
+ this.isConnected = false;
|
|
|
|
|
+ this.stopHeartbeat();
|
|
|
|
|
+ this.scheduleReconnect();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ WebSocket连接异常:', error);
|
|
|
|
|
+ this.scheduleReconnect();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 监听 TIM 连接状态变更
|
|
|
|
|
+ */
|
|
|
|
|
+ listenTIMConnectionStatus() {
|
|
|
|
|
+ if (!timManager.tim) {
|
|
|
|
|
+ console.warn('⚠️ TIM 未初始化,无法监听连接状态');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const TIM = timManager.tim.TIM;
|
|
|
|
|
+
|
|
|
|
|
+ // 监听 IM 连接状态变化
|
|
|
|
|
+ this.timConnectListener = (event) => {
|
|
|
|
|
+ console.log('📡 TIM 连接状态变更:', event.data.state);
|
|
|
|
|
+
|
|
|
|
|
+ let imStatus = 'offline';
|
|
|
|
|
+
|
|
|
|
|
+ // 映射 TIM 状态到业务状态
|
|
|
|
|
+ switch (event.data.state) {
|
|
|
|
|
+ case TIM.TYPES.NET_STATE_CONNECTED:
|
|
|
|
|
+ imStatus = 'online';
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TIM.TYPES.NET_STATE_DISCONNECTED:
|
|
|
|
|
+ case TIM.TYPES.NET_STATE_CONNECTING:
|
|
|
|
|
+ imStatus = 'offline';
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 通过 WebSocket 上报状态给服务端
|
|
|
|
|
+ this.reportIMStatus(imStatus);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ timManager.tim.on(TIM.EVENT.NET_STATE_CHANGE, this.timConnectListener);
|
|
|
|
|
+ console.log('✅ 已监听 TIM 连接状态变更');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 监听 TIM 用户状态更新(好友状态)
|
|
|
|
|
+ */
|
|
|
|
|
+ listenTIMUserStatus() {
|
|
|
|
|
+ if (!timManager.tim) {
|
|
|
|
|
+ console.warn('⚠️ TIM 未初始化,无法监听用户状态');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const TIM = timManager.tim.TIM;
|
|
|
|
|
+
|
|
|
|
|
+ // 监听用户状态更新事件
|
|
|
|
|
+ this.timStatusListener = (event) => {
|
|
|
|
|
+ console.log('👥 收到 TIM 用户状态更新:', event.data);
|
|
|
|
|
+
|
|
|
|
|
+ const { userStatusList } = event.data;
|
|
|
|
|
+
|
|
|
|
|
+ if (userStatusList && userStatusList.length > 0) {
|
|
|
|
|
+ userStatusList.forEach(item => {
|
|
|
|
|
+ const userId = item.userID;
|
|
|
|
|
+ const status = item.statusType === TIM.TYPES.USER_STATUS_ONLINE ? 'online' : 'offline';
|
|
|
|
|
+
|
|
|
|
|
+ // 更新本地缓存
|
|
|
|
|
+ this.onlineStatusCache.set(String(userId), status === 'online');
|
|
|
|
|
+
|
|
|
|
|
+ // 通知状态变化
|
|
|
|
|
+ this.notifyStatusChange(String(userId), status);
|
|
|
|
|
+
|
|
|
|
|
+ // 也可以通过 WS 上报给服务端,保证服务端状态一致
|
|
|
|
|
+ this.reportFriendStatus(userId, status);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ timManager.tim.on(TIM.EVENT.USER_STATUS_UPDATED, this.timStatusListener);
|
|
|
|
|
+ console.log('✅ 已监听 TIM 用户状态更新');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 上报当前 TIM 连接状态
|
|
|
|
|
+ */
|
|
|
|
|
+ reportCurrentTIMStatus() {
|
|
|
|
|
+ if (!timManager.isLogin) {
|
|
|
|
|
+ this.reportIMStatus('offline');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // TIM 已登录,上报在线状态
|
|
|
|
|
+ this.reportIMStatus('online');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 上报 IM 状态给服务端
|
|
|
|
|
+ * @param {String} status 状态:online/offline
|
|
|
|
|
+ */
|
|
|
|
|
+ reportIMStatus(status) {
|
|
|
|
|
+ if (!this.isConnected) {
|
|
|
|
|
+ console.warn('⚠️ WebSocket 未连接,无法上报 IM 状态');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.sendMessage({
|
|
|
|
|
+ type: 'imStatusReport',
|
|
|
|
|
+ userId: this.userId,
|
|
|
|
|
+ status: status,
|
|
|
|
|
+ device: 'mobile', // 设备类型
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`📤 已上报 IM 状态: ${status}`);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 上报好友状态给服务端
|
|
|
|
|
+ * @param {String} friendUserId 好友用户ID
|
|
|
|
|
+ * @param {String} status 状态:online/offline
|
|
|
|
|
+ */
|
|
|
|
|
+ reportFriendStatus(friendUserId, status) {
|
|
|
|
|
+ if (!this.isConnected) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.sendMessage({
|
|
|
|
|
+ type: 'friendStatusReport',
|
|
|
|
|
+ userId: friendUserId,
|
|
|
|
|
+ status: status,
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 订阅用户状态(使用 TIM 原生能力)
|
|
|
|
|
+ * @param {Array<String>} userIdList 用户ID列表
|
|
|
|
|
+ */
|
|
|
|
|
+ async subscribeUserStatus(userIdList) {
|
|
|
|
|
+ if (!timManager.tim || !timManager.isLogin) {
|
|
|
|
|
+ console.warn('⚠️ TIM 未登录,无法订阅用户状态');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const result = await timManager.tim.subscribeUserStatus({
|
|
|
|
|
+ userIDList: userIdList.map(id => String(id))
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ console.log('✅ 订阅用户状态成功:', result);
|
|
|
|
|
+
|
|
|
|
|
+ // 订阅成功后,初始化这些用户的状态
|
|
|
|
|
+ if (result.data && result.data.successUserList) {
|
|
|
|
|
+ result.data.successUserList.forEach(user => {
|
|
|
|
|
+ const status = user.statusType === timManager.tim.TIM.TYPES.USER_STATUS_ONLINE ? 'online' : 'offline';
|
|
|
|
|
+ this.onlineStatusCache.set(String(user.userID), status === 'online');
|
|
|
|
|
+ this.notifyStatusChange(String(user.userID), status);
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 订阅用户状态失败:', error);
|
|
|
|
|
+ throw error;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 取消订阅用户状态
|
|
|
|
|
+ * @param {Array<String>} userIdList 用户ID列表
|
|
|
|
|
+ */
|
|
|
|
|
+ async unsubscribeUserStatus(userIdList) {
|
|
|
|
|
+ if (!timManager.tim || !timManager.isLogin) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ await timManager.tim.unsubscribeUserStatus({
|
|
|
|
|
+ userIDList: userIdList.map(id => String(id))
|
|
|
|
|
+ });
|
|
|
|
|
+ console.log('✅ 取消订阅用户状态成功');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 取消订阅用户状态失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 处理接收到的消息
|
|
|
|
|
+ */
|
|
|
|
|
+ handleMessage(data) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const message = typeof data === 'string' ? JSON.parse(data) : data;
|
|
|
|
|
+
|
|
|
|
|
+ switch (message.type) {
|
|
|
|
|
+ case 'PONG':
|
|
|
|
|
+ // 心跳响应
|
|
|
|
|
+ console.log('💓 收到心跳响应');
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'ONLINE':
|
|
|
|
|
+ case 'STATUS_UPDATE':
|
|
|
|
|
+ // 用户上线/状态更新通知
|
|
|
|
|
+ if (message.userId || message.fromUserId) {
|
|
|
|
|
+ const userId = String(message.userId || message.fromUserId);
|
|
|
|
|
+ const isOnline = message.online !== undefined ? message.online : (message.type === 'ONLINE');
|
|
|
|
|
+
|
|
|
|
|
+ this.onlineStatusCache.set(userId, isOnline);
|
|
|
|
|
+ this.notifyStatusChange(userId, isOnline ? 'online' : 'offline');
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'OFFLINE':
|
|
|
|
|
+ // 用户离线通知
|
|
|
|
|
+ if (message.userId || message.fromUserId) {
|
|
|
|
|
+ const userId = String(message.userId || message.fromUserId);
|
|
|
|
|
+ this.onlineStatusCache.set(userId, false);
|
|
|
|
|
+ this.notifyStatusChange(userId, 'offline');
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 消息解析失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 启动心跳
|
|
|
|
|
+ */
|
|
|
|
|
+ startHeartbeat() {
|
|
|
|
|
+ this.stopHeartbeat();
|
|
|
|
|
+
|
|
|
|
|
+ this.heartbeatTimer = setInterval(() => {
|
|
|
|
|
+ if (this.isConnected) {
|
|
|
|
|
+ this.sendMessage({
|
|
|
|
|
+ type: 'PING',
|
|
|
|
|
+ fromUserId: this.userId,
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }, this.heartbeatInterval);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 停止心跳
|
|
|
|
|
+ */
|
|
|
|
|
+ stopHeartbeat() {
|
|
|
|
|
+ if (this.heartbeatTimer) {
|
|
|
|
|
+ clearInterval(this.heartbeatTimer);
|
|
|
|
|
+ this.heartbeatTimer = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 发送消息
|
|
|
|
|
+ */
|
|
|
|
|
+ sendMessage(data) {
|
|
|
|
|
+ if (!this.isConnected) {
|
|
|
|
|
+ console.warn('⚠️ WebSocket未连接,无法发送消息');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ uni.sendSocketMessage({
|
|
|
|
|
+ data: JSON.stringify(data),
|
|
|
|
|
+ fail: (err) => {
|
|
|
|
|
+ console.error('❌ 发送消息失败:', err);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 发送消息异常:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 监听用户状态变化
|
|
|
|
|
+ * @param {String} targetUserId 目标用户ID
|
|
|
|
|
+ * @param {Function} callback 回调函数 (status) => {}
|
|
|
|
|
+ */
|
|
|
|
|
+ onStatusChange(targetUserId, callback) {
|
|
|
|
|
+ if (!this.statusCallbacks.has(targetUserId)) {
|
|
|
|
|
+ this.statusCallbacks.set(targetUserId, []);
|
|
|
|
|
+ }
|
|
|
|
|
+ this.statusCallbacks.get(targetUserId).push(callback);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 移除状态监听
|
|
|
|
|
+ * @param {String} targetUserId 目标用户ID
|
|
|
|
|
+ * @param {Function} callback 回调函数
|
|
|
|
|
+ */
|
|
|
|
|
+ offStatusChange(targetUserId, callback) {
|
|
|
|
|
+ if (!this.statusCallbacks.has(targetUserId)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const callbacks = this.statusCallbacks.get(targetUserId);
|
|
|
|
|
+ const index = callbacks.indexOf(callback);
|
|
|
|
|
+ if (index > -1) {
|
|
|
|
|
+ callbacks.splice(index, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (callbacks.length === 0) {
|
|
|
|
|
+ this.statusCallbacks.delete(targetUserId);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 通知状态变化
|
|
|
|
|
+ */
|
|
|
|
|
+ notifyStatusChange(userId, status) {
|
|
|
|
|
+ console.log(`👤 用户 ${userId} 状态变更: ${status}`);
|
|
|
|
|
+
|
|
|
|
|
+ const callbacks = this.statusCallbacks.get(userId);
|
|
|
|
|
+ if (callbacks && callbacks.length > 0) {
|
|
|
|
|
+ callbacks.forEach(callback => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ callback(status);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('❌ 状态回调执行失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取缓存的在线状态
|
|
|
|
|
+ * @param {String} userId 目标用户ID
|
|
|
|
|
+ * @return {Boolean|null} 在线状态,null表示未知
|
|
|
|
|
+ */
|
|
|
|
|
+ getCachedStatus(userId) {
|
|
|
|
|
+ return this.onlineStatusCache.get(String(userId)) || null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 计划重连
|
|
|
|
|
+ */
|
|
|
|
|
+ scheduleReconnect() {
|
|
|
|
|
+ if (this.reconnectTimer) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.log('🔄 将在5秒后重连...');
|
|
|
|
|
+ this.reconnectTimer = setTimeout(() => {
|
|
|
|
|
+ this.reconnectTimer = null;
|
|
|
|
|
+ if (!this.isConnected && this.userId) {
|
|
|
|
|
+ console.log('🔄 尝试重连...');
|
|
|
|
|
+ this.connectWebSocket();
|
|
|
|
|
+ }
|
|
|
|
|
+ }, this.reconnectInterval);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 断开连接
|
|
|
|
|
+ */
|
|
|
|
|
+ disconnect() {
|
|
|
|
|
+ this.stopHeartbeat();
|
|
|
|
|
+
|
|
|
|
|
+ if (this.reconnectTimer) {
|
|
|
|
|
+ clearTimeout(this.reconnectTimer);
|
|
|
|
|
+ this.reconnectTimer = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 移除 TIM 事件监听
|
|
|
|
|
+ if (timManager.tim) {
|
|
|
|
|
+ const TIM = timManager.tim.TIM;
|
|
|
|
|
+ if (this.timConnectListener) {
|
|
|
|
|
+ timManager.tim.off(TIM.EVENT.NET_STATE_CHANGE, this.timConnectListener);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.timStatusListener) {
|
|
|
|
|
+ timManager.tim.off(TIM.EVENT.USER_STATUS_UPDATED, this.timStatusListener);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isConnected) {
|
|
|
|
|
+ uni.closeSocket();
|
|
|
|
|
+ this.isConnected = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.statusCallbacks.clear();
|
|
|
|
|
+ this.userId = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取连接状态
|
|
|
|
|
+ */
|
|
|
|
|
+ getConnectionStatus() {
|
|
|
|
|
+ return this.isConnected;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 导出单例
|
|
|
|
|
+export default new TIMPresenceManager();
|