增加站内信未读提醒和后台通知中心+txt 校验
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
|
||||
import { fetchAdminNotificationUnreadCount } from '@/features/admin/api/adminNotifications'
|
||||
import { useAdminSessionStore } from '@/stores/adminSession'
|
||||
|
||||
export const adminNotificationUnreadChangedEvent = 'admin-notification-unread-changed'
|
||||
|
||||
export function useAdminNotificationUnreadCount(route: RouteLocationNormalizedLoaded) {
|
||||
const adminSession = useAdminSessionStore()
|
||||
const unreadCount = ref(0)
|
||||
let timer: number | null = null
|
||||
let requestID = 0
|
||||
|
||||
const unreadLabel = computed(() => (unreadCount.value > 99 ? '99+' : String(unreadCount.value)))
|
||||
|
||||
function stopPolling() {
|
||||
if (timer) {
|
||||
window.clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUnreadCount() {
|
||||
if (!adminSession.hasSessionHint) {
|
||||
unreadCount.value = 0
|
||||
return
|
||||
}
|
||||
|
||||
const currentID = ++requestID
|
||||
try {
|
||||
const count = await fetchAdminNotificationUnreadCount()
|
||||
if (currentID === requestID) {
|
||||
unreadCount.value = count
|
||||
}
|
||||
} catch {
|
||||
// 后台角标静默失败,避免干扰当前操作。
|
||||
}
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
stopPolling()
|
||||
void loadUnreadCount()
|
||||
timer = window.setInterval(loadUnreadCount, 30_000)
|
||||
}
|
||||
|
||||
function resumePollingIfVisible() {
|
||||
if (document.hidden || !adminSession.hasSessionHint) return
|
||||
startPolling()
|
||||
}
|
||||
|
||||
function handleVisibilityChange() {
|
||||
if (document.hidden) {
|
||||
stopPolling()
|
||||
return
|
||||
}
|
||||
resumePollingIfVisible()
|
||||
}
|
||||
|
||||
function handleUnreadChanged() {
|
||||
void loadUnreadCount()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener(adminNotificationUnreadChangedEvent, handleUnreadChanged)
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||||
resumePollingIfVisible()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
stopPolling()
|
||||
window.removeEventListener(adminNotificationUnreadChangedEvent, handleUnreadChanged)
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => adminSession.hasSessionHint,
|
||||
hasSession => {
|
||||
if (hasSession) {
|
||||
resumePollingIfVisible()
|
||||
return
|
||||
}
|
||||
stopPolling()
|
||||
unreadCount.value = 0
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
() => {
|
||||
void loadUnreadCount()
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
unreadCount,
|
||||
unreadLabel,
|
||||
refreshUnreadCount: loadUnreadCount,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user