Parcourir la source

add websocket

SyuanYu il y a 2 ans
Parent
commit
7973840225

+ 30 - 21
frontend/package-lock.json

@@ -13,6 +13,7 @@
         "sass": "^1.57.1",
         "vue": "^3.2.45",
         "vue-i18n": "^9.2.2",
+        "vue-native-websocket-vue3": "^3.1.7",
         "vue-router": "^4.1.6",
         "vue3-google-login": "^2.0.14",
         "vuetify": "^3.1.1"
@@ -1869,8 +1870,7 @@
     "node_modules/balanced-match": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "dev": true
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
     "node_modules/binary-extensions": {
       "version": "2.2.0",
@@ -1890,7 +1890,6 @@
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
       "dependencies": {
         "balanced-match": "^1.0.0",
         "concat-map": "0.0.1"
@@ -2107,8 +2106,7 @@
     "node_modules/concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
     },
     "node_modules/convert-source-map": {
       "version": "1.9.0",
@@ -2116,6 +2114,17 @@
       "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
       "dev": true
     },
+    "node_modules/core-js": {
+      "version": "3.29.1",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz",
+      "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==",
+      "hasInstallScript": true,
+      "peer": true,
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
     "node_modules/cross-spawn": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -3004,7 +3013,6 @@
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
       "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-      "dev": true,
       "dependencies": {
         "flat-cache": "^3.0.4"
       },
@@ -3043,7 +3051,6 @@
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
       "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
-      "dev": true,
       "dependencies": {
         "flatted": "^3.1.0",
         "rimraf": "^3.0.2"
@@ -3055,8 +3062,7 @@
     "node_modules/flatted": {
       "version": "3.2.7",
       "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
-      "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
-      "dev": true
+      "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ=="
     },
     "node_modules/follow-redirects": {
       "version": "1.15.2",
@@ -3102,8 +3108,7 @@
     "node_modules/fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "dev": true
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
     },
     "node_modules/fsevents": {
       "version": "2.3.2",
@@ -3203,7 +3208,6 @@
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
       "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "dev": true,
       "dependencies": {
         "fs.realpath": "^1.0.0",
         "inflight": "^1.0.4",
@@ -3501,7 +3505,6 @@
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
       "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "dev": true,
       "dependencies": {
         "once": "^1.3.0",
         "wrappy": "1"
@@ -3510,8 +3513,7 @@
     "node_modules/inherits": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "node_modules/internal-slot": {
       "version": "1.0.4",
@@ -4063,7 +4065,6 @@
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
       "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
       "dependencies": {
         "brace-expansion": "^1.1.7"
       },
@@ -4315,7 +4316,6 @@
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
       "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "dev": true,
       "dependencies": {
         "wrappy": "1"
       }
@@ -4417,7 +4417,6 @@
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
       "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -4795,7 +4794,6 @@
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
       "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
       "dependencies": {
         "glob": "^7.1.3"
       },
@@ -5647,6 +5645,18 @@
         "vue": "^3.0.0"
       }
     },
+    "node_modules/vue-native-websocket-vue3": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/vue-native-websocket-vue3/-/vue-native-websocket-vue3-3.1.7.tgz",
+      "integrity": "sha512-f7cmJE+okUrGGu1kR5ZY5ZGzNDCJW0ktUso3QytnrtdM4i8cyiJDHjUl8hPBiwTqVuuwadc3lRsPGt0BrcrReQ==",
+      "dependencies": {
+        "file-entry-cache": "^6.0.1"
+      },
+      "peerDependencies": {
+        "core-js": "^3.6.5",
+        "vue": "^3.0.0"
+      }
+    },
     "node_modules/vue-router": {
       "version": "4.1.6",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
@@ -5858,8 +5868,7 @@
     "node_modules/wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "dev": true
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
     },
     "node_modules/ws": {
       "version": "8.12.0",

+ 1 - 0
frontend/package.json

@@ -17,6 +17,7 @@
     "sass": "^1.57.1",
     "vue": "^3.2.45",
     "vue-i18n": "^9.2.2",
+    "vue-native-websocket-vue3": "^3.1.7",
     "vue-router": "^4.1.6",
     "vue3-google-login": "^2.0.14",
     "vuetify": "^3.1.1"

+ 9 - 1
frontend/src/main.ts

@@ -5,8 +5,11 @@ import { vuetify } from "./plugins/vuetify";
 import { pinia } from "./plugins/pinia";
 import i18n from './plugins/i18n'
 import vue3GoogleLogin from 'vue3-google-login'
+import VueNativeSock from "vue-native-websocket-vue3";
+import { useSocketStoreWithOut } from './stores/useSocketStore';
 
 const app = createApp(App);
+const store = useSocketStoreWithOut();
 
 app.use(pinia);
 app.use(router);
@@ -14,6 +17,11 @@ app.use(vuetify);
 app.use(i18n);
 app.use(vue3GoogleLogin, {
     clientId: '136107811725-n71808u8t465f1afhpe2e5j7mn606nd8.apps.googleusercontent.com'
-})
+});
+app.use(VueNativeSock, "ws://172.104.93.163:1853/ws", {
+    store: store
+});
 
 app.mount("#app");
+
+export default app;

+ 0 - 1
frontend/src/stores/main.ts

@@ -6,7 +6,6 @@ import { getLocalToken, removeLocalToken, saveLocalToken } from "@/utils";
 import type { AppNotification } from '@/interfaces';
 import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState, Video, VideoCreate, ArticleCreate, Image, ImageDownload } from '@/interfaces';
 import i18n from '@/plugins/i18n'
-import { GoogleLogin } from "vue3-google-login";
 
 const defaultState: MainState = {
   isLoggedIn: null,

+ 10 - 0
frontend/src/stores/store.ts

@@ -0,0 +1,10 @@
+import { createPinia } from "pinia";
+import type { App } from "vue";
+
+const store = createPinia();
+
+export function setupStore(app: App<Element>) {
+  app.use(store);
+}
+
+export { store };

+ 16 - 0
frontend/src/stores/type.ts

@@ -0,0 +1,16 @@
+export type SocketStore = {
+    // 連接狀態
+    isConnected: boolean;
+    // 內容
+    message: string;
+    // 重新連接錯誤
+    reconnectError: boolean;
+    // 心跳消息發送時間
+    heartBeatInterval: number;
+    // 心跳定時器
+    heartBeatTimer: number;
+  };
+  
+  export type socketType = {
+    $connect: () => void;
+  };

+ 69 - 0
frontend/src/stores/useSocketStore.ts

@@ -0,0 +1,69 @@
+import { defineStore } from "pinia";
+import { store } from "@/stores/store";
+import main from "../main";
+import type { SocketStore } from "./type";
+
+export const useSocketStore = defineStore({
+  id: "socket",
+  state: (): SocketStore => ({
+    // 連接狀態
+    isConnected: false,
+    // 訊息內容
+    message: "",
+    // 重新連接錯誤
+    reconnectError: false,
+    // 心跳消息發送時間
+    heartBeatInterval: 50000,
+    // 心跳定時器
+    heartBeatTimer: 0
+  }),
+  actions: {
+    // 開啟連接
+    SOCKET_ONOPEN(event: any) {
+      console.log("successful websocket connection");
+      console.log('event',event);
+      main.config.globalProperties.$socket = event.currentTarget;
+      this.isConnected = true;
+      // 連接成功時啟動定時發送心跳訊息,避免被服務器斷開連接
+      this.heartBeatTimer = window.setInterval(() => {
+        const message = "心跳消息";
+        this.isConnected &&
+          main.config.globalProperties.$socket.sendObj({
+            code: 200,
+            msg: message
+          });
+      }, this.heartBeatInterval);
+    },
+    // 關閉連接
+    SOCKET_ONCLOSE(event: any) {
+      this.isConnected = false;
+      // 連接關閉時停掉心跳訊息
+      window.clearInterval(this.heartBeatTimer);
+      this.heartBeatTimer = 0;
+      console.log("連接已斷線:" + new Date());
+      console.log(event);
+    },
+    // 發生錯誤
+    SOCKET_ONERROR(event: any) {
+      console.error(event);
+    },
+    // 收到服務端發送的訊息
+    SOCKET_ONMESSAGE(message: any) {
+      this.message = message;
+      console.log('SOCKET_ONMESSAGE',message);
+    },
+    // 自動重連
+    SOCKET_RECONNECT(count: any) {
+      console.info("重新連接中...", count);
+    },
+    // 重連錯誤
+    SOCKET_RECONNECT_ERROR() {
+      this.reconnectError = true;
+    }
+  }
+});
+
+// Need to be used outside the setup
+export function useSocketStoreWithOut() {
+  return useSocketStore(store);
+}

+ 1 - 1
frontend/src/views/Login.vue

@@ -15,7 +15,7 @@ const callback: CallbackTypes.CredentialCallback = (response: any) => {
   console.log("Handle the response", response);
   const userData: any = decodeCredential(response.credential);
   console.log("Handle the userData", userData);
-  mainStore.googleLogin(userData.email, "google");
+  mainStore.googleLogin(userData.email);
 };
 
 // const data = ref();