Files
Edu/packages/shared-ts/contracts/graphql/parent-bff.graphql
SpecialX 2229309a1e feat: initialize parent-bff service with full core features
add complete parent-bff implementation including:
- GraphQL endpoint with depth/cost validation
- ChildGuard越权校验 with redis cache and singleflight
- parallel orchestration with partial failure fallback
- three-level cache fallback strategy (Redis + LRU + downstream)
- Kafka consumer for cache invalidation and notification push
- opossum circuit breaker for downstream services
- Prometheus metrics and SLO alerts
- Helm chart for k8s deployment with multi-environment configs
- Grafana dashboard for observability
- complete unit and integration tests
2026-07-10 18:49:06 +08:00

245 lines
4.2 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.
# parent-bff GraphQL SchemaSDL 契约,对齐 02-architecture-design.md §4.2
#
# 本文件是 parent-bff GraphQL 端点的契约唯一源single source of truth
# - 前端 parent-portal 引用本文件生成 TypeScript 类型
# - 后端 parent-bff 引用本文件加载为 GraphQLSchema
# - CI 强制检测 breaking change与 main 分支对比)
#
# 仲裁依据:
# - U3GraphQL P2 立即引入parent-bff P4 直接用 GraphQL不走 REST 过渡)
# - C1错误码前缀 BFF_PARENT_
# - U4BFF 豁免 @RequirePermission仅校验 x-user-id + ChildGuard
# - 02 §9 #5depth ≤ 7 / cost ≤ 1000
scalar DateTime
# ============ Types ============
type Parent {
id: ID!
email: String!
name: String!
avatar: String
roles: [String!]!
dataScope: DataScope!
}
enum DataScope {
SELF
CHILDREN
CLASS
GRADE
SCHOOL
DISTRICT
ALL
}
type ViewportItem {
key: String!
label: String!
route: String!
icon: String
sortOrder: String!
requiredPermission: String
}
type Child {
id: ID!
name: String!
grade: String!
class: ClassInfo!
lastGrade: Grade
grades(page: Int = 1, pageSize: Int = 20, subject: String): GradePage!
homework: [Homework!]!
exams: [Exam!]!
analytics: ChildAnalytics!
}
type ClassInfo {
id: ID!
name: String!
gradeId: String!
}
type Grade {
id: ID!
examId: ID!
examTitle: String!
subject: String!
score: Float!
rank: Int
gradedAt: DateTime!
}
type GradePage {
items: [Grade!]!
pagination: Pagination!
}
type Pagination {
page: Int!
pageSize: Int!
total: Int!
}
type Homework {
id: ID!
title: String!
classId: ID!
dueDate: DateTime!
status: HomeworkStatus!
submittedAt: DateTime
}
enum HomeworkStatus {
NOT_SUBMITTED
SUBMITTED
GRADED
OVERDUE
}
type Exam {
id: ID!
title: String!
classId: ID!
status: ExamStatus!
examDate: DateTime!
publishedAt: DateTime
}
enum ExamStatus {
DRAFT
PUBLISHED
IN_PROGRESS
GRADING
SCORED
ARCHIVED
}
type ChildAnalytics {
childId: ID!
weakness: [WeaknessTopic!]!
trend: [TrendPoint!]!
classRank: Int
classAverage: Float
}
type WeaknessTopic {
knowledgePointId: ID!
name: String!
subject: String!
masteryRate: Float!
}
type TrendPoint {
date: DateTime!
score: Float!
subject: String
}
type Notification {
id: ID!
type: NotificationType!
title: String!
content: String!
read: Boolean!
childId: ID
createdAt: DateTime!
}
enum NotificationType {
SYSTEM
EXAM
HOMEWORK
GRADE
ATTENDANCE
ANNOUNCEMENT
}
type NotificationPreferences {
channels: [NotificationChannel!]!
eventTypes: NotificationEventTypes!
}
enum NotificationChannel {
APP
SMS
EMAIL
WECHAT
}
type NotificationEventTypes {
gradeReleased: Boolean!
homeworkGraded: Boolean!
examPublished: Boolean!
attendanceAlert: Boolean!
schoolAnnouncement: Boolean!
}
type DashboardData {
parent: Parent
children: [Child!]!
viewports: [ViewportItem!]!
unreadNotifications: Int!
degraded: Boolean!
}
# ============ Query ============
type Query {
dashboard: DashboardData!
viewports: [ViewportItem!]!
me: Parent!
children: [Child!]!
child(childId: ID!): Child
childGrades(
childId: ID!
page: Int = 1
pageSize: Int = 20
subject: String
): GradePage!
childHomework(childId: ID!): [Homework!]!
childExams(childId: ID!): [Exam!]!
childAnalytics(childId: ID!, dateRange: DateRangeInput): ChildAnalytics!
notifications(
unreadOnly: Boolean
page: Int = 1
pageSize: Int = 20
): [Notification!]!
notificationPreferences: NotificationPreferences!
}
input DateRangeInput {
start: DateTime!
end: DateTime!
}
# ============ Mutation ============
type Mutation {
selectChild(childId: ID!): SelectChildResult!
markNotificationRead(notificationId: ID!): Notification!
updateNotificationPreferences(
input: UpdateNotificationPreferencesInput!
): NotificationPreferences!
}
type SelectChildResult {
childId: ID!
selectedAt: DateTime!
audited: Boolean!
}
input UpdateNotificationPreferencesInput {
channels: [NotificationChannel!]!
eventTypes: NotificationEventTypesInput!
}
input NotificationEventTypesInput {
gradeReleased: Boolean
homeworkGraded: Boolean
examPublished: Boolean
attendanceAlert: Boolean
schoolAnnouncement: Boolean
}