feat: 新增备课模块并修复全模块 P0/P1/P2 缺陷
Some checks failed
Security / deep-security-scan (push) Failing after 20m5s
DR Drill / dr-drill (push) Failing after 1m31s
CI / scheduled-backup (push) Failing after 1m31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
Some checks failed
Security / deep-security-scan (push) Failing after 20m5s
DR Drill / dr-drill (push) Failing after 1m31s
CI / scheduled-backup (push) Failing after 1m31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
主要变更: - 新增 lesson-preparation 模块: 备课编辑器、节点编辑、AI 建议、知识点选择、版本历史、作业发布 - 新增 shared 通用组件: charts/question-bank-filters/schedule-list/ui (chip-nav/filter-bar/page-header/stat-card/stat-item) - 新增 student/admin 端 loading.tsx 与 error.tsx, 优化加载与错误态体验 - 新增 teacher/lesson-plans 页面 (列表/新建/编辑) - 新增 drizzle 迁移 0002_tiny_lionheart 及 snapshot - 新增 textbooks/schema.ts 与 exams/utils/normalize-structure.ts - 修复 Tiptap v3 SSR hydration 崩溃 (rich-text-block immediatelyRender: false) - 重构多模块 data-access/actions/组件, 修复权限校验与类型规范 - 同步架构文档 004/005 反映新增模块、导出、依赖关系 - 归档 bugs/* 测试报告与 e2e 测试脚本 (admin/parent/student/teacher web_test)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"generatedAt": "2026-06-17",
|
||||
"formatVersion": "1.1",
|
||||
"rule": "每次文件修改后须同步更新本文件",
|
||||
"lastUpdate": "P2-6/P2-7/P2-8/P2-11/P2-17/P2-18 已修复:proxy.ts 改用 Permissions 常量替代硬编码字符串;useA11yId 文件已不存在(use-aria-live.ts 已在 hooks/ 目录);schema.ts 分节编号重新编号为连续 1-24,消除 8b/14b/乱序问题;announcements 死代码 void wasPublished 已不存在;layout/app-sidebar.tsx 改用 hasRole() 判断角色,不再用权限反推角色;scheduling/actions.ts 移除末尾 re-export data-access,4 个页面改为从 data-access 直接导入;P1-1 已修复:所有跨模块直查已改为通过对方 data-access 接口(homework/grades/parent/diagnostic/elective/proctoring/notifications/scheduling/classes 模块);P0-2 已修复:shared/lib ↔ auth 循环依赖已解决,新增 shared/lib/session.ts 单一入口;P1-6 已修复:http-utils.ts 统一 IP/UA 提取;P0-1/P0-2/P0-3/P0-4/P0-5/P0-7/P0-8 已修复;P1-2 已修复:actions 层 DB 操作下沉到 data-access;P2-2/P2-3/P2-12/P2-20 已修复"
|
||||
"lastUpdate": "P0-b/P1-a/P1-b/P1-c/P2-a/P2-b/P3-a/P3-b/P3-c/P3-d 共享组件抽取重构已同步:新增 shared 层 UI 组件(StatCard/StatItem/ChipNav/PageHeader/FilterBar+FilterSearchInput+FilterResetButton)、图表组件(ChartCardShell/TrendLineChart/SimpleBarChart/ComparisonRadarChart)、课表组件(ScheduleList+ScheduleListItem)、题库组件(QuestionBankFilters)、工具函数(downloadBase64File/downloadBlob/getInitials/formatDateForFile);新增 settings 模块 SettingsView 组件;删除 messaging/notification-preferences.ts(P0-b 通知模块去重,re-export shim 已移除,消费方改为直接从 notifications/preferences 导入);P2-6/P2-7/P2-8/P2-11/P2-17/P2-18 已修复:proxy.ts 改用 Permissions 常量替代硬编码字符串;useA11yId 文件已不存在(use-aria-live.ts 已在 hooks/ 目录);schema.ts 分节编号重新编号为连续 1-24,消除 8b/14b/乱序问题;announcements 死代码 void wasPublished 已不存在;layout/app-sidebar.tsx 改用 hasRole() 判断角色,不再用权限反推角色;scheduling/actions.ts 移除末尾 re-export data-access,4 个页面改为从 data-access 直接导入;P1-1 已修复:所有跨模块直查已改为通过对方 data-access 接口(homework/grades/parent/diagnostic/elective/proctoring/notifications/scheduling/classes 模块);P0-2 已修复:shared/lib ↔ auth 循环依赖已解决,新增 shared/lib/session.ts 单一入口;P1-6 已修复:http-utils.ts 统一 IP/UA 提取;P0-1/P0-2/P0-3/P0-4/P0-5/P0-7/P0-8 已修复;P1-2 已修复:actions 层 DB 操作下沉到 data-access;P2-2/P2-3/P2-12/P2-20 已修复"
|
||||
},
|
||||
"architectureOverview": {
|
||||
"layers": [
|
||||
@@ -231,6 +231,7 @@
|
||||
"FILE_READ",
|
||||
"COURSE_PLAN_READ",
|
||||
"ATTENDANCE_READ",
|
||||
"MESSAGE_SEND",
|
||||
"MESSAGE_READ",
|
||||
"MESSAGE_DELETE",
|
||||
"DIAGNOSTIC_READ",
|
||||
@@ -360,6 +361,37 @@
|
||||
"textbooks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getParam",
|
||||
"file": "lib/search-params.ts",
|
||||
"signature": "getParam(params: SearchParams, key: string): string | undefined",
|
||||
"params": {
|
||||
"params": "Next.js searchParams 对象",
|
||||
"key": "参数键名"
|
||||
},
|
||||
"purpose": "规范化 Next.js 15+ searchParams 访问(string | string[] | undefined → string | undefined),re-export 自 utils.ts 的 getSearchParam",
|
||||
"deps": [
|
||||
"shared/lib/utils.getSearchParam"
|
||||
],
|
||||
"usedBy": [
|
||||
"teacher/attendance/page.tsx",
|
||||
"teacher/attendance/sheet/page.tsx",
|
||||
"teacher/attendance/stats/page.tsx",
|
||||
"teacher/classes/schedule/page.tsx",
|
||||
"teacher/classes/students/page.tsx",
|
||||
"teacher/course-plans/page.tsx",
|
||||
"teacher/diagnostic/page.tsx",
|
||||
"teacher/elective/page.tsx",
|
||||
"teacher/exams/all/page.tsx",
|
||||
"teacher/grades/page.tsx",
|
||||
"teacher/grades/analytics/page.tsx",
|
||||
"teacher/grades/entry/page.tsx",
|
||||
"teacher/grades/stats/page.tsx",
|
||||
"teacher/homework/assignments/page.tsx",
|
||||
"teacher/questions/page.tsx",
|
||||
"teacher/textbooks/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "parseAiChatPayload",
|
||||
"file": "lib/ai/payload-parser.ts",
|
||||
@@ -795,6 +827,55 @@
|
||||
"usedBy": [
|
||||
"待扩展"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getInitials",
|
||||
"file": "lib/utils.ts",
|
||||
"signature": "getInitials(name: string | null | undefined): string",
|
||||
"purpose": "从用户姓名提取首字母缩写(最多2字符,用于头像 fallback)",
|
||||
"deps": [],
|
||||
"usedBy": [
|
||||
"shared/components/ui/avatar.tsx",
|
||||
"modules/dashboard/components/*-dashboard/*-header.tsx",
|
||||
"modules/parent/components/child-card.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "formatDateForFile",
|
||||
"file": "lib/utils.ts",
|
||||
"signature": "formatDateForFile(d?: Date): string",
|
||||
"purpose": "格式化日期为 YYYY-MM-DD 用于文件名(P1-c/P2-c 重构:从 grades/export.ts、audit/actions.ts、api/export/route.ts、users/actions.ts 四处重复实现抽取)",
|
||||
"deps": [],
|
||||
"usedBy": [
|
||||
"grades/actions.exportGradesAction",
|
||||
"audit/actions.exportAuditLogsAction",
|
||||
"api/export/route",
|
||||
"users/actions.exportUsersAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "downloadBase64File",
|
||||
"file": "lib/download.ts",
|
||||
"signature": "downloadBase64File(base64: string, filename: string, mimeType?: string): void",
|
||||
"purpose": "客户端下载 Base64 编码文件(默认 MIME 为 Excel xlsx),P1-c 重构从 grades/export-button、users/user-import-dialog 两处重复实现抽取",
|
||||
"deps": [
|
||||
"shared/lib/download.downloadBlob"
|
||||
],
|
||||
"usedBy": [
|
||||
"grades/components/export-button.tsx",
|
||||
"users/components/user-import-dialog.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "downloadBlob",
|
||||
"file": "lib/download.ts",
|
||||
"signature": "downloadBlob(blob: Blob, filename: string): void",
|
||||
"purpose": "客户端下载 Blob 对象(创建临时 URL + a 标签点击 + revoke),P1-c 重构从 audit/audit-log-export-button 抽取",
|
||||
"deps": [],
|
||||
"usedBy": [
|
||||
"shared/lib/download.downloadBase64File",
|
||||
"audit/components/audit-log-export-button.tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hooks": [
|
||||
@@ -940,6 +1021,261 @@
|
||||
"usedBy": [
|
||||
"settings/components/notification-preferences-form.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "StatCard",
|
||||
"file": "components/ui/stat-card.tsx",
|
||||
"props": "{ title, value, icon?, description?, color?, highlight?, href?, isLoading?, valueClassName? }",
|
||||
"purpose": "统计卡片(标题+数值+图标+描述+跳转+骨架屏),P1-a 重构从 8 处重复实现抽取(teacher/student/admin dashboard stats、class-overview-stats、grade insights 等)",
|
||||
"internalDeps": [
|
||||
"Card",
|
||||
"CardHeader",
|
||||
"CardTitle",
|
||||
"CardContent",
|
||||
"Link",
|
||||
"cn",
|
||||
"Skeleton"
|
||||
],
|
||||
"usedBy": [
|
||||
"dashboard/components/teacher-dashboard/teacher-stats.tsx",
|
||||
"dashboard/components/student-dashboard/student-stats-grid.tsx",
|
||||
"dashboard/components/admin-dashboard/admin-dashboard.tsx",
|
||||
"classes/components/class-detail/class-overview-stats.tsx",
|
||||
"app/(dashboard)/admin/school/grades/insights/page.tsx",
|
||||
"app/(dashboard)/management/grade/insights/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "StatItem",
|
||||
"file": "components/ui/stat-item.tsx",
|
||||
"props": "{ label, value, icon?, hint?, valueClassName? }",
|
||||
"purpose": "紧凑统计项(label+icon+value+hint,用于统计面板网格),P1-a 重构从 attendance-stats-card、grade-stats-card 两处重复实现抽取",
|
||||
"internalDeps": [
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"attendance/components/attendance-stats-card.tsx",
|
||||
"grades/components/grade-stats-card.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ChipNav",
|
||||
"file": "components/ui/chip-nav.tsx",
|
||||
"props": "{ options: ChipNavOption[], currentId, buildHref: (id) => string, size?: 'sm'|'xs', allOption?, className? }",
|
||||
"purpose": "芯片导航组(通过 URL search params 切换筛选维度,Link 跳转),P1-b 重构从 stats-class-selector、attendance-stats-class-selector、analytics-filters 三处重复实现抽取",
|
||||
"internalDeps": [
|
||||
"Link",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"grades/components/stats-class-selector.tsx",
|
||||
"attendance/components/attendance-stats-class-selector.tsx",
|
||||
"grades/components/analytics-filters.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PageHeader",
|
||||
"file": "components/ui/page-header.tsx",
|
||||
"props": "{ title, description?, icon?: ComponentType, actions?: ReactNode, className? }",
|
||||
"purpose": "页面头部(标题+描述+icon+actions,响应式布局:移动端纵向,桌面端横向),P2-b 重构从 admin-dashboard、profile/page、settings/security/page 三处内联头部抽取",
|
||||
"internalDeps": [
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"dashboard/components/admin-dashboard/admin-dashboard.tsx",
|
||||
"app/(dashboard)/profile/page.tsx",
|
||||
"app/(dashboard)/settings/security/page.tsx",
|
||||
"modules/settings/components/settings-view.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FilterBar",
|
||||
"file": "components/ui/filter-bar.tsx",
|
||||
"props": "{ children, hasFilters?, onReset?, layout?: 'default'|'wrap'|'between', gapClassName?, className?, resetClassName? }",
|
||||
"purpose": "筛选栏容器(统一布局壳 + Reset 按钮),P3-b 重构从 exam/textbook/question/audit-log/login-log filters 五处重复布局抽取。URL 状态管理方式(nuqs/router/callback)由各模块自行处理",
|
||||
"internalDeps": [
|
||||
"Button",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"exams/components/exam-filters.tsx",
|
||||
"textbooks/components/textbook-filters.tsx",
|
||||
"questions/components/question-filters.tsx",
|
||||
"audit/components/audit-log-filters.tsx",
|
||||
"audit/components/login-log-filters.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FilterSearchInput",
|
||||
"file": "components/ui/filter-bar.tsx",
|
||||
"props": "{ value, onChange, placeholder?, className?, inputClassName? }",
|
||||
"purpose": "筛选栏搜索框(带 Search 图标的 Input),P3-b 重构从 exam/textbook/question filters 三处重复搜索框抽取",
|
||||
"internalDeps": [
|
||||
"Input",
|
||||
"Search (lucide-react)",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"exams/components/exam-filters.tsx",
|
||||
"textbooks/components/textbook-filters.tsx",
|
||||
"questions/components/question-filters.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FilterResetButton",
|
||||
"file": "components/ui/filter-bar.tsx",
|
||||
"props": "{ onClick, className? }",
|
||||
"purpose": "筛选栏重置按钮(Reset + X 图标),P3-b 重构从 6 个 filter 文件中重复的 Reset 按钮抽取",
|
||||
"internalDeps": [
|
||||
"Button",
|
||||
"X (lucide-react)",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"FilterBar(内部使用)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ChartCardShell",
|
||||
"file": "components/charts/chart-card-shell.tsx",
|
||||
"props": "{ title, description?, icon?, iconClassName?, titleClassName?, isEmpty?, emptyTitle?, emptyDescription?, emptyIcon?, emptyClassName?, children, className?, contentClassName? }",
|
||||
"purpose": "图表卡片外壳(Card + CardHeader + EmptyState + CardContent 统一结构),P3-c 重构从 8 个图表文件重复的 Card 包装抽取",
|
||||
"internalDeps": [
|
||||
"Card",
|
||||
"CardHeader",
|
||||
"CardTitle",
|
||||
"CardDescription",
|
||||
"CardContent",
|
||||
"EmptyState",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"grades/components/grade-trend-chart.tsx",
|
||||
"grades/components/grade-distribution-chart.tsx",
|
||||
"grades/components/class-comparison-chart.tsx",
|
||||
"grades/components/subject-comparison-chart.tsx",
|
||||
"dashboard/components/teacher-dashboard/teacher-grade-trends.tsx",
|
||||
"dashboard/components/student-dashboard/student-grades-card.tsx",
|
||||
"parent/components/child-grade-summary.tsx",
|
||||
"diagnostic/components/mastery-radar-chart.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TrendLineChart",
|
||||
"file": "components/charts/trend-line-chart.tsx",
|
||||
"props": "{ data, series: TrendLineSeries[], xKey?, yDomain?, yTickFormatter?, xTickFormatter?, heightClassName?, margin?, yWidth?, tooltipClassName?, tooltipLabelKey?, className? }",
|
||||
"purpose": "趋势折线图(LineChart 统一配置:CartesianGrid + XAxis + YAxis + ChartTooltip + Line),P3-c 重构从 4 个 LineChart 文件(grade-trend-chart、teacher-grade-trends、student-grades-card、child-grade-summary)几乎逐行相同的配置抽取",
|
||||
"internalDeps": [
|
||||
"ChartContainer",
|
||||
"ChartTooltip",
|
||||
"ChartTooltipContent",
|
||||
"CartesianGrid",
|
||||
"Line",
|
||||
"LineChart",
|
||||
"XAxis",
|
||||
"YAxis",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"grades/components/grade-trend-chart.tsx",
|
||||
"dashboard/components/teacher-dashboard/teacher-grade-trends.tsx",
|
||||
"dashboard/components/student-dashboard/student-grades-card.tsx",
|
||||
"parent/components/child-grade-summary.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SimpleBarChart",
|
||||
"file": "components/charts/simple-bar-chart.tsx",
|
||||
"props": "{ data, bars: BarSeries[], xKey, yDomain?, yAllowDecimals?, yTickFormatter?, xTickFormatter?, xTruncateLength?, yWidth?, heightClassName?, margin?, showLegend?, tooltipClassName?, tooltipFormatter?, cellColors?, className? }",
|
||||
"purpose": "柱状图(BarChart 统一配置:CartesianGrid + XAxis + YAxis + ChartTooltip + Bar),P3-c 重构从 grade-distribution-chart(单 Bar + Cell 分桶着色)和 class-comparison-chart(多 Bar + Legend)抽取",
|
||||
"internalDeps": [
|
||||
"ChartContainer",
|
||||
"ChartTooltip",
|
||||
"ChartTooltipContent",
|
||||
"Bar",
|
||||
"BarChart",
|
||||
"CartesianGrid",
|
||||
"Legend",
|
||||
"XAxis",
|
||||
"YAxis",
|
||||
"Cell",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"grades/components/grade-distribution-chart.tsx",
|
||||
"grades/components/class-comparison-chart.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ComparisonRadarChart",
|
||||
"file": "components/charts/comparison-radar-chart.tsx",
|
||||
"props": "{ data, series: RadarSeries[], angleKey, angleTickFormatter?, angleTickFontSize?, domain?, tickCount?, showLegend?, heightClassName?, tooltipClassName?, className?, gridStrokeDasharray?, gridStrokeOpacity? }",
|
||||
"purpose": "对比雷达图(RadarChart 统一配置:PolarGrid + PolarAngleAxis + PolarRadiusAxis + ChartTooltip + Radar),P3-c 重构从 subject-comparison-chart(双 Radar:averageScore + passRate)和 mastery-radar-chart(双 Radar:student + classAverage,含条件 Legend)抽取",
|
||||
"internalDeps": [
|
||||
"ChartContainer",
|
||||
"ChartTooltip",
|
||||
"ChartTooltipContent",
|
||||
"PolarAngleAxis",
|
||||
"PolarGrid",
|
||||
"PolarRadiusAxis",
|
||||
"Radar",
|
||||
"RadarChart",
|
||||
"Legend",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"grades/components/subject-comparison-chart.tsx",
|
||||
"diagnostic/components/mastery-radar-chart.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ScheduleList",
|
||||
"file": "components/schedule/schedule-list.tsx",
|
||||
"props": "{ items: ScheduleListItemData[], variant?: 'separator'|'card', spacingClassName?, renderTrailing?, className? }",
|
||||
"purpose": "课表列表(课程+时间+地点+班级徽章),P3-a 重构从 student-today-schedule-card、child-schedule-card、student-schedule-view 三处逐行复制的列表项渲染抽取。支持 separator(分隔线)和 card(卡片)两种变体",
|
||||
"internalDeps": [
|
||||
"ScheduleListItem",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"dashboard/components/student-dashboard/student-today-schedule-card.tsx",
|
||||
"parent/components/child-schedule-card.tsx",
|
||||
"student/components/student-schedule-view.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ScheduleListItem",
|
||||
"file": "components/schedule/schedule-list.tsx",
|
||||
"props": "{ item: ScheduleListItemData, variant?: 'separator'|'card', trailing?, className? }",
|
||||
"purpose": "课表列表项(单条课程渲染:course + Clock + MapPin + Badge),P3-a 重构从 3 个课表文件中重复的列表项抽取",
|
||||
"internalDeps": [
|
||||
"Badge",
|
||||
"Clock (lucide-react)",
|
||||
"MapPin (lucide-react)",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"ScheduleList(内部使用)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "QuestionBankFilters",
|
||||
"file": "components/question/question-bank-filters.tsx",
|
||||
"props": "{ search, onSearchChange, type, onTypeChange, difficulty, onDifficultyChange, layout?: 'default'|'compact', className? }",
|
||||
"purpose": "题库筛选栏(搜索+题型+难度),P3-d 重构从 exam-assembly(compact 布局)和 question-bank-picker(default 布局,同时将原生 HTML input/select 迁移到 shadcn Input/Select)两处重复筛选栏抽取。状态管理方式由调用方自行处理",
|
||||
"internalDeps": [
|
||||
"Select",
|
||||
"SelectContent",
|
||||
"SelectItem",
|
||||
"SelectTrigger",
|
||||
"SelectValue",
|
||||
"FilterSearchInput",
|
||||
"cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"exams/components/exam-assembly.tsx",
|
||||
"lesson-preparation/components/question-bank-picker.tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
@@ -1029,10 +1365,22 @@
|
||||
"所有actions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Role",
|
||||
"file": "types/permissions.ts",
|
||||
"definition": "Role = 'admin' | 'teacher' | 'student' | 'parent' | 'grade_head' | 'teaching_head'",
|
||||
"usedBy": [
|
||||
"auth-guard",
|
||||
"permissions",
|
||||
"proxy",
|
||||
"next-auth.d.ts",
|
||||
"use-permission"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DataScope",
|
||||
"file": "types/permissions.ts",
|
||||
"definition": "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[] }",
|
||||
"definition": "DataScope = { type: 'all' } | { type: 'owned'; userId: string } | { type: 'class_members'; classIds: string[] } | { type: 'grade_managed'; gradeIds: string[] } | { type: 'class_taught'; classIds: string[]; subjectIds?: string[] } | { type: 'children'; childrenIds: string[] }",
|
||||
"usedBy": [
|
||||
"auth-guard",
|
||||
"exams/data-access",
|
||||
@@ -1045,7 +1393,7 @@
|
||||
{
|
||||
"name": "AuthContext",
|
||||
"file": "types/permissions.ts",
|
||||
"definition": "AuthContext = { userId: string; roles: string[]; permissions: Permission[]; dataScope: DataScope }",
|
||||
"definition": "AuthContext = { userId: string; roles: Role[]; permissions: Permission[]; dataScope: DataScope }",
|
||||
"usedBy": [
|
||||
"auth-guard",
|
||||
"所有调用requirePermission的Server Action"
|
||||
@@ -2676,6 +3024,22 @@
|
||||
"exam-form.tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"utils": [
|
||||
{
|
||||
"name": "normalizeStructure",
|
||||
"file": "utils/normalize-structure.ts",
|
||||
"type": "function",
|
||||
"signature": "(nodes: unknown) => ExamNode[]",
|
||||
"purpose": "将持久化的 exam.structure(unknown JSON)运行时校验并归一化为类型安全的 ExamNode[](类型守卫模式,无 as 断言;递归处理 group children;保证 id 唯一)",
|
||||
"deps": [
|
||||
"@paralleldrive/cuid2.createId",
|
||||
"exams/components/assembly/selected-question-list.ExamNode"
|
||||
],
|
||||
"usedBy": [
|
||||
"teacher/exams/[id]/build/page.tsx"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -4260,6 +4624,14 @@
|
||||
"usedBy": [
|
||||
"grades/data-access-analytics"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getTeacherIdsByClassIds",
|
||||
"signature": "(classIds: string[]) => Promise<string[]>",
|
||||
"purpose": "获取多个班级的所有教师 ID(班主任 + 任课教师,跨模块接口)",
|
||||
"usedBy": [
|
||||
"messaging/data-access.getRecipients"
|
||||
]
|
||||
}
|
||||
],
|
||||
"schema": [
|
||||
@@ -5369,8 +5741,8 @@
|
||||
{
|
||||
"name": "getAiProviderSummaries",
|
||||
"permission": "AI_CONFIGURE",
|
||||
"signature": "() => Promise<AiProviderSummary[]>",
|
||||
"purpose": "获取AI Provider列表(P1 已修复:DB 操作下沉到 data-access.getAiProviderSummaries)",
|
||||
"signature": "() => Promise<ActionState<AiProviderSummary[]>>",
|
||||
"purpose": "获取AI Provider列表(P1 已修复:DB 操作下沉到 data-access.getAiProviderSummaries;v3 已修复:返回值统一为 ActionState)",
|
||||
"deps": [
|
||||
"data-access.getAiProviderSummaries"
|
||||
]
|
||||
@@ -6499,13 +6871,14 @@
|
||||
"name": "getFileAttachmentsWithFilters",
|
||||
"signature": "(params: FileAttachmentQueryParams) => Promise<FileAttachment[]>",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "按 mimeType(精确或前缀匹配)与 search(originalName/filename 模糊匹配)筛选文件列表,支持 limit/offset 分页",
|
||||
"purpose": "按 mimeType(精确或前缀匹配)与 search(originalName/filename 模糊匹配)筛选文件列表,支持 limit/offset 分页(v3 修复:conditions 显式标注 SQL[] 类型,消除隐式 any[])",
|
||||
"deps": [
|
||||
"shared.db",
|
||||
"shared.db.schema.fileAttachments",
|
||||
"drizzle-orm.like",
|
||||
"drizzle-orm.or",
|
||||
"drizzle-orm.and"
|
||||
"drizzle-orm.and",
|
||||
"drizzle-orm.SQL"
|
||||
],
|
||||
"usedBy": [
|
||||
"app/(dashboard)/admin/files/page.tsx"
|
||||
@@ -7234,11 +7607,12 @@
|
||||
"name": "formatDateForFile",
|
||||
"signature": "(d?: Date) => string",
|
||||
"file": "export.ts",
|
||||
"purpose": "格式化日期为 YYYY-MM-DD 用于文件名",
|
||||
"deps": [],
|
||||
"usedBy": [
|
||||
"actions.exportGradesAction"
|
||||
]
|
||||
"purpose": "⚠️ P1-c/P2-c 已迁移:本地实现已删除,改为从 @/shared/lib/utils 导入。此条目保留仅作历史记录",
|
||||
"deps": [
|
||||
"shared/lib/utils.formatDateForFile"
|
||||
],
|
||||
"usedBy": [],
|
||||
"migratedTo": "shared/lib/utils.formatDateForFile"
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
@@ -7321,6 +7695,30 @@
|
||||
"recharts",
|
||||
"shared/components/ui/chart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "AnalyticsFilters",
|
||||
"file": "components/analytics-filters.tsx",
|
||||
"purpose": "成绩分析页筛选器(班级、科目、年级 Link 筛选按钮组,含 focus-visible 焦点样式)",
|
||||
"deps": [
|
||||
"next/link",
|
||||
"shared/lib/utils.cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"teacher/grades/analytics/page.tsx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "StatsClassSelector",
|
||||
"file": "components/stats-class-selector.tsx",
|
||||
"purpose": "统计页班级+科目筛选器(Link 筛选按钮组,含 focus-visible 焦点样式)",
|
||||
"deps": [
|
||||
"next/link",
|
||||
"shared/lib/utils.cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"teacher/grades/stats/page.tsx"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8232,12 +8630,16 @@
|
||||
"name": "getRecipients",
|
||||
"signature": "(ctx: AuthContext) => Promise<RecipientOption[]>",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "按 DataScope 过滤可发送对象列表:class_taught(教师→学生)、grade_managed(年级管理员→教师/学生)、all(管理员)、class_members(学生→自己班级的任课教师/班主任)、children(家长→孩子的班主任/任课教师)",
|
||||
"deps": [
|
||||
"shared.db",
|
||||
"shared.db.schema.users",
|
||||
"shared.db.schema.classEnrollments",
|
||||
"shared.db.schema.classes",
|
||||
"shared.db.schema.grades"
|
||||
"shared.db.schema.grades",
|
||||
"classes.data-access.getTeacherIdsByClassIds",
|
||||
"classes.data-access.getStudentActiveClassId",
|
||||
"users.data-access.getUserNamesByIds"
|
||||
],
|
||||
"usedBy": [
|
||||
"getRecipientsAction",
|
||||
@@ -9307,6 +9709,18 @@
|
||||
"name": "AttendanceRulesForm",
|
||||
"file": "components/attendance-rules-form.tsx",
|
||||
"purpose": "考勤规则配置表单(班级选择器、迟到/早退阈值、自动标记勾选)"
|
||||
},
|
||||
{
|
||||
"name": "AttendanceStatsClassSelector",
|
||||
"file": "components/attendance-stats-class-selector.tsx",
|
||||
"purpose": "考勤统计页班级筛选器(Link 筛选按钮组,含 focus-visible 焦点样式)",
|
||||
"deps": [
|
||||
"next/link",
|
||||
"shared/lib/utils.cn"
|
||||
],
|
||||
"usedBy": [
|
||||
"teacher/attendance/stats/page.tsx"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -9961,7 +10375,7 @@
|
||||
{
|
||||
"name": "getStudentProctoringStatuses",
|
||||
"signature": "(examId: string) => Promise<StudentProctoringStatus[]>",
|
||||
"purpose": "获取所有学生监考状态",
|
||||
"purpose": "获取所有学生监考状态(v3 优化:Promise.all 并行执行 getUserNamesByIds 与事件聚合查询)",
|
||||
"usedBy": [
|
||||
"actions.getProctoringDashboardAction",
|
||||
"teacher/exams/[id]/proctoring/page.tsx"
|
||||
@@ -10102,7 +10516,7 @@
|
||||
"name": "updateMasteryFromSubmission",
|
||||
"signature": "(submissionId: string) => Promise<void>",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "从提交答案更新掌握度(按知识点聚合正确率,onDuplicateKeyUpdate upsert)",
|
||||
"purpose": "从提交答案更新掌握度(按知识点聚合正确率,onDuplicateKeyUpdate upsert;v3 优化:Promise.all 并行执行多个知识点 upsert)",
|
||||
"deps": [
|
||||
"shared.db",
|
||||
"shared.db.schema.examSubmissions",
|
||||
@@ -10118,7 +10532,7 @@
|
||||
"name": "getClassMasterySummary",
|
||||
"signature": "(classId: string) => Promise<ClassMasterySummary | null>",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "获取班级掌握度摘要(学生数、平均掌握度、知识点统计、需重点关注学生)",
|
||||
"purpose": "获取班级掌握度摘要(学生数、平均掌握度、知识点统计、需重点关注学生;v3 优化:两阶段 Promise.all 并行查询班级信息+学生 ID、用户名+掌握度)",
|
||||
"deps": [
|
||||
"shared.db",
|
||||
"shared.db.schema.classes",
|
||||
@@ -10182,7 +10596,7 @@
|
||||
"name": "getDiagnosticReports",
|
||||
"signature": "(filters: DiagnosticReportQueryParams) => Promise<DiagnosticReportWithDetails[]>",
|
||||
"file": "data-access-reports.ts",
|
||||
"purpose": "查询诊断报告列表(可按 studentId/reportType/status/period 过滤,含学生名和生成者名)",
|
||||
"purpose": "查询诊断报告列表(可按 studentId/reportType/status/period 过滤,含学生名和生成者名;v3 修复:conditions 显式标注 SQL[] 类型,移除 round2 死代码)",
|
||||
"deps": [
|
||||
"shared.db",
|
||||
"shared.db.schema.learningDiagnosticReports",
|
||||
@@ -10787,13 +11201,35 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getSubjectOptions",
|
||||
"name": "buildCourseSelect",
|
||||
"file": "data-access.ts",
|
||||
"signature": "() => Promise<{id, name}[]>",
|
||||
"purpose": "获取学科选项(按 order, name 排序)",
|
||||
"signature": "() => query builder",
|
||||
"purpose": "构建 electiveCourses 表查询(仅查询本表字段,不跨表 JOIN;v3 重构:移除跨模块 LEFT JOIN,名称解析改由 resolveCourseDisplayNames 异步聚合)",
|
||||
"usedBy": [
|
||||
"admin/elective/create/page.tsx",
|
||||
"admin/elective/[id]/edit/page.tsx"
|
||||
"data-access.getElectiveCourses",
|
||||
"data-access.getElectiveCourseById",
|
||||
"data-access-selections.getAvailableCoursesForStudent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mapCourseRow",
|
||||
"file": "data-access.ts",
|
||||
"signature": "(row: CourseCoreRow, display: {teacherName?, subjectName?, gradeName?}) => ElectiveCourseWithDetails",
|
||||
"purpose": "将核心行 + 显示名映射为 ElectiveCourseWithDetails(v3 抽取:消除 data-access 与 data-access-selections 重复代码)",
|
||||
"usedBy": [
|
||||
"data-access.getElectiveCourses",
|
||||
"data-access.getElectiveCourseById",
|
||||
"data-access-selections.getAvailableCoursesForStudent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "resolveCourseDisplayNames",
|
||||
"file": "data-access.ts",
|
||||
"signature": "(rows: CourseCoreRow[]) => Promise<{teacherName?, subjectName?, gradeName?}[]>",
|
||||
"purpose": "并行聚合教师名(users.getUserNamesByIds)、学科(school.getSubjectOptions)、年级(school.getGradeOptions),返回每行的显示名映射(v3 重构:替代跨模块 LEFT JOIN)",
|
||||
"usedBy": [
|
||||
"data-access.getElectiveCourses",
|
||||
"data-access.getElectiveCourseById"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -10838,7 +11274,7 @@
|
||||
"name": "runLottery",
|
||||
"file": "data-access-operations.ts",
|
||||
"signature": "(courseId: string) => Promise<{enrolled: number, waitlist: number}>",
|
||||
"purpose": "抽签录取(随机打乱 selected 记录,前 capacity 名 enrolled,其余 waitlist,课程 status=closed)",
|
||||
"purpose": "抽签录取(Fisher-Yates 无偏洗牌 selected 记录,前 capacity 名 enrolled,其余 waitlist,课程 status=closed;v3 修复:替换 sort(Math.random) 有偏洗牌)",
|
||||
"usedBy": [
|
||||
"actions.runLotteryAction"
|
||||
]
|
||||
@@ -10847,7 +11283,7 @@
|
||||
"name": "selectCourse",
|
||||
"file": "data-access-operations.ts",
|
||||
"signature": "(courseId: string, studentId: string, priority?: number) => Promise<{status: CourseSelectionStatus, message: string}>",
|
||||
"purpose": "学生选课(校验课程状态/时间窗口/重复选课;FCFS 模式即时 enrolled/waitlist,lottery 模式 selected)",
|
||||
"purpose": "学生选课(校验课程状态/时间窗口/重复选课;FCFS 模式即时 enrolled/waitlist,lottery 模式 selected;v3 修复:db.transaction 包裹 + .for('update') 锁课程行防 FCFS 超卖)",
|
||||
"usedBy": [
|
||||
"actions.selectCourseAction"
|
||||
]
|
||||
@@ -10856,7 +11292,7 @@
|
||||
"name": "dropCourse",
|
||||
"file": "data-access-operations.ts",
|
||||
"signature": "(courseId: string, studentId: string) => Promise<void>",
|
||||
"purpose": "学生退课(status=dropped;FCFS 模式自动递补 waitlist 首位)",
|
||||
"purpose": "学生退课(status=dropped;FCFS 模式自动递补 waitlist 首位;v3 修复:db.transaction 包裹 + .for('update') 锁课程行保证递补一致性)",
|
||||
"usedBy": [
|
||||
"actions.dropCourseAction"
|
||||
]
|
||||
@@ -10893,6 +11329,12 @@
|
||||
"file": "types.ts",
|
||||
"definition": "ElectiveCourse & { teacherName?, subjectName?, gradeName? }"
|
||||
},
|
||||
{
|
||||
"name": "CourseCoreRow",
|
||||
"type": "type",
|
||||
"file": "data-access.ts",
|
||||
"definition": "buildCourseSelect 返回行的推断类型(v3 新增:供 mapCourseRow/resolveCourseDisplayNames 共享)"
|
||||
},
|
||||
{
|
||||
"name": "CourseSelection",
|
||||
"type": "interface",
|
||||
@@ -11025,7 +11467,7 @@
|
||||
},
|
||||
"lesson_preparation": {
|
||||
"path": "src/modules/lesson-preparation",
|
||||
"description": "教师备课模块:基于教材章节创建课案(Block 编辑器),支持模板、版本管理、知识点标注、题目创建/拉取、作业发布",
|
||||
"description": "教师备课模块:基于教材章节创建课案(节点图编辑器 React Flow,v2 nodes+edges 数据结构),支持模板、版本管理、知识点标注、题目创建/拉取、作业发布。编辑器从列表式(BlockRenderer + @dnd-kit)升级为节点图式(NodeEditor + @xyflow/react),旧 v1 数据通过 migrateV1ToV2() 自动迁移",
|
||||
"exports": {
|
||||
"dataAccess": [
|
||||
{
|
||||
@@ -11046,7 +11488,7 @@
|
||||
{
|
||||
"name": "updateLessonPlanContent",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "更新课案内容(Block JSON)"
|
||||
"purpose": "更新课案内容(v2 nodes+edges JSON)"
|
||||
},
|
||||
{
|
||||
"name": "softDeleteLessonPlan",
|
||||
@@ -11066,7 +11508,17 @@
|
||||
{
|
||||
"name": "buildInitialContent",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "基于模板构建初始课案内容"
|
||||
"purpose": "基于模板构建初始课案内容(v2 nodes+edges)"
|
||||
},
|
||||
{
|
||||
"name": "migrateV1ToV2",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "v1→v2 迁移:将旧 blocks 数组转换为 nodes + 线性 edges(节点按网格布局)"
|
||||
},
|
||||
{
|
||||
"name": "normalizeDocument",
|
||||
"file": "data-access.ts",
|
||||
"purpose": "规范化:确保 content 为 v2 格式,兼容旧 v1 数据(自动调用 migrateV1ToV2)"
|
||||
},
|
||||
{
|
||||
"name": "getLessonPlanVersions",
|
||||
@@ -11229,7 +11681,8 @@
|
||||
"homework",
|
||||
"classes",
|
||||
"files",
|
||||
"shared/lib/ai"
|
||||
"shared/lib/ai",
|
||||
"@xyflow/react"
|
||||
],
|
||||
"files": [
|
||||
"types.ts",
|
||||
@@ -11251,6 +11704,9 @@
|
||||
"components/lesson-plan-card.tsx",
|
||||
"components/lesson-plan-filters.tsx",
|
||||
"components/lesson-plan-editor.tsx",
|
||||
"components/node-editor.tsx",
|
||||
"components/node-edit-panel.tsx",
|
||||
"components/nodes/lesson-node.tsx",
|
||||
"components/block-renderer.tsx",
|
||||
"components/template-picker.tsx",
|
||||
"components/version-history-drawer.tsx",
|
||||
@@ -12028,6 +12484,7 @@
|
||||
"shared": [
|
||||
"db",
|
||||
"auth-guard.requireAuth",
|
||||
"auth-guard.getAuthContext",
|
||||
"db.schema.parentStudentRelations",
|
||||
"types"
|
||||
],
|
||||
@@ -12041,14 +12498,13 @@
|
||||
"classes": [
|
||||
"data-access.getStudentClasses",
|
||||
"data-access.getStudentSchedule",
|
||||
"data-access.getClassNameById",
|
||||
"data-access.getStudentActiveClassId"
|
||||
"data-access.getStudentActiveClass"
|
||||
],
|
||||
"grades": [
|
||||
"data-access.getStudentGradeSummary"
|
||||
],
|
||||
"school": [
|
||||
"data-access.getGradeOptions"
|
||||
"data-access.getGradeNameById"
|
||||
],
|
||||
"users": [
|
||||
"data-access.getUserBasicInfo",
|
||||
@@ -12060,7 +12516,8 @@
|
||||
"dependsOn": [
|
||||
"shared",
|
||||
"auth",
|
||||
"notifications"
|
||||
"notifications",
|
||||
"classes"
|
||||
],
|
||||
"uses": {
|
||||
"shared": [
|
||||
@@ -12087,6 +12544,10 @@
|
||||
"data-access.getUnreadNotificationCount (via re-export)",
|
||||
"preferences.getNotificationPreferences (via re-export)",
|
||||
"preferences.upsertNotificationPreferences (via re-export)"
|
||||
],
|
||||
"classes": [
|
||||
"data-access.getTeacherIdsByClassIds",
|
||||
"data-access.getStudentActiveClassId"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -12332,6 +12793,11 @@
|
||||
"files": [
|
||||
"data-access.createFileAttachment",
|
||||
"data-access.getFileAttachmentsByTarget"
|
||||
],
|
||||
"external": [
|
||||
"@xyflow/react(React Flow 节点图编辑器:ReactFlow/Background/Controls/MiniMap/Handle/applyNodeChanges/applyEdgeChanges)",
|
||||
"@paralleldrive/cuid2(节点 ID 生成)",
|
||||
"zustand(编辑器状态管理)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -12449,6 +12915,12 @@
|
||||
"type": "data-access",
|
||||
"description": "✅ P0-4 / P1-5 已修复:messaging 通过 sendNotification dispatcher 发送通知,通知 CRUD 和偏好通过 re-export 保持向后兼容"
|
||||
},
|
||||
{
|
||||
"from": "messaging",
|
||||
"to": "classes",
|
||||
"type": "data-access",
|
||||
"description": "getRecipients 通过 classes data-access.getTeacherIdsByClassIds / getStudentActiveClassId 获取班级教师 ID,支持 class_members(学生)和 children(家长)数据范围"
|
||||
},
|
||||
{
|
||||
"from": "classes",
|
||||
"to": "homework",
|
||||
@@ -13456,9 +13928,11 @@
|
||||
"component": "StudentDashboardView",
|
||||
"type": "server",
|
||||
"dataAccess": [
|
||||
"dashboard/data-access (student)",
|
||||
"homework/data-access.getStudentDashboardGrades",
|
||||
"classes/data-access.getStudentClasses"
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"classes/data-access.getStudentClasses",
|
||||
"classes/data-access.getStudentSchedule",
|
||||
"homework/data-access.getStudentHomeworkAssignments",
|
||||
"homework/data-access.getStudentDashboardGrades"
|
||||
],
|
||||
"permission": "homework:submit"
|
||||
},
|
||||
@@ -13467,13 +13941,14 @@
|
||||
"type": "server",
|
||||
"module": "homework",
|
||||
"dataAccess": [
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"homework/data-access.getStudentHomeworkAssignments"
|
||||
],
|
||||
"permission": "homework:submit"
|
||||
},
|
||||
"/student/learning/assignments/[assignmentId]": {
|
||||
"component": "学生作答/复习",
|
||||
"type": "client",
|
||||
"type": "server",
|
||||
"module": "homework",
|
||||
"actions": [
|
||||
"startHomeworkSubmissionAction",
|
||||
@@ -13481,6 +13956,7 @@
|
||||
"submitHomeworkAction"
|
||||
],
|
||||
"dataAccess": [
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"homework/data-access.getStudentHomeworkTakeData"
|
||||
],
|
||||
"permission": "homework:submit"
|
||||
@@ -13488,6 +13964,10 @@
|
||||
"/student/learning/courses": {
|
||||
"component": "StudentCoursesView",
|
||||
"type": "server",
|
||||
"dataAccess": [
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"classes/data-access.getStudentClasses"
|
||||
],
|
||||
"permission": "homework:submit"
|
||||
},
|
||||
"/student/learning/textbooks": {
|
||||
@@ -13495,18 +13975,20 @@
|
||||
"type": "server",
|
||||
"module": "textbooks",
|
||||
"dataAccess": [
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"textbooks/data-access.getTextbooks"
|
||||
],
|
||||
"permission": "textbook:read"
|
||||
},
|
||||
"/student/learning/textbooks/[id]": {
|
||||
"component": "学生教材阅读(只读)",
|
||||
"type": "client",
|
||||
"type": "server",
|
||||
"module": "textbooks",
|
||||
"dataAccess": [
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"textbooks/data-access.getTextbookById",
|
||||
"getChaptersByTextbookId",
|
||||
"getKnowledgePointsByTextbookId"
|
||||
"textbooks/data-access.getChaptersByTextbookId",
|
||||
"textbooks/data-access.getKnowledgePointsByTextbookId"
|
||||
],
|
||||
"permission": "textbook:read"
|
||||
},
|
||||
@@ -13515,6 +13997,8 @@
|
||||
"type": "server",
|
||||
"module": "classes",
|
||||
"dataAccess": [
|
||||
"users/data-access.getCurrentStudentUser",
|
||||
"classes/data-access.getStudentClasses",
|
||||
"classes/data-access.getStudentSchedule"
|
||||
],
|
||||
"permission": "homework:submit"
|
||||
@@ -13524,7 +14008,7 @@
|
||||
"type": "server",
|
||||
"module": "grades",
|
||||
"dataAccess": [
|
||||
"grades/actions.getStudentGradeSummaryAction"
|
||||
"grades/data-access.getStudentGradeSummary"
|
||||
],
|
||||
"permission": "grade_record:read"
|
||||
},
|
||||
@@ -13540,7 +14024,7 @@
|
||||
},
|
||||
"/student/diagnostic": {
|
||||
"component": "StudentDiagnosticView",
|
||||
"type": "client",
|
||||
"type": "server",
|
||||
"module": "diagnostic",
|
||||
"dataAccess": [
|
||||
"diagnostic/data-access.getStudentMasterySummary (ctx.userId)",
|
||||
|
||||
Reference in New Issue
Block a user