Files
NextEdu/bugs/parent_web_test.json
SpecialX 978d9a8309
Some checks failed
Security / deep-security-scan (push) Failing after 20m5s
DR Drill / dr-drill (push) Failing after 1m31s
CI / scheduled-backup (push) Failing after 1m31s
CI / backup-verify (push) Has been skipped
CI / weekly-dr-drill (push) Failing after 0s
CI / build-deploy (push) Has been cancelled
CI / security-scan (push) Has been cancelled
feat: 新增备课模块并修复全模块 P0/P1/P2 缺陷
主要变更:

- 新增 lesson-preparation 模块: 备课编辑器、节点编辑、AI 建议、知识点选择、版本历史、作业发布

- 新增 shared 通用组件: charts/question-bank-filters/schedule-list/ui (chip-nav/filter-bar/page-header/stat-card/stat-item)

- 新增 student/admin 端 loading.tsx 与 error.tsx, 优化加载与错误态体验

- 新增 teacher/lesson-plans 页面 (列表/新建/编辑)

- 新增 drizzle 迁移 0002_tiny_lionheart 及 snapshot

- 新增 textbooks/schema.ts 与 exams/utils/normalize-structure.ts

- 修复 Tiptap v3 SSR hydration 崩溃 (rich-text-block immediatelyRender: false)

- 重构多模块 data-access/actions/组件, 修复权限校验与类型规范

- 同步架构文档 004/005 反映新增模块、导出、依赖关系

