更新
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
</a-tooltip>
|
||||
|
||||
<!-- 消息通知 -->
|
||||
<a-dropdown v-model:open="messageVisible" :trigger="['click']" placement="bottomRight">
|
||||
<a-dropdown v-model:open="messageVisible" :trigger="['click']" placement="bottomRight" @openChange="handleMessageDropdownOpen">
|
||||
<a-badge :count="messageCount" :offset="[-5, 5]">
|
||||
<a-button type="text" class="action-btn">
|
||||
<BellOutlined />
|
||||
@@ -51,9 +51,9 @@
|
||||
<div class="message-content">
|
||||
<div class="message-title">{{ msg.title }}</div>
|
||||
<div class="message-content-text">{{ msg.content }}</div>
|
||||
<div class="message-time">{{ messageStore.formatMessageTime(msg.timestamp) }}</div>
|
||||
<div class="message-time">{{ notificationStore.formatNotificationTime(msg.created_at) }}</div>
|
||||
</div>
|
||||
<a-badge v-if="!msg.read" dot />
|
||||
<a-badge v-if="!msg.is_read" dot />
|
||||
<a-button
|
||||
type="text"
|
||||
size="small"
|
||||
@@ -160,11 +160,12 @@ import { useRouter } from 'vue-router'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
import { useI18nStore } from '@/stores/modules/i18n'
|
||||
import { useMessageStore, MessageType } from '@/stores/modules/message'
|
||||
import { useNotificationStore } from '@/stores/modules/notification'
|
||||
import { DownOutlined, UserOutlined, LogoutOutlined, FullscreenOutlined, FullscreenExitOutlined, BellOutlined, CheckSquareOutlined, GlobalOutlined, SearchOutlined, SettingOutlined, DeleteOutlined } from '@ant-design/icons-vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import search from './search.vue'
|
||||
import task from './task.vue'
|
||||
import { useWebSocket } from '@/composables/useWebSocket'
|
||||
|
||||
// 定义组件名称(多词命名)
|
||||
defineOptions({
|
||||
@@ -175,7 +176,7 @@ const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const i18nStore = useI18nStore()
|
||||
const messageStore = useMessageStore()
|
||||
const notificationStore = useNotificationStore()
|
||||
|
||||
const isFullscreen = ref(false)
|
||||
const searchVisible = ref(false)
|
||||
@@ -184,28 +185,16 @@ const messageVisible = ref(false)
|
||||
const currentMessageType = ref('all')
|
||||
const messagesPage = ref(1)
|
||||
const messagesPageSize = ref(10)
|
||||
|
||||
// 从 store 获取消息数据
|
||||
const messages = computed(() => {
|
||||
const result = messageStore.getMessages({
|
||||
page: messagesPage.value,
|
||||
pageSize: messagesPageSize.value,
|
||||
type: currentMessageType.value === 'all' ? null : currentMessageType.value
|
||||
})
|
||||
return result.list
|
||||
})
|
||||
|
||||
// 消息总数(用于分页)
|
||||
const messagesTotal = computed(() => {
|
||||
return messageStore.getMessages({
|
||||
page: messagesPage.value,
|
||||
pageSize: messagesPageSize.value,
|
||||
type: currentMessageType.value === 'all' ? null : currentMessageType.value
|
||||
}).total
|
||||
})
|
||||
const notificationsList = ref([])
|
||||
|
||||
// 未读消息数量
|
||||
const messageCount = computed(() => messageStore.unreadCount)
|
||||
const messageCount = computed(() => notificationStore.unreadCount)
|
||||
|
||||
// 消息总数(用于分页)
|
||||
const messagesTotal = computed(() => notificationStore.total)
|
||||
|
||||
// 从 store 获取消息数据
|
||||
const messages = computed(() => notificationsList.value)
|
||||
|
||||
// 任务数据
|
||||
const tasks = ref([
|
||||
@@ -232,8 +221,58 @@ const handleFullscreenChange = () => {
|
||||
isFullscreen.value = !!document.fullscreenElement
|
||||
}
|
||||
|
||||
// 加载未读通知
|
||||
const loadNotifications = async () => {
|
||||
try {
|
||||
await notificationStore.fetchUnreadCount()
|
||||
await loadUnreadNotifications()
|
||||
} catch (error) {
|
||||
console.error('加载通知失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载未读通知列表
|
||||
const loadUnreadNotifications = async () => {
|
||||
try {
|
||||
const res = await notificationStore.fetchUnreadNotifications({
|
||||
page: messagesPage.value,
|
||||
page_size: messagesPageSize.value,
|
||||
type: currentMessageType.value === 'all' ? null : currentMessageType.value
|
||||
})
|
||||
notificationsList.value = res.list || []
|
||||
} catch (error) {
|
||||
console.error('加载未读通知列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载所有通知
|
||||
const loadAllNotifications = async () => {
|
||||
try {
|
||||
await notificationStore.fetchNotifications({
|
||||
page: messagesPage.value,
|
||||
page_size: messagesPageSize.value,
|
||||
type: currentMessageType.value === 'all' ? null : currentMessageType.value
|
||||
})
|
||||
notificationsList.value = notificationStore.notifications
|
||||
} catch (error) {
|
||||
console.error('加载通知列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// WebSocket 消息处理
|
||||
const handleWebSocketMessage = (data) => {
|
||||
notificationStore.handleWebSocketMessage(data)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('fullscreenchange', handleFullscreenChange)
|
||||
|
||||
// 加载通知数据
|
||||
loadNotifications()
|
||||
|
||||
// 连接 WebSocket
|
||||
const { initWebSocket } = useWebSocket()
|
||||
initWebSocket()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -246,46 +285,113 @@ const showSearch = () => {
|
||||
}
|
||||
|
||||
// 清除消息
|
||||
const clearMessages = () => {
|
||||
const clearMessages = async () => {
|
||||
Modal.confirm({
|
||||
title: t('common.confirmClear'),
|
||||
content: t('common.confirmClearMessages'),
|
||||
okText: t('common.confirm'),
|
||||
cancelText: t('common.cancel'),
|
||||
onOk: () => {
|
||||
messageStore.clearAll()
|
||||
message.success(t('common.cleared'))
|
||||
onOk: async () => {
|
||||
try {
|
||||
await notificationStore.clearReadNotifications()
|
||||
message.success(t('common.cleared'))
|
||||
notificationsList.value = []
|
||||
} catch (error) {
|
||||
console.error('清空消息失败:', error)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 标记消息为已读
|
||||
const handleMessageRead = (msg) => {
|
||||
if (!msg.read) {
|
||||
messageStore.markAsRead(msg.id)
|
||||
const handleMessageRead = async (msg) => {
|
||||
if (!msg.is_read) {
|
||||
try {
|
||||
await notificationStore.markAsRead(msg.id)
|
||||
// 更新本地状态
|
||||
const notification = notificationsList.value.find(n => n.id === msg.id)
|
||||
if (notification) {
|
||||
notification.is_read = true
|
||||
notification.read_at = new Date().toISOString()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('标记已读失败:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 标记所有消息为已读
|
||||
const markAllAsRead = () => {
|
||||
messageStore.markAllAsRead()
|
||||
message.success(t('common.markedAsRead'))
|
||||
const markAllAsRead = async () => {
|
||||
Modal.confirm({
|
||||
title: '确认全部已读',
|
||||
content: '确定要将所有消息标记为已读吗?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await notificationStore.markAllAsRead()
|
||||
message.success(t('common.markedAsRead'))
|
||||
// 更新本地状态
|
||||
notificationsList.value.forEach(n => {
|
||||
n.is_read = true
|
||||
n.read_at = n.read_at || new Date().toISOString()
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('标记全部已读失败:', error)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除消息
|
||||
const handleDeleteMessage = (msgId) => {
|
||||
messageStore.removeMessage(msgId)
|
||||
const handleDeleteMessage = async (msgId) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这条消息吗?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await notificationStore.deleteNotification(msgId)
|
||||
message.success('删除成功')
|
||||
// 更新本地状态
|
||||
const index = notificationsList.value.findIndex(n => n.id === msgId)
|
||||
if (index !== -1) {
|
||||
notificationsList.value.splice(index, 1)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除消息失败:', error)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 切换消息类型
|
||||
const changeMessageType = (type) => {
|
||||
const changeMessageType = async (type) => {
|
||||
currentMessageType.value = type
|
||||
messagesPage.value = 1
|
||||
if (type === 'all') {
|
||||
await loadAllNotifications()
|
||||
} else {
|
||||
await loadUnreadNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
// 分页变化
|
||||
const handleMessagePageChange = (page) => {
|
||||
const handleMessagePageChange = async (page) => {
|
||||
messagesPage.value = page
|
||||
if (currentMessageType.value === 'all') {
|
||||
await loadAllNotifications()
|
||||
} else {
|
||||
await loadUnreadNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
// 下拉框打开时加载数据
|
||||
const handleMessageDropdownOpen = async (open) => {
|
||||
if (open) {
|
||||
await loadNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
// 显示任务抽屉
|
||||
|
||||
Reference in New Issue
Block a user