chatStore.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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.id && 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. chat.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. chat.lastSendTime = new Date().getTime();
  139. chat.stored = false;
  140. this.saveToStorage();
  141. }
  142. },
  143. insertMessage(msgInfo) {
  144. // 获取对方id或群id
  145. let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE';
  146. // 记录消息的最大id
  147. if (msgInfo.id && type == "PRIVATE" && msgInfo.id > this.privateMsgMaxId) {
  148. this.privateMsgMaxId = msgInfo.id;
  149. }
  150. if (msgInfo.id && type == "GROUP" && msgInfo.id > this.groupMsgMaxId) {
  151. this.groupMsgMaxId = msgInfo.id;
  152. }
  153. // 如果是已存在消息,则覆盖旧的消息数据
  154. let chat = this.findChat(msgInfo);
  155. let message = this.findMessage(chat, msgInfo);
  156. if (message) {
  157. Object.assign(message, msgInfo);
  158. // 撤回消息需要显示
  159. if (msgInfo.type == MESSAGE_TYPE.RECALL) {
  160. chat.lastContent = msgInfo.content;
  161. }
  162. chat.stored = false;
  163. this.saveToStorage();
  164. return;
  165. }
  166. // 会话列表内容
  167. if (msgInfo.type == MESSAGE_TYPE.IMAGE) {
  168. chat.lastContent = "[图片]";
  169. } else if (msgInfo.type == MESSAGE_TYPE.FILE) {
  170. chat.lastContent = "[文件]";
  171. } else if (msgInfo.type == MESSAGE_TYPE.AUDIO) {
  172. chat.lastContent = "[语音]";
  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. } else if (msgInfo.type == MESSAGE_TYPE.TEXT ||
  178. msgInfo.type == MESSAGE_TYPE.RECALL ||
  179. msgInfo.type == MESSAGE_TYPE.TIP_TEXT) {
  180. chat.lastContent = msgInfo.content;
  181. }
  182. chat.lastSendTime = msgInfo.sendTime;
  183. chat.sendNickName = msgInfo.sendNickName;
  184. // 未读加1
  185. if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED &&
  186. msgInfo.type != MESSAGE_TYPE.TIP_TEXT) {
  187. chat.unreadCount++;
  188. }
  189. // 是否有人@我
  190. if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds &&
  191. msgInfo.status != MESSAGE_STATUS.READED) {
  192. const userStore = useUserStore();
  193. let userId = userStore.userInfo.id;
  194. if (msgInfo.atUserIds.indexOf(userId) >= 0) {
  195. chat.atMe = true;
  196. }
  197. if (msgInfo.atUserIds.indexOf(-1) >= 0) {
  198. chat.atAll = true;
  199. }
  200. }
  201. // 间隔大于10分钟插入时间显示
  202. if (!chat.lastTimeTip || (chat.lastTimeTip < msgInfo.sendTime - 600 * 1000)) {
  203. chat.messages.push({
  204. sendTime: msgInfo.sendTime,
  205. type: MESSAGE_TYPE.TIP_TIME,
  206. });
  207. chat.lastTimeTip = msgInfo.sendTime;
  208. }
  209. // 根据id顺序插入,防止消息乱序
  210. let insertPos = chat.messages.length;
  211. // 防止 图片、文件 在发送方 显示 在顶端 因为还没存库,id=0
  212. if (msgInfo.id && msgInfo.id > 0) {
  213. for (let idx in chat.messages) {
  214. if (chat.messages[idx].id && msgInfo.id < chat.messages[idx].id) {
  215. insertPos = idx;
  216. console.log(`消息出现乱序,位置:${chat.messages.length},修正至:${insertPos}`);
  217. break;
  218. }
  219. }
  220. }
  221. if (insertPos == chat.messages.length) {
  222. // 这种赋值效率最高
  223. chat.messages[insertPos] = msgInfo;
  224. } else {
  225. chat.messages.splice(insertPos, 0, msgInfo);
  226. }
  227. chat.stored = false;
  228. this.saveToStorage();
  229. },
  230. updateMessage(msgInfo) {
  231. // 获取对方id或群id
  232. let chat = this.findChat(msgInfo);
  233. let message = this.findMessage(chat, msgInfo);
  234. if (message) {
  235. // 属性拷贝
  236. Object.assign(message, msgInfo);
  237. chat.stored = false;
  238. this.saveToStorage();
  239. }
  240. },
  241. deleteMessage(msgInfo) {
  242. // 获取对方id或群id
  243. let chat = this.findChat(msgInfo);
  244. for (let idx in chat.messages) {
  245. // 已经发送成功的,根据id删除
  246. if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) {
  247. chat.messages.splice(idx, 1);
  248. break;
  249. }
  250. // 正在发送中的消息可能没有id,根据发送时间删除
  251. if (msgInfo.selfSend && chat.messages[idx].selfSend &&
  252. chat.messages[idx].sendTime == msgInfo.sendTime) {
  253. chat.messages.splice(idx, 1);
  254. break;
  255. }
  256. }
  257. chat.stored = false;
  258. this.saveToStorage();
  259. },
  260. updateChatFromFriend(friend) {
  261. let chat = this.findChatByFriend(friend.id)
  262. if (chat && (chat.headImage != friend.headImageThumb ||
  263. chat.showName != friend.nickName)) {
  264. // 更新会话中的群名和头像
  265. chat.headImage = friend.headImageThumb;
  266. chat.showName = friend.nickName;
  267. chat.stored = false;
  268. this.saveToStorage();
  269. }
  270. },
  271. updateChatFromGroup(group) {
  272. let chat = this.findChatByGroup(group.id);
  273. if (chat && (chat.headImage != group.headImageThumb ||
  274. chat.showName != group.showGroupName)) {
  275. // 更新会话中的群名称和头像
  276. chat.headImage = group.headImageThumb;
  277. chat.showName = group.showGroupName;
  278. chat.stored = false;
  279. this.saveToStorage();
  280. }
  281. },
  282. setLoadingPrivateMsg(loading) {
  283. this.loadingPrivateMsg = loading;
  284. if (!this.isLoading()) {
  285. this.refreshChats()
  286. }
  287. },
  288. setLoadingGroupMsg(loading) {
  289. this.loadingGroupMsg = loading;
  290. if (!this.isLoading()) {
  291. this.refreshChats()
  292. }
  293. },
  294. refreshChats(state) {
  295. // 排序
  296. cacheChats.sort((chat1, chat2) => {
  297. return chat2.lastSendTime - chat1.lastSendTime;
  298. });
  299. // 将消息一次性装载回来
  300. this.chats = cacheChats;
  301. // 断线重连后不能使用缓存模式,否则会导致聊天窗口的消息不刷新
  302. cacheChats = this.chats;
  303. this.saveToStorage();
  304. },
  305. saveToStorage(state) {
  306. // 加载中不保存,防止卡顿
  307. if (this.isLoading()) {
  308. return;
  309. }
  310. const userStore = useUserStore();
  311. let userId = userStore.userInfo.id;
  312. let key = "chats-app-" + userId;
  313. let chatKeys = [];
  314. // 按会话为单位存储,只存储有改动的会话
  315. this.chats.forEach((chat)=>{
  316. let chatKey = `${key}-${chat.type}-${chat.targetId}`
  317. if(!chat.stored){
  318. if(chat.delete){
  319. uni.removeStorageSync(chatKey);
  320. }else{
  321. uni.setStorageSync(chatKey,chat);
  322. }
  323. chat.stored = true;
  324. }
  325. if(!chat.delete){
  326. chatKeys.push(chatKey);
  327. }
  328. })
  329. // 会话核心信息
  330. let chatsData = {
  331. privateMsgMaxId: this.privateMsgMaxId,
  332. groupMsgMaxId: this.groupMsgMaxId,
  333. chatKeys: chatKeys
  334. }
  335. uni.setStorageSync(key, chatsData)
  336. // 清理已删除的会话
  337. this.chats = this.chats.filter(chat => !chat.delete)
  338. },
  339. clear(state) {
  340. cacheChats = [];
  341. this.chats = [];
  342. this.privateMsgMaxId = 0;
  343. this.groupMsgMaxId = 0;
  344. this.loadingPrivateMsg = false;
  345. this.loadingGroupMsg = false;
  346. },
  347. loadChat(context) {
  348. return new Promise((resolve, reject) => {
  349. let userStore = useUserStore();
  350. let userId = userStore.userInfo.id;
  351. let chatsData = uni.getStorageSync("chats-app-" + userId)
  352. if(chatsData){
  353. if(chatsData.chatKeys){
  354. let time = new Date().getTime();
  355. chatsData.chats = [];
  356. chatsData.chatKeys.forEach(key=>{
  357. let chat = uni.getStorageSync(key);
  358. if(chat){
  359. chatsData.chats.push(chat);
  360. }
  361. })
  362. }
  363. this.initChats(chatsData);
  364. }
  365. resolve()
  366. })
  367. }
  368. },
  369. getters: {
  370. isLoading: (state) => () => {
  371. return state.loadingPrivateMsg || state.loadingGroupMsg
  372. },
  373. curChats: (state) => {
  374. return state.isLoading() ? cacheChats : state.chats;
  375. },
  376. findChatIdx: (state) => (chat) => {
  377. let chats = state.curChats;
  378. for (let idx in chats) {
  379. if (chats[idx].type == chat.type &&
  380. chats[idx].targetId === chat.targetId) {
  381. chat = state.chats[idx];
  382. return idx;
  383. }
  384. }
  385. },
  386. findChat: (state) => (msgInfo) => {
  387. let chats = state.curChats;
  388. // 获取对方id或群id
  389. let type = msgInfo.groupId ? 'GROUP' : 'PRIVATE';
  390. let targetId = msgInfo.groupId ? msgInfo.groupId : msgInfo.selfSend ? msgInfo.recvId : msgInfo
  391. .sendId;
  392. let chat = null;
  393. for (let idx in chats) {
  394. if (chats[idx].type == type &&
  395. chats[idx].targetId === targetId) {
  396. chat = chats[idx];
  397. break;
  398. }
  399. }
  400. return chat;
  401. },
  402. findChatByFriend: (state) => (fid) => {
  403. return state.curChats.find(chat => chat.type == 'PRIVATE' &&
  404. chat.targetId == fid)
  405. },
  406. findChatByGroup: (state) => (gid) => {
  407. return state.curChats.find(chat => chat.type == 'GROUP' &&
  408. chat.targetId == gid)
  409. },
  410. findMessage: (state) => (chat, msgInfo) => {
  411. if (!chat) {
  412. return null;
  413. }
  414. for (let idx in chat.messages) {
  415. // 通过id判断
  416. if (msgInfo.id && chat.messages[idx].id == msgInfo.id) {
  417. return chat.messages[idx];
  418. }
  419. // 正在发送中的消息可能没有id,只有tmpId
  420. if (msgInfo.tmpId && chat.messages[idx].tmpId &&
  421. chat.messages[idx].tmpId == msgInfo.tmpId) {
  422. return chat.messages[idx];
  423. }
  424. }
  425. }
  426. }
  427. });