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:
@@ -2735,6 +2735,14 @@
|
||||
"createExamAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "addExamQuestions",
|
||||
"signature": "addExamQuestions(examId: string, items: Array<{ questionId: string; score: number; order: number }>): Promise<void>",
|
||||
"purpose": "批量插入考试-题目关联(跨模块写接口,供 lesson-preparation/publish-service 调用,避免直查 examQuestions 表)",
|
||||
"usedBy": [
|
||||
"lesson-preparation/publish-service.publishLessonPlanHomework"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "persistAiGeneratedExamDraft",
|
||||
"signature": "persistAiGeneratedExamDraft(input: { examId, title, creatorId, subjectId, gradeId, scheduledAt?, description, structure, generated }): Promise<void>",
|
||||
@@ -6258,56 +6266,125 @@
|
||||
"usedBy": [
|
||||
"data-access.getAiProviderForUpdate"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SettingsService",
|
||||
"file": "types.ts",
|
||||
"type": "interface",
|
||||
"definition": "设置模块统一服务接口(profile + notifications + trackEvent),通过 React Context 注入实现解耦",
|
||||
"usedBy": [
|
||||
"components/settings-service-context.tsx",
|
||||
"app/(dashboard)/settings/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ProfileService",
|
||||
"file": "types.ts",
|
||||
"type": "interface",
|
||||
"definition": "个人资料服务接口(getProfile + updateProfile),解耦组件对 users/actions 的直接依赖",
|
||||
"usedBy": [
|
||||
"types.SettingsService",
|
||||
"components/profile-settings-form.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "NotificationPreferenceService",
|
||||
"file": "types.ts",
|
||||
"type": "interface",
|
||||
"definition": "通知偏好服务接口(getPreferences + updatePreferences),解耦组件对 messaging/actions 的直接依赖",
|
||||
"usedBy": [
|
||||
"types.SettingsService",
|
||||
"components/notification-preferences-form.tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"name": "AiProviderSettingsCard",
|
||||
"purpose": "AI Provider设置卡片"
|
||||
"purpose": "AI Provider设置卡片(i18n:settings.ai.providers)"
|
||||
},
|
||||
{
|
||||
"name": "AdminSettingsView",
|
||||
"purpose": "系统设置视图(学校信息/安全策略/文件上传/通知配置 4 个 Card,模拟保存;消费方:/admin/settings 页面)",
|
||||
"purpose": "系统设置视图(学校信息/安全策略/文件上传/通知配置 4 个 Card,i18n;消费方:/admin/settings 页面)",
|
||||
"usedBy": [
|
||||
"app/(dashboard)/admin/settings/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ProfileSettingsForm",
|
||||
"purpose": "个人资料设置表单"
|
||||
"purpose": "个人资料设置表单(通过 useSettingsService().profile.updateProfile 调用,i18n:settings.profile)",
|
||||
"deps": [
|
||||
"useSettingsService",
|
||||
"shared/components/form-fields/text-field",
|
||||
"shared/components/form-fields/select-field"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ThemePreferencesCard",
|
||||
"purpose": "主题偏好卡片"
|
||||
"purpose": "主题偏好卡片(i18n:settings.appearance)"
|
||||
},
|
||||
{
|
||||
"name": "StudentSettingsView",
|
||||
"purpose": "学生设置视图(含 Notifications tab)"
|
||||
},
|
||||
{
|
||||
"name": "TeacherSettingsView",
|
||||
"purpose": "教师设置视图(含 Notifications tab)"
|
||||
},
|
||||
{
|
||||
"name": "ParentSettingsView",
|
||||
"purpose": "家长设置视图(复用 SettingsView 布局,backHref 指向 /parent/dashboard,含家长专属快捷链接;消费方:/settings 页面 parent 角色分支)",
|
||||
"name": "SettingsView",
|
||||
"purpose": "统一设置页布局(5 标签页:General/Notifications/Appearance/Security/AI;角色差异通过 resolveRoleSettingsConfig 配置驱动 + generalExtra props 注入;Tab URL 持久化;每个 TabsContent 包裹 SettingsSectionErrorBoundary + Suspense 骨架屏;AI 标签页条件渲染需 AI_CONFIGURE 权限;登出 AlertDialog 二次确认;i18n:settings 命名空间)",
|
||||
"usedBy": [
|
||||
"app/(dashboard)/settings/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SettingsView",
|
||||
"purpose": "统一设置页布局(5 标签页:General/Notifications/Appearance/Security/AI,角色差异通过 description/backHref/generalExtra 三个 props 注入;Tab 通过 URL ?tab= 参数持久化;AI 标签页条件渲染需 AI_CONFIGURE 权限;登出按钮使用 AlertDialog 二次确认;4 个消费方:admin/teacher/student/parent 设置页)",
|
||||
"name": "SettingsServiceProvider",
|
||||
"file": "components/settings-service-context.tsx",
|
||||
"purpose": "SettingsService React Context Provider,页面层注入服务实现,组件层通过 useSettingsService() 消费",
|
||||
"usedBy": [
|
||||
"AdminSettingsView",
|
||||
"TeacherSettingsView",
|
||||
"StudentSettingsView",
|
||||
"ParentSettingsView"
|
||||
"app/(dashboard)/settings/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SettingsSectionErrorBoundary",
|
||||
"file": "components/settings-section-error-boundary.tsx",
|
||||
"purpose": "分区 Error Boundary,包裹每个 TabsContent 和 profile 角色概览区块,局部失败不影响整页",
|
||||
"usedBy": [
|
||||
"components/settings-view.tsx",
|
||||
"app/(dashboard)/profile/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "QuickLinksCard",
|
||||
"file": "components/quick-links-card.tsx",
|
||||
"purpose": "快捷链接卡片(客户端组件,i18n 键驱动:settings.quickLinks)",
|
||||
"usedBy": [
|
||||
"config/role-settings-config.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ProfileStudentOverview",
|
||||
"file": "components/profile-student-overview.tsx",
|
||||
"purpose": "学生概览异步 Server Component,独立获取学生数据并渲染(StatsGrid + UpcomingAssignments + Grades + TodaySchedule),可被 Suspense + ErrorBoundary 包裹实现流式渲染",
|
||||
"deps": [
|
||||
"classes/data-access.getStudentClasses",
|
||||
"classes/data-access.getStudentSchedule",
|
||||
"homework/data-access.getStudentHomeworkAssignments",
|
||||
"homework/data-access.getStudentDashboardGrades",
|
||||
"lib/student-overview-data.buildStudentOverviewData"
|
||||
],
|
||||
"usedBy": [
|
||||
"app/(dashboard)/profile/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ProfileTeacherOverview",
|
||||
"file": "components/profile-teacher-overview.tsx",
|
||||
"purpose": "教师概览异步 Server Component,独立获取教师数据并渲染(任教科目 + 任教班级),可被 Suspense + ErrorBoundary 包裹",
|
||||
"deps": [
|
||||
"classes/data-access.getTeacherClasses",
|
||||
"classes/data-access.getTeacherTeachingSubjects"
|
||||
],
|
||||
"usedBy": [
|
||||
"app/(dashboard)/profile/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PasswordChangeForm",
|
||||
"purpose": "密码修改表单(当前密码/新密码/确认密码 + 强度指示器 + 需求提示)",
|
||||
"purpose": "密码修改表单(当前密码/新密码/确认密码 + 强度指示器 + 需求提示;i18n:settings.security;a11y:aria-label)",
|
||||
"deps": [
|
||||
"changePasswordAction",
|
||||
"getPasswordStrength",
|
||||
@@ -6317,17 +6394,14 @@
|
||||
{
|
||||
"name": "NotificationPreferencesForm",
|
||||
"file": "components/notification-preferences-form.tsx",
|
||||
"purpose": "通知偏好设置表单(Switch 切换 email/sms/push 通道 + 5 个分类开关:作业/成绩/公告/消息/考勤;隐藏 checkbox 与 Switch 同步,useActionState 调用 updateNotificationPreferencesAction)",
|
||||
"purpose": "通知偏好设置表单(Switch 切换 email/sms/push 通道 + 5 个分类开关;通过 useSettingsService().notifications.updatePreferences 调用,i18n:settings.notifications)",
|
||||
"deps": [
|
||||
"updateNotificationPreferencesAction",
|
||||
"useSettingsService",
|
||||
"shared/components/ui/switch",
|
||||
"shared/components/ui/card",
|
||||
"react.useActionState"
|
||||
"shared/components/ui/card"
|
||||
],
|
||||
"usedBy": [
|
||||
"TeacherSettingsView",
|
||||
"StudentSettingsView",
|
||||
"ParentSettingsView"
|
||||
"SettingsView"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -12083,17 +12157,17 @@
|
||||
},
|
||||
{
|
||||
"name": "buildInitialContent",
|
||||
"file": "data-access.ts",
|
||||
"file": "lib/document-migration.ts(data-access.ts re-export)",
|
||||
"purpose": "基于模板构建初始课案内容(v2 nodes+edges)"
|
||||
},
|
||||
{
|
||||
"name": "migrateV1ToV2",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "v1→v2 迁移:将旧 blocks 数组转换为 nodes + 线性 edges(节点按网格布局)"
|
||||
"file": "lib/document-migration.ts(data-access.ts re-export)",
|
||||
"purpose": "v1→v2 迁移:将旧 blocks 数组转换为 nodes + 线性 edges(节点按网格布局),使用类型守卫 isV1Document/isV2Document 替代 as 断言"
|
||||
},
|
||||
{
|
||||
"name": "normalizeDocument",
|
||||
"file": "data-access.ts",
|
||||
"file": "lib/document-migration.ts(data-access.ts re-export)",
|
||||
"purpose": "规范化:确保 content 为 v2 格式,兼容旧 v1 数据(自动调用 migrateV1ToV2)"
|
||||
},
|
||||
{
|
||||
@@ -12149,7 +12223,7 @@
|
||||
{
|
||||
"name": "publishLessonPlanHomework",
|
||||
"file": "publish-service.ts",
|
||||
"purpose": "发布课案为作业(编排 homework/exams/classes)"
|
||||
"purpose": "发布课案为作业(编排 homework/exams/classes,通过对方 data-access 调用 addExamQuestions/getStudentIdsByClassIds,无直查跨模块表)"
|
||||
},
|
||||
{
|
||||
"name": "suggestKnowledgePoints",
|
||||
@@ -12264,6 +12338,10 @@
|
||||
"types.ts",
|
||||
"constants.ts",
|
||||
"schema.ts",
|
||||
"lib/document-migration.ts",
|
||||
"lib/node-summary.ts",
|
||||
"lib/rf-mappers.ts",
|
||||
"config/block-registry.tsx",
|
||||
"data-access.ts",
|
||||
"data-access-versions.ts",
|
||||
"data-access-templates.ts",
|
||||
@@ -12283,6 +12361,8 @@
|
||||
"components/node-editor.tsx",
|
||||
"components/node-edit-panel.tsx",
|
||||
"components/nodes/lesson-node.tsx",
|
||||
"components/lesson-plan-error-boundary.tsx",
|
||||
"components/lesson-plan-skeleton.tsx",
|
||||
"components/block-renderer.tsx",
|
||||
"components/template-picker.tsx",
|
||||
"components/version-history-drawer.tsx",
|
||||
@@ -13027,7 +13107,11 @@
|
||||
"dependsOn": [
|
||||
"shared",
|
||||
"auth",
|
||||
"messaging"
|
||||
"classes",
|
||||
"homework",
|
||||
"dashboard",
|
||||
"users",
|
||||
"notifications"
|
||||
],
|
||||
"uses": {
|
||||
"shared": [
|
||||
@@ -13035,17 +13119,41 @@
|
||||
"auth-guard",
|
||||
"ai",
|
||||
"types",
|
||||
"components.ui.switch"
|
||||
"components.ui.switch",
|
||||
"components.ui.card",
|
||||
"components.ui.tabs",
|
||||
"components.ui.alert-dialog",
|
||||
"components.form-fields"
|
||||
],
|
||||
"auth": [
|
||||
"auth"
|
||||
],
|
||||
"messaging": [
|
||||
"notification-preferences.getNotificationPreferences",
|
||||
"actions.getNotificationPreferencesAction",
|
||||
"actions.updateNotificationPreferencesAction"
|
||||
"classes": [
|
||||
"data-access.getStudentClasses",
|
||||
"data-access.getStudentSchedule",
|
||||
"data-access.getTeacherClasses",
|
||||
"data-access.getTeacherTeachingSubjects"
|
||||
],
|
||||
"homework": [
|
||||
"data-access.getStudentHomeworkAssignments",
|
||||
"data-access.getStudentDashboardGrades"
|
||||
],
|
||||
"dashboard": [
|
||||
"components.student-dashboard.student-grades-card",
|
||||
"components.student-dashboard.student-stats-grid",
|
||||
"components.student-dashboard.student-today-schedule-card",
|
||||
"components.student-dashboard.student-upcoming-assignments-card"
|
||||
],
|
||||
"users": [
|
||||
"data-access.UserProfile",
|
||||
"data-access.UpdateUserProfileInput"
|
||||
],
|
||||
"notifications": [
|
||||
"types.NotificationPreferences",
|
||||
"types.UpdateNotificationPreferencesInput"
|
||||
]
|
||||
}
|
||||
},
|
||||
"note": "组件层通过 SettingsService 接口注入解耦,不直接 import messaging/actions;页面层 app/(dashboard)/settings/page.tsx 负责注入 users/actions + messaging/actions 实现"
|
||||
},
|
||||
"users": {
|
||||
"dependsOn": [
|
||||
|
||||
Reference in New Issue
Block a user