feat: 使用mitt库
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { eventBus, AppEvents } from '@/utils'
|
import { eventBus, AppEvents } from '@/utils'
|
||||||
import type { RequestErrorEvent } from './types'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册请求错误 UI 展示
|
* 注册请求错误 UI 展示
|
||||||
@@ -8,7 +7,6 @@ import type { RequestErrorEvent } from './types'
|
|||||||
* 订阅应用级 REQUEST_ERROR 事件,统一展示错误提示,
|
* 订阅应用级 REQUEST_ERROR 事件,统一展示错误提示,
|
||||||
* 实现网络模块与 UI 的解耦。
|
* 实现网络模块与 UI 的解耦。
|
||||||
*/
|
*/
|
||||||
eventBus.on(AppEvents.REQUEST_ERROR, (payload: unknown) => {
|
eventBus.on(AppEvents.REQUEST_ERROR, (payload) => {
|
||||||
const { message: errorMessage } = payload as RequestErrorEvent
|
ElMessage.error(payload.message)
|
||||||
ElMessage.error(errorMessage)
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios, { type AxiosInstance, type CreateAxiosDefaults } from 'axios'
|
import axios, { type AxiosInstance, type CreateAxiosDefaults } from 'axios'
|
||||||
import { useAccountStore } from '@/stores'
|
import { useAccountStore } from '@/stores'
|
||||||
import { eventBus, AppEvents } from '@/utils'
|
import { eventBus, AppEvents } from '@/utils'
|
||||||
import type { ApiResponse, InternalRequestConfig, RequestErrorEvent } from './types'
|
import type { ApiResponse, InternalRequestConfig } from './types'
|
||||||
import { createRefreshTokenInterceptor } from './refreshInterceptor'
|
import { createRefreshTokenInterceptor } from './refreshInterceptor'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,7 +106,7 @@ class RequestClient {
|
|||||||
type: 'business',
|
type: 'business',
|
||||||
code: data.code,
|
code: data.code,
|
||||||
message: data.message || '请求失败'
|
message: data.message || '请求失败'
|
||||||
} satisfies RequestErrorEvent)
|
})
|
||||||
return Promise.reject(data)
|
return Promise.reject(data)
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
@@ -121,7 +121,7 @@ class RequestClient {
|
|||||||
message: error.response
|
message: error.response
|
||||||
? `请求错误 (${error.response.status})`
|
? `请求错误 (${error.response.status})`
|
||||||
: '网络异常,请检查网络连接'
|
: '网络异常,请检查网络连接'
|
||||||
} satisfies RequestErrorEvent)
|
})
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ export function useSse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vite 代理: /api/sse/subscribe → 后端 /sse/subscribe
|
// Vite 代理: /api/sse/subscribe → 后端 /sse/subscribe
|
||||||
const url = `/api/sse/subscribe?token=${encodeURIComponent(token)}`
|
// 鉴权走 Cookie(登录后 Sa-Token 写入同名 Cookie,EventSource 同域请求自动携带)
|
||||||
|
const url = `/api/sse/subscribe`
|
||||||
es = new EventSource(url)
|
es = new EventSource(url)
|
||||||
|
|
||||||
es.onopen = () => {
|
es.onopen = () => {
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
/** 事件处理器类型 */
|
import mitt from 'mitt'
|
||||||
type EventHandler = (...args: unknown[]) => void
|
|
||||||
|
/** 应用级事件类型定义 */
|
||||||
|
type AppEventsMap = {
|
||||||
|
/** 401 未授权 */
|
||||||
|
'app:unauthorized': void
|
||||||
|
/** 请求错误(业务错误 / HTTP 错误 / 网络错误) */
|
||||||
|
'app:request:error': {
|
||||||
|
type: 'business' | 'http' | 'network'
|
||||||
|
code?: number
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 应用级事件常量 */
|
/** 应用级事件常量 */
|
||||||
export const AppEvents = {
|
export const AppEvents = {
|
||||||
/** 401 未授权 */
|
|
||||||
UNAUTHORIZED: 'app:unauthorized',
|
UNAUTHORIZED: 'app:unauthorized',
|
||||||
/** 请求错误(业务错误 / HTTP 错误 / 网络错误) */
|
|
||||||
REQUEST_ERROR: 'app:request:error'
|
REQUEST_ERROR: 'app:request:error'
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发布订阅事件总线
|
* 应用级事件总线(基于 mitt)
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
@@ -23,69 +32,4 @@ export const AppEvents = {
|
|||||||
* eventBus.emit(AppEvents.UNAUTHORIZED)
|
* eventBus.emit(AppEvents.UNAUTHORIZED)
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class EventBus {
|
export const eventBus = mitt<AppEventsMap>()
|
||||||
/** 事件名 → 处理器集合 */
|
|
||||||
private handlers = new Map<string, Set<EventHandler>>()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册事件处理器
|
|
||||||
* @param event - 事件名
|
|
||||||
* @param handler - 处理器函数
|
|
||||||
*/
|
|
||||||
on(event: string, handler: EventHandler): void {
|
|
||||||
if (!this.handlers.has(event)) {
|
|
||||||
this.handlers.set(event, new Set())
|
|
||||||
}
|
|
||||||
this.handlers.get(event)!.add(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册一次性事件处理器(触发后自动取消注册)
|
|
||||||
* @param event - 事件名
|
|
||||||
* @param handler - 处理器函数
|
|
||||||
*/
|
|
||||||
once(event: string, handler: EventHandler): void {
|
|
||||||
const wrapper: EventHandler = (...args: unknown[]) => {
|
|
||||||
handler(...args)
|
|
||||||
this.off(event, wrapper)
|
|
||||||
}
|
|
||||||
this.on(event, wrapper)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消注册事件处理器
|
|
||||||
* @param event - 事件名
|
|
||||||
* @param handler - 要取消的处理器函数
|
|
||||||
*/
|
|
||||||
off(event: string, handler: EventHandler): void {
|
|
||||||
this.handlers.get(event)?.delete(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发布事件
|
|
||||||
* @param event - 事件名
|
|
||||||
* @param args - 传递给处理器的参数
|
|
||||||
*/
|
|
||||||
emit(event: string, ...args: unknown[]): void {
|
|
||||||
const handlers = this.handlers.get(event)
|
|
||||||
if (!handlers) return
|
|
||||||
handlers.forEach((handler) => {
|
|
||||||
handler(...args)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除指定事件的所有处理器,或清除所有事件
|
|
||||||
* @param event - 可选,不传则清除全部
|
|
||||||
*/
|
|
||||||
clear(event?: string): void {
|
|
||||||
if (event) {
|
|
||||||
this.handlers.delete(event)
|
|
||||||
} else {
|
|
||||||
this.handlers.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 事件总线单例 */
|
|
||||||
export const eventBus = new EventBus()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user