"use client" import * as React from "react" import { useTranslations } from "next-intl" import { toast } from "sonner" import { School, Shield, Database, Bell, Loader2 } from "lucide-react" import { getAdminSystemSettingsAction, saveAdminSystemSettingsAction, } from "@/modules/settings/actions-system-settings" import { Button } from "@/shared/components/ui/button" import { Input } from "@/shared/components/ui/input" import { Label } from "@/shared/components/ui/label" import { Textarea } from "@/shared/components/ui/textarea" import { Switch } from "@/shared/components/ui/switch" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Separator } from "@/shared/components/ui/separator" interface AdminSettingsFormValues { schoolInfo: { schoolName: string schoolCode: string schoolPhone: string schoolEmail: string schoolAddress: string schoolDescription: string } securityPolicy: { passwordMinLength: number sessionTimeout: number requireSpecialChar: boolean requireUppercase: boolean forcePasswordChange: boolean } fileUpload: { maxFileSize: number allowedTypes: string } notificationConfig: { notifyNewUser: boolean notifyScheduleChange: boolean notifyAnnouncement: boolean } } const DEFAULT_VALUES: AdminSettingsFormValues = { schoolInfo: { schoolName: "", schoolCode: "", schoolPhone: "", schoolEmail: "", schoolAddress: "", schoolDescription: "", }, securityPolicy: { passwordMinLength: 8, sessionTimeout: 60, requireSpecialChar: true, requireUppercase: false, forcePasswordChange: true, }, fileUpload: { maxFileSize: 10, allowedTypes: "jpg,png,pdf,docx,xlsx,pptx", }, notificationConfig: { notifyNewUser: true, notifyScheduleChange: true, notifyAnnouncement: false, }, } /** * 管理员系统设置视图 * * 通过 Server Actions 加载和保存系统设置,数据持久化到 system_settings 表。 * 4 个 Card:学校信息 / 安全策略 / 文件上传 / 通知配置。 * 所有文本通过 settings.admin.* i18n 键获取。 */ export function AdminSettingsView(): React.ReactElement { const t = useTranslations("settings.admin") const [values, setValues] = React.useState(DEFAULT_VALUES) const [loadedValues, setLoadedValues] = React.useState(DEFAULT_VALUES) const [loading, setLoading] = React.useState(true) const [saving, setSaving] = React.useState(false) React.useEffect(() => { let cancelled = false async function load(): Promise { try { const result = await getAdminSystemSettingsAction() if (!cancelled && result.success && result.data) { setValues(result.data) setLoadedValues(result.data) } } catch { // 加载失败时使用默认值 } finally { if (!cancelled) setLoading(false) } } void load() return () => { cancelled = true } }, []) // dirty 检测:当前值与加载值不一致时为 dirty const isDirty = React.useMemo( () => JSON.stringify(values) !== JSON.stringify(loadedValues), [values, loadedValues], ) const handleSave = async (e: React.FormEvent): Promise => { e.preventDefault() if (!isDirty) return setSaving(true) try { const result = await saveAdminSystemSettingsAction(values) if (result.success) { toast.success(t("saveSuccess")) setLoadedValues(values) } else { toast.error(result.message || t("saveFailure")) } } catch { toast.error(t("saveFailure")) } finally { setSaving(false) } } const handleReset = (): void => { setValues(loadedValues) } const updateSchoolInfo = (key: keyof AdminSettingsFormValues["schoolInfo"], value: string): void => { setValues((prev) => ({ ...prev, schoolInfo: { ...prev.schoolInfo, [key]: value } })) } const updateSecurityPolicy = ( key: keyof AdminSettingsFormValues["securityPolicy"], value: number | boolean ): void => { setValues((prev) => ({ ...prev, securityPolicy: { ...prev.securityPolicy, [key]: value } })) } const updateFileUpload = ( key: keyof AdminSettingsFormValues["fileUpload"], value: number | string ): void => { setValues((prev) => ({ ...prev, fileUpload: { ...prev.fileUpload, [key]: value } })) } const updateNotificationConfig = ( key: keyof AdminSettingsFormValues["notificationConfig"], value: boolean ): void => { setValues((prev) => ({ ...prev, notificationConfig: { ...prev.notificationConfig, [key]: value } })) } if (loading) { return (
) } return (

{t("title")}

{t("description")}

{/* 学校信息 */}
{t("schoolInfo.title")} {t("schoolInfo.description")}
updateSchoolInfo("schoolName", e.target.value)} />
updateSchoolInfo("schoolCode", e.target.value)} />
updateSchoolInfo("schoolPhone", e.target.value)} />
updateSchoolInfo("schoolEmail", e.target.value)} />
updateSchoolInfo("schoolAddress", e.target.value)} />