CEES-manage/src/layouts/default/header/components/notify/index.vue

272 lines
7.6 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 :class="prefixCls">
<Popover v-model:visible="popoverVisible" title="" trigger="click" :overlayClassName="`${prefixCls}__overlay`">
<Badge :count="count" :overflowCount="9" :offset="[-4, 10]" :numberStyle="numberStyle">
<BellOutlined />
</Badge>
<template #content>
<Tabs>
<template v-for="item in listData" :key="item.key">
<TabPane>
<template #tab>
{{ item.name }}
<span v-if="item.list.length !== 0">({{ item.count }})</span>
</template>
<!-- 绑定title-click事件的通知列表中标题是“可点击”的-->
<NoticeList :list="item.list" @title-click="onNoticeClick" />
</TabPane>
</template>
</Tabs>
<a-row class="bottom-buttons">
<a-col :span="count === 0 ? 0 : 12">
<a-button @click="onEmptyNotify" type="dashed" block>清空消息</a-button>
</a-col>
<a-col :span="count === 0 ? 24 : 12">
<a-button @click="popoverVisible = false" type="dashed" block>
<router-link to="/monitor/mynews">查看更多</router-link>
</a-button>
</a-col>
</a-row>
</template>
</Popover>
<DynamicNotice ref="dynamicNoticeRef" v-bind="dynamicNoticeProps" />
<DetailModal @register="registerDetail" />
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref, reactive, onMounted, getCurrentInstance } from 'vue';
import { Popover, Tabs, Badge } from 'ant-design-vue';
import { BellOutlined } from '@ant-design/icons-vue';
import { tabListData } from './data';
import { listCementByUser, editCementSend } from './notify.api';
import NoticeList from './NoticeList.vue';
import DetailModal from '/@/views/monitor/mynews/DetailModal.vue';
import DynamicNotice from '/@/views/monitor/mynews/DynamicNotice.vue';
import { useModal } from '/@/components/Modal';
import { useDesign } from '/@/hooks/web/useDesign';
import { useGlobSetting } from '/@/hooks/setting';
import { useUserStore } from '/@/store/modules/user';
import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
import { readAllMsg } from '/@/views/monitor/mynews/mynews.api';
import { getToken } from '/@/utils/auth';
export default defineComponent({
components: {
Popover,
BellOutlined,
Tabs,
TabPane: Tabs.TabPane,
Badge,
NoticeList,
DetailModal,
DynamicNotice,
},
setup() {
const { prefixCls } = useDesign('header-notify');
const instance: any = getCurrentInstance();
const userStore = useUserStore();
const glob = useGlobSetting();
const dynamicNoticeProps = reactive({ path: '', formData: {} });
const [registerDetail, detailModal] = useModal();
const popoverVisible = ref<boolean>(false);
const listData = ref(tabListData);
listData.value[0].list = [];
listData.value[1].list = [];
listData.value[0].count = 0;
listData.value[1].count = 0;
onMounted(() => {
initWebSocket();
});
const count = computed(() => {
let count = 0;
for (let i = 0; i < listData.value.length; i++) {
count += listData.value[i].count;
}
return count;
});
function mapAnnouncement(item) {
return {
...item,
title: item.titile,
description: item.msgAbstract,
datetime: item.sendTime,
};
}
// 获取系统消息
async function loadData() {
try {
let { anntMsgList, sysMsgList, anntMsgTotal, sysMsgTotal } = await listCementByUser({
pageSize: 5,
});
listData.value[0].list = anntMsgList.map(mapAnnouncement);
listData.value[1].list = sysMsgList.map(mapAnnouncement);
listData.value[0].count = anntMsgTotal;
listData.value[1].count = sysMsgTotal;
} catch (e) {
console.warn('系统消息通知异常:', e);
}
}
loadData();
function onNoticeClick(record) {
try {
editCementSend(record.id);
loadData();
} catch (e) {
console.error(e);
}
if (record.openType === 'component') {
dynamicNoticeProps.path = record.openPage;
dynamicNoticeProps.formData = { id: record.busId };
instance.refs.dynamicNoticeRef?.detail(record.openPage);
} else {
detailModal.openModal(true, {
record,
isUpdate: true,
});
}
popoverVisible.value = false;
}
// 初始化 WebSocket
function initWebSocket() {
let userId = unref(userStore.getUserInfo).id;
let token = getToken();
// WebSocket与普通的请求所用协议有所不同ws等同于httpwss等同于https
let url = glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
connectWebSocket(url);
onWebSocket(onWebSocketMessage);
}
function onWebSocketMessage(data) {
if (data.cmd === 'topic' || data.cmd === 'user') {
//update-begin-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
//后台保存数据太慢 前端延迟刷新消息
setTimeout(() => {
loadData();
}, 1000);
//update-end-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
}
}
// 清空消息
function onEmptyNotify() {
popoverVisible.value = false;
readAllMsg({}, loadData);
}
return {
prefixCls,
listData,
count,
onNoticeClick,
onEmptyNotify,
numberStyle: {},
popoverVisible,
registerDetail,
dynamicNoticeProps,
};
},
});
</script>
<style lang="less">
//noinspection LessUnresolvedVariable
@prefix-cls: ~'@{namespace}-header-notify';
.@{prefix-cls} {
padding-top: 2px;
&__overlay {
max-width: 340px;
.ant-popover-inner-content {
padding: 0;
}
.ant-tabs-bar {
margin-bottom: 12px;
}
.ant-list-item {
padding: 12px 24px;
transition: background-color 300ms;
&:hover {
background-color: #e6f7ff;
}
}
.bottom-buttons {
text-align: center;
border-top: 1px solid #f0f0f0;
height: 42px;
.ant-btn {
border: 0;
height: 100%;
&:first-child {
border-right: 1px solid #f0f0f0;
}
}
}
}
.ant-tabs-content {
width: 300px;
}
.ant-badge {
font-size: 18px;
.ant-badge-count {
@badget-size: 16px;
width: @badget-size;
height: @badget-size;
min-width: @badget-size;
line-height: @badget-size;
padding: 0;
.ant-scroll-number-only > p.ant-scroll-number-only-unit {
font-size: 14px;
height: @badget-size;
}
}
.ant-badge-multiple-words {
padding: 0 0 0 2px;
font-size: 12px;
}
svg {
width: 0.9em;
}
}
}
// 兼容黑暗模式
[data-theme='dark'] .@{prefix-cls} {
&__overlay {
.ant-list-item {
&:hover {
background-color: #111b26;
}
}
.bottom-buttons {
border-top: 1px solid #303030;
.ant-btn {
&:first-child {
border-right: 1px solid #303030;
}
}
}
}
}
</style>