refactor(classes): actions 迁移至 invalidateFor 集中编排
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { invalidateFor } from "@/shared/lib/cache"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||
import { handleActionError } from "@/shared/lib/action-utils"
|
||||
@@ -55,10 +55,7 @@ export async function createAdminClassAction(
|
||||
homeroom: homeroom ?? null,
|
||||
room: room ?? null,
|
||||
})
|
||||
revalidatePath("/admin/school/classes")
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.create")
|
||||
return { success: true, message: t("actions.classCreated"), data: id }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -114,10 +111,7 @@ export async function updateAdminClassAction(
|
||||
})
|
||||
}
|
||||
|
||||
revalidatePath("/admin/school/classes")
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.update", { id: validatedClassId })
|
||||
return { success: true, message: t("actions.classUpdated") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -139,10 +133,7 @@ export async function deleteAdminClassAction(classId: string): Promise<ActionSta
|
||||
|
||||
try {
|
||||
await deleteAdminClass(parsed.data.classId)
|
||||
revalidatePath("/admin/school/classes")
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.delete", { id: parsed.data.classId })
|
||||
return { success: true, message: t("actions.classDeleted") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { invalidateFor } from "@/shared/lib/cache"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||
import { handleActionError } from "@/shared/lib/action-utils"
|
||||
@@ -63,7 +63,7 @@ export async function createGradeClassAction(
|
||||
homeroom: homeroom ?? null,
|
||||
room: room ?? null,
|
||||
})
|
||||
revalidatePath("/management/grade/classes")
|
||||
await invalidateFor("classes.create")
|
||||
return { success: true, message: t("actions.classCreated"), data: id }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -138,7 +138,7 @@ export async function updateGradeClassAction(
|
||||
})
|
||||
}
|
||||
|
||||
revalidatePath("/management/grade/classes")
|
||||
await invalidateFor("classes.update", { id: validatedClassId })
|
||||
return { success: true, message: t("actions.classUpdated") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -173,7 +173,7 @@ export async function deleteGradeClassAction(classId: string): Promise<ActionSta
|
||||
|
||||
try {
|
||||
await deleteAdminClass(validatedClassId)
|
||||
revalidatePath("/management/grade/classes")
|
||||
await invalidateFor("classes.delete", { id: validatedClassId })
|
||||
return { success: true, message: t("actions.classDeleted") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { invalidateFor } from "@/shared/lib/cache"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||
import { handleActionError } from "@/shared/lib/action-utils"
|
||||
@@ -60,8 +60,7 @@ export async function enrollStudentByEmailAction(
|
||||
|
||||
try {
|
||||
await enrollStudentByEmail(parsed.data.classId, parsed.data.email)
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/my")
|
||||
await invalidateFor("classes.students.update", { classId: parsed.data.classId })
|
||||
return { success: true, message: t("actions.studentAdded") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -130,13 +129,7 @@ export async function joinClassByInvitationCodeAction(
|
||||
},
|
||||
})
|
||||
|
||||
if (hasStudentScope(ctx)) {
|
||||
revalidatePath("/student/learning/courses")
|
||||
revalidatePath("/student/schedule")
|
||||
} else {
|
||||
revalidatePath("/teacher/classes/my")
|
||||
}
|
||||
revalidatePath("/profile")
|
||||
await invalidateFor("classes.students.update", { classId })
|
||||
return { success: true, message: t("actions.joinedClass"), data: { classId } }
|
||||
} catch (error) {
|
||||
// 审计日志:加入失败
|
||||
@@ -170,8 +163,7 @@ export async function ensureClassInvitationCodeAction(classId: string): Promise<
|
||||
|
||||
try {
|
||||
const code = await ensureClassInvitationCode(classId)
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath(`/teacher/classes/my/${encodeURIComponent(classId)}`)
|
||||
await invalidateFor("classes.invitation.create", { classId })
|
||||
return { success: true, message: t("actions.invitationCodeReady"), data: { code } }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -192,8 +184,7 @@ export async function regenerateClassInvitationCodeAction(classId: string): Prom
|
||||
|
||||
try {
|
||||
const code = await regenerateClassInvitationCode(classId)
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath(`/teacher/classes/my/${encodeURIComponent(classId)}`)
|
||||
await invalidateFor("classes.invitation.create", { classId })
|
||||
return { success: true, message: t("actions.invitationCodeUpdated"), data: { code } }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -267,9 +258,7 @@ export async function createClassInvitationCodeAction(
|
||||
},
|
||||
})
|
||||
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath(`/teacher/classes/my/${encodeURIComponent(classId)}`)
|
||||
revalidatePath(`/admin/school/classes`)
|
||||
await invalidateFor("classes.invitation.create", { classId })
|
||||
return {
|
||||
success: true,
|
||||
message: t("actions.invitationCodeGenerated"),
|
||||
@@ -300,7 +289,8 @@ export async function revokeClassInvitationCodeAction(
|
||||
}
|
||||
|
||||
try {
|
||||
const { revokeInvitationCode } = await import("./data-access-invitations")
|
||||
const { revokeInvitationCode, getClassIdByCodeId } = await import("./data-access-invitations")
|
||||
const classId = await getClassIdByCodeId(codeId)
|
||||
await revokeInvitationCode(codeId, ctx.userId)
|
||||
|
||||
const { logAudit } = await import("@/shared/lib/audit-logger")
|
||||
@@ -312,8 +302,9 @@ export async function revokeClassInvitationCodeAction(
|
||||
detail: { revokedBy: ctx.userId },
|
||||
})
|
||||
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath(`/admin/school/classes`)
|
||||
if (classId) {
|
||||
await invalidateFor("classes.invitation.revoke", { classId })
|
||||
}
|
||||
return { success: true, message: t("actions.invitationCodeRevoked") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -383,8 +374,7 @@ export async function setStudentEnrollmentStatusAction(
|
||||
|
||||
try {
|
||||
await setStudentEnrollmentStatus(classId, studentId, status)
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/my")
|
||||
await invalidateFor("classes.students.update", { classId })
|
||||
return { success: true, message: t("actions.studentUpdated") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -448,8 +438,7 @@ export async function bulkEnrollStudentsAction(
|
||||
}
|
||||
}
|
||||
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/admin/school/classes")
|
||||
await invalidateFor("classes.students.update", { classId })
|
||||
return {
|
||||
success: true,
|
||||
message: t("actions.bulkImportResult", { imported, failed }),
|
||||
@@ -510,7 +499,7 @@ export async function bulkAssignSubjectTeachersAction(
|
||||
}
|
||||
}
|
||||
|
||||
revalidatePath("/admin/school/classes")
|
||||
// 当前为 stub 实现(无 DB 写入),暂不触发缓存失效
|
||||
return {
|
||||
success: true,
|
||||
message: t("actions.bulkAssignResult", { updated, failed }),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { invalidateFor } from "@/shared/lib/cache"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||
import { Permissions } from "@/shared/types/permissions"
|
||||
@@ -72,7 +72,7 @@ export async function createClassScheduleItemAction(
|
||||
course,
|
||||
location: location ?? null,
|
||||
})
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.schedule.update", { classId })
|
||||
return { success: true, message: t("actions.scheduleItemCreated"), data: id }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -126,7 +126,7 @@ export async function updateClassScheduleItemAction(
|
||||
course: course ?? undefined,
|
||||
location: location ?? undefined,
|
||||
})
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.schedule.update", { classId: targetClassId })
|
||||
return { success: true, message: t("actions.scheduleItemUpdated") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -156,7 +156,7 @@ export async function deleteClassScheduleItemAction(scheduleId: string): Promise
|
||||
|
||||
try {
|
||||
await deleteClassScheduleItem(parsed.data.scheduleId)
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.schedule.update", { classId: targetClassId })
|
||||
return { success: true, message: t("actions.scheduleItemDeleted") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use server"
|
||||
|
||||
import { revalidatePath } from "next/cache"
|
||||
import { invalidateFor } from "@/shared/lib/cache"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { requirePermission } from "@/shared/lib/auth-guard"
|
||||
import { Permissions } from "@/shared/types/permissions"
|
||||
@@ -67,9 +67,7 @@ export async function createTeacherClassAction(
|
||||
homeroom: homeroom ?? null,
|
||||
room: room ?? null,
|
||||
})
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.create")
|
||||
return { success: true, message: t("actions.classCreated"), data: id }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -122,9 +120,7 @@ export async function updateTeacherClassAction(
|
||||
homeroom: homeroom ?? undefined,
|
||||
room: room ?? undefined,
|
||||
})
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.update", { id: validatedClassId })
|
||||
return { success: true, message: t("actions.classUpdated") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
@@ -154,9 +150,7 @@ export async function deleteTeacherClassAction(classId: string): Promise<ActionS
|
||||
|
||||
try {
|
||||
await deleteTeacherClass(parsed.data.classId)
|
||||
revalidatePath("/teacher/classes/my")
|
||||
revalidatePath("/teacher/classes/students")
|
||||
revalidatePath("/teacher/classes/schedule")
|
||||
await invalidateFor("classes.delete", { id: parsed.data.classId })
|
||||
return { success: true, message: t("actions.classDeleted") }
|
||||
} catch (error) {
|
||||
return handleActionError(error)
|
||||
|
||||
@@ -307,6 +307,18 @@ export async function consumeInvitationCode(code: string): Promise<void> {
|
||||
.where(eq(classInvitationCodes.code, normalized))
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据邀请码 ID 查询所属班级 ID(用于缓存失效参数填充)。
|
||||
*/
|
||||
export async function getClassIdByCodeId(codeId: string): Promise<string | null> {
|
||||
const [record] = await db
|
||||
.select({ classId: classInvitationCodes.classId })
|
||||
.from(classInvitationCodes)
|
||||
.where(eq(classInvitationCodes.id, codeId))
|
||||
.limit(1)
|
||||
return record?.classId ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销邀请码(软删除)。
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user