From 660338688a16a6abeb52c2f9f39a687ea814260c Mon Sep 17 00:00:00 2001 From: jxxghp Date: Wed, 8 Apr 2026 13:47:04 +0800 Subject: [PATCH] refactor: adjust TransferHistoryView layout offset and apply code style improvements --- src/composables/useAvailableHeight.ts | 24 ++++----- src/views/reorganize/TransferHistoryView.vue | 54 +++++++++++--------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/composables/useAvailableHeight.ts b/src/composables/useAvailableHeight.ts index 2072b0ea..60fa7ed8 100644 --- a/src/composables/useAvailableHeight.ts +++ b/src/composables/useAvailableHeight.ts @@ -1,4 +1,4 @@ -import { computed, ref, onMounted, onUnmounted } from 'vue' +import { computed, ref, watch, onMounted, onUnmounted, nextTick } from 'vue' import { usePWA } from '@/composables/usePWA' /** @@ -35,19 +35,19 @@ export function useAvailableHeight( layoutPaddingBottom.value = parseFloat(style.paddingBottom) || 24 } - // 测量 Footer Dock 的实际高度 - // .footer-nav-container 是 position:fixed, padding-block-end 含 env(safe-area-inset-bottom) - // offsetHeight 是元素自身的渲染高度(含 padding),即 Dock 遮挡的区域大小 - if (appMode.value) { - const footerEl = document.querySelector('.footer-nav-container') as HTMLElement | null - footerDockMeasuredHeight.value = footerEl ? footerEl.offsetHeight : 70 - } else { - footerDockMeasuredHeight.value = 0 - } + // 直接查询 Footer Dock DOM,无论 appMode 状态 + // Dock 通过 Teleport 挂载到 body,存在即测量,不存在即为 0 + const footerEl = document.querySelector('.footer-nav-container') as HTMLElement | null + footerDockMeasuredHeight.value = footerEl ? footerEl.offsetHeight : 0 } + // appMode 异步变化时(PWA 检测完成、屏幕尺寸变化等),Dock 会出现/消失 + // 需要等 DOM 更新后重新测量 + watch(appMode, () => { + nextTick(updateMeasurements) + }) + onMounted(() => { - // 初始测量(nextTick 确保 DOM 已渲染) nextTick(updateMeasurements) window.addEventListener('resize', updateMeasurements) @@ -72,7 +72,7 @@ export function useAvailableHeight( // 布局底部 padding const bottomPadding = layoutPaddingBottom.value - // 底部 Dock 栏遮挡高度(appMode 下通过 DOM 测量,含 safe-area-inset-bottom) + // 底部 Dock 栏遮挡高度(通过 DOM 测量,含 safe-area-inset-bottom) const footerDockHeight = footerDockMeasuredHeight.value const available = vh - topPadding - bottomPadding - footerDockHeight - componentOffset diff --git a/src/views/reorganize/TransferHistoryView.vue b/src/views/reorganize/TransferHistoryView.vue index fbeb0148..d26bdc72 100644 --- a/src/views/reorganize/TransferHistoryView.vue +++ b/src/views/reorganize/TransferHistoryView.vue @@ -23,8 +23,8 @@ const display = useDisplay() const { appMode } = usePWA() // 计算列表可用高度 -// componentOffset = VCardItem搜索栏(80) + VDivider(1) + 分页栏(52) + VCard边距(4) = 137 -const { availableHeight } = useAvailableHeight(137, 300) +// componentOffset = VCardItem搜索栏(68) + VDivider(1) + 分页栏(40) + VCard边距(2) = 111 +const { availableHeight } = useAvailableHeight(125, 300) // 提示框 const $toast = useToast() @@ -51,21 +51,21 @@ const redoTargetStorage = ref() // 已选中的数据 const selected = ref([]) -const getNum = (s?: string) => (s ? parseInt(s.replace(/[^0-9]/g, ''), 10) || 0 : 0); +const getNum = (s?: string) => (s ? parseInt(s.replace(/[^0-9]/g, ''), 10) || 0 : 0) function sortByTitle(a: TransferHistory, b: TransferHistory) { if (a.type !== b.type) { - return (a.type ?? '').localeCompare(b.type ?? ''); + return (a.type ?? '').localeCompare(b.type ?? '') } if (a.title !== b.title) { - return (a.title ?? '').toLocaleLowerCase().localeCompare((b.title ?? '').toLocaleLowerCase()); + return (a.title ?? '').toLocaleLowerCase().localeCompare((b.title ?? '').toLocaleLowerCase()) } if (a.type === '电视剧') { if (a.seasons !== b.seasons) { - return getNum(a.seasons) - getNum(b.seasons); + return getNum(a.seasons) - getNum(b.seasons) } if (a.episodes !== b.episodes) { - return getNum(a.episodes) - getNum(b.episodes); + return getNum(a.episodes) - getNum(b.episodes) } } return 0 @@ -231,10 +231,13 @@ async function loadStorages() { // 存储字典 const storageDict = computed(() => { - return storages.value.reduce((dict, item) => { - dict[item.type] = item.name - return dict - }, {} as Record) + return storages.value.reduce( + (dict, item) => { + dict[item.type] = item.name + return dict + }, + {} as Record, + ) }) // 转移方式字典 @@ -247,8 +250,6 @@ const TransferDict: { [key: string]: string } = { rclone_move: t('transferHistory.transferMode.rclone_move'), } - - // 分页提示 const pageTip = computed(() => { const begin = itemsPerPage.value * (currentPage.value - 1) + 1 @@ -488,23 +489,26 @@ function ensureNumber(value: any, defaultValue: number = 0) { // 按标题分组后的选中数量统计,键为标题,值为对应分组的选中数 const selectedCountsGroupedByTitle = computed(() => { - return selected.value.reduce((acc, item) => { - const title = item.title || ''; - acc[title] = (acc[title] || 0) + 1; - return acc; - }, {} as Record); -}); + return selected.value.reduce( + (acc, item) => { + const title = item.title || '' + acc[title] = (acc[title] || 0) + 1 + return acc + }, + {} as Record, + ) +}) // 控制分组内所有子项的选中状态 const toggleGroupSelection = (checked: boolean | null, items: readonly any[]) => { - const values = items.map(item => item.value); + const values = items.map(item => item.value) if (checked) { - selected.value = [...new Set([...selected.value, ...values])]; + selected.value = [...new Set([...selected.value, ...values])] } else { - const itemsSet = new Set(values); - selected.value = selected.value.filter(item => !itemsSet.has(item)); + const itemsSet = new Set(values) + selected.value = selected.value.filter(item => !itemsSet.has(item)) } -}; +} // 初始加载数据 onMounted(() => { @@ -579,7 +583,7 @@ onMounted(() => { {{ item.value }}