From af53ec7625c60033e9165e2efa41746a3f29f8b9 Mon Sep 17 00:00:00 2001 From: Soybean Date: Sun, 18 Jun 2023 22:23:42 +0800 Subject: [PATCH] feat(projects): add websocket demo --- package.json | 1 + pnpm-lock.yaml | 72 ++++++++++++++++++++++++-- src/composables/index.ts | 1 + src/composables/websocket.ts | 50 ++++++++++++++++++ src/store/modules/app/index.ts | 10 +++- src/typings/page-route.d.ts | 2 + src/views/function/websocket/index.vue | 7 +++ src/views/index.ts | 1 + 8 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 src/composables/websocket.ts create mode 100644 src/views/function/websocket/index.vue diff --git a/package.json b/package.json index 4d502e33..e3a07972 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "pinia": "2.1.4", "print-js": "1.6.0", "qs": "6.11.2", + "socket.io-client": "^4.6.2", "swiper": "9.4.1", "ua-parser-js": "1.0.35", "vditor": "3.9.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9dff0d06..85990592 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,9 @@ dependencies: qs: specifier: 6.11.2 version: 6.11.2 + socket.io-client: + specifier: ^4.6.2 + version: 4.6.2 swiper: specifier: 9.4.1 version: 9.4.1 @@ -187,7 +190,7 @@ devDependencies: specifier: 2.0.1 version: 2.0.1(vite@4.3.9) vite-plugin-vue-devtools: - specifier: ^0.2.0 + specifier: 0.2.0 version: 0.2.0(@types/node@20.3.1)(axios-cache-adapter@2.7.3)(axios@1.4.0)(body-parser@1.20.2)(cli-color@2.0.3)(express@4.18.2)(image-downloader@4.3.0)(jimp@0.16.13)(morgan@1.10.0)(pug@3.0.2)(rollup@2.79.1)(vite@4.3.9)(vue@3.3.4) vue-tsc: specifier: 1.6.5 @@ -2824,6 +2827,10 @@ packages: engines: {node: '>=14.16'} dev: true + /@socket.io/component-emitter@3.1.0: + resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} + dev: false + /@soybeanjs/changelog@0.0.4: resolution: {integrity: sha512-+aDF1k8Vy5StReDe+1bm1cymOnFCdnY2huf6Nuj1u2sbnfaTaySQ3XcFR56rxNVSh9iRaWSOPEkj74rLYjuFxg==} dependencies: @@ -4995,7 +5002,6 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: true /decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} @@ -5284,6 +5290,25 @@ packages: dev: true optional: true + /engine.io-client@6.4.0: + resolution: {integrity: sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + engine.io-parser: 5.0.7 + ws: 8.11.0 + xmlhttprequest-ssl: 2.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /engine.io-parser@5.0.7: + resolution: {integrity: sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==} + engines: {node: '>=10.0.0'} + dev: false + /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} @@ -8221,7 +8246,6 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -9939,6 +9963,30 @@ packages: - supports-color dev: true + /socket.io-client@4.6.2: + resolution: {integrity: sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + engine.io-client: 6.4.0 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /socks-proxy-agent@7.0.0: resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} engines: {node: '>= 10'} @@ -11548,6 +11596,19 @@ packages: typedarray-to-buffer: 3.1.5 dev: true + /ws@8.11.0: + resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xdg-basedir@5.1.0: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} @@ -11606,6 +11667,11 @@ packages: engines: {node: '>=4.0'} dev: true + /xmlhttprequest-ssl@2.0.0: + resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} + engines: {node: '>=0.4.0'} + dev: false + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} diff --git a/src/composables/index.ts b/src/composables/index.ts index bda997f8..72b8eed5 100644 --- a/src/composables/index.ts +++ b/src/composables/index.ts @@ -4,3 +4,4 @@ export * from './layout'; export * from './events'; export * from './echarts'; export * from './icon'; +export * from './websocket'; diff --git a/src/composables/websocket.ts b/src/composables/websocket.ts new file mode 100644 index 00000000..0d0e8cc2 --- /dev/null +++ b/src/composables/websocket.ts @@ -0,0 +1,50 @@ +import { io } from 'socket.io-client'; +import type { Socket } from 'socket.io-client'; +import { useAppStore } from '../store'; + +type ListenEvents = { + update: (id: string, data: { name: string; age: number }) => void; +}; + +type EmitEvents = { + update: (id: string, data: { name: string; age: number }) => void; +}; + +export function useWebsocket() { + const app = useAppStore(); + + const socket: Socket = (app.socket || io('ws://localhost:8080')) as Socket< + ListenEvents, + EmitEvents + >; + + if (!app.socket) { + app.setSocket(socket); + } + + function init() { + window.console.log('[socket.io] connecting...'); + + socket.on('connect', () => { + window.console.log('[socket.io] connected.'); + }); + + socket.on('disconnect', () => { + window.console.log('[socket.io] disconnected.'); + }); + + socket.on('update', (id, data) => { + window.console.log('[socket.io] update', id, data); + }); + } + + function handleUpdate(id: string, data: { name: string; age: number }) { + socket.emit('update', id, data); + } + + init(); + + return { + handleUpdate + }; +} diff --git a/src/store/modules/app/index.ts b/src/store/modules/app/index.ts index 86fb33dd..801173ce 100644 --- a/src/store/modules/app/index.ts +++ b/src/store/modules/app/index.ts @@ -1,5 +1,6 @@ import { nextTick } from 'vue'; import { defineStore } from 'pinia'; +import type { Socket } from 'socket.io-client'; import { LAYOUT_SCROLL_EL_ID } from '@soybeanjs/vue-materials'; interface AppState { @@ -17,6 +18,8 @@ interface AppState { siderCollapse: boolean; /** vertical-mix模式下 侧边栏的固定状态 */ mixSiderFixed: boolean; + /** socket.io 实例 */ + socket: Socket | null; } export const useAppStore = defineStore('app-store', { @@ -27,7 +30,8 @@ export const useAppStore = defineStore('app-store', { reloadFlag: true, settingDrawerVisible: false, siderCollapse: false, - mixSiderFixed: false + mixSiderFixed: false, + socket: null }), actions: { /** @@ -97,6 +101,10 @@ export const useAppStore = defineStore('app-store', { /** 设置主体内容全屏 */ setContentFull(full: boolean) { this.contentFull = full; + }, + /** 设置socket实例 */ + setSocket(socket: T) { + this.socket = socket; } } }); diff --git a/src/typings/page-route.d.ts b/src/typings/page-route.d.ts index 48bdafa1..b33cafc0 100644 --- a/src/typings/page-route.d.ts +++ b/src/typings/page-route.d.ts @@ -47,6 +47,7 @@ declare namespace PageRoute { | 'function_tab-detail' | 'function_tab-multi-detail' | 'function_tab' + | 'function_websocket' | 'management' | 'management_auth' | 'management_role' @@ -102,6 +103,7 @@ declare namespace PageRoute { | 'function_tab-detail' | 'function_tab-multi-detail' | 'function_tab' + | 'function_websocket' | 'management_auth' | 'management_role' | 'management_route' diff --git a/src/views/function/websocket/index.vue b/src/views/function/websocket/index.vue new file mode 100644 index 00000000..fb62d1f0 --- /dev/null +++ b/src/views/function/websocket/index.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/src/views/index.ts b/src/views/index.ts index f4b28ffa..52b4d6c1 100644 --- a/src/views/index.ts +++ b/src/views/index.ts @@ -29,6 +29,7 @@ export const views: Record< 'function_tab-detail': () => import('./function/tab-detail/index.vue'), 'function_tab-multi-detail': () => import('./function/tab-multi-detail/index.vue'), function_tab: () => import('./function/tab/index.vue'), + function_websocket: () => import('./function/websocket/index.vue'), management_auth: () => import('./management/auth/index.vue'), management_role: () => import('./management/role/index.vue'), management_route: () => import('./management/route/index.vue'),