chatStore.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. import { defineStore } from 'pinia';
  2. import { MESSAGE_TYPE, MESSAGE_STATUS } from '@/common/enums.js';
  3. import useUserStore from './userStore';
  4. let cacheChats = [];
  5. export default defineStore('chatStore', {
  6. state: () => {
  7. return {
  8. chats: [],
  9. privateMsgMaxId: 0,
  10. groupMsgMaxId: 0,
  11. loadingPrivateMsg: false,
  12. loadingGroupMsg: false
  13. }
  14. },
  15. actions: {
  16. initChats(chatsData) {
  17. cacheChats = [];
  18. this.chats = [];
  19. for (let chat of chatsData.chats) {
  20. // 暂存至缓冲区
  21. chat.stored = false;
  22. cacheChats.push(JSON.parse(JSON.stringify(chat)));
  23. // 加载期间显示只前15个会话做做样子,一切都为了加快初始化时间
  24. if (this.chats.length < 15) {
  25. chat.messages = [];
  26. this.chats.push(chat);
  27. }
  28. }
  29. this.privateMsgMaxId = chatsData.privateMsgMaxId || 0;
  30. this.groupMsgMaxId = chatsData.groupMsgMaxId || 0;
  31. // 防止图片一直处在加载中状态
  32. cacheChats.forEach((chat) => {
  33. chat.messages.forEach((msg) => {
  34. if (msg.loadStatus == "loading") {
  35. msg.loadStatus = "fail"
  36. }
  37. })
  38. })
  39. },
  40. openChat(chatInfo) {
  41. let chats = this.curChats;
  42. let chat = null;
  43. for (let idx in chats) {
  44. if (chats[idx].type == chatInfo.type &&
  45. chats[idx].targetId === chatInfo.targetId) {
  46. chat = chats[idx];
  47. // 放置头部
  48. this.moveTop(idx)
  49. break;
  50. }
  51. }
  52. // 创建会话
  53. if (chat == null) {
  54. chat = {
  55. targetId: chatInfo.targetId,
  56. type: chatInfo.type,
  57. showName: chatInfo.showName,
  58. headImage: chatInfo.headImage,
  59. lastContent: "",
  60. lastSendTime: new Date().getTime(),
  61. unreadCount: 0,
  62. messages: [],
  63. atMe: false,
  64. atAll: false,
  65. stored: false
  66. };
  67. chats.unshift(chat);
  68. this.saveToStorage();
  69. }
  70. },
  71. activeChat(idx) {
  72. let chats = this.curChats;
  73. if (idx >= 0) {
  74. chats[idx].unreadCount = 0;
  75. }
  76. },
  77. resetUnreadCount(chatInfo) {
  78. let chats = this.curChats;
  79. for (let idx in chats) {
  80. if (chats[idx].type == chatInfo.type &&
  81. chats[idx].targetId == chatInfo.targetId) {
  82. chats[idx].unreadCount = 0;
  83. chats[idx].atMe = false;
  84. chats[idx].atAll = false;
  85. chats[idx].stored = false;
  86. this.saveToStorage();
  87. }
  88. }
  89. },
  90. readedMessage(pos) {
  91. let chat = this.findChatByFriend(pos.friendId);
  92. chat.messages.forEach((m) => {
  93. if (m.selfSend && m.status < MESSAGE_STATUS.RECALL) {
  94. // pos.maxId为空表示整个会话已读
  95. if (!pos.maxId || m.id <= pos.maxId) {
  96. m.status = MESSAGE_STATUS.READED
  97. chats.stored = false;
  98. }
  99. }
  100. })
  101. if(!chat.stored){
  102. this.saveToStorage();
  103. }
  104. },
  105. removeChat(idx) {
  106. let chats = this.curChats;
  107. chats[idx].delete = true;
  108. chats[idx].stored = false;
  109. this.saveToStorage();
  110. },
  111. removePrivateChat(userId) {
  112. let chats = this.curChats;
  113. for (let idx in chats) {
  114. if (chats[idx].type == 'PRIVATE' &&
  115. chats[idx].targetId == userId) {
  116. this.removeChat(idx);
  117. }
  118. }
  119. },
  120. removeGroupChat(groupId) {
  121. let chats = this.curChats;
  122. for (let idx in chats) {
  123. if (chats[idx].type == 'GROUP' &&
  124. chats[idx].targetId == groupId) {
  125. this.removeChat(idx);
  126. }
  127. }
  128. },
  129. moveTop(idx) {
  130. if (this.isLoading()) {
  131. return;
  132. }
  133. let chats = this.curChats;
  134. if (idx > 0) {
  135. let chat = chats[idx];
  136. chats.splice(idx, 1);
  137. chats.unshift(chat);
  138. this.saveToStorage();
  139. }
  140. },
  141. insertMessage(msgInfo) {
  142. // 获取对方id或群id
  143. let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE';
  144. // 记录消息的最大id
  145. if (msgInfo.id && type == "PRIVATE" && msgInfo.id > this.privateMsgMaxId) {
  146. this.privateMsgMaxId = msgInfo.id;
  147. }
  148. if (msgInfo.id && type == "GROUP" && msgInfo.id > this.groupMsgMaxId) {
  149. this.groupMsgMaxId = msgInfo.id;
  150. }
  151. // 如果是已存在消息,则覆盖旧的消息数据
  152. let chat = this.findChat(msgInfo);
  153. let message = this.findMessage(chat, msgInfo);
  154. if (message) {
  155. Object.assign(message, msgInfo);
  156. // 撤回消息需要显示
  157. if (msgInfo.type == MESSAGE_TYPE.RECALL) {
  158. chat.lastContent = msgInfo.content;
  159. }
  160. chat.stored = false;
  161. this.saveToStorage();
  162. return;
  163. }
  164. // 会话列表内容
  165. if (msgInfo.type == MESSAGE_TYPE.IMAGE) {
  166. chat.lastContent = "[图片]";
  167. } else if (msgInfo.type == MESSAGE_TYPE.FILE) {
  168. chat.lastContent = "[文件]";
  169. } else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
  170. chat.lastContent = "[语音]";
  171. } else if (msgInfo.type == MESSAGE_TYPE.TEXT || msgInfo.type == MESSAGE_TYPE.RECALL) {
  172. chat.lastContent = msgInfo.content;
  173. } else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VOICE) {
  174. chat.lastContent = "[语音通话]";
  175. } else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VIDEO) {
  176. chat.lastContent = "[视频通话]";
  177. }
  178. chat.lastSendTime = msgInfo.sendTime;
  179. chat.sendNickName = msgInfo.sendNickName;
  180. // 未读加1
  181. if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED &&
  182. msgInfo.type != MESSAGE_TYPE.TIP_TEXT) {
  183. chat.unreadCount++;
  184. }
  185. // 是否有人@我
  186. if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds &&
  187. msgInfo.status != MESSAGE_STATUS.READED) {
  188. const userStore = useUserStore();
  189. let userId = userStore.userInfo.id;
  190. if (msgInfo.atUserIds.indexOf(userId) >= 0) {
  191. chat.atMe = true;
  192. }
  193. if (msgInfo.atUserIds.indexOf(-1) >= 0) {
  194. chat.atAll = true;
  195. }
  196. }
  197. // 间隔大于10分钟插入时间显示
  198. if (!chat.lastTimeTip || (chat.lastTimeTip < msgInfo.sendTime - 600 * 1000)) {
  199. chat.messages.push({
  200. sendTime: msgInfo.sendTime,
  201. type: MESSAGE_TYPE.TIP_TIME,
  202. });
  203. chat.lastTimeTip = msgInfo.sendTime;
  204. }
  205. // 根据id顺序插入,防止消息乱序
  206. let insertPos = chat.messages.length;
  207. // 防止 图片、文件 在发送方 显示 在顶端 因为还没存库,id=0
  208. if (msgInfo.id && msgInfo.id > 0) {
  209. for (let idx in chat.messages) {
  210. if (chat.messages[idx].id && msgInfo.id < chat.messages[idx].id) {
  211. insertPos = idx;
  212. console.log(`消息出现乱序,位置:${chat.messages.length},修正至:${insertPos}`);
  213. break;
  214. }
  215. }
  216. }
  217. if (insertPos == chat.messages.length) {
  218. // 这种赋值效率最高
  219. chat.messages[insertPos] = msgInfo;
  220. } else {
  221. chat.messages.splice(insertPos, 0, msgInfo);
  222. }
  223. chat.stored = false;
  224. this.saveToStorage();
  225. },
  226. updateMessage(msgInfo) {
  227. // 获取对方id或群id
  228. let chat = this.findChat(msgInfo);
  229. let message = this.findMessage(chat, msgInfo);
  230. if (message) {
  231. // 属性拷贝
  232. Object.assign(message, msgInfo);
  233. chat.stored = false;
  234. this.saveToStorage();
  235. }
  236. },
  237. deleteMessage(msgInfo) {
  238. // 获取对方id或群id
  239. let chat = this.findChat(msgInfo);
  240. for (let idx in chat.messages) {
  241. // 已经发送成功的,根据id删除
  242. if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) {
  243. chat.messages.splice(idx, 1);
  244. break;
  245. }
  246. // 正在发送中的消息可能没有id,根据发送时间删除
  247. if (msgInfo.selfSend && chat.messages[idx].selfSend &&
  248. chat.messages[idx].sendTime == msgInfo.sendTime) {
  249. chat.messages.splice(idx, 1);
  250. break;
  251. }
  252. }
  253. chat.stored = false;
  254. this.saveToStorage();
  255. },
  256. updateChatFromFriend(friend) {
  257. let chat = this.findChatByFriend(friend.id)
  258. if (chat.headImage != friend.headImageThumb ||
  259. chat.showName != friend.nickName) {
  260. // 更新会话中的群名和头像
  261. chat.headImage = friend.headImageThumb;
  262. chat.showName = friend.nickName;
  263. chat.stored = false;
  264. this.saveToStorage();
  265. }
  266. },
  267. updateChatFromGroup(group) {
  268. let chat = this.findChatByGroup(group.id);
  269. if (chat.headImage != group.headImageThumb ||
  270. chat.showName != group.showGroupName) {
  271. // 更新会话中的群名称和头像
  272. chat.headImage = group.headImageThumb;
  273. chat.showName = group.showGroupName;
  274. chat.stored = false;
  275. this.saveToStorage();
  276. }
  277. },
  278. setLoadingPrivateMsg(loading) {
  279. this.loadingPrivateMsg = loading;
  280. if (!this.isLoading()) {
  281. this.refreshChats()
  282. }
  283. },
  284. setLoadingGroupMsg(loading) {
  285. this.loadingGroupMsg = loading;
  286. if (!this.isLoading()) {
  287. this.refreshChats()
  288. }
  289. },
  290. refreshChats(state) {
  291. // 排序
  292. cacheChats.sort((chat1, chat2) => {
  293. return chat2.lastSendTime - chat1.lastSendTime;
  294. });
  295. // 将消息一次性装载回来
  296. this.chats = cacheChats;
  297. // 断线重连后不能使用缓存模式,否则会导致聊天窗口的消息不刷新
  298. cacheChats = this.chats;
  299. this.saveToStorage();
  300. },
  301. saveToStorage(state) {
  302. // 加载中不保存,防止卡顿
  303. if (this.isLoading()) {
  304. return;
  305. }
  306. const userStore = useUserStore();
  307. let userId = userStore.userInfo.id;
  308. let key = "chats-app-" + userId;
  309. let chatKeys = [];
  310. // 按会话为单位存储,只存储有改动的会话
  311. this.chats.forEach((chat)=>{
  312. let chatKey = `${key}-${chat.type}-${chat.targetId}`
  313. if(chat.delete){
  314. uni.removeStorageSync(chatKey);
  315. return;
  316. }
  317. if(!chat.stored){
  318. uni.setStorageSync(chatKey,chat);
  319. }
  320. chat.stored = true;
  321. chatKeys.push(chatKey);
  322. })
  323. // 会话核心信息
  324. let chatsData = {
  325. privateMsgMaxId: this.privateMsgMaxId,
  326. groupMsgMaxId: this.groupMsgMaxId,
  327. chatKeys: chatKeys
  328. //chats: this.chats
  329. }
  330. uni.setStorageSync(key, chatsData)
  331. },
  332. clear(state) {
  333. cacheChats = [];
  334. this.chats = [];
  335. this.privateMsgMaxId = 0;
  336. this.groupMsgMaxId = 0;
  337. this.loadingPrivateMsg = false;
  338. this.loadingGroupMsg = false;
  339. },
  340. loadChat(context) {
  341. return new Promise((resolve, reject) => {
  342. let userStore = useUserStore();
  343. let userId = userStore.userInfo.id;
  344. let chatsData = uni.getStorageSync("chats-app-" + userId)
  345. if(chatsData){
  346. if(chatsData.chatKeys){
  347. let time = new Date().getTime();
  348. chatsData.chats = [];
  349. chatsData.chatKeys.forEach(key=>{
  350. let chat = uni.getStorageSync(key);
  351. if(chat){
  352. chatsData.chats.push(chat);
  353. }
  354. })
  355. }
  356. this.initChats(chatsData);
  357. }
  358. resolve()
  359. })
  360. }
  361. },
  362. getters: {
  363. isLoading: (state) => () => {
  364. return state.loadingPrivateMsg || state.loadingGroupMsg
  365. },
  366. curChats: (state) => {
  367. return state.isLoading() ? cacheChats : state.chats;
  368. },
  369. findChatIdx: (state) => (chat) => {
  370. let chats = state.curChats;
  371. for (let idx in chats) {
  372. if (chats[idx].type == chat.type &&
  373. chats[idx].targetId === chat.targetId) {
  374. chat = state.chats[idx];
  375. return idx;
  376. }
  377. }
  378. },
  379. findChat: (state) => (msgInfo) => {
  380. let chats = state.curChats;
  381. // 获取对方id或群id
  382. let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE';
  383. let targetId = msgInfo.groupId ? msgInfo.groupId : msgInfo.selfSend ? msgInfo.recvId : msgInfo
  384. .sendId;
  385. let chat = null;
  386. for (let idx in chats) {
  387. if (chats[idx].type == type &&
  388. chats[idx].targetId === targetId) {
  389. chat = chats[idx];
  390. break;
  391. }
  392. }
  393. return chat;
  394. },
  395. findChatByFriend: (state) => (fid) => {
  396. return state.curChats.find(chat => chat.type == 'PRIVATE' &&
  397. chat.targetId == fid)
  398. },
  399. findChatByGroup: (state) => (gid) => {
  400. return state.curChats.find(chat => chat.type == 'GROUP' &&
  401. chat.targetId == gid)
  402. },
  403. findMessage: (state) => (chat, msgInfo) => {
  404. if (!chat) {
  405. return null;
  406. }
  407. for (let idx in chat.messages) {
  408. // 通过id判断
  409. if (msgInfo.id && chat.messages[idx].id == msgInfo.id) {
  410. return chat.messages[idx];
  411. }
  412. // 正在发送中的消息可能没有id,只有tmpId
  413. if (msgInfo.tmpId && chat.messages[idx].tmpId &&
  414. chat.messages[idx].tmpId == msgInfo.tmpId) {
  415. return chat.messages[idx];
  416. }
  417. }
  418. }
  419. }
  420. });