/** * M2 协同备课 - 评论 Server Actions */ "use server"; import { revalidatePath } from "next/cache"; import { z } from "zod"; import { getCommentsByPlanId, getCommentsByBlockId, createComment, updateCommentContent, toggleCommentResolved, deleteComment, countUnresolvedComments, } from "./data-access-comments"; import type { LessonPlanComment } from "./data-access-comments"; 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 createCommentSchema = z.object({ planId: z.string().min(1, "error.planIdRequired"), blockId: z.string().min(1, "error.blockIdRequired"), content: z.string().min(1, "error.contentRequired").max(2000, "error.contentTooLong"), parentCommentId: z.string().optional(), }); const updateCommentSchema = z.object({ commentId: z.string().min(1, "error.commentIdRequired"), content: z.string().min(1, "error.contentRequired").max(2000, "error.contentTooLong"), }); /** * 查询课案评论 */ export async function getLessonPlanCommentsAction( planId: string, blockId?: string, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_READ); const items = blockId ? await getCommentsByBlockId(planId, blockId) : await getCommentsByPlanId(planId); return { success: true, data: { items } }; } catch (e) { return handleActionError(e); } } /** * 创建评论 */ export async function createLessonPlanCommentAction( input: Record, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); const parseResult = createCommentSchema.safeParse(input); if (!parseResult.success) { return { success: false, message: "Invalid input", errors: Object.fromEntries( Object.entries(parseResult.error.flatten().fieldErrors), ), }; } const auth = await getAuthContext(); if (!auth.userId) { return { success: false, message: "Unauthorized" }; } const comment = await createComment(parseResult.data, auth.userId); revalidatePath(`/teacher/lesson-plans/${parseResult.data.planId}/edit`); return { success: true, data: { comment } }; } catch (e) { return handleActionError(e); } } /** * 更新评论 */ export async function updateLessonPlanCommentAction( input: Record, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); const parseResult = updateCommentSchema.safeParse(input); if (!parseResult.success) { return { success: false, message: "Invalid input" }; } await updateCommentContent(parseResult.data.commentId, parseResult.data.content); return { success: true, data: null }; } catch (e) { return handleActionError(e); } } /** * 切换评论解决状态 */ export async function toggleCommentResolvedAction( commentId: string, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); await toggleCommentResolved(commentId); return { success: true, data: null }; } catch (e) { return handleActionError(e); } } /** * 删除评论 */ export async function deleteLessonPlanCommentAction( commentId: string, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_UPDATE); await deleteComment(commentId); return { success: true, data: null }; } catch (e) { return handleActionError(e); } } /** * 统计未解决评论数(用于列表卡片徽章) */ export async function getUnresolvedCommentCountAction( planId: string, ): Promise> { try { await requirePermission(Permissions.LESSON_PLAN_READ); const count = await countUnresolvedComments(planId); return { success: true, data: { count } }; } catch (e) { return handleActionError(e); } }