<template>
|
<div class="top_text flex justify-between px-6 items-center" :class="sidebarIsShow ? 'px-6' : 'pl-[unset] pr-6'">
|
<div class="flex-items-center">
|
<div
|
class="flex-items-center space-x-3 mr-4 pr-4 border border-solid border-r-1 border-l-0 border-y-0 border-gray-300"
|
v-if="!sidebarIsShow"
|
></div>
|
<div v-if="routerMeta.showTitle" class="font-bold flex items-center">
|
<span class="flex-center cursor-pointer" v-if="routerMeta.showBack" @click="goBack">
|
<SvgIcon name="ele-ArrowLeft" />
|
</span>
|
<span class="">
|
{{ routerMeta.title }}
|
</span>
|
</div>
|
</div>
|
<el-dialog
|
v-model="state.isAnnouncementDialog"
|
width="500"
|
:before-close="handleCloseAnnouncement"
|
:modal="false"
|
title="公告内容"
|
:align-center="true"
|
>
|
<div class="set-content">
|
<span class="notice-content">{{ state.announcementContent }}</span>
|
</div>
|
<template #footer>
|
<p class="text-right text-[#555]">
|
<span>{{ state.announcementTime }}</span>
|
</p>
|
</template>
|
</el-dialog>
|
</div>
|
<div class="notice" v-if="!isSharePage">
|
<el-badge :value="`${state.announcementList.length}`">
|
<el-button link size="small" icon="ele-Message" class="set-notice" @click="handleAnnouncementClick">系统公告</el-button>
|
</el-badge>
|
<div class="notice_box notice_box_show" v-show="state.isShowAnnouncement" ref="noticeRef">
|
<div class="notice_box_header">
|
<span>最新公告</span>
|
</div>
|
<div class="notice_box_body">
|
<div class="notice_item" v-for="item in state.announcementList" :key="item.notify_id" @click="announcementContentClick(item)">
|
<div class="flex items-center">
|
<p class="set-circle"></p>
|
<p>{{ item.notify_message }}</p>
|
</div>
|
|
<p class="text-right mr-[19px]">
|
<span>{{ item.notify_time }}</span>
|
</p>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { onClickOutside } from '@vueuse/core';
|
import { computed, onMounted, onUnmounted, reactive, ref, triggerRef } from 'vue';
|
import { systemNotifyList } from '/@/api/ai/chat';
|
import router from '/@/router';
|
import { isSharePage, newChatRoomClick } from '/@/stores/chatRoom';
|
import emitter from '/@/utils/mitt';
|
const props = defineProps(['sidebarIsShow']);
|
let state = reactive({
|
isShowAnnouncement: false,
|
isAnnouncementDialog: false,
|
announcementList: [],
|
announcementContent: '',
|
announcementTime: '',
|
});
|
const noticeRef = ref(null);
|
const getSystemNotify = async () => {
|
const res = await systemNotifyList();
|
res.messages?.forEach((element) => {
|
element.notify_time = element.notify_time.slice(0, 10);
|
});
|
state.announcementList = res.messages?.sort(sortData).slice(0, 5) ?? [];
|
};
|
const routerMeta = computed(() => router.currentRoute.value.meta);
|
|
const setHeaderTitle = (title: string) => {
|
routerMeta.value.title = title;
|
triggerRef(routerMeta);
|
};
|
|
const handleAnnouncementClick = () => {
|
state.isShowAnnouncement = !state.isShowAnnouncement;
|
};
|
|
const goBack = () => {
|
router.back();
|
};
|
//根据指定字段 规则排序 这里是获取时间的时间戳然后比较
|
function sortData(a, b) {
|
return new Date(b.notify_time).getTime() - new Date(a.notify_time).getTime();
|
}
|
//公告内容点击事件
|
const announcementContentClick = (item) => {
|
state.announcementContent = item.notify_message;
|
state.announcementTime = item.notify_time.slice(0, 10);
|
state.isAnnouncementDialog = true;
|
};
|
const handleCloseAnnouncement = () => {
|
state.isAnnouncementDialog = false;
|
};
|
// 区域关闭最新公告
|
onClickOutside(
|
noticeRef,
|
() => {
|
state.isShowAnnouncement = false;
|
},
|
{
|
ignore: ['.el-overlay-dialog'],
|
}
|
);
|
const newChatClick = () => {
|
newChatRoomClick();
|
};
|
onMounted(() => {
|
getSystemNotify();
|
emitter.on('updateHeaderTitle', setHeaderTitle);
|
});
|
|
onUnmounted(() => {
|
emitter.off('updateHeaderTitle', setHeaderTitle);
|
});
|
</script>
|
<style scoped lang="scss">
|
.top_text {
|
width: 100%;
|
height: 42px;
|
background-color: #fff;
|
top: 0;
|
z-index: 1;
|
}
|
|
.notice {
|
position: fixed;
|
top: 18px;
|
right: 30px;
|
z-index: 1;
|
.set-notice {
|
font-size: 12px;
|
font-weight: 400;
|
letter-spacing: 0;
|
line-height: 17.38px;
|
color: #9598b3;
|
z-index: 0;
|
}
|
.notice_box_show {
|
width: 300px !important;
|
height: 470px !important;
|
// height: 100% !important;
|
padding: 0 20px 10px;
|
::-webkit-scrollbar {
|
height: 0;
|
width: 0;
|
color: transparent;
|
}
|
}
|
.notice_box {
|
position: absolute;
|
z-index: 1;
|
top: calc(100% + 20px);
|
right: -10px;
|
width: 0;
|
height: 0;
|
border-radius: 5px;
|
-webkit-box-shadow: 0 0 5px #ddd;
|
box-shadow: 0 0 5px #ddd;
|
background: #fff;
|
display: block;
|
-webkit-transition: all 0.3s;
|
|
-o-transition: all 0.3s;
|
transition: all 0.3s;
|
overflow: hidden;
|
&_header {
|
line-height: 40px;
|
font-size: 14px;
|
height: 40px;
|
color: #0084ff;
|
}
|
&_body {
|
height: calc(100% - 40px);
|
// overflow: auto;
|
.notice_item {
|
cursor: pointer;
|
padding: 10px;
|
width: 272px;
|
border-top: 1px solid #efefef;
|
color: #767a97;
|
position: relative;
|
box-sizing: border-box;
|
line-height: 19px;
|
font-size: 12px;
|
.set-circle {
|
width: 3px;
|
height: 3px;
|
position: absolute;
|
top: 17px;
|
left: 0;
|
transform: scale(0.8) translate(50%, -50%);
|
display: block;
|
padding: 2px;
|
min-width: 3px;
|
min-height: 3px;
|
text-align: center;
|
border-radius: 50%;
|
background: #ff423d;
|
color: #fff;
|
font-size: 12px;
|
}
|
}
|
}
|
}
|
}
|
|
.set-content {
|
padding: 0px 20px;
|
.notice-content {
|
white-space: pre-wrap;
|
font-size: 14px;
|
}
|
}
|
:deep(.el-dialog__footer) {
|
border-top: unset;
|
padding: 10px 20px 20px;
|
box-sizing: border-box;
|
}
|
</style>
|