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

@@ -18,6 +18,11 @@ import {
} from "../actions";
import { getKnowledgePointOptionsAction } from "../actions-kp";
import { publishLessonPlanHomeworkAction } from "../actions-publish";
import {
getLessonPlanAttachmentsAction,
createLessonPlanAttachmentAction,
deleteLessonPlanAttachmentAction,
} from "../actions-attachments";
import type { LessonPlanDataService } from "../providers/lesson-plan-provider";
/**
@@ -148,5 +153,51 @@ export function createDefaultDataService(): LessonPlanDataService {
}
return { success: false, message: res.message, errors: res.errors };
},
// V5-5M6 附件库 UI 集成
async getLessonPlanAttachments(planId) {
const res = await getLessonPlanAttachmentsAction(planId);
if (res.success && res.data) {
// 将 DB 层的 Date 转为 ISO string 以匹配 LessonPlanAttachmentOption 类型
const items = res.data.items.map((a) => ({
id: a.id,
planId: a.planId,
blockId: a.blockId ?? undefined,
fileId: a.fileId,
displayName: a.displayName,
attachmentType: a.attachmentType,
uploadedBy: a.uploadedBy,
createdAt: a.createdAt instanceof Date ? a.createdAt.toISOString() : a.createdAt,
}));
return { success: true, data: { items } };
}
return { success: false, message: res.message };
},
async createLessonPlanAttachment(input) {
const res = await createLessonPlanAttachmentAction(input);
if (res.success && res.data) {
const a = res.data.attachment;
const attachment = a
? {
id: a.id,
planId: a.planId,
blockId: a.blockId ?? undefined,
fileId: a.fileId,
displayName: a.displayName,
attachmentType: a.attachmentType,
uploadedBy: a.uploadedBy,
createdAt: a.createdAt instanceof Date ? a.createdAt.toISOString() : a.createdAt,
}
: null;
return { success: true, data: { attachment } };
}
return { success: false, message: res.message };
},
async deleteLessonPlanAttachment(attachmentId) {
const res = await deleteLessonPlanAttachmentAction(attachmentId);
return { success: res.success, message: res.message };
},
};
}