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;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
});
|