feat(message): 优化消息通知功能
- 修改标题为"IOT设备管理系统" - 优化消息通知组件,增加未读消息数量显示- 添加消息详情查看功能 - 更新消息列表展示,增加操作按钮 - 调整消息接口路径
This commit is contained in:
parent
69a0144ebd
commit
13360113ef
@ -8,7 +8,7 @@
|
||||
href="https://unpkg.byted-static.com/latest/byted/arco-config/assets/favicon.ico"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>基于MQTT的IOT设备管理系统</title>
|
||||
<title>IOT设备管理系统</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -1,39 +0,0 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export interface MessageRecord {
|
||||
id: number;
|
||||
type: string;
|
||||
title: string;
|
||||
subTitle: string;
|
||||
avatar?: string;
|
||||
content: string;
|
||||
time: string;
|
||||
status: 0 | 1;
|
||||
messageType?: number;
|
||||
}
|
||||
export type MessageListType = MessageRecord[];
|
||||
|
||||
export function queryMessageList() {
|
||||
return axios.post<MessageListType>('/api/message/list');
|
||||
}
|
||||
|
||||
interface MessageStatus {
|
||||
ids: string[];
|
||||
}
|
||||
|
||||
// 批量设置消息已读
|
||||
export function setMessageStatus(data: MessageStatus) {
|
||||
return axios.post<MessageListType>('/api/message/read', data);
|
||||
}
|
||||
|
||||
export interface ChatRecord {
|
||||
id: number;
|
||||
username: string;
|
||||
content: string;
|
||||
time: string;
|
||||
isCollect: boolean;
|
||||
}
|
||||
|
||||
export function queryChatList() {
|
||||
return axios.post<ChatRecord[]>('/api/chat/list');
|
||||
}
|
@ -68,7 +68,7 @@ export function queryMessagesList(data: MessagesRecord) {
|
||||
}
|
||||
// 未读消息数量
|
||||
export function queryMessagesCount() {
|
||||
return axios.get('/api/rest/notice/count-unread');
|
||||
return axios.get('/api/rest/notice/countUnread');
|
||||
}
|
||||
|
||||
// 已读消息数量
|
||||
|
@ -69,12 +69,11 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue';
|
||||
import { MessageRecord, MessageListType } from '@/api/message';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const props = defineProps({
|
||||
renderList: {
|
||||
type: Array as PropType<MessageListType>,
|
||||
type: Array as PropType<any>,
|
||||
required: true,
|
||||
},
|
||||
unreadCount: {
|
||||
@ -87,7 +86,7 @@
|
||||
// emit('itemClick', [...props.renderList]);
|
||||
// };
|
||||
|
||||
const onItemClick = (item: MessageRecord) => {
|
||||
const onItemClick = (item: any) => {
|
||||
if (!item.status) {
|
||||
emit('itemClick', [item]);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@
|
||||
<li>
|
||||
<a-tooltip content="消息通知">
|
||||
<div class="message-box-trigger">
|
||||
<a-badge :count="9" dot>
|
||||
<a-badge v-if="messageCount > 0" :count="9" dot>
|
||||
<a-button
|
||||
class="nav-btn"
|
||||
type="outline"
|
||||
@ -53,6 +53,15 @@
|
||||
<icon-notification />
|
||||
</a-button>
|
||||
</a-badge>
|
||||
<a-button
|
||||
v-else
|
||||
class="nav-btn"
|
||||
type="outline"
|
||||
:shape="'circle'"
|
||||
@click="setPopoverVisible"
|
||||
>
|
||||
<icon-notification />
|
||||
</a-button>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<a-popover
|
||||
@ -204,7 +213,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, inject } from 'vue';
|
||||
import { computed, ref, inject, onMounted } from 'vue';
|
||||
import { useDark, useToggle, useFullscreen } from '@vueuse/core';
|
||||
import { useAppStore, useUserStore } from '@/store';
|
||||
import { LOCALE_OPTIONS } from '@/locale';
|
||||
@ -215,6 +224,7 @@
|
||||
import { useRouter } from 'vue-router';
|
||||
import { clearToken } from '@/utils/auth';
|
||||
import messageBox from '@/components/message-box/index.vue';
|
||||
import { queryMessagesCount } from '@/api/messages';
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
@ -222,6 +232,7 @@
|
||||
|
||||
const { changeLocale, currentLocale } = useLocale();
|
||||
const { isFullscreen, toggle: toggleFullScreen } = useFullscreen();
|
||||
const messageCount = ref(0);
|
||||
const locales = [...LOCALE_OPTIONS];
|
||||
const avatar = computed(() => {
|
||||
return userStore.avatar ? userStore.avatar : userIcon;
|
||||
@ -275,12 +286,22 @@
|
||||
triggerBtn.value.dispatchEvent(event);
|
||||
};
|
||||
|
||||
const fetchMessageCount = async () => {
|
||||
const response = await queryMessagesCount();
|
||||
messageCount.value = response.data;
|
||||
};
|
||||
|
||||
// 切换角色
|
||||
const handleSwitchRole = (roleId: number) => {
|
||||
userStore.switchRole(roleId);
|
||||
};
|
||||
|
||||
const toggleDrawerMenu = inject('toggleDrawerMenu') as () => void;
|
||||
|
||||
// 在组件挂载时调用
|
||||
onMounted(() => {
|
||||
fetchMessageCount();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
@ -152,8 +152,13 @@
|
||||
<template #createTime="{ record }">
|
||||
{{ dayjs(record.createTime).format('YYYY-MM-DD HH:mm') }}
|
||||
</template>
|
||||
<template #isRead="{ record }">
|
||||
{{ record.isRead == true ? '已读' : '未读' }}
|
||||
<template #operation="{ record }">
|
||||
<a-button type="outline" size="small" @click="handleViewDetail(record)">
|
||||
<template #icon>
|
||||
<icon-eye />
|
||||
</template>
|
||||
详情
|
||||
</a-button>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
@ -167,6 +172,31 @@
|
||||
@change="onPageChange"
|
||||
/>
|
||||
</a-card>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
width="900px"
|
||||
:visible="visible"
|
||||
:footer="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>消息详情</template>
|
||||
<a-descriptions :column="1">
|
||||
<a-descriptions-item label="标题">
|
||||
{{ selectedRecord.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="时间">
|
||||
{{ dayjs(selectedRecord.createTime).format('YYYY-MM-DD HH:mm') }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="备注">
|
||||
<div v-html="selectedRecord.remark"></div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="内容">
|
||||
<div v-html="selectedRecord.content"></div>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -193,6 +223,13 @@
|
||||
const renderData = ref<MessageRecord[]>([]);
|
||||
const formModel = ref(generateFormModel());
|
||||
const selectedIds = ref<number[]>([]);
|
||||
const visible = ref(false);
|
||||
const selectedRecord = ref({
|
||||
title: '',
|
||||
createTime: '',
|
||||
remark: '',
|
||||
content: '',
|
||||
});
|
||||
const {
|
||||
cloneColumns,
|
||||
showColumns,
|
||||
@ -209,10 +246,6 @@
|
||||
const { pagination, setPagination } = usePagination();
|
||||
|
||||
const columns = computed<TableColumnData[]>(() => [
|
||||
// {
|
||||
// title: '用户编号',
|
||||
// dataIndex: 'userId',
|
||||
// },
|
||||
{
|
||||
title: '标题',
|
||||
dataIndex: 'title',
|
||||
@ -231,6 +264,11 @@
|
||||
dataIndex: 'remark',
|
||||
slotName: 'remark',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
slotName: 'operation',
|
||||
},
|
||||
]);
|
||||
// 获取消息列表
|
||||
const fetchData = async (params = { size: 10, current: 1 }) => {
|
||||
@ -274,6 +312,15 @@
|
||||
search();
|
||||
};
|
||||
|
||||
const handleViewDetail = (record: any) => {
|
||||
selectedRecord.value = record;
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formModel.value = generateFormModel();
|
||||
|
@ -103,8 +103,8 @@
|
||||
style="margin-bottom: 40px"
|
||||
@page-change="onPageChange"
|
||||
>
|
||||
<template #operationTime="{ record }">
|
||||
{{ dayjs(record.operationTime).format('YYYY-MM-DD HH:mm') }}
|
||||
<template #makeTime="{ record }">
|
||||
{{ dayjs(record.makeTime).format('YYYY-MM-DD HH:mm') }}
|
||||
</template>
|
||||
</a-table>
|
||||
<a-pagination
|
||||
@ -158,8 +158,8 @@
|
||||
},
|
||||
{
|
||||
title: '操作时间',
|
||||
dataIndex: 'operationTime',
|
||||
slotName: 'operationTime',
|
||||
dataIndex: 'makeTime',
|
||||
slotName: 'makeTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
|
@ -76,12 +76,23 @@
|
||||
@change="handleSortChange"
|
||||
@page-change="onPageChange"
|
||||
>
|
||||
<template #publishTime="{ record }">
|
||||
{{ dayjs(record.publishTime).format('YYYY-MM-DD HH:mm') }}
|
||||
<template #createTime="{ record }">
|
||||
{{ dayjs(record.createTime).format('YYYY-MM-DD HH:mm') }}
|
||||
</template>
|
||||
<template #isRead="{ record }">
|
||||
{{ record.isRead == true ? '已读' : '未读' }}
|
||||
</template>
|
||||
<template #operation="{ record }">
|
||||
<a-button
|
||||
type="outline"
|
||||
size="small"
|
||||
status="success"
|
||||
@click="handleViewDetail(record)"
|
||||
style="padding: 7px; margin-right: 10px"
|
||||
>
|
||||
<template #icon><icon-list /></template>详情
|
||||
</a-button>
|
||||
</template>
|
||||
<!-- <template #operations="{ record }">-->
|
||||
<!-- <a-button-->
|
||||
<!-- type="outline"-->
|
||||
@ -106,6 +117,29 @@
|
||||
@change="onPageChange"
|
||||
/>
|
||||
</a-card>
|
||||
|
||||
<a-modal
|
||||
width="900px"
|
||||
:visible="visible"
|
||||
:footer="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>消息详情</template>
|
||||
<a-descriptions :column="1">
|
||||
<a-descriptions-item label="标题">
|
||||
{{ selectedRecord.title }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="时间">
|
||||
{{ dayjs(selectedRecord.createTime).format('YYYY-MM-DD HH:mm') }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="备注">
|
||||
<div v-html="selectedRecord.remark"></div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="内容">
|
||||
<div v-html="selectedRecord.content"></div>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -153,8 +187,8 @@
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'publishTime',
|
||||
slotName: 'publishTime',
|
||||
dataIndex: 'createTime',
|
||||
slotName: 'createTime',
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
@ -164,11 +198,11 @@
|
||||
dataIndex: 'isRead',
|
||||
slotName: 'isRead',
|
||||
},
|
||||
// {
|
||||
// title: '操作',
|
||||
// dataIndex: 'operations',
|
||||
// slotName: 'operations',
|
||||
// },
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
slotName: 'operation',
|
||||
},
|
||||
]);
|
||||
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||
{
|
||||
@ -181,6 +215,14 @@
|
||||
},
|
||||
]);
|
||||
|
||||
const visible = ref(false);
|
||||
const selectedRecord = ref({
|
||||
title: '',
|
||||
createTime: '',
|
||||
remark: '',
|
||||
content: '',
|
||||
});
|
||||
|
||||
// 获取消息列表
|
||||
const fetchData = async (
|
||||
params: BulletinsRecord = { size: 10, current: 1 }
|
||||
@ -234,6 +276,15 @@
|
||||
search();
|
||||
};
|
||||
|
||||
const handleViewDetail = (record: any) => {
|
||||
selectedRecord.value = record;
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
search();
|
||||
|
||||
// 重置
|
||||
|
Loading…
Reference in New Issue
Block a user