refactor: P0-3/5/6 解耦修复 - 循环依赖/通知分发/课表写入口

P0-3: 修复 shared/lib <-> auth 循环依赖
- audit-logger.ts, change-logger.ts, auth-guard.ts, classes/data-access.ts
  改用动态 import("@/auth") 打破静态模块级循环依赖
- shared/lib 不再静态导入 @/auth

P0-5: messaging 改用 notifications dispatcher
- messaging/actions.ts 的 sendMessageAction 改用 sendNotification
  替代直接调用 createNotification
- 用户通知偏好(SMS/微信/邮件/站内)现在被正确尊重

P0-6: 统一 classSchedule 写入口到 scheduling/data-access
- 新增 insertClassScheduleItem/updateClassScheduleItemById/
  deleteClassScheduleItemById/replaceClassSchedule 统一写入函数
- classes/data-access.ts 的三个 schedule 写入函数委托给 scheduling
- scheduling/actions.ts 的 applyAutoScheduleAction 改用 replaceClassSchedule
- 移除 scheduling/actions.ts 中不再使用的 classSchedule/createId 导入

验证: tsc --noEmit 0 errors, npm run lint 0 errors
This commit is contained in:
SpecialX
2026-06-17 23:44:02 +08:00
parent 02dc1093fb
commit 220061d62e
7 changed files with 155 additions and 31 deletions

View File

@@ -4,6 +4,7 @@ import { revalidatePath } from "next/cache"
import { PermissionDeniedError, requireAuth, requirePermission } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"
import { sendNotification } from "@/modules/notifications/dispatcher"
import { SendMessageSchema } from "./schema"
import {
@@ -13,7 +14,6 @@ import {
markMessageAsRead,
deleteMessage,
getNotifications,
createNotification,
markNotificationAsRead,
markAllNotificationsAsRead,
getRecipients,
@@ -62,13 +62,15 @@ export async function sendMessageAction(
parentMessageId: input.parentMessageId,
})
// Notify the receiver about the new message
await createNotification({
// Notify the receiver about the new message via the notifications dispatcher.
// This respects user notification preferences (SMS/WeChat/Email/In-App).
await sendNotification({
userId: input.receiverId,
type: "message",
type: "info",
title: input.subject ? `New message: ${input.subject}` : "New message",
content: input.content.slice(0, 200),
link: `/messages/${id}`,
actionUrl: `/messages/${id}`,
metadata: { messageType: "message", messageId: id },
})
revalidatePath("/messages")