"use server" import { requirePermission } from "@/shared/lib/auth-guard" import { Permissions } from "@/shared/types/permissions" import type { ActionState } from "@/shared/types/action-state" import { handleActionError } from "@/shared/lib/action-utils" import { getClassSchedule, getStudentClasses, getStudentSchedule, getTeacherClasses, getTeacherIdForMutations } from "@/modules/classes/data-access" import { getHomeworkAssignments, getHomeworkSubmissions, } from "@/modules/homework/data-access" import { getStudentHomeworkAssignments } from "@/modules/homework/data-access-student" import { getStudentDashboardGrades, getTeacherGradeTrends } from "@/modules/homework/stats-service" import { getCurrentStudentUser, getUserBasicInfo } from "@/modules/users/data-access" import { getParentDashboardData } from "@/modules/parent/data-access" import { getAdminDashboardData } from "./data-access" import type { AdminDashboardData, StudentDashboardProps, TeacherDashboardData, } from "./types" import type { ParentDashboardData } from "@/modules/parent/types" import { computeTeacherMetrics, countStudentAssignments, sortUpcomingAssignments, toWeekday, filterTodaySchedule, type TeacherDashboardMetrics, } from "./lib/dashboard-utils" /** * 获取管理员仪表盘数据。 * 权限:DASHBOARD_ADMIN_READ */ export async function getAdminDashboardAction(): Promise> { try { const ctx = await requirePermission(Permissions.DASHBOARD_ADMIN_READ) const data = await getAdminDashboardData(ctx.dataScope) return { success: true, data } } catch (e) { return handleActionError(e) } } /** * 获取教师仪表盘数据(含派生指标)。 * 权限:DASHBOARD_TEACHER_READ */ export async function getTeacherDashboardAction(): Promise> { try { await requirePermission(Permissions.DASHBOARD_TEACHER_READ) const teacherId = await getTeacherIdForMutations() const [classes, schedule, assignments, submissions, teacherProfile, gradeTrends] = await Promise.all([ getTeacherClasses({ teacherId }), getClassSchedule({ teacherId }), getHomeworkAssignments({ creatorId: teacherId }), getHomeworkSubmissions({ creatorId: teacherId }), getUserBasicInfo(teacherId), getTeacherGradeTrends(teacherId), ]) const metrics = computeTeacherMetrics( classes, schedule, assignments, submissions, gradeTrends, new Date(), ) return { success: true, data: { classes, schedule, assignments, submissions, teacherName: teacherProfile?.name ?? "", gradeTrends, metrics, }, } } catch (e) { return handleActionError(e) } } /** * 获取学生仪表盘数据(含派生指标)。 * 权限:DASHBOARD_STUDENT_READ */ export async function getStudentDashboardAction(): Promise | null }>> { try { await requirePermission(Permissions.DASHBOARD_STUDENT_READ) const student = await getCurrentStudentUser() if (!student) { return { success: true, data: { student: null, dashboardProps: null } } } const [classes, schedule, assignments, grades] = await Promise.all([ getStudentClasses(student.id), getStudentSchedule(student.id), getStudentHomeworkAssignments(student.id), getStudentDashboardGrades(student.id), ]) const now = new Date() const stats = countStudentAssignments(assignments, now) const todayWeekday = toWeekday(now) const todayScheduleItems = filterTodaySchedule(schedule, todayWeekday) const upcomingAssignments = sortUpcomingAssignments(assignments, 6) return { success: true, data: { student: { id: student.id, name: student.name }, dashboardProps: { enrolledClassCount: classes.length, dueSoonCount: stats.dueSoonCount, overdueCount: stats.overdueCount, gradedCount: stats.gradedCount, todayScheduleItems, upcomingAssignments, grades, }, }, } } catch (e) { return handleActionError(e) } } /** * 获取家长仪表盘数据。 * 权限:DASHBOARD_PARENT_READ */ export async function getParentDashboardAction(): Promise> { try { const ctx = await requirePermission(Permissions.DASHBOARD_PARENT_READ) // 非 admin 且 dataScope 非 children 类型时,无孩子数据 if ( ctx.dataScope.type !== "all" && !(ctx.dataScope.type === "children" && ctx.dataScope.childrenIds.length > 0) ) { return { success: true, data: { data: null, hasChildren: false } } } const data = await getParentDashboardData(ctx.userId) return { success: true, data: { data, hasChildren: data.children.length > 0 } } } catch (e) { return handleActionError(e) } }