"use server"; import { revalidatePath } from "next/cache"; import { getTranslations } from "next-intl/server"; import { requirePermission, } from "@/shared/lib/auth-guard"; import { Permissions } from "@/shared/types/permissions"; import { handleActionError, safeParseDate } from "@/shared/lib/action-utils"; import { getLessonPlanById } from "./data-access"; import { publishLessonPlanHomework, PublishServiceError } from "./publish-service"; import { publishLessonPlanHomeworkSchema } from "./schema"; import { translateFieldErrors } from "./lib/i18n-errors"; import type { ActionState } from "./types"; export async function publishLessonPlanHomeworkAction(input: { planId: string; blockId: string; classIds: string[]; availableAt?: string; dueAt?: string; }): Promise> { const t = await getTranslations("lessonPreparation"); try { const parsed = publishLessonPlanHomeworkSchema.safeParse(input); if (!parsed.success) { const errors = await translateFieldErrors(parsed.error.flatten().fieldErrors); return { success: false, errors }; } const ctx = await requirePermission( Permissions.LESSON_PLAN_PUBLISH, ); await requirePermission(Permissions.HOMEWORK_CREATE); // P0-6 修复:先查询课案标题,用于作业标题的 i18n 翻译 // (原代码错误地传入 planId 作为 title 参数) const plan = await getLessonPlanById(parsed.data.planId, ctx.userId); if (!plan) { return { success: false, message: t("error.notFound") }; } const homeworkTitle = t("publish.homeworkTitle", { title: plan.title }); const homeworkDescription = t("publish.homeworkDescription"); const availableAtLabel = t("publish.availableAtLabel"); const dueAtLabel = t("publish.dueAtLabel"); const result = await publishLessonPlanHomework({ planId: parsed.data.planId, blockId: parsed.data.blockId, userId: ctx.userId, classIds: parsed.data.classIds, availableAt: parsed.data.availableAt ? safeParseDate(parsed.data.availableAt, availableAtLabel) : undefined, dueAt: parsed.data.dueAt ? safeParseDate(parsed.data.dueAt, dueAtLabel) : undefined, homeworkTitle, homeworkDescription, }); revalidatePath("/teacher/lesson-plans"); revalidatePath("/teacher/homework"); return { success: true, data: { examId: result.examId, assignmentId: result.assignmentId, }, }; } catch (e) { // publish-service 抛出 PublishServiceError(含 code),翻译为 i18n 消息 if (e instanceof PublishServiceError) { const messageKey = PUBLISH_ERROR_KEY_MAP[e.code] ?? "error.publish"; return { success: false, message: t(messageKey) }; } return handleActionError(e); } } // publish-service 错误码 → i18n 键映射 const PUBLISH_ERROR_KEY_MAP: Record = { PLAN_NOT_FOUND: "publish.planNotFound", NO_PERMISSION: "publish.noPermission", NO_EXERCISE_BLOCK: "publish.noExerciseBlock", NO_QUESTIONS: "publish.noQuestions", ALREADY_PUBLISHED: "publish.alreadyPublished", NO_SUBJECT_OR_GRADE: "publish.noSubjectOrGrade", NO_STUDENTS: "publish.noStudents", INVALID_QUESTION_TYPE: "error.invalidQuestionType", };