mdm-im-v3 2.1.0 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +50 -1
  3. package/dist/{FilePreview-dpnc9m3Z.js → FilePreview-CJdqlDs0.js} +2 -2
  4. package/dist/core.es.js +2 -2
  5. package/dist/{index-D5S79LNp.js → index-BLdSVjT-.js} +682 -332
  6. package/dist/{index-CsaYx_7b.js → index-CrMTFmHU.js} +2 -2
  7. package/dist/{index-CNxeqkio.js → index-VIcWin6Y.js} +68 -54
  8. package/dist/index.es.js +1 -1
  9. package/dist/style/index.css +1 -1
  10. package/dist-h5/{ChatHistoryH5-BhrGF5WR.js → ChatHistoryH5-BeCSVzKZ.js} +2 -2
  11. package/dist-h5/{ChatPageH5-B3azJu7O.js → ChatPageH5-GUblGkKv.js} +12 -7
  12. package/dist-h5/{ChatSettingsH5-CFr9Bn69.js → ChatSettingsH5-wyQ01zjO.js} +3 -2
  13. package/dist-h5/{CreateGroupH5-a16jkObH.js → CreateGroupH5-CCtTCnLG.js} +2 -2
  14. package/dist-h5/{GroupAnnouncementH5-B-Qfzoy2.js → GroupAnnouncementH5-BYN-HzX0.js} +1 -1
  15. package/dist-h5/{GroupInfoDialogH5-BHLKs62Z.js → GroupInfoDialogH5-DDjYHm7i.js} +1 -1
  16. package/dist-h5/{GroupMembersH5-D_f1RFjO.js → GroupMembersH5-DUWs89a3.js} +1 -1
  17. package/dist-h5/{GroupNoticeH5-46ZjBe92.js → GroupNoticeH5-C6hNtZzy.js} +1 -1
  18. package/dist-h5/{MemberDetailH5-B7nlr8ZT.js → MemberDetailH5-BZlExAgj.js} +16 -3
  19. package/dist-h5/{SearchPageH5-hYxNItvz.js → SearchPageH5-CjBq_40x.js} +2 -2
  20. package/dist-h5/{SelectMembersH5-DQIfX_w4.js → SelectMembersH5-BSLarLGK.js} +2 -2
  21. package/dist-h5/{imChat-Bfl2JS8Q.js → imChat-CdmqPGQ6.js} +40 -7
  22. package/dist-h5/index.es.js +2 -2
  23. package/dist-h5/{indexH5-CUQe-Ize.js → indexH5-CCseQmQb.js} +9 -4
  24. package/dist-h5/{indexH5-DAnvVyZ1.js → indexH5-DikfbMIK.js} +524 -166
  25. package/dist-h5/style/index-h5.css +1 -1
  26. package/package.json +72 -71
  27. package/dist-h5/request-CK8gkCRf.js +0 -44
@@ -2,9 +2,77 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { ref, computed } from "vue";
5
- import { defineStore } from "pinia";
6
5
  import axios from "axios";
7
6
  import { ElMessage } from "element-plus";
