update 消息推送增加 消息类型 消息来源 前端跳转路径等扩展参数
This commit is contained in:
@@ -8,8 +8,9 @@
|
|||||||
<template v-if="newsList.length > 0">
|
<template v-if="newsList.length > 0">
|
||||||
<div v-for="(v, k) in newsList" :key="k" class="content-box-item" @click="onNewsClick(k)">
|
<div v-for="(v, k) in newsList" :key="k" class="content-box-item" @click="onNewsClick(k)">
|
||||||
<div class="item-conten">
|
<div class="item-conten">
|
||||||
|
<div class="content-box-title">{{ v.title || '消息' }}</div>
|
||||||
<div>{{ v.message }}</div>
|
<div>{{ v.message }}</div>
|
||||||
<div class="content-box-msg"></div>
|
<div v-if="v.content" class="content-box-msg">{{ v.content }}</div>
|
||||||
<div class="content-box-time">{{ v.time }}</div>
|
<div class="content-box-time">{{ v.time }}</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 已读/未读 -->
|
<!-- 已读/未读 -->
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts" name="layoutBreadcrumbUserNews">
|
<script setup lang="ts" name="layoutBreadcrumbUserNews">
|
||||||
import { useNoticeStore } from '@/store/modules/notice';
|
import { useNoticeStore } from '@/store/modules/notice';
|
||||||
|
import router from '@/router';
|
||||||
|
|
||||||
const noticeStore = useNoticeStore();
|
const noticeStore = useNoticeStore();
|
||||||
const { readAll } = useNoticeStore();
|
const { readAll } = useNoticeStore();
|
||||||
@@ -46,10 +48,17 @@ const getTableData = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//点击消息,写入已读
|
//点击消息,写入已读
|
||||||
const onNewsClick = (item: any) => {
|
const onNewsClick = async (item: any) => {
|
||||||
newsList.value[item].read = true;
|
newsList.value[item].read = true;
|
||||||
//并且写入pinia
|
//并且写入pinia
|
||||||
noticeStore.state.notices = newsList.value;
|
noticeStore.state.notices = newsList.value;
|
||||||
|
const current = newsList.value[item];
|
||||||
|
if (current?.path) {
|
||||||
|
await router.push({
|
||||||
|
path: current.path,
|
||||||
|
query: current.query || undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 前往通知中心点击
|
// 前往通知中心点击
|
||||||
@@ -123,8 +132,12 @@ onMounted(() => {
|
|||||||
|
|
||||||
.content-box-msg {
|
.content-box-msg {
|
||||||
color: var(--el-text-color-secondary);
|
color: var(--el-text-color-secondary);
|
||||||
margin-top: 5px;
|
margin: 2px 0 0;
|
||||||
margin-bottom: 5px;
|
display: -webkit-box;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-box-time {
|
.content-box-time {
|
||||||
@@ -141,6 +154,12 @@ onMounted(() => {
|
|||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-box-title {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--app-accent-strong);
|
||||||
|
}
|
||||||
|
|
||||||
.read {
|
.read {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
interface NoticeItem {
|
export interface NoticeItem {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
type?: string;
|
||||||
|
source?: string;
|
||||||
read: boolean;
|
read: boolean;
|
||||||
message: any;
|
message: string;
|
||||||
|
content?: string;
|
||||||
|
data?: Record<string, any> | null;
|
||||||
|
path?: string;
|
||||||
|
query?: Record<string, any> | null;
|
||||||
time: string;
|
time: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
export const PUSH_MESSAGE_TYPE = {
|
||||||
|
MESSAGE: 'message',
|
||||||
|
NOTICE: 'notice',
|
||||||
|
LLM: 'llm',
|
||||||
|
CUSTOM: 'custom'
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export interface PushMessagePayload {
|
||||||
|
type?: string;
|
||||||
|
source?: string;
|
||||||
|
message?: string;
|
||||||
|
data?: Record<string, any> | null;
|
||||||
|
path?: string;
|
||||||
|
query?: Record<string, any> | null;
|
||||||
|
timestamp?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MESSAGE_CENTER_TYPES = new Set<string>([PUSH_MESSAGE_TYPE.MESSAGE, PUSH_MESSAGE_TYPE.NOTICE]);
|
||||||
|
|
||||||
|
export const parsePushMessage = (raw: string): PushMessagePayload => {
|
||||||
|
try {
|
||||||
|
const payload = JSON.parse(raw) as PushMessagePayload;
|
||||||
|
return {
|
||||||
|
type: payload.type ?? PUSH_MESSAGE_TYPE.MESSAGE,
|
||||||
|
source: payload.source ?? 'backend',
|
||||||
|
message: payload.message ?? '',
|
||||||
|
data: payload.data ?? null,
|
||||||
|
path: payload.path,
|
||||||
|
query: payload.query ?? null,
|
||||||
|
timestamp: payload.timestamp ?? Date.now()
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
return {
|
||||||
|
type: PUSH_MESSAGE_TYPE.MESSAGE,
|
||||||
|
source: 'backend',
|
||||||
|
message: raw,
|
||||||
|
data: null,
|
||||||
|
path: undefined,
|
||||||
|
query: null,
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const shouldAppendNotice = (payload: PushMessagePayload) => {
|
||||||
|
return MESSAGE_CENTER_TYPES.has(payload.type ?? PUSH_MESSAGE_TYPE.MESSAGE);
|
||||||
|
};
|
||||||
+22
-11
@@ -1,6 +1,7 @@
|
|||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { ElNotification } from 'element-plus';
|
import { ElNotification } from 'element-plus';
|
||||||
import { useNoticeStore } from '@/store/modules/notice';
|
import { useNoticeStore } from '@/store/modules/notice';
|
||||||
|
import { parsePushMessage, PUSH_MESSAGE_TYPE, shouldAppendNotice } from '@/utils/push-message';
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
export const initSSE = (url: any) => {
|
export const initSSE = (url: any) => {
|
||||||
@@ -26,17 +27,27 @@ export const initSSE = (url: any) => {
|
|||||||
|
|
||||||
watch(data, () => {
|
watch(data, () => {
|
||||||
if (!data.value) return;
|
if (!data.value) return;
|
||||||
useNoticeStore().addNotice({
|
const payload = parsePushMessage(data.value);
|
||||||
message: data.value,
|
if (shouldAppendNotice(payload)) {
|
||||||
read: false,
|
useNoticeStore().addNotice({
|
||||||
time: new Date().toLocaleString()
|
title: payload.type === PUSH_MESSAGE_TYPE.NOTICE ? '通知公告' : '系统消息',
|
||||||
});
|
type: payload.type,
|
||||||
ElNotification({
|
source: payload.source,
|
||||||
title: '消息',
|
message: payload.message ?? '',
|
||||||
message: data.value,
|
content: payload.data?.noticeContent,
|
||||||
type: 'success',
|
data: payload.data,
|
||||||
duration: 3000
|
path: payload.path,
|
||||||
});
|
query: payload.query,
|
||||||
|
read: false,
|
||||||
|
time: new Date(payload.timestamp ?? Date.now()).toLocaleString()
|
||||||
|
});
|
||||||
|
ElNotification({
|
||||||
|
title: payload.type === PUSH_MESSAGE_TYPE.NOTICE ? '通知公告' : '消息',
|
||||||
|
message: payload.message ?? '',
|
||||||
|
type: 'success',
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
}
|
||||||
data.value = null;
|
data.value = null;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
+23
-12
@@ -1,6 +1,7 @@
|
|||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { ElNotification } from 'element-plus';
|
import { ElNotification } from 'element-plus';
|
||||||
import { useNoticeStore } from '@/store/modules/notice';
|
import { useNoticeStore } from '@/store/modules/notice';
|
||||||
|
import { parsePushMessage, PUSH_MESSAGE_TYPE, shouldAppendNotice } from '@/utils/push-message';
|
||||||
|
|
||||||
// 初始化socket
|
// 初始化socket
|
||||||
export const initWebSocket = (url: any) => {
|
export const initWebSocket = (url: any) => {
|
||||||
@@ -32,20 +33,30 @@ export const initWebSocket = (url: any) => {
|
|||||||
console.log('websocket已经断开');
|
console.log('websocket已经断开');
|
||||||
},
|
},
|
||||||
onMessage: (_, e) => {
|
onMessage: (_, e) => {
|
||||||
if (e.data.indexOf('ping') > 0) {
|
if (typeof e.data === 'string' && e.data.includes('ping')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
useNoticeStore().addNotice({
|
const payload = parsePushMessage(String(e.data));
|
||||||
message: e.data,
|
if (shouldAppendNotice(payload)) {
|
||||||
read: false,
|
useNoticeStore().addNotice({
|
||||||
time: new Date().toLocaleString()
|
title: payload.type === PUSH_MESSAGE_TYPE.NOTICE ? '通知公告' : '系统消息',
|
||||||
});
|
type: payload.type,
|
||||||
ElNotification({
|
source: payload.source,
|
||||||
title: '消息',
|
message: payload.message ?? '',
|
||||||
message: e.data,
|
content: payload.data?.noticeContent,
|
||||||
type: 'success',
|
data: payload.data,
|
||||||
duration: 3000
|
path: payload.path,
|
||||||
});
|
query: payload.query,
|
||||||
|
read: false,
|
||||||
|
time: new Date(payload.timestamp ?? Date.now()).toLocaleString()
|
||||||
|
});
|
||||||
|
ElNotification({
|
||||||
|
title: payload.type === PUSH_MESSAGE_TYPE.NOTICE ? '通知公告' : '消息',
|
||||||
|
message: payload.message ?? '',
|
||||||
|
type: 'success',
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user