refactor(actions): 组 B 模块迁移至 invalidateFor(exams/grades/homework/attendance/leave-requests/diagnostic/error-book/adaptive-practice)
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
|
|
||||||
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { Permissions, type AuthContext } from "@/shared/types/permissions"
|
import { Permissions, type AuthContext } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
import { handleActionError } from "@/shared/lib/action-utils"
|
import { handleActionError } from "@/shared/lib/action-utils"
|
||||||
@@ -221,7 +220,7 @@ export async function createPracticeSessionAction(
|
|||||||
questionCount: parsed.data.questionCount,
|
questionCount: parsed.data.questionCount,
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/student/practice")
|
await invalidateFor("adaptive-practice.create")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -269,7 +268,7 @@ export async function submitPracticeAnswerAction(
|
|||||||
skip ?? false,
|
skip ?? false,
|
||||||
)
|
)
|
||||||
|
|
||||||
revalidatePath(`/student/practice/${sessionId}`)
|
await invalidateFor("adaptive-practice.submit")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -305,8 +304,7 @@ export async function completePracticeSessionAction(
|
|||||||
|
|
||||||
await completePracticeSession(parsed.data.sessionId, targetStudentId)
|
await completePracticeSession(parsed.data.sessionId, targetStudentId)
|
||||||
|
|
||||||
revalidatePath("/student/practice")
|
await invalidateFor("adaptive-practice.complete")
|
||||||
revalidatePath(`/student/practice/${parsed.data.sessionId}`)
|
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -339,7 +337,7 @@ export async function abandonPracticeSessionAction(
|
|||||||
|
|
||||||
await abandonPracticeSession(parsed.data.sessionId, targetStudentId)
|
await abandonPracticeSession(parsed.data.sessionId, targetStudentId)
|
||||||
|
|
||||||
revalidatePath("/student/practice")
|
await invalidateFor("adaptive-practice.abandon")
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
@@ -95,7 +95,7 @@ export async function recordAttendanceAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = await createAttendanceRecord(parsed.data, ctx.userId)
|
const id = await createAttendanceRecord(parsed.data, ctx.userId)
|
||||||
revalidatePath("/teacher/attendance")
|
await invalidateFor("attendance.record")
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "attendance.recorded",
|
event: "attendance.recorded",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -135,7 +135,7 @@ export async function batchRecordAttendanceAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const count = await batchCreateAttendanceRecords(parsed.data, ctx.userId)
|
const count = await batchCreateAttendanceRecords(parsed.data, ctx.userId)
|
||||||
revalidatePath("/teacher/attendance")
|
await invalidateFor("attendance.batchRecord")
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "attendance.batch_recorded",
|
event: "attendance.batch_recorded",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -196,7 +196,7 @@ export async function updateAttendanceAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await updateAttendanceRecord(id, parsed.data)
|
await updateAttendanceRecord(id, parsed.data)
|
||||||
revalidatePath("/teacher/attendance")
|
await invalidateFor("attendance.update")
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "attendance.updated",
|
event: "attendance.updated",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -223,7 +223,7 @@ export async function deleteAttendanceAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await deleteAttendanceRecord(id)
|
await deleteAttendanceRecord(id)
|
||||||
revalidatePath("/teacher/attendance")
|
await invalidateFor("attendance.delete")
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "attendance.deleted",
|
event: "attendance.deleted",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -265,7 +265,7 @@ export async function saveAttendanceRulesAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = await upsertAttendanceRules(parsed.data)
|
const id = await upsertAttendanceRules(parsed.data)
|
||||||
revalidatePath("/teacher/attendance")
|
await invalidateFor("attendance.saveRules")
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "attendance.rules_saved",
|
event: "attendance.rules_saved",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
import { handleActionError } from "@/shared/lib/action-utils"
|
import { handleActionError } from "@/shared/lib/action-utils"
|
||||||
@@ -48,8 +48,7 @@ export async function generateStudentReportAction(
|
|||||||
|
|
||||||
const { studentId, period } = parsed.data
|
const { studentId, period } = parsed.data
|
||||||
const id = await generateDiagnosticReport(studentId, period, ctx.userId)
|
const id = await generateDiagnosticReport(studentId, period, ctx.userId)
|
||||||
revalidatePath("/teacher/diagnostic")
|
await invalidateFor("diagnostic.generateStudentReport")
|
||||||
revalidatePath(`/teacher/diagnostic/student/${studentId}`)
|
|
||||||
return { success: true, message: "Diagnostic report generated", data: id }
|
return { success: true, message: "Diagnostic report generated", data: id }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -74,8 +73,7 @@ export async function generateClassReportAction(
|
|||||||
|
|
||||||
const { classId, period } = parsed.data
|
const { classId, period } = parsed.data
|
||||||
const id = await generateClassDiagnosticReport(classId, period, ctx.userId)
|
const id = await generateClassDiagnosticReport(classId, period, ctx.userId)
|
||||||
revalidatePath("/teacher/diagnostic")
|
await invalidateFor("diagnostic.generateClassReport")
|
||||||
revalidatePath(`/teacher/diagnostic/class/${classId}`)
|
|
||||||
return { success: true, message: "Class diagnostic report generated", data: id }
|
return { success: true, message: "Class diagnostic report generated", data: id }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -100,8 +98,7 @@ export async function generateGradeReportAction(
|
|||||||
|
|
||||||
const { gradeId, period } = parsed.data
|
const { gradeId, period } = parsed.data
|
||||||
const id = await generateGradeDiagnosticReport(gradeId, period, ctx.userId)
|
const id = await generateGradeDiagnosticReport(gradeId, period, ctx.userId)
|
||||||
revalidatePath("/teacher/diagnostic")
|
await invalidateFor("diagnostic.generateGradeReport")
|
||||||
revalidatePath("/admin/diagnostic")
|
|
||||||
return { success: true, message: "Grade diagnostic report generated", data: id }
|
return { success: true, message: "Grade diagnostic report generated", data: id }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -130,7 +127,7 @@ export async function publishReportAction(
|
|||||||
// - 班级报告:通知全班学生 + 全班学生家长
|
// - 班级报告:通知全班学生 + 全班学生家长
|
||||||
const report = await getDiagnosticReportById(parsed.data.id)
|
const report = await getDiagnosticReportById(parsed.data.id)
|
||||||
if (!report) {
|
if (!report) {
|
||||||
revalidatePath("/teacher/diagnostic")
|
await invalidateFor("diagnostic.publish")
|
||||||
return { success: true, message: "Report published" }
|
return { success: true, message: "Report published" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +183,7 @@ export async function publishReportAction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/diagnostic")
|
await invalidateFor("diagnostic.publish")
|
||||||
return { success: true, message: "Report published" }
|
return { success: true, message: "Report published" }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -209,7 +206,7 @@ export async function deleteReportAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await deleteDiagnosticReport(parsed.data.id)
|
await deleteDiagnosticReport(parsed.data.id)
|
||||||
revalidatePath("/teacher/diagnostic")
|
await invalidateFor("diagnostic.delete")
|
||||||
return { success: true, message: "Report deleted" }
|
return { success: true, message: "Report deleted" }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ export async function createErrorBookItemAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = await createErrorBookItem(ctx.userId, parsed.data)
|
const id = await createErrorBookItem(ctx.userId, parsed.data)
|
||||||
revalidatePath("/student/error-book")
|
await invalidateFor("error-book.create")
|
||||||
|
|
||||||
return { success: true, message: "错题已添加", data: id }
|
return { success: true, message: "错题已添加", data: id }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -198,7 +198,7 @@ export async function updateErrorBookNoteAction(
|
|||||||
const { itemId, ...input } = parsed.data
|
const { itemId, ...input } = parsed.data
|
||||||
await updateErrorBookNote(itemId, ctx.userId, input)
|
await updateErrorBookNote(itemId, ctx.userId, input)
|
||||||
|
|
||||||
revalidatePath("/student/error-book")
|
await invalidateFor("error-book.update")
|
||||||
|
|
||||||
return { success: true, message: "笔记已更新" }
|
return { success: true, message: "笔记已更新" }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -233,7 +233,7 @@ export async function reviewErrorBookItemAction(
|
|||||||
|
|
||||||
await recordReview(parsed.data.itemId, ctx.userId, parsed.data.result)
|
await recordReview(parsed.data.itemId, ctx.userId, parsed.data.result)
|
||||||
|
|
||||||
revalidatePath("/student/error-book")
|
await invalidateFor("error-book.review")
|
||||||
|
|
||||||
return { success: true, message: "复习结果已记录" }
|
return { success: true, message: "复习结果已记录" }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -259,7 +259,7 @@ export async function deleteErrorBookItemAction(
|
|||||||
|
|
||||||
await deleteErrorBookItem(itemId, ctx.userId)
|
await deleteErrorBookItem(itemId, ctx.userId)
|
||||||
|
|
||||||
revalidatePath("/student/error-book")
|
await invalidateFor("error-book.delete")
|
||||||
|
|
||||||
return { success: true, message: "错题已删除" }
|
return { success: true, message: "错题已删除" }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -285,7 +285,7 @@ export async function archiveErrorBookItemAction(
|
|||||||
|
|
||||||
await archiveErrorBookItem(itemId, ctx.userId)
|
await archiveErrorBookItem(itemId, ctx.userId)
|
||||||
|
|
||||||
revalidatePath("/student/error-book")
|
await invalidateFor("error-book.archive")
|
||||||
|
|
||||||
return { success: true, message: "错题已归档" }
|
return { success: true, message: "错题已归档" }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -322,7 +322,7 @@ export async function collectFromSubmissionAction(
|
|||||||
? await collectFromExamSubmission(parsed.data.submissionId, ctx.userId)
|
? await collectFromExamSubmission(parsed.data.submissionId, ctx.userId)
|
||||||
: await collectFromHomeworkSubmission(parsed.data.submissionId, ctx.userId)
|
: await collectFromHomeworkSubmission(parsed.data.submissionId, ctx.userId)
|
||||||
|
|
||||||
revalidatePath("/student/error-book")
|
await invalidateFor("error-book.collect")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
* - 共享辅助函数:convertStructureNode(递归转换 EditorStructureNode → AiGeneratedStructureNode)
|
* - 共享辅助函数:convertStructureNode(递归转换 EditorStructureNode → AiGeneratedStructureNode)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
@@ -169,7 +169,7 @@ export async function createExamFromRichEditorAction(
|
|||||||
examModeConfig: parseExamModeConfig(formData),
|
examModeConfig: parseExamModeConfig(formData),
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.create")
|
||||||
return successState(context.examId, t("exam.actionMessages.draftCreated"))
|
return successState(context.examId, t("exam.actionMessages.draftCreated"))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof PermissionDeniedError) {
|
if (error instanceof PermissionDeniedError) {
|
||||||
@@ -279,8 +279,7 @@ export async function updateExamFromRichEditorAction(
|
|||||||
orderedQuestions,
|
orderedQuestions,
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.update")
|
||||||
revalidatePath(`/teacher/exams/${input.examId}/build`)
|
|
||||||
return successState(input.examId, t("exam.actionMessages.examUpdated"))
|
return successState(input.examId, t("exam.actionMessages.examUpdated"))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof PermissionDeniedError) {
|
if (error instanceof PermissionDeniedError) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
@@ -193,7 +193,7 @@ export async function createExamAction(
|
|||||||
return failState<string>(t("dbCreateFailed"))
|
return failState<string>(t("dbCreateFailed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.create")
|
||||||
|
|
||||||
return successState(context.examId, t("createdSuccess"))
|
return successState(context.examId, t("createdSuccess"))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -314,7 +314,7 @@ export async function createAiExamAction(
|
|||||||
return failState<string>(t("dbCreateFailed"))
|
return failState<string>(t("dbCreateFailed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.createAi")
|
||||||
|
|
||||||
// V3-4: 埋点监控(AI 生成考试)
|
// V3-4: 埋点监控(AI 生成考试)
|
||||||
await trackExamEvent("exam.ai_generated", {
|
await trackExamEvent("exam.ai_generated", {
|
||||||
@@ -496,7 +496,7 @@ export async function updateExamAction(
|
|||||||
return failState<string>(t("dbUpdateFailed"))
|
return failState<string>(t("dbUpdateFailed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.update")
|
||||||
|
|
||||||
// V3-4: 埋点监控
|
// V3-4: 埋点监控
|
||||||
await trackExamEvent("exam.updated", {
|
await trackExamEvent("exam.updated", {
|
||||||
@@ -554,7 +554,7 @@ export async function deleteExamAction(
|
|||||||
return failState<string>(t("dbDeleteFailed"))
|
return failState<string>(t("dbDeleteFailed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.delete")
|
||||||
|
|
||||||
// V3-4: 埋点监控
|
// V3-4: 埋点监控
|
||||||
await trackExamEvent("exam.deleted", {
|
await trackExamEvent("exam.deleted", {
|
||||||
@@ -608,7 +608,7 @@ export async function duplicateExamAction(
|
|||||||
return failState<string>(t("dbDuplicateFailed"))
|
return failState<string>(t("dbDuplicateFailed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/exams/all")
|
await invalidateFor("exams.duplicate")
|
||||||
|
|
||||||
// V3-4: 埋点监控
|
// V3-4: 埋点监控
|
||||||
await trackExamEvent("exam.duplicated", {
|
await trackExamEvent("exam.duplicated", {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
@@ -83,7 +83,7 @@ export async function createGradeAppealAction(
|
|||||||
expectedScore: parsed.data.expectedScore,
|
expectedScore: parsed.data.expectedScore,
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/student/grades")
|
await invalidateFor("grades.appeal.create")
|
||||||
return { success: true, message: t("appeal.created"), data: id }
|
return { success: true, message: t("appeal.created"), data: id }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -101,7 +101,7 @@ export async function withdrawGradeAppealAction(
|
|||||||
|
|
||||||
await withdrawGradeAppeal({ appealId, studentId: ctx.userId })
|
await withdrawGradeAppeal({ appealId, studentId: ctx.userId })
|
||||||
|
|
||||||
revalidatePath("/student/grades")
|
await invalidateFor("grades.appeal.withdraw")
|
||||||
return { success: true, data: { withdrawn: true } }
|
return { success: true, data: { withdrawn: true } }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -176,8 +176,7 @@ export async function reviewGradeAppealAction(
|
|||||||
adjustedScore: parsed.data.adjustedScore,
|
adjustedScore: parsed.data.adjustedScore,
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.appeal.review")
|
||||||
revalidatePath("/student/grades")
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: parsed.data.decision === "approved"
|
message: parsed.data.decision === "approved"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
@@ -114,7 +114,7 @@ export async function deleteGradeDraftAction(params: {
|
|||||||
type: params.type,
|
type: params.type,
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.draft.delete")
|
||||||
return { success: true, data: { deleted: true } }
|
return { success: true, data: { deleted: true } }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
|
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
@@ -207,9 +207,7 @@ export async function importGradesFromExcelAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 刷新缓存
|
// 刷新缓存
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.import")
|
||||||
revalidatePath("/teacher/grades/entry")
|
|
||||||
revalidatePath(`/teacher/grades?classId=${parsed.data.classId}`)
|
|
||||||
|
|
||||||
const result: GradeImportResult = {
|
const result: GradeImportResult = {
|
||||||
successCount: createdIds.length,
|
successCount: createdIds.length,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
@@ -119,7 +119,7 @@ export async function createGradeRecordAction(
|
|||||||
} catch {
|
} catch {
|
||||||
// 通知失败不阻断成绩录入
|
// 通知失败不阻断成绩录入
|
||||||
}
|
}
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.create")
|
||||||
return { success: true, message: t("action.recordCreated"), data: id }
|
return { success: true, message: t("action.recordCreated"), data: id }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -204,7 +204,7 @@ export async function batchCreateGradeRecordsAction(
|
|||||||
// 异常检测失败不阻断成绩录入
|
// 异常检测失败不阻断成绩录入
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.batchCreate")
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: t("action.recordsCreated", { count: ids.length }),
|
message: t("action.recordsCreated", { count: ids.length }),
|
||||||
@@ -338,7 +338,7 @@ export async function batchCreateGradeRecordsByExamAction(
|
|||||||
// 异常检测失败不阻断成绩录入
|
// 异常检测失败不阻断成绩录入
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.batchCreateByExam")
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: t("action.recordsCreated", { count: ids.length }),
|
message: t("action.recordsCreated", { count: ids.length }),
|
||||||
@@ -370,7 +370,7 @@ export async function undoBatchCreateGradeRecordsAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deletedCount = await undoBatchCreateGradeRecords(ids, ctx.userId)
|
const deletedCount = await undoBatchCreateGradeRecords(ids, ctx.userId)
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.undoBatchCreate")
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: t("action.recordsUndoneCount", { count: deletedCount }),
|
message: t("action.recordsUndoneCount", { count: deletedCount }),
|
||||||
@@ -409,7 +409,7 @@ export async function updateGradeRecordAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await updateGradeRecord(id, parsed.data)
|
await updateGradeRecord(id, parsed.data)
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.update")
|
||||||
return { success: true, message: t("action.recordUpdated") }
|
return { success: true, message: t("action.recordUpdated") }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -433,7 +433,7 @@ export async function deleteGradeRecordAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await deleteGradeRecord(parsed.data.id)
|
await deleteGradeRecord(parsed.data.id)
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.delete")
|
||||||
return { success: true, message: t("action.recordDeleted") }
|
return { success: true, message: t("action.recordDeleted") }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return handleActionError(e)
|
return handleActionError(e)
|
||||||
@@ -461,7 +461,7 @@ export async function bulkDeleteGradeRecordsAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deletedCount = await bulkDeleteGradeRecords(ids)
|
const deletedCount = await bulkDeleteGradeRecords(ids)
|
||||||
revalidatePath("/teacher/grades")
|
await invalidateFor("grades.bulkDelete")
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: t("action.recordsDeletedCount", { count: deletedCount }),
|
message: t("action.recordsDeletedCount", { count: deletedCount }),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { createId } from "@paralleldrive/cuid2"
|
import { createId } from "@paralleldrive/cuid2"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
@@ -206,8 +206,7 @@ export async function createHomeworkAssignmentAction(
|
|||||||
targetStudentIds,
|
targetStudentIds,
|
||||||
})
|
})
|
||||||
|
|
||||||
revalidatePath("/teacher/homework/assignments")
|
await invalidateFor("homework.create")
|
||||||
revalidatePath("/teacher/homework/submissions")
|
|
||||||
|
|
||||||
// V3-4: 埋点监控
|
// V3-4: 埋点监控
|
||||||
await trackExamEvent("homework.created", {
|
await trackExamEvent("homework.created", {
|
||||||
@@ -241,7 +240,7 @@ export async function startHomeworkSubmissionAction(
|
|||||||
return { success: false, message: result.error }
|
return { success: false, message: result.error }
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/student/learning/assignments")
|
await invalidateFor("homework.startSubmission")
|
||||||
|
|
||||||
await trackExamEvent("homework.started", {
|
await trackExamEvent("homework.started", {
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -327,8 +326,7 @@ export async function submitHomeworkAction(
|
|||||||
await runPostGradingHooks(submissionId, ctx.userId)
|
await runPostGradingHooks(submissionId, ctx.userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/homework/submissions")
|
await invalidateFor("homework.submit")
|
||||||
revalidatePath("/student/learning/assignments")
|
|
||||||
|
|
||||||
// V3-4: 埋点监控
|
// V3-4: 埋点监控
|
||||||
await trackExamEvent("homework.submitted", {
|
await trackExamEvent("homework.submitted", {
|
||||||
@@ -397,7 +395,7 @@ export async function gradeHomeworkSubmissionAction(
|
|||||||
// 批改完成后自动采集错题 + 更新掌握度
|
// 批改完成后自动采集错题 + 更新掌握度
|
||||||
await runPostGradingHooks(submissionId, submissionForGrading.studentId)
|
await runPostGradingHooks(submissionId, submissionForGrading.studentId)
|
||||||
|
|
||||||
revalidatePath("/teacher/homework/submissions")
|
await invalidateFor("homework.grade")
|
||||||
|
|
||||||
// V3-4: 埋点监控
|
// V3-4: 埋点监控
|
||||||
await trackExamEvent("homework.graded", {
|
await trackExamEvent("homework.graded", {
|
||||||
@@ -466,8 +464,7 @@ export async function batchAutoGradeSubmissionsAction(
|
|||||||
.map((r) => runPostGradingHooks(r.submissionId, r.studentId)),
|
.map((r) => runPostGradingHooks(r.submissionId, r.studentId)),
|
||||||
)
|
)
|
||||||
|
|
||||||
revalidatePath("/teacher/homework/submissions")
|
await invalidateFor("homework.batchAutoGrade")
|
||||||
revalidatePath("/teacher/homework/assignments")
|
|
||||||
|
|
||||||
await trackExamEvent("homework.graded", {
|
await trackExamEvent("homework.graded", {
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use server"
|
"use server"
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache"
|
|
||||||
import { getTranslations } from "next-intl/server"
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { invalidateFor } from "@/shared/lib/cache"
|
||||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||||
import { Permissions } from "@/shared/types/permissions"
|
import { Permissions } from "@/shared/types/permissions"
|
||||||
import type { ActionState } from "@/shared/types/action-state"
|
import type { ActionState } from "@/shared/types/action-state"
|
||||||
@@ -89,9 +89,7 @@ export async function createLeaveRequestAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const id = await createLeaveRequest(parsed.data, ctx.userId)
|
const id = await createLeaveRequest(parsed.data, ctx.userId)
|
||||||
revalidatePath("/parent/leave")
|
await invalidateFor("leave-requests.create")
|
||||||
revalidatePath("/student/leave")
|
|
||||||
revalidatePath("/teacher/leave")
|
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "leave_request.created",
|
event: "leave_request.created",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -175,9 +173,7 @@ export async function reviewLeaveRequestAction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/teacher/leave")
|
await invalidateFor("leave-requests.review")
|
||||||
revalidatePath("/parent/leave")
|
|
||||||
revalidatePath(`/teacher/leave/${id}`)
|
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "leave_request.reviewed",
|
event: "leave_request.reviewed",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
@@ -221,9 +217,7 @@ export async function cancelLeaveRequestAction(
|
|||||||
return { success: false, message: t("errors.cannotCancel") }
|
return { success: false, message: t("errors.cannotCancel") }
|
||||||
}
|
}
|
||||||
|
|
||||||
revalidatePath("/parent/leave")
|
await invalidateFor("leave-requests.cancel")
|
||||||
revalidatePath("/student/leave")
|
|
||||||
revalidatePath("/teacher/leave")
|
|
||||||
await trackEvent({
|
await trackEvent({
|
||||||
event: "leave_request.cancelled",
|
event: "leave_request.cancelled",
|
||||||
userId: ctx.userId,
|
userId: ctx.userId,
|
||||||
|
|||||||
Reference in New Issue
Block a user