feat(shared-ts): 同步 3 个 BFF GraphQL schema + downstream-client/logger/outbox 增强
This commit is contained in:
@@ -10,10 +10,13 @@
|
||||
# - C1:错误码前缀 BFF_PARENT_
|
||||
# - U4:BFF 豁免 @RequirePermission,仅校验 x-user-id + ChildGuard
|
||||
# - 02 §9 #5:depth ≤ 7 / cost ≤ 1000
|
||||
#
|
||||
# 版本:v2(32 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 Types(v2 新增) ============
|
||||
|
||||
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!
|
||||
}
|
||||
|
||||
# ============ Query(32 个) ============
|
||||
|
||||
type Query {
|
||||
# Legacy(11 个)
|
||||
dashboard: DashboardData!
|
||||
viewports: [ViewportItem!]!
|
||||
me: Parent!
|
||||
@@ -207,27 +616,81 @@ type Query {
|
||||
pageSize: Int = 20
|
||||
): [Notification!]!
|
||||
notificationPreferences: NotificationPreferences!
|
||||
|
||||
# Extended(21 个)
|
||||
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!
|
||||
}
|
||||
|
||||
# ============ Mutation(6 个) ============
|
||||
|
||||
type Mutation {
|
||||
# Legacy(3 个)
|
||||
selectChild(childId: ID!): SelectChildResult!
|
||||
markNotificationRead(notificationId: ID!): Notification!
|
||||
updateNotificationPreferences(
|
||||
input: UpdateNotificationPreferencesInput!
|
||||
): NotificationPreferences!
|
||||
|
||||
# Extended(6 个新 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!
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user