forked from ccsens_fe/tall-mui-3
13 changed files with 398 additions and 1 deletions
@ -0,0 +1,3 @@ |
|||||
|
const getters = {}; |
||||
|
|
||||
|
export default getters; |
@ -0,0 +1,4 @@ |
|||||
|
import state from './state'; |
||||
|
import mutations from './mutations'; |
||||
|
|
||||
|
export default { namespaced: true, state, mutations }; |
@ -0,0 +1,84 @@ |
|||||
|
import { setStorageSync, getStorageSync, removeStorageSync } from '@/utils/storage'; |
||||
|
|
||||
|
const mutations = { |
||||
|
/** |
||||
|
* 初始化消息栈 |
||||
|
* @param {object} state |
||||
|
* @param {string} type |
||||
|
* type: |
||||
|
* syncMessages 同步消息栈 |
||||
|
* faultMessages 故障消息 未处理消息栈 |
||||
|
* faults 所有的故障消息栈 |
||||
|
*/ |
||||
|
messagesInit(state, type) { |
||||
|
const messages = getStorageSync(type) ? JSON.parse(getStorageSync(type)) : []; |
||||
|
state[type] = messages; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 将新 消息添加到 消息栈 最前边 |
||||
|
* @param { object } state |
||||
|
* @param { object } data |
||||
|
* data: message, type |
||||
|
* message 消息对象 |
||||
|
* type: |
||||
|
* syncMessages 同步消息栈 |
||||
|
* faultMessages 故障消息 未处理消息栈 |
||||
|
* faults 所有的故障消息栈 |
||||
|
* game 游戏的消息 |
||||
|
* |
||||
|
* cache: boolean true 本地存储 false 不存储 |
||||
|
*/ |
||||
|
messagesAdd(state, data) { |
||||
|
const messages = state[data.type]; |
||||
|
if (messages.length > 0) { |
||||
|
const result = messages.find(msg => msg.id === data.message.id); |
||||
|
if (result) return; |
||||
|
} |
||||
|
messages.unshift(data.message); |
||||
|
// eslint-disable-next-line no-param-reassign
|
||||
|
state[data.type] = messages; |
||||
|
if (data.cache) { |
||||
|
setStorageSync(data.type, JSON.stringify(messages)); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 通过消息id移除指定 同步 消息 |
||||
|
* @param { object } state |
||||
|
* @param { object } data |
||||
|
* data: messageId, type |
||||
|
* messageId: 要移除的消息的messageId |
||||
|
* type: |
||||
|
* syncMessages 同步消息栈 |
||||
|
* faultMessages 故障消息 未处理消息栈 |
||||
|
* faults 所有的故障消息栈 |
||||
|
* cache: boolean true 本地存储 false 不存储 |
||||
|
*/ |
||||
|
messagesRemoveById(state, data) { |
||||
|
const messages = state[data.type]; |
||||
|
const index = messages.findIndex(msg => msg.id === data.messageId); |
||||
|
if (index < 0) return; |
||||
|
messages.splice(index, 1); |
||||
|
// eslint-disable-next-line no-param-reassign
|
||||
|
state[data.type] = messages; |
||||
|
if (data.cache) { |
||||
|
setStorageSync(data.type, JSON.stringify(messages)); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 清除指定type的消息 |
||||
|
* @param {any} state |
||||
|
* @param {object} data |
||||
|
* data: type, cache |
||||
|
*/ |
||||
|
messagesClear(state, data) { |
||||
|
state[data.type] = []; |
||||
|
if (data.cache) { |
||||
|
removeStorageSync(data.type); |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default mutations; |
@ -0,0 +1,8 @@ |
|||||
|
const state = { |
||||
|
syncMessages: [], // 同步消息
|
||||
|
faultMessages: [], // 新收到的未处理的 故障消息
|
||||
|
faults: [], // 所有的故障消息
|
||||
|
game: [], // 游戏的消息
|
||||
|
}; |
||||
|
|
||||
|
export default state; |
@ -0,0 +1,147 @@ |
|||||
|
const WS_BASE_URL = process.env.VUE_APP_MSG_URL; |
||||
|
|
||||
|
let prevTime = 0; |
||||
|
let socketMsgQueue = []; // socket消息队列
|
||||
|
let sendHeartTimer = null; |
||||
|
|
||||
|
const actions = { |
||||
|
// 初始化socket
|
||||
|
initSocket({ commit, dispatch, state, rootState }) { |
||||
|
if (state.lockSocket) return; |
||||
|
const { token } = rootState.user; |
||||
|
if (!token) return; |
||||
|
commit('setLockSocket', true); |
||||
|
commit('setSocket', uni.connectSocket({ url: WS_BASE_URL, complete: () => {} })); |
||||
|
dispatch('onSocketOpen'); |
||||
|
dispatch('onSocketMessage'); |
||||
|
dispatch('onSocketClose'); |
||||
|
state.socket.onError(errMsg => console.error(errMsg)); |
||||
|
commit('setLockSocket', false); |
||||
|
}, |
||||
|
|
||||
|
// 监听ws打开
|
||||
|
onSocketOpen({ dispatch, commit, state }) { |
||||
|
state.socket.onOpen(res => { |
||||
|
console.log('ws open: ', res); |
||||
|
commit('setConnected', true); |
||||
|
prevTime = Date.now(); |
||||
|
// this.auth();
|
||||
|
dispatch('auth'); |
||||
|
for (let i = 0; i < socketMsgQueue.length; i++) { |
||||
|
dispatch('sendSocketMessage', socketMsgQueue[i]); |
||||
|
} |
||||
|
socketMsgQueue = []; |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 监听收到的ws消息
|
||||
|
onSocketMessage({ dispatch, state }) { |
||||
|
state.socket.onMessage(res => { |
||||
|
// console.log('收到消息:', res);
|
||||
|
prevTime = Date.now(); |
||||
|
if (!res || !res.data || !JSON.parse(res.data)) return; |
||||
|
const resData = JSON.parse(res.data); |
||||
|
const { messageSet, ackId } = resData; |
||||
|
// 处理消息体对象
|
||||
|
messageSet.forEach(item => dispatch('handleMessagesData', item)); |
||||
|
ackId && dispatch('sendSocketMessage', { type: 'Ack', data: { ackId } }); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 处理收到的消息内容 |
||||
|
* @param {object} item 单个消息体对象 |
||||
|
*/ |
||||
|
handleMessagesData({ dispatch, commit }, item) { |
||||
|
const data = JSON.parse(item.data); |
||||
|
switch (data.type) { |
||||
|
case 'Sync': // 开始某个节点
|
||||
|
commit('messages/messagesAdd', { message: data, type: 'syncMessages' }, { root: true }); |
||||
|
break; |
||||
|
// case 'Chrome': // !收到开始游戏的消息
|
||||
|
// console.log('handleMessagesData', data);
|
||||
|
// // @ts-ignore
|
||||
|
// util.openGameApp({
|
||||
|
// type: data.data.type,
|
||||
|
// projectId: data.data.projectId,
|
||||
|
// id: data.data.recordId,
|
||||
|
// token: rootState.user.token,
|
||||
|
// });
|
||||
|
// break;
|
||||
|
// case 'Deliver': // 交付物相关消息
|
||||
|
// commit('messages/messagesAdd', { type: 'checkMessages', message: data }, { root: true });
|
||||
|
// break;
|
||||
|
case 'ChannelStatus': |
||||
|
dispatch('handleAuthMessage', data); |
||||
|
break; |
||||
|
// case 'switchoverProject': // 康复相关消息
|
||||
|
// dispatch('home/getProjectById', data.data.projectId, { root: true });
|
||||
|
// break;
|
||||
|
// case 'startDrill': // 康复开始训练相关消息
|
||||
|
// console.log('setStartDrillInfo', data.data);
|
||||
|
// commit('home/setStartDrillMessages', data.data, { root: true });
|
||||
|
// break;
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 发送消息
|
||||
|
sendSocketMessage({ state }, data) { |
||||
|
if (state.connected) { |
||||
|
const msg = JSON.stringify({ toDomain: 'Server', data: JSON.stringify(data) }); |
||||
|
state.socket.send({ data: msg }); |
||||
|
} else { |
||||
|
socketMsgQueue.push(data); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 监听关闭事件
|
||||
|
onSocketClose({ dispatch, commit, state }) { |
||||
|
console.log('onSocketClose'); |
||||
|
state.socket.onClose(() => { |
||||
|
commit('setConnected', false); |
||||
|
if (sendHeartTimer) clearInterval(sendHeartTimer); |
||||
|
setTimeout(() => { |
||||
|
dispatch('initSocket'); |
||||
|
}, 300); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// websocket发送channelId进行认证
|
||||
|
auth({ dispatch, rootState }) { |
||||
|
const { token } = rootState.user; |
||||
|
if (!token) return; |
||||
|
const data = { type: 'Auth', data: { token } }; |
||||
|
dispatch('sendSocketMessage', data); |
||||
|
}, |
||||
|
|
||||
|
// 心跳检测
|
||||
|
sendHeart({ dispatch, state }) { |
||||
|
if (sendHeartTimer) clearInterval(sendHeartTimer); |
||||
|
sendHeartTimer = setInterval(() => { |
||||
|
if (Date.now() - prevTime >= 15000) { |
||||
|
dispatch('sendSocketMessage', { type: 'Ping' }); |
||||
|
if (Date.now() - prevTime >= 20000) { |
||||
|
state.socket.close(); |
||||
|
} |
||||
|
} |
||||
|
}, 5000); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 处理auth认证返回的ChannelStatus消息 |
||||
|
* @param {object} data 消息内容对象 |
||||
|
*/ |
||||
|
handleAuthMessage({ commit, dispatch }, data) { |
||||
|
if (data.data.authed) { |
||||
|
dispatch('sendHeart'); |
||||
|
} else { |
||||
|
uni.$u.toast('消息系统认证失败, 请退出重新登录'); |
||||
|
uni.$t.removeStorageSync('anyringToken'); |
||||
|
commit('setSocket', null); |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default actions; |
@ -0,0 +1,5 @@ |
|||||
|
import state from './state'; |
||||
|
import mutations from './mutations'; |
||||
|
import actions from './actions'; |
||||
|
|
||||
|
export default { namespaced: true, state, mutations, actions }; |
@ -0,0 +1,26 @@ |
|||||
|
const mutations = { |
||||
|
// 设置socket实例
|
||||
|
setSocket(state, socket) { |
||||
|
state.socket = socket; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置socket连接状态 |
||||
|
* @param {Object} state |
||||
|
* @param {boolean} connected 是否连接 true -> 连接 |
||||
|
*/ |
||||
|
setConnected(state, connected) { |
||||
|
state.connected = connected; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置连接锁 正在连接中 锁上 避免多个连接同时发出 |
||||
|
* @param {Object} state |
||||
|
* @param {boolean} lockSocket 是否正在连接的过程中 |
||||
|
*/ |
||||
|
setLockSocket(state, lockSocket) { |
||||
|
state.lockSocket = lockSocket; |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default mutations; |
@ -0,0 +1,7 @@ |
|||||
|
const state = { |
||||
|
socket: null, // websocket实例
|
||||
|
connected: false, // 是否处于连接状态
|
||||
|
lockSocket: false, // 是否正在连接状态
|
||||
|
}; |
||||
|
|
||||
|
export default state; |
@ -0,0 +1,100 @@ |
|||||
|
export default { |
||||
|
/** |
||||
|
* 设置本地存储 同步 |
||||
|
* @param {string} key |
||||
|
* @param {*} data |
||||
|
*/ |
||||
|
setStorageSync(key, data) { |
||||
|
const value = typeof data === 'string' ? data : JSON.stringify(data); |
||||
|
uni.setStorageSync(key, value); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 获取本地存储的信息 根据key |
||||
|
* @param {string} key |
||||
|
* @return {string} |
||||
|
*/ |
||||
|
getStorageSync(key) { |
||||
|
return uni.getStorageSync(key); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 根据key移除某条数据 同步 |
||||
|
* @param {string} key |
||||
|
*/ |
||||
|
removeStorageSync(key) { |
||||
|
uni.removeStorageSync(key); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 清楚全部数据 同步 |
||||
|
*/ |
||||
|
clearStorageSync() { |
||||
|
uni.clearStorageSync(); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置本地存储 异步 |
||||
|
* @param {string} key |
||||
|
* @param {*} data |
||||
|
*/ |
||||
|
setStorage(key, data) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const value = typeof data === 'string' ? data : JSON.stringify(data); |
||||
|
uni.setStorage({ |
||||
|
key, |
||||
|
data: value, |
||||
|
success() { |
||||
|
resolve(`数据${key}存储成功`); |
||||
|
}, |
||||
|
fail() { |
||||
|
reject(`数据${key}存储失败`); |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 获取本地存储的信息 根据key 异步 |
||||
|
* @param {string} key |
||||
|
* @return {string} |
||||
|
*/ |
||||
|
getStorage(key) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
uni.getStorage({ |
||||
|
key, |
||||
|
success(res) { |
||||
|
resolve(res.data); |
||||
|
}, |
||||
|
fail(error) { |
||||
|
reject(`数据${key}获取失败, error: ${error}`); |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 根据key移除某条数据 异步 |
||||
|
* @param {string} key |
||||
|
*/ |
||||
|
removeStorage(key) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
uni.removeStorage({ |
||||
|
key, |
||||
|
success(res) { |
||||
|
resolve(res); |
||||
|
}, |
||||
|
fail(error) { |
||||
|
reject(`数据${key}删除失败, error: ${error}`); |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* 清楚全部数据 异步 |
||||
|
*/ |
||||
|
clearStorage() { |
||||
|
uni.clearStorage(); |
||||
|
}, |
||||
|
}; |
Loading…
Reference in new issue