import { getTranslations } from "next-intl/server" import { getAuthContext } from "@/shared/lib/auth-guard" import { CalendarCheck } from "lucide-react" import { createAttendanceReadService } from "@/modules/attendance/services/attendance-data-service" import type { AttendanceReadService } from "@/modules/attendance/services/types" import { ParentChildrenDataPage, ParentNoChildrenPage, } from "@/modules/parent/components/parent-children-data-page" import { ParentAttendanceWarning } from "@/modules/parent/components/parent-attendance-warning" import { ParentAttendanceRateCard } from "@/modules/parent/components/parent-attendance-rate-card" import { ParentAttendanceCalendar } from "@/modules/parent/components/parent-attendance-calendar" import { ParentStudentAttendanceDetail } from "@/modules/parent/components/parent-student-attendance-detail" import type { ParentStudentAttendanceSummary } from "@/modules/parent/types" export const dynamic = "force-dynamic" /** * 将 attendance 模块的 StudentAttendanceSummary 映射为 parent 模块的视图模型。 * parent 模块仅消费自身类型,不依赖 attendance 内部类型变更(P1-2 解耦)。 */ function toParentSummary( summary: Awaited>, ): ParentStudentAttendanceSummary | null { if (!summary) return null return { studentId: summary.studentId, studentName: summary.studentName, stats: { total: summary.stats.total, present: summary.stats.present, absent: summary.stats.absent, late: summary.stats.late, presentRate: summary.stats.presentRate, }, recentRecords: summary.recentRecords.map((r) => ({ id: r.id, date: r.date, status: r.status, reason: r.reason, remark: r.remark, })), } } export default async function ParentAttendancePage() { const t = await getTranslations("attendance") const ctx = await getAuthContext() if (ctx.dataScope.type !== "children" || ctx.dataScope.childrenIds.length === 0) { return ( ) } // 通过接口抽象消费 attendance 数据(P1-2 修复:不再直接 import data-access) const attendanceService = createAttendanceReadService(ctx.dataScope) // 使用 allSettled 容错:单个子女查询失败不影响其他子女展示 const results = await Promise.allSettled( ctx.dataScope.childrenIds.map((id) => attendanceService.getStudentSummary(id)), ) const validSummaries = results .map((r) => r.status === "fulfilled" ? toParentSummary(r.value) : null, ) .filter((s): s is ParentStudentAttendanceSummary => s !== null) return ( (

{summary.studentName}

)} headerExtra={ validSummaries.length > 0 ? (
) : null } /> ) }