🎨 organize websocket code structure

This commit is contained in:
landaiqing
2024-09-27 00:42:50 +08:00
parent 4f42d1c5b4
commit 172bf00d93
7 changed files with 80 additions and 38 deletions

View File

@@ -16,5 +16,4 @@ VITE_TITLE_NAME='五味子云相册'
VITE_APP_TOKEN_KEY='Bearer'
# the websocket url
#VITE_WEB_SOCKET_URL='ws://127.0.0.1:80/api/ws/gws'
VITE_WEB_SOCKET_URL='wss://landaiqing.cn/api/ws/gws'
VITE_WEB_SOCKET_URL='ws://127.0.0.1:80/api/ws/gws'

View File

@@ -7,7 +7,7 @@ VITE_APP_BASE_API='/sys'
VITE_APP_TITLE=生产环境
# 网络请求公用地址
VITE_API_BASE_URL='http://127.0.0.1:80'
VITE_API_BASE_URL='https://landaiqing.cn'
VITE_TITLE_NAME='五味子云相册'

View File

@@ -3,6 +3,7 @@ import {useThemeStore} from "@/store/modules/themeStore.ts";
import {langStore} from "@/store/modules/langStore.ts";
import {useClientStore} from "@/store/modules/clientStore.ts";
import {useCommentStore} from "@/store/modules/commentStore.ts";
import {useWebSocketStore} from "@/store/modules/websocketStore.ts";
export default function useStore() {
return {
@@ -11,5 +12,6 @@ export default function useStore() {
lang: langStore(),
client: useClientStore(),
comment: useCommentStore(),
websocket: useWebSocketStore(),
};
}

View File

@@ -0,0 +1,45 @@
// useWebSocketStore.ts
import {defineStore} from 'pinia';
import {onUnmounted, reactive} from 'vue';
import {WebSocketService} from '@/utils/websocket/websocket.ts';
type MessageCallback = (data: any) => void;
type EventCallback = () => void;
export const useWebSocketStore = defineStore('websocket', () => {
const state = reactive({
wsService: null as WebSocketService | null,
});
function initialize(options: { url: string; protocols?: string | string[]; reconnectTimeout?: number }) {
state.wsService = new WebSocketService(options);
state.wsService.open();
onUnmounted(() => {
state.wsService?.close(true);
});
}
function sendMessage(data: any) {
state.wsService?.send(data);
}
function on(event: 'message', callback: MessageCallback) {
state.wsService?.on(event, callback);
}
function onEvent(event: 'open' | 'error' | 'close', callback: EventCallback) {
state.wsService?.on(event, callback);
}
function close() {
state.wsService?.close();
}
return {
initialize,
sendMessage,
on,
onEvent,
close,
};
});

View File

@@ -1,6 +1,4 @@
// src/utils/websocket.ts
import {onUnmounted} from 'vue';
// WebSocketService.ts
interface WebSocketOptions {
url: string;
protocols?: string | string[];
@@ -10,14 +8,13 @@ interface WebSocketOptions {
type MessageCallback = (data: any) => void;
type EventCallback = () => void;
class WebSocketService {
export class WebSocketService {
private ws: WebSocket | null = null;
private callbacks: { [key: string]: (MessageCallback | EventCallback)[] } = {};
private reconnectTimeoutMs: number = 5000; // 默认5秒重连间隔
private heartbeatIntervalMs: number = 5000; // 默认5秒心跳间隔
constructor(private options: WebSocketOptions) {
}
constructor(private options: WebSocketOptions) {}
public open(): void {
this.ws = new WebSocket(this.options.url, this.options.protocols);
@@ -25,6 +22,7 @@ class WebSocketService {
this.ws.addEventListener('message', this.handleMessage);
this.ws.addEventListener('error', this.handleError);
this.ws.addEventListener('close', this.handleClose);
setInterval(() => {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.send("ping");
@@ -55,7 +53,6 @@ class WebSocketService {
}
private handleOpen = (): void => {
console.log('WebSocket连接已建立');
if (this.callbacks.open) {
this.callbacks.open.forEach((cb) => (cb as EventCallback)());
}
@@ -63,7 +60,6 @@ class WebSocketService {
private handleMessage = (event: MessageEvent): void => {
const data = JSON.parse(event.data);
console.log('WebSocket接收到消息:', data);
if (this.callbacks.message) {
this.callbacks.message.forEach((cb) => (cb as MessageCallback)(data));
}
@@ -94,19 +90,3 @@ class WebSocketService {
}
}
}
export default function useWebSocket(options: WebSocketOptions) {
const wsService = new WebSocketService(options);
onUnmounted(() => {
wsService.close(true);
});
return {
open: wsService.open.bind(wsService),
close: wsService.close.bind(wsService),
reconnect: wsService.reconnect.bind(wsService),
on: wsService.on.bind(wsService),
send: wsService.send.bind(wsService)
};
}

View File

@@ -11,17 +11,37 @@ import {useRequest} from "alova/client";
import {getUserPermissions} from "@/api/user";
import useStore from "@/store";
import CommentReply from "@/components/CommentReply/index.vue";
import {h, onMounted} from "vue";
import {notification} from "ant-design-vue";
import {SmileOutlined} from "@ant-design/icons-vue";
const websocket = useStore().websocket;
const userInfo = useStore().user;
const {data, send} = useRequest(getUserPermissions, {
immediate: false
});
const handleClick = () => {
const userInfo = useStore().user;
const userId: string = userInfo.user.uid;
send(userId);
};
const wsOptions = {
url: import.meta.env.VITE_WEB_SOCKET_URL + "?client_id=" + userInfo.user.uid,
};
onMounted(() => {
websocket.initialize(wsOptions);
websocket.on("message", async (data: any) => {
notification.open({
message: '消息来了',
description:
data,
icon: () => h(SmileOutlined, {style: 'color: #108ee9'}),
});
});
});
</script>
<style scoped>

View File

@@ -58,9 +58,9 @@ import BoxDog from "@/components/BoxDog/BoxDog.vue";
import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue";
import {useRouter} from 'vue-router';
import {generateQrCode} from "@/api/oauth/wechat.ts";
import {onMounted, onUnmounted, ref} from "vue";
import {onMounted, ref} from "vue";
import logo from "@/assets/svgs/logo-schisandra.svg";
import useWebSocket from "@/utils/websocket/websocket.ts";
import useStore from "@/store";
import {message} from "ant-design-vue";
import {generateClientId, getUserDevice} from "@/api/oauth";
@@ -71,6 +71,7 @@ const router = useRouter();
const client = useStore().client;
const qrcode = ref<string>('');
const status = ref<string>('loading');
const websocket = useStore().websocket;
/**
* 获取client_id
@@ -119,15 +120,14 @@ const wsOptions = {
url: import.meta.env.VITE_WEB_SOCKET_URL + "?client_id=" + getLocalClientId(),
};
const {open, close, on} = useWebSocket(wsOptions);
/**
* 监听消息
*/
async function handleListenMessage() {
open();
websocket.initialize(wsOptions);
// 注册消息接收处理函数
on('message', async (data: any) => {
websocket.on('message', async (data: any) => {
if (data.code === 200 && data.data) {
const user = useStore().user;
const {access_token, refresh_token, uid, expires_at} = data.data;
@@ -148,10 +148,6 @@ async function handleListenMessage() {
onMounted(async () => {
await getQrCode();
});
onUnmounted(async () => {
close(true);
});
</script>
<style src="./index.scss" scoped>
@import "@/assets/styles/global.scss";