"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 (

Settings

{description}
General Notifications Appearance Security {canConfigureAi ? ( AI ) : null} {generalExtra} Session Account access and session controls.
Sign out
Return to the login screen.
Confirm sign out Are you sure you want to sign out? You will be returned to the login screen. Cancel signOut({ callbackUrl: "/login" })}> Sign out
{canConfigureAi ? ( ) : null}
) } export function SettingsView(props: SettingsViewProps) { return ( ) }