mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 15:36:49 +08:00
实现未读消息的全局事件处理
This commit is contained in:
+14
@@ -6,6 +6,7 @@ import api from '@/api'
|
|||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { getBrowserLocale, setI18nLanguage } from './plugins/i18n'
|
import { getBrowserLocale, setI18nLanguage } from './plugins/i18n'
|
||||||
import { SupportedLocale } from '@/types/i18n'
|
import { SupportedLocale } from '@/types/i18n'
|
||||||
|
import { checkAndEmitUnreadMessages } from '@/utils/badge'
|
||||||
|
|
||||||
// 生效主题
|
// 生效主题
|
||||||
const { global: globalTheme } = useTheme()
|
const { global: globalTheme } = useTheme()
|
||||||
@@ -172,6 +173,11 @@ onMounted(async () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 移除加载动画,显示页面
|
// 移除加载动画,显示页面
|
||||||
animateAndRemoveLoader()
|
animateAndRemoveLoader()
|
||||||
|
|
||||||
|
// 页面完全显示后,检查未读消息
|
||||||
|
setTimeout(() => {
|
||||||
|
checkAndEmitUnreadMessages()
|
||||||
|
}, 1000)
|
||||||
}, 1500)
|
}, 1500)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -180,6 +186,10 @@ onMounted(async () => {
|
|||||||
document.addEventListener('visibilitychange', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
if (document.visibilityState === 'visible') {
|
if (document.visibilityState === 'visible') {
|
||||||
loadBackgroundImages()
|
loadBackgroundImages()
|
||||||
|
// 页面恢复可见时检查未读消息
|
||||||
|
setTimeout(() => {
|
||||||
|
checkAndEmitUnreadMessages()
|
||||||
|
}, 500)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -188,6 +198,10 @@ onMounted(async () => {
|
|||||||
// persisted属性为true表示页面是从bfcache中恢复的
|
// persisted属性为true表示页面是从bfcache中恢复的
|
||||||
if (event.persisted) {
|
if (event.persisted) {
|
||||||
loadBackgroundImages()
|
loadBackgroundImages()
|
||||||
|
// PWA恢复时检查未读消息
|
||||||
|
setTimeout(() => {
|
||||||
|
checkAndEmitUnreadMessages()
|
||||||
|
}, 500)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { NavMenu } from '@/@layouts/types'
|
|||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { filterMenusByPermission } from '@/utils/permission'
|
import { filterMenusByPermission } from '@/utils/permission'
|
||||||
import { checkUnreadOnStartup } from '@/utils/badge'
|
import { onUnreadMessage } from '@/utils/badge'
|
||||||
|
|
||||||
const display = useDisplay()
|
const display = useDisplay()
|
||||||
const appMode = inject('pwaMode')
|
const appMode = inject('pwaMode')
|
||||||
@@ -28,9 +28,6 @@ const superUser = computed(() => userStore.superUser)
|
|||||||
// ShortcutBar 引用
|
// ShortcutBar 引用
|
||||||
const shortcutBarRef = ref<InstanceType<typeof ShortcutBar> | null>(null)
|
const shortcutBarRef = ref<InstanceType<typeof ShortcutBar> | null>(null)
|
||||||
|
|
||||||
// 未读消息检查状态
|
|
||||||
const hasCheckedUnread = ref(false)
|
|
||||||
|
|
||||||
// 获取用户权限信息
|
// 获取用户权限信息
|
||||||
const userPermissions = computed(() => ({
|
const userPermissions = computed(() => ({
|
||||||
is_superuser: userStore.superUser,
|
is_superuser: userStore.superUser,
|
||||||
@@ -65,57 +62,18 @@ function goBack() {
|
|||||||
history.back()
|
history.back()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查未读消息并自动打开消息弹窗
|
// 处理未读消息事件
|
||||||
async function checkUnreadMessages() {
|
function handleUnreadMessage(count: number) {
|
||||||
if (!superUser.value || hasCheckedUnread.value) {
|
if (superUser.value && count > 0) {
|
||||||
return // 只有超级用户才能看到消息,且每次会话只检查一次
|
// 延迟一点时间确保组件已渲染
|
||||||
}
|
setTimeout(() => {
|
||||||
|
if (shortcutBarRef.value && typeof shortcutBarRef.value.openMessageDialog === 'function') {
|
||||||
hasCheckedUnread.value = true
|
shortcutBarRef.value.openMessageDialog()
|
||||||
|
}
|
||||||
try {
|
}, 500)
|
||||||
const unreadCount = await checkUnreadOnStartup()
|
|
||||||
|
|
||||||
if (unreadCount > 0) {
|
|
||||||
// 等待组件完全加载并重试打开消息弹窗
|
|
||||||
await waitAndOpenMessageDialog()
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// 静默处理错误
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待组件准备好并打开消息弹窗
|
|
||||||
async function waitAndOpenMessageDialog() {
|
|
||||||
const maxRetries = 5
|
|
||||||
const retryDelay = 1000 // 1秒
|
|
||||||
|
|
||||||
for (let i = 0; i < maxRetries; i++) {
|
|
||||||
// 等待一段时间确保组件加载完成
|
|
||||||
await new Promise(resolve => setTimeout(resolve, retryDelay * (i + 1)))
|
|
||||||
|
|
||||||
// 检查ShortcutBar组件是否已经准备好
|
|
||||||
if (shortcutBarRef.value && typeof shortcutBarRef.value.openMessageDialog === 'function') {
|
|
||||||
shortcutBarRef.value.openMessageDialog()
|
|
||||||
return // 成功打开,退出重试循环
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听用户状态变化
|
|
||||||
watch(
|
|
||||||
superUser,
|
|
||||||
newValue => {
|
|
||||||
if (newValue && !hasCheckedUnread.value) {
|
|
||||||
// 用户状态变为超级用户且还没检查过未读消息时,延迟检查
|
|
||||||
setTimeout(() => {
|
|
||||||
checkUnreadMessages()
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取菜单列表
|
// 获取菜单列表
|
||||||
startMenus.value = getMenuList(t('menu.start'))
|
startMenus.value = getMenuList(t('menu.start'))
|
||||||
@@ -124,11 +82,12 @@ onMounted(() => {
|
|||||||
organizeMenus.value = getMenuList(t('menu.organize'))
|
organizeMenus.value = getMenuList(t('menu.organize'))
|
||||||
systemMenus.value = getMenuList(t('menu.system'))
|
systemMenus.value = getMenuList(t('menu.system'))
|
||||||
|
|
||||||
// 延迟检查未读消息,确保所有组件都已加载完成
|
// 监听全局未读消息事件
|
||||||
nextTick(() => {
|
const unsubscribe = onUnreadMessage(handleUnreadMessage)
|
||||||
setTimeout(() => {
|
|
||||||
checkUnreadMessages()
|
// 组件卸载时清理监听
|
||||||
}, 2000) // 增加延迟时间到2秒
|
onBeforeUnmount(() => {
|
||||||
|
unsubscribe()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+38
-29
@@ -2,6 +2,27 @@
|
|||||||
* PWA 徽章管理工具
|
* PWA 徽章管理工具
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// 全局事件类型
|
||||||
|
interface UnreadMessageEvent extends CustomEvent {
|
||||||
|
detail: { count: number }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送全局未读消息事件
|
||||||
|
export function emitUnreadMessageEvent(count: number) {
|
||||||
|
const event = new CustomEvent('unreadMessage', { detail: { count } }) as UnreadMessageEvent
|
||||||
|
window.dispatchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听全局未读消息事件
|
||||||
|
export function onUnreadMessage(callback: (count: number) => void) {
|
||||||
|
const handler = (event: Event) => {
|
||||||
|
const unreadEvent = event as UnreadMessageEvent
|
||||||
|
callback(unreadEvent.detail.count)
|
||||||
|
}
|
||||||
|
window.addEventListener('unreadMessage', handler)
|
||||||
|
return () => window.removeEventListener('unreadMessage', handler)
|
||||||
|
}
|
||||||
|
|
||||||
// 等待Service Worker准备就绪
|
// 等待Service Worker准备就绪
|
||||||
export async function waitForServiceWorker(): Promise<ServiceWorker | null> {
|
export async function waitForServiceWorker(): Promise<ServiceWorker | null> {
|
||||||
if (!('serviceWorker' in navigator)) {
|
if (!('serviceWorker' in navigator)) {
|
||||||
@@ -50,43 +71,31 @@ export async function waitForServiceWorker(): Promise<ServiceWorker | null> {
|
|||||||
// 应用启动时检查未读消息数量
|
// 应用启动时检查未读消息数量
|
||||||
export async function checkUnreadOnStartup(): Promise<number> {
|
export async function checkUnreadOnStartup(): Promise<number> {
|
||||||
try {
|
try {
|
||||||
// 对于PWA应用,冷启动时需要更长的等待时间
|
// 检查Service Worker是否可用
|
||||||
const isPWAColdStart = !navigator.serviceWorker.controller
|
if (!('serviceWorker' in navigator) || !navigator.serviceWorker.controller) {
|
||||||
const initialDelay = isPWAColdStart ? 3000 : 1000
|
|
||||||
|
|
||||||
// 初始延迟,等待应用完全启动
|
|
||||||
await new Promise(resolve => setTimeout(resolve, initialDelay))
|
|
||||||
|
|
||||||
// 等待Service Worker准备就绪
|
|
||||||
const sw = await waitForServiceWorker()
|
|
||||||
if (!sw) {
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 额外延迟确保Service Worker完全准备好
|
// 获取未读消息数量
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
const unreadCount = await getUnreadCount()
|
||||||
|
return unreadCount
|
||||||
// 重试机制获取未读消息数量
|
|
||||||
for (let i = 0; i < 5; i++) {
|
|
||||||
// 增加重试次数
|
|
||||||
try {
|
|
||||||
const unreadCount = await getUnreadCount()
|
|
||||||
if (unreadCount >= 0) {
|
|
||||||
// 确保返回有效数字
|
|
||||||
return unreadCount
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (i === 4) throw error // 最后一次重试失败则抛出错误
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) // 递增等待时间
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 应用启动检查并触发事件
|
||||||
|
export async function checkAndEmitUnreadMessages() {
|
||||||
|
try {
|
||||||
|
const count = await checkUnreadOnStartup()
|
||||||
|
if (count > 0) {
|
||||||
|
emitUnreadMessageEvent(count)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 静默处理错误
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 清除桌面图标徽章
|
// 清除桌面图标徽章
|
||||||
export async function clearAppBadge(): Promise<boolean> {
|
export async function clearAppBadge(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user