🎨 统一后台分页与设置页布局

This commit is contained in:
2026-06-05 15:23:25 +08:00
parent a66a0b6a77
commit f7108f5b44
5 changed files with 58 additions and 58 deletions
+1 -1
View File
@@ -97,7 +97,7 @@ interface Props {
}
const props = withDefaults(defineProps<Props>(), {
pageSizeOptions: () => [10, 20, 50, 100]
pageSizeOptions: () => [5, 10, 20, 50, 100]
})
defineEmits<{
+10 -7
View File
@@ -81,6 +81,8 @@ const legacyForeverExpiresAt = '2099-12-31T23:59'
const detailPolicyDownloadLimit = 5
const hourInMilliseconds = 60 * 60 * 1000
const dayInMilliseconds = 24 * 60 * 60 * 1000
const adminPageSizeOptions = [5, 10, 20, 50, 100] as const
const defaultAdminPageSize = 10
type DetailPolicyActionOption = {
action: AdminFilePolicyAction
@@ -167,8 +169,10 @@ const normalizePresetChoice = <T extends string>(
const normalizePresetSize = (value: unknown) => {
const normalizedSize = Number(value)
if (!Number.isFinite(normalizedSize)) return 10
return Math.min(Math.max(Math.trunc(normalizedSize), 1), 100)
const pageSize = Number.isFinite(normalizedSize) ? Math.trunc(normalizedSize) : defaultAdminPageSize
return adminPageSizeOptions.includes(pageSize as (typeof adminPageSizeOptions)[number])
? pageSize
: defaultAdminPageSize
}
const buildDefaultViewPresetParams = (): AdminFileViewPresetParams => ({
@@ -178,7 +182,7 @@ const buildDefaultViewPresetParams = (): AdminFileViewPresetParams => ({
health: 'all',
sortBy: 'created_at',
sortOrder: 'desc',
size: 10
size: defaultAdminPageSize
})
const normalizeViewPresetParams = (params: unknown): AdminFileViewPresetParams => {
@@ -218,7 +222,7 @@ export function useAdminFiles() {
const summary = ref<AdminFileSummary>(emptySummary())
const params = ref<AdminFileListParams & { total: number }>({
page: 1,
size: 10,
size: defaultAdminPageSize,
total: 0,
keyword: '',
status: 'all',
@@ -311,7 +315,7 @@ export function useAdminFiles() {
health: params.value.health || 'all',
sortBy: params.value.sortBy || 'created_at',
sortOrder: params.value.sortOrder || 'desc',
size: params.value.size || 10
size: params.value.size || defaultAdminPageSize
})
const buildBuiltInViewPreset = (
@@ -1204,8 +1208,7 @@ export function useAdminFiles() {
}
const handlePageSizeChange = async (size: number) => {
if (!Number.isFinite(size) || size < 1) return
params.value.size = Math.min(Math.trunc(size), 100)
params.value.size = normalizePresetSize(size)
params.value.page = 1
markViewPresetDirty()
await loadFiles()
+2 -2
View File
@@ -89,10 +89,10 @@
<div class="flex h-full min-h-0 min-w-0 flex-1 flex-col">
<!-- Header -->
<header
class="shadow-md border-b transition-colors duration-300 h-16"
class="h-14 border-b shadow-md transition-colors duration-300 lg:hidden"
:class="[isDarkMode ? 'bg-[#1a2930] border-[#31454d]' : 'bg-[#f2f6f5] border-[#c8d7da]']"
>
<div class="flex items-center justify-between h-16 px-4">
<div class="flex h-14 items-center justify-between px-4">
<button @click="toggleSidebar" class="lg:hidden">
<MenuIcon class="w-6 h-6" :class="[isDarkMode ? 'text-gray-400' : 'text-gray-600']" />
</button>
+1 -1
View File
@@ -707,7 +707,7 @@
:current-page="historyPage"
:page-size="historyPageSize"
:total="historyRows.length"
:page-size-options="[5, 10, 20, 50]"
:page-size-options="[5, 10, 20, 50, 100]"
@page-change="historyPage = $event"
@page-size-change="handleHistoryPageSizeChange"
/>
+21 -24
View File
@@ -31,47 +31,35 @@ onMounted(() => {
<template>
<div class="p-6">
<div
class="sticky top-0 z-20 -mx-6 -mt-6 mb-6 border-b px-6 py-4 backdrop-blur"
:class="[isDarkMode ? 'border-gray-700 bg-gray-900/85' : 'border-gray-200 bg-gray-50/90']"
class="mb-6 flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between"
>
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-2xl font-bold" :class="[isDarkMode ? 'text-white' : 'text-gray-800']">
<h2 class="text-2xl font-bold" :class="[isDarkMode ? 'text-white' : 'text-[#2d4650]']">
{{ t('admin.settings.title') }}
</h2>
<p
class="mt-1 text-sm"
:class="[isDirty ? 'text-amber-500' : isDarkMode ? 'text-gray-400' : 'text-gray-500']"
:class="[isDirty ? 'text-amber-500' : isDarkMode ? 'text-gray-400' : 'text-[#586f75]']"
>
{{
isDirty ? t('manage.settings.unsavedChanges') : t('manage.settings.allChangesSaved')
}}
{{ isDirty ? t('manage.settings.unsavedChanges') : t('manage.settings.allChangesSaved') }}
</p>
</div>
<div class="flex flex-wrap items-center gap-3">
<div class="flex flex-wrap items-center gap-2">
<BaseButton
variant="secondary"
:loading="isRefreshing"
:disabled="isSaving || isDirty"
:title="
isDirty ? t('manage.settings.refreshBlocked') : t('manage.settings.refreshConfig')
"
:title="isDirty ? t('manage.settings.refreshBlocked') : t('manage.settings.refreshConfig')"
@click="refreshConfig"
>
<template #icon>
<RefreshCwIcon class="mr-2 h-4 w-4" />
</template>
{{
isRefreshing ? t('manage.settings.refreshing') : t('manage.settings.refreshConfig')
}}
{{ isRefreshing ? t('manage.settings.refreshing') : t('manage.settings.refreshConfig') }}
</BaseButton>
<BaseButton
:loading="isSaving"
:disabled="!isDirty || isRefreshing"
@click="submitConfig"
>
<BaseButton :loading="isSaving" :disabled="!isDirty || isRefreshing" @click="submitConfig">
<template #icon>
<SaveIcon class="mr-2 h-4 w-4" />
</template>
@@ -79,11 +67,14 @@ onMounted(() => {
</BaseButton>
</div>
</div>
</div>
<div
class="space-y-6 rounded-lg shadow-md p-6"
:class="[isDarkMode ? 'bg-gray-800 bg-opacity-70' : 'bg-white']"
class="theme-2026-card theme-2026-card-hover space-y-8 rounded-[30px] border p-6 shadow-md transition-all duration-200 hover:-translate-y-0.5 hover:shadow-lg"
:class="[
isDarkMode
? 'border-[#40545c] bg-[#202f36]/90 hover:border-[#7199a8] hover:bg-[#263941] hover:shadow-black/25'
: 'border-[#d7e3e5] bg-[#f8fbfb] hover:border-[#8fb2bf] hover:shadow-[#a9bdc2]/70'
]"
>
<!-- 基本设置 -->
<section class="space-y-4">
@@ -714,4 +705,10 @@ onMounted(() => {
</div>
</div>
</template>
<style scoped></style>
<style scoped>
:deep(input:not([type='checkbox'])),
:deep(select),
:deep(textarea) {
border-radius: 30px;
}
</style>