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.

356 lines
10 KiB

1 year ago
/**
* WanlShop状态管理器 - 即时通讯
*
* @ author 深圳前海万联科技有限公司 <wanlshop@i36k.com>
* < 程序仅用作FastAdmin付费插件API测试使用未经版权所有权人书面许可不能用于商业用途>
* @ link http://www.wanlshop.com
* @ 2020年9月29日19:00:46
* @ version 1.0.0
**/
import Vue from 'vue';
import api from '../../common/request/request';
import fun from '../../common/wanlshop_function';
import config from '../../common/config/config';
export default {
namespaced: true,
state: {
ischat: {
notice: true,
number: 0
},
close: false,
list: [],
reconnections: 0
},
mutations: {
setIschat(state, payload) {
for (let i in payload) {
for (let j in state.ischat) {
if (i === j) {
state.ischat[j] = payload[i];
}
}
}
}
},
actions: {
// 开始或重启即时通讯,全局监听,主要用于系统消息提示
async start({state, dispatch, rootState}){
// 如果已连接,关闭重新连接
uni.onSocketOpen(()=> {
state.isclose = true;
});
if (state.isclose) {
uni.closeSocket();
uni.onSocketClose((res)=> {
config.debug ? console.log('WanlChat 已关闭!') : '';
});
}
// 创建一个 WebSocket 连接
uni.connectSocket({url: config.socketurl});
// 监听 WebSocket 连接打开事件
uni.onSocketOpen((res)=> {
config.debug ? console.log('WanlChat 连接已打开!') : '';
});
// 监听WebSocket错误。
uni.onSocketError((res)=> {
api.get({
url: '/wanlshop/chat/state',
success: res => {
state.reconnections += 1;
if (state.reconnections <= 3) {
// uni.showToast({
// title: `IM 连接失败,正尝试第${state.reconnections}次连接`,
// icon: 'loading'
// });
dispatch('start');
}else{
console.error('IM服务器启动正常,客户端已尝试3次重连接,请检查ws和wss是否可以正常访问');
}
}
});
});
uni.onSocketMessage((res)=> {
let data = JSON.parse(res.data);
// 初始化
if (data.type == 'init') {
// 绑定 client_id 到 uid
api.post({
url: '/wanlshop/chat/shake',
data: {'client_id': data.client_id},
success: res => {
uni.setStorageSync("wanlshop:chat_client_id", res);
}
});
// 心跳回执
}else if(data.type == 'ping'){
// 通过 WebSocket 连接发送数据
uni.sendSocketMessage({data: '{"type":"pong"}'});
// 客服消息
}else if(data.type == 'service') {
// 全局通知
uni.$emit('onService', data);
// 消息提示
dispatch('notice', {type: data.type, data: null});
// 即时通讯消息
}else if(data.type == 'chat'){
// 全局通知
uni.$emit('onChat', fun.setChat(data));
// 更新数量
dispatch('update', {type: data.type, data:data, shop: {id: data.form.shop_id, user_id: data.form.id, name: data.form.name,avatar: data.form.avatar,}});
let tipsContent = '';
if (data.message.type == 'text') {
tipsContent = data.message.content.text
}else if(data.message.type == 'img') {
tipsContent = '[图片消息]';
}else if(data.message.type == 'voice') {
tipsContent = '[语音消息]';
}
if (state.ischat.notice) {
dispatch('notice', {
type: data.type,
data: {
title: data.form.name,
subtitle: '发来一条消息',
content: tipsContent,
jsondata: JSON.stringify({
id: 0
})
}
});
}else{
state.ischat.number++;
}
// 订单消息
}else if(data.type == 'order'){
// 全局更新,分析订单类型: 待收货(已发货)交易物流+1
// 接受其他 签收,退款申请同意,拒绝
dispatch('storage', {type: data.type});
// 消息提示
dispatch('notice', {
type: 'order',
data: {
title: data.title,
subtitle: '',
content: data.content,
jsondata: JSON.stringify({
modules: data.modules,
modules_id: data.modules_id
})
}
});
// 通知消息
}else if(data.type == 'notice'){
dispatch('storage', {type: data.type});
// 消息提示
dispatch('notice', {
type: data.type,
data: {
title: '标题',
subtitle: '副标题',
content: '内容',
jsondata: JSON.stringify({
id: 0
})
}
});
}else if(data.type == 'live'){
// 全局通知
uni.$emit('onLive', data);
}else{
config.debug ? console.log("未知消息: " + JSON.stringify(data)) : '';
}
});
// 获取一次聊天列表
setTimeout(()=> {
if (rootState.user.isLogin) {
dispatch('get');
}
},300);
},
// 全局消息提示
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}) {
api.get({
url: '/wanlshop/chat/lists',
success: res => {
state.list = res;
let count = 0;
res.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('删除消息成功'):'';
}
});
// 操作云
api.post({url: '/wanlshop/chat/del',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'});
// 操作云
api.post({
url: '/wanlshop/chat/read',
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});
// 操作云
api.post({url: '/wanlshop/chat/clear',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);
},
// 关闭即时通讯
async close(){
uni.onSocketOpen(()=> {
uni.closeSocket();
});
uni.onSocketClose((res)=> {
console.log('WanlChat 已关闭!');
});
}
}
};