/** * WanlShop状态管理器 - 即时通讯 * * @ author 深圳前海万联科技有限公司 * < 程序仅用作FastAdmin付费插件API测试使用,非FastAdmin购买授权,未经版权所有权人书面许可,不能用于商业用途!> * @ link http://www.wanlshop.com **/ import Vue from 'vue'; import fun from '../../common/wanlshop_function'; import config from '../../common/config/config'; export default { namespaced: true, state: { isOnline: false, socket: null, reconnectTime: 0, isOpenReconnect: true, ischat: { notice: true, number: 0 }, close: false, list: [], }, mutations: { setIschat(state, payload) { for (let i in payload) { for (let j in state.ischat) { if (i === j) { state.ischat[j] = payload[i]; } } } } }, actions: { // 连接socket connectSocket({ state, rootState, dispatch }) { config.debug ? console.log("连接 GatewayWorker"):''; state.socket = uni.connectSocket({ url: config.socketurl, complete: () => {} }); // 监听连接成功 state.socket.onOpen(() => dispatch('onOpen')); // 监听接收信息 state.socket.onMessage((res) => dispatch('onMessage', res)); // 监听断开 state.socket.onClose((e) => dispatch('onClose', e)); // 监听错误 state.socket.onError(() => dispatch('onError')); // 获取一次聊天列表 setTimeout(()=> { if (rootState.user.isLogin) { dispatch('get'); } },300); }, onOpen({ state, dispatch }) { // 用户上线 state.isOnline = true; config.debug ? console.log('GatewayWorker连接成功'):''; state.isOpenReconnect = true; }, // 监听关闭 onClose({ state, dispatch }, e) { // 用户下线 state.isOnline = false; state.socket = null; config.debug ? console.log('GatewayWorker连接已关闭'):''; if (state.isOpenReconnect) { config.debug ? console.log("3秒后重新链接"):''; setTimeout(()=> { dispatch('reconnect'); }, 3000); } }, // 监听连接错误 onError({ state, dispatch }) { // 用户下线 state.isOnline = false; state.socket = null; config.debug ? console.log('socket连接错误'):''; if (!state.socket) { setTimeout(()=> { dispatch('reconnect'); }, 3000); } }, // 监听接收消息 onMessage({ state, dispatch, rootDispatch }, data) { let message = JSON.parse(data.data) switch (message['type']) { case 'ping': state.socket.send({ data: '{"type":"pong"}', async success() { config.debug ? console.log("GatewayWorker心跳:" + new Date()):''; } }) break; case 'init': uni.request({ url: '/wanlshop/chat/shake', method: 'POST', data: {'client_id': message.client_id}, success: res => { uni.setStorageSync("wanlshop:chat_client_id", res.data); } }); break; case 'service': // 全局通知 uni.$emit('onService', message); // 消息提示 dispatch('notice', {type: message.type, data: null}); break; case 'chat': // 全局通知 uni.$emit('onMessage', fun.setChat(message)); // 更新数量 dispatch('update', {type: message.type, data:message, shop: {id: message.form.shop_id, user_id: message.form.id, name: message.form.name,avatar: message.form.avatar,}}); let tipsContent = ''; if (message.message.type == 'text') { tipsContent = message.message.content.text }else if(message.message.type == 'img') { tipsContent = '[图片消息]'; }else if(message.message.type == 'voice') { tipsContent = '[语音消息]'; } if (state.ischat.notice) { dispatch('notice', { type: message.type, data: { title: message.form.name, subtitle: '发来一条消息', content: tipsContent, jsondata: JSON.stringify({ id: 0 }) } }); }else{ state.ischat.number++; } break; case 'order': // 全局更新,分析订单类型: 待收货(已发货)交易物流+1 // 接受其他 签收,退款申请同意,拒绝 dispatch('storage', {type: message.type}); // 消息提示 dispatch('notice', { type: 'order', data: { title: message.title, subtitle: '', content: message.content, jsondata: JSON.stringify({ modules: message.modules, modules_id: message.modules_id }) } }); break; case 'notice': dispatch('storage', {type: message.type}); // 消息提示 dispatch('notice', { type: message.type, data: { title: '标题', subtitle: '副标题', content: '内容', jsondata: JSON.stringify({ id: 0 }) } }); break; case 'live': // 全局通知 uni.$emit('onLiveMessage', message); break; } }, // 处理消息 async handleOnMessage({ state, dispatch }, message) { if (message.type == "say") { uni.$emit('onMessage', message) } else if (message.type == "getLivingPool") { uni.$emit('onLibingPool', message) } else if (message.type == "SocketLivingInfo") { uni.$emit('SocketLivingInfo', message) } }, // 断线重连 reconnect({ state, dispatch }) { config.debug ? console.log("GatewayWorker准备重新连接"):''; if (state.isOnline) { return; } if (state.reconnectTime >= 3) { return dispatch('reconnectConfirm'); } state.reconnectTime += 1 console.log(`GatewayWorker正在${state.reconnectTime}次重新连接`); return dispatch('connectSocket'); }, // 断线重连提示 reconnectConfirm({ state, dispatch }) { dispatch('connectSocket'); state.reconnectTime = 0 }, // 验证是否上线 checkOnline({ state, dispatch }) { if (!state.isOnline) { // 断线重连提示 dispatch('reconnectConfirm'); return false } return true }, //踢下线 kickout({ state, rootState }, msg) { uni.showModal({ title: '提示', content: msg, success: (res) => { if (res.confirm) { console.log('用户点击确定'); } else if (res.cancel) { console.log('用户点击取消'); } // #ifdef APP if (uni.getSystemInfoSync().platform == 'ios'){ plus.ios.import("UIApplication").sharedApplication().performSelector("exit") } else if (uni.getSystemInfoSync().platform == 'android'){ plus.runtime.quit(); } // #endif // #ifdef MP-WEIXIN wx.exitMiniProgram({ success: (res) => {} }) // #endif dispatch('logout'); } }); }, // 退出登录 async logout({state, rootState}) { await uni.request({ url: '/wanlshop/user/logout', success: res => { for (let j in rootState.user) { rootState.user[j] = '' } rootState.user.isLogin = false; let statistics = rootState.statistics; for (let j in statistics) { for (let i in statistics[j]) { statistics[j][i] = 0 } } // 从本地缓存中异步移除指定key uni.removeStorageSync('wanlshop:user'); uni.removeStorageSync('wanlshop:statis'); // 关闭即时通讯 dispatch('close'); } }); }, // 关闭连接 close({ state, dispatch }) { if (state.socket) { state.socket.close() } dispatch('destoryChatObject'); state.isOpenReconnect = false }, // 创建聊天对象 createChatObject({ state, dispatch }, detail) { state.TO = detail }, // 销毁聊天对象 destoryChatObject({ state, dispatch }) { state.TO = false }, // 全局消息提示 async notice({state, dispatch, rootState}, {type, data}){ // 声音提示 if (rootState.user.voice) { let audio = uni.createInnerAudioContext(); let cdn = rootState.common.appUrl.oss; let src = { service: cdn + '/assets/addons/wanlshop/voice/service.mp3', order: cdn + '/assets/addons/wanlshop/voice/order.mp3', notice: cdn + '/assets/addons/wanlshop/voice/notice.mp3', chat: cdn + '/assets/addons/wanlshop/voice/chat.mp3' }; audio.autoplay = true; audio.src = src[type]; audio.onPlay(() => { config.debug ? console.log('开始播放') : ''; }); audio.onError((res) => { config.debug ? console.log(res) : ''; }); } // 震动 // #ifndef H5 if (rootState.user.shock) { uni.vibrateShort(); } // #endif //推送 // #ifdef APP-PLUS // if (rootState.user.pushs) { // if (data) { // plus.push.createMessage(data.content, data.jsondata, { // cover: false, // title: data.title, // subtitle: data.subtitle // }); // }else{ // config.debug ? console.log('推送数据不存在无法推送') : ''; // } // } // #endif }, // 读取消息列表 async get({state, dispatch, rootState}) { await uni.request({ url: '/wanlshop/chat/lists', success: res => { state.list = res.data; let count = 0; res.data.forEach(item => {count += item.count;}); dispatch('storage', {type: 'statis', number: count}); } }); }, // 删除指定消息 async del({state, dispatch, rootState}, index){ let list = state.list; // 修改消息总数量 dispatch('storage', {type: 'del', number: list[index].count}); // 清空本地储存 uni.removeStorage({ key: 'wanlchat:message_' + list[index].user_id, success: (res) => { config.debug ? console.log('删除消息成功'):''; } }); // 操作云 await uni.request({url: '/wanlshop/chat/del',method: 'POST',data: {id: list[index].user_id}}); // 删除状态管理器 Vue.delete(state.list, index); }, // 全部已读 async empty({state, dispatch, rootState}){ uni.showModal({ content: '是否将全部数据标记已读状态?', success: res=> { if (res.confirm) { // 已读状态管理器 state.list.forEach(item => {item.count = 0}); // 全局清零 dispatch('storage', {type: 'empty'}); // 操作云 uni.request({ url: '/wanlshop/chat/read', method: 'POST', success: res => { uni.showToast({title: '全部已读',icon: 'none'}); } }); } else if (res.cancel) { config.debug ? console.log('用户点击取消') : ''; } } }); }, // 通用更新,接受消息更新,发送消息更新,返回清空角标 async update({state, dispatch}, {type, data, id, shop}){ if (type == 'del') { let counts = 0; state.list.some(chat => {if (chat.user_id == id) { counts = chat.count; chat.count = 0; return true }}); // 操作统计 dispatch('storage', {type: 'del', number: counts}); // 操作云 await uni.request({url: '/wanlshop/chat/clear',method: 'POST',data: {id: id}}); }else if(type == 'chat' || type == 'send'){ let content = ''; let createtime = data.createtime; let chat_id = 0; let chat_name = null; let chat_avatar = null; if (data.message.type == 'text') { content = data.message.content.text; }else if(data.message.type == 'img') { content = '[图片消息]'; }else if(data.message.type == 'voice') { content = '[语音消息]'; }else if(data.message.type == 'goods') { content = '[商品消息]'; }else{ content = '[未知类型消息]'; } if(type == 'chat'){ chat_id = data.form.id; dispatch('storage', {type: 'chat'}); }else if (type == 'send') { chat_id = data.to_id; } let result = state.list.some(chat => { if (chat.user_id == chat_id) { if(type == 'chat'){ chat.count += 1; } chat.createtime = createtime; chat.content = content; return true } }); // 如果没有新增一个,chat 数量初始1 if (!result) { Vue.set(state.list, 0, { id: shop.id, user_id: shop.user_id, name: shop.name, avatar: shop.avatar, content: content, count: 1, createtime: createtime, }); } } }, // 操作储存 async storage({state, rootState}, {type, number}) { if(type == 'statis'){ rootState.statistics.notice.chat = number; }else if(type == 'order'){ rootState.statistics.notice.order += 1; }else if(type == 'notice'){ rootState.statistics.notice.notice += 1; }else if(type == 'chat'){ rootState.statistics.notice.chat += 1; }else if(type == 'del'){ rootState.statistics.notice.chat -= number; }else if(type == 'empty'){ rootState.statistics.notice.chat = 0; rootState.statistics.notice.order = 0; rootState.statistics.notice.notice = 0; } uni.setStorageSync("wanlshop:statis", rootState.statistics); } } };