7
+ import { defineStore } from "pinia";
8
+ function normalizeIMIdentity(config = {}) {
9
+ const version = Number(config.imIdentityVersion || 1);
10
+ const tenantID = String(config.tenantID || "");
11
+ const userID = version === 2 ? String(config.imUserID || "") : String(config.userID || "");
12
+ if (![1, 2].includes(version)) throw new Error("不支持的 IM 身份版本");
13
+ if (version === 2 && (!tenantID || !/^mdm2u_[a-f0-9]{48}$/.test(userID))) {
14
+ throw new Error("租户 IM 身份信息不完整");
15
+ }
16
+ return { imIdentityVersion: version, tenantID, userID, imUserID: version === 2 ? userID : "" };
17
+ }
18
+ function imSessionScope(config = {}) {
19
+ if (!config.userID && !config.imUserID) return "";
20
+ const identity = normalizeIMIdentity(config);
21
+ return JSON.stringify([
22
+ config.apiUrl || "",
23
+ config.wsUrl || "",
24
+ identity.tenantID,
25
+ identity.imIdentityVersion,
26
+ identity.userID,
27
+ config.platformID ?? 5
28
+ ]);
29
+ }
30
+ function imCacheNamespace(config = {}) {
31
+ if (!config.tenantID || !config.userID && !config.imUserID) return "";
32
+ return `scope2:${imSessionScope(config)}`;
33
+ }
34
+ function nextIMSession(current, input = {}) {
35
+ const merged = { ...current, ...input };
36
+ if (Number(merged.imIdentityVersion) === 2 && String(current.tenantID || "") !== String(merged.tenantID || "") && !Object.hasOwn(input, "imUserID")) {
37
+ throw new Error("切换租户必须提供目标 IM 身份");
38
+ }
39
+ const next = { ...merged, ...normalizeIMIdentity(merged) };
40
+ if (imSessionScope(current) !== imSessionScope(next)) {
41
+ for (const key of ["imToken", "satoken", "chatToken", "nickname", "faceURL", "remoteConnectUrl", "remoteConnectToken", "businessUserID", "loginCode"]) {
42
+ next[key] = Object.hasOwn(input, key) ? input[key] : "";
43
+ }
44
+ next.loginStatus = 1;
45
+ next.groupStatus = 0;
46
+ next.currentChatId = "";
47
+ next.unReadCount = 0;
48
+ next.isViewingChat = false;
49
+ }
50
+ return next;
51
+ }
52
+ function parseIMBusinessData(value) {
53
+ try {
54
+ const result = typeof value === "string" ? JSON.parse(value) : value;
55
+ return result && typeof result === "object" && !Array.isArray(result) ? result : null;
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+ function shouldHandleLoginNotice(notice, session) {
61
+ if (Number(session.imIdentityVersion) === 2) return false;
62
+ if (!notice || notice.event !== "LOGIN_NOTICE") return false;
63
+ if (notice.tenantID != null && String(notice.tenantID) !== String(session.tenantID)) return false;
64
+ return Boolean(notice.sendUserID && notice.imToken && session.imToken && notice.sendUserID === session.userID && notice.imToken !== session.imToken);
65
+ }
66
+ function assertIMTarget(value, kind = "user") {
67
+ const pattern = kind === "group" ? /^mdm2g_[a-f0-9]{48}$/ : /^mdm2u_[a-f0-9]{48}$/;
68
+ if (!pattern.test(String(value || ""))) throw new Error(kind === "group" ? "请先通过服务端预留租户群组身份" : "消息目标缺少租户 IM 身份");
69
+ }
70
+ function shouldHandleRemoteNotice(notice, session) {
71
+ if (!notice) return false;
72
+ if (Number(session.imIdentityVersion) !== 2) return notice.sendUserID !== session.userID;
73
+ const own = session.imUserID || session.userID;
74
+ return Boolean(own && String(notice.tenantID || "") === String(session.tenantID || "") && /^mdm2u_[a-f0-9]{48}$/.test(notice.sendIMUserID || "") && notice.recvIMUserID === own && notice.sendIMUserID !== own);
75
+ }
8
76
  const CbEvents = {
9
77
  OnConnectFailed: "OnConnectFailed",
10
78
  OnConnectSuccess: "OnConnectSuccess",
@@ -9786,6 +9854,230 @@ class EventEmitter {
9786
9854
  this.emitter.all.clear();
9787
9855
  }
9788
9856
  }
9857
+ const useChatStore = defineStore("chatMessage", {
9858
+ state: () => {
9859
+ return {
9860
+ userID: "",
9861
+ // SDK IM identity (legacy hosts still supply loginCode)
9862
+ imUserID: "",
9863
+ businessUserID: "",
9864
+ loginCode: "",
9865
+ imIdentityVersion: 1,
9866
+ nickname: "",
9867
+ // 用户昵称
9868
+ faceURL: "",
9869
+ // 用户头像
9870
+ platformID: IM_LOGIN_PLATFORM.Web,
9871
+ loginStatus: IM_LOGIN_STATUS.Logout,
9872
+ // 登录状态
9873
+ groupStatus: IM_GROUP_STATUS.Nomal,
9874
+ // 群组状态
9875
+ apiUrl: "",
9876
+ wsUrl: "",
9877
+ tenantID: "",
9878
+ satoken: "",
9879
+ // 系统Token
9880
+ imToken: "",
9881
+ // IM token
9882
+ chatToken: "",
9883
+ // 聊天token
9884
+ unReadCount: 0,
9885
+ // 本账号所有未读消息
9886
+ currentChatId: "",
9887
+ // 当前会话ID
9888
+ isFocused: true,
9889
+ // 窗口是否聚焦
9890
+ remoteConnectUrl: "",
9891
+ // 向日葵被控端连接地址
9892
+ remoteConnectToken: "",
9893
+ // 被控端连接token(session)
9894
+ isViewingChat: false
9895
+ // 是否在H5聊天详情页(控制自动标记已读)
9896
+ };
9897
+ },
9898
+ getters: {
9899
+ // 获取当前会话ID
9900
+ getCurrentChatId(state) {
9901
+ return state.currentChatId;
9902
+ },
9903
+ // 获取用户登录状态
9904
+ getLoginStatus(state) {
9905
+ return state.loginStatus;
9906
+ },
9907
+ // 获取基本地址路径
9908
+ getBaseUrl(state) {
9909
+ return state.apiUrl;
9910
+ },
9911
+ // 获取socket链接路径
9912
+ getWsUrl(state) {
9913
+ return state.wsUrl;
9914
+ },
9915
+ // 获取系统token
9916
+ getToken(state) {
9917
+ return state.satoken;
9918
+ },
9919
+ // 获取租户ID
9920
+ getTenantID(state) {
9921
+ return state.tenantID;
9922
+ },
9923
+ // 获取用户登录信息
9924
+ getUserInfo(state) {
9925
+ return {
9926
+ userID: state.userID,
9927
+ imUserID: state.imUserID,
9928
+ businessUserID: state.businessUserID,
9929
+ loginCode: state.loginCode,
9930
+ imIdentityVersion: state.imIdentityVersion,
9931
+ nickname: state.nickname,
9932
+ faceURL: state.faceURL,
9933
+ loginStatus: state.loginStatus,
9934
+ platformID: state.platformID,
9935
+ satoken: state.satoken,
9936
+ tenantID: state.tenantID,
9937
+ imToken: state.imToken,
9938
+ chatToken: state.chatToken
9939
+ };
9940
+ },
9941
+ // 获取未读消息总数
9942
+ getUnReadCount(state) {
9943
+ return state.unReadCount;
9944
+ },
9945
+ // 获取窗口是否聚焦
9946
+ getIsFocused(state) {
9947
+ return state.isFocused;
9948
+ },
9949
+ // 获取被控端连接地址
9950
+ getRemoteConnectUrl(state) {
9951
+ return state.remoteConnectUrl;
9952
+ },
9953
+ // 获取被控端连接token
9954
+ getRemoteConnectToken(state) {
9955
+ return state.remoteConnectToken;
9956
+ },
9957
+ // 获取是否在查看H5聊天详情
9958
+ getIsViewingChat(state) {
9959
+ return state.isViewingChat;
9960
+ }
9961
+ },
9962
+ actions: {
9963
+ // 设置当前会话ID
9964
+ setCurrentChatId(id) {
9965
+ this.currentChatId = id;
9966
+ },
9967
+ // 更新未读总数
9968
+ setUnReadCount(count = 0) {
9969
+ const next = Number(count) || 0;
9970
+ if (this.unReadCount === next) return;
9971
+ console.log("[IM][unread] store 未读总数更新", { from: this.unReadCount, to: next });
9972
+ this.unReadCount = next;
9973
+ },
9974
+ // 更新用户的登录状态
9975
+ setLoginStatus(val) {
9976
+ this.loginStatus = val;
9977
+ },
9978
+ // 更新群组状态
9979
+ setGroupStatus(val) {
9980
+ this.groupStatus = val;
9981
+ },
9982
+ // 保存登录用户信息
9983
+ setUserInfo(obj) {
9984
+ const next = nextIMSession(this.$state, obj);
9985
+ this.$patch(next);
9986
+ },
9987
+ // 设置窗口聚焦状态
9988
+ setIsFocused(val) {
9989
+ this.isFocused = val;
9990
+ },
9991
+ // 设置被控端连接地址
9992
+ setRemoteConnectUrl(url) {
9993
+ this.remoteConnectUrl = url;
9994
+ },
9995
+ // 设置被控端连接token
9996
+ setRemoteConnectToken(token) {
9997
+ this.remoteConnectToken = token;
9998
+ },
9999
+ // 设置是否在查看H5聊天详情
10000
+ setIsViewingChat(val) {
10001
+ this.isViewingChat = val;
10002
+ }
10003
+ },
10004
+ persist: {
10005
+ enabled: true,
10006
+ // 开启持久化
10007
+ strategies: [
10008
+ {
10009
+ key: "MDM_CHAT_MESSAGE",
10010
+ // 存储的 key 名(默认 store id)
10011
+ storage: localStorage,
10012
+ // 存储位置(默认 localStorage)
10013
+ // HttpOnly Cookie 认证:satoken 和 imToken 不再持久化到 localStorage,仅保留在 Pinia 内存中
10014
+ paths: ["userID", "nickname", "faceURL", "platformID", "apiUrl", "wsUrl", "tenantID", "imUserID", "businessUserID", "loginCode", "imIdentityVersion"]
10015
+ }
10016
+ ]
10017
+ }
10018
+ });
10019
+ const requestInstance = axios.create({
10020
+ baseURL: "",
10021
+ timeout: 6e4,
10022
+ withCredentials: true
10023
+ // HttpOnly Cookie 认证:自动携带会话 Cookie
10024
+ });
10025
+ requestInstance.defaults.headers.post["Content-Type"] = "application/json; charset=utf-8";
10026
+ requestInstance.interceptors.request.use(
10027
+ function(config) {
10028
+ config.headers["X-Login-Type"] = "3";
10029
+ const chatStore = useChatStore();
10030
+ if (chatStore.satoken) {
10031
+ config.headers["satoken"] = chatStore.satoken;
10032
+ }
10033
+ return config;
10034
+ },
10035
+ function(error) {
10036
+ return Promise.reject(error);
10037
+ }
10038
+ );
10039
+ requestInstance.interceptors.response.use(
10040
+ function(response) {
10041
+ if ((response == null ? void 0 : response.status) == 200) {
10042
+ const code = response == null ? void 0 : response.data.code;
10043
+ if (EXIT_CODE.values.includes(code)) {
10044
+ if (EXIT_CODE[code] !== "token") {
10045
+ ElMessage.error(EXIT_CODE.label[code]);
10046
+ }
10047
+ }
10048
+ } else {
10049
+ ElMessage.error("接口出错,请检查网络后重试");
10050
+ }
10051
+ return response;
10052
+ },
10053
+ function(error) {
10054
+ return Promise.reject(error);
10055
+ }
10056
+ );
10057
+ class IMSessionChangedError extends Error {
10058
+ constructor() {
10059
+ super("IM 会话已切换,请重试");
10060
+ this.name = "IMSessionChangedError";
10061
+ }
10062
+ }
10063
+ function guardIMSDK(sdk, isCurrent) {
10064
+ const lifecycle = /* @__PURE__ */ new Set(["on", "off", "logout"]);
10065
+ return new Proxy(sdk, {
10066
+ get(target, key) {
10067
+ const value = Reflect.get(target, key);
10068
+ if (typeof value !== "function") return value;
10069
+ return (...args) => {
10070
+ if (!lifecycle.has(key) && !isCurrent()) return Promise.reject(new IMSessionChangedError());
10071
+ const result = Reflect.apply(value, target, args);
10072
+ if (!result || typeof result.then !== "function" || lifecycle.has(key)) return result;
10073
+ return result.then((data) => {
10074
+ if (!isCurrent()) throw new IMSessionChangedError();
10075
+ return data;
10076
+ });
10077
+ };
10078
+ }
10079
+ });
10080
+ }
9789
10081
  const HEX = "0123456789abcdef";
9790
10082
  function randomBytes(length) {
9791
10083
  if (typeof crypto !== "undefined" && crypto.getRandomValues) {
@@ -9819,7 +10111,9 @@ class ImKit extends EventEmitter {
9819
10111
  dataDir = "./",
9820
10112
  userID,
9821
10113
  imToken,
9822
- chatToken
10114
+ chatToken,
10115
+ imIdentityVersion = 1,
10116
+ isCurrentSession = () => true
9823
10117
  }) {
9824
10118
  super();
9825
10119
  __publicField(this, "apiUrl", "");
@@ -9843,6 +10137,11 @@ class ImKit extends EventEmitter {
9843
10137
  __publicField(this, "loginStatus", IM_LOGIN_STATUS.Logout);
9844
10138
  // 1 未登录 2 登录中 3 已登录
9845
10139
  __publicField(this, "groupStatus", IM_GROUP_STATUS.Nomal);
10140
+ this.imIdentityVersion = Number(imIdentityVersion);
10141
+ this.isCurrentSession = isCurrentSession;
10142
+ this.disposed = false;
10143
+ this.pendingGroupCreates = /* @__PURE__ */ new Map();
10144
+ this.businessApiUrl = apiUrl;
9846
10145
  this.apiUrl = `${apiUrl}/imapi`;
9847
10146
  this.wsUrl = `${wsUrl}/imws`;
9848
10147
  this.platformID = platformID;
@@ -9878,7 +10177,8 @@ class ImKit extends EventEmitter {
9878
10177
  // @openim/client-sdk和@openim/wasm-client-sdk 不需要初始化,直接调用 login 即可。
9879
10178
  initSDK() {
9880
10179
  try {
9881
- this.IMSDK = Ot();
10180
+ this.disposed = false;
10181
+ this.IMSDK = guardIMSDK(Ot(), () => !this.disposed && this.isCurrentSession());
9882
10182
  this.bindEvent();
9883
10183
  } catch (err) {
9884
10184
  console.error(err);
@@ -9918,6 +10218,7 @@ class ImKit extends EventEmitter {
9918
10218
  }
9919
10219
  // 清空即时通信实例
9920
10220
  clearSDK() {
10221
+ this.disposed = true;
9921
10222
  this.unbindEvent();
9922
10223
  this.IMSDK = null;
9923
10224
  }
@@ -10147,8 +10448,9 @@ class ImKit extends EventEmitter {
10147
10448
  console.log("请先初始化SDK");
10148
10449
  return;
10149
10450
  }
10150
- this.IMSDK.logout().then(() => {
10151
- this.getLoginStatus();
10451
+ return this.IMSDK.logout().then(() => {
10452
+ this.loginStatus = IM_LOGIN_STATUS.Logout;
10453
+ this.emit("updateStatus", this.loginStatus);
10152
10454
  return true;
10153
10455
  }).catch((error) => {
10154
10456
  console.log("IM登出异常:", error);
@@ -10520,20 +10822,20 @@ class ImKit extends EventEmitter {
10520
10822
  }
10521
10823
  /**
10522
10824
  * 获取所有会话的未读消息总数
10523
- * @returns {Number}
10825
+ * @returns {Number|null} 未读总数;获取失败返回 null(调用方不应把 null 当成 0 覆盖本地值)
10524
10826
  */
10525
10827
  async getTotalUnreadMsgCount(operationID = uuidv4()) {
10526
10828
  var _a;
10527
10829
  if (!this.IMSDK) {
10528
- return 0;
10830
+ return null;
10529
10831
  }
10530
10832
  try {
10531
10833
  const res = await ((_a = this.IMSDK) == null ? void 0 : _a.getTotalUnreadMsgCount(operationID));
10532
- return (res == null ? void 0 : res.data) || 0;
10834
+ return Number(res == null ? void 0 : res.data) || 0;
10533
10835
  } catch (error) {
10534
- console.error("获取未读消息总数失败:", error);
10836
+ console.error("[IM][unread] 获取未读消息总数失败:", error);
10535
10837
  this.handleError(error);
10536
- return 0;
10838
+ return null;
10537
10839
  }
10538
10840
  }
10539
10841
  /**
@@ -10821,6 +11123,10 @@ class ImKit extends EventEmitter {
10821
11123
  }
10822
11124
  // 发送消息,发送通过 create***Message 创建的消息,offlinePushInfo-离线消息体,groupID-发送单聊消息时传空字符串
10823
11125
  async sendMessage({ recvID, groupID, offlinePushInfo, message }, operationID = uuidv4()) {
11126
+ if (this.imIdentityVersion === 2) {
11127
+ if (groupID) assertIMTarget(groupID, "group");
11128
+ else assertIMTarget(recvID);
11129
+ }
10824
11130
  try {
10825
11131
  const res = await this.IMSDK.sendMessage({ recvID, groupID, offlinePushInfo, message }, operationID);
10826
11132
  if (res.data) {
@@ -10995,9 +11301,26 @@ class ImKit extends EventEmitter {
10995
11301
  * @param {String} operationID
10996
11302
  */
10997
11303
  async createGroup({ groupInfo, memberUserIDs, ownerUserID, adminUserIDs }, operationID = uuidv4()) {
10998
- var _a;
11304
+ var _a, _b, _c;
11305
+ if (this.imIdentityVersion === 2) {
11306
+ if (this.disposed || !this.isCurrentSession()) throw new IMSessionChangedError();
11307
+ if (ownerUserID !== this.userID) throw new Error("群主必须是当前用户");
11308
+ if (adminUserIDs == null ? void 0 : adminUserIDs.length) throw new Error("请在建群后设置管理员");
11309
+ const spec = JSON.stringify([groupInfo == null ? void 0 : groupInfo.groupName, ownerUserID, [...memberUserIDs || []].sort()]);
11310
+ const requestID = String((groupInfo == null ? void 0 : groupInfo.groupID) || this.pendingGroupCreates.get(spec) || operationID);
11311
+ this.pendingGroupCreates.set(spec, requestID);
11312
+ const result = await requestInstance.post(`${this.businessApiUrl}/api/v1/openim/createTenantGroup`, {
11313
+ requestID,
11314
+ groupName: groupInfo == null ? void 0 : groupInfo.groupName,
11315
+ members: memberUserIDs || []
11316
+ });
11317
+ if (this.disposed || !this.isCurrentSession()) throw new IMSessionChangedError();
11318
+ if (((_a = result.data) == null ? void 0 : _a.code) !== 200) throw new Error(((_b = result.data) == null ? void 0 : _b.msg) || "建群失败");
11319
+ this.pendingGroupCreates.delete(spec);
11320
+ return true;
11321
+ }
10999
11322
  try {
11000
- const res = await ((_a = this.IMSDK) == null ? void 0 : _a.createGroup(
11323
+ const res = await ((_c = this.IMSDK) == null ? void 0 : _c.createGroup(
11001
11324
  {
11002
11325
  groupInfo,
11003
11326
  memberUserIDs,
@@ -11066,6 +11389,10 @@ class ImKit extends EventEmitter {
11066
11389
  * @param {String} operationID
11067
11390
  */
11068
11391
  async inviteUserToGroup({ groupID, userIDList: userIDList2, reason }, operationID = uuidv4()) {
11392
+ if (this.imIdentityVersion === 2) {
11393
+ assertIMTarget(groupID, "group");
11394
+ for (const id of userIDList2 || []) assertIMTarget(id);
11395
+ }
11069
11396
  if (!groupID || !this.IMSDK) return;
11070
11397
  try {
11071
11398
  const res = await this.IMSDK.inviteUserToGroup({ groupID, userIDList: userIDList2, reason }, operationID);
@@ -11412,165 +11739,6 @@ class ImKit extends EventEmitter {
11412
11739
  }
11413
11740
  }
11414
11741
  }
11415
- const useChatStore = defineStore("chatMessage", {
11416
- state: () => {
11417
- return {
11418
- userID: "",
11419
- // 用户ID
11420
- nickname: "",
11421
- // 用户昵称
11422
- faceURL: "",
11423
- // 用户头像
11424
- platformID: IM_LOGIN_PLATFORM.Web,
11425
- loginStatus: IM_LOGIN_STATUS.Logout,
11426
- // 登录状态
11427
- groupStatus: IM_GROUP_STATUS.Nomal,
11428
- // 群组状态
11429
- apiUrl: "",
11430
- wsUrl: "",
11431
- tenantID: "",
11432
- satoken: "",
11433
- // 系统Token
11434
- imToken: "",
11435
- // IM token
11436
- chatToken: "",
11437
- // 聊天token
11438
- unReadCount: 0,
11439
- // 本账号所有未读消息
11440
- currentChatId: "",
11441
- // 当前会话ID
11442
- isFocused: true,
11443
- // 窗口是否聚焦
11444
- remoteConnectUrl: "",
11445
- // 向日葵被控端连接地址
11446
- remoteConnectToken: "",
11447
- // 被控端连接token(session)
11448
- isViewingChat: false
11449
- // 是否在H5聊天详情页(控制自动标记已读)
11450
- };
11451
- },
11452
- getters: {
11453
- // 获取当前会话ID
11454
- getCurrentChatId(state) {
11455
- return state.currentChatId;
11456
- },
11457
- // 获取用户登录状态
11458
- getLoginStatus(state) {
11459
- return state.loginStatus;
11460
- },
11461
- // 获取基本地址路径
11462
- getBaseUrl(state) {
11463
- return state.apiUrl;
11464
- },
11465
- // 获取socket链接路径
11466
- getWsUrl(state) {
11467
- return state.wsUrl;
11468
- },
11469
- // 获取系统token
11470
- getToken(state) {
11471
- return state.satoken;
11472
- },
11473
- // 获取租户ID
11474
- getTenantID(state) {
11475
- return state.tenantID;
11476
- },
11477
- // 获取用户登录信息
11478
- getUserInfo(state) {
11479
- return {
11480
- userID: state.userID,
11481
- nickname: state.nickname,
11482
- faceURL: state.faceURL,
11483
- loginStatus: state.loginStatus,
11484
- platformID: state.platformID,
11485
- satoken: state.satoken,
11486
- tenantID: state.tenantID,
11487
- imToken: state.imToken,
11488
- chatToken: state.chatToken
11489
- };
11490
- },
11491
- // 获取未读消息总数
11492
- getUnReadCount(state) {
11493
- return state.unReadCount;
11494
- },
11495
- // 获取窗口是否聚焦
11496
- getIsFocused(state) {
11497
- return state.isFocused;
11498
- },
11499
- // 获取被控端连接地址
11500
- getRemoteConnectUrl(state) {
11501
- return state.remoteConnectUrl;
11502
- },
11503
- // 获取被控端连接token
11504
- getRemoteConnectToken(state) {
11505
- return state.remoteConnectToken;
11506
- },
11507
- // 获取是否在查看H5聊天详情
11508
- getIsViewingChat(state) {
11509
- return state.isViewingChat;
11510
- }
11511
- },
11512
- actions: {
11513
- // 设置当前会话ID
11514
- setCurrentChatId(id) {
11515
- this.currentChatId = id;
11516
- },
11517
- // 更新未读总数
11518
- setUnReadCount(count = 0) {
11519
- this.unReadCount = count;
11520
- },
11521
- // 更新用户的登录状态
11522
- setLoginStatus(val) {
11523
- this.loginStatus = val;
11524
- },
11525
- // 更新群组状态
11526
- setGroupStatus(val) {
11527
- this.groupStatus = val;
11528
- },
11529
- // 保存登录用户信息
11530
- setUserInfo(obj) {
11531
- this.userID = (obj == null ? void 0 : obj.userID) || this.userID;
11532
- this.nickname = (obj == null ? void 0 : obj.nickname) || this.nickname;
11533
- this.faceURL = (obj == null ? void 0 : obj.faceURL) || this.faceURL;
11534
- this.imToken = (obj == null ? void 0 : obj.imToken) || this.imToken;
11535
- this.chatToken = (obj == null ? void 0 : obj.chatToken) || this.chatToken;
11536
- this.satoken = (obj == null ? void 0 : obj.satoken) || this.satoken;
11537
- this.apiUrl = (obj == null ? void 0 : obj.apiUrl) || this.apiUrl;
11538
- this.wsUrl = (obj == null ? void 0 : obj.wsUrl) || this.wsUrl;
11539
- this.tenantID = (obj == null ? void 0 : obj.tenantID) || this.tenantID;
11540
- this.platformID = obj.platformID || this.platformID;
11541
- },
11542
- // 设置窗口聚焦状态
11543
- setIsFocused(val) {
11544
- this.isFocused = val;
11545
- },
11546
- // 设置被控端连接地址
11547
- setRemoteConnectUrl(url) {
11548
- this.remoteConnectUrl = url;
11549
- },
11550
- // 设置被控端连接token
11551
- setRemoteConnectToken(token) {
11552
- this.remoteConnectToken = token;
11553
- },
11554
- // 设置是否在查看H5聊天详情
11555
- setIsViewingChat(val) {
11556
- this.isViewingChat = val;
11557
- }
11558
- },
11559
- persist: {
11560
- enabled: true,
11561
- // 开启持久化
11562
- strategies: [
11563
- {
11564
- key: "MDM_CHAT_MESSAGE",
11565
- // 存储的 key 名(默认 store id)
11566
- storage: localStorage,
11567
- // 存储位置(默认 localStorage)
11568
- // HttpOnly Cookie 认证:satoken 和 imToken 不再持久化到 localStorage,仅保留在 Pinia 内存中
11569
- paths: ["userID", "nickname", "faceURL", "platformID", "apiUrl", "wsUrl", "tenantID"]
11570
- }
11571
- ]
11572
- }
11573
- });
11574
11742
  const userList = ref([]);
11575
11743
  const userIDList = ref([]);
11576
11744
  const userOnlineStatus = ref({});
@@ -11608,7 +11776,12 @@ const useUsers = () => {
11608
11776
  const getAllUserStatus = () => {
11609
11777
  return userOnlineStatus.value;
11610
11778
  };
11611
- return { updateUserList, getUserIds, updateUserStatus, getCurrentUserInfo, getAllUserStatus, getUserStatus };
11779
+ const resetUsers = () => {
11780
+ userList.value = [];
11781
+ userIDList.value = [];
11782
+ userOnlineStatus.value = {};
11783
+ };
11784
+ return { resetUsers, updateUserList, getUserIds, updateUserStatus, getCurrentUserInfo, getAllUserStatus, getUserStatus };
11612
11785
  };
11613
11786
  function getDefaultExportFromCjs(x3) {
11614
11787
  return x3 && x3.__esModule && Object.prototype.hasOwnProperty.call(x3, "default") ? x3["default"] : x3;
@@ -36257,7 +36430,12 @@ const toPinyin = (text) => {
36257
36430
  const conversationList = ref([]);
36258
36431
  const skipSortIds = /* @__PURE__ */ new Set();
36259
36432
  const currentConversation = ref({});
36260
- ref([]);
36433
+ const currentConversationUsers = ref([]);
36434
+ let conversationListReady = false;
36435
+ const setConversationListReady = (value) => {
36436
+ conversationListReady = Boolean(value);
36437
+ };
36438
+ const isConversationListReady = () => conversationListReady;
36261
36439
  const useConversations = () => {
36262
36440
  const chatMessage = useChatStore();
36263
36441
  const baseUrl = chatMessage.getBaseUrl;
@@ -36386,8 +36564,12 @@ const useConversations = () => {
36386
36564
  currentConversation.value = curCvs;
36387
36565
  }
36388
36566
  const unreadCount = getUnReadMessageCount();
36389
- if (chatMessage.setUnReadCount) {
36390
- chatMessage.setUnReadCount(unreadCount);
36567
+ if (conversationListReady) {
36568
+ if (chatMessage.setUnReadCount) {
36569
+ chatMessage.setUnReadCount(unreadCount);
36570
+ }
36571
+ } else {
36572
+ console.log("[IM][unread] 会话列表未加载完成,跳过列表汇总覆盖", { listCount: unreadCount });
36391
36573
  }
36392
36574
  };
36393
36575
  const getCurrentConversation = (id) => {
@@ -36446,6 +36628,9 @@ const useConversations = () => {
36446
36628
  if (id) skipSortIds.add(id);
36447
36629
  };
36448
36630
  const clearConversationList = () => {
36631
+ skipSortIds.clear();
36632
+ conversationListReady = false;
36633
+ currentConversationUsers.value = [];
36449
36634
  conversationList.value = [];
36450
36635
  currentConversation.value = {};
36451
36636
  chatMessage.setUnReadCount(0);
@@ -36460,7 +36645,9 @@ const useConversations = () => {
36460
36645
  getConversationIDBySessionType,
36461
36646
  getConversationByKey,
36462
36647
  markSkipNextSort,
36463
- clearConversationList
36648
+ clearConversationList,
36649
+ setConversationListReady,
36650
+ isConversationListReady
36464
36651
  };
36465
36652
  };
36466
36653
  const ga1 = "data:image/png;base64,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";
@@ -36848,9 +37035,10 @@ const getSelectionText = () => {
36848
37035
  return "";
36849
37036
  };
36850
37037
  const NOTICE_AGENT_PREFIX = "agent_";
37038
+ const isNoticeAgentUser = (userID) => String(userID || "").startsWith(NOTICE_AGENT_PREFIX);
36851
37039
  const isNoticeAgentConversation = (cvs) => {
36852
37040
  if (!cvs || cvs.conversationType !== IM_CVS_TYPE.Single) return false;
36853
- return String(cvs.userID || "").startsWith(NOTICE_AGENT_PREFIX);
37041
+ return isNoticeAgentUser(cvs.userID);
36854
37042
  };
36855
37043
  const createCvsId = (msg) => {
36856
37044
  if (msg.sessionType === IM_CVS_TYPE.Single) {
@@ -37141,7 +37329,14 @@ const useMsgList = () => {
37141
37329
  }
37142
37330
  return obj.sessionType === IM_CVS_TYPE.Group ? `${obj.senderNickname}: [未知消息]` : `${obj.senderNickname}发送了消息`;
37143
37331
  };
37332
+ const clearMessageList = () => {
37333
+ messageList.value = [];
37334
+ startClientMsgID.value = "";
37335
+ isLastMessage.value = true;
37336
+ isFirstMessage.value = false;
37337
+ };
37144
37338
  return {
37339
+ clearMessageList,
37145
37340
  messageList,
37146
37341
  startClientMsgID,
37147
37342
  isLastMessage,
@@ -37322,7 +37517,7 @@ const useBurnAfterReading = () => {
37322
37517
  const origin = Number(startAt) || Date.now();
37323
37518
  const deadline = origin + duration * 1e3;
37324
37519
  if (deadline <= Date.now()) {
37325
- setTimeout(() => runHandlers(conversationID, msg.clientMsgID), 0);
37520
+ timers.set(key, setTimeout(() => fireBurn(conversationID, msg.clientMsgID), 0));
37326
37521
  return;
37327
37522
  }
37328
37523
  deadlines.set(key, deadline);
@@ -39575,13 +39770,14 @@ async function clearCache(userID) {
39575
39770
  function useMessageCache() {
39576
39771
  const chatMessage = useChatStore();
39577
39772
  function _getUserID() {
39578
- return chatMessage.userID || "";
39773
+ return imCacheNamespace(chatMessage);
39579
39774
  }
39580
39775
  async function loadConversationsFromCache() {
39581
39776
  const userID = _getUserID();
39582
39777
  if (!userID) return null;
39583
39778
  try {
39584
39779
  const list = await loadConversations(userID);
39780
+ if (userID !== _getUserID()) return null;
39585
39781
  if (list && Array.isArray(list) && list.length > 0) {
39586
39782
  console.log(
39587
39783
  `[MessageCache] Loaded ${list.length} conversations from IndexedDB cache`
@@ -39609,6 +39805,7 @@ function useMessageCache() {
39609
39805
  if (!userID || !conversationID) return null;
39610
39806
  try {
39611
39807
  const list = await loadMessages(userID, conversationID);
39808
+ if (userID !== _getUserID()) return null;
39612
39809
  if (list && Array.isArray(list) && list.length > 0) {
39613
39810
  console.log(
39614
39811
  `[MessageCache] Loaded ${list.length} messages for ${conversationID} from IndexedDB cache`
@@ -39652,12 +39849,26 @@ function useMessageCache() {
39652
39849
  const mittBus = mitt();
39653
39850
  const newMsgAudioUrl = "data:audio/mpeg;base64,SUQzAwAAAAAgAFRJVDMAAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSlUUFVCAAAAGAAAANW+s6TL2LLEKHNjLmNoaW5hei5jb20pV09BUgAAABcAANW+s6TL2LLEKHNjLmNoaW5hei5jb20pVEVOQwAAABgAAADVvrOky9iyxChzYy5jaGluYXouY29tKVRBTEIAAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSlUWUVSAAAABQAAADIwMjBUUEUyAAAAGAAAANW+s6TL2LLEKHNjLmNoaW5hei5jb20pVElUMgAAABgAAADVvrOky9iyxChzYy5jaGluYXouY29tKVRDT04AAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSlDT01NAAAAHAAAAGNoaQDVvrOky9iyxChzYy5jaGluYXouY29tKVRQRTEAAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJRDMEAAAAADYkVFhYWAAAAAsAAANUREFUADMwMDYAVFhYWAAAAAsAAANUSU1FADIxMzEAVFhYWAAAAAoAAANjb21tZW50AABQUklWAAA1OQAAWE1QADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQzIDc5LjE2MTIxMCwgMjAxNy8wOC8xMS0xMDoyODozNiAgICAgICAgIj4KIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6eG1wRE09Imh0dHA6Ly9ucy5hZG9iZS5jb20veG1wLzEuMC9EeW5hbWljTWVkaWEvIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6Y3JlYXRvckF0b209Imh0dHA6Ly9ucy5hZG9iZS5jb20vY3JlYXRvckF0b20vMS4wLyIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3YjdlYjE0OC03ZTllLTA3NDctYTNlNS05NzlmN2IzZTQ4ODEiCiAgIHhtcE1NOkRvY3VtZW50SUQ9ImU4YTMzOWUyLWI5YjQtM2I5MC02OTFkLWMwZWMwMDAwMDAzZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjM2ZDgxZDUxLWYxM2QtMWQ0MS1hODYxLWIxZTlmZDEyMzgxOCIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMC0wNi0zMFQyMTozMTozNCswODowMCIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDYtMzBUMjE6MzE6MzQrMDg6MDAiCiAgIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUHJlbWllcmUgUHJvIENDIDIwMTguMCAoV2luZG93cykiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTA2LTMwVDIxOjMxOjA0KzA4OjAwIgogICB4bXBETTphdWRpb1NhbXBsZVJhdGU9Ii0xIgogICB4bXBETTphdWRpb1NhbXBsZVR5cGU9IjE2SW50IgogICB4bXBETTphdWRpb0NoYW5uZWxUeXBlPSJTdGVyZW8iCiAgIHhtcERNOnN0YXJ0VGltZVNjYWxlPSIzMDAwMCIKICAgeG1wRE06c3RhcnRUaW1lU2FtcGxlU2l6ZT0iMTAwMSIKICAgZGM6Zm9ybWF0PSJNUDMiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0iZDEwNTQ1NzMtNjlmMS02Y2M2LTJhYTItNzk0ZDAwMDAwMDZhIgogICAgICBzdEV2dDp3aGVuPSIyMDIwLTA2LTMwVDIxOjMxOjM0KzA4OjAwIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQcmVtaWVyZSBQcm8gQ0MgMjAxOC4wIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIvPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjIwYWNhNWE3LTAwMzQtNDM0OC05ZWQ4LTBlMWY3Y2IwOGVhZCIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMC0wNi0zMFQyMTozMTozNCswODowMCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUHJlbWllcmUgUHJvIENDIDIwMTguMCAoV2luZG93cykiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ZmYxY2M1NmItMmUyMS1kMTRlLThhMGEtYTZlYWVjY2ZjODVmIgogICAgICBzdEV2dDp3aGVuPSIyMDIwLTA2LTMwVDIxOjMxOjM0KzA4OjAwIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQcmVtaWVyZSBQcm8gQ0MgMjAxOC4wIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIvPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo3YjdlYjE0OC03ZTllLTA3NDctYTNlNS05NzlmN2IzZTQ4ODEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjAtMDYtMzBUMjE6MzE6MzQrMDg6MDAiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFByZW1pZXJlIFBybyBDQyAyMDE4LjAgKFdpbmRvd3MpIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvbWV0YWRhdGEiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogICA8eG1wTU06SW5ncmVkaWVudHM+CiAgICA8cmRmOkJhZz4KICAgICA8cmRmOmxpCiAgICAgIHN0UmVmOmluc3RhbmNlSUQ9IjBmODZjODFiLTgxYzAtOTY2Mi1lNGZlLTcyOTMwMDAwMDA2YSIKICAgICAgc3RSZWY6ZG9jdW1lbnRJRD0iZjNjYTE3ZDItZjhlNi1lNjY1LTMyZmEtYTI3ZDAwMDAwMDNkIgogICAgICBzdFJlZjpmcm9tUGFydD0idGltZTo1MDU1NzM4NjQ5NTBmMjU0MDE2MDAwMDAwZDIwOTIwMjk3ODYwMGYyNTQwMTYwMDAwMDAiCiAgICAgIHN0UmVmOnRvUGFydD0idGltZTowZDIwOTIwMjk3ODYwMGYyNTQwMTYwMDAwMDAiCiAgICAgIHN0UmVmOmZpbGVQYXRoPSLlvq7kv6HmnaXkv6Hmga8ubXA0IgogICAgICBzdFJlZjptYXNrTWFya2Vycz0iTm9uZSIvPgogICAgPC9yZGY6QmFnPgogICA8L3htcE1NOkluZ3JlZGllbnRzPgogICA8eG1wTU06UGFudHJ5PgogICAgPHJkZjpCYWc+CiAgICAgPHJkZjpsaT4KICAgICAgPHJkZjpEZXNjcmlwdGlvbgogICAgICAgeG1wOkNyZWF0ZURhdGU9IjE5MDQtMDEtMDFUMDA6MDBaIgogICAgICAgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDYtMzBUMjE6MzA6MzQrMDg6MDAiCiAgICAgICB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTA2LTMwVDIxOjMwOjM0KzA4OjAwIgogICAgICAgeG1wRE06bG9nQ29tbWVudD0i5pys6KeG6aKR55Sx5rmW5Y2X5LiA5ZSv5L+h5oGv56eR5oqA5byA5Y+R55qERVblvZXlsY/ova/ku7blvZXliLbvvIx3d3cuaWV3YXkuY24iCiAgICAgICB4bXBNTTpJbnN0YW5jZUlEPSIwZjg2YzgxYi04MWMwLTk2NjItZTRmZS03MjkzMDAwMDAwNmEiCiAgICAgICB4bXBNTTpEb2N1bWVudElEPSJmM2NhMTdkMi1mOGU2LWU2NjUtMzJmYS1hMjdkMDAwMDAwM2QiCiAgICAgICB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6OTk4YTUwOGUtY2IxMC01ODQ1LWI3YmItYzBhMTg2Yjk5YmJkIj4KICAgICAgPHhtcERNOmR1cmF0aW9uCiAgICAgICB4bXBETTp2YWx1ZT0iMTAyMTkiCiAgICAgICB4bXBETTpzY2FsZT0iMS8xMDAwIi8+CiAgICAgIDxkYzp0aXRsZT4KICAgICAgIDxyZGY6QWx0PgogICAgICAgIDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+RVblvZXlsY8zLjkuN+i9r+S7tuW9leWItjwvcmRmOmxpPgogICAgICAgPC9yZGY6QWx0PgogICAgICA8L2RjOnRpdGxlPgogICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgIDxyZGY6U2VxPgogICAgICAgIDxyZGY6bGkKICAgICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0iMGY4NmM4MWItODFjMC05NjYyLWU0ZmUtNzI5MzAwMDAwMDZhIgogICAgICAgICBzdEV2dDp3aGVuPSIyMDIwLTA2LTMwVDIxOjMwOjM0KzA4OjAwIgogICAgICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQcmVtaWVyZSBQcm8gQ0MgMjAxOC4wIChXaW5kb3dzKSIKICAgICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIvPgogICAgICAgPC9yZGY6U2VxPgogICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgIDwvcmRmOmxpPgogICAgPC9yZGY6QmFnPgogICA8L3htcE1NOlBhbnRyeT4KICAgPHhtcE1NOkRlcml2ZWRGcm9tCiAgICBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjIwYWNhNWE3LTAwMzQtNDM0OC05ZWQ4LTBlMWY3Y2IwOGVhZCIKICAgIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjBhY2E1YTctMDAzNC00MzQ4LTllZDgtMGUxZjdjYjA4ZWFkIgogICAgc3RSZWY6b3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjIwYWNhNWE3LTAwMzQtNDM0OC05ZWQ4LTBlMWY3Y2IwOGVhZCIvPgogICA8Y3JlYXRvckF0b206d2luZG93c0F0b20KICAgIGNyZWF0b3JBdG9tOmV4dGVuc2lvbj0iLnBycHJvaiIKICAgIGNyZWF0b3JBdG9tOmludm9jYXRpb25GbGFncz0iL0wiCiAgICBjcmVhdG9yQXRvbTp1bmNQcm9qZWN0UGF0aD0iXFw/XEM6XFVzZXJzXEFkbWluaXN0cmF0b3JcRGVza3RvcFzpn7PmlYgucHJwcm9qIi8+CiAgIDxjcmVhdG9yQXRvbTptYWNBdG9tCiAgICBjcmVhdG9yQXRvbTphcHBsaWNhdGlvbkNvZGU9IjEzNDc0NDk0NTUiCiAgICBjcmVhdG9yQXRvbTppbnZvY2F0aW9uQXBwbGVFdmVudD0iMTEyOTQ2ODAxOCIvPgogICA8eG1wRE06cHJvamVjdFJlZgogICAgeG1wRE06dHlwZT0ibW92aWUiLz4KICAgPHhtcERNOmR1cmF0aW9uCiAgICB4bXBETTp2YWx1ZT0iMjQiCiAgICB4bXBETTpzY2FsZT0iMTAwMS8zMDAwMCIvPgogICA8eG1wRE06c3RhcnRUaW1lY29kZQogICAgeG1wRE06dGltZUZvcm1hdD0iMjk5N0Ryb3BUaW1lY29kZSIKICAgIHhtcERNOnRpbWVWYWx1ZT0iMDA7MDA7MDA7MDAiLz4KICAgPHhtcERNOmFsdFRpbWVjb2RlCiAgICB4bXBETTp0aW1lVmFsdWU9IjAwOzAwOzAwOzAwIgogICAgeG1wRE06dGltZUZvcm1hdD0iMjk5N0Ryb3BUaW1lY29kZSIvPgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAg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R+ysrWhKgCe0AAAE////qEyAWeDSGdWZw2wAAAAAAA7PDy2vdviCQp8RAEQmECDyBc0BSO/M6dMN+qqSJlakAAgAYNLPMBcAqVkgNNRfSGxEAVUdCVoDEYqqM/kx96JCmFQDo5y2hvcRYcEUqljw70MeUb1TjyqNJFYy0te9HIr9amt56hKwQlBiAAOqUP+gJNVXC8qDUFX/yj2/T///9cUqAUFriUAu//uUZOiAAs400H1poAomobnNpAgBFw0hSfm8AkCqBqi/DDABgrUeDsQ1TEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//tUZOSD8lwZSU8kYAAbgTk54YAAAWwBJwAAACAAAD/AAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZOGP8AAAf4AAAAgAAA/wAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV";
39654
39851
  let imInstance = null;
39852
+ let failedLogoutClient = null;
39853
+ let sessionRevision = 0;
39854
+ let sessionQueue = Promise.resolve();
39855
+ let pendingSessionKey = "";
39856
+ const subscribedStores = /* @__PURE__ */ new WeakSet();
39857
+ let activeSessionScope = "";
39858
+ let reloginTimer = null;
39859
+ const enqueueSession = (operation) => {
39860
+ const result = sessionQueue.then(operation, operation);
39861
+ sessionQueue = result.catch(() => {
39862
+ });
39863
+ return result;
39864
+ };
39655
39865
  let initPromise = null;
39656
39866
  let httpAuthBroken = false;
39657
39867
  let syncFinished = false;
39658
39868
  let syncWaiters = [];
39659
39869
  let conversationBusBound = false;
39660
39870
  let burnHandlerBound = false;
39871
+ let lastUnreadCount = null;
39661
39872
  const resolveSyncWaiters = (ok) => {
39662
39873
  syncFinished = true;
39663
39874
  const waiters = syncWaiters.splice(0);
@@ -39671,7 +39882,8 @@ const resolveSyncWaiters = (ok) => {
39671
39882
  };
39672
39883
  const resetSyncState = () => {
39673
39884
  syncFinished = false;
39674
- syncWaiters = [];
39885
+ const waiters = syncWaiters.splice(0);
39886
+ waiters.forEach((done) => done(false));
39675
39887
  };
39676
39888
  const buildConversationFromMessage = (msg, selfUserID) => {
39677
39889
  if (!msg) return null;
@@ -39749,13 +39961,14 @@ const useMessage = (config = {}) => {
39749
39961
  }
39750
39962
  const loginStatus = computed(() => messageStore.loginStatus);
39751
39963
  let msgAudioEl = null;
39964
+ let initTimer = null;
39752
39965
  const getMsgAudio = () => {
39753
39966
  if (!msgAudioEl) {
39754
39967
  msgAudioEl = new Audio(newMsgAudioUrl);
39755
39968
  }
39756
39969
  return msgAudioEl;
39757
39970
  };
39758
- const { updateUserStatus } = useUsers();
39971
+ const { updateUserStatus, resetUsers } = useUsers();
39759
39972
  const {
39760
39973
  conversationList: conversationList2,
39761
39974
  currentConversation: currentConversation2,
@@ -39763,10 +39976,13 @@ const useMessage = (config = {}) => {
39763
39976
  updateConversationLatestMessage,
39764
39977
  getConversationIDBySessionType,
39765
39978
  getConversationByKey,
39766
- clearConversationList
39979
+ clearConversationList,
39980
+ setConversationListReady: setConversationListReady2,
39981
+ isConversationListReady: isConversationListReady2
39767
39982
  } = useConversations();
39768
39983
  const {
39769
39984
  messageList: messageList2,
39985
+ clearMessageList,
39770
39986
  updateMessageList,
39771
39987
  updateMessageIsRead,
39772
39988
  handleMessage,
@@ -39781,6 +39997,8 @@ const useMessage = (config = {}) => {
39781
39997
  onBurn(async (conversationID, clientMsgID) => {
39782
39998
  var _a;
39783
39999
  if (!conversationID || !clientMsgID) return;
40000
+ const burnScope = imSessionScope(messageStore);
40001
+ const burnRevision = sessionRevision;
39784
40002
  const inCurrentList = messageList2.value.some((item) => item.clientMsgID === clientMsgID);
39785
40003
  if (inCurrentList) deleteMessageById(clientMsgID);
39786
40004
  try {
@@ -39788,6 +40006,7 @@ const useMessage = (config = {}) => {
39788
40006
  } catch (error) {
39789
40007
  console.error("[IM] 删除焚毁消息失败:", error);
39790
40008
  }
40009
+ if (burnRevision !== sessionRevision || burnScope !== imSessionScope(messageStore)) return;
39791
40010
  if (inCurrentList) {
39792
40011
  const rest = JSON.parse(JSON.stringify(messageList2.value));
39793
40012
  saveMessagesToCache(conversationID, rest);
@@ -39797,6 +40016,7 @@ const useMessage = (config = {}) => {
39797
40016
  }
39798
40017
  try {
39799
40018
  const cached = await loadMessagesFromCache(conversationID);
40019
+ if (burnRevision !== sessionRevision || burnScope !== imSessionScope(messageStore)) return;
39800
40020
  if ((_a = cached == null ? void 0 : cached.list) == null ? void 0 : _a.length) {
39801
40021
  const rest = cached.list.filter((item) => item.clientMsgID !== clientMsgID);
39802
40022
  saveMessagesToCache(conversationID, rest);
@@ -39818,20 +40038,64 @@ const useMessage = (config = {}) => {
39818
40038
  if (((_a = currentConversation2.value) == null ? void 0 : _a.conversationID) === data.conversationID) {
39819
40039
  currentConversation2.value = { ...currentConversation2.value, ...data };
39820
40040
  }
40041
+ refreshUnreadCount();
39821
40042
  });
39822
40043
  }
39823
- const getUnReadMessageCount = async (bool = false) => {
40044
+ const publishUnreadCount = (reason = "update", extra = {}) => {
40045
+ if (reason === "init") {
40046
+ setConversationListReady2(true);
40047
+ if (conversationList2.value.length > 0) {
40048
+ const listCount = conversationList2.value.reduce(
40049
+ (pre, cur) => pre + (cur.unreadCount > 0 ? cur.unreadCount : 0),
40050
+ 0
40051
+ );
40052
+ messageStore.setUnReadCount(listCount);
40053
+ }
40054
+ }
40055
+ const count = Number(messageStore.getUnReadCount) || 0;
40056
+ lastUnreadCount = count;
40057
+ const payload = { count, reason, time: Date.now(), ...extra };
40058
+ console.log("[IM][unread] 广播未读消息事件", payload);
40059
+ mittBus.emit("IM_UNREAD_COUNT_CHANGED", payload);
40060
+ };
40061
+ const publishUnreadIfChanged = (reason = "update") => {
40062
+ if ((Number(messageStore.getUnReadCount) || 0) === lastUnreadCount) return;
40063
+ publishUnreadCount(reason);
40064
+ };
40065
+ const refreshUnreadCount = () => {
40066
+ if (isConversationListReady2()) {
40067
+ publishUnreadIfChanged("update");
40068
+ } else {
40069
+ getUnReadMessageCount(true);
40070
+ }
40071
+ };
40072
+ const getUnReadMessageCount = async (bool = false, reason = "update", extra = {}) => {
39824
40073
  if (bool) {
39825
40074
  if (!imInstance) return;
40075
+ const countScope = imSessionScope(messageStore);
40076
+ const countRevision = sessionRevision;
39826
40077
  const count = await (imInstance == null ? void 0 : imInstance.getTotalUnreadMsgCount());
40078
+ if (countRevision !== sessionRevision || countScope !== imSessionScope(messageStore)) return;
40079
+ if (count == null) {
40080
+ console.warn("[IM][unread] SDK 未读总数获取失败,保留当前未读数", {
40081
+ current: messageStore.getUnReadCount
40082
+ });
40083
+ return;
40084
+ }
40085
+ console.log("[IM][unread] 重新计算未读总数", { source: "sdk", count: count || 0, reason });
39827
40086
  messageStore.setUnReadCount(count || 0);
39828
40087
  } else {
39829
40088
  const count = conversationList2.value.reduce((pre, cur) => {
39830
40089
  return pre + (cur.unreadCount > 0 ? cur.unreadCount : 0);
39831
40090
  }, 0);
39832
- console.log("全部未读消息1:", count);
40091
+ console.log("[IM][unread] 重新计算未读总数", { source: "conversationList", count, reason });
39833
40092
  messageStore.setUnReadCount(count || 0);
39834
40093
  }
40094
+ if (reason === "receive") {
40095
+ publishUnreadCount(reason, extra);
40096
+ } else {
40097
+ publishUnreadIfChanged(reason);
40098
+ }
39835
40099
  };
39836
40100
  const setConversationMsgAsRead = async (id) => {
39837
40101
  var _a;
@@ -39853,47 +40117,91 @@ const useMessage = (config = {}) => {
39853
40117
  }
39854
40118
  return bool;
39855
40119
  };
39856
- const initIMSDK = async (force = false) => {
39857
- if (initPromise) return initPromise;
39858
- const sameSession = !force && !!imInstance && messageStore.loginStatus === IM_LOGIN_STATUS.Logged && imInstance.userID === String(messageStore.userID || "") && imInstance.imToken === messageStore.imToken && imInstance.apiUrl === `${messageStore.apiUrl}/imapi` && imInstance.wsUrl === `${messageStore.wsUrl}/imws`;
39859
- if (sameSession) {
39860
- window["imInstance"] = imInstance;
39861
- return true;
39862
- }
39863
- initPromise = (async () => {
39864
- if (messageStore.loginStatus === IM_LOGIN_STATUS.Logged) {
39865
- await clearInstance();
40120
+ const disposeInstance = async (clearData = true) => {
40121
+ if (reloginTimer) clearTimeout(reloginTimer);
40122
+ reloginTimer = null;
40123
+ if (initTimer) clearTimeout(initTimer);
40124
+ initTimer = null;
40125
+ unbindMessageEvent();
40126
+ cancelAllBurns();
40127
+ const previous = imInstance || failedLogoutClient;
40128
+ previous == null ? void 0 : previous.removeAllListeners();
40129
+ let loggedOut = false;
40130
+ try {
40131
+ const result = await (previous == null ? void 0 : previous.logout());
40132
+ if (result === false) throw new Error("IM 退出失败,请重试后再切换");
40133
+ loggedOut = true;
40134
+ } catch (error) {
40135
+ failedLogoutClient = previous;
40136
+ throw error;
40137
+ } finally {
40138
+ if (loggedOut) {
40139
+ previous == null ? void 0 : previous.clearSDK();
40140
+ if (failedLogoutClient === previous) failedLogoutClient = null;
39866
40141
  }
40142
+ if (imInstance === previous) imInstance = null;
40143
+ if (typeof window !== "undefined" && window.imInstance === previous) window.imInstance = null;
39867
40144
  resetSyncState();
39868
- if (!imInstance) {
39869
- imInstance = new ImKit({
39870
- userID: messageStore.userID,
39871
- imToken: messageStore.imToken,
39872
- chatToken: messageStore.chatToken,
39873
- apiUrl: messageStore.apiUrl,
39874
- wsUrl: messageStore.wsUrl
39875
- });
39876
- } else {
39877
- imInstance.userID = String(messageStore.userID || "");
39878
- imInstance.imToken = messageStore.imToken;
39879
- imInstance.chatToken = messageStore.chatToken;
39880
- imInstance.apiUrl = `${messageStore.apiUrl}/imapi`;
39881
- imInstance.wsUrl = `${messageStore.wsUrl}/imws`;
40145
+ lastUnreadCount = null;
40146
+ if (clearData) {
40147
+ clearConversationList();
40148
+ clearMessageList();
40149
+ resetUsers();
40150
+ messageStore.currentChatId = "";
40151
+ messageStore.remoteConnectUrl = "";
40152
+ messageStore.remoteConnectToken = "";
40153
+ messageStore.isViewingChat = false;
40154
+ }
40155
+ messageStore.setLoginStatus(IM_LOGIN_STATUS.Logout);
40156
+ }
40157
+ };
40158
+ const initIMSDK = async (force = false) => {
40159
+ const snapshot = { ...messageStore.$state, ...normalizeIMIdentity(messageStore) };
40160
+ const scope = imSessionScope(snapshot);
40161
+ if (!scope || !snapshot.imToken) return false;
40162
+ const key = JSON.stringify([scope, snapshot.imToken]);
40163
+ if (initPromise && pendingSessionKey === key) return initPromise;
40164
+ const sameSession = !force && imInstance && activeSessionScope === scope && messageStore.loginStatus === IM_LOGIN_STATUS.Logged && imInstance.imToken === snapshot.imToken;
40165
+ if (sameSession && !initPromise) return true;
40166
+ const revision = ++sessionRevision;
40167
+ pendingSessionKey = key;
40168
+ const operation = enqueueSession(async () => {
40169
+ if (revision !== sessionRevision || imSessionScope(messageStore) !== scope) return false;
40170
+ await disposeInstance(activeSessionScope !== scope);
40171
+ if (revision !== sessionRevision || imSessionScope(messageStore) !== scope) return false;
40172
+ activeSessionScope = scope;
40173
+ const client = new ImKit({
40174
+ userID: snapshot.userID,
40175
+ imToken: snapshot.imToken,
40176
+ chatToken: snapshot.chatToken,
40177
+ imIdentityVersion: snapshot.imIdentityVersion,
40178
+ apiUrl: snapshot.apiUrl,
40179
+ wsUrl: snapshot.wsUrl,
40180
+ platformID: snapshot.platformID,
40181
+ isCurrentSession: () => revision === sessionRevision && imSessionScope(messageStore) === scope
40182
+ });
40183
+ imInstance = client;
40184
+ client.initSDK();
40185
+ bindMessageEvent(client, revision, scope);
40186
+ const loginOk = await client.login();
40187
+ if (revision !== sessionRevision || imSessionScope(messageStore) !== scope) {
40188
+ await disposeInstance(true);
40189
+ return false;
39882
40190
  }
39883
- imInstance == null ? void 0 : imInstance.initSDK();
39884
- bindMessageEvent();
39885
- const loginOk = await (imInstance == null ? void 0 : imInstance.login());
39886
40191
  if (loginOk !== false) httpAuthBroken = false;
39887
- window["imInstance"] = imInstance;
40192
+ if (typeof window !== "undefined") window.imInstance = client;
39888
40193
  return loginOk !== false;
39889
- })();
40194
+ });
40195
+ initPromise = operation;
39890
40196
  try {
39891
- return await initPromise;
40197
+ return await operation;
39892
40198
  } finally {
39893
- initPromise = null;
40199
+ if (initPromise === operation) {
40200
+ initPromise = null;
40201
+ pendingSessionKey = "";
40202
+ }
39894
40203
  }
39895
40204
  };
39896
- let reloginTimer = null;
39897
40205
  let reloginAttempts = 0;
39898
40206
  let tokenInvalidNotified = false;
39899
40207
  let recoveredToken = "";
@@ -39910,11 +40218,17 @@ const useMessage = (config = {}) => {
39910
40218
  notifyTokenInvalid({ errMsg: "auto relogin exhausted" });
39911
40219
  return;
39912
40220
  }
40221
+ const recoveryScope = imSessionScope(messageStore);
40222
+ const recoveryRevision = sessionRevision;
39913
40223
  reloginTimer = setTimeout(async () => {
39914
40224
  reloginTimer = null;
40225
+ if (recoveryRevision !== sessionRevision || recoveryScope !== imSessionScope(messageStore)) return;
39915
40226
  reloginAttempts += 1;
39916
40227
  console.warn(`[IM] token 已失效,自动重新登录(第 ${reloginAttempts} 次)`);
39917
40228
  const ok = await initIMSDK(true);
40229
+ const recoveryClient = imInstance;
40230
+ const currentRevision = sessionRevision;
40231
+ if (recoveryScope !== imSessionScope(messageStore) || !recoveryClient) return;
39918
40232
  if (!ok) {
39919
40233
  tryRelogin();
39920
40234
  return;
@@ -39923,7 +40237,9 @@ const useMessage = (config = {}) => {
39923
40237
  tokenInvalidNotified = false;
39924
40238
  try {
39925
40239
  await waitForSyncFinish(8e3);
39926
- const list = await (imInstance == null ? void 0 : imInstance.getConversationListSplit(0, 200));
40240
+ if (currentRevision !== sessionRevision || recoveryScope !== imSessionScope(messageStore)) return;
40241
+ const list = await recoveryClient.getConversationListSplit(0, 200);
40242
+ if (currentRevision !== sessionRevision || recoveryScope !== imSessionScope(messageStore)) return;
39927
40243
  if (list == null ? void 0 : list.length) {
39928
40244
  handleConversationList(list, "init", handleMessage);
39929
40245
  }
@@ -39957,34 +40273,31 @@ const useMessage = (config = {}) => {
39957
40273
  tokenInvalidNotified = false;
39958
40274
  tryRelogin();
39959
40275
  };
39960
- const clearInstance = async (bool) => {
39961
- unbindMessageEvent();
39962
- cancelAllBurns();
39963
- imInstance == null ? void 0 : imInstance.removeAllListeners();
39964
- await (imInstance == null ? void 0 : imInstance.logout());
39965
- imInstance == null ? void 0 : imInstance.clearSDK();
39966
- if (imInstance) {
39967
- imInstance.syncFinished = false;
39968
- }
39969
- resetSyncState();
39970
- if (bool) {
39971
- imInstance = null;
39972
- window.imInstance = null;
39973
- clearConversationList();
39974
- }
39975
- messageStore.setLoginStatus(IM_LOGIN_STATUS.Logout);
40276
+ const clearInstance = async () => {
40277
+ ++sessionRevision;
40278
+ pendingSessionKey = "";
40279
+ if (reloginTimer) clearTimeout(reloginTimer);
40280
+ reloginTimer = null;
40281
+ return enqueueSession(async () => {
40282
+ await disposeInstance(true);
40283
+ activeSessionScope = "";
40284
+ });
39976
40285
  };
39977
- const bindMessageEvent = () => {
39978
- if (!imInstance || !imInstance.on) return;
39979
- imInstance.on("im-error", handleImError);
40286
+ const bindMessageEvent = (client, revision, scope) => {
40287
+ const isActive = () => revision === sessionRevision && client === imInstance && imSessionScope(messageStore) === scope;
40288
+ const onSessionEvent = (event, handler) => client.on(event, (...args) => {
40289
+ if (isActive()) return handler(...args);
40290
+ });
40291
+ if (!client || !client.on) return;
40292
+ onSessionEvent("im-error", handleImError);
39980
40293
  bindUnhandledRejection(handleImError);
39981
- imInstance.on(CbEvents.OnUserTokenExpired, () => {
40294
+ onSessionEvent(CbEvents.OnUserTokenExpired, () => {
39982
40295
  console.log("用户授权信息过期,重新登录");
39983
40296
  });
39984
- imInstance.on(CbEvents.OnSelfInfoUpdated, (data) => {
40297
+ onSessionEvent(CbEvents.OnSelfInfoUpdated, (data) => {
39985
40298
  console.log("用户资料更新:", data);
39986
40299
  });
39987
- imInstance.on(CbEvents.OnUserStatusChanged, (data) => {
40300
+ onSessionEvent(CbEvents.OnUserStatusChanged, (data) => {
39988
40301
  console.log("用户在线状态变化:", data);
39989
40302
  if (data == null ? void 0 : data.userID) {
39990
40303
  updateUserStatus([data]);
@@ -40006,11 +40319,10 @@ const useMessage = (config = {}) => {
40006
40319
  }
40007
40320
  });
40008
40321
  const handleSunloginEvent = (data) => {
40009
- var _a;
40010
- const info = typeof data.data === "string" && data.data.indexOf("{") > -1 ? JSON.parse(data.data) : {};
40322
+ const info = parseIMBusinessData(data.data);
40323
+ if (!info) return;
40011
40324
  const { event, sendUserID, recvUserID, sendUserName, address, session } = info;
40012
- const currentUserId = (_a = messageStore.getUserInfo) == null ? void 0 : _a.userID;
40013
- if (sendUserID === currentUserId) return;
40325
+ if (!shouldHandleRemoteNotice(info, messageStore.getUserInfo)) return;
40014
40326
  const SUN_EVENTS = {
40015
40327
  "create-sl-remote": () => mittBus.emit("createSLRemote", { address, session }),
40016
40328
  "apply-sl-control": () => mittBus.emit("applySLControl", { sendUserName, sendUserID, recvUserID }),
@@ -40024,17 +40336,13 @@ const useMessage = (config = {}) => {
40024
40336
  if (handler) handler();
40025
40337
  };
40026
40338
  const handleImNoticeEvent = (data) => {
40027
- var _a, _b;
40028
- const info = typeof data.data === "string" && data.data.indexOf("{") > -1 ? JSON.parse(data.data) : {};
40029
- const { event, sendUserID, imToken } = info;
40030
- if (event !== "LOGIN_NOTICE") return;
40031
- const currentUserId = (_a = messageStore.getUserInfo) == null ? void 0 : _a.userID;
40032
- const curImToken = (_b = messageStore.getUserInfo) == null ? void 0 : _b.imToken;
40033
- if (sendUserID === currentUserId && imToken !== curImToken) {
40339
+ const info = parseIMBusinessData(data.data);
40340
+ if (!info) return;
40341
+ if (shouldHandleLoginNotice(info, messageStore.getUserInfo)) {
40034
40342
  mittBus.emit("LOGOUT_NOTICE");
40035
40343
  }
40036
40344
  };
40037
- imInstance.on(CbEvents.OnRecvCustomBusinessMessage, (data) => {
40345
+ onSessionEvent(CbEvents.OnRecvCustomBusinessMessage, (data) => {
40038
40346
  if (data.key === "sunlogin") {
40039
40347
  handleSunloginEvent(data);
40040
40348
  } else if (data.key === "imNotice") {
@@ -40044,13 +40352,14 @@ const useMessage = (config = {}) => {
40044
40352
  const resolveConversationIDs = async (list) => {
40045
40353
  var _a;
40046
40354
  for (let i3 = 0; i3 < list.length; i3++) {
40355
+ if (!isActive()) return;
40047
40356
  const item = list[i3];
40048
40357
  let cvsId = getConversationIDBySessionType(item, "sendID");
40049
40358
  if (!cvsId) {
40050
40359
  let info = null;
40051
40360
  if (!httpAuthBroken) {
40052
40361
  try {
40053
- info = await (imInstance == null ? void 0 : imInstance.getOneConversation(
40362
+ info = await (client == null ? void 0 : client.getOneConversation(
40054
40363
  item.sessionType === IM_CVS_TYPE.Single ? item.sendID : item.groupID,
40055
40364
  item == null ? void 0 : item.sessionType
40056
40365
  ));
@@ -40058,6 +40367,7 @@ const useMessage = (config = {}) => {
40058
40367
  console.warn("[IM] 获取会话信息失败,改用消息数据兜底:", error);
40059
40368
  }
40060
40369
  }
40370
+ if (!isActive()) return;
40061
40371
  if (info == null ? void 0 : info.conversationID) {
40062
40372
  item.showName = info.showName;
40063
40373
  item.faceURL = info.faceURL;
@@ -40066,7 +40376,8 @@ const useMessage = (config = {}) => {
40066
40376
  handleConversationList([info], "add", handleMessage);
40067
40377
  if (info.ex) {
40068
40378
  const clearedEx = preserveBurnInEx("", info.ex);
40069
- await (imInstance == null ? void 0 : imInstance.setConversation({ conversationID: cvsId, ex: clearedEx }));
40379
+ await (client == null ? void 0 : client.setConversation({ conversationID: cvsId, ex: clearedEx }));
40380
+ if (!isActive()) return;
40070
40381
  info.ex = clearedEx;
40071
40382
  }
40072
40383
  } else {
@@ -40101,6 +40412,7 @@ const useMessage = (config = {}) => {
40101
40412
  for (const [cvsID, items] of grouped) {
40102
40413
  try {
40103
40414
  const cached = ((_a = await loadMessagesFromCache(cvsID)) == null ? void 0 : _a.list) || [];
40415
+ if (!isActive()) return;
40104
40416
  saveMessagesToCache(cvsID, dedupeMessages([...cached, ...items]));
40105
40417
  } catch (error) {
40106
40418
  console.warn("[IM] 兜底会话消息写入缓存失败:", error);
@@ -40111,6 +40423,7 @@ const useMessage = (config = {}) => {
40111
40423
  const curMsgList = [];
40112
40424
  const cvs = currentConversation2.value;
40113
40425
  for (let i3 = 0; i3 < list.length; i3++) {
40426
+ if (!isActive()) return;
40114
40427
  const item = list[i3];
40115
40428
  const cvsId = item.conversationID;
40116
40429
  if (item.sessionType === IM_CVS_TYPE.Single && (cvs == null ? void 0 : cvs.userID) === item.sendID || item.groupID && cvs.groupID === item.groupID) {
@@ -40128,11 +40441,14 @@ const useMessage = (config = {}) => {
40128
40441
  }
40129
40442
  return curMsgList;
40130
40443
  };
40131
- imInstance.on(CbEvents.OnRecvNewMessages, async (list) => {
40444
+ onSessionEvent(CbEvents.OnRecvNewMessages, async (list) => {
40445
+ var _a;
40132
40446
  console.log("批量接收消息:", list);
40133
40447
  if ((list == null ? void 0 : list.length) > 0) {
40134
40448
  await resolveConversationIDs(list);
40449
+ if (!isActive()) return;
40135
40450
  await cacheFallbackMessages(list);
40451
+ if (!isActive()) return;
40136
40452
  const curMsgList = routeMessages(list);
40137
40453
  if (curMsgList.length > 0) {
40138
40454
  const cvs = currentConversation2.value;
@@ -40141,9 +40457,12 @@ const useMessage = (config = {}) => {
40141
40457
  const latestMsg = curMsgList[curMsgList.length - 1];
40142
40458
  updateConversationLatestMessage(cvs.conversationID, latestMsg, handleMessage(latestMsg));
40143
40459
  }
40460
+ if (!isActive()) return;
40461
+ const cvsId = ((_a = list[list.length - 1]) == null ? void 0 : _a.conversationID) || "";
40462
+ await getUnReadMessageCount(!isConversationListReady2(), "receive", { conversationID: cvsId });
40144
40463
  }
40145
40464
  });
40146
- imInstance.on(CbEvents.OnRecvC2CReadReceipt, async (list) => {
40465
+ onSessionEvent(CbEvents.OnRecvC2CReadReceipt, async (list) => {
40147
40466
  if ((list == null ? void 0 : list.length) > 0) {
40148
40467
  const cvs = currentConversation2.value;
40149
40468
  const curList = list.filter((item) => item.userID === (cvs == null ? void 0 : cvs.userID) && item.sessionType === IM_CVS_TYPE.Single);
@@ -40158,45 +40477,52 @@ const useMessage = (config = {}) => {
40158
40477
  setConversationMsgAsRead(cvs.conversationID);
40159
40478
  }
40160
40479
  });
40161
- imInstance.on(CbEvents.OnNewRecvMessageRevoked, (data) => {
40480
+ onSessionEvent(CbEvents.OnNewRecvMessageRevoked, (data) => {
40162
40481
  if (data == null ? void 0 : data.clientMsgID) {
40163
40482
  revokeMessage(data);
40164
40483
  }
40165
40484
  });
40166
- imInstance.on("updateStatus", (val = 1) => {
40485
+ onSessionEvent("updateStatus", (val = 1) => {
40167
40486
  console.log("登录状态", val);
40168
40487
  messageStore.setLoginStatus(val);
40169
40488
  if (val === IM_LOGIN_STATUS.Logged) {
40170
- setTimeout(() => {
40171
- getUnReadMessageCount();
40489
+ initTimer = setTimeout(() => {
40490
+ if (!isActive()) return;
40491
+ getUnReadMessageCount(true);
40172
40492
  }, 1e3);
40173
40493
  } else if (val === IM_LOGIN_STATUS.Logout) {
40174
40494
  mittBus.emit("IM_LOGOUT");
40175
40495
  }
40176
40496
  });
40177
- imInstance.on(CbEvents.OnSyncServerStart, () => {
40497
+ onSessionEvent(CbEvents.OnSyncServerStart, () => {
40178
40498
  console.log("IM 服务端同步开始");
40179
40499
  syncFinished = false;
40180
40500
  });
40181
- imInstance.on(CbEvents.OnSyncServerFinish, () => {
40501
+ onSessionEvent(CbEvents.OnSyncServerFinish, () => {
40182
40502
  console.log("IM 服务端同步完成");
40183
40503
  resolveSyncWaiters(true);
40184
40504
  mittBus.emit("IM_SYNC_SERVER_FINISH", true);
40505
+ getUnReadMessageCount(true);
40185
40506
  });
40186
- imInstance.on(CbEvents.OnSyncServerFailed, (data) => {
40507
+ onSessionEvent(CbEvents.OnSyncServerFailed, (data) => {
40187
40508
  console.warn("IM 服务端同步失败:", data);
40188
40509
  resolveSyncWaiters(false);
40189
40510
  mittBus.emit("IM_SYNC_SERVER_FINISH", false);
40190
40511
  });
40191
- imInstance.on("im-error", async (err) => {
40512
+ onSessionEvent("im-error", async (err) => {
40513
+ if (initTimer) {
40514
+ clearTimeout(initTimer);
40515
+ initTimer = null;
40516
+ }
40192
40517
  });
40193
- imInstance.on(CbEvents.OnConversationChanged, (data) => {
40518
+ onSessionEvent(CbEvents.OnConversationChanged, (data) => {
40194
40519
  if (Array.isArray(data) && (data == null ? void 0 : data.length)) {
40195
40520
  console.log("会话状态改变:", data);
40196
40521
  handleConversationList(data, "update", handleMessage);
40522
+ refreshUnreadCount();
40197
40523
  }
40198
40524
  });
40199
- imInstance.on(CbEvents.OnNewConversation, async (data) => {
40525
+ onSessionEvent(CbEvents.OnNewConversation, async (data) => {
40200
40526
  console.log("新会话:", data);
40201
40527
  if (data == null ? void 0 : data.length) {
40202
40528
  const cvsIds = conversationList2.value.map((item) => item.conversationID);
@@ -40204,7 +40530,8 @@ const useMessage = (config = {}) => {
40204
40530
  const userIds = newList.filter((item) => item.conversationType === IM_CVS_TYPE.Single).map((item) => item.userID);
40205
40531
  let statusInfo = {};
40206
40532
  if (userIds.length > 0) {
40207
- const statusList = await (imInstance == null ? void 0 : imInstance.subscribeUsersStatus(userIds));
40533
+ const statusList = await (client == null ? void 0 : client.subscribeUsersStatus(userIds));
40534
+ if (!isActive()) return;
40208
40535
  statusInfo = updateUserStatus(statusList);
40209
40536
  }
40210
40537
  newList.forEach((item) => {
@@ -40217,51 +40544,52 @@ const useMessage = (config = {}) => {
40217
40544
  } else if (newList.length > 0) {
40218
40545
  handleConversationList(newList, "add", handleMessage);
40219
40546
  }
40547
+ refreshUnreadCount();
40220
40548
  mittBus.emit("OnNewConversationCreated", data);
40221
40549
  }
40222
40550
  });
40223
- imInstance.on(CbEvents.OnGroupInfoChanged, (data) => {
40551
+ onSessionEvent(CbEvents.OnGroupInfoChanged, (data) => {
40224
40552
  if (data == null ? void 0 : data.groupID) {
40225
40553
  mittBus.emit("OnGroupInfoChanged", data);
40226
40554
  }
40227
40555
  });
40228
- imInstance.on(CbEvents.OnGroupMemberInfoChanged, (data) => {
40556
+ onSessionEvent(CbEvents.OnGroupMemberInfoChanged, (data) => {
40229
40557
  if (data == null ? void 0 : data.groupID) {
40230
40558
  updateMessageSenderInfo(data);
40231
40559
  mittBus.emit("OnGroupMemberInfoChanged", data);
40232
40560
  }
40233
40561
  });
40234
- imInstance.on(CbEvents.OnJoinedGroupAdded, (data) => {
40562
+ onSessionEvent(CbEvents.OnJoinedGroupAdded, (data) => {
40235
40563
  if (data == null ? void 0 : data.groupID) {
40236
40564
  mittBus.emit("OnJoinedGroupAdded", data.groupID);
40237
40565
  }
40238
40566
  });
40239
- imInstance.on(CbEvents.OnGroupMemberAdded, (data) => {
40567
+ onSessionEvent(CbEvents.OnGroupMemberAdded, (data) => {
40240
40568
  if (data == null ? void 0 : data.groupID) {
40241
40569
  mittBus.emit("OnGroupMemberAdded", data);
40242
40570
  }
40243
40571
  });
40244
- imInstance.on(CbEvents.OnGroupApplicationAdded, (data) => {
40572
+ onSessionEvent(CbEvents.OnGroupApplicationAdded, (data) => {
40245
40573
  console.log("收到入群申请通知:", data);
40246
40574
  mittBus.emit("OnGroupApplicationAdded", data);
40247
40575
  });
40248
- imInstance.on(CbEvents.OnGroupApplicationAccepted, (data) => {
40576
+ onSessionEvent(CbEvents.OnGroupApplicationAccepted, (data) => {
40249
40577
  console.log("入群申请被同意:", data);
40250
40578
  mittBus.emit("OnGroupApplicationAccepted", data);
40251
40579
  });
40252
- imInstance.on(CbEvents.OnGroupApplicationRejected, (data) => {
40580
+ onSessionEvent(CbEvents.OnGroupApplicationRejected, (data) => {
40253
40581
  console.log("入群申请被拒绝:", data);
40254
40582
  mittBus.emit("OnGroupApplicationRejected", data);
40255
40583
  });
40256
- imInstance.on(CbEvents.OnJoinedGroupDeleted, (data) => {
40584
+ onSessionEvent(CbEvents.OnJoinedGroupDeleted, (data) => {
40257
40585
  if (data.groupID) {
40258
40586
  mittBus.emit("OnJoinedGroupDeleted", data.groupID);
40259
40587
  }
40260
40588
  });
40261
- imInstance.on(CbEvents.OnGroupMemberDeleted, (data) => {
40589
+ onSessionEvent(CbEvents.OnGroupMemberDeleted, (data) => {
40262
40590
  mittBus.emit("OnGroupMemberDeleted", data);
40263
40591
  });
40264
- imInstance.on(CbEvents.OnGroupDismissed, (data) => {
40592
+ onSessionEvent(CbEvents.OnGroupDismissed, (data) => {
40265
40593
  if (data && data.groupID) {
40266
40594
  data.status = IM_GROUP_STATUS.Dismissed;
40267
40595
  mittBus.emit("OnGroupInfoChanged", data);
@@ -40296,6 +40624,24 @@ const useMessage = (config = {}) => {
40296
40624
  imInstance.off(CbEvents.OnGroupApplicationAccepted);
40297
40625
  imInstance.off(CbEvents.OnGroupApplicationRejected);
40298
40626
  };
40627
+ if (!subscribedStores.has(messageStore)) {
40628
+ subscribedStores.add(messageStore);
40629
+ let previousScope = imSessionScope(messageStore);
40630
+ messageStore.$subscribe((_mutation, state) => {
40631
+ let nextScope = "";
40632
+ try {
40633
+ nextScope = imSessionScope(state);
40634
+ } catch {
40635
+ }
40636
+ if (previousScope === nextScope) return;
40637
+ previousScope = nextScope;
40638
+ clearConversationList();
40639
+ clearMessageList();
40640
+ resetUsers();
40641
+ cancelAllBurns();
40642
+ void clearInstance().catch((error) => console.error("[IM] 会话切换清理失败:", error));
40643
+ }, { detached: true, flush: "sync" });
40644
+ }
40299
40645
  return {
40300
40646
  messageStore,
40301
40647
  loginStatus,
@@ -40303,68 +40649,72 @@ const useMessage = (config = {}) => {
40303
40649
  initIMSDK,
40304
40650
  clearInstance,
40305
40651
  getUnReadMessageCount,
40652
+ publishUnreadCount,
40306
40653
  setConversationMsgAsRead,
40307
40654
  waitForSyncFinish
40308
40655
  };
40309
40656
  };
40310
40657
  export {
40311
- getDefaultExportFromCjs as $,
40312
- isBurnMessage as A,
40658
+ sleep as $,
40659
+ formatSeconds as A,
40313
40660
  BURN_DEFAULT as B,
40314
- formatBurnRemain as C,
40315
- isBurned as D,
40316
- EXIT_CODE as E,
40317
- smoothScrollTo as F,
40318
- getJsonDetail as G,
40319
- getSelectionText as H,
40320
- IM_CVS_TYPE as I,
40321
- useBurnAfterReading as J,
40322
- createCvsId as K,
40323
- dedupeMessages as L,
40324
- handleUrl as M,
40325
- handleDate as N,
40326
- GROUP_JOIN_SOURCE as O,
40327
- GROUP_APPLICATION_STATUS as P,
40328
- useMessage as Q,
40329
- useUsers as R,
40330
- useConversations as S,
40331
- useMessageCache as T,
40332
- mittBus as U,
40333
- IM_LOGIN_STATUS as V,
40334
- preserveBurnInEx as W,
40335
- buildBurnEx as X,
40336
- sleep as Y,
40337
- uuidv4 as Z,
40338
- GROUP_VERIFICATION_TYPE as _,
40339
- getAvatarBg as a,
40340
- getMediaDuration as a0,
40341
- IM_FONT_SIZE as a1,
40342
- IM_FONT_FAMILY as a2,
40343
- IM_FONT_STYLE as a3,
40344
- formatFileSize as a4,
40345
- getAvatarText as b,
40346
- cloneDeep as c,
40347
- getConversationBurnSetting as d,
40348
- useDate as e,
40349
- isNoticeAgentConversation as f,
40661
+ getReplyDetail as C,
40662
+ useMsgList as D,
40663
+ throttle as E,
40664
+ isBurnMessage as F,
40665
+ formatBurnRemain as G,
40666
+ isBurned as H,
40667
+ IMSessionChangedError as I,
40668
+ smoothScrollTo as J,
40669
+ getJsonDetail as K,
40670
+ getSelectionText as L,
40671
+ useBurnAfterReading as M,
40672
+ createCvsId as N,
40673
+ dedupeMessages as O,
40674
+ handleUrl as P,
40675
+ handleDate as Q,
40676
+ GROUP_JOIN_SOURCE as R,
40677
+ GROUP_APPLICATION_STATUS as S,
40678
+ useMessage as T,
40679
+ useUsers as U,
40680
+ useConversations as V,
40681
+ useMessageCache as W,
40682
+ mittBus as X,
40683
+ IM_LOGIN_STATUS as Y,
40684
+ preserveBurnInEx as Z,
40685
+ buildBurnEx as _,
40686
+ IM_CVS_TYPE as a,
40687
+ uuidv4 as a0,
40688
+ GROUP_VERIFICATION_TYPE as a1,
40689
+ getDefaultExportFromCjs as a2,
40690
+ getMediaDuration as a3,
40691
+ IM_FONT_SIZE as a4,
40692
+ IM_FONT_FAMILY as a5,
40693
+ IM_FONT_STYLE as a6,
40694
+ formatFileSize as a7,
40695
+ isDefaultAvatar as b,
40696
+ getAvatarBg as c,
40697
+ getAvatarText as d,
40698
+ cloneDeep as e,
40699
+ getConversationBurnSetting as f,
40350
40700
  getGroupAvatarBg as g,
40351
- IM_GROUP_MEMBER_ROLE as h,
40352
- isDefaultAvatar as i,
40353
- IM_MSG_TYPE as j,
40354
- debounce as k,
40355
- IM_GROUP_STATUS as l,
40356
- IM_LOGIN_PLATFORM as m,
40357
- BURN_PRESETS as n,
40358
- formatBurnDuration as o,
40359
- BURN_MAX as p,
40360
- BURN_MIN as q,
40361
- handleLinks as r,
40362
- clampBurnDuration as s,
40363
- copyToClipboard as t,
40701
+ isNoticeAgentUser as h,
40702
+ imSessionScope as i,
40703
+ useDate as j,
40704
+ isNoticeAgentConversation as k,
40705
+ IM_GROUP_MEMBER_ROLE as l,
40706
+ IM_MSG_TYPE as m,
40707
+ debounce as n,
40708
+ IM_GROUP_STATUS as o,
40709
+ IM_LOGIN_PLATFORM as p,
40710
+ BURN_PRESETS as q,
40711
+ requestInstance as r,
40712
+ formatBurnDuration as s,
40713
+ BURN_MAX as t,
40364
40714
  useChatStore as u,
40365
- downloadFileByBlob as v,
40366
- formatSeconds as w,
40367
- getReplyDetail as x,
40368
- useMsgList as y,
40369
- throttle as z
40715
+ BURN_MIN as v,
40716
+ handleLinks as w,
40717
+ clampBurnDuration as x,
40718
+ copyToClipboard as y,
40719
+ downloadFileByBlob as z
40370
40720
  };