refactor: P0-1/2/4 解耦修复 - 拆分过耦合文件 + dashboard 解耦

This commit is contained in:
SpecialX
2026-06-18 01:45:55 +08:00
parent 220061d62e
commit 62be0b9404
18 changed files with 2534 additions and 2130 deletions

View File

@@ -1,205 +1,47 @@
import "server-only"
import { cache } from "react"
import { count, desc, eq, gt, inArray, and } from "drizzle-orm"
import { db } from "@/shared/db"
import {
chapters,
classes,
exams,
homeworkAssignments,
homeworkSubmissions,
questions,
roles,
sessions,
textbooks,
users,
usersToRoles,
} from "@/shared/db/schema"
import type { AdminDashboardData } from "./types"
import { getClassesDashboardStats } from "@/modules/classes/data-access"
import { getExamsDashboardStats } from "@/modules/exams/data-access"
import { getHomeworkDashboardStats } from "@/modules/homework/stats-service"
import { getQuestionsDashboardStats } from "@/modules/questions/data-access"
import { getTextbooksDashboardStats } from "@/modules/textbooks/data-access"
import { getUsersDashboardStats } from "@/modules/users/data-access"
import type { DataScope } from "@/shared/types/permissions"
import type { AdminDashboardData } from "./types"
export const getAdminDashboardData = cache(async (scope?: DataScope): Promise<AdminDashboardData> => {
const now = new Date()
// Build scope-based conditions for exams
const examConditions = []
const homeworkConditions = []
const submissionConditions = []
if (scope && scope.type !== "all") {
if (scope.type === "owned") {
examConditions.push(eq(exams.creatorId, scope.userId))
homeworkConditions.push(eq(homeworkAssignments.creatorId, scope.userId))
const ownedAssignmentIds = db
.select({ id: homeworkAssignments.id })
.from(homeworkAssignments)
.where(eq(homeworkAssignments.creatorId, scope.userId))
submissionConditions.push(inArray(homeworkSubmissions.assignmentId, ownedAssignmentIds))
}
if (scope.type === "grade_managed" && scope.gradeIds.length > 0) {
examConditions.push(inArray(exams.gradeId, scope.gradeIds))
const gradeExamIds = db
.select({ id: exams.id })
.from(exams)
.where(inArray(exams.gradeId, scope.gradeIds))
homeworkConditions.push(inArray(homeworkAssignments.sourceExamId, gradeExamIds))
const gradeAssignmentIds = db
.select({ id: homeworkAssignments.id })
.from(homeworkAssignments)
.where(inArray(homeworkAssignments.sourceExamId, gradeExamIds))
submissionConditions.push(inArray(homeworkSubmissions.assignmentId, gradeAssignmentIds))
}
if (scope.type === "class_taught" && scope.classIds.length > 0) {
const teacherGradeIds = await db
.selectDistinct({ gradeId: classes.gradeId })
.from(classes)
.where(inArray(classes.id, scope.classIds))
const gradeIds = teacherGradeIds.map(g => g.gradeId).filter(Boolean) as string[]
if (gradeIds.length > 0) {
examConditions.push(inArray(exams.gradeId, gradeIds))
const gradeExamIds = db
.select({ id: exams.id })
.from(exams)
.where(inArray(exams.gradeId, gradeIds))
homeworkConditions.push(inArray(homeworkAssignments.sourceExamId, gradeExamIds))
const gradeAssignmentIds = db
.select({ id: homeworkAssignments.id })
.from(homeworkAssignments)
.where(inArray(homeworkAssignments.sourceExamId, gradeExamIds))
submissionConditions.push(inArray(homeworkSubmissions.assignmentId, gradeAssignmentIds))
}
}
}
const [
activeSessionsRow,
userCountRow,
userRoleCountRows,
classCountRow,
textbookCountRow,
chapterCountRow,
questionCountRow,
examCountRow,
homeworkAssignmentCountRow,
homeworkAssignmentPublishedCountRow,
homeworkSubmissionCountRow,
homeworkSubmissionToGradeCountRow,
recentUserRows,
usersStats,
classesStats,
textbooksStats,
questionsStats,
examsStats,
homeworkStats,
] = await Promise.all([
db.select({ value: count() }).from(sessions).where(gt(sessions.expires, now)),
db.select({ value: count() }).from(users),
db
.select({ role: roles.name, value: count() })
.from(usersToRoles)
.innerJoin(roles, eq(usersToRoles.roleId, roles.id))
.groupBy(roles.name),
db.select({ value: count() }).from(classes),
db.select({ value: count() }).from(textbooks),
db.select({ value: count() }).from(chapters),
db.select({ value: count() }).from(questions),
db.select({ value: count() }).from(exams).where(examConditions.length ? and(...examConditions) : undefined),
db.select({ value: count() }).from(homeworkAssignments).where(homeworkConditions.length ? and(...homeworkConditions) : undefined),
db.select({ value: count() }).from(homeworkAssignments).where(
homeworkConditions.length
? and(eq(homeworkAssignments.status, "published"), ...homeworkConditions)
: eq(homeworkAssignments.status, "published")
),
db.select({ value: count() }).from(homeworkSubmissions).where(submissionConditions.length ? and(...submissionConditions) : undefined),
db.select({ value: count() }).from(homeworkSubmissions).where(
submissionConditions.length
? and(eq(homeworkSubmissions.status, "submitted"), ...submissionConditions)
: eq(homeworkSubmissions.status, "submitted")
),
db
.select({
id: users.id,
name: users.name,
email: users.email,
createdAt: users.createdAt,
})
.from(users)
.orderBy(desc(users.createdAt))
.limit(8),
getUsersDashboardStats(),
getClassesDashboardStats(),
getTextbooksDashboardStats(),
getQuestionsDashboardStats(),
getExamsDashboardStats(scope),
getHomeworkDashboardStats(scope),
])
const activeSessionsCount = Number(activeSessionsRow[0]?.value ?? 0)
const userCount = Number(userCountRow[0]?.value ?? 0)
const classCount = Number(classCountRow[0]?.value ?? 0)
const textbookCount = Number(textbookCountRow[0]?.value ?? 0)
const chapterCount = Number(chapterCountRow[0]?.value ?? 0)
const questionCount = Number(questionCountRow[0]?.value ?? 0)
const examCount = Number(examCountRow[0]?.value ?? 0)
const homeworkAssignmentCount = Number(homeworkAssignmentCountRow[0]?.value ?? 0)
const homeworkAssignmentPublishedCount = Number(homeworkAssignmentPublishedCountRow[0]?.value ?? 0)
const homeworkSubmissionCount = Number(homeworkSubmissionCountRow[0]?.value ?? 0)
const homeworkSubmissionToGradeCount = Number(homeworkSubmissionToGradeCountRow[0]?.value ?? 0)
const userRoleCounts = userRoleCountRows
.map((r) => ({ role: r.role ?? "unknown", count: Number(r.value ?? 0) }))
.sort((a, b) => b.count - a.count)
const normalizeRole = (value: string) => {
const role = value.trim().toLowerCase()
if (role === "grade_head" || role === "teaching_head") return "teacher"
if (role === "admin" || role === "student" || role === "teacher" || role === "parent") return role
return ""
}
const recentUserIds = recentUserRows.map((u) => u.id)
const recentRoleRows = recentUserIds.length
? await db
.select({
userId: usersToRoles.userId,
roleName: roles.name,
})
.from(usersToRoles)
.innerJoin(roles, eq(usersToRoles.roleId, roles.id))
.where(inArray(usersToRoles.userId, recentUserIds))
: []
const rolesByUserId = new Map<string, string[]>()
for (const row of recentRoleRows) {
const list = rolesByUserId.get(row.userId) ?? []
list.push(row.roleName)
rolesByUserId.set(row.userId, list)
}
const resolvePrimaryRole = (roleNames: string[]) => {
const mapped = roleNames.map(normalizeRole).filter(Boolean)
if (mapped.includes("admin")) return "admin"
if (mapped.includes("teacher")) return "teacher"
if (mapped.includes("parent")) return "parent"
if (mapped.includes("student")) return "student"
return "student"
}
const recentUsers = recentUserRows.map((u) => {
const roleNames = rolesByUserId.get(u.id) ?? []
return {
id: u.id,
name: u.name,
email: u.email,
role: resolvePrimaryRole(roleNames),
createdAt: u.createdAt.toISOString(),
}
})
return {
activeSessionsCount,
userCount,
userRoleCounts,
classCount,
textbookCount,
chapterCount,
questionCount,
examCount,
homeworkAssignmentCount,
homeworkAssignmentPublishedCount,
homeworkSubmissionCount,
homeworkSubmissionToGradeCount,
recentUsers,
activeSessionsCount: usersStats.activeSessionsCount,
userCount: usersStats.userCount,
userRoleCounts: usersStats.userRoleCounts,
classCount: classesStats.classCount,
textbookCount: textbooksStats.textbookCount,
chapterCount: textbooksStats.chapterCount,
questionCount: questionsStats.questionCount,
examCount: examsStats.examCount,
homeworkAssignmentCount: homeworkStats.homeworkAssignmentCount,
homeworkAssignmentPublishedCount: homeworkStats.homeworkAssignmentPublishedCount,
homeworkSubmissionCount: homeworkStats.homeworkSubmissionCount,
homeworkSubmissionToGradeCount: homeworkStats.homeworkSubmissionToGradeCount,
recentUsers: usersStats.recentUsers,
}
})