428 lines
11 KiB
Vue
428 lines
11 KiB
Vue
<template>
|
|
<div :class="prefixCls">
|
|
<Popover
|
|
v-model:visible="visible"
|
|
title=""
|
|
trigger="click"
|
|
:overlayClassName="`${prefixCls}__overlay`"
|
|
>
|
|
<Badge :count="count" dot :numberStyle="numberStyle">
|
|
<BellOutlined />
|
|
</Badge>
|
|
<template #content>
|
|
<Tabs>
|
|
<template v-for="item in listData" :key="item.key">
|
|
<Tabs.TabPane>
|
|
<template #tab>
|
|
{{ item.name }}
|
|
<span v-if="item.list.length !== 0">({{ item.list.length }})</span>
|
|
</template>
|
|
<!-- 绑定title-click事件的通知列表中标题是“可点击”的-->
|
|
<NoticeList :list="item.list" v-if="item.key === '1'" @title-click="onNoticeClick" />
|
|
<NoticeList :list="item.list" v-else />
|
|
</Tabs.TabPane>
|
|
</template>
|
|
</Tabs>
|
|
</template>
|
|
</Popover>
|
|
<!-- 云查询内容提示 -->
|
|
<div class="cloudquery-notice" v-if="cloudQueryVisible">
|
|
<div class="cloudquery-title">
|
|
<div class="cloudquery-left">
|
|
<img src="/message.png" alt="" />
|
|
<span class="title-box">您有一条云查询结果,请查收</span>
|
|
</div>
|
|
<div class="cloudquery-right">
|
|
<a-button type="primary" @click="handCloudQuery">查看</a-button>
|
|
<div class="line"></div>
|
|
<CloseOutlined @click="closeCloudQuery" style="color: #fff" title="关闭" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- 流程任务详情 -->
|
|
<a-modal
|
|
width="100%"
|
|
wrap-class-name="full-modal"
|
|
v-model:open="auditOpen"
|
|
title="详情"
|
|
:destroyOnClose="true"
|
|
>
|
|
<template #footer> </template>
|
|
<Look ref="posRef" :processId="processId" />
|
|
</a-modal>
|
|
<!-- 消息详情 -->
|
|
<DetailModal @register="registerModal" />
|
|
<!-- 云查询结果 -->
|
|
<a-modal
|
|
v-model:open="open"
|
|
:footer="false"
|
|
@cancel="open = false"
|
|
:width="compare ? '1020px' : '510px'"
|
|
style="top: 20px"
|
|
>
|
|
<div class="modal-content-div">
|
|
<div class="title-text">
|
|
{{ compare ? '国家云查询结果(对比模式)' : '国家云查询结果' }}
|
|
<Icon
|
|
class="split-button"
|
|
style="font-size: 20px"
|
|
icon="bi:layout-split"
|
|
@click="changeCompare"
|
|
/>
|
|
</div>
|
|
<div style="display: flex; width: 100%">
|
|
<div :style="`display: block; width: ${compare ? '50%' : '100%'};`">
|
|
<CloudQueryModal />
|
|
</div>
|
|
<div style="display: block; width: 50%; margin-left: 20px" v-if="compare">
|
|
<CloudQueryModal />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</a-modal>
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import { computed, onMounted, ref, h } from 'vue';
|
|
import { Popover, Tabs, Badge, Button } from 'ant-design-vue';
|
|
import {
|
|
BellOutlined,
|
|
CloseOutlined,
|
|
FileSearchOutlined,
|
|
StarFilled,
|
|
} from '@ant-design/icons-vue';
|
|
import { tabListData } from './data';
|
|
import { useDesign } from '@/hooks/web/useDesign';
|
|
import { useMessage } from '@/hooks/web/useMessage';
|
|
import { getLastList, readMsg, getInfoByContentId } from '@/api/demo/message';
|
|
import { useUserStore } from '@/store/modules/user';
|
|
import { Look } from '@/views/demo/workflow/task/process/page';
|
|
import { useModal } from '@/components/Modal';
|
|
import NoticeList from './NoticeList.vue';
|
|
import { signal } from '@/utils/signalR';
|
|
import { getDetail } from '@/api/sys/WFSchemeInfo';
|
|
import { flowStore } from '@/store/modules/flow';
|
|
import DetailModal from '@/views/demo/message/msg/DetailModal.vue';
|
|
import CloudQueryModal from '@/views/dashboard/test/SearchMenu/CloudQueryModal/index.vue';
|
|
import Icon from '@/components/Icon/Icon.vue';
|
|
import { useCloudQueryStore } from '@/store/modules/cloudquery';
|
|
|
|
const flowWfDataStore = flowStore();
|
|
const useCloudQuery = useCloudQueryStore();
|
|
const [registerModal, { openModal: openLookModal }] = useModal();
|
|
const userStore = useUserStore();
|
|
const userInfo: any = userStore.getUserInfo;
|
|
const visible = ref(false);
|
|
const { prefixCls } = useDesign('header-notify');
|
|
const { createMessage, notification } = useMessage();
|
|
const listData = ref(tabListData);
|
|
const numberStyle = {};
|
|
const auditOpen = ref(false);
|
|
const processId = ref('');
|
|
const taskId = ref('');
|
|
const isRead: any = ref(0);
|
|
const type = ref('');
|
|
const cloudQueryVisible = ref(false);
|
|
const compare = ref(false);
|
|
const open = ref(false);
|
|
const count = computed(() => {
|
|
let count = 0;
|
|
for (let i = 0; i < listData.value.length; i++) {
|
|
count += listData.value[i].list.length;
|
|
}
|
|
return count;
|
|
});
|
|
|
|
async function onNoticeClick(record) {
|
|
console.log(record);
|
|
visible.value = false;
|
|
const index = listData.value[0].list.findIndex((item: any) => item.id === record.id);
|
|
if (index !== -1) {
|
|
listData.value[0].list.splice(index, 1);
|
|
}
|
|
if (record.contentId) {
|
|
const info = await getInfoByContentId({
|
|
id: record.contentId,
|
|
});
|
|
if (info) {
|
|
let data = await getDetail({ code: info.ProcessCode });
|
|
let scheme = JSON.parse(data.scheme.content);
|
|
let wfData = scheme.wfData;
|
|
flowWfDataStore.setWfDataAll(wfData);
|
|
auditOpen.value = true;
|
|
processId.value = info.ProcessId;
|
|
taskId.value = info.Id;
|
|
type.value = info.Type;
|
|
} else {
|
|
openLookModal(true, {
|
|
record: {
|
|
content: record.title,
|
|
createDate: record.datetime,
|
|
isRead: 0,
|
|
},
|
|
});
|
|
}
|
|
} else {
|
|
openLookModal(true, {
|
|
record: {
|
|
content: record.title,
|
|
createDate: record.datetime,
|
|
isRead: 0,
|
|
},
|
|
});
|
|
}
|
|
const data = await readMsg({
|
|
id: record.id,
|
|
});
|
|
}
|
|
async function getList() {
|
|
const data = await getLastList({
|
|
userId: userInfo.id,
|
|
});
|
|
let arr: any = [];
|
|
if (data && data.length > 0) {
|
|
data.forEach((item: any) => {
|
|
arr.push({
|
|
id: item.msgId,
|
|
title: item.content,
|
|
datetime: item.createDate,
|
|
contentId: item.contentId,
|
|
});
|
|
});
|
|
listData.value[0].list = arr;
|
|
}
|
|
}
|
|
|
|
// 连接
|
|
async function start() {
|
|
try {
|
|
await signal.start().then(() => {
|
|
signal
|
|
.invoke('SendInfo', userInfo.id.toString())
|
|
.catch((err) => console.error(err.toString()));
|
|
});
|
|
console.log('userInfo.id', userInfo.id);
|
|
console.log('SignalR Connected.连接成功');
|
|
} catch (err) {
|
|
console.log(err);
|
|
// setTimeout(start, 5000);
|
|
}
|
|
}
|
|
signal.onclose(async () => {
|
|
await start();
|
|
});
|
|
//接口推送
|
|
signal.on('RevMsg', (user, message, time, id, issystem) => {
|
|
console.log('报警', user, message, time, id, issystem); //拿到后台推送的数据
|
|
// ChaoShi 超时报警
|
|
// CloudQuery 云查询
|
|
if (user == 'CloudQuery') {
|
|
showCloudQuery({
|
|
id,
|
|
});
|
|
} else {
|
|
notification.info({
|
|
message: '您有一条新消息',
|
|
description: () => {
|
|
const res = message + '\n' + time;
|
|
return h('pre', {}, res);
|
|
},
|
|
duration: 3,
|
|
});
|
|
getList();
|
|
}
|
|
});
|
|
onMounted(() => {
|
|
getList();
|
|
start();
|
|
});
|
|
function closeMolder() {
|
|
auditOpen.value = false;
|
|
}
|
|
function showCloudQuery(info) {
|
|
cloudQueryVisible.value = true;
|
|
useCloudQuery.setIdentification(false);
|
|
useCloudQuery.setCloudQueryInfo(info);
|
|
}
|
|
// 查看云查询结果
|
|
function handCloudQuery() {
|
|
open.value = true;
|
|
closeCloudQuery();
|
|
}
|
|
function closeCloudQuery() {
|
|
cloudQueryVisible.value = false;
|
|
}
|
|
const changeCompare = () => {
|
|
compare.value = !compare.value;
|
|
console.log('compare.value', compare.value);
|
|
};
|
|
</script>
|
|
<style lang="less">
|
|
@prefix-cls: ~'@{namespace}-header-notify';
|
|
|
|
.@{prefix-cls} {
|
|
padding-bottom: 1px;
|
|
|
|
&__overlay {
|
|
max-width: 360px;
|
|
}
|
|
|
|
.ant-tabs-content {
|
|
width: 300px;
|
|
}
|
|
|
|
.ant-badge {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 18px;
|
|
|
|
.ant-badge-multiple-words {
|
|
padding: 0 4px;
|
|
}
|
|
|
|
svg {
|
|
width: 0.9em;
|
|
}
|
|
}
|
|
}
|
|
.full-modal {
|
|
.ant-modal {
|
|
max-width: 100%;
|
|
top: 0;
|
|
}
|
|
|
|
.ant-modal-content {
|
|
height: calc(100vh);
|
|
}
|
|
|
|
.ant-modal-body {
|
|
height: 85%;
|
|
}
|
|
}
|
|
.cloudquery-notice {
|
|
background: rgba(0, 0, 0, 0.53);
|
|
padding: 0px 14px;
|
|
border-radius: 6px;
|
|
position: fixed;
|
|
top: 30px;
|
|
right: 1vw;
|
|
width: 700px;
|
|
color: #fff;
|
|
z-index: 10;
|
|
.cloudquery-title {
|
|
height: 40px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
font-size: 16px;
|
|
}
|
|
.cloudquery-left {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.cloudquery-right {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-around;
|
|
width: 130px;
|
|
}
|
|
img {
|
|
width: 34px;
|
|
height: 29px;
|
|
}
|
|
.cloudquery-btn {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
.line {
|
|
background: #ededed;
|
|
width: 1px;
|
|
height: 20px;
|
|
}
|
|
.anticon.anticon-close {
|
|
height: 30px;
|
|
}
|
|
button {
|
|
width: 70px;
|
|
height: 26px;
|
|
background: linear-gradient(-74deg, #086dec, #0b4bdd);
|
|
box-shadow: 3px 4px 5px 1px rgba(13, 13, 13, 0.05);
|
|
border-radius: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.title-box {
|
|
margin-left: 10px;
|
|
font-size: 14px;
|
|
}
|
|
}
|
|
</style>
|
|
<style lang="scss" scoped>
|
|
.modal-content-div {
|
|
padding: 53px 20px 10px 20px;
|
|
width: 100%;
|
|
.title-text {
|
|
display: flex;
|
|
justify-content: center;
|
|
font-size: 18px;
|
|
color: #2f83d9;
|
|
text-decoration: underline;
|
|
font-weight: 600;
|
|
position: relative;
|
|
}
|
|
.split-button {
|
|
font-size: 20px;
|
|
display: inline-flex;
|
|
position: absolute;
|
|
right: 8px;
|
|
top: 2px;
|
|
color: #000000a3;
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
.search-menu {
|
|
width: 50px;
|
|
height: 355px;
|
|
background-color: #fff;
|
|
position: absolute;
|
|
top: 30px;
|
|
left: 20px;
|
|
border-radius: 25px;
|
|
padding-top: 19px;
|
|
}
|
|
.active {
|
|
background: repeating-linear-gradient(to left, rgb(38, 51, 231), rgb(20, 118, 230));
|
|
color: #fff;
|
|
}
|
|
.menu-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
margin-bottom: 7px;
|
|
cursor: pointer;
|
|
.item-icon {
|
|
font-size: 20px;
|
|
margin-bottom: 2px;
|
|
width: 40px;
|
|
height: 40px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 50%;
|
|
transition: 0.2s;
|
|
}
|
|
.item-text {
|
|
user-select: none;
|
|
}
|
|
}
|
|
.menu-content {
|
|
padding: 10px;
|
|
background: #fff;
|
|
position: absolute;
|
|
top: 0px;
|
|
left: 70px;
|
|
width: 420px;
|
|
}
|
|
</style>
|