运维管理平台前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

221 lines
6.4 KiB

import { defineStore } from 'pinia';
import { store } from '@/store';
import { useGlobSetting } from '@/hooks/setting';
import { useWebSocket, useEventSource } from '@vueuse/core';
import { getToken } from '@/utils/auth';
import { tabListData, TabItem } from '@/layouts/default/header/components/notify/data';
import { useUserStoreWithOut } from '@/store/modules/user';
import dayjs from 'dayjs';
import { isUrl } from '@/utils/is';
import { useMessage } from '@/hooks/web/useMessage';
import { watch } from 'vue';
interface NotifyState {
listData: TabItem[];
}
const { notification } = useMessage();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function listenWithWebSocket(listData: TabItem[]) {
// 从配置文件获取的为String类型
const { websocketEnable } = useGlobSetting();
if (!websocketEnable) {
console.log('当前未开启websocket.');
return;
}
const { apiUrl, clientId } = useGlobSetting();
let apiUrlStr = String(apiUrl);
/**
* 这里可能有两种情况 兼容dev模式的proxy或者prod模式但是没有用全路径比如http://xxx/xxx
* 1. apiUrl为https://xxx.com/xxx
* 2. apiUrl为/xxx
* 转换后为http链接形式
*/
if (!isUrl(apiUrl)) {
// 协议+域名
apiUrlStr = `${window.location.protocol}//${window.location.host}${apiUrl}`;
}
// 这里是http链接形式
let websocketAddr = `${apiUrlStr}/resource/websocket?clientid=${clientId}&Authorization=Bearer ${getToken()}`;
// http/https处理
if (window.location.protocol.includes('https')) {
websocketAddr = websocketAddr.replace('https://', 'wss://');
} else {
websocketAddr = websocketAddr.replace('http://', 'ws://');
}
// console.log('websocketUrl: ' + websocketAddr);
/**
* 功能太强大了 自动重连 自动发送心跳 连退出登录自动断开都做了
*/
useWebSocket(websocketAddr, {
autoReconnect: {
// 重连最大次数
retries: 3,
// 重连间隔
delay: 1000,
onFailed() {
console.log('websocket重连失败.');
},
},
heartbeat: {
message: JSON.stringify({ type: 'ping' }),
// 发送心跳的间隔
interval: 10000,
// 接收到心跳response的超时时间
pongTimeout: 2000,
},
onConnected() {
console.log('websocket已经连接');
},
onDisconnected() {
console.log('websocket已经断开');
},
onMessage: (_, message) => {
console.log('接收到消息: ' + message.data);
// 需要id不同 否则list foreach会有bug
const id = 'notify-' + listData[0].list.length;
// 获取uid
const uid = useUserStoreWithOut().userInfo?.userId || 0;
// 添加到通知就是第一个index
listData[0].list.unshift({
id,
uid,
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
title: message.data,
description: '',
datetime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
type: '1',
});
notification.info({
message: '收到新消息',
description: message.data,
duration: 3,
});
},
});
}
function listenWithSSE(listData: TabItem[]) {
const { apiUrl, clientId } = useGlobSetting();
const sseAddr = `${apiUrl}/resource/sse?clientid=${clientId}&Authorization=Bearer ${getToken()}`;
const { data } = useEventSource(sseAddr, [], {
autoReconnect: {
retries: 3,
delay: 1000,
onFailed() {
console.log('sse重连失败.');
},
},
});
watch(data, (message) => {
if (!message) return;
console.log('接收到消息: ' + message);
// 需要id不同 否则list foreach会有bug
const id = 'notify-' + listData[0].list.length;
// 获取uid
const uid = useUserStoreWithOut().userInfo?.userId || 0;
// 添加到通知就是第一个index
listData[0].list.unshift({
id,
uid,
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
title: message,
description: '',
datetime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
type: '1',
});
notification.info({
message: '收到新消息',
description: message,
duration: 3,
});
data.value = null;
});
}
export const useNotifyStore = defineStore('notify', {
state: (): NotifyState => ({
listData: tabListData,
}),
getters: {
// 当前用户所有消息的数量
count(state) {
const userStore = useUserStoreWithOut();
const uid = userStore.userInfo?.userId || 0;
let count = 0;
for (let i = 0; i < state.listData.length; i++) {
count += state.listData[i].list.filter((item) => item.uid === uid).length;
}
return count;
},
// 当前用户所有未读消息数量
unreadCount(state) {
const userStore = useUserStoreWithOut();
const uid = userStore.userInfo?.userId || 0;
let count = 0;
for (let i = 0; i < state.listData.length; i++) {
// 这里显示消息数量 使用删除线作为条件
// 只显示当前用户的消息
count += state.listData[i].list.filter(
(item) => item.uid === uid && !item.titleDelete,
).length;
}
return count;
},
// 所有消息 根据uid显示
userMessageList(state): TabItem[] {
const userStore = useUserStoreWithOut();
const uid = userStore.userInfo?.userId || 0;
return state.listData.map((item) => {
return {
...item,
list: item.list.filter((item) => item.uid === uid),
};
});
},
},
actions: {
listeningMessage() {
// listenWithWebSocket(this.listData);
listenWithSSE(this.listData);
},
clearAll() {
const userStore = useUserStoreWithOut();
const uid = userStore.userInfo?.userId || 0;
/**
* 去掉当前用户的所有消息
*/
this.listData = this.listData.map((item) => {
return {
...item,
list: item.list.filter((node) => node.uid !== uid),
};
});
},
readAll() {
const userStore = useUserStoreWithOut();
const uid = userStore.userInfo?.userId || 0;
for (let i = 0; i < this.listData.length; i++) {
this.listData[i].list.forEach((item) => {
if (item.uid === uid) {
item.read = true;
item.titleDelete = true;
}
});
}
},
},
persist: true,
});
export function useNotifyStoreWithOut() {
return useNotifyStore(store);
}