src/App.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components.d.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/enum/socketMessage.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/eventBus.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/socket/socketMessage.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/App.vue
@@ -40,13 +40,15 @@ <script> import zhCn from 'element-plus/dist/locale/zh-cn.mjs'; import { FYWebSocket } from '@/socket/index.js' import eventBus from '@/socket/eventBus.js'; export default { data() { return { isCollapsed: false, navTitles: [], locale: zhCn, socket: null, }; }, methods: { @@ -56,7 +58,26 @@ navPage(titles) { this.navTitles = titles; }, // è¿æ¥websocket connectWebSocket() { this.socket = new FYWebSocket() this.socket.init({ time: 4 * 1000, timeout: 2 * 1000, reconnect: 3 * 1000 }, true) }, // æçº¿éè¿websocket startReconnectWebSocket() { eventBus.register('reconnect', () => { this.connectWebSocket() }) } }, created() { this.connectWebSocket() this.startReconnectWebSocket() } }; </script> 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.d.ts
@@ -13,32 +13,22 @@ CompGenericWrapper: typeof import('./components/CompGenericWrapper.vue')['default'] CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default'] Content: typeof import('./components/core/Content.vue')['default'] ElAffix: typeof import('element-plus/es')['ElAffix'] ElAside: typeof import('element-plus/es')['ElAside'] ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElBadge: typeof import('element-plus/es')['ElBadge'] ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] ElButton: typeof import('element-plus/es')['ElButton'] ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElCalendar: typeof import('element-plus/es')['ElCalendar'] ElCard: typeof import('element-plus/es')['ElCard'] ElCascader: typeof import('element-plus/es')['ElCascader'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] ElCol: typeof import('element-plus/es')['ElCol'] ElCollapse: typeof import('element-plus/es')['ElCollapse'] ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElContainer: typeof import('element-plus/es')['ElContainer'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] ElDialog: typeof import('element-plus/es')['ElDialog'] ElDivider: typeof import('element-plus/es')['ElDivider'] ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] @@ -47,29 +37,19 @@ ElImage: typeof import('element-plus/es')['ElImage'] ElImageViewer: typeof import('element-plus/es')['ElImageViewer'] ElInput: typeof import('element-plus/es')['ElInput'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElLink: typeof import('element-plus/es')['ElLink'] ElMain: typeof import('element-plus/es')['ElMain'] ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] ElOption: typeof import('element-plus/es')['ElOption'] ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm'] ElPopover: typeof import('element-plus/es')['ElPopover'] ElRadio: typeof import('element-plus/es')['ElRadio'] ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRow: typeof import('element-plus/es')['ElRow'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElSegmented: typeof import('element-plus/es')['ElSegmented'] ElSelect: typeof import('element-plus/es')['ElSelect'] ElSpace: typeof import('element-plus/es')['ElSpace'] ElStep: typeof import('element-plus/es')['ElStep'] ElSteps: typeof import('element-plus/es')['ElSteps'] ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTabPane: typeof import('element-plus/es')['ElTabPane'] @@ -77,7 +57,6 @@ ElTag: typeof import('element-plus/es')['ElTag'] ElText: typeof import('element-plus/es')['ElText'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTransfer: typeof import('element-plus/es')['ElTransfer'] ElTree: typeof import('element-plus/es')['ElTree'] ElUpload: typeof import('element-plus/es')['ElUpload'] Footer: typeof import('./components/core/Footer.vue')['default'] src/enum/socketMessage.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,6 @@ const messageTypes = [ { id: 0, label: 'å¿è·³æ£æµ', value: '0' }, { id: 1, label: 'åå°ä»»å¡', value: '1' }, { id: 2, label: 'ä¸å¡æ¥å¿', value: '2' } ]; export { messageTypes }; 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,134 @@ import eventBus from './eventBus.js'; import { messageTypes } 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: æçº¿éè¿æ¶é´é´é * isReconnect æ¯å¦æçº¿éè¿ */ init(heartBeatConfig, isReconnect) { this.onopen = this.openHandler; // è¿æ¥æååçåè°å½æ° this.onclose = this.closeHandler; // è¿æ¥å ³éåçåè° å½æ° this.onmessage = this.messageHandler; // æ¶å°æå¡å¨æ°æ®åçåè°å½æ° this.onerror = this.errorHandler; // è¿æ¥åçé误çåè°æ¹æ³ this.heartBeatConfig = heartBeatConfig; // å¿è·³è¿æ¥é ç½®åæ° this.isReconnect = isReconnect; // è®°å½æ¯å¦æçº¿éè¿ 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 è¿æ¥æå===='); // 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 switch (type) { case '1': // åå°ä»»å¡ // åéäºä»¶ eventBus.emit('1', data); console.log('====onmessage åå°ä»»å¡====', data); break; case '2': // ä¸å¡æ¥å¿ // åéäºä»¶ eventBus.emit('2', data); console.log('====onmessage ä¸å¡æ¥å¿====', data); break; case '0': // å¿è·³æ£æµ // å°è¿æ¥ç¶ææ´æ°ä¸ºå¨çº¿ this.webSocketState = true; eventBus.emit('0', data); console.log('====onmessage å¿è·³æ£æµ====', data); break; } } // è¿æ¥å ³éåçåè° å½æ° 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(messageTypes[0].value, Date.now()); this.waitingServer(); }, time); } //å¨å®¢æ·ç«¯åéæ¶æ¯ä¹åï¼å»¶æ¶çå¾ æå¡å¨ååº,éè¿webSocketState夿æ¯å¦è¿çº¿æå waitingServer() { this.webSocketState = false; setTimeout(() => { // è¿çº¿æåç¶æä¸ ç»§ç»å¿è·³æ£æµ if (this.webSocketState) { this.startHeartBeat(this.heartBeatConfig.time); return; } console.log('å¿è·³æ ååº, å·²ç»åæå¡ç«¯æçº¿'); // éæ°è¿æ¥æ¶ï¼è®°å¾è¦å å ³éå½åè¿æ¥ try { this.close(); } catch (error) { console.log('å½åè¿æ¥å·²ç»å ³é'); } // // éæ°è¿æ¥ // this.reconnectWebSocket() }, this.heartBeatConfig.timeout); } // éæ°è¿æ¥ reconnectWebSocket() { // 夿æ¯å¦æ¯éæ°è¿æ¥ç¶æ(å³è¢«å¨ç¶ææçº¿)ï¼å¦ææ¯ä¸»å¨æçº¿çä¸éè¦éæ°è¿æ¥ if (!this.isReconnect) { return; } // æ ¹æ®ä¼ å ¥çæçº¿éè¿æ¶é´é´é å»¶æ¶è¿æ¥ this.reconnectTimer = setTimeout(() => { // 触åéæ°è¿æ¥äºä»¶ eventBus.emit('reconnect'); }, this.heartBeatConfig.reconnect); } } export { FYWebSocket }; src/socket/socketMessage.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,52 @@ import { messageTypes } from '@/enum/socketMessage.js' // å¼å§ç¬¦å·åç»æç¬¦å·åå«ä¸º '##' å '%%', åé符为 && // å¼å§ç¬¦å· const startStr = '##'; // åéç¬¦å· const splitStr = '&&'; // ç»æç¬¦å· const endStr = '%%'; // æ ¡éªæ ¼å¼ function verificationMessahe(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 (!verificationMessahe(message)) { return; } const parts = message.slice(startStr.length, -endStr.length).split(splitStr); const type = parts[0]; let data = JSON.parse(parts[1]); return { type: messageTypes.find((item) => item.value == type).value, data: data }; } /** * çææå®æ ¼å¼çæ¶æ¯å符串 * @param {*} type æ¶æ¯ç±»å * @param {*} data æ¶æ¯å 容 * @returns çæçæ¶æ¯å符串 */ function encodeMessage(type, data) { return `${startStr}${type}${splitStr}${JSON.stringify(data)}${endStr}`; } export { verificationMessahe, decodeMessage, encodeMessage, messageTypes };