UNPKG

create-iking-admin

Version:

金合技术中台脚手架

221 lines (210 loc) 7.62 kB
/* * @Author : wfl * @LastEditors: qiye * @description : * @updateInfo : * @Date : 2023-07-26 11:10:34 * @LastEditTime: 2024-02-05 11:56:16 */ import { ElNotification } from 'element-plus' import router from '@main/router' import useUserStore from './user' import useNotificationStore from './notification' import useApproveFlowStore from './approveFlow' export const REDIRECT = { // 审批模块跳转 approve: { path: '/approve-center/approve-list', value: { // 进入 我审批的 'back-to-approve': 1, 'submit': 1, 'remind': 1, // 进入 我提交的 'reject': 2, 'pass': 2, 'back-to-initiator': 2, // 进入 抄送我的 'carbon-copy': 3, }, }, } const logStyle = 'font-size: 14px; color: green; ' const logErrStyle = 'text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);color: red;' const useSocketStore = defineStore( // 唯一ID 'socket', () => { ikNotification.checkPermission() // =======================Socket相关================================ // socket实例 let socketApp: WebSocket | null = null // 初始重连间隔为 1 秒 let reconnectInterval = 1000 // 最大重连间隔 const maxReconnectInterval = import.meta.env.VITE_APP_MAX_SOCKET_RECONNECT_TIME // 重连定时器 let timer: number | null = null // 保存消息实例,用于点击后关闭对应实例 const notificationMap = new Map() const userStore = useUserStore() const flowStore = useApproveFlowStore() const notificationStore = useNotificationStore() // 是否连接 const connected = ref(false) // 系统消息 const systemMsgList = ref<any[]>([]) // 消息地址 const SOCKET_URL = `${window.location.href.startsWith('https') ? 'wss' : 'ws'}://${location.host}${import.meta.env.VITE_APP_SOCKET_URL}/server/ws/message` // =======================Socket相关================================ const linkTo = (path: string, info: { tabId?: string, id?: string, target?: '_black' | '_self', uuid?: string }) => { if (path.startsWith('http')) { window.open(path, info.target) } else { flowStore.setSocketInfo({ path, ...info, }) router.push({ path, }) } if (notificationMap.has(info?.uuid)) { notificationMap.get(info?.uuid)?.close() notificationMap.delete(info?.uuid) } } // 创建socket const createSocket = () => { const user = userStore.userInfo if (!user) { return } socketApp = new WebSocket(`${SOCKET_URL}?userId=${user?.id}&token=${ikStore.local.getItem('token')}`) // 连接成功 socketApp.onopen = () => { console.info('%c[Iking Admin] Socket已连接', logStyle) reconnectInterval = 1000 // 重连成功后重置重连间隔 } // 收到消息 socketApp.onmessage = (e: any) => { console.info(`%c[Iking Admin] Socket消息: ${e?.data}`, logStyle) try { const data = JSON.parse(e?.data) const { redirectTo, text, showNotification }: { redirectTo: Array<{ redirectLink: string, redirectName: string }>, text: string, showNotification: boolean } = data const linkArr: any[] = [] // 不需要系统提示的消息 if (!showNotification) { ikMitt.emit('socket-message', e) return } const uuid = buildUUID() if (Array.isArray(redirectTo)) { for (const li of redirectTo) { const isHttpLink = li?.redirectLink.startsWith('http') if (isHttpLink) { linkArr.push(h('a', { class: 'ik-sys-msg-no', onClick: () => linkTo(li?.redirectLink, { uuid, target: '_black' }) }, li?.redirectName || '查看详情')) } else { const splitPath = li?.redirectLink.split('/') const tabId = splitPath?.[2] const id = splitPath?.[3] let redirectObj: any if (li?.redirectLink.startsWith('approve://')) { redirectObj = REDIRECT.approve } linkArr.push(h('a', { class: 'ik-sys-msg-no', onClick: () => redirectObj ? linkTo(redirectObj.path, { tabId: redirectObj.value[tabId], id, uuid, target: '_self' }) : (() => { router.push({ path: li.redirectLink, query: { link: li.redirectLink, }, }) // 跳转后关闭消息框 if (notificationMap.has(uuid)) { notificationMap.get(uuid)?.close() notificationMap.delete(uuid) } })(), }, li?.redirectName || '查看详情')) } } } // 顶部消息图表 - 未读消息数+1 notificationStore.message += 1 const infoHtml = [] for (const i of text?.split('\r\n')) { infoHtml.push(h('p', { class: '' }, i)) } const Notifion = ElNotification({ title: '有新消息', // dangerouslyUseHTMLString: true, type: 'success', duration: 0, message: h('p', { style: '', }, [...infoHtml, ...linkArr], ), }) notificationMap.set(uuid, Notifion) } catch (error) { } try { ikMitt.emit('socket-message', e) const data = JSON.parse(e?.data) systemMsgList.value.push(data) ikNotification.showNotification({ title: '有新消息', message: e?.data, }, () => { }) } catch (error) { } } // 连接错误 socketApp.onerror = () => { console.error('%c[Iking Admin] Socket连接错误', logErrStyle) } // 连接关闭 socketApp.onclose = (e: any) => { console.info('%c[Iking Admin] Socket连接关闭', logStyle, e) timer && clearTimeout(timer) // 根据需要判断是否进行重连 const isLoginPage = location.href.includes('/login') if (!e.wasClean && !isLoginPage) { reconnect() } } return socketApp } // 重连 const reconnect = () => { if (socketApp) { socketApp.close() } // 指数退避重连时间逐步增加 timer = window.setTimeout(() => { if (reconnectInterval < maxReconnectInterval) { reconnectInterval *= 2 } // 重连间隔翻倍 console.info(`%c[Iking Admin] 下次重连时间${reconnectInterval}ms后`, logStyle) createSocket() }, reconnectInterval) } // 页面加载完成后创建socket window.onload = () => { createSocket() } // 发送消息 const emitMessage = (data?: string) => { socketApp?.send(JSON.stringify({ data })) } // 关闭socket const closeScoket = () => { socketApp?.close() } return { connected, systemMsgList, createSocket, closeScoket, emitMessage, } }, ) export default useSocketStore