wip: 🚧 通知公告临时提交
通知公告临时提交
This commit is contained in:
113
src/api/WebSocketManager.ts
Normal file
113
src/api/WebSocketManager.ts
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import { Client } from "@stomp/stompjs";
|
||||||
|
import { TOKEN_KEY } from "@/enums/CacheEnum";
|
||||||
|
|
||||||
|
const MAX_RETRIES = 3; // 最大重试次数
|
||||||
|
const RETRY_DELAY_MS = 5000; // 重试延迟时间,单位:毫秒
|
||||||
|
const HEARTBEAT_INTERVAL = 30000; // 心跳间隔时间,单位:毫秒
|
||||||
|
|
||||||
|
class WebSocketManager {
|
||||||
|
private clients: Map<string, Client> = new Map();
|
||||||
|
private retryCountMap: Map<string, number> = new Map();
|
||||||
|
private subscriptions: Map<string, ((message: string) => void)[]> = new Map();
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
public getWebSocketClient(
|
||||||
|
url: string,
|
||||||
|
onMessage: (message: string) => void,
|
||||||
|
onError?: (error: any) => void
|
||||||
|
): Client {
|
||||||
|
if (this.clients.has(url)) {
|
||||||
|
// 如果连接已存在,添加新的订阅回调
|
||||||
|
this.subscriptions.get(url)?.push(onMessage);
|
||||||
|
return this.clients.get(url)!;
|
||||||
|
} else {
|
||||||
|
const client = this.createClient(url, onMessage, onError);
|
||||||
|
this.clients.set(url, client);
|
||||||
|
this.subscriptions.set(url, [onMessage]);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 WebSocket 客户端
|
||||||
|
* @param url WebSocket订阅地址
|
||||||
|
* @param onMessage 收到消息时的回调
|
||||||
|
* @param onError 出现错误时的回调
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private createClient(
|
||||||
|
url: string,
|
||||||
|
onMessage: (message: string) => void,
|
||||||
|
onError?: (error: any) => void
|
||||||
|
): Client {
|
||||||
|
const token = localStorage.getItem(TOKEN_KEY) || "";
|
||||||
|
const client = new Client({
|
||||||
|
brokerURL: import.meta.env.VITE_APP_WS_ENDPOINT,
|
||||||
|
connectHeaders: {
|
||||||
|
Authorization: token,
|
||||||
|
},
|
||||||
|
heartbeatIncoming: HEARTBEAT_INTERVAL,
|
||||||
|
heartbeatOutgoing: HEARTBEAT_INTERVAL,
|
||||||
|
onConnect: () => {
|
||||||
|
console.log(`Connected to ${url}`);
|
||||||
|
client.subscribe(url, (message) => {
|
||||||
|
onMessage(message.body);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onStompError: (frame) => {
|
||||||
|
console.error(`Error on ${url}: ${frame.headers["message"]}`);
|
||||||
|
console.error(`Details: ${frame.body}`);
|
||||||
|
if (onError) {
|
||||||
|
onError(frame);
|
||||||
|
}
|
||||||
|
this.handleReconnect(url);
|
||||||
|
},
|
||||||
|
onDisconnect: () => {
|
||||||
|
console.log(`连接失败 ${url}`);
|
||||||
|
this.handleReconnect(url);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
client.activate();
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理重连
|
||||||
|
* @param url WebSocket订阅地址
|
||||||
|
*/
|
||||||
|
private handleReconnect(url: string) {
|
||||||
|
const retryCount = this.retryCountMap.get(url) || 0;
|
||||||
|
|
||||||
|
if (retryCount < MAX_RETRIES) {
|
||||||
|
this.retryCountMap.set(url, retryCount + 1);
|
||||||
|
console.log(`重试连接 ${url} (${retryCount + 1}/${MAX_RETRIES})...`);
|
||||||
|
setTimeout(
|
||||||
|
() =>
|
||||||
|
this.getWebSocketClient(
|
||||||
|
url,
|
||||||
|
() => {},
|
||||||
|
() => {}
|
||||||
|
),
|
||||||
|
RETRY_DELAY_MS
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error(`已经达到最大重试次数 ${url}`);
|
||||||
|
this.retryCountMap.delete(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断开所有 WebSocket 连接
|
||||||
|
*/
|
||||||
|
public disconnectAll() {
|
||||||
|
this.clients.forEach((client, url) => {
|
||||||
|
console.log(`断开连接: ${url}`);
|
||||||
|
client.deactivate();
|
||||||
|
});
|
||||||
|
this.clients.clear();
|
||||||
|
this.retryCountMap.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new WebSocketManager();
|
||||||
@@ -44,10 +44,10 @@
|
|||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Client } from "@stomp/stompjs";
|
|
||||||
import { TOKEN_KEY } from "@/enums/CacheEnum";
|
|
||||||
import { MessageTypeEnum, MessageTypeLabels } from "@/enums/MessageTypeEnum";
|
import { MessageTypeEnum, MessageTypeLabels } from "@/enums/MessageTypeEnum";
|
||||||
import NoticeAPI from "@/api/notice";
|
import NoticeAPI from "@/api/notice";
|
||||||
|
import { getWebSocketClient, WebSocketService } from "@/api/socket";
|
||||||
|
import WebSocketManager from "@/api/WebSocketManager";
|
||||||
|
|
||||||
const activeTab = ref(MessageTypeEnum.MESSAGE);
|
const activeTab = ref(MessageTypeEnum.MESSAGE);
|
||||||
|
|
||||||
@@ -90,49 +90,18 @@ const getFilteredMessages = (type: MessageTypeEnum) => {
|
|||||||
return messages.value.filter((message) => message.type === type);
|
return messages.value.filter((message) => message.type === type);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isConnected = ref(false);
|
|
||||||
const socketEndpoint = ref(import.meta.env.VITE_APP_WS_ENDPOINT);
|
|
||||||
|
|
||||||
let stompClient: Client;
|
|
||||||
|
|
||||||
function connectWebSocket() {
|
function connectWebSocket() {
|
||||||
console.log("连接消息ws的url:" + socketEndpoint.value);
|
WebSocketManager.getWebSocketClient("/user/queue/message", (message) => {
|
||||||
stompClient = new Client({
|
console.log("收到消息:", message);
|
||||||
brokerURL: socketEndpoint.value,
|
|
||||||
connectHeaders: {
|
|
||||||
Authorization: localStorage.getItem(TOKEN_KEY) || "",
|
|
||||||
},
|
|
||||||
debug: (str) => {
|
|
||||||
console.log(str);
|
|
||||||
},
|
|
||||||
onConnect: () => {
|
|
||||||
console.log("消息ws连接成功");
|
|
||||||
isConnected.value = true;
|
|
||||||
|
|
||||||
stompClient.subscribe("/user/queue/message", (res) => {
|
|
||||||
console.log("收到消息:" + res.body);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onStompError: (frame) => {
|
|
||||||
console.error("Broker reported error: " + frame.headers["message"]);
|
|
||||||
console.error("Additional details: " + frame.body);
|
|
||||||
},
|
|
||||||
onDisconnect: () => {
|
|
||||||
isConnected.value = false;
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
stompClient.activate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function listNotice() {
|
function listNotice() {
|
||||||
NoticeAPI.listNotice().then((res) => {
|
NoticeAPI.listNotice().then((res) => {});
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
listNotice();
|
// listNotice();
|
||||||
connectWebSocket();
|
connectWebSocket();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -188,6 +188,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import WebSocketManager from "@/api/WebSocketManager";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Dashboard",
|
name: "Dashboard",
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
@@ -197,11 +199,8 @@ import { Client } from "@stomp/stompjs";
|
|||||||
|
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { NoticeTypeEnum, getNoticeLabel } from "@/enums/NoticeTypeEnum";
|
import { NoticeTypeEnum, getNoticeLabel } from "@/enums/NoticeTypeEnum";
|
||||||
import { TOKEN_KEY } from "@/enums/CacheEnum";
|
|
||||||
import StatsAPI, { VisitStatsVO } from "@/api/log";
|
import StatsAPI, { VisitStatsVO } from "@/api/log";
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const socketEndpoint = ref(import.meta.env.VITE_APP_WS_ENDPOINT);
|
|
||||||
const date: Date = new Date();
|
const date: Date = new Date();
|
||||||
const greetings = computed(() => {
|
const greetings = computed(() => {
|
||||||
const hours = date.getHours();
|
const hours = date.getHours();
|
||||||
@@ -390,31 +389,11 @@ const getNoticeLevelTag = (type: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let stompClient: Client;
|
|
||||||
|
|
||||||
function connectWebSocket() {
|
function connectWebSocket() {
|
||||||
stompClient = new Client({
|
WebSocketManager.getWebSocketClient("/topic/onlineUserCount", (message) => {
|
||||||
brokerURL: socketEndpoint.value,
|
console.log("收到消息:", message);
|
||||||
connectHeaders: {
|
onlineUserCount.value = JSON.parse(message);
|
||||||
Authorization: localStorage.getItem(TOKEN_KEY) || "",
|
|
||||||
},
|
|
||||||
debug: (str) => {
|
|
||||||
console.log(str);
|
|
||||||
},
|
|
||||||
onConnect: () => {
|
|
||||||
console.log("连接成功");
|
|
||||||
stompClient.subscribe("/topic/onlineUserCount", (message) => {
|
|
||||||
onlineUserCount.value = JSON.parse(message.body);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onStompError: (frame) => {
|
|
||||||
console.error("Broker reported error: " + frame.headers["message"]);
|
|
||||||
console.error("Additional details: " + frame.body);
|
|
||||||
},
|
|
||||||
onDisconnect: () => {},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
stompClient.activate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user