/** * M5 形成性评价闭环 - Server Actions */ "use server"; import { z } from "zod"; import { revalidatePath } from "next/cache"; import { getFormativeItemsByPlanId, createFormativeItem, updateFormativeItem, deleteFormativeItem, submitFormativeResponse, getResponsesByItemId, getFormativeItemStats, } from "./data-access-formative"; import type { FormativeItem, FormativeResponse } from "./data-access-formative"; import type { ActionState } from "@/shared/types/action-state"; import { getAuthContext, requirePermission } from "@/shared/lib/auth-guard"; import { handleActionError } from "@/shared/lib/action-utils"; import { Permissions } from "@/shared/types/permissions"; const createFormativeItemSchema = z.object({ planId: z.string().min(1), blockId: z.string().min(1), interactionType: z.enum(["poll", "quiz", "exit_ticket"]), payload: z.record(z.string(), z.unknown()), instantFeedback: z.boolean().optional(), orderIndex: z.number().int().min(0).optional(), }); const submitResponseSchema = z.object({ itemId: z.string().min(1), classId: z.string().optional(), response: z.record(z.string(), z.unknown()), isCorrect: z.boolean().optional(), durationSec: z.number().int().min(0).optional(), }); /** * 查询课案互动组件 */ export async function getFormativeItemsAction( planId: string, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_READ); const items = await getFormativeItemsByPlanId(planId); return { success: true, data: { items } }; } catch (e) { return handleActionError(e); } } /** * 创建互动组件 */ export async function createFormativeItemAction( input: Record, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); const parseResult = createFormativeItemSchema.safeParse(input); if (!parseResult.success) { return { success: false, message: "Invalid input" }; } const item = await createFormativeItem(parseResult.data); revalidatePath(`/teacher/lesson-plans/${parseResult.data.planId}/edit`); return { success: true, data: { item } }; } catch (e) { return handleActionError(e); } } /** * 更新互动组件 */ export async function updateFormativeItemAction( id: string, patch: { payload?: unknown; instantFeedback?: boolean; orderIndex?: number }, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); await updateFormativeItem(id, patch); return { success: true, data: null }; } catch (e) { return handleActionError(e); } } /** * 删除互动组件 */ export async function deleteFormativeItemAction(id: string): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); await deleteFormativeItem(id); return { success: true, data: null }; } catch (e) { return handleActionError(e); } } /** * 学生提交作答 */ export async function submitFormativeResponseAction( input: Record, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_READ); const parseResult = submitResponseSchema.safeParse(input); if (!parseResult.success) { return { success: false, message: "Invalid input" }; } const auth = await getAuthContext(); if (!auth.userId) { return { success: false, message: "Unauthorized" }; } const response = await submitFormativeResponse({ ...parseResult.data, studentId: auth.userId, }); return { success: true, data: { response } }; } catch (e) { return handleActionError(e); } } /** * 查询互动组件作答列表(教师查看) */ export async function getFormativeResponsesAction( itemId: string, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_READ); const responses = await getResponsesByItemId(itemId); return { success: true, data: { responses } }; } catch (e) { return handleActionError(e); } } /** * 查询互动组件统计(教师实时反馈) */ export async function getFormativeItemStatsAction( itemId: string, ): Promise> }>> { try { await requirePermission(Permissions.LESSON_PLAN_READ); const stats = await getFormativeItemStats(itemId); return { success: true, data: { stats } }; } catch (e) { return handleActionError(e); } }