- 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
204 lines
7.1 KiB
TypeScript
204 lines
7.1 KiB
TypeScript
"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-5:M6 附件库 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 };
|
||
},
|
||
};
|
||
}
|