{
  "test_date": "2026-06-22 19:32:45",
  "module": "年级管理 (Grade Management)",
  "version": "v1",
  "base_url": "http://localhost:3000",
  "covered_submodules": [
    "admin-grades",
    "admin-insights",
    "management-classes",
    "management-insights"
  ],
  "summary": {
    "total": 22,
    "passed": 20,
    "failed": 0,
    "warnings": 2
  },
  "roles": {
    "admin": {
      "role": "admin",
      "login_success": true,
      "access_tests": [
        {
          "route_key": "admin_grades",
          "url": "http://localhost:3000/admin/school/grades",
          "expected_access": true,
          "http_status": 200,
          "final_url": "http://localhost:3000/admin/school/grades",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "页面正常加载",
              "passed": true
            }
          ]
        },
        {
          "route_key": "admin_insights",
          "url": "http://localhost:3000/admin/school/grades/insights",
          "expected_access": true,
          "http_status": 200,
          "final_url": "http://localhost:3000/admin/school/grades/insights",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "页面正常加载",
              "passed": true
            }
          ]
        },
        {
          "route_key": "management_classes",
          "url": "http://localhost:3000/management/grade/classes",
          "expected_access": true,
          "http_status": 200,
          "final_url": "http://localhost:3000/management/grade/classes",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "页面正常加载",
              "passed": true
            }
          ]
        },
        {
          "route_key": "management_insights",
          "url": "http://localhost:3000/management/grade/insights",
          "expected_access": true,
          "http_status": 200,
          "final_url": "http://localhost:3000/management/grade/insights",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "页面正常加载",
              "passed": true
            }
          ]
        }
      ],
      "crud_tests": [
        {
          "feature": "年级 CRUD (admin)",
          "role": "admin",
          "operations": [
            {
              "name": "列表加载",
              "passed": true,
              "detail": "列表/空状态正常显示"
            },
            {
              "name": "筛选器存在",
              "passed": true,
              "detail": "找到筛选器（select: 3, search: 1）"
            },
            {
              "name": "打开创建对话框",
              "passed": true,
              "detail": "创建对话框已打开"
            },
            {
              "name": "编辑入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            },
            {
              "name": "删除入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            },
            {
              "name": "洞察入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            }
          ],
          "status": "passed",
          "errors": []
        },
        {
          "feature": "年级班级 CRUD (grade_head)",
          "role": "admin",
          "operations": [
            {
              "name": "列表加载",
              "passed": false,
              "detail": "未找到表格或空状态"
            },
            {
              "name": "打开创建对话框",
              "passed": false,
              "detail": "异常: Locator.click: Timeout 30000ms exceeded.\nCall log:\n  - waiting for locator(\"button:has-text(\\\"New\\\"), button:has-text(\\\"新建\\\"), button:has-text(\\\"Create\\\"), button:has-text(\\\"新增\\\")\").first\n    - locator resolved to <button disabled data-slot=\"button\" class=\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 focus-visible:ring-4 focus-visible:outline-1 aria-invalid:focus-visible:ring-0 bg-primary text-primary-foreground shadow-sm hover:bg-primary/90 h-9…>…</button>\n  - attempting click action\n    2 × waiting for element to be visible, enabled and stable\n      - element is not enabled\n    - retrying click action\n    - waiting 20ms\n    2 × waiting for element to be visible, enabled and stable\n      - element is not enabled\n    - retrying click action\n      - waiting 100ms\n    58 × waiting for element to be visible, enabled and stable\n       - element is not enabled\n     - retrying click action\n       - waiting 500ms\n"
            },
            {
              "name": "编辑入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            },
            {
              "name": "删除入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            }
          ],
          "status": "warning",
          "errors": []
        }
      ],
      "insights_tests": [
        {
          "feature": "洞察页面 (admin_insights)",
          "role": "admin",
          "operations": [
            {
              "name": "页面加载",
              "passed": true,
              "detail": "页面内容长度 421472"
            },
            {
              "name": "年级筛选器存在",
              "passed": true,
              "detail": "找到年级筛选 select"
            }
          ],
          "status": "passed",
          "errors": []
        },
        {
          "feature": "洞察页面 (management_insights)",
          "role": "admin",
          "operations": [
            {
              "name": "页面加载",
              "passed": true,
              "detail": "页面内容长度 449687"
            },
            {
              "name": "年级筛选器存在",
              "passed": false,
              "detail": "未找到年级筛选 select"
            }
          ],
          "status": "warning",
          "errors": []
        }
      ],
      "errors": [],
      "warnings": [
        "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran",
        "控制台错误: %o\n\n%s Error: Teacher not found\n    at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5Csrc_modules_2587b0bf._.js?113:5823:27)\n    at  Teacher",
        "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran",
        "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran",
        "控制台错误: %o\n\n%s Error: Teacher not found\n    at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5Csrc_modules_2587b0bf._.js?113:5823:27)\n    at  Teacher"
      ]
    },
    "teacher": {
      "role": "teacher",
      "login_success": true,
      "access_tests": [
        {
          "route_key": "admin_grades",
          "url": "http://localhost:3000/admin/school/grades",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/teacher/dashboard?from=%2Fadmin%2Fschool%2Fgrades&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/teacher/dashboard?from=%2Fadmin%2Fschool%2Fgrades&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "admin_insights",
          "url": "http://localhost:3000/admin/school/grades/insights",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/teacher/dashboard?from=%2Fadmin%2Fschool%2Fgrades%2Finsights&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/teacher/dashboard?from=%2Fadmin%2Fschool%2Fgrades%2Finsights&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "management_classes",
          "url": "http://localhost:3000/management/grade/classes",
          "expected_access": true,
          "http_status": 200,
          "final_url": "http://localhost:3000/management/grade/classes",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "页面正常加载",
              "passed": true
            }
          ]
        },
        {
          "route_key": "management_insights",
          "url": "http://localhost:3000/management/grade/insights",
          "expected_access": true,
          "http_status": 200,
          "final_url": "http://localhost:3000/management/grade/insights",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "页面正常加载",
              "passed": true
            }
          ]
        }
      ],
      "crud_tests": [
        {
          "feature": "年级 CRUD (admin)",
          "role": "teacher",
          "operations": [],
          "status": "skipped",
          "errors": [
            "teacher 无 SCHOOL_MANAGE 权限，跳过 admin 年级 CRUD 测试"
          ]
        },
        {
          "feature": "年级班级 CRUD (grade_head)",
          "role": "teacher",
          "operations": [
            {
              "name": "列表加载",
              "passed": true,
              "detail": "列表/空状态正常显示"
            },
            {
              "name": "打开创建对话框",
              "passed": true,
              "detail": "创建对话框已打开"
            },
            {
              "name": "编辑入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            },
            {
              "name": "删除入口存在",
              "passed": true,
              "detail": "无数据行，跳过"
            }
          ],
          "status": "passed",
          "errors": []
        }
      ],
      "insights_tests": [
        {
          "feature": "洞察页面 (admin_insights)",
          "role": "teacher",
          "operations": [],
          "status": "skipped",
          "errors": [
            "teacher 无访问权限，跳过洞察页面测试"
          ]
        },
        {
          "feature": "洞察页面 (management_insights)",
          "role": "teacher",
          "operations": [
            {
              "name": "页面加载",
              "passed": true,
              "detail": "页面内容长度 450625"
            },
            {
              "name": "年级筛选器存在",
              "passed": true,
              "detail": "找到年级筛选 select"
            }
          ],
          "status": "passed",
          "errors": []
        }
      ],
      "errors": [],
      "warnings": [
        "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran"
      ]
    },
    "student": {
      "role": "student",
      "login_success": true,
      "access_tests": [
        {
          "route_key": "admin_grades",
          "url": "http://localhost:3000/admin/school/grades",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/student/dashboard?from=%2Fadmin%2Fschool%2Fgrades&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fadmin%2Fschool%2Fgrades&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "admin_insights",
          "url": "http://localhost:3000/admin/school/grades/insights",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/student/dashboard?from=%2Fadmin%2Fschool%2Fgrades%2Finsights&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fadmin%2Fschool%2Fgrades%2Finsights&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "management_classes",
          "url": "http://localhost:3000/management/grade/classes",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/student/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "management_insights",
          "url": "http://localhost:3000/management/grade/insights",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/student/dashboard?from=%2Fmanagement%2Fgrade%2Finsights&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/student/dashboard?from=%2Fmanagement%2Fgrade%2Finsights&reason=forbidden"
            }
          ]
        }
      ],
      "crud_tests": [
        {
          "feature": "年级 CRUD (admin)",
          "role": "student",
          "operations": [],
          "status": "skipped",
          "errors": [
            "student 无 SCHOOL_MANAGE 权限，跳过 admin 年级 CRUD 测试"
          ]
        },
        {
          "feature": "年级班级 CRUD (grade_head)",
          "role": "student",
          "operations": [],
          "status": "skipped",
          "errors": [
            "student 无 GRADE_MANAGE 权限，跳过 management 班级 CRUD 测试"
          ]
        }
      ],
      "insights_tests": [
        {
          "feature": "洞察页面 (admin_insights)",
          "role": "student",
          "operations": [],
          "status": "skipped",
          "errors": [
            "student 无访问权限，跳过洞察页面测试"
          ]
        },
        {
          "feature": "洞察页面 (management_insights)",
          "role": "student",
          "operations": [],
          "status": "skipped",
          "errors": [
            "student 无访问权限，跳过洞察页面测试"
          ]
        }
      ],
      "errors": [],
      "warnings": [
        "控制台错误: ./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^",
        "控制台错误: ./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^",
        "控制台错误: ./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^",
        "控制台错误: ./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^",
        "控制台错误: ./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^"
      ]
    },
    "parent": {
      "role": "parent",
      "login_success": true,
      "access_tests": [
        {
          "route_key": "admin_grades",
          "url": "http://localhost:3000/admin/school/grades",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool%2Fgrades&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool%2Fgrades&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "admin_insights",
          "url": "http://localhost:3000/admin/school/grades/insights",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool%2Fgrades%2Finsights&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool%2Fgrades%2Finsights&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "management_classes",
          "url": "http://localhost:3000/management/grade/classes",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden"
            }
          ]
        },
        {
          "route_key": "management_insights",
          "url": "http://localhost:3000/management/grade/insights",
          "expected_access": false,
          "http_status": 200,
          "final_url": "http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Finsights&reason=forbidden",
          "status": "passed",
          "errors": [],
          "warnings": [],
          "checks": [
            {
              "name": "权限拒绝重定向",
              "passed": true,
              "detail": "正确重定向到 http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Finsights&reason=forbidden"
            }
          ]
        }
      ],
      "crud_tests": [
        {
          "feature": "年级 CRUD (admin)",
          "role": "parent",
          "operations": [],
          "status": "skipped",
          "errors": [
            "parent 无 SCHOOL_MANAGE 权限，跳过 admin 年级 CRUD 测试"
          ]
        },
        {
          "feature": "年级班级 CRUD (grade_head)",
          "role": "parent",
          "operations": [],
          "status": "skipped",
          "errors": [
            "parent 无 GRADE_MANAGE 权限，跳过 management 班级 CRUD 测试"
          ]
        }
      ],
      "insights_tests": [
        {
          "feature": "洞察页面 (admin_insights)",
          "role": "parent",
          "operations": [],
          "status": "skipped",
          "errors": [
            "parent 无访问权限，跳过洞察页面测试"
          ]
        },
        {
          "feature": "洞察页面 (management_insights)",
          "role": "parent",
          "operations": [],
          "status": "skipped",
          "errors": [
            "parent 无访问权限，跳过洞察页面测试"
          ]
        }
      ],
      "errors": [],
      "warnings": [
        "控制台错误: A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client bran"
      ]
    }
  },
  "console_errors_global": [
    {
      "role": "admin",
      "error": "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n%s%s https://react.dev/link/hydration-mismatch \n\n  ...\n    <div className=\"flex items...\">\n      <GlobalSearch>\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" size=\"icon\" className=\"relative t...\" aria-label=\"通知\" type=\"button\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded...\"}\n                                  aria-label=\"通知\"\n                                  type=\"button\"\n+                                 id=\"radix-_R_lebn6lb_\"\n-                                 id=\"radix-_R_2lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" className=\"relative s...\" type=\"button\" id=\"radix-_R_t...\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm...\"}\n                                  type=\"button\"\n+                                 id=\"radix-_R_tebn6lb_\"\n-                                 id=\"radix-_R_3lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n"
    },
    {
      "role": "admin",
      "error": "%o\n\n%s Error: Teacher not found\n    at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5Csrc_modules_2587b0bf._.js?113:5823:27)\n    at  TeacherGradeInsightsPage (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__86fbdb11._.js?114:440:23)\n    at resolveErrorDev (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:1882:148)\n    at processFullStringRow (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2390:29)\n    at processFullBinaryRow (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2349:9)\n    at processBinaryChunk (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2459:98)\n    at progress (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2628:13) The above error occurred in the <TeacherGradeInsightsPage> component. It was handled by the <ErrorBoundaryHandler> error boundary."
    },
    {
      "role": "admin",
      "error": "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n%s%s https://react.dev/link/hydration-mismatch \n\n  ...\n    <div className=\"flex items...\">\n      <GlobalSearch>\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" size=\"icon\" className=\"relative t...\" aria-label=\"通知\" type=\"button\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded...\"}\n                                  aria-label=\"通知\"\n                                  type=\"button\"\n+                                 id=\"radix-_R_lebn6lb_\"\n-                                 id=\"radix-_R_2lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" className=\"relative s...\" type=\"button\" id=\"radix-_R_t...\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm...\"}\n                                  type=\"button\"\n+                                 id=\"radix-_R_tebn6lb_\"\n-                                 id=\"radix-_R_3lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n"
    },
    {
      "role": "admin",
      "error": "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n%s%s https://react.dev/link/hydration-mismatch \n\n  ...\n    <tbody ref={null} role=\"rowgroup\" className={\"[&_tr:la...\"}>\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_e...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_e...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_e...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" size=\"icon\" className=\"h-8 w-8\" disabled={false} type=\"button\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded...\"}\n                                  disabled={false}\n                                  type=\"button\"\n+                                 id=\"radix-_R_eqb9bn5ritqbnubn6lb_\"\n-                                 id=\"radix-_R_1r9d5esnebn9evqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_f...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_f...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_f...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" size=\"icon\" className=\"h-8 w-8\" disabled={false} type=\"button\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded...\"}\n                                  disabled={false}\n                                  type=\"button\"\n+                                 id=\"radix-_R_fab9bn5ritqbnubn6lb_\"\n-                                 id=\"radix-_R_1t9d5esnebn9evqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n"
    },
    {
      "role": "admin",
      "error": "%o\n\n%s Error: Teacher not found\n    at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5Csrc_modules_2587b0bf._.js?113:5823:27)\n    at  TeacherGradeInsightsPage (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__86fbdb11._.js?114:440:23)\n    at resolveErrorDev (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:1882:148)\n    at processFullStringRow (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2390:29)\n    at processFullBinaryRow (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2349:9)\n    at processBinaryChunk (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2459:98)\n    at progress (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:2628:13) The above error occurred in the <TeacherGradeInsightsPage> component. It was handled by the <ErrorBoundaryHandler> error boundary."
    },
    {
      "role": "teacher",
      "error": "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n%s%s https://react.dev/link/hydration-mismatch \n\n  ...\n    <div className=\"flex items...\">\n      <GlobalSearch>\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" size=\"icon\" className=\"relative t...\" aria-label=\"通知\" type=\"button\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded...\"}\n                                  aria-label=\"通知\"\n                                  type=\"button\"\n+                                 id=\"radix-_R_lebn6lb_\"\n-                                 id=\"radix-_R_2lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" className=\"relative s...\" type=\"button\" id=\"radix-_R_t...\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm...\"}\n                                  type=\"button\"\n+                                 id=\"radix-_R_tebn6lb_\"\n-                                 id=\"radix-_R_3lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n"
    },
    {
      "role": "student",
      "error": "./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^^^^^^^^^^^\n  123 |\n  124 |   return (\n  125 |     <div className=\"flex h-full flex-col gap-8 p-8\">\n\nthe name `canConfigureAi` is defined multiple times\n\nImport trace:\n  Server Component:\n    ./src/modules/settings/components/settings-view.tsx\n    ./src/app/(dashboard)/settings/page.tsx"
    },
    {
      "role": "student",
      "error": "./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^^^^^^^^^^^\n  123 |\n  124 |   return (\n  125 |     <div className=\"flex h-full flex-col gap-8 p-8\">\n\nthe name `canConfigureAi` is defined multiple times\n\nImport trace:\n  Server Component:\n    ./src/modules/settings/components/settings-view.tsx\n    ./src/app/(dashboard)/settings/page.tsx"
    },
    {
      "role": "student",
      "error": "./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^^^^^^^^^^^\n  123 |\n  124 |   return (\n  125 |     <div className=\"flex h-full flex-col gap-8 p-8\">\n\nthe name `canConfigureAi` is defined multiple times\n\nImport trace:\n  Server Component:\n    ./src/modules/settings/components/settings-view.tsx\n    ./src/app/(dashboard)/settings/page.tsx"
    },
    {
      "role": "student",
      "error": "./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^^^^^^^^^^^\n  123 |\n  124 |   return (\n  125 |     <div className=\"flex h-full flex-col gap-8 p-8\">\n\nthe name `canConfigureAi` is defined multiple times\n\nImport trace:\n  Server Component:\n    ./src/modules/settings/components/settings-view.tsx\n    ./src/app/(dashboard)/settings/page.tsx"
    },
    {
      "role": "student",
      "error": "./src/modules/settings/components/settings-view.tsx:122:9\nEcmascript file had an error\n  120 |   }\n  121 |\n> 122 |   const canConfigureAi = hasPermission(Permissions.AI_CONFIGURE)\n      |         ^^^^^^^^^^^^^^\n  123 |\n  124 |   return (\n  125 |     <div className=\"flex h-full flex-col gap-8 p-8\">\n\nthe name `canConfigureAi` is defined multiple times\n\nImport trace:\n  Server Component:\n    ./src/modules/settings/components/settings-view.tsx\n    ./src/app/(dashboard)/settings/page.tsx"
    },
    {
      "role": "parent",
      "error": "A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:\n\n- A server/client branch `if (typeof window !== 'undefined')`.\n- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.\n- Date formatting in a user's locale which doesn't match the server.\n- External changing data without sending a snapshot of it along with the HTML.\n- Invalid HTML tag nesting.\n\nIt can also happen if the client has a browser extension installed which messes with the HTML before React loaded.\n\n%s%s https://react.dev/link/hydration-mismatch \n\n  ...\n    <div className=\"flex items...\">\n      <GlobalSearch>\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_l...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" size=\"icon\" className=\"relative t...\" aria-label=\"通知\" type=\"button\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded...\"}\n                                  aria-label=\"通知\"\n                                  type=\"button\"\n+                                 id=\"radix-_R_lebn6lb_\"\n-                                 id=\"radix-_R_2lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n      ...\n        <MenuProvider scope={{Menu:[...], ...}} onClose={function Menu.useCallback} isUsingKeyboardRef={{current:false}} ...>\n          <DropdownMenuTrigger asChild={true}>\n            <DropdownMenuTrigger data-slot=\"dropdown-m...\" asChild={true}>\n              <MenuAnchor asChild={true} __scopeMenu={{Menu:[...], ...}}>\n                <PopperAnchor __scopePopper={{Menu:[...], ...}} asChild={true} ref={null}>\n                  <Primitive.div asChild={true} ref={function}>\n                    <Primitive.div.Slot ref={function}>\n                      <Primitive.div.SlotClone ref={function}>\n                        <Primitive.button type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" aria-expanded={false} ...>\n                          <Primitive.button.Slot type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                            <Primitive.button.SlotClone type=\"button\" id=\"radix-_R_t...\" aria-haspopup=\"menu\" ...>\n                              <Button variant=\"ghost\" className=\"relative s...\" type=\"button\" id=\"radix-_R_t...\" ...>\n                                <button\n                                  data-slot=\"dropdown-menu-trigger\"\n                                  className={\"inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm...\"}\n                                  type=\"button\"\n+                                 id=\"radix-_R_tebn6lb_\"\n-                                 id=\"radix-_R_3lqbn6lb_\"\n                                  aria-haspopup=\"menu\"\n                                  aria-expanded={false}\n                                  aria-controls={undefined}\n                                  data-state=\"closed\"\n                                  data-disabled={undefined}\n                                  disabled={false}\n                                  onPointerDown={function handleEvent}\n                                  onKeyDown={function handleEvent}\n                                  ref={function}\n                                >\n          ...\n"
    }
  ]
}