Files
geg-gas-web/src/layouts/default/header/components/notify/index.vue

504 lines
21 KiB
Vue
Raw Normal View History

<template>
2025-10-21 18:04:02 +08:00
<div :class="prefixCls">
<Popover title="" trigger="click" :overlayClassName="`${prefixCls}__overlay`">
<Badge :count="count" dot :numberStyle="numberStyle">
<Icon icon="ion:notifcations" size="22" />
</Badge>
<template #content>
<Tabs>
<template v-for="item in listData" :key="item.key">
<TabPane>
<template #tab>
{{ item.name }}
<span v-if="item.unreadNum !== 0">({{ item.unreadNum }})</span>
</template>
2025-10-21 18:04:02 +08:00
<div v-if="item.key === '4'" class="min-h-88">
<div>
<div class="list-item">
<span class="header-title">{{ t('流程审批') }}</span>
<router-link
class="opr"
:to="{
path: '/task/processtasks',
query: {}
}"
>
{{ t('查看更多') }}
</router-link>
</div>
<div v-if="item.list.length > 0">
<div class="readed-mark" v-for="it in item.list" :key="it.id">
<div class="list-data-item" :class="it.read ? 'readed' : ''" @click="ApprovalHandle(it, item.key, 1)">
<span class="list-item-title">{{ it.title }}</span>
<span class="list-item-time">{{ it.timeFormat }}</span>
</div>
</div>
</div>
<a-empty :image="simpleImage" v-else />
</div>
<div>
<div class="list-item">
<span class="header-title">{{ t('流程传阅') }}</span>
<router-link
class="opr"
:to="{
path: '/task/processtasks',
query: { name: 'MyCirculation' }
}"
>
{{ t('查看更多') }}
</router-link>
</div>
<div v-if="item.read!.length>0">
<div class="list-item readed-mark" v-for="it in item.read" :key="it.id">
<div class="list-data-item" :class="it.read ? 'readed' : ''" @click="ApprovalHandle(it, item.key, 2)">
<span class="list-item-title">{{ it.title }}</span>
<span class="list-item-time">{{ it.timeFormat }}</span>
</div>
</div>
</div>
<a-empty :image="simpleImage" v-else />
</div>
<div class="notice-footer">
<span @click="setReadAll(item.key)">{{ t('全部设置已读') }}</span>
</div>
</div>
<!--系统通知消息-->
<div v-else-if="item.key === '5'" class="h-88">
<div v-if="item.list.length > 0" class="h-82">
<div
class="list-item readed-mark"
v-for="it in item.list"
:key="it.id"
:class="it.isRead === 1 ? 'readed' : ''"
@click="
() => {
it.isRead = 1;
setReadSingle(it.id, item.key);
goToRouter(it);
}
"
>
<span class="list-item-title" style="width: 220px">
<a-tooltip>
<template #title>{{ it.title }}</template>
{{ it.title }}
</a-tooltip>
</span>
<span class="list-item-time">{{ it.createDate }}</span>
</div>
</div>
<a-empty :image="simpleImage" v-else />
</div>
<div v-else class="h-88">
<div v-if="item.list.length > 0" class="h-82">
<div
class="list-item readed-mark"
v-for="it in item.list"
:key="it.id"
:class="it.read ? 'readed' : ''"
@click="
() => {
it.read = 1;
setReadSingle(it.id, item.key);
}
"
>
<span class="list-item-title">
<a-tooltip>
<template #title>{{ it.title }}</template>
{{ it.title }}
</a-tooltip>
</span>
<span class="list-item-time">{{ it.timeFormat }}</span>
</div>
<div class="notice-footer"
><span @click="setReadAll(item.key)">{{ t('全部设置已读') }}</span
><span>{{ t('查看更多') }} </span></div
>
</div>
<a-empty :image="simpleImage" v-else />
</div>
</TabPane>
</template>
</Tabs>
<ApprovalProcess
v-if="Approval.visible"
:taskId="Approval.taskId || ''"
:processId="Approval.processId || ''"
:schemaId="Approval.schemaId || ''"
:visible="Approval.visible"
@close="
() => {
Approval.visible = false;
}
"
2025-10-21 18:04:02 +08:00
/>
<LookProcess
v-if="LookData.visible"
:taskId="LookData.taskId || ''"
:processId="LookData.processId || ''"
:visible="LookData.visible"
@close="
() => {
LookData.visible = false;
}
"
/>
</template>
</Popover>
</div>
</template>
<script lang="ts">
2025-10-21 18:04:02 +08:00
import { computed, defineComponent, ref, onUnmounted } from 'vue';
import { Popover, Tabs, Badge } from 'ant-design-vue';
import { Icon } from '/@/components/Icon';
import { tabListData } from './data';
2025-10-21 18:04:02 +08:00
import { useDesign } from '/@/hooks/web/useDesign';
import { downloadByUrl } from '/@/utils/file/download';
2025-10-21 18:04:02 +08:00
import { getOaMessage, getOaNews, setOaRead, setSingleRead, setWorkReadAll, getScheduleMsg, setScheduleRead, setScheduleReadAll } from '/@/api/system/login';
import { queryLoginUserNotices, setSystemNoticeRead } from '/@/api/system/systemNotice/index';
import { getInfoByDownloadUrl } from '/@/api/system/file';
import { Empty } from 'ant-design-vue';
2025-10-21 18:04:02 +08:00
import ApprovalProcess from '/@/views/workflow/task/components/ApprovalProcess.vue';
import LookProcess from '/@/views/workflow/task/components/LookProcess.vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { useRouter } from 'vue-router';
const { t } = useI18n();
export default defineComponent({
components: {
Popover,
Tabs,
TabPane: Tabs.TabPane,
Badge,
Icon,
ApprovalProcess,
LookProcess
},
setup() {
const router = useRouter();
const Approval = ref<{
taskId?: string;
processId?: string;
schemaId?: string;
visible: boolean;
}>({
visible: false
2025-10-13 11:53:54 +08:00
});
2025-10-21 18:04:02 +08:00
const LookData = ref<{
taskId?: string;
processId?: string;
visible: boolean;
}>({
visible: false
2025-10-13 11:53:54 +08:00
});
2025-10-21 18:04:02 +08:00
const { prefixCls } = useDesign('header-notify');
let times: any = ref();
const listData = ref(tabListData);
const simpleImage = ref(Empty.PRESENTED_IMAGE_SIMPLE);
getDatas();
2025-12-02 10:39:26 +08:00
//停止循环获取通知
// times.value = setInterval(() => {
// getDatas();
// }, 10000);
2025-10-21 18:04:02 +08:00
async function getDatas() {
listData.value.forEach((o) => {
o.list = [];
o.unreadNum = 0;
if (o.read) o.read = [];
2025-10-13 11:53:54 +08:00
});
2025-10-21 18:04:02 +08:00
try {
if (import.meta.env.VITE_GLOB_DISABLE_NEWS !== 'true') {
let res = await getOaNews(1);
res.list.forEach((o) => {
if (!o.readId) listData.value[0].unreadNum += 1;
listData.value[0].list.push({
id: o.id,
avatar: '',
title: o.briefHead,
description: '',
datetime: o.releaseTime,
color: '',
type: '3',
read: o.isRead
});
});
let res1 = await getOaNews(2);
res1.list.forEach((o) => {
if (!o.readId) listData.value[1].unreadNum += 1;
listData.value[1].list.push({
id: o.id,
avatar: '',
title: o.briefHead,
description: '',
datetime: o.releaseTime,
color: '',
type: '3',
read: o.isRead
});
});
let res2 = await getOaMessage();
res2.forEach((o) => {
if (o.messageType === 0) {
if (!o.isRead) listData.value[2].unreadNum += 1;
listData.value[2].list.push({
id: o.id,
avatar: '',
title: o.messageContent,
description: '',
datetime: o.sendTime,
timeFormat: o.timeFormat,
color: '',
type: '3',
read: o.isRead
});
} else if (o.messageType == 1) {
if (!o.isRead) listData.value[3].unreadNum += 1;
listData.value[3].list.push({
id: o.id,
avatar: '',
title: o.messageContent,
description: '',
datetime: o.sendTime,
timeFormat: o.timeFormat,
color: '',
type: '3',
taskId: o.objectId,
processId: o.processId,
schemaId: o.schemaId,
read: o.isRead
});
} else if (o.messageType == 2) {
if (!o.isRead) listData.value[3].unreadNum += 1;
listData.value[3].read?.push({
id: o.id,
avatar: '',
title: o.messageContent,
description: '',
datetime: o.sendTime,
read: o.isRead,
timeFormat: o.timeFormat,
color: '',
type: '3',
taskId: o.objectId,
processId: o.processId
});
}
});
2025-10-13 11:53:54 +08:00
2025-10-21 18:04:02 +08:00
//系统消息
let res4 = import.meta.env.VITE_DISABLE_NOTE === 'true' ? { list: [] } : await queryLoginUserNotices({ limit: 1, size: 10 });
listData.value[4].list = res4.list;
listData.value[4].unreadNum = res4.list.filter((item) => item.isRead == 0).length;
}
2025-10-21 18:04:02 +08:00
let res3 = await getScheduleMsg();
res3.list.forEach((item) => (item.read = item.isRead));
listData.value[2].unreadNum = res3.list.filter((x) => !x.isRead).length;
listData.value[2].list.push(...res3.list);
console.log('message', listData.value);
} catch (error) {
console.error('message error', error);
clearInterval(times.value);
}
}
2025-10-21 18:04:02 +08:00
const count = computed(() => {
let count = 0;
for (let i = 0; i < listData.value.length; i++) {
count += listData.value[i].unreadNum;
}
return count;
});
2025-10-21 18:04:02 +08:00
async function setReadAll(type) {
if (type == 1 || type == 2) {
let ids: string[] = [];
2025-10-21 18:04:02 +08:00
listData.value[type - 1].list.forEach((o) => {
o.read = 1;
ids.push(o.id);
});
await setOaRead(ids);
} else if (type == 3) {
await setScheduleReadAll();
listData.value[type - 1].list.forEach((o) => {
o.read = 1;
});
} else if (type == 4) {
listData.value[type - 1].list.forEach((o) => {
o.read = 1;
});
await setWorkReadAll();
}
listData.value[type - 1].unreadNum = 0;
}
async function setReadSingle(ids, num) {
if (num == 3) {
await setScheduleRead([ids]);
} else if (num == 4) {
await setSingleRead(ids);
} else if (num == 5) {
await setSystemNoticeRead([ids]);
} else {
await setOaRead([ids]);
}
if (listData.value[num - 1].unreadNum > 0) listData.value[num - 1].unreadNum -= 1;
}
function goToRouter(record) {
if (record.type === '99') {
//异步打包下载
record.paramsJson = record.paramsJson ? JSON.parse(record.paramsJson) : {};
let fileId = record.paramsJson.id || [];
getInfoByDownloadUrl({ id: fileId }).then((res) => {
let fileUrl = res.fileUrlFixed || res.fileUrl;
downloadByUrl({ url: fileUrl, fileName: res.fileName + res.fileType || 'files.zip' });
});
return;
}
router.push(record.path);
}
onUnmounted(() => {
clearInterval(times.value);
});
function ApprovalHandle(it, key, type) {
if (type == 1) {
Approval.value = {
taskId: it.taskId,
processId: it.processId,
schemaId: it.schemaId,
visible: true
};
} else {
LookData.value = {
taskId: it.taskId,
processId: it.processId,
visible: true
};
}
it.read = 1;
setReadSingle(it.id, key);
}
return {
prefixCls,
listData,
count,
setReadAll,
simpleImage,
numberStyle: {
top: '18px',
right: '8px'
},
setReadSingle,
ApprovalHandle,
Approval,
LookData,
t,
goToRouter
};
}
2025-10-21 18:04:02 +08:00
});
</script>
<style lang="less">
2025-10-21 18:04:02 +08:00
@prefix-cls: ~'@{namespace}-header-notify';
2025-10-21 18:04:02 +08:00
.@{prefix-cls} {
padding-top: 2px;
2025-10-21 18:04:02 +08:00
&__overlay {
width: 380px;
}
2025-10-21 18:04:02 +08:00
.ant-tabs-content {
width: 300px;
}
2025-10-21 18:04:02 +08:00
.ant-badge {
font-size: 18px;
2025-10-21 18:04:02 +08:00
.ant-badge-multiple-words {
padding: 0 4px;
}
2025-10-21 18:04:02 +08:00
svg {
width: 0.9em;
}
}
}
</style>
<style scoped lang="less">
2025-10-21 18:04:02 +08:00
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #f2f2f2;
font-weight: 400;
font-size: 12px;
height: 36px;
cursor: pointer;
2025-10-21 18:04:02 +08:00
.header-title {
font-weight: 700;
font-size: 14px;
}
2025-10-21 18:04:02 +08:00
.opr {
color: #02a7f0;
cursor: pointer;
font-size: 12px;
}
2025-10-21 18:04:02 +08:00
&.readed {
color: gray;
}
}
2025-10-21 18:04:02 +08:00
.list-data-item {
display: flex;
height: 36px;
cursor: pointer;
border-bottom: 1px solid #f2f2f2;
justify-content: space-between;
align-items: center;
2025-10-21 18:04:02 +08:00
&.readed {
color: gray;
}
}
2025-10-21 18:04:02 +08:00
.list-item-title {
width: 280px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
2025-10-21 18:04:02 +08:00
.list-item-time {
text-align: right;
}
2025-10-21 18:04:02 +08:00
.readed-mark {
color: #02a7f0;
}
2025-10-21 18:04:02 +08:00
.notice-footer {
display: flex;
justify-content: space-around;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 40px;
line-height: 40px;
border-bottom: 1px solid #f2f2f2;
font-size: 12px;
color: #02a7f0;
cursor: pointer;
}
</style>