mirror of
https://gitee.com/bootx/dax-pay-ui
synced 2026-08-14 17:35:36 +08:00
feat 用户全局websocket消息推送
This commit is contained in:
9
src/enums/wsNoticeEnum.ts
Normal file
9
src/enums/wsNoticeEnum.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* 服务端websocket事件通知类型
|
||||
*/
|
||||
export enum WsListenerEnum {
|
||||
// 通知消息发生消息更新 主要是 未读数量更新
|
||||
NOTICE_MESSAGE_UPDATE = 'notice_message_update',
|
||||
// ws测试事件
|
||||
EVENT_TEST_WEBSOCKET = 'event_test_websocket',
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { store } from '/@/store'
|
||||
import { countByReceiveNotRead } from './SiteMessage.api'
|
||||
import { listenerEvent } from '/@/logics/websocket/WebsocketNotice'
|
||||
import { WsListenerEnum } from '/@/enums/wsNoticeEnum'
|
||||
|
||||
export const useSiteMessageStore = defineStore({
|
||||
id: 'SiteMessageStore',
|
||||
@@ -20,3 +22,7 @@ export const useSiteMessageStore = defineStore({
|
||||
export function useSiteMessageStoreWithOut() {
|
||||
return useSiteMessageStore(store)
|
||||
}
|
||||
// 监听 通知消息更新
|
||||
listenerEvent(WsListenerEnum.NOTICE_MESSAGE_UPDATE, (event) => {
|
||||
useSiteMessageStoreWithOut().updateNotReadCount()
|
||||
})
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@visibleChange="visibleChange"
|
||||
:overlayStyle="{ width: '300px' }"
|
||||
>
|
||||
<a-badge :count="notReadMsgCount" dot>
|
||||
<a-badge :count="notReadMsgCount">
|
||||
<BellOutlined />
|
||||
</a-badge>
|
||||
<template #content>
|
||||
@@ -26,7 +26,7 @@
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
<div style="margin-top: 5px; text-align: center">
|
||||
<a-button @click="toSiteMessage" type="dashed" block>查看{{ num }}更多</a-button>
|
||||
<a-button @click="toSiteMessage" type="dashed" block>查看更多</a-button>
|
||||
</div>
|
||||
</a-spin>
|
||||
</template>
|
||||
@@ -94,4 +94,9 @@
|
||||
noticeIconReader.init(message)
|
||||
}
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
<style lang="less">
|
||||
.ant-badge-count {
|
||||
top: 14px;
|
||||
right: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
97
src/logics/websocket/UserGlobalWebSocker.ts
Normal file
97
src/logics/websocket/UserGlobalWebSocker.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 用户全局websocket连接管理
|
||||
*/
|
||||
import { useWebSocket } from '@vueuse/core'
|
||||
import { useUserStoreWithOut } from '/@/store/modules/user'
|
||||
import { EVENT_NOTICE, NOTIFICATION_ERROR, NOTIFICATION_INFO, NOTIFICATION_WARN } from '/@/logics/websocket/WebSockerType'
|
||||
import { publishWsEvent } from '/@/logics/websocket/WebsocketNotice'
|
||||
import { useMessage } from '/@/hooks/web/useMessage'
|
||||
|
||||
const { notification } = useMessage()
|
||||
|
||||
// websocket关闭
|
||||
let wsClose: WebSocket['close']
|
||||
|
||||
export function initWebSocket() {
|
||||
const userStore = useUserStoreWithOut()
|
||||
const token = userStore.getToken
|
||||
const wsUrl = 'ws://localhost:9999'
|
||||
const serverUrl = `${wsUrl}/ws/user?AccessToken=${token}`
|
||||
|
||||
const { close } = useWebSocket(serverUrl, {
|
||||
autoReconnect: false,
|
||||
heartbeat: true,
|
||||
onMessage: onMessage,
|
||||
onConnected: () => {
|
||||
console.log('用户全局WebSocket连接成功')
|
||||
},
|
||||
onDisconnected: (ws, event) => {
|
||||
console.error('用户全局WebSocket断开连接')
|
||||
},
|
||||
})
|
||||
wsClose = close
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件分发
|
||||
*/
|
||||
/**
|
||||
* 处理接收到的消息
|
||||
*/
|
||||
function onMessage(ws: WebSocket, event: MessageEvent) {
|
||||
const res = JSON.parse(event.data)
|
||||
|
||||
if ([NOTIFICATION_INFO, NOTIFICATION_INFO, NOTIFICATION_ERROR].includes(res.type)) {
|
||||
wsNotification(res)
|
||||
} else if ([EVENT_NOTICE].includes(res.type)) {
|
||||
wsEventNotice(res)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件通知 弹框
|
||||
*/
|
||||
function wsNotification(res: WsResult) {
|
||||
if (res.type === NOTIFICATION_INFO) {
|
||||
notification.info({
|
||||
message: '消息通知',
|
||||
description: res.data,
|
||||
})
|
||||
} else if (res.type === NOTIFICATION_WARN) {
|
||||
notification.warn({
|
||||
message: '警告',
|
||||
description: res.data,
|
||||
})
|
||||
} else if (res.type === NOTIFICATION_ERROR) {
|
||||
notification.info({
|
||||
message: '警告',
|
||||
description: res.data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件通知 发送到消息总线
|
||||
*/
|
||||
function wsEventNotice(res: WsResult) {
|
||||
// 发布事件到消息总线
|
||||
publishWsEvent(res.eventCode, res.data)
|
||||
}
|
||||
/**
|
||||
* 关闭
|
||||
*/
|
||||
export function closeWebSocket() {
|
||||
wsClose && wsClose()
|
||||
}
|
||||
|
||||
/**
|
||||
* websocket响应消息类
|
||||
*/
|
||||
export interface WsResult<T = any> {
|
||||
// 类型编码
|
||||
type: number
|
||||
// 数据体
|
||||
data: T
|
||||
// 事件编码
|
||||
eventCode: number
|
||||
}
|
||||
9
src/logics/websocket/WebSockerType.ts
Normal file
9
src/logics/websocket/WebSockerType.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// 普通通知
|
||||
export const NOTIFICATION_INFO = 1001
|
||||
// 警告通知
|
||||
export const NOTIFICATION_WARN = 1002
|
||||
// 错误通知
|
||||
export const NOTIFICATION_ERROR = 1003
|
||||
|
||||
// 事件通知跳转
|
||||
export const EVENT_NOTICE = 9001
|
||||
37
src/logics/websocket/WebsocketNotice.ts
Normal file
37
src/logics/websocket/WebsocketNotice.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import mitt, { EventHandlerList, Handler } from '/@/utils/mitt'
|
||||
import { WsListenerEnum } from '/@/enums/wsNoticeEnum'
|
||||
|
||||
/**
|
||||
* 服务端WebSocket消息推送通知
|
||||
*/
|
||||
|
||||
const emitter = mitt()
|
||||
|
||||
/**
|
||||
* 发布事件
|
||||
*/
|
||||
export function publishWsEvent(key, data) {
|
||||
emitter.emit(key, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件监听
|
||||
*/
|
||||
export function listenerEvent(key: WsListenerEnum, callback: Handler) {
|
||||
emitter.on(key.toString(), callback)
|
||||
}
|
||||
/**
|
||||
* 清除指定key所关联的事件监听
|
||||
*/
|
||||
export function clearEventsByKey(key: WsListenerEnum) {
|
||||
// 一个key可能对应多个事件回调, 清除时
|
||||
const eventHandlerList = emitter.all.get(key.toString()) as EventHandlerList
|
||||
eventHandlerList.forEach((value) => emitter.off(key.toString(), value))
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定事件的监听
|
||||
*/
|
||||
export function clearEvent(key: WsListenerEnum, callback: Handler) {
|
||||
emitter.off(key.toString(), callback)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { useUserStoreWithOut } from '/@/store/modules/user'
|
||||
import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'
|
||||
|
||||
import { RootRoute } from '/@/router/routes'
|
||||
import { initWebSocket } from "/@/logics/websocket/UserGlobalWebSocker";
|
||||
// import { useDictStoreWithOut } from '/@/store/modules/dict'
|
||||
|
||||
const LOGIN_PATH = PageEnum.BASE_LOGIN
|
||||
@@ -97,16 +98,13 @@ export function createPermissionGuard(router: Router) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
//TODO 添加 websocket连接.
|
||||
// 初始化 websocket连接.
|
||||
initWebSocket()
|
||||
|
||||
// 重载菜单
|
||||
console.log('重载菜单')
|
||||
const routes = await permissionStore.buildRoutesAction()
|
||||
|
||||
// 初始化字典 改到项目加载的时候进行初始化
|
||||
// console.log('初始化字典')
|
||||
// await useDictStore.initDict()
|
||||
|
||||
routes.forEach((route) => {
|
||||
router.addRoute(route as unknown as RouteRecordRaw)
|
||||
})
|
||||
|
||||
@@ -20,7 +20,7 @@ export const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH),
|
||||
// 应该添加到路由的初始路由列表。
|
||||
routes: basicRoutes as unknown as RouteRecordRaw[],
|
||||
// 是否应该禁止尾部斜杠。默认为假
|
||||
// 是否应该禁止尾部斜杠。默认为否
|
||||
strict: true,
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
})
|
||||
|
||||
@@ -26,6 +26,7 @@ export const useDictStore = defineStore({
|
||||
name: o.name,
|
||||
} as Dict
|
||||
})
|
||||
console.log('初始化字典')
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
@@ -16,6 +16,7 @@ import { h } from 'vue'
|
||||
import { getFilePreviewUrlPrefix } from '/@/api/common/FileUpload'
|
||||
// @ts-ignore
|
||||
import { getUserInfo } from '/@/api/sys/user'
|
||||
import { closeWebSocket, initWebSocket } from "/@/logics/websocket/UserGlobalWebSocker";
|
||||
|
||||
interface UserState {
|
||||
userInfo: Nullable<UserInfo>
|
||||
@@ -103,7 +104,7 @@ export const useUserStore = defineStore({
|
||||
*/
|
||||
async afterLoginAction(goHome?: boolean) {
|
||||
if (!this.getToken) return null
|
||||
// 获取用户信息
|
||||
// 刷新登陆后用户信息
|
||||
await this.refreshUserInfoAction()
|
||||
const sessionTimeout = this.sessionTimeout
|
||||
// 超时
|
||||
@@ -121,6 +122,8 @@ export const useUserStore = defineStore({
|
||||
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw)
|
||||
permissionStore.setDynamicAddedRoute(true)
|
||||
}
|
||||
// 初始化 websocket连接.
|
||||
initWebSocket()
|
||||
goHome && (await router.replace(PageEnum.BASE_HOME))
|
||||
}
|
||||
},
|
||||
@@ -147,6 +150,7 @@ export const useUserStore = defineStore({
|
||||
this.setToken(undefined)
|
||||
this.setSessionTimeout(false)
|
||||
this.setUserInfo(null)
|
||||
closeWebSocket()
|
||||
goLogin && router.push(PageEnum.BASE_LOGIN)
|
||||
},
|
||||
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
}
|
||||
// 保存
|
||||
function handleOk() {
|
||||
console.log(form.efficientTime)
|
||||
formRef.validate().then(async () => {
|
||||
confirmLoading.value = true
|
||||
await saveOrUpdate(form)
|
||||
|
||||
Reference in New Issue
Block a user