| | |
| | | "quill": "1.3.7", |
| | | "screenfull": "5.0.2", |
| | | "sortablejs": "1.10.2", |
| | | "speak-tts": "^2.0.8", |
| | | "stylus": "^0.59.0", |
| | | "stylus-loader": "^7.1.0", |
| | | "viewerjs": "^1.11.3", |
New file |
| | |
| | | import request from '@/utils/request'; |
| | | |
| | | /** |
| | | * 获取websocket连接地址。 |
| | | * @param query |
| | | * @returns {*} |
| | | * @author 时克英 |
| | | * @date 2023-04-17 |
| | | */ |
| | | export function getWebsocketUri() { |
| | | return request({ |
| | | url: '/websocket/uri', |
| | | method: 'get', |
| | | params: null |
| | | }) |
| | | } |
| | |
| | | showBreadCrumb:false // 是否显示顶部面包屑 |
| | | } |
| | | }, |
| | | |
| | | created() { |
| | | this.initTts(); |
| | | }, |
| | | |
| | | methods: { |
| | | initTts(){ |
| | | this.$store.dispatch('app/setSpeechTts'); |
| | | }, |
| | | toggleSideBar() { |
| | | this.$store.dispatch('app/toggleSideBar') |
| | | this.$store.dispatch('app/toggleSideBar'); |
| | | }, |
| | | async logout() { |
| | | this.$confirm('确定注销并退出系统吗?', '提示', { |
| | |
| | | }, |
| | | variables() { |
| | | return variables; |
| | | }, |
| | | |
| | | // 2023-04-17,定义接收websocket消息 |
| | | getWsMsg (){ |
| | | // return this.$store.websocket.state.webSocketMsg; |
| | | return this.$store.state.user.webSocketMsg; |
| | | } |
| | | }, |
| | | // 2023-04-17 |
| | | watch: { |
| | | getWsMsg:{ |
| | | handler: function(newVal) { |
| | | // console.log(newVal) |
| | | // alert('接收到webSocket推送:'+ newVal); |
| | | this.$notify({ |
| | | title: '新消息提醒:', //标题 |
| | | // message: '这是一条不会自动关闭的消息', //内容 |
| | | duration: 0, //设置弹框消失事件 |
| | | position:'bottom-right', // 设置弹框在屏幕的哪个角弹出(只能设置4个角) |
| | | type: 'info', //给标题前加一个小图标 |
| | | offset: 100, //偏移量:距离四个角的偏移程度(默认偏移了16px) |
| | | dangerouslyUseHTMLString: true, //是否支持弹出框内传入 HTML 片段 |
| | | message: '<strong>这是 <i>HTML</i> 片段</strong>' + newVal, //开启后,这里可以写html |
| | | showClose: true, //隐藏关闭按钮(右上角的x 默认为true,显示) |
| | | onClose() {console.log('关闭啦', event)}, // 手动关闭时的回调函数 |
| | | }); |
| | | this.$store.state.app.tts.speak("有新消息提醒,请点击查看"); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | methods: { |
| | | handleClickOutside() { |
| | | this.$store.dispatch('app/closeSideBar', { withoutAnimation: false }) |
| | |
| | | // 字典数据组件 |
| | | import DictData from '@/components/RuoYi/DictData' |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` |
| | | //~ 平台提供的组件,时克英,2023-04-17 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` |
| | | // import * as WebConnection from "@/utils/webconnection"; |
| | | |
| | | // 全局方法挂载 |
| | | Vue.prototype.getDicts = getDicts |
| | | Vue.prototype.getConfigKey = getConfigKey |
| | |
| | | Vue.prototype.download = download |
| | | Vue.prototype.handleTree = handleTree |
| | | |
| | | // 时克英,2023-04-17 |
| | | // Vue.prototype.webConnection = WebConnection |
| | | |
| | | // 全局组件挂载 |
| | | Vue.component('DictTag', DictTag) |
| | | Vue.component('Pagination', Pagination) |
| | |
| | | import settings from './modules/settings' |
| | | import getters from './getters' |
| | | |
| | | // 时克英,2023-04-17 |
| | | // import websocket from './modules/websoket' |
| | | |
| | | Vue.use(Vuex) |
| | | |
| | | const store = new Vuex.Store({ |
| | |
| | | tagsView, |
| | | permission, |
| | | settings |
| | | // websocket |
| | | }, |
| | | getters |
| | | }) |
| | |
| | | import Cookies from 'js-cookie' |
| | | import SpeechObject from '@/utils/Speech' |
| | | |
| | | const state = { |
| | | sidebar: { |
| | |
| | | hide: false |
| | | }, |
| | | device: 'desktop', |
| | | size: Cookies.get('size') || 'medium' |
| | | size: Cookies.get('size') || 'medium', |
| | | |
| | | // 2023-04-18,语音播报对象 |
| | | tts: null |
| | | } |
| | | |
| | | const mutations = { |
| | |
| | | }, |
| | | SET_SIDEBAR_HIDE: (state, status) => { |
| | | state.sidebar.hide = status |
| | | }, |
| | | SET_SPEECH_TTS: (state) => { |
| | | state.tts = new SpeechObject(); |
| | | } |
| | | } |
| | | |
| | |
| | | }, |
| | | toggleSideBarHide({ commit }, status) { |
| | | commit('SET_SIDEBAR_HIDE', status) |
| | | }, |
| | | setSpeechTts({commit}){ |
| | | commit('SET_SPEECH_TTS') |
| | | } |
| | | } |
| | | |
| | |
| | | import { login, logout, getInfo } from '@/api/login' |
| | | import { getToken, setToken, removeToken } from '@/utils/auth' |
| | | import {encrypt} from '@/utils/jsencrypt' |
| | | // import Vue from 'vue' |
| | | import {Message} from "element-ui"; |
| | | // import WebConnection from "@/utils/webconnection"; |
| | | import WebConnection from "@/utils/web-connection"; |
| | | |
| | | const user = { |
| | | state: { |
| | |
| | | name: '', |
| | | avatar: '', |
| | | roles: [], |
| | | permissions: [] |
| | | permissions: [], |
| | | // 2023-04-17 添加websocket |
| | | webConnection: null, // 单例对象 |
| | | webSocketMsg: null, // 接收到的消息 |
| | | uri: null, // 连接websocket地址 |
| | | uid: null // 连接用户标识 |
| | | }, |
| | | |
| | | mutations: { |
| | |
| | | }, |
| | | SET_PERMISSIONS: (state, permissions) => { |
| | | state.permissions = permissions |
| | | }, |
| | | |
| | | // 2023-04-17 |
| | | SET_CONNECTION: (state, data) => { |
| | | // var webConnection = new WebConnection(); |
| | | // if(state.webConnection == null){ |
| | | state.webConnection = new WebConnection(data.uri, data.uid); |
| | | state.webConnection.startConnect(); |
| | | // } |
| | | }, |
| | | SET_CONNECTION_CLEAR: (state, data) => { |
| | | if(state.webConnection != null){ |
| | | state.webConnection.shutdown(); |
| | | } |
| | | state.webConnection = null; |
| | | }, |
| | | // 2023-04-17,监控消息变化 |
| | | SET_WS_MSG: (state, data)=>{ |
| | | state.webSocketMsg = data; |
| | | }, |
| | | SET_WS_INFO: (state, data)=>{ |
| | | state.uri = data.uri; |
| | | state.uid = data.uid; |
| | | } |
| | | }, |
| | | |
| | |
| | | } |
| | | commit('SET_NAME', user.user_name) |
| | | commit('SET_AVATAR', avatar) |
| | | |
| | | // 2023-04-17,获取用户同时,启动:websocket |
| | | // this.webConnection = new WebConnection(); |
| | | // this.webConnection.uri = res.data.uri; |
| | | // this.webConnection.uid = res.data.uid; |
| | | // vue.webConnection.setInfo(res.data.uri, res.data.uid); |
| | | // this.webConnection.timedCheckConnection(); |
| | | // this.$store.dispatch('CreateWebConnection', res.data).then(()=>{ |
| | | // }).catch(err => { |
| | | // Message.error(err); |
| | | // }); |
| | | commit('SET_WS_INFO', res.data); |
| | | commit('SET_CONNECTION', res.data); |
| | | console.log(".............CreateWebConnection()"); |
| | | |
| | | resolve(res) |
| | | |
| | | }).catch(error => { |
| | | reject(error) |
| | | }) |
| | |
| | | commit('SET_TOKEN', '') |
| | | commit('SET_ROLES', []) |
| | | commit('SET_PERMISSIONS', []) |
| | | commit('SET_CONNECTION_CLEAR', null) |
| | | removeToken() |
| | | // console.log("删除浏览器token..."); |
| | | resolve() |
New file |
| | |
| | | import WebConnection from "@/utils/webconnection"; |
| | | |
| | | /** |
| | | * 该对象废弃,放到:user组件中了 |
| | | * @type {{mutations: {SET_CONNECTION: websocket.mutations.SET_CONNECTION, SET_WS_MSG: websocket.mutations.SET_WS_MSG}, state: {webConnection: null, webSocketMsg: null}, actions: {CreateWebConnection({commit: *}, *): void}}} |
| | | */ |
| | | const websocket = { |
| | | state: { |
| | | webConnection: null, |
| | | webSocketMsg: null |
| | | }, |
| | | |
| | | mutations: { |
| | | SET_CONNECTION: (state, data) => { |
| | | // var webConnection = new WebConnection(); |
| | | WebConnection.setInfo(data.uri, data.uid); |
| | | state.webConnection = WebConnection; |
| | | }, |
| | | SET_WS_MSG: (state, data)=>{ |
| | | state.webSocketMsg = data; |
| | | } |
| | | }, |
| | | |
| | | actions: { |
| | | CreateWebConnection({ commit }, data){ |
| | | commit('SET_CONNECTION', data); |
| | | } |
| | | } |
| | | } |
| | | |
| | | export default websocket |
New file |
| | |
| | | import Speech from 'speak-tts' |
| | | |
| | | class SpeechObject { |
| | | |
| | | constructor() { |
| | | this.speech = new Speech(); |
| | | this.speech.setLanguage("zh-CN"); |
| | | this.speech.init().then(() => {console.log("tts......")}); |
| | | } |
| | | |
| | | speak(message){ |
| | | this.speech.speak({ text: message }).then(() => { |
| | | console.log("tts成功"); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | export default SpeechObject; |
New file |
| | |
| | | /** |
| | | * 判断给定字符串是否为空 |
| | | * @param val |
| | | * @returns {boolean} |
| | | * @author 时克英 |
| | | * @date 2023-04-18 |
| | | */ |
| | | export function isEmptyValue(val){ |
| | | if(val == null || val == undefined || val == '' || val == 'null' || val == 'undefined'){ |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
New file |
| | |
| | | import {isEmptyValue} from '@/utils/StringUtils' |
| | | import store from "@/store"; |
| | | |
| | | /** |
| | | * 定义'Websocket'连接对象。 |
| | | * @author 时克英 |
| | | * @date 2023-04-17 |
| | | */ |
| | | class WebConnection { |
| | | // static uid; |
| | | // static uri; |
| | | constructor(_uri, _uid) { |
| | | if(isEmptyValue(_uri)){ |
| | | throw 'uri参数为空'; |
| | | } |
| | | if(isEmptyValue(_uid)){ |
| | | throw 'uid参数为空'; |
| | | } |
| | | this.uri = _uri; |
| | | this.uid = _uid; |
| | | this.socket = null; |
| | | this._ws_timer = setInterval(this.timedCheckConnection, 120000); // 定时任务 |
| | | } |
| | | |
| | | shutdown(){ |
| | | if(this.socket != null && this.socket != undefined){ |
| | | this.socket.close(); |
| | | } |
| | | } |
| | | |
| | | startConnect(){ |
| | | if('WebSocket' in window){ |
| | | this.socket = new WebSocket(this.uri); |
| | | this.socket.onopen = this.wsOpen; |
| | | this.socket.onmessage = this.wsMessage; |
| | | this.socket.onerror = this.wsError; |
| | | this.socket.onclose = this.wsClose; |
| | | } else { |
| | | this.socket = null; |
| | | console.log('创建ws错误,可能当前浏览器不支持webSocket') |
| | | } |
| | | } |
| | | |
| | | timedCheckConnection(){ |
| | | let uri = store.state.user.uri; |
| | | let uid = store.state.user.uid; |
| | | if(!isEmptyValue(uri) && !isEmptyValue(uid)){ |
| | | // 2023-04-18,这里也无法直接使用:this.socket,因为此时为空(undefined) |
| | | // console.log("是否连接 = " + this.socket); |
| | | // if(this.socket == null || this.socket == undefined || !this.connected()){ |
| | | if(store.state.user.webConnection == null || !store.state.user.webConnection.connected()){ |
| | | this.uri = uri; |
| | | this.uid = uid; |
| | | console.log("重新连接:" + this.uri); |
| | | store.state.user.webConnection.startConnect(); |
| | | } |
| | | } else{ |
| | | console.error("uri或uid为空," + this.uid + ", " + this.uri); |
| | | } |
| | | } |
| | | wsOpen(){ |
| | | // 2023-04-18,注意:这里回调方法中无法直接获取:this.uid,猜测是因为上下文环境已经变化(类似于匿名类换成独立类的情况) |
| | | // 因此,经过长时间研究,决定需要放在全局store中。 |
| | | let uid = store.state.user.uid; |
| | | console.log("--------> uid = " + uid); |
| | | this.send(JSON.stringify({"protocol":"login", "uid":uid})); |
| | | // console.log(this); |
| | | } |
| | | wsClose(){ |
| | | this.uid = store.state.uid; |
| | | console.log("浏览器断开连接:" + this.uid); |
| | | } |
| | | wsError(err){ |
| | | console.log('== websocket error ==', err); |
| | | } |
| | | wsMessage(event){ |
| | | // console.log(event); |
| | | if(event.data == null || event.data == "" || event.data == "null"){ |
| | | console.log("接收到服务端空数据\n"); |
| | | return; |
| | | } |
| | | store.state.user.webConnection.processServerRequest(eval("("+ event.data +")")); |
| | | } |
| | | |
| | | processServerRequest(data){ |
| | | // console.log(data); |
| | | if(data == null){ |
| | | return; |
| | | } |
| | | if(data.protocol == "heartbeat"){ |
| | | return; |
| | | } |
| | | if(data.protocol == "login"){ |
| | | if(data.status == 0){ |
| | | // uid = data.uid; |
| | | //$("#showText").append("服务已连接,开始提问:" + data.uid + "\n"); |
| | | console.log("浏览器连接成功:" + data.uid); |
| | | } else { |
| | | console.log("登录认证失败:" + data.status + "\n"); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | if(data.protocol == "data" || data.protocol == "broadcast"){ |
| | | console.log("接收到web推送:"); |
| | | console.log(data.data + "\n"); |
| | | store.commit('SET_WS_MSG', data.data); |
| | | // if(data.data.touch == 1){ |
| | | // touchEvent(data.data); |
| | | // } else { |
| | | // voiceEvent(data.data); |
| | | // } |
| | | } |
| | | } |
| | | |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | //~ 内部私有方法 |
| | | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | send(message){ |
| | | if(this.socket == null){ |
| | | return; |
| | | } |
| | | if (this.socket.readyState == WebSocket.OPEN) { |
| | | this.socket.send(message); |
| | | } else { |
| | | console.log("connection is not start."); |
| | | } |
| | | } |
| | | |
| | | connected(){ |
| | | if(this.socket == null || this.socket == undefined){ |
| | | return false; |
| | | } |
| | | if(this.socket.readyState == 1){ |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |
| | | |
| | | export default WebConnection; |
New file |
| | |
| | | /** |
| | | * 定义'Websocket'连接对象。 |
| | | * @author 时克英 |
| | | * @date 2023-04-17 |
| | | * @date 2023-04-18 对象废弃,参考:web-connection.js |
| | | */ |
| | | const WebConnection = { |
| | | uri: null, // 连接地址 |
| | | _uid: null, // 用户身份 |
| | | $webSocket: null, |
| | | _ws_timer: null, // 定时任务 |
| | | |
| | | // /** |
| | | // * 默认构造函数 |
| | | // * @constructor |
| | | // */ |
| | | // WebConnection: function (){ |
| | | // console.log("..........定时任务"); |
| | | // this._ws_timer = setInterval(this.timedCheckConnection, 60000); |
| | | // }, |
| | | |
| | | setInfo: function (uri, uid){ |
| | | this.uri = uri; |
| | | this._uid = uid + ''; |
| | | console.log("..........定时任务: uid=" + this._uid); |
| | | this._ws_timer = setInterval(this.timedCheckConnection, 60000); |
| | | }, |
| | | |
| | | startConnect: function (){ |
| | | if(this.uri != null && this.uri == '-1'){ |
| | | console.log("未启用websocket"); |
| | | return; |
| | | } |
| | | // if(this.uri == null){ |
| | | // getWebsocketUri().then(response => { |
| | | // this.uri = response.data.uri; |
| | | // this.uid = response.data.uid; |
| | | // }).catch(()=>{ |
| | | // this.uri = null; |
| | | // this.uid = null; |
| | | // console.log("异常"); |
| | | // }); |
| | | // } |
| | | if('WebSocket' in window){ |
| | | this.$webSocket = new WebSocket(this.uri); |
| | | this.$webSocket.onopen = this.wsOpen; |
| | | this.$webSocket.onmessage = this.wsMessage; |
| | | this.$webSocket.onerror = this.wsError; |
| | | this.$webSocket.onclose = this.wsClose; |
| | | } else { |
| | | this.$webSocket = null; |
| | | console.log('创建ws错误,可能当前浏览器不支持webSocket') |
| | | } |
| | | }, |
| | | |
| | | send: function (message){ |
| | | if(this.$webSocket == null){ |
| | | return; |
| | | } |
| | | if (this.$webSocket.readyState == WebSocket.OPEN) { |
| | | this.$webSocket.send(message); |
| | | } else { |
| | | console.log("connection is not start."); |
| | | } |
| | | }, |
| | | |
| | | connected: function (){ |
| | | if(this.$webSocket == null || this.$webSocket == undefined){ |
| | | return false; |
| | | } |
| | | if(this.$webSocket.readyState == 1){ |
| | | // connected |
| | | return true; |
| | | } |
| | | return false; |
| | | }, |
| | | |
| | | wsOpen: function() { |
| | | // this.send(JSON.stringify({"protocol":"login", "uid":this.uid})); |
| | | let loginInfo = "{\"protocol\":\"login\", \"uid\":\"" + this._uid + "\"}"; |
| | | this.send(loginInfo); |
| | | console.log('== websocket open ==' + this._uid); |
| | | }, |
| | | |
| | | wsClose: function (){ |
| | | this._uid = null; |
| | | console.log("浏览器断开连接:" + this._uid); |
| | | }, |
| | | wsError: function(err){ |
| | | console.log('== websocket error ==', err) |
| | | }, |
| | | |
| | | wsMessage:function(event) { |
| | | if(event.data == null || event.data == "" || event.data == "null"){ |
| | | // $("#showText").append("接收到服务端空数据\n"); |
| | | console.log("接收到服务端空数据\n"); |
| | | return; |
| | | } |
| | | this.processServerRequest(eval("("+ event.data +")")); |
| | | }, |
| | | |
| | | processServerRequest: function (data){ |
| | | if(data == null){ |
| | | return; |
| | | } |
| | | if(data.protocol == "heartbeat"){ |
| | | return; |
| | | } |
| | | if(data.protocol == "login"){ |
| | | if(data.status == 0){ |
| | | // uid = data.uid; |
| | | //$("#showText").append("服务已连接,开始提问:" + data.uid + "\n"); |
| | | console.log("浏览器连接成功:" + data.uid); |
| | | } else { |
| | | console.log("登录认证失败:" + data.status + "\n"); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | if(data.protocol == "data"){ |
| | | console.log("接收到web推送:"); |
| | | console.log(data.data + "\n"); |
| | | store.commit('SET_WS_MSG', data.data); |
| | | // if(data.data.touch == 1){ |
| | | // touchEvent(data.data); |
| | | // } else { |
| | | // voiceEvent(data.data); |
| | | // } |
| | | } |
| | | }, |
| | | |
| | | timedCheckConnection: function (){ |
| | | if(this.uri != null && this.uri != "" && this.uri != undefined |
| | | && this._uid != null && this._uid != "" && this._uid != undefined){ |
| | | if(this.$webSocket == null || this.$webSocket == undefined || !this.connected()){ |
| | | console.log("重新连接:" + this.uri); |
| | | // webConnection = new WebConnection(_wurl, _uid, null); |
| | | this.startConnect(); |
| | | } |
| | | } else{ |
| | | console.error("uri或uid为空," + this._uid + ", " + this.uri); |
| | | } |
| | | } |
| | | } |
| | | |
| | | export default WebConnection; |