diff --git a/package.json b/package.json index ee40bc8a..02d4eac8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "moviepilot", - "version": "2.6.2", + "version": "2.6.3", "private": true, "type": "module", "bin": "dist/service.js", diff --git a/src/App.vue b/src/App.vue index 3b599fe0..21339d45 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,6 +9,7 @@ import { SupportedLocale } from '@/types/i18n' import { checkAndEmitUnreadMessages } from '@/utils/badge' import { preloadImage } from './@core/utils/image' import { globalLoadingStateManager } from '@/utils/loadingStateManager' +import { addBackgroundTimer, removeBackgroundTimer } from '@/utils/backgroundManager' // 生效主题 const { global: globalTheme } = useTheme() @@ -34,7 +35,6 @@ const loginStateKey = computed(() => (isLogin.value ? 'logged-in' : 'logged-out' const backgroundImages = ref([]) const activeImageIndex = ref(0) const isTransparentTheme = computed(() => globalTheme.name.value === 'transparent') -let backgroundRotationTimer: NodeJS.Timeout | null = null @@ -102,23 +102,37 @@ async function fetchBackgroundImages() { } } +// 背景图片轮换函数 +function rotateBackgroundImage() { + if (backgroundImages.value.length > 1) { + // 计算下一个图片索引 + const nextIndex = (activeImageIndex.value + 1) % backgroundImages.value.length + // 预加载下一张图片 + preloadImage(backgroundImages.value[nextIndex]).then(success => { + // 只有图片成功加载才切换 + if (success) { + activeImageIndex.value = nextIndex + } + }) + } +} + // 开始背景图片轮换 function startBackgroundRotation() { - // 清除轮换定时器 - if (backgroundRotationTimer) clearInterval(backgroundRotationTimer) + // 清除现有定时器 + removeBackgroundTimer('background-rotation') + if (backgroundImages.value.length > 1) { - // 每10秒切换一次 - backgroundRotationTimer = setInterval(() => { - // 计算下一个图片索引 - const nextIndex = (activeImageIndex.value + 1) % backgroundImages.value.length - // 预加载下一张图片 - preloadImage(backgroundImages.value[nextIndex]).then(success => { - // 只有图片成功加载才切换 - if (success) { - activeImageIndex.value = nextIndex - } - }) - }, 10000) + // 使用优化的定时器管理器,后台时自动暂停 + addBackgroundTimer( + 'background-rotation', + rotateBackgroundImage, + 10000, // 每10秒切换一次 + { + runInBackground: false, // 后台时不运行 + skipInitialRun: true // 不需要立即执行 + } + ) } } @@ -220,11 +234,8 @@ onMounted(async () => { }) onUnmounted(() => { - // 清除轮换定时器 - if (backgroundRotationTimer) { - clearInterval(backgroundRotationTimer) - backgroundRotationTimer = null - } + // 清除背景轮换定时器 + removeBackgroundTimer('background-rotation') }) diff --git a/src/components/cards/DownloaderCard.vue b/src/components/cards/DownloaderCard.vue index 5f1e09a0..99ba6b4b 100644 --- a/src/components/cards/DownloaderCard.vue +++ b/src/components/cards/DownloaderCard.vue @@ -11,12 +11,14 @@ import { cloneDeep } from 'lodash-es' import { useI18n } from 'vue-i18n' import { downloaderDict } from '@/api/constants' import { useDisplay } from 'vuetify' +import { useBackgroundOptimization } from '@/composables/useBackgroundOptimization' // 显示器宽度 const display = useDisplay() // 获取i18n实例 const { t } = useI18n() +const { useConditionalDataRefresh } = useBackgroundOptimization() // 定义输入 const props = defineProps({ @@ -43,9 +45,6 @@ const emit = defineEmits(['close', 'done', 'change']) // 提示框 const $toast = useToast() -// timeout定时器 -let timeoutTimer: NodeJS.Timeout | undefined = undefined - // 上传速率 const upload_rate = ref(0) @@ -64,9 +63,15 @@ const downloaderInfo = ref({ config: {}, }) +// 下载器是否应该刷新数据的计算属性 +const shouldRefresh = computed(() => props.allowRefresh && props.downloader.enabled) + // 调用API查询下载器数据 async function loadDownloaderInfo() { - if (!props.allowRefresh) { + if (!shouldRefresh.value) { + // 当下载器被禁用时,重置速率数据 + upload_rate.value = 0 + download_rate.value = 0 return } try { @@ -79,11 +84,6 @@ async function loadDownloaderInfo() { if (res) { upload_rate.value = res.upload_speed download_rate.value = res.download_speed - // 定时查询 - clearTimeout(timeoutTimer) - if (props.downloader.enabled) { - timeoutTimer = setTimeout(loadDownloaderInfo, 3000) - } } } catch (e) { console.log(e) @@ -141,14 +141,17 @@ function onClose() { emit('close') } -onMounted(async () => { - if (props.downloader.enabled) { - await loadDownloaderInfo() - } -}) +// 使用条件性数据刷新定时器(只在下载器启用时运行) +const { stop: stopRefresh } = useConditionalDataRefresh( + `downloader-${props.downloader.name}`, + loadDownloaderInfo, + shouldRefresh, // 响应式条件:只有当allowRefresh为true且downloader启用时才运行 + 3000, // 3秒间隔 + true // 立即执行一次 +) onUnmounted(() => { - if (timeoutTimer) clearTimeout(timeoutTimer) + stopRefresh() })