21 changed files with 546 additions and 229 deletions
@ -1,10 +1,10 @@ |
|||
VUE_APP_MODE=development |
|||
VUE_APP_NODE_ENV=development |
|||
VUE_APP_SCENE=greenvalley |
|||
VUE_APP_SCENE=wisdomcar |
|||
VUE_APP_BASE_URL=http://test.tall.wiki/ |
|||
VUE_APP_API_URL=http://test.tall.wiki/gateway |
|||
VUE_APP_PROXY_URL=/gateway |
|||
VUE_APP_PUBLIC_PATH=/greenvalley |
|||
VUE_APP_PUBLIC_PATH=/wisdomcar |
|||
VUE_APP_MSG_URL=wss://test.tall.wiki/websocket/message/v4.0/ws |
|||
VUE_APP_TITLE=盐湖区人民医院数字看板 |
|||
VUE_APP_DESCRIPTION=盐湖区人民医院数字看板 |
|||
|
@ -1,10 +1,10 @@ |
|||
VUE_APP_MODE=production |
|||
VUE_APP_NODE_ENV=production |
|||
VUE_APP_SCENE=greenvalley |
|||
VUE_APP_SCENE=wisdomcar |
|||
VUE_APP_BASE_URL=http://www.sxwikionline.com/ |
|||
VUE_APP_API_URL=http://www.sxwikionline.com/gateway |
|||
VUE_APP_PROXY_URL=/gateway |
|||
VUE_APP_PUBLIC_PATH=/greenvalley |
|||
VUE_APP_PUBLIC_PATH=/wisdomcar |
|||
VUE_APP_MSG_URL=wss://www.tall.wiki/websocket/message/v4.0/ws |
|||
VUE_APP_TITLE=盐湖区人民医院数字看板 |
|||
VUE_APP_DESCRIPTION=盐湖区人民医院数字看板 |
|||
|
@ -0,0 +1,51 @@ |
|||
.box { |
|||
width: 88%; |
|||
left: 6%; |
|||
position: relative; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 17px; |
|||
color: #C8CED5; |
|||
letter-spacing: 2px; |
|||
} |
|||
|
|||
.number { |
|||
height: 80%; |
|||
position: absolute; |
|||
right: 0; |
|||
bottom: 0; |
|||
} |
|||
|
|||
.number .num_item { |
|||
background: url('~assets/cz-bg.png') no-repeat bottom left; |
|||
background-size: auto 90%; |
|||
position: relative; |
|||
top: -6px; |
|||
left: 2px; |
|||
} |
|||
|
|||
.number span { |
|||
display: inline-block; |
|||
position: relative; |
|||
top: -8px; |
|||
left: 2px; |
|||
font-size: 38px; |
|||
font-style: oblique; |
|||
font-weight: 400; |
|||
letter-spacing: 18px; |
|||
height: 100%; |
|||
} |
|||
|
|||
@media (max-width: 1500px) { |
|||
.title { |
|||
font-size: 12px; |
|||
letter-spacing: 0; |
|||
} |
|||
|
|||
.number span { |
|||
top: -8px; |
|||
font-size: 23px; |
|||
letter-spacing: 16px; |
|||
} |
|||
} |
@ -0,0 +1,213 @@ |
|||
import { WS_BASE_URL } from 'config/api'; |
|||
import { mapGetters, mapMutations } from 'vuex'; |
|||
|
|||
let connected = false; // socket 是否连接
|
|||
let socket = null; // websocket 实例
|
|||
let lockSocket = false; |
|||
let socketMsgQueue = []; // socket消息队列
|
|||
let prevTimestamp = 0; // 上次收到消息的时间戳
|
|||
let sendHeartTimer = null; // 💓的timer计时器
|
|||
|
|||
const mixin = { |
|||
// computed: mapGetters('home', ['projectId']),
|
|||
|
|||
mounted() { |
|||
socket ? socket.close() : this.initSocket(); |
|||
}, |
|||
|
|||
methods: { |
|||
...mapMutations('messages', [ |
|||
'messagesAdd', |
|||
'messagesAddWeight', |
|||
'messagesAddRfid', |
|||
'messagesAddWeighSensor1', |
|||
'messagesAddWeighSensor2', |
|||
'messagesAddWeighSensor3', |
|||
'messagesAddWeighSensor4', |
|||
'messagesAddVibrationSensor', |
|||
'messagesAddThrombolyticDose', |
|||
'messagesAddBolusDose', |
|||
'messagesAddMaintenanceDose', |
|||
]), |
|||
// ...mapMutations('home', ['increaseProjectsRingNum']),
|
|||
|
|||
// 初始化websocket
|
|||
initSocket() { |
|||
if (lockSocket) return; |
|||
lockSocket = true; |
|||
// const token = sessionStorage.getItem('anyringToken');
|
|||
// if (!token) return;
|
|||
if ('WebSocket' in window) { |
|||
socket = new WebSocket(WS_BASE_URL); |
|||
socket.onopen = this.websocketOpen; |
|||
socket.onmessage = this.websocketOnMessage; |
|||
socket.onclose = this.websocketClose; |
|||
socket.onerror = this.websocketError; |
|||
} else { |
|||
this.$message.error('当前浏览器不支持 websocket'); |
|||
} |
|||
lockSocket = false; |
|||
}, |
|||
|
|||
/** |
|||
* 处理收到的消息内容 |
|||
* @param {object} item 单个消息体对象 |
|||
*/ |
|||
handleMessagesData(item) { |
|||
const data = JSON.parse(item.data); |
|||
console.log('data: ', data); |
|||
switch (data.type) { |
|||
case 'ChannelStatus': // 认证消息
|
|||
this.handleAuthMessage(data); |
|||
break; |
|||
case 1: // 体重
|
|||
// 收到同步消息
|
|||
// 把消息添加到store 的消息栈中
|
|||
this.messagesAddWeight(data); |
|||
break; |
|||
case 2: // RFID
|
|||
this.messagesAddRfid(data); |
|||
break; |
|||
case 3: // 称重传感器一
|
|||
this.messagesAddWeighSensor1(data); |
|||
break; |
|||
case 4: // 称重传感器二
|
|||
this.messagesAddWeighSensor2(data); |
|||
break; |
|||
case 5: // 称重传感器三
|
|||
this.messagesAddWeighSensor3(data); |
|||
break; |
|||
case 6: // 称重传感器四
|
|||
this.messagesAddWeighSensor4(data); |
|||
break; |
|||
case 7: // 震动传感器
|
|||
this.messagesAddVibrationSensor(data); |
|||
break; |
|||
case 8: // 溶栓剂量(总量)
|
|||
this.messagesAddThrombolyticDose(data); |
|||
break; |
|||
case 9: // 团注剂量
|
|||
this.messagesAddBolusDose(data); |
|||
break; |
|||
case 10: // 维持剂量
|
|||
this.messagesAddMaintenanceDose(data); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 收到ws 消息 |
|||
* @param {object} res 收到的消息数据 |
|||
*/ |
|||
async websocketOnMessage(res) { |
|||
try { |
|||
prevTimestamp = Date.now(); |
|||
// console.warn('message: ', res, new Date().toLocaleString());
|
|||
if (res && res.data && JSON.parse(res.data)) { |
|||
const resData = JSON.parse(res.data); |
|||
const { messageSet, ackId } = resData; |
|||
// 处理消息体对象
|
|||
messageSet.forEach(item => this.handleMessagesData(item)); |
|||
// console.log('ackId', ackId);
|
|||
// 有ackId 发送ack
|
|||
ackId && this.sendSocketMessage({ type: 'Ack', data: { ackId } }); |
|||
} |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
}, |
|||
|
|||
// 打开socket
|
|||
websocketOpen() { |
|||
// console.warn('socket 打开成功', new Date().toLocaleString());
|
|||
connected = true; |
|||
prevTimestamp = Date.now(); |
|||
this.auth(); |
|||
for (let i = 0; i < socketMsgQueue.length; i += 1) { |
|||
this.sendSocketMessage(socketMsgQueue[i]); |
|||
} |
|||
socketMsgQueue = []; |
|||
}, |
|||
|
|||
// 发送消息
|
|||
sendSocketMessage(data) { |
|||
// console.warn('send:', data, new Date().toLocaleString());
|
|||
if (connected) { |
|||
if (socket.readyState === 1) { |
|||
socket.send(JSON.stringify({ toDomain: 'Server', data: JSON.stringify(data) })); |
|||
} |
|||
} else { |
|||
socketMsgQueue.push(data); |
|||
} |
|||
}, |
|||
|
|||
// 关闭socket
|
|||
websocketClose(e) { |
|||
// console.warn(e);
|
|||
connected = false; |
|||
if (sendHeartTimer) clearInterval(sendHeartTimer); |
|||
// console.warn('close:', connected, new Date().toLocaleString());
|
|||
if (!e || e.code !== 1005) { |
|||
socket.close(); |
|||
} |
|||
|
|||
setTimeout(() => { |
|||
// connected 在这里的作用是:
|
|||
// 在发生重连 但是还没连上之前 不要再次重连
|
|||
this.initSocket(); |
|||
}, 300); |
|||
}, |
|||
|
|||
// 连接失败
|
|||
websocketError() { |
|||
console.warn('error = ', connected); |
|||
}, |
|||
|
|||
// websocket发送token进行认证
|
|||
auth() { |
|||
// const token = sessionStorage.getItem('anyringToken');
|
|||
// if (!token) return;
|
|||
const userId = '1338747522436435968'; |
|||
const data = { type: 'Auth', data: { userId }, major: 1, minor: 1 }; |
|||
this.sendSocketMessage(data); |
|||
}, |
|||
|
|||
// 心跳检测
|
|||
sendHeart() { |
|||
if (sendHeartTimer) clearInterval(sendHeartTimer); |
|||
sendHeartTimer = setInterval(() => { |
|||
if (Date.now() - prevTimestamp >= 15000) { |
|||
this.sendSocketMessage({ type: 'Ping' }); |
|||
|
|||
if (Date.now() - prevTimestamp > 20000) { |
|||
// console.warn('手动断开');
|
|||
socket.close(); |
|||
} |
|||
} |
|||
}, 5000); |
|||
}, |
|||
|
|||
/** |
|||
* 处理auth认证返回的ChannelStatus消息 |
|||
* @param {object} data 消息内容对象 |
|||
*/ |
|||
handleAuthMessage(data) { |
|||
if (data.data.authed) { |
|||
// 认证成功
|
|||
this.sendHeart(); |
|||
} else { |
|||
this.$message.error('消息系统认证失败, 请重新登录'); |
|||
// 清除掉本地无用的token
|
|||
sessionStorage.removeItem('anyringToken'); |
|||
socket = null; |
|||
setTimeout(() => { |
|||
this.$router.push('/user/login'); |
|||
}, 1000); |
|||
} |
|||
}, |
|||
}, |
|||
}; |
|||
|
|||
export default mixin; |
@ -1,143 +0,0 @@ |
|||
import axios from 'axios'; |
|||
import { message } from 'ant-design-vue'; |
|||
import { getSmscode, getPicCode, signIn, changePassword, signUp, getUserId } from 'config/api-user'; |
|||
|
|||
const actions = { |
|||
/** |
|||
* sendCode 发送验证码 |
|||
* @param {any} commit |
|||
* @param {object} params 提交的数据 |
|||
* @param {string} params.phone 手机号 |
|||
*/ |
|||
async sendCode({ commit }, params) { |
|||
try { |
|||
const res = await getSmscode({ params }); |
|||
const { code, msg, data } = res.data; |
|||
if (code === 200) { |
|||
return data; |
|||
} else { |
|||
message.error(msg || '发送失败'); |
|||
throw msg; |
|||
} |
|||
} catch (error) { |
|||
throw error || '发送失败'; |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* sendPicCode 获取图片验证码 |
|||
* @param {any} commit |
|||
* @param {object} params 提交的数据 |
|||
*/ |
|||
async sendPicCode({ commit }) { |
|||
try { |
|||
const res = await getPicCode(); |
|||
const { code, msg, data } = res.data; |
|||
if (code === 200) { |
|||
commit('setPicCode', data); |
|||
return data; |
|||
} else { |
|||
throw msg; |
|||
} |
|||
} catch (error) { |
|||
throw error || '获取失败'; |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* signIn 登录 |
|||
* @param {any} commit |
|||
* @param {string} identifier 身份标识 手机号 用户名 |
|||
* @param {string} credential 身份凭证 验证码 密码 |
|||
* @return {Promise} result 服务器返回信息 |
|||
*/ |
|||
async signIn({ commit }, params) { |
|||
const hideLoading = message.loading('登录中', 0); |
|||
try { |
|||
const res = await signIn(params); |
|||
const { code, msg, data } = res.data; |
|||
if (code === 200) { |
|||
commit('sign', data.token); |
|||
commit('setUser', data); |
|||
hideLoading(); |
|||
message.success('登录成功'); |
|||
return data; |
|||
} else { |
|||
hideLoading(); |
|||
throw msg || '登录失败'; |
|||
} |
|||
} catch (error) { |
|||
hideLoading(); |
|||
throw error || '登录失败'; |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 修改密码 忘记密码 |
|||
* @param {any} commit |
|||
* @param {object} params 要提交的参数 |
|||
*/ |
|||
async changePassword({ commit }, params) { |
|||
try { |
|||
const res = await changePassword(params); |
|||
const { code, msg, data } = res.data; |
|||
if (code === 200) { |
|||
message.success('修改密码成功'); |
|||
return data; |
|||
} else { |
|||
throw msg || '修改密码失败'; |
|||
} |
|||
} catch (error) { |
|||
throw error || '修改密码失败'; |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* singUp 注册新用户 |
|||
* @param {any} commit |
|||
* @param {object} params 提交的数据 |
|||
* @param {string} params.account 用户名 |
|||
* @param {string} params.password 密码 |
|||
* @param {string} params.phone 手机号 |
|||
* @param {string} params.smsCode 验证码 |
|||
*/ |
|||
async signUp({ commit }, params) { |
|||
try { |
|||
const res = await signUp(params); |
|||
const { code, msg, data } = res.data; |
|||
if (code === 200) { |
|||
commit('sign', data.token); |
|||
commit('setUser', data); |
|||
message.success('注册成功'); |
|||
return data; |
|||
} else { |
|||
throw msg || '注册失败'; |
|||
} |
|||
} catch (error) { |
|||
throw error || '注册失败'; |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 通过userId获取token |
|||
* @param {any} commit |
|||
* @param {object} params 提交的参数 |
|||
*/ |
|||
// async getUserId({ commit }, params) {
|
|||
// try {
|
|||
// const res = await getUserId({ params });
|
|||
// const { code, msg, data } = res.data;
|
|||
// if (code === 200) {
|
|||
// commit('sign', data.token);
|
|||
// commit('setUser', data);
|
|||
// return data;
|
|||
// } else {
|
|||
// throw msg;
|
|||
// }
|
|||
// } catch (error) {
|
|||
// throw error || '获取个人信息失败';
|
|||
// }
|
|||
// },
|
|||
}; |
|||
|
|||
export default actions; |
@ -1,16 +1,13 @@ |
|||
import Vue from "vue"; |
|||
import Vuex from "vuex"; |
|||
import mutations from './mutations'; |
|||
import actions from './actions'; |
|||
import state from './state'; |
|||
import getters from './getters'; |
|||
/* |
|||
* Copyright (c) 2019. |
|||
* author: wally |
|||
* email: 18603454788@163.com |
|||
*/ |
|||
|
|||
Vue.use(Vuex); |
|||
|
|||
const store = new Vuex.Store({ |
|||
state, |
|||
mutations, |
|||
actions, |
|||
}); |
|||
import Vue from 'vue'; |
|||
import Vuex from 'vuex'; |
|||
import home from './modules/home/index'; |
|||
import messages from './modules/messages/index'; |
|||
|
|||
export default store; |
|||
Vue.use(Vuex); |
|||
export default new Vuex.Store({ modules: { home, messages } }); |
|||
|
@ -0,0 +1,28 @@ |
|||
import axios from 'axios'; |
|||
import { message } from 'ant-design-vue'; |
|||
import { getUserId } from 'config/api-user'; |
|||
|
|||
const actions = { |
|||
/** |
|||
* 通过userId获取token |
|||
* @param {any} commit |
|||
* @param {object} params 提交的参数 |
|||
*/ |
|||
async getUserId({ commit }, params) { |
|||
try { |
|||
const res = await getUserId({ params }); |
|||
const { code, msg, data } = res.data; |
|||
if (code === 200) { |
|||
commit('sign', data.token); |
|||
commit('setUser', data); |
|||
return data; |
|||
} else { |
|||
throw msg; |
|||
} |
|||
} catch (error) { |
|||
throw error || '获取个人信息失败'; |
|||
} |
|||
}, |
|||
}; |
|||
|
|||
export default actions; |
@ -0,0 +1,6 @@ |
|||
import mutations from './mutations'; |
|||
import actions from './actions'; |
|||
import getters from './getters'; |
|||
import state from './state'; |
|||
|
|||
export default { namespaced: true, state, getters, mutations, actions }; |
@ -0,0 +1,7 @@ |
|||
import http from 'axios'; |
|||
import { message } from 'ant-design-vue'; |
|||
import {} from 'config/api'; |
|||
|
|||
const actions = {}; |
|||
|
|||
export default actions; |
@ -0,0 +1,3 @@ |
|||
const getters = {}; |
|||
|
|||
export default getters; |
@ -0,0 +1,11 @@ |
|||
/* |
|||
* Copyright (c) 2019. |
|||
* author: wally |
|||
* email: 18603454788@163.com |
|||
*/ |
|||
import mutations from './mutations'; |
|||
import actions from './actions'; |
|||
import getters from './getters'; |
|||
import state from './state'; |
|||
|
|||
export default { namespaced: true, state, getters, mutations, actions }; |
@ -0,0 +1,173 @@ |
|||
const mutations = { |
|||
/** |
|||
* 初始化消息栈 |
|||
* @param {object} state |
|||
* @param {string} type |
|||
* type: |
|||
* syncMessages 同步消息栈 |
|||
* checkMessages 交付物消息栈 |
|||
* faultMessages 故障消息 未处理消息栈 |
|||
* faults 所有的故障消息栈 |
|||
*/ |
|||
messagesInit(state, type) { |
|||
const messages = localStorage.getItem(type) ? JSON.parse(localStorage.getItem(type)) : []; |
|||
state[type] = messages; |
|||
}, |
|||
|
|||
/** |
|||
* 将新 消息添加到 消息栈 最前边 |
|||
* @param { object } state |
|||
* @param { object } data |
|||
* data: message, type |
|||
* message 消息对象 |
|||
* type: |
|||
* syncMessages 同步消息栈 |
|||
* checkMessages 交付物消息栈 |
|||
* faultMessages 故障消息 未处理消息栈 |
|||
* faults 所有的故障消息栈 |
|||
* |
|||
* 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) { |
|||
localStorage.setItem(data.type, JSON.stringify(messages)); |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 通过消息id移除指定 同步 消息 |
|||
* @param { object } state |
|||
* @param { object } data |
|||
* data: messageId, type |
|||
* messageId: 要移除的消息的messageId |
|||
* type: |
|||
* syncMessages 同步消息栈 |
|||
* checkMessages 交付物消息栈 |
|||
* 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) { |
|||
localStorage.setItem(data.type, JSON.stringify(messages)); |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 清除指定type的消息 |
|||
* @param {any} state |
|||
* @param {object} data |
|||
* data: type, cache |
|||
*/ |
|||
messagesClear(state, data) { |
|||
state[data.type] = []; |
|||
if (data.cache) { |
|||
localStorage.removeItem(data.type); |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 添加体重消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddWeight(state, data) { |
|||
state.weightMessage = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加RFID消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddRfid(state, data) { |
|||
state.rfidMessage = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加称重传感器一消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddWeighSensor1(state, data) { |
|||
state.weighSensor1 = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加称重传感器二消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddWeighSensor2(state, data) { |
|||
state.weighSensor2 = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加称重传感器三消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddWeighSensor3(state, data) { |
|||
state.weighSensor3 = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加称重传感器四消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddWeighSensor4(state, data) { |
|||
state.weighSensor4 = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加震动传感器消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddVibrationSensor(state, data) { |
|||
state.vibrationSensor = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加溶栓剂量(总量)消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddThrombolyticDose(state, data) { |
|||
state.thrombolyticDose = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加团注剂量消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddBolusDose(state, data) { |
|||
state.bolusDose = data; |
|||
}, |
|||
|
|||
/** |
|||
* 添加维持剂量消息 |
|||
* @param {*} state |
|||
* @param {*} data |
|||
*/ |
|||
messagesAddMaintenanceDose(state, data) { |
|||
state.maintenanceDose = data; |
|||
}, |
|||
}; |
|||
export default mutations; |
@ -0,0 +1,15 @@ |
|||
const state = { |
|||
syncMessages: [], // 同步消息
|
|||
weightMessage: null, // 体重
|
|||
rfidMessage: null, // RFID
|
|||
weighSensor1: null, // 称重传感器一
|
|||
weighSensor2: null, // 称重传感器二
|
|||
weighSensor3: null, // 称重传感器三
|
|||
weighSensor4: null, // 称重传感器四
|
|||
vibrationSensor: null, // 震动传感器
|
|||
thrombolyticDose: null, // 溶栓剂量(总量)
|
|||
bolusDose: null, // 团注剂量
|
|||
maintenanceDose: null, // 维持剂量
|
|||
}; |
|||
|
|||
export default state; |
Loading…
Reference in new issue