diff --git a/src/components/cache/TmdbRecognitionCachePanel.vue b/src/components/cache/TmdbRecognitionCachePanel.vue index 9e4b7740..24c94d82 100644 --- a/src/components/cache/TmdbRecognitionCachePanel.vue +++ b/src/components/cache/TmdbRecognitionCachePanel.vue @@ -9,6 +9,10 @@ import { useGlobalSettingsStore } from '@/stores' import { getDisplayImageUrl } from '@/utils/imageUtils' type RecognitionStatusFilter = 'all' | 'recognized' | 'unrecognized' +type InfiniteScrollStatus = 'ok' | 'empty' | 'loading' | 'error' + +const MOBILE_CACHE_PAGE_SIZE = 20 +const MOBILE_CACHE_ITEM_HEIGHT = 144 const { t } = useI18n() const display = useDisplay() @@ -28,6 +32,8 @@ const cacheData = ref({ unrecognized: 0, data: [], }) +const mobileVisibleCount = ref(MOBILE_CACHE_PAGE_SIZE) +const mobileInfiniteKey = ref(0) const statusOptions = computed(() => [ { title: t('setting.cache.allStatuses'), value: 'all' }, @@ -58,6 +64,31 @@ const filteredData = computed(() => { }) }) +const mobileVisibleData = computed(() => filteredData.value.slice(0, mobileVisibleCount.value)) +const mobileHasMore = computed(() => mobileVisibleData.value.length < filteredData.value.length) + +/** 重置移动端分页,让筛选或刷新后的识别缓存从第一页开始展示。 */ +function resetMobilePagination() { + mobileVisibleCount.value = MOBILE_CACHE_PAGE_SIZE + mobileInfiniteKey.value++ +} + +/** 追加移动端下一页识别缓存,并由虚拟滚动限制实际渲染节点。 */ +function loadMoreMobileCache({ done }: { done: (status: InfiniteScrollStatus) => void }) { + if (loading.value) { + done('ok') + return + } + + if (!mobileHasMore.value) { + done('empty') + return + } + + mobileVisibleCount.value = Math.min(mobileVisibleCount.value + MOBILE_CACHE_PAGE_SIZE, filteredData.value.length) + done(mobileHasMore.value ? 'ok' : 'empty') +} + /** 加载 TheMovieDb 识别缓存列表。 */ async function loadCacheData(showSuccess = false) { try { @@ -65,6 +96,7 @@ async function loadCacheData(showSuccess = false) { const response = (await api.get('tmdb/cache')) as unknown as ApiResponse cacheData.value = response.data ?? { count: 0, recognized: 0, unrecognized: 0, data: [] } selectedItems.value = selectedItems.value.filter(key => cacheData.value.data.some(item => item.key === key)) + resetMobilePagination() if (showSuccess) $toast.success(t('setting.cache.listRefreshSuccess')) } catch (error) { console.error(error) @@ -172,6 +204,10 @@ function getRecognitionStatusLabel(item: TmdbRecognitionCacheItem): string { onMounted(() => { void loadCacheData() }) + +watch([searchFilter, statusFilter], () => { + resetMobilePagination() +})