feat(lesson-preparation): major update with AI features, schedules, and new components

- Add actions-schedules.ts and data-access-schedules.ts for schedule management

- Add AI differentiation, AI feedback, consistency check dialogs

- Add attachment-picker, curriculum-heatmap, print-view, version-diff-view

- Add lesson-plan-mobile-view and schedule-dialog components

- Add lib: ai-differentiation, ai-feedback, auto-layout, consistency-check,

  curriculum-coverage, export, version-diff

- Add history-slice hook for version history

- Update existing components, hooks, providers, services, types

- Add teacher lesson-plans heatmap and library pages
This commit is contained in:
SpecialX
2026-07-04 10:22:10 +08:00
parent 41fe8d8903
commit 25dca843be
45 changed files with 5295 additions and 210 deletions

View File

@@ -3,9 +3,20 @@
import { requirePermission } from "@/shared/lib/auth-guard";
import { handleActionError } from "@/shared/lib/action-utils";
import { Permissions } from "@/shared/types/permissions";
import { getKnowledgePointsByTextbookId } from "@/modules/textbooks/data-access";
import { suggestKnowledgePoints } from "./ai-suggest";
import { suggestKnowledgePointsSchema } from "./schema";
import { translateFieldErrors } from "./lib/i18n-errors";
import { generateLessonPlanFeedback, type AiFeedbackResult } from "./lib/ai-feedback";
import {
generateDifferentiationSuggestions,
checkCurriculumAlignment,
generateExplainableAssessment,
type DifferentiationSuggestion,
type CurriculumCheckItem,
type ExplainableAssessment,
} from "./lib/ai-differentiation";
import type { LessonPlanDocument } from "./types";
import type { ActionState } from "@/shared/types/action-state";
export async function suggestKnowledgePointsAction(input: {
@@ -45,3 +56,99 @@ export async function suggestKnowledgePointsAction(input: {
return handleActionError(e);
}
}
/**
* V5-17 A1/A2AI 反馈闭环。
* 调用 AI 对课案文档生成结构化反馈(含解释性展示)。
*/
export async function generateLessonPlanFeedbackAction(
doc: LessonPlanDocument,
): Promise<ActionState<AiFeedbackResult>> {
try {
await Promise.all([
requirePermission(Permissions.LESSON_PLAN_READ),
requirePermission(Permissions.AI_CHAT),
]);
const result = await generateLessonPlanFeedback(doc);
return { success: true, data: result };
} catch (e) {
return handleActionError(e);
}
}
/**
* V5-21 A3AI 差异化教学建议生成。
* 根据课案内容生成基础/提高/拓展三个层次的教学建议。
*/
export async function generateDifferentiationSuggestionsAction(
doc: LessonPlanDocument,
): Promise<ActionState<{ items: DifferentiationSuggestion[] }>> {
try {
await Promise.all([
requirePermission(Permissions.LESSON_PLAN_READ),
requirePermission(Permissions.AI_CHAT),
]);
const items = await generateDifferentiationSuggestions(doc);
return { success: true, data: { items } };
} catch (e) {
return handleActionError(e);
}
}
/**
* V5-21 A4AI 课标实时核对。
* 检查课案是否覆盖教材课标要求。
*/
export async function checkCurriculumAlignmentAction(
doc: LessonPlanDocument,
knowledgePoints: { id: string; name: string }[],
): Promise<ActionState<{ items: CurriculumCheckItem[] }>> {
try {
await Promise.all([
requirePermission(Permissions.LESSON_PLAN_READ),
requirePermission(Permissions.AI_CHAT),
]);
const items = await checkCurriculumAlignment(doc, knowledgePoints);
return { success: true, data: { items } };
} catch (e) {
return handleActionError(e);
}
}
/**
* V5-21 A5AI 可解释评估。
* 对课案中的练习节点给出可解释的评分依据。
*/
export async function generateExplainableAssessmentAction(
doc: LessonPlanDocument,
): Promise<ActionState<{ items: ExplainableAssessment[] }>> {
try {
await Promise.all([
requirePermission(Permissions.LESSON_PLAN_READ),
requirePermission(Permissions.AI_CHAT),
]);
const items = await generateExplainableAssessment(doc);
return { success: true, data: { items } };
} catch (e) {
return handleActionError(e);
}
}
/**
* V5-21 A4 辅助:按教材 ID 获取知识点列表(仅 id + name
* 供课标核对 Tab 按需加载,避免编辑页首屏负担。
*/
export async function getKnowledgePointsForAlignmentAction(
textbookId: string,
): Promise<ActionState<{ items: { id: string; name: string }[] }>> {
try {
await requirePermission(Permissions.LESSON_PLAN_READ);
const kps = await getKnowledgePointsByTextbookId(textbookId);
return {
success: true,
data: { items: kps.map((kp) => ({ id: kp.id, name: kp.name })) },
};
} catch (e) {
return handleActionError(e);
}
}