| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- import {defineStore} from 'pinia'
- import type Chat from '@/mode/Chat'
- import type Message from '@/mode/Message'
- import ChatType from '@/utils/ChatType'
- import GroupApi from '@/api/GroupApi'
- import UserApi from '../api/UserApi'
- import MessageType from '@/utils/MessageType'
- import FetchRequest from '@/api/FetchRequest'
- import {useSettingStore} from '@/store/settingStore'
- import DictUtils from '@/utils/DictUtils'
- import {useUserStore} from '@/store/userStore'
- import {useImmunityStore} from '@/store/immunityStore'
- import type Extend from '@/mode/Extend'
- import {useSysStore} from "@/store/sysStore";
- import type Receipt from "@/mode/Receipt";
- import {useWsStore} from "@/store/WsStore";
- import ChatApi from "@/api/ChatApi";
- import VimConfig from "@/config/VimConfig";
- import {decryptLong2 } from '@/store/cryptoAES';
- import dbApi from '@/api/DBactApi';
- export interface IState {
- chats: Array<Chat>;
- openChatId: string | null;
- last: number;
- quoteMessage: Message | undefined
- chatMessage: Map<string, Message[]>;
- chatLastTime: Map<string, number>;
- chatLastMessage: Map<string, string>;
- //未读消息id
- chatUnreadId: Map<string, Array<string>>
- }
- export const useChatStore = defineStore({
- id: 'chat_store',
- state: (): IState => ({
- chats: new Array<Chat>(),
- //当前打开的聊天室id
- openChatId: null,
- //消息声音提醒时间(限流作用)
- last: 0,
- //引用消息的id
- quoteMessage: undefined,
- chatMessage: new Map<string, Message[]>(),
- chatLastTime: new Map<string,number>(),
- chatLastMessage: new Map<string,string>(),
- chatUnreadId: new Map<string, []>()
- }),
- // // 开启数据缓存
- persist: {
- enabled: true,
- strategies: [
- {
- key: 'chat',
- storage: localStorage,
- paths: ['chatLastTime','chatLastMessage','chatUnreadId']
- }
- ]
- },
- getters: {
- allUnReadCount(): number {
- //console.log('allUnReadCount',this.chats)
- return this.chats.reduce((accumulator, currentValue) => accumulator + currentValue.unreadCount, 0)
- }
- },
- actions: {
- /**
- * 去重
- * @param chatArr 聊天室数组
- */
- removeDuplicateChats(chatArr: Chat[]) {
- return chatArr.reduce((prev: Chat[], cur: Chat) => {
- const has = prev.some((item) => item.id === cur.id)
- return has ? prev : [...prev, cur]
- }, [])
- },
- /**
- * 插入数据库
- * @param chatArr 聊天室数组
- */
- insertChats(chatArr: Chat[]){
- chatArr.forEach((item) => {
- dbApi.insertchat(item);
- })
- },
-
- /**
- * 重新加载聊历史记录
- */
- reloadChats() {
- var locatList=[];
- dbApi.selectchats().then((sres:any)=>{
- if(sres){
- //console.log('selectchats',sres);
- locatList=sres;
- }
- });
- return Promise.all([ChatApi.topList(), ChatApi.list()])
- .then((res) => {
- //console.log('reloadChats',res)
- this.chats = []
- const topChats = res[0].data
- topChats.forEach((item) => {
- item.top = true
- })
- const list = topChats.concat(res[1].data)
- list.forEach((item) => {
- item.unreadCount = (this.chatUnreadId[item.id]??[]).length
- })
-
- const rlist=list.concat(locatList);
- //console.log(rlist);
- //去重
- this.chats = this.removeDuplicateChats(rlist);
- //插入数据库
- this.insertChats(this.chats);
-
- return Promise.resolve()
- })
- },
- setQuoteMessage(quoteMessage: Message | undefined) {
- this.quoteMessage = quoteMessage
- },
- /**
- * 把一个消息推送到对应的聊天记录里面
- * @param message 消息
- */
- pushMessage(message: Message) {
- //console.log('pushMessage',message);
- const hideIndex = 10
- const chat = this.getChat(message.chatId)
- //所在的位置
- const chatIndex = this.getChatIndex(message.chatId)
- //消息是在队列的后面,用户可能看不到,需要把消息移到队列的前面
- if (chatIndex > hideIndex) {
- const topList = this.chats.filter((item) => !!item.top) // 查找已置顶元素的位置
- const topIndex = topList.length
- if (topIndex < hideIndex) {
- const temp = this.chats.splice(chatIndex, 1)[0];
- this.chats.splice(topIndex, 0, temp)
- //把消息列表更新到服务端
- ChatApi.move(message.chatId)
- }
- }
- //说明该聊天对话框已经存在
- if (chat) {
- this.addToMessageList(message, chat, true)
- } else {
- this.createChatRoom(message)
- const chat = this.getChat(message.chatId);
- if (chat) {
- this.addToMessageList(message, chat, true)
- }
- }
- if (message.chatId === this.openChatId && !message.mine) {
- const user = useUserStore().getUser();
- if (chat && user) {
- const receipt: Receipt = {
- chatId: chat.id,
- userId: user?.id,
- timestamp: new Date().getTime(),
- type: chat.type
- }
- useWsStore().sendRead(receipt)
- }
- }
- },
- /**
- * 收到后端返回的用户自己发送数据,删除本地临时数据
- * @param message 消息
- * @param chat 聊天室
- * @param addTips 仅仅添加,不做其他操作(true:提醒 false:不提醒)
- */
- delLocalMessageList(message: Message) {
- const chat = this.getChat(message.chatId)
- if (chat) {
- const messageList = this.getChatMessage(chat.id)
- //执行清除操作
- const len = messageList.findIndex((n:Message) => {
- // @ts-ignore
- return n.localtime > message.localtime
- })
- messageList.splice(len,1);
-
- this.chatMessage.set(chat.id, messageList)
- }
- },
- /**
- * 把数据插入到消息的列表,有序插入
- * @param list list
- * @param message 消息
- * @param chat 聊天室
- * @param addTips 仅仅添加,不做其他操作(true:提醒 false:不提醒)
- */
- insertMessage(list: Message[], message: Message, chat: Chat, addTips: boolean = true): void {
- //重复数据,不予处理
- const repeat = list.findIndex((item) => {
- return item.id === message.id
- })
- if (repeat > -1) {
- return
- }
- //console.log('insertMessage',message)
- var content=decryptLong2(message.content);
- if(content){
- message.content=content;
- }
- var extend=message.extend;
- if((typeof extend)=='string'){
- //console.log('typeof extend==string');
- try {
- message.extend=JSON.parse(extend);
- } catch (e) {
- message.extend=undefined; // 如果 jsonString 不是有效的 JSON,会进入这里
- }
- }
- else{
- //console.log('typeof extend!=string');
- }
- //console.log('insertMessage1',message)
- if (addTips && !message.mine && this.openChatId !== chat.id && ((message.fromId != useUserStore().getUser()?.id &&
- useImmunityStore().immunityList.indexOf(message.chatId) === -1) ||
- (message.type === ChatType.GROUP && this.isAtMine(message.extend)))) {
- // @ts-ignore
- this.chatLastMessage[chat.id] = message.content
- // @ts-ignore
- this.chatLastTime[chat.id] = message.timestamp
- if (!this.chatUnreadId[chat.id]) {
- this.chatUnreadId[chat.id] = []
- }
- if(!this.chatUnreadId[chat.id].includes(message.id)){
- this.chatUnreadId[chat.id].push(message.id)
- }
- chat.unreadCount = this.chatUnreadId[chat.id].length
- //console.log('chat.unreadCount',chat.unreadCount)
- this.messageTips(message)
- } else if (message.fromId == useUserStore().getUser()?.id) {
- // @ts-ignore
- this.chatLastMessage[chat.id] = message.content
- // @ts-ignore
- this.chatLastTime[chat.id] = message.timestamp
- }
- //如果新消息的时间比历史数据的时间小
- const len = list.findIndex((n) => {
- // @ts-ignore
- return n.timestamp > message.timestamp
- })
- //消息是在队列的中间,不在最后
- if (len > -1) {
- list.splice(len, 0, message)
- } else {
- list.push(message)
- }
- },
- /**
- * 当前用户是否被@
- * @param extend 扩展信息
- */
- isAtMine(extend: Extend | undefined): boolean {
- const user = useUserStore().getUser()
- //@所有人
- if (extend && extend.atAll && user) {
- return true
- }
- //@指定用户
- if (extend && extend.atUserIds && user) {
- return extend.atUserIds.indexOf(user.id) > -1
- }
- return false
- },
- /**
- * 创建一个新聊天室
- * @param message message
- * @private 私有方法
- */
- createChatRoom(message: Message) {
- //先占位,后加载
- const chat: Chat = {
- id: message.chatId,
- name: '加载中...',
- avatar: '',
- type: message.type,
- unreadCount: 0,
- isLoading: false,
- loaded: true
- }
- // @ts-ignore
- this.chatLastMessage[chat.id] = message.content
- // @ts-ignore
- this.chatLastTime[chat.id] = message.timestamp
- this.newChat(chat)
- if (message.type === ChatType.GROUP) {
- GroupApi.get(message.chatId).then((res) => {
- this.updateChat(chat.id, res.data.name, res.data.avatar, false)
- })
- } else {
- UserApi.getUser(message.mine ? message.chatId : message.fromId).then((res) => {
- this.updateChat(chat.id, res.data.name, res.data.avatar, false)
- })
- }
- },
- /**
- * 重置未读消息计数
- */
- reset() {
- this.chats.forEach((item: Chat) => {
- item.unreadCount = 0
- this.chatUnreadId[item.id] = []
- })
- },
- /**
- * 打开一个聊天对话框
- * @param chat chat
- */
- openChat(chat: Chat) {
- let hasChat = false
- this.chats.forEach((item: Chat) => {
- //聊天对话框已经存在
- if (item.id === chat.id) {
- item.unreadCount = 0
- this.chatUnreadId[item.id] = []
- hasChat = true
- }
- })
- //新增一个新聊天对话框
- if (!hasChat) {
- chat.unreadCount = 0
- this.chatUnreadId[chat.id] = []
- //添加到聊天列表第一个
- this.newChat(chat)
- }
- },
- /**
- * 根据聊天室的ID 获取他的index
- * @param id 聊天室的ID
- */
- getChatIndex(id: string) {
- let i = -1
- this.chats.forEach((item: Chat, index: number) => {
- if (item.id === id) {
- i = index
- }
- })
- return i
- },
- /**
- * 根据聊天室的ID 获取聊天室
- * @param id 聊天室的ID
- */
- getChat(id: string): null | Chat {
- let chat: null | Chat = null
- this.chats.forEach((item: Chat) => {
- if (item.id === id) {
- chat = item
- }
- })
- return chat
- },
- /**
- * 退出清除chatMessage
- */
- clearMessage(): void {
- this.chatMessage = new Map<string, Message[]>()
- },
- /**
- * 设置打开的chatId
- */
- setOpenChatId(id: string | null) {
- this.openChatId = id
- },
- /**
- * 限制聊天记录的数组的长度
- * @param message 新增的聊天消息
- * @param chat 聊天室
- * @param addTips 是否提醒
- */
- addToMessageList(message: Message, chat: Chat, addTips: boolean = true) {
- const messageList = this.getChatMessage(chat.id)
- this.insertMessage(messageList, message, chat, addTips)
- this.chatMessage.set(chat.id, messageList)
- },
- /**
- * 获取聊天消息
- */
- getChatMessage(chatId: string) {
- return this.chatMessage.get(chatId) ?? []
- },
- /**
- * 删除聊天
- * @param id 聊天室的ID
- */
- delChat(id: string) {
- this.chats.splice(this.getChatIndex(id), 1)
- ChatApi.delete(id)
- },
- /**
- * 更新聊天室信息
- * @param id 聊天室id
- * @param name 名称
- * @param avatar 头像
- * @param updateUnreadCount 是否更新未读消息数
- * @param updateServer 是否更新服务器
- */
- updateChat(id: string, name: string, avatar: string, updateUnreadCount: boolean = true, updateServer: boolean = true) {
-
- this.chats.forEach((item: Chat) => {
- if (item.id === id) {
- item.name = name
- item.avatar = avatar
- if (updateUnreadCount) {
- item.unreadCount = 0
- this.chatUnreadId[item.id] = []
- }
- if (updateServer) {
- ChatApi.update(item)
- }
- }
- })
- },
- /**
- * 新增聊天室
- * @param chat 聊天室
- */
- newChat(chat: Chat) {
- const items = this.chats
- const topList = items.filter((item) => item.top) // 查找已置顶元素的位置
- const topIndex = topList.length
- if (this.chats.findIndex((item) => item.id === chat.id) === -1) {
- items.splice(topIndex, 0, chat) // 将该元素插入已置顶元素的后面
- ChatApi.add(chat)
- }
- },
- /**
- * 撤回消息
- * @param message 消息
- */
- backMessage(message: Message) {
- this.chatMessage.get(message.chatId)?.forEach((item) => {
- if (item.id === message.id) {
- item.content = '该消息已被撤回'
- item.messageType = MessageType.event
- }
- })
- },
- /**
- * 撤回消息
- * @param message 消息
- */
- deMessage(message: Message) {
- let dechatId='';
- if(message.mine){
- dechatId = message.chatId
- }
- else{
- dechatId = message.fromId
- }
- const messages = this.chatMessage.get(dechatId)
- console.log('deMessage',message)
- messages?.forEach((item) => {
- //删除id 一样的消息
- if (item.id === message.id) {
- console.log(item)
- messages?.splice(messages?.indexOf(item), 1);
- dbApi.deleteLocalmsg(message);
- if(this.chatLastTime[message.chatId]==message.timestamp){
- this.chatLastMessage[message.chatId]='';
- }
- }
- })
- },
- /**
- * 置顶聊天室
- * @param id 聊天室的ID
- */
- topChat(id: string) {
- const items = this.chats
- const itemIndex = this.getChatIndex(id) // 查找对应元素的索引
- const chat = JSON.parse(JSON.stringify(this.chats[itemIndex]))
- if (itemIndex !== -1) {
- items.splice(itemIndex, 1) // 先从原数组中删除该元素
- const topIndex = items.findIndex((item) => !!item.top) // 查找已置顶元素的位置
- if (topIndex !== -1) {
- items.splice(topIndex, 0, chat) // 将该元素插入已置顶元素的前面
- } else {
- items.unshift(chat) // 如果不存在已置顶元素,则将该元素插入数组最前面
- }
- chat.top = true // 标记该元素已置顶
- }
- ChatApi.top(id)
- },
- /**
- * 实现取消置顶功能
- * @param id 聊天室的ID
- */
- cancelTop(id: string) {
- const items = this.chats
- const itemIndex = this.getChatIndex(id) // 查找对应元素的索引
- const chat = JSON.parse(JSON.stringify(this.chats[itemIndex]))
- if (itemIndex !== -1 && chat.top) {
- chat.top = false // 标记该元素已取消置顶
- const topList = items.filter((item) => !!item.top) // 查找已置顶元素的位置
- const topIndex = topList.length
- if (topIndex !== 0) {
- items.splice(topIndex, 0, chat) // 将该元素插入已置顶元素的后面
- } else {
- items.push(chat) // 如果不存在已置顶元素,则将该元素插入数组末尾
- }
- items.splice(itemIndex, 1) // 最后从原位置删除该元素
- }
- ChatApi.cancelTop(id)
- },
- /**
- * 消息提醒,限流2秒
- */
- messageTips: function (message: Message) {
- const now = Date.now()
- if (now - this.last >= 1000) {
- this.last = now
- if (useSettingStore().setting?.canSoundRemind === DictUtils.YES) {
- // 创建音频对象并播放
- // const innerAudioContext = uni.createInnerAudioContext();
- // innerAudioContext.src = `${FetchRequest.getHost()}${VimConfig.soundPath}`;
- // innerAudioContext.play()
- //#ifdef APP-PLUS
- //只提醒友聊,如果想提示群聊,去掉 && message.type === ChatType.FRIEND
- if (VimConfig.openUniPush && !useSysStore().show && message.type === ChatType.FRIEND) {
- let content = MessageType.text === message.messageType ? message.content : ''
- uni.createPushMessage({
- title: '您有一条新消息',
- content: content,
- sound: 'system',
- fail: fail => {
- console.log(fail);
- }
- })
- }
- // #endif
- }
- }
- },
- /**
- * 设置已读读消息时间
- */
- setLastReadTime(receipt: Receipt) {
- this.chats.forEach((item: Chat) => {
- if (receipt.userId === item.id) {
- item.lastReadTime = receipt.timestamp
- }
- })
- },
- /**
- * 设置当前聊天室的对方 已读时间
- */
- setCurrentChatLastReadTime(time: number) {
- if (this.openChatId && this.getChat(this.openChatId)) {
- const chat = this.getChat(this.openChatId);
- //console.log('setCurrentChatLastReadTime',chat);
- if (chat) {
- chat.lastReadTime = time
- }
- }
- },
- }
- })
|