"use server"; 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: { doc: unknown; textbookId?: string; chapterId?: string; }): Promise< ActionState<{ suggestions: { id: string; name: string; reason: string }[]; }> > { try { const parsed = suggestKnowledgePointsSchema.safeParse(input); if (!parsed.success) { const errors = await translateFieldErrors(parsed.error.flatten().fieldErrors); return { success: false, errors }; } // 并行校验两个权限点 await Promise.all([ requirePermission(Permissions.LESSON_PLAN_READ), requirePermission(Permissions.AI_CHAT), ]); // P1 修复:从 unknown 安全提取 nodes 数组,显式类型标注替代隐式 any // Zod 已校验 doc 是 Record,但 nodes 字段需运行时检查 const doc = parsed.data.doc; const nodes: unknown[] = Array.isArray(doc.nodes) ? doc.nodes : []; const suggestions = await suggestKnowledgePoints( { nodes }, parsed.data.textbookId, parsed.data.chapterId, ); return { success: true, data: { suggestions } }; } catch (e) { // P1 修复:统一使用 handleActionError 处理错误,避免手动判断 PermissionDeniedError return handleActionError(e); } } /** * V5-17 A1/A2:AI 反馈闭环。 * 调用 AI 对课案文档生成结构化反馈(含解释性展示)。 */ export async function generateLessonPlanFeedbackAction( doc: LessonPlanDocument, ): Promise> { 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 A3:AI 差异化教学建议生成。 * 根据课案内容生成基础/提高/拓展三个层次的教学建议。 */ export async function generateDifferentiationSuggestionsAction( doc: LessonPlanDocument, ): Promise> { 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 A4:AI 课标实时核对。 * 检查课案是否覆盖教材课标要求。 */ export async function checkCurriculumAlignmentAction( doc: LessonPlanDocument, knowledgePoints: { id: string; name: string }[], ): Promise> { 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 A5:AI 可解释评估。 * 对课案中的练习节点给出可解释的评分依据。 */ export async function generateExplainableAssessmentAction( doc: LessonPlanDocument, ): Promise> { 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> { 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); } }