refactor: P0-1/2/4 解耦修复 - 拆分过耦合文件 + dashboard 解耦
This commit is contained in:
@@ -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,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user