src/api/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/bg-task/FYBgTaskCard.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/enum/socketMessage.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/FYWebSocket.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/MessageManager.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/eventBus.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/socketMessage.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/index.js
@@ -17,6 +17,9 @@ // ip2_file = 'https://fyami.com.cn/'; } // socket const $socket_base_url = 'ws://192.168.0.150:8080/workstream' //é£ç¾½ç管 const $fysp = axios.create({ baseURL: ip1, @@ -106,4 +109,4 @@ ); }); export { $fysp, $fytz }; export { $fysp, $fytz, $socket_base_url }; src/components/bg-task/FYBgTaskCard.vue
@@ -46,6 +46,8 @@ import { useFetchData } from '@/composables/fetchData'; import bgtaskApi from '@/api/fysp/bgtaskApi'; import { enumBgTask, BG_TASK_TYPE, BG_TASK_STATUS } from '@/enum/bgTask'; import { SOCKET_MESSAGE_TYPE } from '@/enum/socketMessage'; import MessageManager from '@/socket/MessageManager.js'; export default { setup() { @@ -76,7 +78,36 @@ deep: true } }, created() { this.registerBgTaskMessage() }, methods: { registerBgTaskMessage() { MessageManager.register(SOCKET_MESSAGE_TYPE.BACKGROUND_TASK.name, (data) => { this.refreshTaskById(data) }) }, /** * å·æ°ä¸ä¸ªä»»å¡éè¿idï¼å¦ææ¯æ°çä»»å¡åæ·»å å°ä»»å¡å表taskListä¸ * @param data */ refreshTaskById(data) { if (!data || data == {}) { return; } let isNewTask = true for (let index = 0; index < this.taskList.length; index++) { const task = this.taskList[index]; if (task.id == data.id) { this.taskList[index] = data isNewTask = false break } } if (isNewTask) { this.taskList.push(data) } }, addTask() {}, newTestTask() { this.fetchData((page, pageSize) => { src/enum/socketMessage.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ import { Enum } from './enum'; const SOCKET_MESSAGE_TYPE = Enum({ BACKGROUND_TASK: { id: 1, value: '1', label: 'åå°ä»»å¡', name: 'background_task' }, BUSINESS_LOG: { id: 2, value: '2', label: 'ä¸å¡æ¥å¿', name: 'business_log' } }); /** * æ ¹æ®socketæ¶æ¯ç±»ååæ®µå¾å°è¿ä¸ªç±»å对象 * @param {*} value socketæ¶æ¯ç±»å * @returns 对åºçæ¶æ¯ç±»å对象 */ /** * éè¿åç§°æ¥æ¾æä¸¾ç±» * @param {String} value * @returns */ function getByValue(value) { for (const type in SOCKET_MESSAGE_TYPE) { const typeObj = SOCKET_MESSAGE_TYPE[type] if (typeObj.value == value) { return typeObj } } } export { SOCKET_MESSAGE_TYPE, getByValue }; src/main.js
@@ -5,6 +5,7 @@ import { router } from './router'; import App from './App.vue'; import timeUtil from './utils/time-util'; import { initSocketClient } from '@/socket/index.js' // import 'element-plus/dist/index.css'; import './assets/main.css'; @@ -18,6 +19,8 @@ import dayjs from 'dayjs'; import isSameOrAfter from 'dayjs/plugin/isSameOrAfter'; import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'; // socket客æ·ç«¯ initSocketClient() // echarts import * as echarts from 'echarts' src/socket/FYWebSocket.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,132 @@ import { getByValue } from '@/enum/socketMessage.js'; import { encodeMessage, decodeMessage } from './socketMessage.js'; import { $socket_base_url } from '@/api/index.js'; class FYWebSocket extends WebSocket { constructor() { super($socket_base_url); return this; } /** * heartBeatConfig å¿è·³è¿æ¥åæ° * time: å¿è·³æ¶é´é´é * timeout: å¿è·³è¶ æ¶é´é * reconnect: æçº¿éè¿æ¶é´é´é * reconnectFunc æçº¿éè¿å½æ° * messageManager æ¶æ¯ç®¡çå¨ */ init(reconnectFunc, messageManager) { this.onopen = this.openHandler; // è¿æ¥æååçåè°å½æ° this.onclose = this.closeHandler; // è¿æ¥å ³éåçåè° å½æ° this.onmessage = this.messageHandler; // æ¶å°æå¡å¨æ°æ®åçåè°å½æ° this.onerror = this.errorHandler; // è¿æ¥åçé误çåè°æ¹æ³ this.heartBeatConfig = { time: 30 * 1000, timeout: 2 * 1000, reconnect: 30 * 1000 }; // å¿è·³è¿æ¥é ç½®åæ° this.isReconnect = typeof reconnectFunc === 'function'; // è®°å½æ¯å¦æçº¿éè¿ this.reconnectFunc = reconnectFunc; // æçº¿éè¿å½æ° this.messageManager = messageManager; // æ¶æ¯å¤ç管çå¨ this.reconnectTimer = null; // è®°å½æçº¿éè¿çæ¶é´å¨ this.startHeartBeatTimer = null; // è®°å½å¿è·³æ¶é´å¨ this.webSocketState = false; // è®°å½socketè¿æ¥ç¶æ trueä¸ºå·²è¿æ¥ } // è·åæ¶æ¯ getMessage({ data }) { return decodeMessage(data); } // åéæ¶æ¯ sendMessage(type, data) { return this.send(encodeMessage(type, data)); } // è¿æ¥æååçåè°å½æ° openHandler() { console.log('====onopen websocketè¿æ¥æå===='); // socketç¶æè®¾ç½®ä¸ºè¿æ¥ï¼å为åé¢çæçº¿éè¿çæ¦æªå¨ this.webSocketState = true; // 夿æ¯å¦å¯å¨å¿è·³æºå¶ if (this.heartBeatConfig && this.heartBeatConfig.time) { this.startHeartBeat(this.heartBeatConfig.time); } } // æ¶å°æå¡å¨æ°æ®åçåè°å½æ° messageHandler(res) { const webSocketMsg = this.getMessage(res); if (!(webSocketMsg && webSocketMsg != null && webSocketMsg != {})) { return; } const type = webSocketMsg.type; const data = webSocketMsg.data; let typeObj = getByValue(type); if (type == 0) { // å°è¿æ¥ç¶ææ´æ°ä¸ºå¨çº¿ this.webSocketState = true; console.log('====onmessage websocketå¿è·³æ£æµ====', data); } else { // åéäºä»¶ this.messageManager.emit(typeObj.name, data); console.log(`====onmessage websocket${typeObj.label}====`, data); } } // è¿æ¥å ³éåçåè° å½æ° closeHandler() { console.log('====onclose websocketå ³éè¿æ¥===='); // 设置socketç¶æä¸ºæçº¿ this.webSocketState = false; // 卿å¼è¿æ¥æ¶ æ¸ é¤å¿è·³æ¶é´å¨å æå¼éè¿æ¶é´å¨ this.startHeartBeatTimer && clearTimeout(this.startHeartBeatTimer); this.reconnectTimer && clearTimeout(this.reconnectTimer); this.reconnectWebSocket(); } errorHandler() { console.log('====onerror websocketè¿æ¥åºé===='); // 设置socketç¶æä¸ºæçº¿ this.webSocketState = false; // éæ°è¿æ¥ this.reconnectWebSocket(); } // å¿è·³åå§åæ¹æ³ timeï¼å¿è·³é´é startHeartBeat(time) { this.startHeartBeatTimer = setTimeout(() => { // 客æ·ç«¯æ¯é䏿®µæ¶é´åæå¡ç«¯åéä¸ä¸ªå¿è·³æ¶æ¯ this.sendMessage('0', Date.now()); this.waitingServer(); }, time); } //å¨å®¢æ·ç«¯åéæ¶æ¯ä¹åï¼å»¶æ¶çå¾ æå¡å¨ååº,éè¿webSocketState夿æ¯å¦è¿çº¿æå waitingServer() { this.webSocketState = false; setTimeout(() => { // è¿çº¿æåç¶æä¸ ç»§ç»å¿è·³æ£æµ if (this.webSocketState) { this.startHeartBeat(this.heartBeatConfig.time); return; } console.log('websocket å¿è·³æ ååº, å·²ç»åæå¡ç«¯æçº¿'); // éæ°è¿æ¥æ¶ï¼è®°å¾è¦å å ³éå½åè¿æ¥ try { this.close(); } catch (error) { console.log('websocket å½åè¿æ¥å·²ç»å ³é'); } // // éæ°è¿æ¥ // this.reconnectWebSocket() }, this.heartBeatConfig.timeout); } // éæ°è¿æ¥ reconnectWebSocket() { // 夿æ¯å¦æ¯éæ°è¿æ¥ç¶æ(å³è¢«å¨ç¶ææçº¿)ï¼å¦ææ¯ä¸»å¨æçº¿çä¸éè¦éæ°è¿æ¥ if (!this.isReconnect) { return; } // æ ¹æ®ä¼ å ¥çæçº¿éè¿æ¶é´é´é å»¶æ¶è¿æ¥ this.reconnectTimer = setTimeout(() => { // 触åéæ°è¿æ¥å½æ° console.log('====onerror websocketå°è¯éè¿===='); this.reconnectFunc(); }, this.heartBeatConfig.reconnect); } } export { FYWebSocket }; src/socket/MessageManager.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,27 @@ import eventBus from './eventBus.js'; class MessageManager { constructor() { this.messageHandler = eventBus; } /** * 注åäºä»¶ * @param {*} eventType äºä»¶ç±»å * @param {*} handler äºä»¶å¤ç彿° */ register(eventType, handler) { this.messageHandler.register(eventType, handler); } /** * åéäºä»¶ * @param {*} eventType äºä»¶ç±»å * @param {...any} ars äºä»¶å 容 */ emit(eventType, ...ars) { this.messageHandler.emit(eventType, ...ars); } } const instance = new MessageManager(); Object.freeze(instance); // 鲿¢ä¿®æ¹å®ä¾ export default instance; src/socket/eventBus.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,26 @@ // è§å¯è æ¨¡å¼ class EventBus { constructor() { // æ¶æ¯ä¸å¿ï¼è®°å½äºææçäºä»¶ 以å äºä»¶å¯¹åºçå¤ç彿° this.subs = Object.create(null) } // æ³¨åæ¶é´ // åæ°ï¼1.äºä»¶åç§° 2.äºä»¶å¤ç彿° register(eventType, handler) { this.subs[eventType] = this.subs[eventType] || [] this.subs[eventType].push(handler) } // 触åäºä»¶ // åæ°ï¼ 1.äºä»¶åç§° 2.æ¥æ¶çåæ° emit(eventType, ...ars) { if(this.subs[eventType]) { this.subs[eventType].forEach(handler => { handler(...ars) }) } } } export default new EventBus() src/socket/index.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ import { FYWebSocket } from '@/socket/FYWebSocket.js'; import MessageManager from '@/socket/MessageManager.js'; let socket = null; // è¿æ¥websocket function connectWebSocket() { socket = new FYWebSocket(); socket.init(() => { connectWebSocket(); }, MessageManager); return socket; } /** * åå§åsocket客æ·ç«¯ */ function initSocketClient() { connectWebSocket(); } export { initSocketClient }; src/socket/socketMessage.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,51 @@ // å¼å§ç¬¦å·åç»æç¬¦å·åå«ä¸º '##' å '%%', åé符为 && // å¼å§ç¬¦å· const startStr = '##'; // åéç¬¦å· const splitStr = '&&'; // ç»æç¬¦å· const endStr = '%%'; // æ ¡éªæ ¼å¼ function verificationMessage(message) { if (!message || message == '') { return false; } if (!(typeof message == 'string')) { return false; } if (!message.startsWith(startStr)) { return false; } if (!message.endsWith(endStr)) { return false; } return true; } /** * è§£æåºç±»ååå 容 * @param {*} message socketæ¶æ¯ä¸çdataåæ®µ * @returns */ function decodeMessage(message) { if (!verificationMessage(message)) { return; } const parts = message.slice(startStr.length, -endStr.length).split(splitStr); const type = parts[0]; let data = JSON.parse(parts[1]); return { type: type, data: data }; } /** * çææå®æ ¼å¼çæ¶æ¯å符串 * @param {*} type æ¶æ¯ç±»å * @param {*} data æ¶æ¯å 容 * @returns çæçæ¶æ¯å符串 */ function encodeMessage(type, data) { return `${startStr}${type}${splitStr}${JSON.stringify(data)}${endStr}`; } export { verificationMessage, decodeMessage, encodeMessage };