feat(settings): 设置与个人信息模块审计重构 — i18n + 服务注入解耦 + Error Boundary + 流式渲染

- 新增 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
This commit is contained in:
SpecialX
2026-06-22 16:15:36 +08:00
parent 21c7e65fee
commit 5d42495480
29 changed files with 2445 additions and 1094 deletions

View File

@@ -0,0 +1,84 @@
import type { ReactNode } from "react"
import {
LayoutDashboard,
GraduationCap,
CalendarDays,
ClipboardList,
PenTool,
Library,
FileQuestion,
} from "lucide-react"
import { QuickLinksCard, type QuickLinkItem } from "@/modules/settings/components/quick-links-card"
import type { Role } from "@/shared/types/permissions"
/**
* 角色设置页配置
*
* 通过配置驱动角色 → 设置视图的映射,新增角色只需在此添加条目。
* description/backHref 使用 i18n 键,由消费方翻译。
* 快捷链接的 label 通过 settings.quickLinks 命名空间国际化。
*/
export interface RoleSettingsConfig {
/** i18n 键settings.<role>.description */
descriptionKey: string
backHref: string
/** 角色专属快捷链接区块General 标签页底部) */
generalExtra?: ReactNode
}
const STUDENT_LINKS: QuickLinkItem[] = [
{ href: "/student/dashboard", labelKey: "dashboard", icon: <LayoutDashboard className="h-4 w-4" /> },
{ href: "/student/learning/assignments", labelKey: "assignments", icon: <PenTool className="h-4 w-4" /> },
{ href: "/student/schedule", labelKey: "schedule", icon: <CalendarDays className="h-4 w-4" /> },
]
const PARENT_LINKS: QuickLinkItem[] = [
{ href: "/parent/dashboard", labelKey: "dashboard", icon: <LayoutDashboard className="h-4 w-4" /> },
{ href: "/parent/children", labelKey: "children", icon: <GraduationCap className="h-4 w-4" /> },
{ href: "/parent/grades", labelKey: "grades", icon: <ClipboardList className="h-4 w-4" /> },
{ href: "/parent/attendance", labelKey: "attendance", icon: <CalendarDays className="h-4 w-4" /> },
]
const TEACHER_LINKS: QuickLinkItem[] = [
{ href: "/teacher/dashboard", labelKey: "dashboard", icon: <LayoutDashboard className="h-4 w-4" /> },
{ href: "/teacher/textbooks", labelKey: "textbooks", icon: <Library className="h-4 w-4" /> },
{ href: "/teacher/exams/all", labelKey: "exams", icon: <FileQuestion className="h-4 w-4" /> },
{ href: "/teacher/homework/assignments", labelKey: "homework", icon: <PenTool className="h-4 w-4" /> },
{ href: "/teacher/classes/schedule", labelKey: "schedule", icon: <CalendarDays className="h-4 w-4" /> },
]
export const ROLE_SETTINGS_CONFIG: Partial<Record<Role, RoleSettingsConfig>> = {
admin: {
descriptionKey: "settings.roleDescriptions.admin",
backHref: "/admin/dashboard",
},
teacher: {
descriptionKey: "settings.roleDescriptions.teacher",
backHref: "/teacher/dashboard",
generalExtra: <QuickLinksCard links={TEACHER_LINKS} />,
},
student: {
descriptionKey: "settings.roleDescriptions.student",
backHref: "/student/dashboard",
generalExtra: <QuickLinksCard links={STUDENT_LINKS} />,
},
parent: {
descriptionKey: "settings.roleDescriptions.parent",
backHref: "/parent/dashboard",
generalExtra: <QuickLinksCard links={PARENT_LINKS} />,
},
}
/**
* 根据角色列表解析首选设置配置。
* 优先级admin > teacher > student > parent
*/
export function resolveRoleSettingsConfig(roles: Role[]): RoleSettingsConfig | null {
for (const role of roles) {
const config = ROLE_SETTINGS_CONFIG[role]
if (config) return config
}
return null
}