- 归档 bugs/* 测试报告与 e2e 测试脚本 (admin/parent/student/teacher web_test)
2026-06-22 01:06:16 +08:00

493 lines
17 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"test_date": "2026-06-20 12:28:43",
"test_target": "家长端 (Parent)",
"base_url": "http://localhost:3000",
"parent_email": "parent_g1c1_1@xiaoxue.edu.cn",
"summary": {
"total": 24,
"passed": 17,
"failed": 7,
"warnings": 0
},
"pages": {
"parent_dashboard": {
"url": "http://localhost:3000/parent/dashboard",
"route": "/parent/dashboard",
"category": "Dashboard",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"parent_grades": {
"url": "http://localhost:3000/parent/grades",
"route": "/parent/grades",
"category": "Grades",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/grades",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"parent_attendance": {
"url": "http://localhost:3000/parent/attendance",
"route": "/parent/attendance",
"category": "Attendance",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/attendance",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"announcements": {
"url": "http://localhost:3000/announcements",
"route": "/announcements",
"category": "Announcements",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/announcements",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"messages": {
"url": "http://localhost:3000/messages",
"route": "/messages",
"category": "Messages",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/messages",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"messages_compose": {
"url": "http://localhost:3000/messages/compose",
"route": "/messages/compose",
"category": "Messages",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/messages/compose",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"profile": {
"url": "http://localhost:3000/profile",
"route": "/profile",
"category": "Profile",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/profile",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"settings": {
"url": "http://localhost:3000/settings",
"route": "/settings",
"category": "Settings",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/settings",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"settings_security": {
"url": "http://localhost:3000/settings/security",
"route": "/settings/security",
"category": "Settings",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/settings/security",
"redirect_url": null,
"errors": [],
"warnings": [],
"content_checks": []
},
"parent_children_user_s_g1c1_1": {
"url": "http://localhost:3000/parent/children/user_s_g1c1_1",
"route": "/parent/children/user_s_g1c1_1",
"category": "Child Detail",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/children/user_s_g1c1_1",
"redirect_url": null,
"errors": [],
"warnings": [
"Error text on page: Due 2026年6月18日"
],
"content_checks": []
},
"forbidden_admin_dashboard": {
"url": "http://localhost:3000/admin/dashboard",
"route": "/admin/dashboard",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fdashboard&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fdashboard&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
},
"forbidden_admin_school": {
"url": "http://localhost:3000/admin/school",
"route": "/admin/school",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fadmin%2Fschool&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
},
"forbidden_teacher_dashboard": {
"url": "http://localhost:3000/teacher/dashboard",
"route": "/teacher/dashboard",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 500,
"final_url": "http://localhost:3000/teacher/dashboard",
"redirect_url": null,
"errors": [
"跨角色访问返回 HTTP 500应被重定向拦截",
"Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
"%o\n\n%s Error: Teacher not found\n at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__458f1717._.js?61:9381:27)\n at TeacherDashboardPage (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__6e4018f8._.js?62:2019:23)\n at resolveErrorDev (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:...(已截断)"
],
"warnings": [],
"content_checks": []
},
"forbidden_teacher_exams": {
"url": "http://localhost:3000/teacher/exams",
"route": "/teacher/exams",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 200,
"final_url": "http://localhost:3000/teacher/exams/all",
"redirect_url": "http://localhost:3000/teacher/exams/all",
"errors": [
"⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/exams/all权限隔离失效",
"%o\n\n%s Error: Failed query: select `exams`.`id`, `exams`.`title`, `exams`.`description`, `exams`.`structure`, `exams`.`creator_id`, `exams`.`subject_id`, `exams`.`grade_id`, `exams`.`start_time`, `exams`.`end_time`, `exams`.`exam_mode`, `exams`.`duration_minutes`, `exams`.`shuffle_questions`, `exams`.`allow_late_start`, `exams`.`late_start_grace_minutes`, `exams`.`anti_cheat_enabled`, `exams`.`status`, `exams`.`created_at`, `exams`.`updated_at`, `exams_subject`.`data` as `subject`, `exams_gradeE...(已截断)"
],
"warnings": [],
"content_checks": []
},
"forbidden_teacher_homework": {
"url": "http://localhost:3000/teacher/homework",
"route": "/teacher/homework",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 500,
"final_url": "http://localhost:3000/teacher/homework/assignments",
"redirect_url": "http://localhost:3000/teacher/homework/assignments",
"errors": [
"跨角色访问返回 HTTP 500应被重定向拦截",
"Failed to load resource: the server responded with a status of 500 (Internal Server Error)",
"%o\n\n%s Error: Teacher not found\n at getTeacherIdForMutations (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__458f1717._.js?47:9381:27)\n at AssignmentsPage (about://React/Server/E:%5CDesktop%5CCICD%5C.next%5Cdev%5Cserver%5Cchunks%5Cssr%5C%5Broot-of-the-server%5D__8e4de1e6._.js?48:253:23)\n at resolveErrorDev (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_9212ccad._.js:1882:1...(已截断)"
],
"warnings": [],
"content_checks": []
},
"forbidden_teacher_grades": {
"url": "http://localhost:3000/teacher/grades",
"route": "/teacher/grades",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 200,
"final_url": "http://localhost:3000/teacher/grades",
"redirect_url": null,
"errors": [
"⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/grades权限隔离失效"
],
"warnings": [],
"content_checks": []
},
"forbidden_teacher_questions": {
"url": "http://localhost:3000/teacher/questions",
"route": "/teacher/questions",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 200,
"final_url": "http://localhost:3000/teacher/questions",
"redirect_url": null,
"errors": [
"⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/questions权限隔离失效"
],
"warnings": [],
"content_checks": []
},
"forbidden_teacher_classes": {
"url": "http://localhost:3000/teacher/classes",
"route": "/teacher/classes",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 200,
"final_url": "http://localhost:3000/teacher/classes/my",
"redirect_url": "http://localhost:3000/teacher/classes/my",
"errors": [
"⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/classes/my权限隔离失效"
],
"warnings": [],
"content_checks": []
},
"forbidden_teacher_attendance": {
"url": "http://localhost:3000/teacher/attendance",
"route": "/teacher/attendance",
"category": "Cross-Role Access Control",
"status": "failed",
"http_status": 200,
"final_url": "http://localhost:3000/teacher/attendance",
"redirect_url": null,
"errors": [
"⚠️ 安全漏洞:家长成功访问了受限页面(最终 URL: http://localhost:3000/teacher/attendance权限隔离失效"
],
"warnings": [],
"content_checks": []
},
"forbidden_student_dashboard": {
"url": "http://localhost:3000/student/dashboard",
"route": "/student/dashboard",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Fdashboard&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Fdashboard&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
},
"forbidden_student_learning": {
"url": "http://localhost:3000/student/learning",
"route": "/student/learning",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Flearning&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Flearning&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
},
"forbidden_student_grades": {
"url": "http://localhost:3000/student/grades",
"route": "/student/grades",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Fgrades&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Fgrades&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
},
"forbidden_student_attendance": {
"url": "http://localhost:3000/student/attendance",
"route": "/student/attendance",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Fattendance&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fstudent%2Fattendance&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
},
"forbidden_management_grade_classes": {
"url": "http://localhost:3000/management/grade/classes",
"route": "/management/grade/classes",
"category": "Cross-Role Access Control",
"status": "passed",
"http_status": 200,
"final_url": "http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden",
"redirect_url": "http://localhost:3000/parent/dashboard?from=%2Fmanagement%2Fgrade%2Fclasses&reason=forbidden",
"errors": [],
"warnings": [],
"content_checks": [
"跨角色访问被权限系统拦截"
]
}
},
"functional_checks": [
{
"name": "返回仪表盘按钮",
"expected": "存在 Back to Dashboard 链接",
"actual": "Found",
"passed": true
},
{
"name": "子女姓名标题",
"expected": "显示子女姓名",
"actual": "小明",
"passed": true
},
{
"name": "邮箱掩码处理",
"expected": "邮箱被掩码为 j***@domain.com",
"actual": "Masked",
"passed": true
},
{
"name": "作业摘要卡片",
"expected": "显示 {childName}'s Homework",
"actual": "Found",
"passed": true
},
{
"name": "作业统计 - Pending",
"expected": "显示 Pending 计数",
"actual": "Found",
"passed": true
},
{
"name": "作业统计 - Submitted",
"expected": "显示 Submitted 计数",
"actual": "Found",
"passed": true
},
{
"name": "作业统计 - Graded",
"expected": "显示 Graded 计数",
"actual": "Found",
"passed": true
},
{
"name": "成绩趋势卡片",
"expected": "显示成绩信息",
"actual": "Found",
"passed": true
},
{
"name": "今日课表卡片",
"expected": "显示 {childName}'s Today Schedule",
"actual": "Found",
"passed": true
},
{
"name": "View all 链接",
"expected": "存在 View all 链接",
"actual": "Found",
"passed": true
},
{
"name": "仪表盘标题",
"expected": "Parent Dashboard",
"actual": "Parent Dashboard",
"passed": true
},
{
"name": "问候语显示",
"expected": "Good morning/afternoon/evening 或 Welcome",
"actual": "Found",
"passed": true
},
{
"name": "Grades 快捷入口",
"expected": "存在",
"actual": "Found",
"passed": true
},
{
"name": "Attendance 快捷入口",
"expected": "存在",
"actual": "Found",
"passed": true
},
{
"name": "Announcements 快捷入口",
"expected": "存在",
"actual": "Found",
"passed": true
},
{
"name": "子女卡片显示",
"expected": "≥1 个子女卡片",
"actual": "1 个",
"passed": true
},
{
"name": "子女卡片 - Pending 统计",
"expected": "显示 Pending 计数",
"actual": "Found",
"passed": true
},
{
"name": "子女卡片 - Overdue 统计",
"expected": "显示 Overdue 计数",
"actual": "Found",
"passed": true
},
{
"name": "子女数量提示",
"expected": "显示 'N child(ren) linked'",
"actual": "Found",
"passed": true
},
{
"name": "侧边栏 - Dashboard",
"expected": "显示 Dashboard 导航项",
"actual": "Found",
"passed": true
},
{
"name": "侧边栏 - Grades",
"expected": "显示 Grades 导航项",
"actual": "Found",
"passed": true
},
{
"name": "侧边栏 - Attendance",
"expected": "显示 Attendance 导航项",
"actual": "Found",
"passed": true
},
{
"name": "侧边栏 - Announcements",
"expected": "显示 Announcements 导航项",
"actual": "Found",
"passed": true
},
{
"name": "侧边栏 - Messages",
"expected": "显示 Messages 导航项",
"actual": "Found",
"passed": true
}
],
"security_checks": [
{
"name": "访问不存在/非关联子女应被拒绝",
"expected": "显示 Access denied 或 404",
"actual": "Access denied",
"passed": true
}
],
"console_errors": [],
"navigation_issues": []
}