You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
6.4 KiB

4 weeks ago
// common/websocket-manager.js
import * as wsApi from './wssocket';
import * as msgType from './messageType';
import * as enums from './enums';
class WebSocketManager {
constructor() {
if (WebSocketManager.instance) return WebSocketManager.instance;
WebSocketManager.instance = this;
// 状态标志
this.isInit = false;
this.isExit = false;
this.reconnecting = false;
this.audioTip = null;
this.WS_URL=this.$wsUrl
// Store 引用(需外部注入)
this.chatStore = null;
this.userId=null;
// 事件监听器(供页面注册)
this.messageListeners = [];
}
/**
* 初始化 WebSocket 管理器
* @param {Object} stores - 各个 store 实例
* @param {string} accessToken - 用户 token
*/
init(stores, accessToken) {
if (this.isInit) return;
this.chatStore = stores.chatStore;
this.userId=stores.userId;
this.isExit = false;
this.reconnecting = false;
// 加载本地数据并启动 WebSocket
this.loadStore()
.then(() => {
this.initWebSocket(accessToken);
this.isInit = true;
})
.catch((e) => {
console.error(e);
this.exit();
});
}
initWebSocket(accessToken) {
wsApi.connect(this.WS_URL, accessToken);
wsApi.onConnect(() => {
if (this.reconnecting) {
this.onReconnectWs();
} else {
// 首次连接,拉取离线消息
this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId).catch(() => {});
this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId).catch(() => {});
}
});
wsApi.onMessage((cmd, msgInfo) => {
// 分发原始消息给外部监听器
this.messageListeners.forEach(listener => listener(cmd, msgInfo));
// 内部业务处理
if (cmd == 2) {
// 异地登录
uni.showModal({
content: '您已在其他地方登录,将被强制下线',
showCancel: false,
});
this.exit();
} else if (cmd == 3) {
this.handlePrivateMessage(msgInfo);
} else if (cmd == 4) {
this.handleGroupMessage(msgInfo);
} else if (cmd == 5) {
this.handleSystemMessage(msgInfo);
}
});
wsApi.onClose((res) => {
console.log("ws断开", res);
this.reconnect(accessToken);
});
}
/**
* 重新连接token 刷新后调用
* @param {string} accessToken
*/
reconnect(accessToken) {
if (this.isExit) return;
this.reconnecting = true;
wsApi.reconnect(this.WS_URL, accessToken);
}
/**
* 关闭连接并退出登录
*/
exit() {
console.log("WebSocket exit");
this.isExit = true;
wsApi.close(3099);
// uni.removeStorageSync("loginInfo");
// uni.reLaunch({ url: "/pages/login/login" });
this.unloadStore();
}
/**
* 注册消息监听器页面可用来接收新消息通知
* @param {Function} listener - (cmd, msgInfo) => {}
*/
addMessageListener(listener) {
if (typeof listener === 'function') {
this.messageListeners.push(listener);
}
}
/**
* 移除消息监听器
*/
removeMessageListener(listener) {
const index = this.messageListeners.indexOf(listener);
if (index !== -1) this.messageListeners.splice(index, 1);
}
// ============= 私有方法 =============
// 视频通话相关(可根据需要保留或删除)
handleRtcPrivate(msg) {
// #ifdef MP-WEIXIN
// return; // 小程序不支持
// // #endif
// let delayTime = 100;
// if (msg.type === enums.MESSAGE_TYPE.RTC_CALL_VOICE || msg.type === enums.MESSAGE_TYPE.RTC_CALL_VIDEO) {
// const mode = msg.type === enums.MESSAGE_TYPE.RTC_CALL_VIDEO ? "video" : "voice";
// const pages = getCurrentPages();
// const curPage = pages[pages.length - 1].route;
// if (curPage !== "pages/chat/chat-private-video") {
// const friend = this.loadFriendInfo(msg.selfSend ? msg.recvId : msg.sendId);
// const friendInfo = encodeURIComponent(JSON.stringify(friend));
// uni.navigateTo({
// url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false`,
// });
// delayTime = 500;
// }
// }
// setTimeout(() => {
// uni.$emit('WS_RTC_PRIVATE', msg);
// }, delayTime);
}
handleRtcGroup(msg) {
// #ifdef MP-WEIXIN
return;
// #endif
let delayTime = 100;
if (msg.type === enums.MESSAGE_TYPE.RTC_GROUP_SETUP) {
const pages = getCurrentPages();
const curPage = pages[pages.length - 1].route;
if (curPage !== "pages/chat/chat-group-video") {
const userInfos = encodeURIComponent(msg.content);
const inviterId = msg.sendId;
const groupId = msg.groupId;
uni.navigateTo({
url: `/pages/chat/chat-group-video?groupId=${groupId}&isHost=false&inviterId=${inviterId}&userInfos=${userInfos}`,
});
delayTime = 500;
}
}
setTimeout(() => {
uni.$emit('WS_RTC_GROUP', msg);
}, delayTime);
}
playAudioTip() {
// 音频播放实现(如需)
// this.audioTip = uni.createInnerAudioContext();
// this.audioTip.src = "/static/audio/tip.wav";
// this.audioTip.play();
}
async refreshToken(loginInfo) {
// if (!loginInfo || !loginInfo.refreshToken) {
// throw new Error("No refreshToken");
// }
// const newLoginInfo = await http({
// url: '/refreshToken',
// method: 'PUT',
// header: { refreshToken: loginInfo.refreshToken },
// });
// uni.setStorageSync("loginInfo", newLoginInfo);
// return newLoginInfo;
}
}
// 导出单例
const wsManager = new WebSocketManager();
export default wsManager;