Files
Visualize-electronic-fences/src/layout/components/notice/index.vue
2026-05-25 09:24:30 +08:00

187 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div v-loading="state.loading" class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">通知公告</div>
<div class="head-box-btn" @click="readAll">全部已读</div>
</div>
<div v-loading="state.loading" class="content-box">
<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>{{ v.message }}</div>
<div class="content-box-msg"></div>
<div class="content-box-time">{{ v.time }}</div>
</div>
<!-- 已读/未读 -->
<span v-if="v.read" class="el-tag el-tag--success el-tag--mini read">已读</span>
<span v-else class="el-tag el-tag--danger el-tag--mini read">未读</span>
</div>
</template>
<el-empty v-else :description="'消息为空'"></el-empty>
</div>
<!-- <div v-if="newsList.length > 0" class="foot-box" @click="onGoToGiteeClick">前往gitee</div> -->
</div>
</template>
<script setup lang="ts" name="layoutBreadcrumbUserNews">
import { useNoticeStore } from '@/store/modules/notice';
import { listNotice } from '@/api/system/notice';
const noticeStore = useNoticeStore();
const { readAll } = useNoticeStore();
// 定义变量内容
const state = reactive({
loading: false
});
const newsList = ref([]) as any;
/**
* 过滤5分钟内的消息最多5条
* @param messages 消息列表
* @returns 过滤后的消息列表
*/
const filterMessages = (messages: any[]) => {
const now = new Date().getTime();
const fiveMinutesAgo = now - 5 * 60 * 1000; // 5分钟前的时间戳
// 过滤掉5分钟前的消息
const recentMessages = messages.filter((msg: any) => {
const msgTime = new Date(msg.time).getTime();
return msgTime >= fiveMinutesAgo;
});
// 如果5分钟内的消息超过5条则只保留最新的5条
if (recentMessages.length > 5) {
return recentMessages.slice(0, 5); // 只取前5条最新消息
}
return recentMessages;
};
/**
* 初始化数据
* @returns
*/
const getTableData = async () => {
state.loading = true;
const allNotices = [...noticeStore.state.notices]; // 复制数组避免直接修改原数据
// 过滤消息
const filteredNotices = filterMessages(allNotices);
newsList.value = filteredNotices;
state.loading = false;
};
// 监听通知变化,自动过滤
watch(
() => noticeStore.state.notices,
(newNotices) => {
const filteredNotices = filterMessages([...newNotices]);
newsList.value = filteredNotices;
},
{ deep: true }
);
//点击消息,写入已读
const onNewsClick = (item: any) => {
if (newsList.value[item]) {
newsList.value[item].read = true;
//并且写入pinia
noticeStore.state.notices = noticeStore.state.notices.map((notice: any, index: number) => {
if (index === findOriginalIndex(item)) {
return { ...notice, read: true };
}
return notice;
});
}
};
// 辅助函数:找到原始索引
const findOriginalIndex = (filteredIndex: number) => {
const filteredNotices = filterMessages([...noticeStore.state.notices]);
const currentMessage = filteredNotices[filteredIndex];
// 在原始数组中查找对应消息的索引
return noticeStore.state.notices.findIndex((notice: any) => notice.message === currentMessage.message && notice.time === currentMessage.time);
};
// 前往通知中心点击
const onGoToGiteeClick = () => {
window.open('https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/');
};
onMounted(() => {
nextTick(() => {
getTableData();
console.log('消息列表:', newsList.value);
});
});
</script>
<style lang="scss" scoped>
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;
border-bottom: 1px solid var(--el-border-color-lighter);
box-sizing: border-box;
color: var(--el-text-color-primary);
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: var(--el-color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
height: 300px;
overflow: auto;
font-size: 13px;
.content-box-item {
padding-top: 12px;
display: flex;
&:last-of-type {
padding-bottom: 12px;
}
.content-box-msg {
color: var(--el-text-color-secondary);
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: var(--el-text-color-secondary);
}
.item-conten {
width: 100%;
display: flex;
flex-direction: column;
}
}
}
.foot-box {
height: 35px;
color: var(--el-color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid var(--el-border-color-lighter);
&:hover {
opacity: 1;
}
}
:deep(.el-empty__description p) {
font-size: 13px;
}
}
</style>