366 lines
9.8 KiB
JavaScript
366 lines
9.8 KiB
JavaScript
import { defineStore } from "pinia";
|
||
|
||
import TIM from "tim-wx-sdk";
|
||
import TIMUploadPlugin from "tim-upload-plugin";
|
||
import { generateUserSig } from "@/utils/api";
|
||
export const useIMStore = defineStore("im", {
|
||
state: () => ({
|
||
tim: null,
|
||
isSDKReady: false,
|
||
currentConversation: null,
|
||
messageList: [],
|
||
conversationList: [],
|
||
friendList: [],
|
||
userInfo: null,
|
||
isLogin: false,
|
||
}),
|
||
actions: {
|
||
// 初始化IM SDK
|
||
initIM(sdkAppId) {
|
||
// 替换为您的腾讯云IM应用SDKAppID
|
||
const SDKAppID = sdkAppId; // 请替换为您的SDKAppID
|
||
// 创建 SDK 实例
|
||
let tim = TIM.create({
|
||
SDKAppID,
|
||
});
|
||
// 设置日志级别
|
||
tim.setLogLevel(1);
|
||
// 注册上传插件
|
||
tim.registerPlugin({ "tim-upload-plugin": TIMUploadPlugin });
|
||
this.tim = tim;
|
||
// 监听事件
|
||
this.registerTIMListeners();
|
||
},
|
||
// 注册IM事件监听
|
||
registerTIMListeners() {
|
||
if (!this.tim) return;
|
||
// SDK准备就绪
|
||
this.tim.on(TIM.EVENT.SDK_READY, this.onSDKReady);
|
||
// 会话列表更新
|
||
this.tim.on(
|
||
TIM.EVENT.CONVERSATION_LIST_UPDATED,
|
||
this.onConversationListUpdated
|
||
);
|
||
|
||
// 收到新消息
|
||
this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived);
|
||
|
||
// SDK不可用
|
||
this.tim.on(TIM.EVENT.SDK_NOT_READY, this.onSDKNotReady);
|
||
|
||
// 被踢下线
|
||
this.tim.on(TIM.EVENT.KICKED_OUT, this.onKickedOut);
|
||
},
|
||
|
||
// SDK就绪处理
|
||
onSDKReady({ name }) {
|
||
console.log("TIM SDK就绪: ", name);
|
||
this.isSDKReady = true;
|
||
|
||
// 获取个人资料
|
||
this.getUserProfile();
|
||
|
||
// 获取会话列表
|
||
this.getConversationList();
|
||
|
||
// 获取好友列表
|
||
// this.getFriendList();
|
||
},
|
||
|
||
// SDK未就绪处理
|
||
onSDKNotReady({ name }) {
|
||
console.log("TIM SDK未就绪: ", name);
|
||
this.isSDKReady = false;
|
||
},
|
||
|
||
// 被踢下线处理
|
||
onKickedOut({ name }) {
|
||
console.log("被踢下线: ", name);
|
||
this.isLogin = false;
|
||
this.isSDKReady = false;
|
||
uni.showToast({
|
||
title: "您的账号已在其他设备登录",
|
||
icon: "none",
|
||
});
|
||
|
||
// 跳转到登录页
|
||
uni.reLaunch({
|
||
url: "/pages/home/home",
|
||
});
|
||
},
|
||
|
||
// 会话列表更新处理
|
||
onConversationListUpdated({ data }) {
|
||
this.conversationList = data;
|
||
},
|
||
|
||
// 接收新消息处理
|
||
onMessageReceived({ data }) {
|
||
if (this.currentConversation) {
|
||
// 如果是当前会话的消息,直接添加到消息列表
|
||
const newMessages = data.filter(
|
||
(msg) =>
|
||
msg.conversationID === this.currentConversation.conversationID
|
||
);
|
||
if (newMessages.length) {
|
||
this.messageList = [...this.messageList, ...newMessages];
|
||
}
|
||
}
|
||
},
|
||
|
||
// 延时函数
|
||
sleep(time) {
|
||
return new Promise((resolve) => setTimeout(resolve, time));
|
||
},
|
||
|
||
// 登录IM
|
||
async login(userID, retryCount = 0, maxRetries = 3, retryDelay = 1000) {
|
||
try {
|
||
const { sdkAppId, data } = await generateUserSig({
|
||
userId: userID,
|
||
});
|
||
if (!this.tim) {
|
||
this.initIM(sdkAppId);
|
||
}
|
||
//判断若已经登录,则登出
|
||
if (this.isLogin) {
|
||
await this.logout();
|
||
}
|
||
await this.tim.login({ userID, userSig: data });
|
||
this.isLogin = true;
|
||
return true;
|
||
} catch (error) {
|
||
console.error(`登录失败(第${retryCount + 1}次尝试):`, error);
|
||
// 登录失败后的重试机制
|
||
if (retryCount < maxRetries) {
|
||
console.log(`${retryDelay / 1000}秒后尝试重新登录...`);
|
||
await this.sleep(retryDelay);
|
||
// 递增重试延迟,避免频繁请求
|
||
return this.login(
|
||
userID,
|
||
retryCount + 1,
|
||
maxRetries,
|
||
retryDelay * 1.5
|
||
);
|
||
}
|
||
uni.showToast({
|
||
title: `IM登录失败,请检查网络后重试`,
|
||
icon: "none",
|
||
});
|
||
return false;
|
||
}
|
||
},
|
||
|
||
// 登出IM
|
||
async logout() {
|
||
if (!this.tim) return;
|
||
|
||
try {
|
||
await this.tim.logout();
|
||
this.isLogin = false;
|
||
this.isSDKReady = false;
|
||
this.userInfo = null;
|
||
this.conversationList = [];
|
||
this.friendList = [];
|
||
this.messageList = [];
|
||
this.currentConversation = null;
|
||
return true;
|
||
} catch (error) {
|
||
console.error("登出失败:", error);
|
||
return false;
|
||
}
|
||
},
|
||
|
||
// 获取个人资料
|
||
async getUserProfile() {
|
||
if (!this.isSDKReady) return;
|
||
try {
|
||
const res = await this.tim.getMyProfile();
|
||
this.userInfo = res.data;
|
||
return res.data;
|
||
} catch (error) {
|
||
console.error("获取个人资料失败:", error);
|
||
}
|
||
},
|
||
|
||
// 获取会话列表
|
||
async getConversationList() {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
const res = await this.tim.getConversationList();
|
||
this.conversationList = res.data.conversationList;
|
||
return this.conversationList;
|
||
} catch (error) {
|
||
console.error("获取会话列表失败:", error);
|
||
}
|
||
},
|
||
|
||
// 获取好友列表
|
||
async getFriendList() {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
const res = await this.tim.getFriendList();
|
||
this.friendList = res.data;
|
||
return this.friendList;
|
||
} catch (error) {
|
||
console.error("获取好友列表失败:", error);
|
||
}
|
||
},
|
||
|
||
// 进入会话
|
||
async enterConversation(conversationID) {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
// 获取会话信息
|
||
const res = await this.tim.getConversationProfile(conversationID);
|
||
this.currentConversation = res.data.conversation;
|
||
// 获取会话消息
|
||
await this.getMessageList(conversationID);
|
||
|
||
return this.currentConversation;
|
||
} catch (error) {
|
||
return false;
|
||
}
|
||
},
|
||
|
||
// 获取消息列表
|
||
async getMessageList(conversationID, count = 50, nextReqMessageID = "") {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
const res = await this.tim.getMessageList({
|
||
conversationID,
|
||
count: 50,
|
||
nextReqMessageID,
|
||
});
|
||
if (nextReqMessageID) {
|
||
// 如果是加载更多消息,将新消息添加到现有消息列表的前面
|
||
this.messageList = [...res.data.messageList, ...this.messageList];
|
||
} else {
|
||
// 否则,替换当前消息列表
|
||
this.messageList = res.data.messageList;
|
||
}
|
||
|
||
return res.data;
|
||
} catch (error) {
|
||
console.error("获取消息列表失败:", error);
|
||
}
|
||
},
|
||
|
||
// 发送文本消息
|
||
async sendTextMessage(text, conversationID) {
|
||
if (!this.isSDKReady) return;
|
||
try {
|
||
// 创建文本消息
|
||
console.log("创建文本", conversationID);
|
||
const message = this.tim.createTextMessage({
|
||
to: conversationID.replace("C2C", ""),
|
||
conversationType: conversationID.startsWith("C2C")
|
||
? TIM.TYPES.CONV_C2C
|
||
: TIM.TYPES.CONV_GROUP,
|
||
payload: {
|
||
text,
|
||
},
|
||
});
|
||
// 发送消息
|
||
const res = await this.tim.sendMessage(message);
|
||
this.messageList.push(res.data.message);
|
||
return res.data.message;
|
||
} catch (error) {
|
||
console.error("发送文本消息失败:", error);
|
||
}
|
||
},
|
||
|
||
// 发送图片消息
|
||
async sendImageMessage(file, conversationID) {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
// 创建图片消息
|
||
const message = this.tim.createImageMessage({
|
||
to: conversationID.replace("C2C", ""),
|
||
conversationType: conversationID.startsWith("C2C")
|
||
? TIM.TYPES.CONV_C2C
|
||
: TIM.TYPES.CONV_GROUP,
|
||
payload: {
|
||
file,
|
||
},
|
||
});
|
||
|
||
// 发送消息
|
||
const res = await this.tim.sendMessage(message);
|
||
this.messageList.push(res.data.message);
|
||
return res.data.message;
|
||
} catch (error) {
|
||
console.error("发送图片消息失败:", error);
|
||
}
|
||
},
|
||
|
||
// 更新昵称
|
||
async updateNickname(newNickname) {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
const res = await this.tim.updateMyProfile({
|
||
nick: newNickname,
|
||
});
|
||
this.userInfo.nick = newNickname;
|
||
return res.data;
|
||
} catch (error) {
|
||
console.error("更新昵称失败:", error);
|
||
throw error;
|
||
}
|
||
},
|
||
|
||
async getImageUrl(uuid) {
|
||
if (!this.isSDKReady) return;
|
||
try {
|
||
// 假设 tim.getImageUrl 是一个有效的方法
|
||
const url = await this.tim.getImageUrl(uuid);
|
||
return url;
|
||
} catch (error) {
|
||
console.error("获取图片URL失败:", error);
|
||
throw error;
|
||
}
|
||
},
|
||
|
||
// 切换会话
|
||
async switchConversation(conversationID) {
|
||
if (!this.isSDKReady) return;
|
||
try {
|
||
// 进入新的会话
|
||
const res = await this.enterConversation(conversationID);
|
||
return res;
|
||
} catch (error) {
|
||
console.error("切换会话失败:", error);
|
||
throw error;
|
||
}
|
||
},
|
||
|
||
// 发送自定义消息(用于音视频通话信令等场景)
|
||
async sendCustomMessage(payload, conversationID) {
|
||
if (!this.isSDKReady) return;
|
||
|
||
try {
|
||
const message = this.tim.createCustomMessage({
|
||
to: conversationID.replace("C2C", ""),
|
||
conversationType: conversationID.startsWith("C2C")
|
||
? TIM.TYPES.CONV_C2C
|
||
: TIM.TYPES.CONV_GROUP,
|
||
payload,
|
||
});
|
||
|
||
const res = await this.tim.sendMessage(message);
|
||
this.messageList.push(res.data.message);
|
||
return res.data.message;
|
||
} catch (error) {
|
||
console.error("发送自定义消息失败:", error);
|
||
throw error;
|
||
}
|
||
},
|
||
},
|
||
});
|