"use client" import Link from "next/link" import { useRouter, useSearchParams } from "next/navigation" import { Suspense, type ReactNode } from "react" import { User, Palette, Lock, Bell, Sparkles } from "lucide-react" import { signOut } from "next-auth/react" import { ThemePreferencesCard } from "@/modules/settings/components/theme-preferences-card" import { ProfileSettingsForm } from "@/modules/settings/components/profile-settings-form" import { PasswordChangeForm } from "@/modules/settings/components/password-change-form" import { NotificationPreferencesForm } from "@/modules/settings/components/notification-preferences-form" import { AiProviderSettingsCard } from "@/modules/settings/components/ai-provider-settings-card" import { Button } from "@/shared/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/components/ui/tabs" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/shared/components/ui/alert-dialog" import { UserProfile } from "@/modules/users/data-access" import type { NotificationPreferences } from "@/modules/notifications/types" import { usePermission } from "@/shared/hooks/use-permission" import { Permissions } from "@/shared/types/permissions" interface SettingsViewProps { /** 页面副标题描述 */ description: string /** 返回仪表盘的链接 */ backHref: string /** 当前用户 */ user: UserProfile /** 通知偏好 */ notificationPreferences: NotificationPreferences /** General 标签页中 ProfileSettingsForm 下方的内容(角色专属快捷链接/组织信息等) */ generalExtra?: ReactNode } const VALID_TABS = ["general", "notifications", "appearance", "security", "ai"] as const type TabValue = (typeof VALID_TABS)[number] function isTabValue(value: string | null): value is TabValue { return value !== null && (VALID_TABS as readonly string[]).includes(value) } /** * 统一设置页视图 * * 消除 admin / teacher / student / parent 四个设置视图的重复布局: * - 相同的页面头部(标题 + 描述 + 返回按钮) * - 相同的标签页(General / Notifications / Appearance / Security / AI) * - 相同的 Notifications / Appearance / Security 标签页内容 * - 相同的 Session 卡片(登出) * * 角色差异通过 `description`、`backHref` 和 `generalExtra` 三个 props 注入。 * 当前激活的标签页通过 URL `?tab=` 参数持久化。 */ function SettingsViewInner({ description, backHref, user, notificationPreferences, generalExtra, }: SettingsViewProps) { const router = useRouter() const searchParams = useSearchParams() const { hasPermission } = usePermission() const tabParam = searchParams.get("tab") const activeTab: TabValue = isTabValue(tabParam) ? tabParam : "general" const handleTabChange = (value: string) => { const params = new URLSearchParams(searchParams.toString()) if (value === "general") { params.delete("tab") } else { params.set("tab", value) } const query = params.toString() router.push(query ? `?${query}` : "?", { scroll: false }) } const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE) return (