9/20
This commit is contained in:
@@ -1,15 +1,40 @@
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { ElNotification } from 'element-plus';
|
||||
import { useNoticeStore } from '@/store/modules/notice';
|
||||
import { useEventSource } from '@vueuse/core';
|
||||
import { watch } from 'vue';
|
||||
|
||||
// 初始化
|
||||
export const initSSE = (url: any) => {
|
||||
// 全局单例保存SSE实例,防止多次创建
|
||||
let eventSourceInstance: ReturnType<typeof useEventSource> | null = null;
|
||||
let stopWatchError: (() => void) | null = null;
|
||||
let stopWatchData: (() => void) | null = null;
|
||||
|
||||
// 关闭SSE、清理监听
|
||||
export const closeSSE = () => {
|
||||
if (eventSourceInstance) {
|
||||
eventSourceInstance.close();
|
||||
eventSourceInstance = null;
|
||||
}
|
||||
// 销毁watch
|
||||
stopWatchError?.();
|
||||
stopWatchData?.();
|
||||
stopWatchError = null;
|
||||
stopWatchData = null;
|
||||
};
|
||||
|
||||
// 初始化SSE
|
||||
export const initSSE = (url: string) => {
|
||||
if (import.meta.env.VITE_APP_SSE === 'false') {
|
||||
return;
|
||||
}
|
||||
// 关键:新建之前先关闭旧连接!
|
||||
closeSSE();
|
||||
|
||||
url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID;
|
||||
const { data, error } = useEventSource(url, [], {
|
||||
const token = getToken();
|
||||
const clientId = import.meta.env.VITE_APP_CLIENT_ID;
|
||||
const sseUrl = url + '?Authorization=Bearer ' + token + '&clientid=' + clientId;
|
||||
|
||||
eventSourceInstance = useEventSource(sseUrl, [], {
|
||||
autoReconnect: {
|
||||
retries: 5,
|
||||
delay: 5000,
|
||||
@@ -19,14 +44,16 @@ export const initSSE = (url: any) => {
|
||||
}
|
||||
});
|
||||
|
||||
watch(error, () => {
|
||||
const { data, error } = eventSourceInstance;
|
||||
|
||||
stopWatchError = watch(error, () => {
|
||||
console.log('SSE connection error:', error.value);
|
||||
error.value = null;
|
||||
// error.value = null; // 不要手动覆盖,会干扰useEventSource内部状态
|
||||
});
|
||||
|
||||
watch(data, () => {
|
||||
stopWatchData = watch(data, () => {
|
||||
if (!data.value) return;
|
||||
const notice = tryParseJson(data.value);
|
||||
const notice = tryParseJson(data.value as string);
|
||||
if (typeof notice === 'string') {
|
||||
useNoticeStore().addNotice({
|
||||
message: notice,
|
||||
@@ -42,7 +69,6 @@ export const initSSE = (url: any) => {
|
||||
data.value = null;
|
||||
return;
|
||||
} else {
|
||||
// 此处 notice 类型为 Record<string, unknown>,安全取出属性
|
||||
const title = typeof notice.title === 'string' ? notice.title : '消息';
|
||||
const message = typeof notice.message === 'string' ? notice.message : '';
|
||||
const type = typeof notice.type === 'string' ? notice.type : 'info';
|
||||
@@ -75,7 +101,7 @@ function tryParseJson(str: string): string | Record<string, unknown> {
|
||||
if (trimStr === '') return str;
|
||||
try {
|
||||
const parsed = JSON.parse(trimStr);
|
||||
// 只有"纯对象"才返回对象,数组/null/基础值等统一当作字符串处理
|
||||
// 只有纯对象才返回对象,数组/null/基础值等统一当作字符串处理
|
||||
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||
return parsed as Record<string, unknown>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user