You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

468 lines
13 KiB

/**
* WanlShop状态管理器 - 即时通讯
*
* @ author 深圳前海万联科技有限公司 <wanlshop@i36k.com>
* < 程序仅用作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);
}
}
};