refactor: RBAC权限系统重构 + UI组件拆分 + 测试修复 + 架构文档
Some checks failed
CI / build-deploy (push) Has been cancelled

- 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、代码分割
This commit is contained in:
SpecialX
2026-06-16 23:38:33 +08:00
parent 99f116cb64
commit 125f7ec54c
75 changed files with 9480 additions and 3289 deletions

View File

@@ -0,0 +1,682 @@
# 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"`