- 新增 SettingsService 接口 + Context 注入,组件层不再直接 import users/messaging actions - 新增 resolveRoleSettingsConfig 配置驱动角色路由,删除 parent/student/teacher-settings-view 冗余文件 - 新增 SettingsSectionErrorBoundary,每个 TabsContent + profile 角色概览区块均包裹 - 新增 ProfileStudentOverview/ProfileTeacherOverview 异步 Server Component + 骨架屏,支持流式渲染 - 抽取 buildStudentOverviewData 等纯函数到 lib/student-overview-data.ts,便于单元测试 - 新增 settings.json 翻译文件(zh-CN + en),所有组件改用 useTranslations/getTranslations - 重构 profile/page.tsx:i18n 适配 + Suspense 分区加载 + 业务逻辑抽离 - 同步更新架构图 004/005
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
import { redirect } from "next/navigation"
|
||
import { getTranslations } from "next-intl/server"
|
||
|
||
import { requireAuth } from "@/shared/lib/auth-guard"
|
||
import { SettingsView } from "@/modules/settings/components/settings-view"
|
||
import { SettingsServiceProvider } from "@/modules/settings/components/settings-service-context"
|
||
import { resolveRoleSettingsConfig } from "@/modules/settings/config/role-settings-config"
|
||
import type { SettingsService } from "@/modules/settings/types"
|
||
import { getUserProfile } from "@/modules/users/data-access"
|
||
import { updateUserProfile } from "@/modules/users/actions"
|
||
import { getNotificationPreferences } from "@/modules/notifications/preferences"
|
||
import { updateNotificationPreferencesAction } from "@/modules/messaging/actions"
|
||
import type { UpdateNotificationPreferencesInput } from "@/modules/notifications/types"
|
||
|
||
export const dynamic = "force-dynamic"
|
||
|
||
export const metadata = {
|
||
title: "Settings",
|
||
}
|
||
|
||
/**
|
||
* 将通知偏好输入对象转换为 FormData,适配 updateNotificationPreferencesAction 的签名。
|
||
* Action 内部通过 formData.get(key) === "on" 解析布尔值。
|
||
*/
|
||
function buildNotificationFormData(input: UpdateNotificationPreferencesInput): FormData {
|
||
const formData = new FormData()
|
||
const booleanFields: Array<keyof UpdateNotificationPreferencesInput> = [
|
||
"emailEnabled",
|
||
"smsEnabled",
|
||
"pushEnabled",
|
||
"homeworkNotifications",
|
||
"gradeNotifications",
|
||
"announcementNotifications",
|
||
"messageNotifications",
|
||
"attendanceNotifications",
|
||
"quietHoursEnabled",
|
||
]
|
||
for (const field of booleanFields) {
|
||
const value = input[field]
|
||
if (value === true) formData.set(field, "on")
|
||
}
|
||
if (input.quietHoursStart) formData.set("quietHoursStart", input.quietHoursStart)
|
||
if (input.quietHoursEnd) formData.set("quietHoursEnd", input.quietHoursEnd)
|
||
return formData
|
||
}
|
||
|
||
export default async function SettingsPage() {
|
||
const ctx = await requireAuth()
|
||
|
||
const userId = ctx.userId
|
||
const userProfile = await getUserProfile(userId)
|
||
|
||
if (!userProfile) redirect("/login")
|
||
|
||
const roles = ctx.roles
|
||
const notificationPrefs = await getNotificationPreferences(userId)
|
||
const t = await getTranslations("settings")
|
||
|
||
const config = resolveRoleSettingsConfig(roles)
|
||
const description = t(config?.descriptionKey ?? "title")
|
||
const backHref = config?.backHref ?? "/dashboard"
|
||
const generalExtra = config?.generalExtra
|
||
|
||
// 构建 SettingsService 实现,注入到 SettingsServiceProvider
|
||
// 组件层通过 useSettingsService() 消费,不直接 import users/messaging actions
|
||
const service: SettingsService = {
|
||
profile: {
|
||
getProfile: async () => getUserProfile(userId),
|
||
updateProfile: async (input) => updateUserProfile(input),
|
||
},
|
||
notifications: {
|
||
getPreferences: async () => getNotificationPreferences(userId),
|
||
updatePreferences: async (input) =>
|
||
updateNotificationPreferencesAction(null, buildNotificationFormData(input)),
|
||
},
|
||
}
|
||
|
||
return (
|
||
<SettingsServiceProvider service={service}>
|
||
<SettingsView
|
||
description={description}
|
||
backHref={backHref}
|
||
user={userProfile}
|
||
notificationPreferences={notificationPrefs}
|
||
generalExtra={generalExtra}
|
||
/>
|
||
</SettingsServiceProvider>
|
||
)
|
||
}
|