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