Files
NextEdu/docs/architecture/004_architecture_impact_map.md
SpecialX 125f7ec54c
Some checks failed
CI / build-deploy (push) Has been cancelled
refactor: RBAC权限系统重构 + UI组件拆分 + 测试修复 + 架构文档
- RBAC: 新增30个权限点、DataScope行级权限、requirePermission守卫,所有57+ Server Action接入权限校验
- UI拆分: exam-form(1623行→11文件)、textbook-reader(744行→7文件),均降至300行以内
- 测试: 新增5个单元测试文件(19用例),修复4个集成测试文件(38用例全部通过)
- 架构文档: 新增架构影响地图(004/005)、标准功能清单(006)、差距审计报告(007)
- 项目规则: 架构图优先规则,改码必同步图
- 安全: rehype-sanitize净化、AES加密API Key、权限路由守卫
- 无障碍: skip-link、aria-label、prefers-reduced-motion
- 性能: next/font优化、next/image、代码分割
2026-06-16 23:38:33 +08:00

683 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Next_Edu 架构影响地图
> 全模块·全函数·全参数级别
> 生成日期2026-06-16
> 规则:每次文件修改后须同步更新本文档
---
## 模块shared
### 模块职责
提供全项目共享的基础设施数据库连接、Schema、工具函数、权限系统、UI 基础组件、通用 Hooks。
### 导出函数
#### `cn`
- 签名:`cn(...inputs: ClassValue[]): string`
- 参数说明:
- `inputs`: ClassValue[],来自 `clsx` + `tailwind-merge`CSS 类名列表
- 功能:合并 CSS 类名并解决 Tailwind 冲突
- 依赖:`clsx`, `tailwind-merge`
- 被以下模块使用:**所有模块**的组件50+ 文件)
#### `formatDate`
- 签名:`formatDate(date: string | Date, locale?: string): string`
- 参数说明:
- `date`: string | Date日期值
- `locale`: string默认 `"zh-CN"``Intl.DateTimeFormat` 的 locale
- 功能:国际化日期格式化
- 依赖:无
- 被以下模块使用exams, homework, dashboard, textbooks
#### `parseAiChatPayload`
- 签名:`parseAiChatPayload(body: unknown): AiChatRequest`
- 参数说明:`body`: unknownHTTP 请求体
- 功能:解析并校验 AI 聊天请求负载
- 依赖Zod schema
- 被以下模块使用:`app/api/ai/chat/route.ts`
#### `encryptAiApiKey` / `decryptAiApiKey`
- 签名:`(value: string) => string`
- 功能AES 加密/解密 AI Provider API Key
- 依赖:`crypto` (Node.js 内置)
- 被以下模块使用settings (存储/读取 API Key)
#### `testAiProviderConfig` / `testAiProviderById`
- 签名:`(input: { apiKey, baseUrl?, model }) => Promise<boolean>` / `(providerId, overrides?) => Promise<boolean>`
- 功能:测试 AI Provider 连通性
- 依赖:`createAiChatCompletion`, `shared/db`
- 被以下模块使用settings/actions.ts
#### `createAiChatCompletion`
- 签名:`(input: AiChatRequest) => Promise<{ content, usage }>`
- 功能:调用 AI 模型生成聊天回复
- 依赖OpenAI SDK, `shared/db` (读取 provider 配置)
- 被以下模块使用exams/ai-pipeline.ts, `app/api/ai/chat/route.ts`
#### `getAuthContext`
- 签名:`getAuthContext(): Promise<AuthContext>`
- 功能获取当前用户的完整认证上下文userId, roles, permissions, dataScope
- 依赖:`auth` (NextAuth), `shared/db` (查询角色/班级/年级关系)
- 被以下模块使用:**所有业务模块**的 Server Actions
#### `requirePermission`
- 签名:`requirePermission(permission: Permission): Promise<AuthContext>`
- 参数说明:`permission`: Permission来自 `shared/types/permissions` 的权限常量
- 功能:断言当前用户拥有指定权限,否则抛出 PermissionDeniedError
- 依赖:`getAuthContext`
- 被以下模块使用:**所有业务模块**的 Server Actionsexams, homework, questions, textbooks, classes, school, settings
#### `checkPermission`
- 签名:`checkPermission(permission: Permission): Promise<{ allowed: boolean; ctx: AuthContext }>`
- 功能:非抛出版权限检查
- 依赖:`getAuthContext`
- 被以下模块使用:待扩展
#### `requireAuth`
- 签名:`requireAuth(): Promise<AuthContext>`
- 功能:仅断言用户已登录
- 依赖:`getAuthContext`
- 被以下模块使用:待扩展
#### `resolvePermissions`
- 签名:`resolvePermissions(roleNames: string[]): Permission[]`
- 参数说明:`roleNames`: string[],用户的角色名称列表
- 功能:合并多角色的权限列表(去重)
- 依赖:`ROLE_PERMISSIONS` 常量
- 被以下模块使用auth.ts (JWT callback)
### 导出组件
#### `AuthSessionProvider`
- Props: `{ children: React.ReactNode }`
- 内部使用:`next-auth/react``SessionProvider`
- 被使用:`app/layout.tsx`
#### `OnboardingGate`
- Props: 无(内部使用 `useSession`
- 内部使用:`useSession`, `Permissions`, 多个 Server Action
- 功能:新用户引导流程(角色选择、学校/班级配置)
- 被使用:`app/layout.tsx`
#### `ThemeProvider`
- Props: `next-themes``ThemeProviderProps`
- 被使用:`app/layout.tsx`
#### `EmptyState`
- Props: `{ icon?, title, description, action? }`
- 被使用exams, homework, questions, textbooks 等模块的列表空状态
### 导出 Hooks
#### `useActionWithToast`
- 签名:`useActionWithToast<T>(): { isPending, execute }`
- 功能:包装 Server Action + toast 反馈
- 被使用:待扩展
#### `useDebounce`
- 签名:`useDebounce<T>(value: T, delay?: number): T`
- 被使用:搜索输入框等
#### `useMediaQuery`
- 签名:`useMediaQuery(query: string): boolean`
- 被使用:响应式布局判断
#### `useLocalStorage`
- 签名:`useLocalStorage<T>(key: string, initialValue: T): [T, setter]`
- 被使用exam-form (previewTaskStorageKey)
#### `usePermission`
- 签名:`usePermission(): { permissions, roles, hasPermission, hasAnyPermission, hasAllPermissions, hasRole }`
- 功能:客户端权限检查 Hook
- 被使用layout/app-sidebar.tsx, exams/components, homework/components
### 类型/接口
#### `ActionState<T>`
- 定义:`{ success: boolean; message?: string; errors?: Record<string, string[]>; data?: T }`
- 被使用:**所有模块**的 Server Action 返回类型
#### `Permissions` (常量对象)
- 定义22 个权限常量(`exam:create`, `homework:grade` 等)
- 被使用auth-guard.ts, 所有模块的 actions.ts, 前端组件
#### `Permission` (类型)
- 定义:`Permissions` 值的联合类型
- 被使用auth-guard.ts, use-permission.ts
#### `DataScope` (联合类型)
- 定义:`{ type: "all" } | { type: "owned"; userId: string } | { type: "class_taught"; classIds: string[]; subjectIds?: string[] } | { type: "grade_managed"; gradeIds: string[] } | { type: "class_members" } | { type: "children"; childrenIds: string[] }`
- 被使用auth-guard.ts, exams/data-access.ts, homework/data-access.ts, dashboard/data-access.ts
#### `AuthContext` (接口)
- 定义:`{ userId: string; roles: string[]; permissions: Permission[]; dataScope: DataScope }`
- 被使用auth-guard.ts, 所有调用 `requirePermission` 的 Server Action
#### `PermissionDeniedError` (类)
- 被使用:所有 Server Action 的 try/catch
### 数据库表 (shared/db/schema.ts)
| 表名 | 核心字段 | 被哪些模块使用 |
|------|---------|--------------|
| `users` | id, name, email, password, gradeId, departmentId, onboardedAt | auth, users, dashboard, classes |
| `accounts` | userId, provider, access_token | auth |
| `sessions` | userId, sessionToken | auth |
| `roles` | id, name | auth, auth-guard |
| `usersToRoles` | userId, roleId | auth, auth-guard |
| `rolePermissions` | roleId, permission | auth (seed) |
| `knowledgePoints` | id, name, chapterId, parentId | textbooks, questions |
| `questions` | id, content, type, authorId, parentId | questions, exams, homework |
| `questionsToKnowledgePoints` | questionId, knowledgePointId | questions |
| `subjects` | id, name, order | exams, textbooks |
| `textbooks` | id, title, subject, grade | textbooks |
| `chapters` | id, textbookId, title, parentId, content | textbooks |
| `departments` | id, name, description | school |
| `classrooms` | id, location, capacity | school |
| `academicYears` | id, name, startDate, endDate | school |
| `schools` | id, name, code | school, classes |
| `grades` | id, schoolId, name, gradeHeadId, teachingHeadId | school, classes, exams, auth-guard |
| `classes` | id, schoolId, gradeId, teacherId, name, invitationCode | classes, homework, auth-guard |
| `classSubjectTeachers` | classId, teacherId, subject | classes, auth-guard |
| `classEnrollments` | classId, studentId, status | classes, homework |
| `classSchedule` | id, classId, weekday, startTime, endTime, course | classes |
| `exams` | id, creatorId, title, subjectId, gradeId, status, structure | exams, homework |
| `examQuestions` | examId, questionId | exams |
| `examSubmissions` | examId, studentId, score | exams |
| `submissionAnswers` | submissionId, questionId, answer, score | exams |
| `homeworkAssignments` | id, creatorId, sourceExamId, title, status, dueAt | homework |
| `homeworkAssignmentQuestions` | assignmentId, questionId | homework |
| `homeworkAssignmentTargets` | assignmentId, studentId | homework |
| `homeworkSubmissions` | assignmentId, studentId, status, score | homework |
| `homeworkAnswers` | submissionId, questionId, answer, score, feedback | homework |
| `aiProviders` | id, provider, baseUrl, model, apiKeyEncrypted | settings, ai |
---
## 模块auth
### 模块职责
处理用户认证(登录/注册/JWT/Session提供 NextAuth 实例和中间件。
### 导出函数
#### `auth`
- 签名:`auth(): Promise<Session | null>` (NextAuth 导出)
- 功能:获取当前用户 Session
- 被使用auth-guard.ts, 所有 Server Component 页面
#### `handlers`
- 签名:`{ GET, POST }` (NextAuth Route Handler)
- 被使用:`app/api/auth/[...nextauth]/route.ts`
#### `signIn` / `signOut`
- 被使用login-form.tsx, site-header.tsx
#### `middleware` (proxy.ts)
- 签名:`middleware(request: NextRequest) => Promise<NextResponse>`
- 功能:基于权限点的路由守卫,未登录重定向 /login无权限重定向角色首页
- 依赖:`getToken` (next-auth/jwt), `Permissions`
- 被使用Next.js middleware 层
---
## 模块exams
### 模块职责
考试全生命周期管理:创建(手动/AI、编辑、预览、发布、删除、复制。
### 导出函数 (actions.ts)
#### `createExamAction`
- 签名:`(prevState: ActionState<string> | null, formData: FormData) => Promise<ActionState<string>>`
- 参数说明:`formData` 包含 mode, title, subject, grade, difficulty, totalScore, durationMin, scheduledAt
- 功能:手动模式创建考试草稿
- 依赖:`requirePermission(EXAM_CREATE)`, `shared/db`, `data-access.persistExamDraft`
- 被使用exam-form.tsx
#### `createAiExamAction`
- 签名:同上
- 功能AI 模式创建考试(调用 AI pipeline 生成题目)
- 依赖:`requirePermission(EXAM_AI_GENERATE)`, `ai-pipeline.generateAiCreateDraftFromSource`, `data-access.persistAiGeneratedExamDraft`
- 被使用exam-form.tsx
#### `previewAiExamAction`
- 签名:`(prevState: ActionState<AiPreviewData> | null, formData: FormData) => Promise<ActionState<AiPreviewData>>`
- 功能AI 预览试卷(不持久化)
- 依赖:`requirePermission(EXAM_AI_GENERATE)`, `ai-pipeline.generateAiPreviewData`
- 被使用exam-ai-generator.tsx (via useExamPreview)
#### `regenerateAiQuestionAction`
- 签名:`(prevState: ActionState<AiRewriteQuestionData> | null, formData: FormData) => Promise<ActionState<AiRewriteQuestionData>>`
- 功能AI 重写单个题目
- 依赖:`requirePermission(EXAM_AI_GENERATE)`, `ai-pipeline.regenerateAiQuestionByInstruction`
- 被使用exam-preview-question-editor.tsx
#### `updateExamAction`
- 签名:`(prevState: ActionState<string> | null, formData: FormData) => Promise<ActionState<string>>`
- 功能:更新考试信息,含资源归属校验(非 admin 只能改自己的)
- 依赖:`requirePermission(EXAM_UPDATE)`, `shared/db`
- 被使用exam-form.tsx
#### `deleteExamAction`
- 签名:同上
- 功能:删除考试,含资源归属校验
- 依赖:`requirePermission(EXAM_DELETE)`, `shared/db`
- 被使用exam-actions.tsx
#### `duplicateExamAction`
- 签名:同上
- 功能:复制考试
- 依赖:`requirePermission(EXAM_DUPLICATE)`, `shared/db`
- 被使用exam-actions.tsx
#### `getSubjectsAction`
- 签名:`() => Promise<ActionState<{ id: string; name: string }[]>>`
- 依赖:`requirePermission(EXAM_READ)`, `shared/db`
- 被使用exam-form.tsx
#### `getGradesAction`
- 签名:同上
- 依赖:`requirePermission(EXAM_READ)`, `shared/db`
- 被使用exam-form.tsx
### 导出函数 (data-access.ts)
#### `getExams`
- 签名:`getExams(params: GetExamsParams & { scope: DataScope }): Promise<Exam[]>`
- 参数说明:`scope` 来自 `auth-guard.getAuthContext().dataScope`
- 功能:查询考试列表,含数据权限过滤
- 依赖:`shared/db`, `DataScope`
- 被使用teacher/exams/all/page.tsx, homework 创建页面
#### `getExamById`
- 签名:`getExamById(id: string, scope?: DataScope): Promise<Exam | null>`
- 被使用exam 详情/编辑页面
#### `persistExamDraft` / `persistAiGeneratedExamDraft`
- 被使用createExamAction, createAiExamAction
### 导出函数 (ai-pipeline.ts)
#### `generateAiPreviewData`
- 签名:`(input: { title, subject?, grade?, difficulty, totalScore, durationMin, questionCount?, sourceText, aiProviderId? }) => Promise<{ ok, data?, rawOutput?, message? }>`
- 依赖:`shared/lib/ai.createAiChatCompletion`
- 被使用previewAiExamAction
#### `generateAiCreateDraftFromSource`
- 被使用createAiExamAction
#### `regenerateAiQuestionByInstruction`
- 被使用regenerateAiQuestionAction
### 类型/接口
#### `Exam`
- 被使用exams/components, homework/types (sourceExam), dashboard/types
#### `AiPreviewData` / `AiRewriteQuestionData`
- 被使用exams/actions.ts, exams/components
---
## 模块homework
### 模块职责
作业全生命周期:创建(源自考试)、发布、学生作答、教师批改、数据分析。
### 导出函数 (actions.ts)
#### `createHomeworkAssignmentAction`
- 签名:`(prevState: ActionState<string> | null, formData: FormData) => Promise<ActionState<string>>`
- 功能:从已有考试创建作业
- 依赖:`requirePermission(HOMEWORK_CREATE)`, `shared/db`, `exams/data-access.getExams`
- 被使用homework-assignment-form.tsx
#### `startHomeworkSubmissionAction`
- 签名:同上
- 功能:学生开始作答
- 依赖:`requirePermission(HOMEWORK_SUBMIT)`, `shared/db`
- 被使用homework-take-view.tsx
#### `saveHomeworkAnswerAction`
- 签名:同上
- 功能:保存单题答案
- 依赖:`requirePermission(HOMEWORK_SUBMIT)`, `shared/db`
- 被使用homework-take-view.tsx
#### `submitHomeworkAction`
- 签名:同上
- 功能:提交作业
- 依赖:`requirePermission(HOMEWORK_SUBMIT)`, `shared/db`
- 被使用homework-take-view.tsx
#### `gradeHomeworkSubmissionAction`
- 签名:同上
- 功能:教师批改作业
- 依赖:`requirePermission(HOMEWORK_GRADE)`, `shared/db`
- 被使用homework-grading-view.tsx
### 导出函数 (data-access.ts)
#### `getHomeworkAssignments`
- 签名:`(params?: { creatorId?, ids?, classId?, scope? }) => Promise<HomeworkAssignmentListItem[]>`
- 依赖:`shared/db`, `DataScope`
- 被使用teacher 作业列表页, homework-assignment-form.tsx
#### `getStudentHomeworkAssignments`
- 签名:`(studentId: string) => Promise<StudentHomeworkAssignmentListItem[]>`
- 被使用student/dashboard
#### `getStudentDashboardGrades`
- 签名:`(studentId: string) => Promise<StudentDashboardGradeProps>`
- 被使用dashboard/data-access.ts (学生仪表盘)
#### `getHomeworkAssignmentAnalytics`
- 签名:`(assignmentId: string) => Promise<HomeworkAssignmentAnalytics | null>`
- 被使用homework 错误分析组件
### 类型/接口
#### `StudentDashboardGradeProps`
- 被使用dashboard/types.ts (StudentDashboardProps.grades)
#### `HomeworkAssignmentListItem`
- 被使用homework 列表页, homework-assignment-form.tsx
---
## 模块questions
### 模块职责
题库管理:题目 CRUD、知识点关联、题型支持选择/填空/判断/复合)。
### 导出函数 (actions.ts)
#### `createNestedQuestion`
- 签名:`(prevState: ActionState<string> | undefined, formData: FormData | CreateQuestionInput) => Promise<ActionState<string>>`
- 依赖:`requirePermission(QUESTION_CREATE)`, `shared/db`
- 被使用create-question-dialog.tsx
#### `updateQuestionAction`
- 签名:同上
- 依赖:`requirePermission(QUESTION_UPDATE)`, `shared/db`
- 被使用question-actions.tsx
#### `deleteQuestionAction`
- 签名:同上
- 依赖:`requirePermission(QUESTION_DELETE)`, `shared/db`
- 被使用question-actions.tsx
#### `getQuestionsAction`
- 签名:`(params: GetQuestionsParams) => Promise<...>`
- 依赖:`requirePermission(QUESTION_READ)`, `data-access.getQuestions`
- 被使用teacher/questions/page.tsx
#### `getKnowledgePointOptionsAction`
- 签名:`() => Promise<KnowledgePointOption[]>`
- 依赖:`requirePermission(QUESTION_READ)`, `shared/db`
- 被使用create-question-dialog.tsx
### 类型/接口
#### `Question`
- 被使用exams (题目选择), homework (作业题目)
#### `KnowledgePointOption`
- 被使用create-question-dialog.tsx
---
## 模块textbooks
### 模块职责
教材与知识体系管理:教材/章节树形结构、知识点 CRUD、Markdown 内容编辑、知识图谱。
### 导出函数 (actions.ts)
| 函数 | 权限 | 核心功能 |
|------|------|---------|
| `createTextbookAction` | TEXTBOOK_CREATE | 创建教材 |
| `updateTextbookAction` | TEXTBOOK_UPDATE | 更新教材元信息 |
| `deleteTextbookAction` | TEXTBOOK_DELETE | 删除教材 |
| `createChapterAction` | TEXTBOOK_CREATE | 创建章节 |
| `updateChapterContentAction` | TEXTBOOK_UPDATE | 更新章节内容(Markdown) |
| `deleteChapterAction` | TEXTBOOK_DELETE | 删除章节 |
| `createKnowledgePointAction` | TEXTBOOK_CREATE | 创建知识点 |
| `updateKnowledgePointAction` | TEXTBOOK_UPDATE | 更新知识点 |
| `deleteKnowledgePointAction` | TEXTBOOK_DELETE | 删除知识点 |
| `reorderChaptersAction` | TEXTBOOK_UPDATE | 章节排序 |
### 导出函数 (data-access.ts)
| 函数 | 签名 | 被使用 |
|------|------|--------|
| `getTextbooks` | `(query?, subject?, grade?) => Promise<Textbook[]>` | teacher/textbooks/page.tsx |
| `getTextbookById` | `(id: string) => Promise<Textbook \| undefined>` | teacher/textbooks/[id]/page.tsx |
| `getChaptersByTextbookId` | `(textbookId: string) => Promise<Chapter[]>` | textbook-reader.tsx |
| `getKnowledgePointsByChapterId` | `(chapterId: string) => Promise<KnowledgePoint[]>` | textbook-reader.tsx |
| `getKnowledgePointsByTextbookId` | `(textbookId: string) => Promise<KnowledgePoint[]>` | textbook-reader.tsx |
### 导出 Hooks
#### `useTextSelection`
- 签名:`useTextSelection(contentRef, onCreateKnowledgePoint) => { selectedText, createDialogOpen, isCreating, handleContentPointerDown, handleContextMenuChange }`
- 被使用textbook-content-panel.tsx
#### `useKnowledgePointActions`
- 签名:`useKnowledgePointActions(textbookId, selectedChapterId, highlightedKpId, setHighlightedKpId) => { editingKp, editKpDialogOpen, ..., requestDeleteKnowledgePoint, confirmDeleteKnowledgePoint, handleUpdateKnowledgePoint }`
- 被使用textbook-reader.tsx
### 类型/接口
#### `Chapter`
- 被使用textbooks/components, questions (知识点关联)
#### `KnowledgePoint`
- 被使用textbooks/components, questions/types (KnowledgePointOption)
---
## 模块classes
### 模块职责
班级管理:班级 CRUD、学生注册/退班、邀请码、课表、学科教师分配。
### 导出函数 (actions.ts)
| 函数 | 权限 | 核心功能 |
|------|------|---------|
| `createTeacherClassAction` | CLASS_CREATE | 教师创建班级 |
| `updateTeacherClassAction` | CLASS_UPDATE | 教师更新班级 |
| `deleteTeacherClassAction` | CLASS_DELETE | 教师删除班级 |
| `createGradeClassAction` | CLASS_CREATE | 年级主任创建班级 |
| `updateGradeClassAction` | CLASS_UPDATE | 年级主任更新班级 |
| `deleteGradeClassAction` | CLASS_DELETE | 年级主任删除班级 |
| `enrollStudentByEmailAction` | CLASS_ENROLL | 通过邮箱注册学生 |
| `joinClassByInvitationCodeAction` | CLASS_ENROLL | 通过邀请码加入 |
| `ensureClassInvitationCodeAction` | CLASS_ENROLL | 确保邀请码存在 |
| `regenerateClassInvitationCodeAction` | CLASS_ENROLL | 重新生成邀请码 |
| `setStudentEnrollmentStatusAction` | CLASS_ENROLL | 设置学生状态 |
| `createClassScheduleItemAction` | CLASS_SCHEDULE | 创建课表项 |
| `updateClassScheduleItemAction` | CLASS_SCHEDULE | 更新课表项 |
| `deleteClassScheduleItemAction` | CLASS_SCHEDULE | 删除课表项 |
| `createAdminClassAction` | CLASS_CREATE | 管理员创建班级 |
| `updateAdminClassAction` | CLASS_UPDATE | 管理员更新班级 |
| `deleteAdminClassAction` | CLASS_DELETE | 管理员删除班级 |
### 导出函数 (data-access.ts)
| 函数 | 被使用 |
|------|--------|
| `getTeacherClasses(teacherId?)` | teacher/classes/my/page.tsx, dashboard |
| `getAdminClasses()` | admin 班级管理 |
| `getGradeManagedClasses(userId)` | grade_head 班级管理 |
| `getStudentClasses(studentId)` | student/dashboard |
| `getStudentSchedule(studentId)` | student 课表 |
| `getClassStudents(classId, scope?)` | teacher/classes/students/page.tsx |
| `getClassSchedule(classId)` | teacher/classes/schedule/page.tsx |
| `getClassHomeworkInsights(classId)` | classes 作业洞察 |
| `getGradeHomeworkInsights(gradeId)` | 年级作业洞察 |
---
## 模块school
### 模块职责
学校基础数据管理:学校、年级、部门、学年的 CRUD。
### 导出函数 (actions.ts)
| 函数 | 权限 | 核心功能 |
|------|------|---------|
| `createSchoolAction` | SCHOOL_MANAGE | 创建学校 |
| `updateSchoolAction` | SCHOOL_MANAGE | 更新学校 |
| `deleteSchoolAction` | SCHOOL_MANAGE | 删除学校 |
| `createGradeAction` | GRADE_MANAGE | 创建年级 |
| `updateGradeAction` | GRADE_MANAGE | 更新年级 |
| `deleteGradeAction` | GRADE_MANAGE | 删除年级 |
| `createDepartmentAction` | SCHOOL_MANAGE | 创建部门 |
| `updateDepartmentAction` | SCHOOL_MANAGE | 更新部门 |
| `deleteDepartmentAction` | SCHOOL_MANAGE | 删除部门 |
| `createAcademicYearAction` | SCHOOL_MANAGE | 创建学年 |
| `updateAcademicYearAction` | SCHOOL_MANAGE | 更新学年 |
| `deleteAcademicYearAction` | SCHOOL_MANAGE | 删除学年 |
### 导出函数 (data-access.ts)
| 函数 | 被使用 |
|------|--------|
| `getSchools()` | admin 学校管理, onboarding |
| `getGrades()` | admin 年级管理, exams, onboarding |
| `getDepartments()` | admin 部门管理 |
| `getAcademicYears()` | admin 学年管理 |
| `getStaffOptions()` | school 组件 (年级主任选择) |
| `getGradesForStaff(staffId)` | grade_head 视图 |
---
## 模块dashboard
### 模块职责
各角色仪表盘数据聚合与展示。
### 导出函数 (data-access.ts)
#### `getAdminDashboardData`
- 签名:`getAdminDashboardData(scope?: DataScope): Promise<AdminDashboardData>`
- 依赖:`shared/db`, `DataScope`
- 被使用admin/dashboard/page.tsx
### 类型/接口
#### `StudentDashboardProps`
- 被使用student-dashboard-view.tsx
- 依赖:`homework/types.StudentDashboardGradeProps`
#### `TeacherDashboardData`
- 被使用teacher-dashboard-view.tsx
- 依赖:`homework/data-access.getTeacherGradeTrends`, `classes/data-access.getTeacherClasses`
---
## 模块layout
### 模块职责
应用布局框架:侧边栏、顶栏、导航配置。
### 导出组件
#### `AppSidebar`
- 内部使用:`usePermission`, `NAV_CONFIG`
- 功能:根据权限渲染侧边栏导航
#### `SiteHeader`
- 内部使用:`useSession`, `signOut`
- 功能:顶部导航栏
### 导出配置
#### `NAV_CONFIG`
- 类型:`Record<string, NavItem[]>`
- 每个NavItem含 `permission?: string` 字段
- 被使用app-sidebar.tsx
---
## 模块settings
### 模块职责
系统设置AI Provider 配置、用户偏好。
### 导出函数 (actions.ts)
| 函数 | 权限 | 核心功能 |
|------|------|---------|
| `getAiProviderSummaries()` | AI_CONFIGURE | 获取 AI Provider 列表 |
| `upsertAiProviderAction(data)` | AI_CONFIGURE | 创建/更新 AI Provider |
| `testAiProviderAction(data)` | AI_CONFIGURE | 测试 AI Provider 连通性 |
---
## 模块间依赖矩阵
| ↓ 使用 → | shared | auth | exams | homework | questions | textbooks | classes | school | dashboard | layout | settings |
|----------|--------|------|-------|----------|-----------|-----------|---------|--------|-----------|--------|----------|
| **shared** | - | - | - | - | - | - | - | - | - | - | - |
| **auth** | db,schema,permissions | - | - | - | - | - | - | - | - | - | - |
| **exams** | db,auth-guard,types,ai | auth | - | - | - | - | - | - | - | - | - |
| **homework** | db,auth-guard,types | auth | data-access.getExams | - | - | - | schema | - | - | - | - |
| **questions** | db,auth-guard,types | auth | - | - | - | - | - | - | - | - | - |
| **textbooks** | db,auth-guard,types | auth | - | - | - | - | - | - | - | - | - |
| **classes** | db,auth-guard,types | auth | - | homework-insights | - | - | - | - | - | - | - |
| **school** | db,auth-guard,types | auth | - | - | - | - | - | - | - | - | - |
| **dashboard** | db,types | auth | - | data-access.getTeacherGradeTrends,getStudentDashboardGrades | - | - | data-access.getTeacherClasses,getStudentClasses,getStudentSchedule | - | - | - | - |
| **layout** | hooks.usePermission | auth(useSession) | - | - | - | - | - | - | - | - | - |
| **settings** | db,auth-guard,ai,types | auth | - | - | - | - | - | - | - | - | - |
---
## 关键参数影响链
### `userId`
1.`auth.ts` JWT callback 从 `users` 表查询产生,存入 JWT
2. 通过 `session.user.id` 传递到所有 Server Components 和 Client Components
3. 通过 `getAuthContext().userId` 传递到所有 Server Actions
4.`auth-guard.ts` 中用于查询 `usersToRoles`(获取角色)和 `classSubjectTeachers`/`grades`(获取 DataScope
5. 在 exams/actions.ts 中作为 `creatorId` 写入 `exams`
6. 在 homework/actions.ts 中作为 `creatorId` 写入 `homeworkAssignments`
7. 在 classes/data-access.ts 中查询 `getTeacherClasses(teacherId)``getGradeManagedClasses(userId)`
### `examId`
1.`exams/actions.ts``createExamAction` 产生,通过 CUID2 生成,写入 `exams`
2.`exams/data-access.getExamById(id)` 读取
3.`exams/actions.ts``updateExamAction`/`deleteExamAction`/`duplicateExamAction` 用于定位考试
4. 传入 `homework/actions.ts``createHomeworkAssignmentAction``sourceExamId` 参数
5.`homeworkAssignments` 表中作为外键关联到源考试
6.`homework/data-access.getHomeworkAssignmentAnalytics` 用于追溯作业来源
### `classId`
1.`classes/actions.ts``createTeacherClassAction`/`createAdminClassAction` 产生
2.`classes/data-access.getClassStudents(classId)` 读取学生列表
3.`classes/data-access.getClassSchedule(classId)` 读取课表
4.`classes/data-access.getClassHomeworkInsights(classId)` 读取作业洞察
5.`homework/data-access.getHomeworkAssignments({ classId })` 过滤作业列表
6.`auth-guard.ts` 中通过 `classSubjectTeachers` 查询教师关联的 classIds构建 `DataScope.class_taught`
### `permission`
1.`shared/types/permissions.ts``Permissions` 常量定义22 个权限点)
2.`shared/lib/permissions.ts` 中通过 `ROLE_PERMISSIONS` 映射角色到权限列表
3.`auth.ts` JWT callback 中通过 `resolvePermissions(roleNames)` 合并多角色权限,存入 JWT
4.`proxy.ts` middleware 中通过 `token.permissions` 检查路由访问权限
5.`shared/lib/auth-guard.ts` 中通过 `requirePermission(permission)` 在 Server Action 层断言权限
6.`shared/hooks/use-permission.ts` 中通过 `hasPermission(permission)` 在客户端组件中条件渲染
7.`layout/config/navigation.ts` 中作为 `NavItem.permission` 字段过滤侧边栏菜单
### `DataScope`
1.`auth-guard.ts``resolveDataScope(userId, roles)` 根据用户角色和 DB 关系动态计算
2. 传递到 `exams/data-access.getExams({ scope })` 进行行级过滤
3. 传递到 `homework/data-access.getHomeworkAssignments({ scope })` 进行行级过滤
4. 传递到 `dashboard/data-access.getAdminDashboardData(scope)` 进行统计过滤
5. 在 exams/actions.ts 的 `updateExamAction`/`deleteExamAction` 中用于判断是否需要资源归属校验(`scope.type !== "all"`