@@ -1,7 +1,7 @@
"use client" ;
/**
* Dashboard domain API (ARCHITECTURE.md §5.5, §10 P1-2)
* Dashboard domain API (ARCHITECTURE.md §5.5, §10 P1-2 / P1-7 )
*
* Real aggregation queries from data-ana subgraph, replacing the 6 fake
* widget contract queries (grades/homeworks/schedule/attendance/exams/
@@ -9,9 +9,13 @@
*
* Field naming: snake_case (as exposed by data-ana GraphQL schema).
* ARCHITECTURE.md §5.5 note: "底层字段 snake_case 需在 lib/api 层映射"
* — mapping deferred to P1-7 (codegen恢复后统一处理),当前 直传 snake_case。
* — mapping deferred until backend exposes camelCase; current 直传 snake_case。
*
* 关联: ARCHITECTURE.md §5.5 后端已就绪查询的立即利用 / §10 P1-2
* P1-7( ARCHITECTURE.md §10) : 手写 interface 全部删除,改用
* `__generated__/dashboard-types.ts` 由 codegen 严格校验生成的 per-operation
* 类型( skipDocumentsValidation: false, data-ana 域 schema 完全匹配)。
*
* 关联: ARCHITECTURE.md §5.5 后端已就绪查询的立即利用 / §10 P1-2 / §10 P1-7
*/
import type { FetchPolicy } from "@apollo/client" ;
import {
@@ -23,124 +27,17 @@ import {
GET_ERROR_BOOK_STATS_DOC ,
} from "@/lib/api/operations/dashboard.graphql" ;
import { useWidgetQuery } from "@/lib/useWidgetQuery" ;
import type {
GetAdminDashboardQuery ,
GetErrorBookStatsQuery ,
GetParentDashboardQuery ,
GetStudentDashboardQuery ,
GetTeacherDashboardQuery ,
GetWarningsQuery ,
} from "./__generated__/dashboard-types" ;
import type { UseQueryResult } from "./types" ;
// ===== 领域模型类型(对齐 combined-schema.graphql data-ana 子图 ) =====
export interface ClassSummary {
class_id : string ;
class_name : string ;
student_count : number ;
average_score : number ;
}
export interface StudentSummary {
student_id : string ;
student_name : string ;
score : number ;
rank_in_class : number ;
}
export interface WarningInfo {
warning_id : string ;
warning_type : string ;
target_id : string ;
target_name : string ;
threshold : number ;
current_value : number ;
severity : string ;
occurred_at : string ;
}
export interface WarningList {
warnings : WarningInfo ;
total : number ;
}
export interface WeakPoint {
knowledge_point_id : string ;
title : string ;
mastery : number ;
error_count : number ;
}
export interface TrendPoint {
date : string ;
score : number ;
}
export interface AIUsageByProvider {
provider : string ;
request_count : string ;
total_tokens : string ;
cost_cents : string ;
}
export interface AIUsageSummary {
total_requests : string ;
total_tokens : string ;
total_cost_cents : string ;
by_provider : AIUsageByProvider ;
}
export interface KnowledgePointErrorStats {
knowledge_point_id : string ;
title : string ;
error_count : number ;
question_count : number ;
error_rate : number ;
}
export interface ErrorBookStats {
student_id : string ;
total_error_questions : number ;
total_error_count : number ;
by_knowledge_point : KnowledgePointErrorStats ;
recent_7d_errors : number ;
}
export interface TeacherDashboard {
user_id : string ;
total_classes : number ;
total_students : number ;
class_avg_score : number ;
pending_homework_count : number ;
classes : ClassSummary ;
top_students : StudentSummary ;
recent_warnings : WarningInfo ;
}
export interface StudentDashboard {
user_id : string ;
avg_score : number ;
class_rank : number ;
total_students : number ;
weak_points : WeakPoint ;
recent_trends : TrendPoint ;
pending_homework : number ;
}
export interface ParentDashboard {
user_id : string ;
student_id : string ;
child_avg_score : number ;
child_class_rank : number ;
total_class_students : number ;
child_weak_points : WeakPoint ;
child_warnings : WarningInfo ;
}
export interface AdminDashboard {
user_id : string ;
total_teachers : number ;
total_students : number ;
total_classes : number ;
school_avg_score : number ;
recent_warnings : WarningInfo ;
ai_usage : AIUsageSummary ;
}
// ===== 查询选项 =====
// ===== 查询选项( UI 层类型,非 schema 类型 ) =====
export interface DashboardQueryOptions {
/** 是否启用查询( false 时跳过) */
@@ -151,50 +48,81 @@ export interface DashboardQueryOptions {
fetchPolicy? : FetchPolicy ;
}
// ===== 内部 Query 类型 =====
// ===== 数据类型(从 generated per-operation 类型提取) =====
// P1-7: 以下类型均由 codegen 严格校验生成,对应 dashboard.graphql.ts 中
// 6 个 operation。schema 字段全部可空(无 !),故类型为 `T | null`。
// 调用方( pages) 需对 `data` 与字段做空值守卫。
interface T eacherDashboardQueryData {
t eacherDashboard: TeacherDashboard ;
}
type DashboardQueryVars = Record < string , never >;
/** 教师仪表盘聚合数据( t eacherDashboard 根字段) */
export type T eacherDashboard = NonNullable <
GetTeacherDashboardQuery [ "teacherDashboard" ]
>;
interface S tudentDashboardQueryData {
s tudentDashboard: StudentDashboard ;
}
/** 学生仪表盘聚合数据( s tudentDashboard 根字段) */
export type S tudentDashboard = NonNullable <
GetStudentDashboardQuery [ "studentDashboard" ]
> ;
interface P arentDashboardQueryData {
p arentDashboard: ParentDashboard ;
}
/** 家长仪表盘聚合数据( p arentDashboard 根字段) */
export type P arentDashboard = NonNullable <
GetParentDashboardQuery [ "parentDashboard" ]
> ;
interface AdminDashboardQueryData {
a dminDashboard: AdminDashboard ;
}
/** 管理员仪表盘聚合数据( adminDashboard 根字段) */
export type A dminDashboard = NonNullable <
GetAdminDashboardQuery [ "adminDashboard" ]
> ;
interface WarningsQueryData {
w arnings : WarningList ;
}
/** 预警列表( warnings 根字段) */
export type W arningList = NonNullable < GetWarningsQuery [ "warnings" ] > ;
interface ErrorBookStatsQueryData {
errorBookStats : ErrorBookStats ;
}
/** 错题统计( errorBookStats 根字段) */
export type ErrorBookStats = NonNullable <
GetErrorBookStatsQuery [ "errorBookStats" ]
> ;
/** 班级概况( TeacherDashboard.classes 子字段) */
export type ClassSummary = NonNullable < TeacherDashboard [ "classes" ] > ;
/** 学生排名( TeacherDashboard.top_students 子字段) */
export type StudentSummary = NonNullable < TeacherDashboard [ "top_students" ] > ;
/** 预警信息(多处理由 parent/teacher/admin 共享引用) */
export type WarningInfo = NonNullable < TeacherDashboard [ "recent_warnings" ] > ;
/** 知识点薄弱项( StudentDashboard.weak_points 子字段) */
export type WeakPoint = NonNullable < StudentDashboard [ "weak_points" ] > ;
/** 趋势点( StudentDashboard.recent_trends 子字段) */
export type TrendPoint = NonNullable < StudentDashboard [ "recent_trends" ] > ;
/** AI 使用统计( AdminDashboard.ai_usage 子字段) */
export type AIUsageSummary = NonNullable < AdminDashboard [ "ai_usage" ] > ;
/** AI 分提供商统计( AIUsageSummary.by_provider 子字段) */
export type AIUsageByProvider = NonNullable < AIUsageSummary [ "by_provider" ] > ;
/** 知识点错误统计( ErrorBookStats.by_knowledge_point 子字段) */
export type KnowledgePointErrorStats = NonNullable <
ErrorBookStats [ "by_knowledge_point" ]
> ;
// ===== Hooks =====
/**
* 查询教师仪表盘聚合数据(替换原 grades/homeworks/schedule 等假契约查询)。
*
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2 / §10 P1-7
*/
export function useTeacherDashboard (
options? : DashboardQueryOptions ,
) : UseQueryResult < TeacherDashboard > {
const result = useWidgetQuery < TeacherDashboardQueryData , DashboardQueryVars > (
GET_TEACHER_DASHBOARD_DOC ,
{ } ,
options ,
) ;
) : UseQueryResult < TeacherDashboard | null > {
const result = useWidgetQuery <
GetTeacherDashboardQuery ,
Record < string , never >
> ( GET_TEACHER_DASHBOARD_DOC , { } , options ) ;
return {
data : result.data?.teacherDashboard ,
data : result.data?.teacherDashboard ? ? null ,
loading : result.loading ,
error : result.error ,
refetch : result.refetch ,
@@ -204,18 +132,17 @@ export function useTeacherDashboard(
/**
* 查询学生仪表盘聚合数据。
*
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2 / §10 P1-7
*/
export function useStudentDashboard (
options? : DashboardQueryOptions ,
) : UseQueryResult < StudentDashboard > {
const result = useWidgetQuery < StudentDashboardQueryData , DashboardQueryVars > (
GET_STUDENT_DASHBOARD_DOC ,
{ } ,
options ,
) ;
) : UseQueryResult < StudentDashboard | null > {
const result = useWidgetQuery <
GetStudentDashboardQuery ,
Record < string , never >
> ( GET_STUDENT_DASHBOARD_DOC , { } , options ) ;
return {
data : result.data?.studentDashboard ,
data : result.data?.studentDashboard ? ? null ,
loading : result.loading ,
error : result.error ,
refetch : result.refetch ,
@@ -225,18 +152,18 @@ export function useStudentDashboard(
/**
* 查询家长仪表盘聚合数据。
*
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2 / §10 P1-7
*/
export function useParentDashboard (
options? : DashboardQueryOptions ,
) : UseQueryResult < ParentDashboard > {
const result = useWidgetQuery < ParentDashboardQueryData , DashboardQueryVars > (
) : UseQueryResult < ParentDashboard | null > {
const result = useWidgetQuery < Get ParentDashboardQuery, Record < string , never > > (
GET_PARENT_DASHBOARD_DOC ,
{ } ,
options ,
) ;
return {
data : result.data?.parentDashboard ,
data : result.data?.parentDashboard ? ? null ,
loading : result.loading ,
error : result.error ,
refetch : result.refetch ,
@@ -246,18 +173,18 @@ export function useParentDashboard(
/**
* 查询管理员仪表盘聚合数据。
*
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2 / §10 P1-7
*/
export function useAdminDashboard (
options? : DashboardQueryOptions ,
) : UseQueryResult < AdminDashboard > {
const result = useWidgetQuery < AdminDashboardQueryData , DashboardQueryVars > (
) : UseQueryResult < AdminDashboard | null > {
const result = useWidgetQuery < Get AdminDashboardQuery, Record < string , never > > (
GET_ADMIN_DASHBOARD_DOC ,
{ } ,
options ,
) ;
return {
data : result.data?.adminDashboard ,
data : result.data?.adminDashboard ? ? null ,
loading : result.loading ,
error : result.error ,
refetch : result.refetch ,
@@ -267,18 +194,18 @@ export function useAdminDashboard(
/**
* 查询预警列表(跨角色共享)。
*
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2 / §10 P1-7
*/
export function useWarnings (
options? : DashboardQueryOptions ,
) : UseQueryResult < WarningList > {
const result = useWidgetQuery < WarningsQueryData , DashboardQueryVars > (
) : UseQueryResult < WarningList | null > {
const result = useWidgetQuery < Get WarningsQuery, Record < string , never > > (
GET_WARNINGS_DOC ,
{ } ,
options ,
) ;
return {
data : result.data?.warnings ,
data : result.data?.warnings ? ? null ,
loading : result.loading ,
error : result.error ,
refetch : result.refetch ,
@@ -288,18 +215,18 @@ export function useWarnings(
/**
* 查询错题统计(学生仪表盘子区块)。
*
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2
* 关联: ARCHITECTURE.md §5.5 / §10 P1-2 / §10 P1-7
*/
export function useErrorBookStats (
options? : DashboardQueryOptions ,
) : UseQueryResult < ErrorBookStats > {
const result = useWidgetQuery < ErrorBookStatsQueryData , DashboardQueryVars > (
) : UseQueryResult < ErrorBookStats | null > {
const result = useWidgetQuery < Get ErrorBookStatsQuery, Record < string , never > > (
GET_ERROR_BOOK_STATS_DOC ,
{ } ,
options ,
) ;
return {
data : result.data?.errorBookStats ,
data : result.data?.errorBookStats ? ? null ,
loading : result.loading ,
error : result.error ,
refetch : result.refetch ,