style: 优化设置界面布局,添加导航栏

This commit is contained in:
Baobhan Sith
2025-05-13 08:32:55 +08:00
parent ed415a5bd2
commit 83e3d8e043
5 changed files with 197 additions and 50 deletions
+62 -36
View File
@@ -1,68 +1,82 @@
<template>
<div class="p-4 bg-background text-foreground min-h-screen"> <!-- Outer container -->
<div class="max-w-7xl mx-auto"> <!-- Inner container for max-width -->
<h1 class="text-2xl font-semibold text-foreground mb-6 pb-3 border-b border-border"> <!-- Main Title -->
{{ $t('settings.title') }}
</h1>
<!-- Tabs Navigation -->
<div class="mb-6 flex space-x-1 sticky top-0 bg-background z-10 py-2">
<button
v-for="tab in tabs"
:key="tab.key"
@click="activeTab = tab.key"
:class="['px-4 py-2 text-sm font-medium rounded-md focus:outline-none transition-colors duration-150 ease-in-out',
activeTab === tab.key ? 'bg-primary text-white' : 'text-muted-foreground hover:bg-muted/50 hover:text-foreground']"
>
{{ tab.label }}
</button>
</div>
<!-- Error state (Show first if error exists) -->
<div v-if="settingsError" class="p-4 mb-4 border-l-4 border-error bg-error/10 text-error rounded">
{{ settingsError }}
</div>
<!-- Settings Sections Grid (Render grid structure always if no error) -->
<div v-else class="grid grid-cols-1 lg:grid-cols-2 gap-6"> <!-- Changed to 2 columns on large screens -->
<!-- Removed global loading state, content will show/hide based on individual loading states -->
<!-- Column 1: Security -->
<div class="space-y-6"> <!-- Removed col-span -->
<!-- Security Sections: Only show if settings data is loaded -->
<!-- Settings Content based on activeTab -->
<div v-else class="space-y-6">
<!-- Security Tab Content -->
<div v-if="activeTab === 'security'">
<div v-if="settings" class="bg-background border border-border rounded-lg shadow-sm overflow-hidden">
<h2 class="text-lg font-semibold text-foreground px-6 py-4 border-b border-border bg-header/50">{{ $t('settings.category.security') }}</h2>
<div class="p-6 space-y-6">
<!-- Change Password -->
<ChangePasswordForm />
<hr class="border-border/50">
<!-- Passkey Management -->
<PasskeyManagement />
<hr class="border-border/50">
<!-- 2FA -->
<TwoFactorAuthSettings />
<hr class="border-border/50"> <!-- Separator -->
<!-- CAPTCHA Settings -->
<hr class="border-border/50">
<CaptchaSettingsForm />
</div>
</div>
<div v-else class="p-4 text-center text-muted-foreground">{{ $t('settings.loading', '加载中...') }}</div>
</div>
<!-- IP Whitelist Section: Only show if settings data is loaded -->
<div v-if="settings" class="bg-background border border-border rounded-lg shadow-sm overflow-hidden">
<!-- IP Control Tab Content -->
<div v-if="activeTab === 'ipControl'">
<div v-if="settings" class="bg-background border border-border rounded-lg shadow-sm overflow-hidden mb-6">
<h2 class="text-lg font-semibold text-foreground px-6 py-4 border-b border-border bg-header/50">{{ $t('settings.ipWhitelist.title') }}</h2>
<div class="p-6 space-y-6">
<IpWhitelistSettings />
</div>
</div>
<!-- IP Blacklist Section: Only show if settings data is loaded (as config depends on it) -->
<IpBlacklistSettings v-if="settings" />
<div v-else-if="!settings && activeTab === 'ipControl'" class="p-4 text-center text-muted-foreground">{{ $t('settings.loading', '加载中...') }}</div>
</div>
<!-- Workspace Tab Content -->
<div v-if="activeTab === 'workspace'">
<WorkspaceSettingsSection v-if="settings" />
<div v-else class="p-4 text-center text-muted-foreground">{{ $t('settings.loading', '加载中...') }}</div>
</div>
<!-- About Section -->
<AboutSection />
</div>
<!-- Column 2: Appearance, Workspace, System -->
<div class="space-y-6"> <!-- Removed col-span -->
<!-- System Tab Content -->
<div v-if="activeTab === 'system'">
<SystemSettingsSection v-if="settings" />
<div v-else class="p-4 text-center text-muted-foreground">{{ $t('settings.loading', '加载中...') }}</div>
</div>
<!-- Workspace Section: Only show if settings data is loaded -->
<WorkspaceSettingsSection />
<!-- System Section: Only show if settings data is loaded -->
<SystemSettingsSection />
<!-- Data Management Section (including Export) -->
<DataManagementSection />
<!-- Appearance Section: Only show if settings data is loaded -->
<AppearanceSection />
<!-- Data Management Tab Content -->
<div v-if="activeTab === 'dataManagement'">
<DataManagementSection v-if="settings" />
<div v-else class="p-4 text-center text-muted-foreground">{{ $t('settings.loading', '加载中...') }}</div>
</div>
<!-- Appearance Tab Content -->
<div v-if="activeTab === 'appearance'">
<AppearanceSection v-if="settings" />
<div v-else class="p-4 text-center text-muted-foreground">{{ $t('settings.loading', '加载中...') }}</div>
</div>
<!-- About Tab Content -->
<div v-if="activeTab === 'about'">
<AboutSection />
</div>
</div>
</div>
@@ -70,7 +84,7 @@
</template>
<script setup lang="ts">
import { onMounted } from 'vue'; // Simplified Vue imports
import { onMounted, ref } from 'vue'; // Simplified Vue imports
import { useAuthStore } from '../stores/auth.store';
import { useSettingsStore } from '../stores/settings.store';
import { useAppearanceStore } from '../stores/appearance.store'; // 导入外观 store
@@ -93,6 +107,18 @@ const settingsStore = useSettingsStore();
const appearanceStore = useAppearanceStore(); // 实例化外观 store
const { t } = useI18n();
// Define tabs for settings sections
const tabs = ref([
{ key: 'security', label: t('settings.tabs.security', '安全') },
{ key: 'ipControl', label: t('settings.tabs.ipControl', 'IP 管控') },
{ key: 'workspace', label: t('settings.tabs.workspace', '工作区') },
{ key: 'system', label: t('settings.tabs.system', '系统') },
{ key: 'dataManagement', label: t('settings.tabs.dataManagement', '数据管理') },
{ key: 'appearance', label: t('settings.tabs.appearance', '外观') },
{ key: 'about', label: t('settings.tabs.about', '关于') },
]);
const activeTab = ref(tabs.value[0].key);
// --- Reactive state from store ---
// 使用 storeToRefs 获取响应式 getter,包括 language
const {