增加站内信未读提醒和后台通知中心+txt 校验

This commit is contained in:
yml2213
2026-06-19 15:24:15 +08:00
parent 8d5094a8d0
commit a4cdc3e806
30 changed files with 1836 additions and 53 deletions
@@ -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,
}
}