/** * GraphQL operations - P7 扩展(选修课 + 富文本编辑 + 监考 + 扫描批改 + 课标热力图) * * 维护者:ai13(teacher-portal) * 关联:graphql.ts P2/P3 扩展、workline.md §3 P7 交付物 * * schema 尚未在 ARB-001 P2 第一版中定义,开发期通过 MSW 拦截返回 mock 响应; * 上游就绪后由 ai03 在 teacher-bff.graphql 扩展,届时合并本文件到 graphql.ts。 * * 查询范围(P7-advanced): * - ElectiveCourses / ElectiveCourseDetail:选修课列表 + 详情 * - CreateElectiveCourse / UpdateElectiveCourse / PublishElectiveCourse / CancelElectiveCourse * - ExamRichEditor / SaveExamRichContent:富文本试卷内容 * - ProctoringStatus / ProctoringEvent:监考状态 + 事件 * - SubmissionScanGrading / SaveScanGrading:扫描批改 * - LessonPlanHeatmap:课标覆盖热力图 */ import { gql } from "urql"; // ============ Types(选修课) ============ /** 选修课状态 */ export type ElectiveCourseStatus = | "draft" | "open" | "closed" | "cancelled"; /** 选课学生项 */ export interface ElectiveStudent { studentId: string; studentName: string; studentNo: string; enrolledAt: string; status: "enrolled" | "cancelled"; } /** 选修课列表项 */ export interface ElectiveCourseItem { id: string; title: string; subject: string; grade: string; capacity: number; enrolledCount: number; teacherId: string; teacherName: string; semester: string; status: ElectiveCourseStatus; description: string | null; } /** 选修课详情(含学生列表) */ export interface ElectiveCourseDetail extends ElectiveCourseItem { students: ElectiveStudent[]; createdAt: string; updatedAt: string; } /** 创建选修课输入 */ export interface CreateElectiveCourseInput { title: string; subject: string; grade: string; capacity: number; semester: string; description?: string | null; } /** 更新选修课输入 */ export interface UpdateElectiveCourseInput { id: string; title?: string; subject?: string; grade?: string; capacity?: number; semester?: string; description?: string | null; } /** 创建/更新结果 */ export interface ElectiveCourseMutationResult { id: string; status: ElectiveCourseStatus; updatedAt: string; } // ============ Types(富文本编辑) ============ /** 富文本试卷内容(Tiptap examNodes JSON 结构,mock 用 JSON) */ export interface ExamRichContent { examId: string; title: string; totalScore: number; questionCount: number; content: unknown; // Tiptap JSON,结构由编辑器决定 updatedAt: string; } /** 保存富文本输入 */ export interface SaveExamRichContentInput { examId: string; content: unknown; } /** 保存富文本结果 */ export interface SaveExamRichContentResult { examId: string; updatedAt: string; } // ============ Types(监考) ============ /** 监考学生状态 */ export type ProctoringStudentStatus = | "online" | "offline" | "submitted" | "flagged"; /** 监考摘要 */ export interface ProctoringSummary { examId: string; expectedCount: number; onlineCount: number; submittedCount: number; flaggedCount: number; isProctoring: boolean; startedAt: string | null; } /** 监考学生状态项 */ export interface ProctoringStudent { studentId: string; studentName: string; studentNo: string; status: ProctoringStudentStatus; lastEventAt: string | null; ipAddress: string | null; } /** 监考事件类型 */ export type ProctoringEventType = "WARNING" | "FLAG" | "NOTE"; /** 监考事件项 */ export interface ProctoringEvent { eventId: string; examId: string; studentId: string; studentName: string; studentNo: string; eventType: ProctoringEventType; note: string | null; createdAt: string; } /** 监考状态完整结构 */ export interface ProctoringStatus { summary: ProctoringSummary; students: ProctoringStudent[]; recentEvents: ProctoringEvent[]; } /** 提交监考事件输入 */ export interface ProctoringEventInput { examId: string; studentId: string; eventType: ProctoringEventType; note?: string | null; } /** 提交监考事件结果 */ export interface ProctoringEventResult { eventId: string; createdAt: string; } // ============ Types(扫描批改) ============ /** 扫描图片项 */ export interface ScanImage { imageId: string; url: string; page: number; } /** 扫描批改单题项 */ export interface ScanGradingItem { questionId: string; questionTitle: string; questionOrder: number; maxScore: number; recognizedAnswer: string; aiSuggestedScore: number | null; aiSuggestion: string | null; score: number | null; feedback: string | null; } /** 扫描批改视图 */ export interface SubmissionScanGrading { submissionId: string; homeworkTitle: string; studentName: string; studentNo: string; submittedAt: string; images: ScanImage[]; items: ScanGradingItem[]; prevSubmissionId: string | null; nextSubmissionId: string | null; } /** 保存扫描批改单项 */ export interface SaveScanGradingItem { questionId: string; score: number; feedback?: string | null; } /** 保存扫描批改输入 */ export interface SaveScanGradingInput { submissionId: string; items: SaveScanGradingItem[]; } /** 保存扫描批改结果 */ export interface SaveScanGradingResult { submissionId: string; totalScore: number; savedAt: string; } // ============ Types(课标热力图) ============ /** 热力图知识点项 */ export interface HeatmapKnowledgePoint { kpId: string; name: string; chapterName: string; } /** 热力图课案项 */ export interface HeatmapLessonPlan { planId: string; title: string; } /** 热力图覆盖矩阵单元格 */ export interface HeatmapCell { kpId: string; planId: string; coverage: number; // 0-3 覆盖课案数 } /** 课标覆盖热力图 */ export interface LessonPlanHeatmap { textbookId: string; textbookTitle: string; knowledgePoints: HeatmapKnowledgePoint[]; lessonPlans: HeatmapLessonPlan[]; cells: HeatmapCell[]; } // ============ Queries / Mutations(选修课) ============ /** 选修课列表查询(按状态筛选,教师范围) */ export const ElectiveCoursesQuery = gql` query ElectiveCourses($status: String, $subject: String) { electiveCourses(status: $status, subject: $subject) { id title subject grade capacity enrolledCount teacherId teacherName semester status description } } `; /** 选修课详情查询(含学生列表) */ export const ElectiveCourseDetailQuery = gql` query ElectiveCourseDetail($id: ID!) { electiveCourseDetail(id: $id) { id title subject grade capacity enrolledCount teacherId teacherName semester status description students { studentId studentName studentNo enrolledAt status } createdAt updatedAt } } `; /** 创建选修课 Mutation */ export const CreateElectiveCourseMutation = gql` mutation CreateElectiveCourse($input: CreateElectiveCourseInput!) { createElectiveCourse(input: $input) { id status updatedAt } } `; /** 更新选修课 Mutation */ export const UpdateElectiveCourseMutation = gql` mutation UpdateElectiveCourse($input: UpdateElectiveCourseInput!) { updateElectiveCourse(input: $input) { id status updatedAt } } `; /** 发布选修课 Mutation */ export const PublishElectiveCourseMutation = gql` mutation PublishElectiveCourse($id: ID!) { publishElectiveCourse(id: $id) { id status updatedAt } } `; /** 取消选修课 Mutation */ export const CancelElectiveCourseMutation = gql` mutation CancelElectiveCourse($id: ID!) { cancelElectiveCourse(id: $id) { id status updatedAt } } `; // ============ Queries / Mutations(富文本编辑) ============ /** 富文本试卷内容查询 */ export const ExamRichEditorQuery = gql` query ExamRichEditor($examId: ID!) { examRichEditor(examId: $examId) { examId title totalScore questionCount content updatedAt } } `; /** 保存富文本内容 Mutation */ export const SaveExamRichContentMutation = gql` mutation SaveExamRichContent($input: SaveExamRichContentInput!) { saveExamRichContent(input: $input) { examId updatedAt } } `; // ============ Queries / Mutations(监考) ============ /** 监考状态查询 */ export const ProctoringStatusQuery = gql` query ProctoringStatus($examId: ID!) { proctoringStatus(examId: $examId) { summary { examId expectedCount onlineCount submittedCount flaggedCount isProctoring startedAt } students { studentId studentName studentNo status lastEventAt ipAddress } recentEvents { eventId examId studentId studentName studentNo eventType note createdAt } } } `; /** 提交监考事件 Mutation */ export const ProctoringEventMutation = gql` mutation ProctoringEvent($input: ProctoringEventInput!) { proctoringEvent(input: $input) { eventId createdAt } } `; // ============ Queries / Mutations(扫描批改) ============ /** 扫描批改视图查询 */ export const SubmissionScanGradingQuery = gql` query SubmissionScanGrading($submissionId: ID!) { submissionScanGrading(submissionId: $submissionId) { submissionId homeworkTitle studentName studentNo submittedAt images { imageId url page } items { questionId questionTitle questionOrder maxScore recognizedAnswer aiSuggestedScore aiSuggestion score feedback } prevSubmissionId nextSubmissionId } } `; /** 保存扫描批改 Mutation */ export const SaveScanGradingMutation = gql` mutation SaveScanGrading($input: SaveScanGradingInput!) { saveScanGrading(input: $input) { submissionId totalScore savedAt } } `; // ============ Queries(课标热力图) ============ /** 课标覆盖热力图查询(按教材 ID) */ export const LessonPlanHeatmapQuery = gql` query LessonPlanHeatmap($textbookId: ID!) { lessonPlanHeatmap(textbookId: $textbookId) { textbookId textbookTitle knowledgePoints { kpId name chapterName } lessonPlans { planId title } cells { kpId planId coverage } } } `;