Files
Edu/packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql
SpecialX 99155a5ea1 feat(teacher-bff): 完整实现 teacher-bff GraphQL 聚合层
包含 clients/graphql/middleware、health probes、shared-ts contracts 等
2026-07-10 19:10:07 +08:00

453 lines
9.7 KiB
GraphQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# teacher-bff GraphQL Schema (SDL-first, president §2.17)
# 版本v1P2 第一版coord 仲裁)
# 负责人ai03
# 关联contracts/teacher-bff_contract.md §1.3、workline §3.1
#
# 设计原则02-architecture-design.md §5.1
# 1. 按教学场景域组织(不按角色分),教导主任/教研组长复用同一 schema
# 2. Query 为主Mutation 谨慎BFF 偏读多写少)
# 3. N+1 防御:所有 list 字段经 DataLoaderP4 全量接入)
# 4. 复杂度限制depth ≤ 7query cost ≤ 1000
# 5. admin 命名空间预留president §5.1P2 预留 schemaP6 实现 Resolver
#
# 错误响应格式GraphQL errors 数组 + extensions.code = BFF_TEACHER_* + extensions.traceId
# 降级模式 Bpresident §2.6success=true + error=null + data 内 degraded 字段
#
# 阶段标注:
# P2 = 当前实现iam gRPC未启用字段返 null + extensions.warning = "field_unavailable_in_p2"
# P3+ = 跨阶段扩展例外president §2.3Resolver 内逐步补 gRPC 调用
scalar DateTime
# ============ Types ============
type User {
id: ID!
email: String!
name: String!
roles: [String!]!
permissions: [String!]!
dataScope: DataScope!
}
enum DataScope {
SELF
CLASS
GRADE
SCHOOL
DISTRICT
ALL
}
type ViewportItem {
key: String!
label: String!
route: String!
icon: String
sortOrder: String!
requiredPermission: String
}
type Class {
id: ID!
name: String!
gradeId: String!
# 延迟加载班级下的考试P3+ core-edu gRPC
exams: [Exam!]!
# 延迟加载班级下的作业P3+ core-edu gRPC
homework: [Homework!]!
}
type Exam {
id: ID!
title: String!
classId: ID!
status: ExamStatus!
publishedAt: DateTime
# 延迟加载考试下的成绩P3+ core-edu gRPC
grades: [Grade!]!
}
enum ExamStatus {
DRAFT
PUBLISHED
IN_PROGRESS
GRADING
SCORED
ARCHIVED
}
type Homework {
id: ID!
title: String!
classId: ID!
dueDate: DateTime!
submissions: [Submission!]!
}
type Submission {
id: ID!
studentId: ID!
submittedAt: DateTime!
status: SubmissionStatus!
}
enum SubmissionStatus {
NOT_SUBMITTED
SUBMITTED
GRADED
}
type Grade {
id: ID!
examId: ID!
studentId: ID!
score: Float!
rank: Int
submittedAt: DateTime!
}
type DashboardStats {
totalExams: Int
pendingGrading: Int
todayHomework: Int
}
# Dashboard 聚合数据P2: iam gRPC 用户基础信息stats/classes 为 null + warning
type DashboardData {
user: User
classes: [Class!]!
viewports: [ViewportItem!]!
stats: DashboardStats
}
# ============ Query ============
# P2 核心 5 Queryworkline §3.2dashboard / viewports / me / classes / class
type Query {
# 仪表盘聚合P2: iam gRPCP3+: + core-edu + data-ana
# @dataScope: OWN
dashboard: DashboardData!
# 视口配置L1 导航iam.GetViewports
viewports: [ViewportItem!]!
# 当前用户信息iam.GetUserInfo + GetEffectivePermissions
me: User!
# 教师班级列表P2: iam 数据P3+: core-edu.GetClassesByTeacher
# @dataScope: OWN
classes: [Class!]!
# 单个班级详情P3+: core-edu
# @permission: CLASS_READ
# @dataScope: OWN
class(id: ID!): Class
# ===== P3+ 跨阶段扩展core-edu gRPC按 §2.3 跨阶段扩展例外新增)=====
# 班级下的考试列表P3: core-edu.ExamService.ListExamsByClass
# @permission: EXAM_READ
# @dataScope: OWN
exams(classId: ID!): [Exam!]!
# 班级下的作业列表P3: core-edu.HomeworkService.ListHomeworkByClass
# @permission: HOMEWORK_READ
# @dataScope: OWN
homework(classId: ID!): [Homework!]!
# 考试下的成绩列表P3: core-edu.GradeService.ListGradesByExam
# @permission: GRADE_READ
# @dataScope: OWN
grades(examId: ID!): [Grade!]!
# ===== P4+ 跨阶段扩展content + data-ana gRPC=====
# 知识图谱学习路径P4: content.KnowledgeGraphService.GetLearningPath
knowledgePath(knowledgePointId: ID!): KnowledgePath!
# 班级成绩分析P4: data-ana.AnalyticsService.GetClassPerformance
# @permission: ANALYTICS_TEACHER_DASHBOARD
classPerformance(classId: ID!): ClassPerformance!
# 学生薄弱点P4: data-ana.AnalyticsService.GetStudentWeakness
studentWeakness(studentId: ID!): StudentWeakness!
# 学习趋势P4: data-ana.AnalyticsService.GetLearningTrend
learningTrend(studentId: ID!, dateRange: DateRangeInput): LearningTrend!
# ===== P5+ 跨阶段扩展ai + msg gRPC=====
# 教师通知列表P5: msg.NotificationService.ListNotifications
notifications(unreadOnly: Boolean): [Notification!]!
# ===== admin 命名空间president §5.1P2 预留 schemaP6 实现 Resolver=====
# admin-portal 复用 teacher-bff GraphQL endpointadmin 操作低 QPS 无需独立 BFF
admin: AdminQuery!
}
input DateRangeInput {
start: DateTime!
end: DateTime!
}
# ============ Mutation ============
type Mutation {
# ===== P3+ 跨阶段扩展core-edu gRPC 透传)=====
# 创建考试P3: core-edu.ExamService.CreateExam
# @permission: EXAM_CREATE
createExam(input: CreateExamInput!): Exam!
# 布置作业P3: core-edu.HomeworkService.AssignHomework
# @permission: HOMEWORK_ASSIGN
assignHomework(input: AssignHomeworkInput!): Homework!
# 录入成绩P3: core-edu.GradeService.RecordGrade
# @permission: GRADE_RECORD
recordGrade(input: RecordGradeInput!): Grade!
# ===== P5+ 跨阶段扩展ai + msg gRPC=====
# AI 出题P5: ai.AiService.GenerateQuestion
generateQuestion(input: GenerateQuestionInput!): GeneratedQuestion!
# 标记通知已读P5: msg.NotificationService.MarkAsRead
markNotificationAsRead(id: ID!): Notification!
# ===== admin 命名空间 Mutationpresident §5.1P2 预留P6 实现)=====
admin: AdminMutation!
}
input CreateExamInput {
classId: ID!
title: String!
subject: String!
scheduledAt: DateTime!
}
input AssignHomeworkInput {
classId: ID!
title: String!
dueDate: DateTime!
}
input RecordGradeInput {
examId: ID!
studentId: ID!
score: Float!
}
input GenerateQuestionInput {
subject: String!
gradeLevel: String!
difficulty: String!
knowledgePointIds: [ID!]!
}
# ============ P4+ 类型content + data-ana============
type KnowledgePath {
knowledgePointId: ID!
name: String!
prerequisites: [KnowledgePoint!]!
}
type KnowledgePoint {
id: ID!
name: String!
subject: String!
}
type ClassPerformance {
classId: ID!
averageScore: Float!
passRate: Float!
weaknessTopics: [String!]!
}
type StudentWeakness {
studentId: ID!
weakTopics: [String!]!
recommendedExercises: [String!]!
}
type LearningTrend {
studentId: ID!
trend: [TrendPoint!]!
}
type TrendPoint {
date: DateTime!
score: Float!
}
# ============ P5+ 类型ai + msg============
type Notification {
id: ID!
type: NotificationType!
title: String!
content: String!
read: Boolean!
createdAt: DateTime!
}
enum NotificationType {
SYSTEM
EXAM
HOMEWORK
GRADE
ATTENDANCE
}
type GeneratedQuestion {
id: ID!
subject: String!
difficulty: String!
content: String!
answer: String!
}
# ============ admin 命名空间president §5.1P2 预留 schemaP6 实现 Resolver============
# P2: 类型声明占位Resolver 返 null不阻塞 admin-portal schema 内省)
# P6: ai03 实现 admin Resolver 真实数据(用户/角色/学校/组织/审计日志管理)
type AdminQuery {
# 用户管理
users(page: Int = 1, pageSize: Int = 20): AdminUserPage
user(id: ID!): AdminUser
# 角色权限管理
roles: [AdminRole!]!
role(id: ID!): AdminRole
# 学校设置
school: AdminSchool
# 组织管理
organizations: [AdminOrganization!]!
# 审计日志查询
auditLogs(page: Int = 1, pageSize: Int = 20): AuditLogPage
}
type AdminMutation {
createUser(input: AdminCreateUserInput!): AdminUser!
updateUser(id: ID!, input: AdminUpdateUserInput!): AdminUser!
deleteUser(id: ID!): Boolean!
createRole(input: AdminCreateRoleInput!): AdminRole!
updateRole(id: ID!, input: AdminUpdateRoleInput!): AdminRole!
deleteRole(id: ID!): Boolean!
updateSchool(input: AdminUpdateSchoolInput!): AdminSchool!
createOrganization(input: AdminCreateOrganizationInput!): AdminOrganization!
updateOrganization(id: ID!, input: AdminUpdateOrganizationInput!): AdminOrganization!
deleteOrganization(id: ID!): Boolean!
}
type AdminUser {
id: ID!
email: String!
name: String!
roles: [String!]!
status: String!
createdAt: DateTime!
lastLoginAt: DateTime
}
type AdminUserPage {
edges: [AdminUser!]!
totalCount: Int!
page: Int!
pageSize: Int!
}
type AdminRole {
id: ID!
name: String!
description: String
permissions: [String!]!
userCount: Int!
}
type AdminSchool {
id: ID!
name: String!
address: String
phone: String
studentCount: Int!
teacherCount: Int!
classCount: Int!
}
type AdminOrganization {
id: ID!
name: String!
type: String!
parentId: ID
createdAt: DateTime!
}
type AuditLogPage {
edges: [AuditLog!]!
totalCount: Int!
page: Int!
pageSize: Int!
}
type AuditLog {
id: ID!
actorUserId: ID!
action: String!
resourceType: String!
resourceId: ID
occurredAt: DateTime!
ip: String
}
input AdminCreateUserInput {
email: String!
name: String!
roleIds: [ID!]!
}
input AdminUpdateUserInput {
name: String
roleIds: [ID!]
status: String
}
input AdminCreateRoleInput {
name: String!
description: String
permissions: [String!]!
}
input AdminUpdateRoleInput {
name: String
description: String
permissions: [String!]
}
input AdminUpdateSchoolInput {
name: String
address: String
phone: String
}
input AdminCreateOrganizationInput {
name: String!
type: String!
parentId: ID
}
input AdminUpdateOrganizationInput {
name: String
type: String
parentId: ID
}