refactor: RBAC权限系统重构 + UI组件拆分 + 测试修复 + 架构文档
Some checks failed
CI / build-deploy (push) Has been cancelled
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:
682
docs/architecture/004_architecture_impact_map.md
Normal file
682
docs/architecture/004_architecture_impact_map.md
Normal 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`: unknown,HTTP 请求体
|
||||
- 功能:解析并校验 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 Actions(exams, 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"`)
|
||||
Reference in New Issue
Block a user