/** * MSW P4 Handlers - 知识图谱 + 学情分析 mock 拦截 * * 独立于 handlers.ts 维护,合并时将 p4Handlers 追加到主 handlers 数组, * 并在主 handleGraphQL 的 default 之前插入以下 case。 * * 覆盖 operationName(对应 graphql-p4.ts): * - KnowledgeGraph → 知识图谱节点 + 边 * - ClassAnalytics → 班级学情分析 * - StudentAnalytics → 单生学情分析 * * 维护者:ai13(teacher-portal) */ import { http, HttpResponse } from "msw"; import { filterKnowledgeGraph } from "./fixtures/knowledge-graph"; import { mockClassAnalytics, findStudentAnalytics, } from "./fixtures/analytics"; /** GraphQL 响应体(urql 期望 { data: ... }) */ function graphqlData(data: T) { return HttpResponse.json({ data }); } /** * 根据 operationName 路由 P4 GraphQL mock 响应 * * 返回 null 表示当前 operationName 不属于 P4,交回主 handler 处理。 */ export function handleP4GraphQL( operationName: string, variables: Record, ) { switch (operationName) { case "KnowledgeGraph": { const subject = (variables.subject as string | undefined) ?? null; return graphqlData({ knowledgeGraph: filterKnowledgeGraph(subject), }); } case "ClassAnalytics": { // classId 传入但 mock 数据固定,返回时回填以保证字段一致 const classId = (variables.classId as string | undefined) ?? mockClassAnalytics.classId; return graphqlData({ classAnalytics: { ...mockClassAnalytics, classId }, }); } case "StudentAnalytics": { const studentId = (variables.studentId as string | undefined) ?? "stu-001"; return graphqlData({ studentAnalytics: findStudentAnalytics(studentId), }); } default: return null; } } /** * P4 独立 handler(POST /api/v1/teacher/graphql) * * 合并策略:将本数组追加到 handlers.ts 的 handlers 数组之前(MSW 按顺序匹配, * 先于主 handler 的 default case 命中 P4 operation)。 */ export const p4Handlers = [ http.post("*/api/v1/teacher/graphql", async ({ request }) => { const body = (await request.json()) as { operationName?: string; query?: string; variables?: Record; }; const operationName = body.operationName ?? extractOperationName(body.query); const variables = body.variables ?? {}; const p4Result = handleP4GraphQL(operationName, variables); if (p4Result) { return p4Result; } // 非 P4 operation:交回后续 handler(返回 passthrough 让 MSW 继续匹配) return HttpResponse.json( { errors: [ { message: `P4 handler 未覆盖的 GraphQL operation: ${operationName}`, extensions: { code: "BFF_TEACHER_NOT_IMPLEMENTED" }, }, ], }, { status: 200 }, ); }), ]; /** 从 query 字符串提取 operationName(兜底) */ function extractOperationName(query?: string): string { if (!query) return "Unknown"; const match = query.match(/(?:query|mutation)\s+(\w+)/); return match?.[1] ?? "Unknown"; }