feat(shared-ts): 同步 3 个 BFF GraphQL schema + downstream-client/logger/outbox 增强

This commit is contained in:
SpecialX
2026-07-14 15:51:36 +08:00
parent 774af93d76
commit e9d3030f2f
6 changed files with 3474 additions and 244 deletions

View File

@@ -10,10 +10,13 @@
# - C1错误码前缀 BFF_PARENT_
# - U4BFF 豁免 @RequirePermission仅校验 x-user-id + ChildGuard
# - 02 §9 #5depth ≤ 7 / cost ≤ 1000
#
# 版本v232 Query + 6 Mutation对齐 parent-portal 全部 operations
scalar DateTime
scalar JSON
# ============ Types ============
# ============ Legacy Types ============
type Parent {
id: ID!
@@ -21,7 +24,9 @@ type Parent {
name: String!
avatar: String
roles: [String!]!
permissions: [String!]
dataScope: DataScope!
schoolId: ID
}
enum DataScope {
@@ -184,9 +189,413 @@ type DashboardData {
degraded: Boolean!
}
# ============ Query ============
# ============ Extended Typesv2 新增) ============
type ChildBrief {
id: ID!
name: String!
grade: String!
classId: ID
className: String
avatar: String
}
type ChildSummary {
childId: ID!
avgScore: Float
classRank: Int
classSize: Int
attendanceRate: Float
pendingHomeworkCount: Int!
recentGradeTrend: Float
recentScores: [ChildGrade!]!
upcomingEvents: [UpcomingEvent!]!
}
type UpcomingEvent {
id: ID!
type: String!
title: String!
dueDate: DateTime!
}
type ChildDetail {
childId: ID!
basicInfo: ChildBasicInfo!
todaySchedule: [JSON!]!
weeklySchedule: [JSON!]!
homeworkSummary: HomeworkSummary!
gradeSummary: GradeSummary!
examResults: ExamResultSummary!
}
type ChildBasicInfo {
name: String!
avatar: String
grade: String!
className: String!
schoolName: String!
relation: String!
}
type HomeworkSummary {
pendingCount: Int!
overdueCount: Int!
submittedCount: Int!
gradedCount: Int!
}
type GradeSummary {
avgScore: Float!
classRank: Int
classSize: Int
trend: Float
}
type ExamResultSummary {
upcoming: Int!
completed: Int!
avgScore: Float
}
type ChildGrade {
examId: ID!
examName: String!
examDate: DateTime!
subject: String!
studentScore: Float!
classAverage: Float
classMax: Float
classMin: Float
gradeLevel: String
}
type ChildHomework {
id: ID!
title: String!
subject: String!
className: String!
assignedDate: DateTime!
dueDate: DateTime!
status: String!
score: Float
maxScore: Float
feedback: String
}
type ChildExam {
id: ID!
name: String!
subject: String!
status: String!
startsAt: DateTime!
expiresAt: DateTime
durationSeconds: Int
questionCount: Int
totalScore: Float
submittedAt: DateTime
}
type AttendanceRecord {
id: ID!
date: DateTime!
status: String!
checkInTime: DateTime
checkOutTime: DateTime
note: String
}
type ExamResult {
examId: ID!
childId: ID!
score: Float
rank: Int
subjectScores: [SubjectScore!]!
feedback: String
}
type SubjectScore {
subject: String!
score: Float!
fullScore: Float!
}
type ChildClass {
id: ID!
name: String!
homeroomTeacher: String
studentCount: Int
grade: String!
year: String
}
type ReportCard {
childId: ID!
academicYearId: ID!
semester: Int!
subjects: [ReportCardSubject!]!
overallComment: String
classRank: Int
}
type ReportCardSubject {
subject: String!
score: Float!
grade: String!
teacherComment: String
}
type GrowthArchive {
childId: ID!
subject: String
dataPoints: [GrowthDataPoint!]!
}
type GrowthDataPoint {
date: DateTime!
category: String!
title: String!
description: String!
evidence: String
}
type WeaknessItem {
id: ID!
knowledgePoint: String!
masteryLevel: Float!
subject: String!
recommendation: String
}
type ChildTrend {
childId: ID!
period: TrendPeriod!
dataPoints: [TrendDataPoint!]!
}
type TrendDataPoint {
date: DateTime!
score: Float!
subject: String
}
type LearningPathItem {
id: ID!
title: String!
subject: String!
order: Int!
masteryLevel: Float!
resources: [String!]!
}
type ErrorBookStats {
childId: ID!
totalCount: Int!
newCount: Int!
learningCount: Int!
masteredCount: Int!
dueReviewCount: Int!
masteredRate: Float!
}
type WrongQuestion {
id: ID!
questionId: ID!
subject: String!
content: String!
wrongAnswer: String!
correctAnswer: String!
addedAt: DateTime!
status: String!
}
type WeakKp {
id: ID!
knowledgePoint: String!
subject: String!
masteryLevel: Float!
recommendation: String
}
type MasterySummary {
childId: ID!
overallMastery: Float!
subjectMastery: [SubjectMastery!]!
totalKps: Int!
masteredKps: Int!
}
type SubjectMastery {
subject: String!
mastery: Float!
totalKps: Int!
masteredKps: Int!
}
type DiagnosticReport {
id: ID!
childId: ID!
subject: String!
reportDate: DateTime!
summary: String!
recommendations: [String!]!
}
type PracticeStats {
childId: ID!
totalSessions: Int!
completedSessions: Int!
totalQuestionsAnswered: Int!
overallAccuracy: Float!
}
type PracticeSession {
id: ID!
childId: ID!
subject: String!
startedAt: DateTime!
completedAt: DateTime
questionCount: Int!
correctCount: Int!
accuracy: Float!
}
type CoursePlan {
id: ID!
childId: ID!
subject: String!
title: String!
startDate: DateTime!
endDate: DateTime!
progress: Float!
}
type CoursePlanDetail {
id: ID!
childId: ID!
subject: String!
title: String!
startDate: DateTime!
endDate: DateTime!
progress: Float!
lessons: [CoursePlanLesson!]!
}
type CoursePlanLesson {
id: ID!
title: String!
date: DateTime!
completed: Boolean!
}
type LessonPlan {
id: ID!
childId: ID!
subject: String!
title: String!
date: DateTime!
teacherName: String!
}
type LessonPlanDetail {
id: ID!
childId: ID!
subject: String!
title: String!
date: DateTime!
teacherName: String!
objectives: [String!]!
content: String!
homework: String
}
type ElectiveCourse {
id: ID!
childId: ID!
name: String!
subject: String!
teacher: String!
schedule: String!
selected: Boolean!
}
type LeaveRequestItem {
id: ID!
childId: ID!
childName: String
className: String
type: String!
startDate: DateTime!
endDate: DateTime!
reason: String!
status: String!
submittedAt: DateTime!
reviewedAt: DateTime
reviewerName: String
reviewComment: String
}
type AcademicYear {
id: ID!
name: String!
startDate: DateTime!
endDate: DateTime!
isCurrent: Boolean!
}
type MyNotification {
id: ID!
childId: ID
eventType: String!
title: String!
body: String!
read: Boolean!
createdAt: DateTime!
actionUrl: String
pinned: Boolean!
}
type MyNotificationPreferences {
parentId: ID!
preferences: JSON!
defaults: NotificationPreferencesDefaults!
updatedAt: DateTime
}
type NotificationPreferencesDefaults {
channels: [NotificationChannel!]!
eventTypes: NotificationEventTypes!
}
type MarkAsReadResult {
id: ID!
read: Boolean!
}
type MarkAllAsReadResult {
count: Int!
}
type SwitchChildResult {
childId: ID!
childName: String!
selectedAt: DateTime!
}
type ExportChildGradesResult {
downloadUrl: String!
expiresAt: DateTime!
}
type UpdateNotificationPreferencesResult {
parentId: ID!
updatedAt: DateTime!
}
# ============ Query32 个) ============
type Query {
# Legacy11 个)
dashboard: DashboardData!
viewports: [ViewportItem!]!
me: Parent!
@@ -207,27 +616,81 @@ type Query {
pageSize: Int = 20
): [Notification!]!
notificationPreferences: NotificationPreferences!
# Extended21 个)
currentUser: Parent!
myChildren: [ChildBrief!]!
childSummary(childId: ID!): ChildSummary
childDetail(childId: ID!): ChildDetail
childAttendance(
childId: ID!
startDate: DateTime!
endDate: DateTime!
): [AttendanceRecord!]!
childExamResult(childId: ID!, examId: ID!): ExamResult
childClasses(childId: ID!): [ChildClass!]!
childReportCard(
childId: ID!
academicYearId: ID!
semester: Int!
): ReportCard
childGrowthArchive(childId: ID!, subject: String): GrowthArchive!
childWeakness(childId: ID!): [WeaknessItem!]!
childTrend(childId: ID!, period: TrendPeriod!): ChildTrend!
childLearningPath(childId: ID!): [LearningPathItem!]!
childErrorBookStats(childId: ID!): ErrorBookStats!
childTopWrongQuestions(childId: ID!, limit: Int): [WrongQuestion!]!
childWeakKps(childId: ID!, limit: Int): [WeakKp!]!
childMasterySummary(childId: ID!): MasterySummary!
childDiagnosticReports(childId: ID!): [DiagnosticReport!]!
childPracticeStats(childId: ID!): PracticeStats!
childPracticeSessions(childId: ID!, limit: Int): [PracticeSession!]!
childCoursePlans(childId: ID!): [CoursePlan!]!
childCoursePlanDetail(childId: ID!, planId: ID!): CoursePlanDetail
childLessonPlans(childId: ID!, subject: String): [LessonPlan!]!
childLessonPlanDetail(childId: ID!, planId: ID!): LessonPlanDetail
childElective(childId: ID!): [ElectiveCourse!]!
childLeaveRequests(childId: ID!): [LeaveRequestItem!]!
academicYears: [AcademicYear!]!
myNotifications(unreadOnly: Boolean, limit: Int): [MyNotification!]!
myNotificationPreferences: MyNotificationPreferences!
}
# ============ Mutation6 个) ============
type Mutation {
# Legacy3 个)
selectChild(childId: ID!): SelectChildResult!
markNotificationRead(notificationId: ID!): Notification!
updateNotificationPreferences(
input: UpdateNotificationPreferencesInput!
): NotificationPreferences!
# Extended6 个新 mutation覆盖前端全部操作
markAsRead(notificationId: ID!): MarkAsReadResult!
markAllAsRead: MarkAllAsReadResult!
switchChild(childId: ID!): SwitchChildResult!
updateMyNotificationPreferences(
parentId: ID!
preferences: JSON!
defaults: JSON
): UpdateNotificationPreferencesResult!
createLeaveRequest(input: LeaveRequestInput!): LeaveRequestItem!
exportChildGrades(childId: ID!, subject: String): ExportChildGradesResult!
}
# ============ Inputs ============
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!
enum TrendPeriod {
WEEK
MONTH
SEMESTER
YEAR
}
input UpdateNotificationPreferencesInput {
@@ -242,3 +705,17 @@ input NotificationEventTypesInput {
attendanceAlert: Boolean
schoolAnnouncement: Boolean
}
input LeaveRequestInput {
childId: ID!
type: String!
startDate: DateTime!
endDate: DateTime!
reason: String!
}
type SelectChildResult {
childId: ID!
selectedAt: DateTime!
audited: Boolean!
}