chat.js
import $U from "./util.js"; import $H from './request.js'; class chat { constructor(arg) { this.url = arg.url this.isOnline = false this.socket = null // 获取当前用户相关信息 let user = $U.getStorage('user'); this.user = user ? JSON.parse(user) : {}, // 初始化聊天对象 this.TO = false; // 连接和监听 if (this.user.token) { this.connectSocket() } } // 连接socket connectSocket() { console.log(this.user); this.socket = uni.connectSocket({ url: this.url + '?token=' + this.user.token, complete: () => {} }) // 监听连接成功 this.socket.onOpen(() => this.onOpen()) // 监听接收信息 this.socket.onMessage((res) => this.onMessage(res)) // 监听断开 this.socket.onClose(() => this.onClose()) // 监听错误 this.socket.onError(() => this.onError()) } // 监听打开 onOpen() { // 用户状态上线 this.isOnline = true; console.log('socket连接成功'); // 获取用户离线消息 } // 监听关闭 onClose() { // 用户下线 this.isOnline = false; this.socket = null; console.log('socket连接关闭'); } // 监听消息 onMessage(data) { console.log('监听消息', data); } // 监听连接错误 onError() { // 用户下线 this.isOnline = false; this.socket = null; console.log('socket连接错误'); } // 关闭连接 close() { this.socket.close() } // 创建聊天对象 createChatObject(detail) { this.TO = detail; console.log('创建聊天对象', this.TO) } // 销毁聊天对象 destoryChatObject() { this.TO = false } // 组织发送信息格式 formatSendData(params) { return { id: 0, // 唯一id,后端生成,用于撤回指定消息 from_avatar: this.user.avatar, // 发送者头像 from_name: this.user.nickname || this.user.username, // 发送者昵称 from_id: this.user.id, // 发送者id to_id: params.to_id || this.TO.id, // 接收人/群 id to_name: params.to_name || this.TO.name, // 接收人/群 名称 to_avatar: params.to_avatar || this.TO.avatar, // 接收人/群 头像 chat_type: params.chat_type || this.TO.chat_type, // 接收类型 type: params.type, // 消息类型 data: params.data, // 消息内容 options: params.options ? params.options : {}, // 其他参数 create_time: (new Date()).getTime(), // 创建时间 isremove: 0, // 是否撤回 sendStatus: params.sendStatus ? params.sendStatus : "pending" // 发送状态,success发送成功,fail发送失败,pending发送中 } } // 发送信息 send(message) { return new Promise((result, reject) => { // 添加消息历史记录 this.addChatDetail(); let { data,k } = this.addChatDetail(message, true); // 置顶消息记录 // 验证是否上线 $H.post('/chat/send', { to_id: this.TO.id, type: message.type, chat_type: this.TO.chat_type, data: message.data, }).then(res => { // 发送成功 message.id = res.id message.sendStatus = 'success' // 更新指定历史记录 this.updateChatDetail(message,k); result(res); }).catch(err => { // 发送失败 message.sendStatus = 'fail' // 更新指定历史记录 this.updateChatDetail(message,k); // 断线重连提示 result(err); }); }) } // 添加聊天记录 addChatDetail(message,isSend=true){ console.log('添加到聊天记录'); if(!id){ return { data:{}, k:0 } } // 获取对方id let id = isSend ? message.to_id : message.from_id; // key值:chetDetail_当前用户id_会话类型_接收人/群id let key = `chetDetail_${this.user.id}_${message.chat_type}_${id}`; // 获取原来的聊天记录 let list = this.getChatdetail(key) console.log('获取原来的聊天记录',list); // 标识 message.key = 'k'+list.length; list.push(message); // 加入存储 console.log('加入存储',k); this.setStorage(key,list); // 返回 return { data:message, k:message.k } } // 更新指定历史记录 async updateChatDetail(message,k,isSend=true){ // 获取对方id let id = isSend ? message.to_id : message.from_id // key值:chetDetail_当前用户id_会话类型_接收人/群id let key = `chetDetail_${this.user.id}_${message.chat_type}_${id}`; // 获取原来的聊天记录 let list = this.getChatdetail(key); // 根据k查找对应聊天记录 let index = list.findIndex(item=>item.k === k); if(index === -1) return; list[index] = message; // 存储 this.setStorage(key,list); } // 获取聊天记录 getChatdetail(key=false){ key = key ? key : `chatDetail_${this.user.id}_${this.TO.chat_type}_${this.TO.id}`; return this.getStorage(key); } // 获取聊天记录 getChatList(message,isSend=true){ // 获取本地存储会话列表 let list = this.getChatList(); // 是否处在当前聊天中 let isCurrentChat = false // 接收人/群 id/头像/昵称 let id = 0; let avatar = ''; let name = ''; // 判断私聊还是群聊 if(message.chat_type === 'user'){ // 私聊 isCurrentChat = this.TO ? (isSend ? this.TO.id === message.to_id : message.from_id) : false; id = isSend ? message.to_id : message.from_id; avatar = isSend ? message.to_avatar : message.from_avatar name = isSend ? message.to_name : message.from_name }else{ // 群聊 } // 会话是否存在 let index = list.findIndex(item=>{ return item.chat_type === message.chat_type && item.id === id;}) // 最后一条消息展现形式 let data = isSend ? message.data : `${message.from_name}:${message.data}`; // 未读数是否 +1 let noreadnum = (isSend || isCurrentChat) ? 0 : 1; // 会话不存在 创建会话 if(index === -1){ let chatItem = { id, // 接收人/群 id chat_type:message.chat_type, // 接收类型 user 单聊 group群聊 name, // 接收人/群 昵称 avatar, // 接收人/群 头像 update_time:(new Date()).getTime(), // 最后发送的时间 data, // 最后一条消息的内容 type:message.type, noreadnum:1, // 未读数 istop:false, // 是否置顶 shownickname:0, // 是否显示昵称 nowarn:0, // 是否免打扰 strongwarn:0, // 是否强提醒 } if(message.chat_type === 'group'){ chatItem = { ...chatItem, user_id:0, // 管理员id remark:'', // 群公告 invite_confirm:0 // 邀请确认 } } }else{ // 存在,更新会话 // 拿到当前会话 let item = list[index] // 更新改会话最后一条消息时间,内容,类型 item.update_time = (new Date()).getTime(); item.data = data; item.type = message.type; // 未读数更新 item.noreadnum += noreadnum // 置顶会话 list = this.listToFirst(list,index); } // 存储 let key = `chatlist_${this.user.id}`; this.setStorage(key,list); // 更新未读数 // 更新vuex中的聊天会话列表 uni.$emit('onUpdateChatList',list); return list; /** * { id:1, // 接收人/群 id chat_type:'user', // 接收类型 user 单聊 group群聊 name:'昵称', // 接收人/群 昵称 avatar:"/static/images/demo/demo6.jpg", // 接收人/群 头像 type:'',// 最后一条消息类型 update_time:1628069958, // 最后发送的时间 data:"你好啊,哈哈哈", // 最后一条消息的内容 noreadnum:1, // 未读数 istop:false, // 是否置顶 shownickname:0, // 是否显示昵称 nowarn:0, // 是否免打扰 strongwarn:0, // 是否强提醒 user_id://管理员id, remark:'公告', // 群公告 invite_confirm:0, // 邀请确认 }, **/ } // 获取本地存储会话列表 getChatList(){ let key = `chatlist_${this.user.id}`; return this.getStorage(key); } // 获取存储 getStorage(key){ let list = $U.getStorage(key); return list ? JSON.parse(list) : []; } // 设置存储 setStorage(key,value){ return $U.setStorage(key,JSON.stringify(value)); } // 数组置顶 listToFirst(arr,index){ if(index != 0){ arr.unshift(arr.splice(index,1)[0]); } return arr; } } export default chat