Files
NextEdu/src/modules/lesson-preparation/services/default-data-service.ts
SpecialX 25dca843be 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
2026-07-04 10:22:10 +08:00

204 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import {
getLessonPlansAction,
getLessonPlanByIdAction,
updateLessonPlanAction,
saveLessonPlanVersionAction,
getLessonPlanVersionsAction,
revertLessonPlanVersionAction,
duplicateLessonPlanAction,
deleteLessonPlanAction,
publishLessonPlanAction,
unpublishLessonPlanAction,
createLessonPlanAction,
getTextbooksForPickerAction,
getChaptersForPickerAction,
getLessonPlanTemplatesAction,
} 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";
/**
* 默认数据服务实现:包装现有 Server Actions。
* 通过 LessonPlanProvider 注入,组件不直接 import actions。
* 测试时可替换为 mock 实现。
*
* V3 扩展:新增 picker/dialog 组件所需方法createLessonPlan / getTextbooksForPicker /
* getChaptersForPicker / getLessonPlanTemplates / getKnowledgePointOptions /
* publishLessonPlanHomework
*
* V4 P0-4 修复:移除 `getQuestions` 方法及其对 `@/modules/questions/actions` 的直接 import
* 改由独立的 `QuestionService`(见 default-question-service.ts注入。
*/
export function createDefaultDataService(): LessonPlanDataService {
return {
async getLessonPlans(params) {
const res = await getLessonPlansAction(params ?? {});
if (res.success && res.data) {
return { success: true, data: { items: res.data.items } };
}
return { success: false, message: res.message };
},
async getLessonPlanById(planId) {
const res = await getLessonPlanByIdAction(planId);
if (res.success && res.data) {
return { success: true, data: { plan: res.data.plan } };
}
return { success: false, message: res.message };
},
async updateLessonPlan(input) {
const res = await updateLessonPlanAction(input);
return { success: res.success, message: res.message };
},
async saveLessonPlanVersion(input) {
const res = await saveLessonPlanVersionAction(input);
if (res.success && res.data) {
return { success: true, data: { versionNo: res.data.versionNo } };
}
return { success: false, message: res.message };
},
async getLessonPlanVersions(planId) {
const res = await getLessonPlanVersionsAction(planId);
if (res.success && res.data) {
return { success: true, data: { versions: res.data.versions } };
}
return { success: false, message: res.message };
},
async revertLessonPlanVersion(params) {
const res = await revertLessonPlanVersionAction(params);
return { success: res.success, message: res.message };
},
async duplicateLessonPlan(planId) {
const res = await duplicateLessonPlanAction(planId);
return { success: res.success, message: res.message };
},
async deleteLessonPlan(planId) {
const res = await deleteLessonPlanAction(planId);
return { success: res.success, message: res.message };
},
async publishLessonPlan(planId) {
const res = await publishLessonPlanAction(planId);
return { success: res.success, message: res.message };
},
async unpublishLessonPlan(planId) {
const res = await unpublishLessonPlanAction(planId);
return { success: res.success, message: res.message };
},
// ---- V3 新增picker/dialog 组件所需方法 ----
async createLessonPlan(prevState, formData) {
const res = await createLessonPlanAction(prevState, formData);
if (res.success && res.data) {
return { success: true, data: { planId: res.data.planId } };
}
return { success: false, message: res.message, errors: res.errors };
},
async getTextbooksForPicker() {
const res = await getTextbooksForPickerAction();
if (res.success && res.data) {
return { success: true, data: { textbooks: res.data.textbooks } };
}
return { success: false, message: res.message };
},
async getChaptersForPicker(textbookId) {
const res = await getChaptersForPickerAction(textbookId);
if (res.success && res.data) {
return { success: true, data: { chapters: res.data.chapters } };
}
return { success: false, message: res.message };
},
async getLessonPlanTemplates() {
const res = await getLessonPlanTemplatesAction();
if (res.success && res.data) {
return { success: true, data: { templates: res.data.templates } };
}
return { success: false, message: res.message };
},
async getKnowledgePointOptions(input) {
const res = await getKnowledgePointOptionsAction(input);
if (res.success && res.data) {
return { success: true, data: { options: res.data.options } };
}
return { success: false, message: res.message, errors: res.errors };
},
async publishLessonPlanHomework(input) {
const res = await publishLessonPlanHomeworkAction(input);
if (res.success && res.data) {
return {
success: true,
data: { examId: res.data.examId, assignmentId: res.data.assignmentId },
};
}
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 };
},
};
}