Skip to content

AUBB 全量用户侧功能测试报告

1. 执行摘要

  • 测试日期:2026-06-05
  • 测试方式:Playwright MCP 真实浏览器操作 + API/数据库辅助验证
  • 测试范围:管理员、教师、学生三角色全页面全控件
  • 当前状态:进行中
  • 最新补充:2026-06-06 12:56 CST,学生通知中心 390px 行操作已用 Playwright MCP 复核;“标记已读 <通知标题>”可定位,触控高度 44px,点击后 POST /api/v1/me/notifications/1086/read 返回 200,目标按钮隐藏且页面无横向溢出。

2. 环境与账号

项目
前端http://127.0.0.1:3000 (Next.js 16)
后端http://127.0.0.1:18080 (Spring Boot 4)
数据库PostgreSQL (Docker)
对象存储MinIO (Docker)
判题服务go-judge (Docker)
管理员账号U-SA1
教师账号U-TA1
学生账号u-st1

3. 数据准备与残留

数据类型来源关键 ID可清理
学校根节点已有id=1 (SCH-REALRUN)
测试学院API 创建id=213 (E2E-FULLRUN 测试学院)
测试用户UI 创建e2e-fullrun-ml1-testuser
测试学期UI 创建E2E-FULLRUN-ML1-TERM
测试课程模板UI 创建E2E-FULLRUN-ML1-CS101
学生课程关联DB 更新user_id=9, offering_id=1

4. 功能覆盖矩阵

(见阶段 1 产出的测试矩阵文件)

5. 按钮/控件覆盖矩阵

5.1 管理员 - 平台配置

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/platform-config管理员平台名称输入框input修改为"E2E-FULLRUN-ML1 修改后平台"输入框值变化值已变化已真实操作通过
/admin/platform-config管理员保存配置按钮button点击保存保存成功保存成功刷新后值仍为修改后值已真实操作通过
/admin/platform-config管理员取消重置按钮button修改平台名称→点击取消重置表单恢复原值平台名称恢复为 "Realrun School"已真实操作通过
/admin/platform-config管理员平台简称输入框input显示 SCH-REALRUN只读/无副作用已验证
/admin/platform-config管理员Logo URL 输入框input显示空只读/无副作用已验证
/admin/platform-config管理员页脚文字输入框input显示 E2E 历史值只读/无副作用已验证
/admin/platform-config管理员清空按钮button点击清空页脚文字清空页脚文字输入框清空已真实操作通过
/admin/platform-config管理员默认首页路径输入框input显示 /admin只读/无副作用已验证
/admin/platform-config管理员主题键输入框input显示 aubb-light只读/无副作用已验证
/admin/platform-config管理员登录公告文本框textarea显示空只读/无副作用已验证

5.2 管理员 - 组织架构

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/org-units管理员新增根节点按钮button点击"新增根节点"表单切到根节点创建表单标题"新增根节点",节点类型固定 SCHOOLPlaywright MCP 截图/DOM:#org-unit-type=SCHOOL已真实操作通过
/admin/org-units管理员根节点提交创建按钮button填写 MCP-20260605-135309 测试学校后点击提交已存在学校根节点时给出明确业务错误POST /api/v1/admin/org-units 返回 409 ORG_ROOT_ALREADY_EXISTS,响应消息"学校根节点已存在"网络响应体已核对;未新增重复根节点已真实操作通过(负例)
/admin/org-units管理员Realrun School 行加号button点击树中 Realrun School 行加号表单切到学校下新增子节点表单标题"在 [Realrun School] 下新增子节点",节点类型 COLLEGE 可选Playwright MCP DOM:#org-unit-type=COLLEGEdisabled=false已真实操作通过
/admin/org-units管理员节点类型下拉select在学校下新增子节点时保持 COLLEGE类型符合层级规则选中 COLLEGE已真实操作通过
/admin/org-units管理员名称输入框input输入"MCP-20260605-135309 测试学院"输入成功输入成功已真实操作通过
/admin/org-units管理员编码输入框input输入"MCP-20260605-135309-COL"输入成功输入成功已真实操作通过
/admin/org-units管理员排序输入框input输入 902输入成功输入成功已真实操作通过
/admin/org-units管理员子节点提交创建按钮button点击提交创建创建成功并在树中显示POST /api/v1/admin/org-units 返回 201,页面包含新学院名称和编码列表重新请求 /api/v1/admin/org-units/tree 返回 200,刷新前 DOM 已包含新节点已真实操作通过
/admin/org-units管理员创建成功后的根节点表单select子节点创建成功后观察根节点表单不再出现常驻根节点表单状态残留本轮已改为 Dialog 创建模式,子节点创建成功后关闭弹窗并清空父节点上下文单元测试覆盖初始页不常驻提交按钮、根节点 Dialog 固定 SCHOOL、子节点 Dialog 默认 COLLEGE已修复BUG-20260605-009

BUG-20260605-001:组织架构 UI 创建 COLLEGE 类型节点失败

  • 复核时间:2026-06-05 13:55
  • 角色:管理员
  • 页面:/admin/org-units
  • 相关控件:Realrun School 行加号、提交创建按钮
  • 复核结论:非缺陷,原复现路径不符合当前层级规则;COLLEGE 必须通过学校节点行加号创建,不能作为根节点创建。
  • 真实操作:点击 Realrun School 行加号→填写 MCP-20260605-135309 测试学院 / MCP-20260605-135309-COL→点击提交创建。
  • 实际结果:POST /api/v1/admin/org-units 返回 201,树中出现新学院名称和编码。
  • 持久化校验:页面自动重新请求 /api/v1/admin/org-units/tree 返回 200。
  • 当前状态:已关闭,按设计通过。

BUG-20260605-009:组织架构子节点创建成功后根节点表单类型残留 COLLEGE

  • 发现时间:2026-06-05 13:56
  • 角色:管理员
  • 页面:/admin/org-units
  • 相关控件:子节点提交创建按钮、节点类型下拉
  • 复现步骤:点击 Realrun School 行加号→创建学院成功→观察右侧表单。
  • 实际结果:本轮已取消右侧常驻创建表单,新增根节点 / 子节点均通过 Dialog 完成,创建成功后弹窗关闭并清空父节点上下文。
  • 预期结果:不再出现根节点表单与子节点类型残留的自相矛盾状态。
  • 影响范围:原状态残留风险已被 Dialog 模式消解。
  • 严重级别:P3
  • 证据:单元测试 src/tests/unit/admin/org-units-page.test.tsx 覆盖初始页不常驻 提交创建、根节点 Dialog 固定 SCHOOL、子节点 Dialog 默认 COLLEGE
  • 当前状态:已修复,真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed,待 MCP 恢复后复核。

5.3 管理员 - 用户管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/users管理员新增用户按钮button点击打开表单弹出创建表单弹出表单已真实操作通过
/admin/users管理员用户名输入框input输入 e2e-fullrun-ml1-testuser输入成功输入成功已真实操作通过
/admin/users管理员显示名输入框input输入 E2E-ML1 测试用户输入成功输入成功已真实操作通过
/admin/users管理员邮箱输入框input输入 e2e-ml1@test.local输入成功输入成功已真实操作通过
/admin/users管理员初始密码输入框input输入 Test123456!输入成功输入成功已真实操作通过
/admin/users管理员创建按钮button点击创建创建成功创建成功,用户出现在列表搜索可找到已真实操作通过
/admin/users管理员关键词搜索输入框input输入 U-TA1输入成功输入成功已真实操作通过
/admin/users管理员搜索按钮button点击搜索筛选结果搜索到 U-TA1已真实操作通过
/admin/users管理员用户行链接link点击 U-TA1 行跳转详情页跳转到 /admin/users/4详情页显示完整信息已真实操作通过
/admin/users管理员批量导入按钮button/file upload点击批量导入,选择重复用户名 CSV打开文件选择器,上传后展示导入总数、成功数、失败数和行级错误上传 U-SA1 重复用户名 CSV 后页面显示“导入 1 行,成功 0 行,失败 1 行。”并展示第 2 行错误POST /api/v1/admin/users/import 返回 200,响应 total=1/success=0/failed=1辅助回归通过,待 MCP 复核
/admin/users管理员重置按钮button输入关键词→点击重置搜索条件清空关键词输入框清空,列表恢复完整已真实操作通过

5.4 管理员 - 学期管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/academic-terms管理员学期名称输入框input输入 E2E-FULLRUN-ML1 测试学期输入成功输入成功已真实操作通过
/admin/academic-terms管理员学期编码输入框input输入 E2E-FULLRUN-ML1-TERM输入成功输入成功已真实操作通过
/admin/academic-terms管理员学年输入框input输入 2026-2027输入成功输入成功已真实操作通过
/admin/academic-terms管理员季节下拉select选择 SPRING选中成功选中成功已真实操作通过
/admin/academic-terms管理员开始日期input输入 2027-02-01输入成功输入成功已真实操作通过
/admin/academic-terms管理员结束日期input输入 2027-07-31输入成功输入成功已真实操作通过
/admin/academic-terms管理员创建按钮button点击创建创建成功创建成功,列表显示新学期列表可见已真实操作通过
/admin/academic-terms管理员新增学期空提交button点击新增学期→不填写直接点击创建显示字段级错误且不发送创建请求显示 6 个字段错误,6 个字段均为 aria-invalid=true 且关联错误说明未产生新增数据已真实操作通过

5.5 管理员 - 课程模板

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/course-catalogs管理员课程名称输入框input输入 E2E-FULLRUN-ML1 测试课程输入成功输入成功已真实操作通过
/admin/course-catalogs管理员课程编码输入框input输入 E2E-FULLRUN-ML1-CS101输入成功输入成功已真实操作通过
/admin/course-catalogs管理员学院下拉select选择计算机学院选中成功选中成功已真实操作通过
/admin/course-catalogs管理员学分输入框input输入 3输入成功输入成功已真实操作通过
/admin/course-catalogs管理员学时输入框input输入 48输入成功输入成功已真实操作通过
/admin/course-catalogs管理员课程类型下拉select选择必修选中成功选中成功已真实操作通过
/admin/course-catalogs管理员描述文本框textarea输入测试描述输入成功输入成功已真实操作通过
/admin/course-catalogs管理员创建模板按钮button点击创建创建成功创建成功,列表显示列表可见已真实操作通过
/admin/course-catalogs管理员新增模板空提交button点击新增模板→不填写直接点击创建显示字段级错误且不发送创建请求显示 4 个字段错误,4 个字段均为 aria-invalid=true 且关联错误说明;所属学院下拉只包含学院节点未产生新增数据已真实操作通过

5.6 管理员 - 开课管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/course-offerings管理员collegeUnitId 输入框input输入 2输入成功输入成功已真实操作通过
/admin/course-offerings管理员课程模板下拉select选择 E2E-FULLRUN-ML1 测试课程选中成功选中成功已真实操作通过
/admin/course-offerings管理员学期下拉select选择 E2E-FULLRUN-ML1 测试学期选中成功选中成功已真实操作通过
/admin/course-offerings管理员开课名称输入框input输入 E2E-FULLRUN-ML1 测试开课输入成功输入成功已真实操作通过
/admin/course-offerings管理员开课编码输入框input输入 E2E-FULLRUN-ML1-OFF输入成功输入成功已真实操作通过
/admin/course-offerings管理员开始时间input输入 2027-02-01T08:00输入成功输入成功已真实操作通过
/admin/course-offerings管理员结束时间input输入 2027-07-31T23:59输入成功输入成功已真实操作通过
/admin/course-offerings管理员完成创建按钮button点击完成创建创建成功课程模板自动锁定主开课学院,缺主讲教师时显示字段错误;补选教师后创建成功POST /api/v1/admin/course-offerings 返回 201,Toast 显示“开课实例已创建”已真实操作通过BUG-20260605-002

BUG-20260605-002:开课管理 UI 创建失败

  • 发现时间:2026-06-05 17:00
  • 角色:管理员
  • 页面:/admin/course-offerings
  • 相关控件:完成创建按钮
  • 输入数据:模板=E2E-FULLRUN-ML1-CS101,学期=E2E-FULLRUN-ML1-TERM,名称=E2E-FULLRUN-ML1 测试开课
  • 复现步骤:点击新增→填写表单→点击完成创建
  • 实际结果:已修复。课程模板选择后主开课学院自动同步为模板所属学院并禁用;缺少主讲教师时显示“请至少指定一名教师”,主讲教师控件设置 aria-invalid=true 且关联 offering-instructors-error;补选主讲教师后创建请求成功。
  • 预期结果:创建成功并在列表显示
  • 影响范围:管理员无法通过 UI 创建开课
  • 严重级别:P1
  • 修复证据:2026-06-05 21:45 CST,Playwright 真实登录管理员账号打开 /admin/course-offerings,选择课程模板“数据结构 (COURSE-A)”后主开课学院值为 2 且禁用;缺主讲教师时错误状态可见;补选教师后 POST /api/v1/admin/course-offerings 返回 201。
  • 当前状态:已修复

5.7 管理员 - 用户详情

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/users/376管理员返回列表链接link点击跳转用户列表跳转到 /admin/users已真实操作通过
/admin/users/621管理员强制下线按钮button点击强制下线→确认注销该用户所有活跃会话并给出明确确认显示“确认强制下线?”确认弹窗,确认后请求成功POST /api/v1/admin/users/621/sessions/revoke 返回 204已真实操作通过
/admin/users/376管理员禁用账号按钮button点击禁用→确认账号状态变禁用弹出确认弹窗→确认后状态变"禁用"刷新后仍为禁用已真实操作通过
/admin/users/376管理员启用账号按钮button点击启用→确认账号状态恢复激活弹出确认弹窗→确认后状态变"激活"刷新后仍为激活已真实操作通过
/admin/users/376管理员角色下拉框select选择 COLLEGE_ADMIN选中成功选中成功已真实操作通过
/admin/users/376管理员scopeOrgUnitId 输入框input输入 2输入成功输入成功已真实操作通过
/admin/users/376管理员保存身份按钮button点击保存身份更新成功Toast"用户身份已更新",页面显示 COLLEGE_ADMIN刷新后仍显示已真实操作通过
/admin/users/376管理员orgUnitId 输入框input输入 2输入成功输入成功已真实操作通过
/admin/users/376管理员替换组织关系按钮button点击替换组织关系更新Toast"组织成员关系已更新",显示计算机学院刷新后仍显示已真实操作通过
/admin/users/621管理员学籍资料编辑与保存form/button修改真实姓名、学号/工号、身份类型、联系电话→点击保存学籍资料字段可编辑,保存后资料持久化表单显示可编辑字段,保存后详情重新加载PUT /api/v1/admin/users/621/profile 返回 200,响应含 academicId=MCP-REG-621realName=MCP回归姓名-621identityType=TEACHERphone=13900000621已真实操作通过

5.8 管理员 - 审计日志

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/audit-logs管理员页面加载打开页面显示日志列表292 页数据,含真实操作记录已真实操作通过
/admin/audit-logs管理员操作者 ID 输入框input可见只读/无副作用已验证
/admin/audit-logs管理员操作类型输入框input输入 USER_STATUS_CHANGED筛选结果返回 3 页 USER_STATUS_CHANGED 记录已真实操作通过
/admin/audit-logs管理员操作类型下拉框select选择“登录成功”后点击查询返回登录成功记录触发 GET /api/v1/admin/audit-logs?action=LOGIN_SUCCESS&page=1&pageSize=20,表格显示多条“登录成功”记录网络请求 200,响应 total=2849已真实操作通过BUG-20260605-003
/admin/audit-logs管理员对象类型输入框input可见只读/无副作用已验证
/admin/audit-logs管理员查询按钮button点击查询返回筛选结果返回结果已真实操作通过
/admin/audit-logs管理员详情按钮button点击“查看日志详情 登录成功 8007807c”显示中文元数据详情底部显示“日志元数据”和说明“当前行的原始审计上下文,用于排查请求链路和业务对象。”前 5 行详情按钮均具备“查看日志详情 <操作> <短 ID>”可访问名称已真实操作通过
/admin/audit-logs管理员Request ID 复制按钮button点击“复制请求 ID 8007807c”复制到剪贴板并给出明确反馈页面显示“Request ID 已复制”前 5 行复制按钮均具备“复制请求 ID <短 ID>”可访问名称已真实操作通过
/admin/audit-logs管理员复制 JSON 按钮button点击复制复制 JSON 到剪贴板并给出明确反馈页面显示“JSON 已复制”navigator.clipboard.writeText 接收当前行元数据 JSON已真实操作通过
/admin/audit-logs管理员分页控件pagination显示"第 1 页 / 共 292 页"只读/无副作用已验证

5.9 管理员 - 权限解释

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/admin/auth-explain管理员页面加载打开页面显示权限查询界面页面加载成功,显示权限诊断、创建授权组、添加成员三个区域已真实操作通过
/admin/auth-explain管理员用户 ID 输入框input输入 4输入成功输入成功已真实操作通过
/admin/auth-explain管理员权限编码输入框input输入 OFFERING_READ / USER_READ / bad输入成功输入成功,非法编码触发受控错误态已真实操作通过
/admin/auth-explain管理员作用域类型下拉select选择 OFFERING选中成功选中成功,默认 PLATFORM,含 6 个选项已真实操作通过
/admin/auth-explain管理员立即分析按钮(允许)buttonuserId=4,permission=OFFERING_READ,scopeType=OFFERING,scopeRefId=1 后点击分析返回允许结果页面显示"允许 (ALLOWED)",reasonCode 为 ALLOW_BY_SCOPE_ROLEGET /api/v1/admin/auth/explain?...permission=OFFERING_READ... 返回 200已真实操作通过BUG-20260605-004
/admin/auth-explain管理员立即分析按钮(拒绝)buttonpermission=USER_READ 后点击分析返回拒绝结果页面显示"拒绝 (DENIED)",reasonCode 为 DENY_NO_ROLE_BINDINGGET /api/v1/admin/auth/explain?...permission=USER_READ... 返回 200已真实操作通过
/admin/auth-explain管理员立即分析按钮(非法编码)buttonpermission=bad 后点击分析显示可读错误态且页面不崩溃页面显示"数据加载失败"和 Failed to convert 'permission' with value: 'bad'GET /api/v1/admin/auth/explain?...permission=bad... 返回 400已真实操作通过
/admin/auth-explain管理员templateCode 输入框input输入 audit-readonly输入成功输入成功已真实操作通过
/admin/auth-explain管理员displayName 输入框input输入"MCP 审计只读组 0606-0350"输入成功输入成功已真实操作通过
/admin/auth-explain管理员创建授权组按钮(有效模板)buttontemplateCode=audit-readonly,scopeType=SCHOOL,scopeRefId=1 后点击创建授权组创建成功返回新授权组,页面自动填充 groupId=1POST /api/v1/admin/auth/groups 返回 201,响应含 templateCode=audit-readonlyscopeType=SCHOOLstatus=ACTIVE已真实操作通过BUG-20260605-005
/admin/auth-explain管理员创建授权组按钮(无效模板)buttontemplateCode=missing-template-mcp-0606 后点击创建显示模板不存在错误返回 AUTHZ_TEMPLATE_NOT_FOUND / "授权组模板不存在"POST /api/v1/admin/auth/groups 返回 404,无新增授权组预期错误已验证
/admin/auth-explain管理员groupId 输入框input创建有效授权组后查看自动填入新组 ID自动填入 1来自创建授权组 201 响应已真实操作通过
/admin/auth-explain管理员userId 输入框input输入 4输入成功输入成功已真实操作通过
/admin/auth-explain管理员添加成员按钮buttongroupId=1,userId=4 后点击添加成员成员添加成功返回成员绑定记录POST /api/v1/admin/auth/groups/1/members 返回 201,响应含 groupId=1userId=4sourceType=MANUAL已真实操作通过

5.10 教师 - 公告管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/announcements教师发布公告h2(可点击)点击打开表单弹出标题/正文表单弹出表单已真实操作通过
/teacher/courses/1/announcements教师公告标题输入框input输入 E2E-FULLRUN-ML2 测试公告输入成功输入成功已真实操作通过
/teacher/courses/1/announcements教师公告正文文本框textarea输入测试内容输入成功输入成功已真实操作通过
/teacher/courses/1/announcements教师发布按钮button点击发布公告创建成功列表显示新公告刷新后仍可见已真实操作通过
/teacher/courses/1/announcements教师发布公告空提交button点击发布公告→标题和正文留空→点击发布显示字段级错误且不发送创建请求显示“请输入公告标题 / 请输入公告正文”,两个字段 aria-invalid=true,未发送 POST /announcements无新增公告;临时编辑种子清理后残留数 0已真实操作通过
/teacher/courses/1/announcements教师编辑公告空提交button点击编辑公告→清空标题和正文→点击保存显示字段级错误且不发送更新请求显示“请输入公告标题 / 请输入公告正文”,两个字段 aria-invalid=true,未发送 PUT /announcements,无 Dialog 描述警告临时公告种子通过 API 删除,E2E-ANN-NEG-* 残留数 0已真实操作通过
/teacher/courses/{offeringId}/announcements教师移动端长标题公告viewport/button390x844 视口打开公告页,检查长标题公告与行操作页面不出现整页横向溢出,发布入口与公告编辑操作可见documentWidth/bodyWidth <= 390,长标题公告可见,“编辑公告 <标题>”按钮可见通过 API 临时创建公告并在用例结束清理辅助回归通过,待 MCP 复核

5.11 教师 - 讨论管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/discussions教师创建讨论按钮button/h2点击打开表单弹出标题/正文表单弹出表单已真实操作通过
/teacher/courses/1/discussions教师标题输入框input输入 E2E-FULLRUN-ML2 测试讨论输入成功输入成功已真实操作通过
/teacher/courses/1/discussions教师正文文本框textarea输入测试内容输入成功输入成功已真实操作通过
/teacher/courses/1/discussions教师提交按钮button点击提交讨论创建成功列表显示新讨论刷新后仍可见已真实操作通过
/teacher/courses/1/discussions教师创建讨论空提交button点击创建讨论→标题和正文留空→点击创建显示字段级错误且不发送创建请求显示“请输入讨论标题 / 请输入讨论正文”,两个字段 aria-invalid=true,未发送 POST /discussions无新增讨论已真实操作通过
/teacher/courses/1/discussions教师锁定 / 解锁讨论按钮button读取讨论列表行操作名称每个按钮都能区分对应讨论20 个锁定 / 解锁按钮均可通过“锁定讨论 <标题> / 解锁讨论 <标题>”定位已真实操作通过P2-L15
/teacher/courses/{offeringId}/discussions教师移动端长标题讨论viewport/link/button390x844 视口打开讨论页,检查长标题讨论与锁定操作页面不出现整页横向溢出,创建入口与讨论锁定操作可见documentWidth/bodyWidth <= 390,长标题讨论链接可见,“锁定讨论 <标题>”按钮可见通过 API 临时创建讨论;讨论无删除接口,保留 E2E 前缀残留记录辅助回归通过,待 MCP 复核

5.12 教师 - 资源管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/resources教师页面加载打开页面显示资源列表4 个资源文件,含文件名/大小/时间已真实操作通过
/teacher/courses/1/resources教师下载按钮button点击下载文件下载成功文件 e2e-fullrun-ml2-resource.txt 下载(41B)文件内容正确已真实操作通过
/teacher/courses/1/resources教师重命名按钮button点击→修改标题→保存标题更新弹出"编辑资源标题"对话框→修改为"E2E-FULLRUN 重命名测试资源"→保存成功刷新后标题仍为新值已真实操作通过
/teacher/courses/1/resources教师编辑资源标题空提交button/input点击编辑→清空资源标题→保存显示字段级错误且不发送更新请求显示“请输入资源标题”,资源标题字段 aria-invalid=true,未发送 PUT /teacher/course-resources/*无标题变更已真实操作通过
/teacher/courses/1/resources教师编辑 / 删除资源行操作button读取资源列表行操作名称每个按钮都能区分对应资源4 个编辑按钮均可通过“编辑资源 <标题>”定位;抽查资源的“删除资源 <标题>”按钮可定位已真实操作通过
/teacher/courses/1/resources教师上传 / 编辑资源弹窗描述dialog分别打开上传和编辑弹窗弹窗有清晰说明且无可访问性警告上传弹窗显示“上传后学生可在课程资源区下载该文件。标题为空时将使用文件名。”;编辑弹窗显示“资源标题会显示在教师和学生端资源列表中。”;无 Radix Dialog 描述警告已真实操作通过
/teacher/courses/1/resources教师删除按钮button点击删除→确认资源删除弹出确认弹窗→确认后 Toast"资源已删除"刷新后资源不在列表已真实操作通过
/teacher/courses/1/resources教师资源标题输入框input输入"E2E-FULLRUN 上传测试资源"输入成功输入成功已真实操作通过
/teacher/courses/1/resources教师选择文件区域upload选择 e2e-upload-test.txt文件选择成功显示文件名和大小已真实操作通过
/teacher/courses/1/resources教师开始上传按钮button点击上传上传成功Toast"资源已上传",新资源出现在列表刷新后仍可见已真实操作通过
/teacher/courses/{offeringId}/resources教师移动端资源表格viewport/table/button390x844 视口打开资源页,检查长标题资源与行操作页面不出现整页横向溢出,上传入口与资源行编辑操作可见documentWidth/bodyWidth <= 390,长标题资源可见,“编辑资源 <标题>”按钮可见通过 API 临时上传长标题资源并在用例结束清理辅助回归通过,待 MCP 复核

5.12A 教师 - 成员管理补充

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/members教师停用 / 恢复成员按钮button读取成员列表行操作名称每个按钮都能区分对应成员20 个状态按钮均可通过“停用成员 <姓名> / 恢复成员 <姓名>”定位已真实操作通过P2-L14
/teacher/courses/1/members教师转班成员按钮button读取成员列表行操作名称每个按钮都能区分对应成员20 个转班按钮均可通过“转班成员 <姓名>”定位已真实操作通过P2-L14
/teacher/courses/1/members教师添加成员空 userIdbutton/input点击添加成员→不填写 userId→点击添加显示字段级错误且不发送添加请求显示“请输入有效的 userId”,用户 ID 字段 aria-invalid=true未发送 POST /teacher/course-offerings/1/members/batch已真实操作通过
/teacher/courses/1/members教师添加成员缺教学班button/select填写 userId,角色保持学生,教学班留空→点击添加显示字段级错误且不发送添加请求显示“当前角色必须选择教学班”,教学班字段 aria-invalid=true未发送 POST /teacher/course-offerings/1/members/batch已真实操作通过
/teacher/courses/1/members教师添加成员成功反馈button/dialog填写用户 ID 621,角色选择整课助教→点击添加添加成功后保留明确结果反馈弹窗保持打开并显示“添加成功 1 人,失败 0 人。”POST /api/v1/teacher/course-offerings/1/members/batch 返回 200已真实操作通过
/teacher/courses/1/members教师添加 / 导入 / 转班弹窗描述dialog分别打开三个弹窗弹窗有清晰说明且无可访问性警告三个弹窗均显示说明文本,未出现 Radix Dialog 描述警告已真实操作通过
/teacher/courses/{offeringId}/members教师移动端成员筛选与弹窗viewport/input/select/dialog/button390x844 视口打开成员管理页,搜索长名称成员并检查行操作、停用确认、添加成员、批量导入页面不出现整页横向溢出,筛选控件有可访问名称,确认与 Dialog 不超出视口documentWidth/bodyWidth <= 390,搜索 / 教学班 / 角色 / 状态均可通过 label 定位,“停用成员 <姓名> / 转班成员 <姓名>”可见,停用确认、添加成员与导入 Dialog 在视口内通过 API 临时创建长名称学生并加入课程;残留 E2E 前缀成员记录辅助回归通过,待 MCP 复核BUG-20260606-017

5.13 教师 - 题库

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/question-bank教师页面加载打开页面显示题库列表5 个题目(SHORT_ANSWER, MULTIPLE_CHOICE, SINGLE_CHOICE, PROGRAMMING)已真实操作通过
/teacher/courses/1/question-bank教师类型筛选下拉框select选择 PROGRAMMING筛选结果只显示 1 个 PROGRAMMING 题目已真实操作通过
/teacher/courses/1/question-bank教师查询按钮button点击查询返回筛选结果返回结果已真实操作通过
/teacher/courses/1/question-bank教师分类管理入口button检查是否存在假入口不保留无契约支撑的空功能按钮后端稳定 API 仅提供分类/标签字典读取,分类通过题目创建/编辑时的 categoryName 自动维护;当前页面不再保留“分类管理”假按钮API 契约核对:stable-api.md 仅列出题目 CRUD 与分类列表读取非缺陷,入口已清理BUG-20260605-008
/teacher/courses/1/question-bank教师新增题目按钮button填写标题/题干/分值/分类/标签→点击创建题目创建成功并刷新题库列表、分类、标签创建 MCP-QUESTION-0606-0402 后页面无需手动查询即显示新题,标签筛选新增 autorefreshPOST /api/v1/teacher/course-offerings/1/question-bank/questions 返回 201,随后自动触发 questions/categories/tags GET 200;刷新后 MCP-QUESTION-0606-0356 仍可见已真实操作通过BUG-20260606-003
/teacher/courses/1/question-bank教师编辑题目按钮button点击编辑弹出编辑对话框点击“编辑题目 E2E-FULLRUN 新增测试题目”后打开“编辑题目”Dialog,并带入原题目标题和分值Playwright MCP DOM 读取 Dialog 标题、描述、#question-title#question-score已真实操作通过BUG-20260605-006
/teacher/courses/1/question-bank教师编辑 / 归档行操作名称button读取题目列表行操作名称每个按钮都能区分对应题目前 3 行按钮均具备“编辑题目 <标题> / 归档题目 <标题>”的 aria-labeltitlePlaywright MCP DOM 读取 main table buttonaria-label / title;单元测试覆盖“二叉树遍历”行已真实操作通过
/teacher/courses/{offeringId}/question-bank教师移动端题库筛选与弹窗viewport/input/select/dialog/button390x844 视口打开题库页,搜索长标题题目并检查筛选、行操作、归档确认、新增题目 Dialog筛选控件可通过 label 定位,控件触控高度不低于 44px,长题目不造成整页横向溢出,确认与 Dialog 不超出视口修复前搜索框无法通过“搜索题目”可访问名称定位;修复后 documentWidth/bodyWidth <= 390,类型 / 分类 / 标签 / 包含归档均可由 label 定位,长标题题目的编辑 / 归档按钮可见且触控高度达标API 临时创建长标题题目,POST /api/v1/teacher/course-offerings/{offeringId}/question-bank/questions 返回 201;用例结束调用归档接口清理当前测试题辅助回归通过,待 MCP 复核BUG-20260606-018
/teacher/courses/1/question-bank教师归档按钮button点击归档题目归档Toast"题目已归档"已真实操作通过

5.14 教师 - 判题环境

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/judge-environments教师页面加载打开页面显示判题环境列表页面加载成功只读/无副作用已验证
/teacher/courses/1/judge-environments教师编程语言筛选 / 查询select/button选择 Go 1.22 后点击查询只查询 Go 环境触发 GET /teacher/course-offerings/1/judge-environment-profiles?programmingLanguage=GO122&includeArchived=false,列表过滤到 Go 1.22网络请求 200已真实操作通过
/teacher/courses/1/judge-environments教师新增配置空提交button/form打开新增配置后直接点击创建显示字段级错误且不发送创建请求显示“请输入配置编码 / 请输入配置名称”,两个字段 aria-invalid=true空提交期间未新增 POST 创建请求已真实操作通过
/teacher/courses/1/judge-environments教师新增配置正常路径button/form填写 Go 1.22 配置后点击创建创建成功并出现在列表Toast“判题环境已保存”,新配置显示在 Go 1.22 列表POST /teacher/course-offerings/1/judge-environment-profiles 返回 201已真实操作通过
/teacher/courses/1/judge-environments教师编辑配置按钮button/dialog点击新配置行的编辑按钮打开编辑弹窗并带入已有值“编辑配置”弹窗带入配置编码、名称、语言 Go 1.22、语言版本和运行命令;保存后 Toast“判题环境已更新”PUT /teacher/judge-environment-profiles/{id} 返回 200已真实操作通过
/teacher/courses/1/judge-environments教师归档配置按钮button/dialog点击归档并确认归档成功,默认列表隐藏,包含归档后显示已归档状态确认文案包含配置名;Toast“判题环境已归档”;默认筛选下记录隐藏,勾选包含归档后状态为“已归档”,行内不再显示归档按钮POST /teacher/judge-environment-profiles/{id}/archive 返回 200;包含归档查询返回 200已真实操作通过
/teacher/courses/{offeringId}/judge-environments教师移动端判题环境筛选与弹窗viewport/select/dialog/button390x844 视口打开判题环境页,筛选 Python 3 长名称配置并检查行操作、归档确认、新增配置 Dialog主操作、筛选和行操作触控高度不低于 44px,长配置名不造成整页横向溢出,确认与 Dialog 不超出视口修复前“新增配置”按钮高度仅 36px;修复后 documentWidth/bodyWidth <= 390,语言筛选 / 包含归档 / 查询可用,长配置名编辑 / 归档按钮可见且触控高度达标API 临时创建长名称判题环境,POST /api/v1/teacher/course-offerings/{offeringId}/judge-environment-profiles 返回 201;用例结束调用归档接口清理当前测试配置辅助回归通过,待 MCP 复核BUG-20260606-019

5.15 教师 - 通知公告

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/notifications教师页面加载打开页面显示通知列表28 条通知,分 2 页已真实操作通过
/teacher/notifications教师标记已读按钮button点击标记已读通知状态更新未读数从 28 变为 27已真实操作通过
/teacher/notifications教师全部已读按钮button点击全部已读所有通知标记已读未读数徽章消失已真实操作通过
/teacher/notifications教师分页控件pagination显示"共 28 条,第 1/2 页"只读/无副作用已验证

5.16 学生 - 课程学习

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/student/courses/1学生页面加载打开页面显示公告、资源、讨论3 个公告、4 个资源、11 个讨论已真实操作通过
/student/courses/1学生资源下载按钮button点击下载文件下载成功文件 e2e-fullrun-ml2-resource.txt 下载(41B)文件内容正确已真实操作通过
/student/courses/1学生讨论标题输入框input输入"E2E-FULLRUN 学生测试讨论"输入成功输入成功已真实操作通过
/student/courses/1学生讨论内容输入框textarea输入测试内容输入成功输入成功已真实操作通过
/student/courses/1学生创建讨论按钮button点击创建讨论创建成功新讨论出现在列表,链接到 /student/courses/1/discussions/18刷新后仍可见已真实操作通过
/student/courses/学生跨班级课程内容page/API学生打开未加入的教学班课程页公告、资源、讨论均显示清晰无权访问状态,不暴露可提交讨论入口页面显示“无权访问课程公告/课程资源/课程讨论,请确认已加入此课程”,讨论标题输入框与“创建讨论”按钮隐藏GET /api/v1/me/course-classes/{classId}/announcementsresourcesdiscussions 均返回 403辅助回归通过,待 MCP 复核BUG-20260606-016
/student/courses/学生移动端课程讨论创建viewport/form/button390x844 视口打开课程学习页,填写讨论标题和内容并创建移动端无横向溢出,公告/资源/讨论区域可见,创建讨论可完成并刷新documentWidth/bodyWidth <= 390,标题/内容输入框与按钮可用,新讨论出现在列表POST /api/v1/me/course-classes/{classId}/discussions 返回 201辅助回归通过,待 MCP 复核

5.17 学生 - 讨论详情

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/student/courses/1/discussions/18学生页面加载打开页面显示讨论内容和回复表单显示讨论标题、时间、"可回复"状态已真实操作通过
/student/courses/1/discussions/18学生回复内容输入框textarea输入回复内容输入成功输入成功已真实操作通过
/student/courses/1/discussions/18学生发布回复按钮button点击发布回复发布成功Toast"回复已发布",新回复出现在列表刷新后仍可见已真实操作通过
/student/courses/1/discussions/18学生返回课程链接link可见,指向 /student/courses/1只读/无副作用已验证

5.18 学生 - 我的成绩

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/student/grades学生页面加载打开页面显示成绩页面显示课程选择下拉框和成绩表已真实操作通过
/student/grades学生课程选择下拉框select选择"数据结构 2025 秋"选中成功选中成功,表显示"暂无成绩数据"已真实操作通过
/student/grades学生导出成绩按钮button点击导出CSV 文件下载文件 gradebook-me-offering-1.csv 下载文件存在已真实操作通过
/student/grades学生移动端成绩筛选与导出viewport/select/button/table390x844 视口打开成绩页,选择课程并点击导出成绩课程筛选可通过 label 定位,导出按钮启用并发起下载请求,成绩表不造成整页横向溢出修复前课程下拉无法通过“选择课程”可访问名称定位;修复后课程筛选和导出按钮高度不低于 44px,GET /me/course-offerings/{offeringId}/gradebook/export 均返回 200,documentWidth/bodyWidth <= 390真实后端动态 fixture 使用当前学生已加入开课,未新增业务数据辅助回归通过,待 MCP 复核BUG-20260606-020

5.19 学生 - 通知中心

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/student/notifications学生页面加载打开页面显示通知列表8 条通知已真实操作通过
/student/notifications学生标记已读按钮button点击标记已读通知状态更新未读数从 8 变为 7已真实操作通过
/student/notifications学生全部已读按钮button点击全部已读所有通知标记已读未读数徽章消失(从 8 变为 0)已真实操作通过
/student/notifications学生全部已读后列表刷新button/list发布临时实验生成 1 条未读通知,点击“全部已读”未读徽章消失,通知列表同步转为已读,不再显示“标记已读”修复前 POST /read-all 200 后列表仍保留“标记已读”;修复后未读徽章消失,列表刷新后隐藏行按钮后端只读校验 unreadCount=0,目标通知 read=truefirstUnreadId=null已真实操作通过BUG-20260606-014
/student/notifications学生移动端未读通知行操作viewport/button/list390x844 视口打开通知中心,点击对应行“标记已读”行操作名称包含通知标题,移动端触控高度不低于 44px,点击后通知标为已读且页面不横向溢出修复前按钮仅暴露重复的“标记已读”;修复后“标记已读 <通知标题>”可定位,Playwright MCP 点击后 POST /me/notifications/1086/read 返回 200,按钮隐藏,通知类型显示“实验发布”而非后端枚举真实 E2E 先覆盖动态长标题通知;MCP 复核使用当前真实学生未读通知已真实操作通过BUG-20260606-022

6. Playwright MCP 操作证据

(按操作顺序记录)

5.20 教师 - 题库管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/question-bank教师页面加载打开页面显示题库列表5 个题目(SHORT_ANSWER, MULTIPLE_CHOICE, SINGLE_CHOICE, PROGRAMMING)已真实操作通过
/teacher/courses/1/question-bank教师类型筛选下拉框select选择 PROGRAMMING筛选结果只显示 1 个 PROGRAMMING 题目已真实操作通过
/teacher/courses/1/question-bank教师查询按钮button点击查询返回筛选结果返回结果已真实操作通过
/teacher/courses/1/question-bank教师编辑题目按钮button点击编辑弹出编辑对话框点击“编辑题目 E2E-FULLRUN 新增测试题目”后打开“编辑题目”Dialog,并带入原题目标题和分值Playwright MCP DOM 读取 Dialog 标题、描述、#question-title#question-score已真实操作通过BUG-20260605-006
/teacher/courses/1/question-bank教师归档按钮button点击归档题目归档Toast"题目已归档"已真实操作通过

5.21 教师 - 作业管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/assignments教师选择课程下拉框select选择"数据结构 2025 秋"选中成功选中成功,查询按钮启用已真实操作通过
/teacher/assignments教师查询按钮button点击查询返回作业列表返回 20 页作业数据GET /api/v1/teacher/course-offerings/1/assignments?page=1&pageSize=20 返回 200已真实操作通过
/teacher/assignments教师创建作业按钮link/button点击创建作业打开创建表单并保留当前课程跳转 /teacher/assignments/create?offeringId=1已真实操作通过
/teacher/assignments/create?offeringId=1教师题库题目加入试卷select/button选择 MCP-QUESTION-0606-0402 / 简答题 / 13 分 后点击加入试卷试卷显示 1 个分区 / 总分 13页面显示 1 个分区 / 总分 13,包含题目 MCP-QUESTION-0606-0402已真实操作通过
/teacher/assignments/create?offeringId=1教师创建作业按钮button填写标题、说明、教学班 A1、开放/截止时间、提交次数后提交创建成功并返回列表修复后 POST /api/v1/teacher/course-offerings/1/assignments 返回 201,列表出现 MCP 作业回归 0606-0413 id=402 草稿请求体中题库引用仅包含 bankQuestionId=167score=13;201 响应 paper.totalScore=13已真实操作通过BUG-20260606-004
/teacher/assignments教师总分列table cell查看新建作业列表行列表接口未返回试卷详情时不显示误导性 0 分列表行总分显示 暂无;详情/创建/发布响应中的试卷总分仍为 13列表响应 paper=null,前端使用未知态占位已真实操作通过BUG-20260606-005
/teacher/assignments/402/edit教师保存作业按钮button将标题改为 MCP 作业回归 0606-0413-编辑 后保存保存成功并返回列表PUT /api/v1/teacher/assignments/402 返回 200,列表标题更新PUT 请求体中题库引用仅包含 bankQuestionId=167score=13;响应 paper.totalScore=13已真实操作通过BUG-20260606-004
/teacher/assignments教师发布作业按钮button点击发布→确认发布作业状态变为已发布,发布按钮禁用,关闭按钮启用POST /api/v1/teacher/assignments/402/publish 返回 200;列表显示已发布DOM 校验 publishDisabled=truecloseDisabled=false,响应含 publishedAt已真实操作通过
/teacher/assignments教师关闭作业按钮button点击关闭作业关闭Toast"作业已关闭"已真实操作通过

5.22 教师 - 提交管理

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/submissions教师选择课程/作业下拉框select选择课程和作业选项文本可读,选中成功修复后课程下拉宽度约 280px,作业下拉宽度约 492px,长作业标题完整可读Playwright MCP DOM bbox 复核已真实操作通过BUG-20260606-006
/teacher/submissions教师查询按钮button点击查询返回提交列表课程 1 / 作业 414 返回提交 139,提交者 807,分数 100列表查询后 URL 保持 offeringId=1&assignmentId=414已真实操作通过
/teacher/submissions教师状态列table cell查看提交 139 状态后端 SUBMITTED 显示为中文业务状态状态列显示 已提交,不再裸露枚举值单元契约覆盖 SUBMITTED -> 已提交已真实操作通过BUG-20260606-007
/teacher/submissions教师重新判题提交 139button点击重判→确认弹窗确认先确认再创建手动重判任务POST /api/v1/teacher/submissions/139/judge-jobs/requeue 返回 201,响应 job id=133、triggerType=MANUAL_REJUDGE随后详情页判题任务列表出现新增任务已真实操作通过
/teacher/submissions/139教师提交级重判按钮button点击重判→确认弹窗确认先确认再创建提交级手动重判任务弹窗标题“提交级重判”;确认后 POST /api/v1/teacher/submissions/139/judge-jobs/requeue 返回 201,响应 job id=135、status=PENDING随后 GET /api/v1/teacher/submissions/139/judge-jobs 返回 200,页面显示 5 个判题任务已真实操作通过BUG-20260606-008
/teacher/submissions/139教师答案重判按钮button点击“重判答案 E2E-mq1e6zib-89oubn-webide-real-flow-programming”→确认按钮可访问名称包含目标题目,先确认再创建答案级手动重判任务弹窗说明包含题目名称;确认后 POST /api/v1/teacher/submission-answers/490/judge-jobs/requeue 返回 201,响应 job id=136、status=PENDING随后 GET /api/v1/teacher/submissions/139/judge-jobs 返回 200,页面显示 5 个判题任务已真实操作通过BUG-20260606-008
/teacher/submissions/67教师保存批改按钮button输入分数→点击保存批改保存成功Toast"人工批改已保存"已真实操作通过
/teacher/submissions/67教师下载报告按钮button点击下载报告文件下载文件 judge-job-60-report.json 下载文件存在已真实操作通过

5.23 教师 - 成绩册

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/grading/gradebook教师选择课程下拉框select选择"数据结构 2025 秋"选中成功选中成功已真实操作通过
/teacher/grading/gradebook教师查询按钮button点击查询返回成绩数据返回 10 页学生成绩已真实操作通过
/teacher/grading/gradebook教师导出 Excel 按钮button点击导出CSV 文件下载文件 gradebook-offering-1.csv 下载文件存在已真实操作通过
/teacher/grading/gradebook?offeringId=1&assignmentId=414教师选择课程/教学班/作业筛选select打开页面并观察筛选条筛选项宽度稳定,长作业标题可读,移动端不横向溢出修复后桌面课程约 284px、教学班约 224px、作业约 368px,390px 视口四个筛选控件均为 292px 且 documentWidth=390Playwright MCP DOM bbox 复核已真实操作通过BUG-20260606-009
/teacher/grading/gradebook?offeringId=1&assignmentId=414教师批量调分按钮button提交 ID / 答案 ID / 分数留空后点击显示字段级错误且不发送调分请求显示“请输入有效的提交 ID / 答案 ID / 调整分数”,三个字段均 aria-invalid=true未出现 POST /api/v1/teacher/assignments/414/grades/batch-adjust已真实操作通过BUG-20260606-010
/teacher/grading/gradebook?offeringId=1&assignmentId=414教师批量调分按钮button/dialog输入提交 139、答案 490、分数 98、反馈后点击并确认先确认再提交调分,成功后刷新成绩册和报表弹窗说明“将调整提交 139 的答案 490 分数为 98。确定要继续吗?”;确认后调分成功POST /api/v1/teacher/assignments/414/grades/batch-adjust 返回 200,answer 490 manualScore/finalScore=98;随后 gradebook/report GET 200已真实操作通过BUG-20260606-010, BUG-20260606-011
/teacher/grading/gradebook?offeringId=1&assignmentId=414教师下载导入模板按钮button点击下载下载当前作业导入模板下载 assignment-grades-414-template.csvGET /api/v1/teacher/assignments/414/grades/import-template 返回 200,content-disposition 指向模板文件名已真实操作通过
/teacher/grading/gradebook?offeringId=1&assignmentId=414教师成绩导入上传区file upload上传 CSV:提交 139、答案 490、分数 99、反馈 MCP gradebook import 0606导入成功并刷新成绩册和报表上传区显示 aubb-grade-import-414.csv;导入接口成功POST /api/v1/teacher/assignments/414/grades/import 返回 200,successCount=1/failureCount=0;随后 gradebook/report GET 200;提交详情 GET /api/v1/teacher/submissions/139 显示 answer 490 manualScore/finalScore=99、反馈为导入文本已真实操作通过BUG-20260606-011
/teacher/grading/gradebook?offeringId=1&assignmentId=414教师发布成绩按钮button/dialog点击发布成绩并确认先确认发布,学生可见后刷新成绩册和报表弹窗提示“发布后学生即可查看该作业的成绩”;确认后发布成功POST /api/v1/teacher/assignments/414/grades/publish 返回 200,initialPublication=true;刷新后 gradebook summary publishedCount=41,assignment 414 gradePublished=true已真实操作通过BUG-20260606-011

5.24 教师 - 实验中心

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/labs教师选择课程/教学班下拉框select选择课程和教学班选中成功选中成功,实验列表加载已真实操作通过
/teacher/labs教师创建实验空提交button/input选择课程 A1 后点击创建实验,实验标题留空后点击创建显示字段级错误且不发送创建请求显示“请输入实验标题”,标题字段 aria-invalid=true 且关联 lab-title-error仅有列表 GET,未出现 POST /api/v1/teacher/course-offerings/1/labs已真实操作通过BUG-20260606-012
/teacher/labs教师创建实验按钮button/dialog填写 MCP 教师实验回归 0606-0646 后点击创建创建成功并刷新当前列表POST /api/v1/teacher/course-offerings/1/labs 返回 201,列表显示新实验随后 GET /api/v1/teacher/course-offerings/1/labs?teachingClassId=1&page=1&pageSize=50 返回 200已真实操作通过
/teacher/labs教师编辑实验按钮button/dialog点击“编辑实验 MCP 教师实验回归 0606-0646”,先清空标题保存,再填写编辑标题保存空标题显示字段级错误;有效编辑成功刷新空标题显示“请输入实验标题”且未出现 PUT;有效编辑 PUT /api/v1/teacher/labs/74 返回 200,列表显示 MCP 教师实验回归 0606-0646-编辑编辑成功后当前列表 GET 返回 200已真实操作通过BUG-20260606-012
/teacher/labs教师发布实验按钮button/dialog点击“发布实验 MCP 教师实验回归 0606-0646-编辑”并确认先确认再发布,状态与按钮可用性刷新确认弹窗说明包含实验标题;确认前无发布请求,确认后 POST /api/v1/teacher/labs/74/publish 返回 200;列表显示已发布,发布按钮禁用、关闭按钮启用随后当前列表 GET 返回 200已真实操作通过
/teacher/labs教师报告按钮 / 空态button/section点击新实验报告按钮报告区域可见,空态清晰GET /api/v1/teacher/labs/74/reports?page=1&pageSize=20 返回 200,页面显示“暂无实验报告”已真实操作通过
/teacher/labs教师报告详情 / 评阅 / 发布评阅button/dialog打开 MCP 实验回归 mq1bfyvc 报告,查看详情,填写评语并保存、发布报告行操作可区分学生;详情、保存评阅、发布评阅闭环报告行按钮名称包含 MCP实验学生mq1bfyvcGET /api/v1/teacher/labs/63/reportsGET /api/v1/teacher/lab-reports/30 返回 200;正文与 README.md 附件可见;PUT /reviewPOST /publish 均返回 200,报告状态变为已发布报告列表刷新 GET 返回 200已真实操作通过BUG-20260606-012
/teacher/labs教师移动端 390pxviewport设置 390x844 后检查页面宽度和主要控件名称无横向溢出,筛选控件有可访问名称documentWidth=390,课程下拉名称“选择课程”,教学班下拉名称“教学班”,创建实验按钮可见;控制台错误 0已真实操作通过BUG-20260606-012
/teacher/labs教师关闭按钮button点击关闭实验关闭Toast"实验已关闭"已真实操作通过

5.25 教师 - 讨论管理(锁定/解锁)

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/teacher/courses/1/discussions教师锁定讨论按钮button点击锁定讨论锁定Toast"讨论状态已更新",显示"已锁定"标签,按钮变为"解锁讨论"刷新后仍为锁定状态已真实操作通过
/teacher/courses/1/discussions教师解锁讨论按钮button点击解锁讨论解锁Toast"讨论状态已更新",按钮变回"锁定讨论"刷新后仍为解锁状态已真实操作通过

5.26 学生 - 作业任务

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/student/assignments学生页面加载打开页面显示作业列表多个作业(已发布/已关闭),含截止时间和状态已真实操作通过
/student/assignments学生开始做题链接link点击进入跳转作业详情跳转到 /student/assignments/9已真实操作通过
/student/assignments/9学生页面加载打开页面显示作业详情和题目显示 4 个题目(单选/简答/文件上传/编程),作业已过期已真实操作通过
/student/assignments/9学生打开 IDE 链接link点击打开跳转编程工作区跳转到 /student/assignments/9/workspace/23已真实操作通过
/student/assignments/9学生提交答案按钮button可见(disabled,作业已截止)只读/无副作用已验证
/student/assignments/9/workspace/23学生页面加载打开页面显示编程工作区显示工作区,但"无权访问此编程工作区"(403)已真实操作通过
/student/assignments/9/workspace/23学生保存按钮button可见(disabled)只读/无副作用已验证
/student/assignments/9/workspace/23学生重置按钮button可见(作业已过期,工作区 403)受阻未测(作业过期)
/student/assignments/9/workspace/23学生历史按钮button可见(作业已过期)受阻未测(作业过期)
/student/assignments/9/workspace/23学生运行自测按钮button可见(disabled)只读/无副作用已验证
/student/assignments/9/workspace/23学生提交按钮button可见(作业已过期,工作区 403)受阻未测(作业过期)
/student/assignments/439学生结构化答题表单radio/checkbox/input/textarea/file/link/button临时学生打开未过期作业,填写单选 A、多选 A/B、填空 -1、Markdown 简答,上传 assignment-402-requests.txt,打开 IDE 后返回并提交单选/多选/填空/简答/文件/编程 6 类答案一起提交成功POST /api/v1/me/assignments/439/submission-artifacts 返回 201,详情页恢复草稿;提交后跳转 /student/submissions/148,显示 SUBMITTED、附件和 6 个答案POST /api/v1/me/assignments/439/submissions 返回 201,请求体包含 question 1515-1520 全部答案、artifact id 86 和 main.py;响应 submission id=148,单选/多选/填空自动判分 5/8/7已真实操作通过
/student/assignments/439/workspace/1520学生保存 / 运行自测button打开编程题 IDE,保存模板 main.py,点击运行自测工作区可访问、可保存、样例运行通过页面显示 main.pyLanguage: PYTHON3、可编辑;运行结果显示“已完成 / 通过 / ACCEPTED”,stdout 为 3GET /workspace 200,PUT /workspace 200,POST /sample-runs 201,GET /sample-runs 200已真实操作通过
/student/assignments/439/workspace/1520学生历史恢复按钮button/dialog打开历史版本,点击目标历史版本的恢复按钮多个恢复按钮能区分目标版本,恢复后有明确反馈修复后恢复按钮名称包含目标版本和保存类型,如 恢复历史版本 v2 手动保存;点击后显示“历史版本已恢复”真实后端 Playwright 辅助回归覆盖历史列表、恢复点击、后续保存/运行/提交链路;Playwright MCP 当前 Transport closed辅助回归通过,待 MCP 复核BUG-20260606-015
/student/assignments/439/workspace/1520学生重置为模板确认button/alertdialog点击重置,先取消,再再次点击并确认危险操作先确认,取消不生效,确认后重置为模板且可继续编辑点击“重置”显示“重置为模板”确认弹窗;取消后弹窗关闭;确认后显示“已重置模板”,重新填写代码后仍可保存、运行自测并提交真实后端 Playwright 辅助回归覆盖取消/确认两条路径;Playwright MCP 当前 Transport closed辅助回归通过,待 MCP 复核BUG-20260606-015
/student/assignments学生移动端作业卡片viewport/link390x844 视口刷新作业列表无横向溢出,卡片纵向排布,状态和目标明确的开始做题入口可见documentWidth=390,首个卡片宽度 326;状态在移动端可见;链接名称为 开始做题 <作业标题>,控制台错误 0已真实操作通过BUG-20260606-013

5.26 学生 - 实验项目

页面角色控件名称控件类型用户动作预期结果实际结果持久化校验状态缺陷编号
/student/labs学生页面加载打开页面显示实验列表默认选中"数据结构 2025 秋 / A1",可见本轮已发布实验 MCP 实验回归 mq1bfyvc已真实操作通过
/student/labs学生教学班选择下拉框select默认选中"数据结构 2025 秋 / A1"只读/无副作用已验证
/student/labs学生实验项目按钮button点击选择实验启用报告区域报告区域启用(textarea、上传、保存、提交)已真实操作通过
/student/labs学生实验报告输入框textarea输入报告内容输入成功输入成功已真实操作通过
/student/labs学生保存草稿按钮button点击保存保存成功PUT /api/v1/me/labs/63/report 返回 200,页面状态为"草稿"请求体包含 submit:false,随后 GET /report 返回 DRAFT 报告 id=30已真实操作通过BUG-20260605-007
/student/labs学生选择文件按钮button选择 README.md 上传附件上传成功并显示数量POST /api/v1/me/labs/63/attachments 返回 201,页面显示"已上传附件数:1"附件 id=30,文件名 README.md已真实操作通过
/student/labs学生正式提交按钮button点击并确认提交报告正式提交PUT /api/v1/me/labs/63/report 返回 200,页面状态为"已提交"请求体包含 attachmentIds:[30]submit:true,响应 SUBMITTED已真实操作通过
/student/labs学生移动端实验选择与提交viewport/button/textarea/alertdialog390x844 视口打开学生实验页,选择长标题实验,填写报告,保存草稿并正式提交实验卡片和报告输入框可通过明确 label 定位,保存 / 提交控件高度不低于 44px,确认弹窗在视口安全边距内,页面不横向溢出修复前实验卡片无法通过“选择实验 <标题>”定位;补充控件名称后继续暴露 AlertDialog 入场稳定后缺少移动端安全边距;修复后 PUT /me/labs/{labId}/report 草稿与提交均返回 200,documentWidth/bodyWidth <= 390API 临时创建并发布长标题实验;真实后端动态 fixture 使用当前学生已加入教学班辅助回归通过,待 MCP 复核BUG-20260606-021

7. 主链路测试结果

#链路名称步骤状态证据
ML-1管理员初始化平台配置✅ 组织架构✅ 用户✅ 用户批量导入✅ 学期✅ 课程模板✅ 开课✅ 用户详情✅部分通过见 5.1-5.7
ML-2教师教学准备公告✅ 讨论✅ 资源下载✅ 资源重命名✅ 资源空标题校验✅ 通知已读✅ 题库筛选✅ 题库新增自动刷新✅ 关闭作业✅ 资源上传✅ 资源删除✅ 讨论锁定✅ 讨论解锁✅部分通过见 5.10-5.25
ML-3教师创建作业创建作业✅ 编辑作业✅ 发布作业✅ 关闭作业✅ 查看提交✅ 提交级重判✅ 答案重判✅ 人工批改✅ 下载报告✅ 导出成绩册✅ 批量调分✅ 导入成绩✅ 发布成绩✅ 关闭实验✅部分通过见 5.20-5.24
ML-4学生答题作业列表✅ 作业详情✅ 结构化答题提交✅ 编程工作区保存/运行✅ 正式提交含编程答案✅ 实验报告✅部分通过见 5.25-5.26
ML-5评测批改状态中文展示✅ 提交级重判✅ 答案重判✅ 人工批改✅ 批量调分✅ 导入成绩✅ 发布成绩✅ 下载报告✅通过见 5.22-5.23
ML-6学生查看成绩选择课程✅ 导出成绩✅部分通过见 5.18
ML-7实验流程教师创建✅ 编辑✅ 发布✅ 报告详情✅ 评阅✅ 发布评阅✅;学生保存草稿✅ 上传附件✅ 正式提交✅通过见 5.24、5.26
ML-8通知流转教师通知已读✅ 学生通知已读✅ 学生创建讨论✅ 学生回复讨论✅部分通过见 5.15-5.19
ML-9审计权限审计日志筛选✅ 权限诊断✅ 创建授权组✅ 添加成员✅;非法权限编码 / 无效模板错误态✅通过见 5.8-5.9

8. 页面级测试结果

(待补充)

9. 负例与权限测试结果

#测试项场景预期结果实际结果状态
1错误密码登录输入错误密码提示"用户名或密码错误"显示"用户名或密码错误"已真实操作通过
2空输入登录不输入直接点登录提示必填留在登录页已真实操作通过
3未登录访问/无 token 访问根路径跳转登录页跳转到 /login已真实操作通过
4学生访问/admin学生登录后访问跳转 unauthorized跳转到 /unauthorized已真实操作通过
5学生访问/teacher学生登录后访问跳转 unauthorized跳转到 /unauthorized已真实操作通过
6未登录访问 API无 token 请求 API返回 401返回 401已真实操作通过
7退出登录点击退出跳转登录页跳转到 /login已真实操作通过
8学期创建空提交/admin/academic-terms 新增弹窗留空提交显示必填错误且不创建数据显示 6 个字段错误,字段均标记 aria-invalid=true已真实操作通过
9课程模板创建空提交/admin/course-catalogs 新增弹窗留空提交显示必填错误且不创建数据显示 4 个字段错误,字段均标记 aria-invalid=true,所属学院候选排除学校节点已真实操作通过
10公告发布 / 编辑空提交/teacher/courses/1/announcements 发布和编辑弹窗留空提交显示字段级错误且不发送创建 / 更新请求发布和编辑均显示 2 个字段错误,字段均标记 aria-invalid=true,未发送 POST / PUT 公告请求已真实操作通过
11讨论创建空提交/teacher/courses/1/discussions 创建弹窗留空提交显示字段级错误且不发送创建请求显示 2 个字段错误,字段均标记 aria-invalid=true,未发送 POST 讨论请求已真实操作通过
12成员添加负例/teacher/courses/1/members 添加成员弹窗留空或缺教学班提交显示字段级错误且不发送添加请求用户 ID / 教学班错误均可见,对应字段均标记 aria-invalid=true,未发送 POST /members/batch已真实操作通过
13成绩册批量调分空提交/teacher/grading/gradebook?offeringId=1&assignmentId=414 留空提交 ID / 答案 ID / 分数后点击批量调分显示字段级错误且不发送调分请求三个字段错误均可见,字段均标记 aria-invalid=true,未发送 POST /grades/batch-adjust已真实操作通过

10. 响应式与可访问性结果

角色视口页面结果
管理员390x844/admin/course-offerings✅ 汉堡菜单可用,表格可滚动,表单可见,验证消息正确显示
管理员桌面/admin/academic-terms✅ 新增学期弹窗有描述文本,空提交错误与 aria-invalid 状态正确显示
管理员桌面/admin/course-catalogs✅ 列表开课单位可见,新增模板弹窗有描述文本,所属学院过滤和空提交错误状态正确
教师桌面/teacher/courses/1/announcements✅ 发布 / 编辑公告弹窗有描述文本、可见字段标签,空提交错误与 aria-invalid 状态正确显示
教师桌面/teacher/courses/1/discussions✅ 创建讨论弹窗有描述文本、空提交错误与 aria-invalid 状态正确显示;锁定 / 解锁按钮可访问名称包含讨论标题
教师桌面/teacher/courses/1/members✅ 添加 / 导入 / 转班弹窗有描述文本;添加成员负例错误与 aria-invalid 状态正确显示;停用 / 恢复 / 转班按钮可访问名称包含成员姓名
教师桌面/teacher/grading/gradebook✅ 筛选下拉宽度稳定,批量调分空提交显示字段级错误,批量调分和发布均有确认弹窗
教师390x844/teacher/grading/gradebook✅ 筛选条按单列排列,课程 / 教学班 / 学生 ID / 作业控件宽度均为 292px,documentWidth=390,无横向溢出
教师390x844/teacher/courses/{offeringId}/announcements✅ 长标题公告可见,发布入口与编辑公告操作可见,documentWidth/bodyWidth <= 390
教师390x844/teacher/courses/{offeringId}/discussions✅ 长标题讨论链接可见,创建入口与锁定讨论操作可见,documentWidth/bodyWidth <= 390
教师390x844/teacher/courses/{offeringId}/resources✅ 长标题资源可见,上传入口与编辑资源操作可见,documentWidth/bodyWidth <= 390
教师390x844/teacher/courses/{offeringId}/members✅ 筛选控件可通过 label 定位,长名称成员行操作可见,停用确认 / 添加成员 / 批量导入 Dialog 在视口内,documentWidth/bodyWidth <= 390
教师390x844/teacher/courses/{offeringId}/question-bank✅ 筛选控件可通过 label 定位,长标题题目行操作、归档确认和新增题目 Dialog 可见,documentWidth/bodyWidth <= 390
教师390x844/teacher/courses/{offeringId}/judge-environments✅ 语言筛选 / 包含归档 / 查询可用,长配置名行操作、归档确认和新增配置 Dialog 可见,documentWidth/bodyWidth <= 390
学生390x844/student/labs✅ 长标题实验可通过“选择实验 <标题>”定位,报告草稿保存与正式提交请求可用,确认弹窗在视口安全边距内,documentWidth/bodyWidth <= 390
学生390x844/student/grades✅ 课程筛选可通过 label 定位,成绩查询与导出请求可用,documentWidth/bodyWidth <= 390
学生390x844/student/notifications✅ 未读通知行操作可通过“标记已读 <通知标题>”定位,点击后请求 200 且行按钮隐藏,documentWidth/bodyWidth <= 390
管理员390x844汉堡菜单✅ 点击打开/关闭正常,所有导航链接可见
教师390x844/teacher✅ 页面加载成功
学生390x844/student✅ 页面加载成功
学生390x844/student/courses/✅ 公告 / 资源 / 讨论区可见,创建讨论返回 201 并刷新列表,documentWidth/bodyWidth <= 390

11. 缺陷清单

缺陷编号严重级别页面问题摘要状态
BUG-20260605-001P2/admin/org-unitsUI 创建 COLLEGE 类型节点失败(缺 parentId)已修复
BUG-20260605-002P1/admin/course-offeringsUI 创建开课失败(无网络请求,缺必填字段提示)已修复
BUG-20260605-003P3/admin/audit-logs审计日志筛选中文操作类型无结果(列表显示中文但筛选需英文)已修复
BUG-20260605-004P2/admin/auth-explain权限诊断返回 403(PLATFORM 级别资源范围匹配错误)已修复
BUG-20260605-005P3/admin/auth-explain创建授权组返回 404(模板不存在,需先创建模板)非缺陷,预期行为;有效模板 audit-readonly 已回归通过
BUG-20260605-006P2/teacher/courses/1/question-bank编辑题目按钮点击无反应(无对话框弹出)已修复
BUG-20260605-007P1/student/labs学生实验报告保存草稿失败(保存请求缺少 submit:false,后端返回 400 Failed to read request已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260605-008P2/teacher/courses/1/question-bank分类管理按钮点击无反应(无对话框弹出)非缺陷,入口已清理
BUG-20260605-009P3/admin/org-units子节点创建成功后根节点表单类型残留 COLLEGE已修复
BUG-20260606-001P1/admin/users/[userId]用户详情页学籍/教籍资料只读,“保存学籍资料”不可完成真实编辑已修复
BUG-20260606-002P2/teacher/courses/[offeringId]/members添加成员成功后结果提示随弹窗关闭,用户看不到批量结果已修复
BUG-20260606-003P2/teacher/courses/1/question-bank新增题目成功后题库列表、分类、标签筛选未自动刷新已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-004P1/teacher/assignments/create, /teacher/assignments/[assignmentId]/edit引用题库题目创建 / 编辑作业时提交了题干、题型、配置等多余字段,后端返回 400 ASSIGNMENT_QUESTION_BANK_REFERENCE_INVALID已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-005P3/teacher/assignments作业列表接口未返回 paper 时总分列误显示 0,容易被误认为作业 0 分已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-006P2/teacher/submissions提交管理筛选区作业下拉框宽度被压缩,长作业标题不可读已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-007P3/teacher/submissions提交列表直接显示后端枚举 SUBMITTED,未映射为中文业务状态已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-008P2/teacher/submissions/[submissionId]详情页提交级重判 / 答案重判直接触发,缺少确认;答案重判按钮缺少目标题目标识已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-009P2/teacher/grading/gradebook成绩册筛选区教学班 / 作业下拉框宽度被压缩,长标题不可读;移动端作业下拉框曾横向溢出已修复,2026-06-06 Playwright MCP 桌面与 390px 回归通过
BUG-20260606-010P2/teacher/grading/gradebook批量调分空输入静默无反馈,合法调分缺少确认弹窗已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-011P2/teacher/grading/gradebook批量调分 / 导入 / 发布后缓存失效 key 不匹配,当前成绩册和报表可能不刷新已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-012P2/teacher/labs实验中心行操作 / 报告行操作按钮目标不可区分,创建 / 编辑实验空标题静默无反馈,弹窗缺少描述已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-013P2/student/assignments移动端作业卡片仍左右排布导致标题被压缩,所有“开始做题”链接名称相同且无法区分目标作业已修复,2026-06-06 Playwright MCP 回归通过
BUG-20260606-014P2/student/notifications“全部已读”接口成功且未读徽章清零后,分页通知列表未失效刷新,行内“标记已读”仍保留已修复,2026-06-06 真实浏览器补充回归通过;Playwright MCP 当前 Transport closed,已记录工具降级
BUG-20260606-015P3/student/assignments/[assignmentId]/workspace/[questionId]历史版本列表多个“恢复”按钮目标不可区分,重置确认路径缺少回归记录已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-016P2/student/courses/[classId]学生越权访问非所属教学班时虽显示 403 权限错误,但讨论创建表单仍可见已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-017P2/teacher/courses/[offeringId]/members成员管理筛选控件缺少可访问 label,移动端 Dialog 缺少稳定视口宽高约束已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-018P2/teacher/courses/[offeringId]/question-bank题库移动端筛选控件缺少可访问 label、触控高度不足,长题目行操作目标偏小已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-019P2/teacher/courses/[offeringId]/judge-environments判题环境移动端主操作、筛选和行操作触控高度不足,长配置名缺少稳定断行已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-020P2/student/grades学生成绩页课程筛选缺少可访问 label,移动端筛选和导出缺少稳定回归证据已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-021P2/student/labs, shared AlertDialog学生实验页实验卡片缺少目标化可访问名称,报告输入框缺少 label;确认弹窗移动端缺少稳定安全边距已修复,2026-06-06 真实后端 Playwright 辅助回归通过;Playwright MCP 当前 Transport closed
BUG-20260606-022P2/student/notifications未读通知行内“标记已读”按钮目标不可区分,移动端触控高度不足,长标题 / 时间行布局易压缩,通知类型直接显示后端枚举已修复,2026-06-06 真实后端 E2E 与 Playwright MCP 复核通过

12. 修复计划

  • Playwright MCP 恢复后,优先复核近期因 Transport closed 降级为辅助证据的通知、WebIDE、用户导入、组织架构、课程越权、教师成员管理移动端、教师题库移动端、教师判题环境移动端、学生成绩移动端和学生实验移动端批次。
  • 继续按小批次补齐移动端视口覆盖,优先选择学生长链路和教师内容管理中尚未做 390px 回归的页面。
  • 对报告中历史固定 ID 的学生课程 / 工作区记录做一次数据口径整理,避免旧测试数据与动态 fixture 混用造成误读。

13. 未覆盖项与风险

  • 教师:题库"编辑题目"按钮已修复并通过真实浏览器复核
  • 教师:提交管理列表级重判、详情级提交重判和答案重判已修复并通过真实浏览器复核
  • 教师:成绩册"批量调整"、"导入"、"发布"已修复并通过真实浏览器复核
  • 教师:实验"创建实验"、"编辑"、"发布"、"报告查看"、"评阅发布"已修复并通过真实浏览器复核
  • 学生:作业任务(/student/assignments)结构化答题/提交已在 5.26 用 Playwright MCP 回归验证
  • 学生:编程工作区保存/运行和正式提交编程答案已在 5.26 用 Playwright MCP 回归验证;重置/历史恢复已用真实后端 Playwright 辅助回归补测,MCP 待恢复后复核
  • 学生:实验项目(/student/labs)上传附件/提交报告已在 5.26 用 Playwright MCP 回归验证;390px 实验选择、草稿保存、正式提交确认已用真实后端 Playwright 辅助回归补测,MCP 待恢复后复核;教师评阅发布已在 5.24 补测
  • 学生:通知"全部已读"已补测并修复列表刷新问题;390px 未读通知行操作目标命名、触控高度和长标题布局已通过 Playwright MCP 复核
  • 学生:跨角色权限负例(访问非所属教学班课程内容)已补测并修复讨论创建入口暴露问题;MCP 待恢复后复核
  • 移动端视口仍仅局部覆盖;已补充 /teacher/labs/teacher/courses/{offeringId}/announcements/teacher/courses/{offeringId}/discussions/teacher/courses/{offeringId}/resources/teacher/courses/{offeringId}/members/teacher/courses/{offeringId}/question-bank/teacher/courses/{offeringId}/judge-environments/student/assignments/student/courses/{已加入教学班}/student/grades/student/labs/student/notifications 390px 回归

14. 命令与日志证据

命令结果
just healthcheck全部通过(backend 18080, frontend 3000, Docker 依赖)
just status2026-06-06 本轮开始:server/main clean;web/main clean ahead 18;docs/main clean ahead 21;root dirty workspace no
just status2026-06-06 题库移动端批次开始:server/main clean;web/main clean ahead 19;docs/main clean ahead 22;root dirty workspace no
just status2026-06-06 判题环境移动端批次开始:server/main clean;web/main clean ahead 20;docs/main clean ahead 23;root dirty workspace no
just status2026-06-06 学生实验移动端批次开始:server/main clean;web/main clean ahead 22;docs/main clean ahead 25;root dirty workspace no
just status2026-06-06 学生通知移动端批次开始:server/main clean;web/main clean ahead 23;docs/main clean ahead 26;root dirty workspace no
just healthcheck-strict通过;严格 E2E 环境变量、后端 18080、前端 3000、后端 readiness/OpenAPI、前端登录页均可用
just verify2026-06-06 10:37 CST 通过;server 320 测试 0 失败 / 0 错误,web lint/typecheck 通过,docs build 通过(仅 VitePress chunk size warning)
just verify2026-06-06 11:08 CST 通过;server 320 测试 0 失败 / 0 错误 / 0 跳过,web lint/typecheck 通过,docs build 通过(仅 VitePress chunk size warning)
just e2e-real2026-06-06 05:58 CST 复跑通过,38 个真实后端 Playwright E2E 全部通过,耗时 3.3 分钟
cd web && npm run lint通过
cd web && npm run typecheck通过
cd web && npm test -- src/tests/unit/admin/audit-logs-page.test.tsx1 文件 / 2 测试通过
cd docs && npm run docs:build通过;VitePress 输出 chunk size warning
Playwright MCP 审计日志行操作回归管理员真实会话 /admin/audit-logsGET /api/v1/admin/audit-logs?page=1&pageSize=20 返回 200;复制按钮具备“复制请求 ID <短 ID>”名称并显示“Request ID 已复制”;详情按钮具备“查看日志详情 <操作> <短 ID>”名称并显示“日志元数据”;复制 JSON 后显示“JSON 已复制”
cd web && npm test -- --run src/tests/unit/admin/user-detail-page.test.tsx1 文件 / 2 测试通过
Playwright MCP 下载验证e2e-fullrun-ml2-resource.txt (41B), gradebook-me-offering-1.csv
Playwright MCP 用户详情回归管理员真实会话 /admin/users/621 编辑学籍资料,PUT /api/v1/admin/users/621/profile 返回 200;强制下线确认后 POST /api/v1/admin/users/621/sessions/revoke 返回 204
Playwright MCP 成员添加成功反馈回归教师真实会话 /teacher/courses/1/members 添加用户 621 为整课助教,弹窗显示“添加成功 1 人,失败 0 人。”,POST /api/v1/teacher/course-offerings/1/members/batch 返回 200
npm test -- src/tests/unit/course/teacher-announcements-page.test.tsx1 文件 / 2 测试通过
npm test -- src/tests/unit/course/teacher-discussions-page.test.tsx1 文件 / 2 测试通过
npm test -- 公告 / 讨论与已整改相关单测集合9 文件 / 15 测试通过
本地 Playwright 公告负例脚本发布 / 编辑空提交均显示 2 条错误,POST / PUT 公告请求数为 0,Dialog 警告数为 0,临时种子残留数为 0
本地 Playwright 讨论负例脚本创建空提交显示 2 条错误,POST 讨论请求数为 0,Dialog 警告数为 0,20 个锁定 / 解锁按钮名称包含讨论标题
Playwright MCP 判题环境逐按钮回归教师真实会话完成 Go 1.22 筛选、空新增错误、创建、编辑、归档、包含归档复查;对应 GET / POST / PUT / archive 请求为 200/201
Playwright MCP 审计日志中文筛选回归管理员真实会话选择“登录成功”操作类型,下拉值提交 LOGIN_SUCCESSGET /api/v1/admin/audit-logs?action=LOGIN_SUCCESS&page=1&pageSize=20 返回 200,表格显示“登录成功”记录
Playwright MCP 权限解释回归管理员真实会话完成权限允许 / 拒绝 / 非法编码错误态、有效模板创建授权组、添加成员、无效模板 404 预期错误;/admin/auth/explain 200/200/400,/admin/auth/groups 201/404,/admin/auth/groups/1/members 201
Playwright MCP 题库新增自动刷新回归教师真实会话创建 MCP-QUESTION-0606-0402POST /api/v1/teacher/course-offerings/1/question-bank/questions 返回 201,随后自动拉取 questions/categories/tags,当前列表显示新题且标签筛选出现 autorefresh
npm test -- src/tests/unit/api/mappers.contract.test.ts src/tests/unit/assignment/assignment-form.test.ts2 文件 / 10 测试通过
Playwright MCP 作业创建 / 编辑 / 发布回归教师真实会话先复现题库引用作业创建 400 ASSIGNMENT_QUESTION_BANK_REFERENCE_INVALID;修复后创建 MCP 作业回归 0606-0413 id=402 成功,POST /api/v1/teacher/course-offerings/1/assignments 返回 201;编辑标题后 PUT /api/v1/teacher/assignments/402 返回 200;确认发布后 POST /api/v1/teacher/assignments/402/publish 返回 200,列表显示已发布,发布按钮禁用、关闭按钮启用
npm test -- src/tests/unit/api/mappers.contract.test.ts src/tests/unit/submission/teacher-submission-detail-page.test.tsx2 文件 / 9 测试通过
Playwright MCP 提交管理列表回归教师真实会话 /teacher/submissions?offeringId=1&assignmentId=414,课程下拉约 280px、作业下拉约 492px;提交 139 状态显示 已提交;点击“重新判题提交 139”并确认后 POST /api/v1/teacher/submissions/139/judge-jobs/requeue 返回 201
Playwright MCP 提交详情重判回归教师真实会话 /teacher/submissions/139,点击“提交级重判”先出现确认弹窗,确认后 POST /api/v1/teacher/submissions/139/judge-jobs/requeue 返回 201,job id=135;答案按钮可访问名称为“重判答案 E2E-mq1e6zib-89oubn-webide-real-flow-programming”,确认后 POST /api/v1/teacher/submission-answers/490/judge-jobs/requeue 返回 201,job id=136;随后 GET /api/v1/teacher/submissions/139/judge-jobs 返回 200,页面显示 5 个判题任务
npm test -- src/tests/unit/grading/teacher-gradebook-page.test.tsx1 文件 / 2 测试通过
Playwright MCP 成绩册调分/导入/发布回归教师真实会话 /teacher/grading/gradebook?offeringId=1&assignmentId=414,筛选区桌面课程约 284px、教学班约 224px、作业约 368px;390px 视口四个筛选控件宽度均为 292px 且无横向溢出;空批量调分显示 3 个字段错误且未发送调分请求;确认批量调分前未发送请求,确认后 POST /api/v1/teacher/assignments/414/grades/batch-adjust 返回 200,随后 gradebook/report GET 200;历史补充验证:下载模板返回 assignment-grades-414-template.csv;CSV 导入返回 successCount=1/failureCount=0 并刷新;确认发布后 POST /api/v1/teacher/assignments/414/grades/publish 返回 200,initialPublication=true,刷新后 assignment 414 gradePublished=true
npm test -- src/tests/unit/lab/teacher-labs-page.test.tsx1 文件 / 3 测试通过
Playwright MCP 教师实验中心回归教师真实会话 /teacher/labs 选择课程 1 / A1;空创建和空编辑均显示“请输入实验标题”、标题字段 aria-invalid=true 且未发送创建 / 更新请求;创建 MCP 教师实验回归 0606-0646 返回 201,编辑 lab 74 返回 200;发布前先出现包含实验标题的确认弹窗,确认后 POST /api/v1/teacher/labs/74/publish 返回 200,列表显示已发布、发布按钮禁用、关闭按钮启用;报告空态 GET /teacher/labs/74/reports 返回 200 并显示“暂无实验报告”;既有报告 MCP 实验回归 mq1bfyvc 的详情、附件、保存评阅和发布评阅通过,GET /teacher/labs/63/reportsGET /teacher/lab-reports/30PUT /reviewPOST /publish 均返回 200;390px 视口 documentWidth=390,控制台错误 0
npm test -- src/tests/unit/assignment/student-assignments-page.test.tsx1 文件 / 1 测试通过
Playwright MCP 学生作业移动端回归学生真实会话 /student/assignments,390x844 视口 documentWidth=390 / bodyWidth=390GET /api/v1/me/assignments 返回 200,控制台错误 0;前三张作业卡片宽度 326px,类名包含 flex-col / sm:flex-row;“开始做题”链接名称分别包含对应作业标题并指向各自作业详情
npm test -- src/tests/unit/api/query-keys.contract.test.tsRED:新增通知 inbox 前缀契约时失败于 ["notification","inbox", undefined];修复后 1 文件 / 5 测试通过
真实浏览器学生通知全部已读补充回归Playwright MCP 当前返回 Transport closed,本轮降级使用 Codex in-app Browser 操作真实本地页面;学生真实会话 /student/notifications 中临时实验 MCP 通知全部已读回归 mq1lx8tk 生成 1 条未读通知,点击“全部已读”前行内“标记已读”按钮数量为 1,点击后为 0,顶部未读徽标消失;后端只读校验目标通知 id=991read=trueunreadCount=0firstUnreadId=null;浏览器控制台 error 数 0
npm test -- src/tests/unit/submission/programming-workspace-page.test.tsxRED:新增历史恢复按钮目标命名单测时失败,页面仅暴露重复的“恢复”按钮;修复后 1 文件 / 1 测试通过
真实后端 Playwright 学生 WebIDE 辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。学生 WebIDE 完成编辑/保存、历史版本目标命名与恢复、重置取消与确认、重置后重新保存、运行自测、正式提交;webide-real-flow.spec.ts chromium 项目 1 个用例通过
真实后端 Playwright 管理员用户导入辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。管理员真实会话 /admin/users 点击“批量导入”打开文件选择器,上传重复用户名 CSV 后 POST /api/v1/admin/users/import 返回 200,响应 total=1/success=0/failed=1,页面展示“导入 1 行,成功 0 行,失败 1 行。”和第 2 行错误;admin-users-real-flow.spec.ts chromium 项目 1 个用例通过
真实后端 Playwright 管理员组织架构辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。管理员真实会话 /admin/org-units 从学校根节点点击“新增子节点”,Dialog 标题为“在 [学校名] 下新增子节点”,节点类型默认 COLLEGE,填写学院名称/编码后 POST /api/v1/admin/org-units 返回 201,树中显示新学院;admin-org-units-real-flow.spec.ts chromium 项目 1 个用例通过
真实后端 Playwright 学生课程越权辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。动态学生访问非所属教学班课程页时,公告、资源、讨论 API 均返回 403,页面显示三处权限错误并隐藏讨论标题输入框和“创建讨论”按钮;student-course-permission-real-flow.spec.ts chromium 项目 RED 失败于按钮仍可见,修复后 1 个用例通过
真实后端 Playwright 学生课程移动端辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。390x844 视口打开动态学生已加入教学班课程页,公告/资源/讨论区可见,填写讨论标题和内容后 POST /api/v1/me/course-classes/{classId}/discussions 返回 201,新讨论刷新到列表,documentWidth/bodyWidth <= 390student-course-mobile-real-flow.spec.ts chromium 项目 1 个用例通过
真实后端 Playwright 教师课程资源移动端辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。390x844 视口打开动态教师课程资源页,API 临时上传长标题资源,页面显示该资源、上传入口和“编辑资源 <标题>”按钮,documentWidth/bodyWidth <= 390,用例结束清理临时资源;teacher-course-resources-mobile-real-flow.spec.ts chromium 项目 1 个用例通过
真实后端 Playwright 教师公告讨论移动端辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。390x844 视口打开动态教师课程公告与讨论页,API 临时创建长标题公告和讨论,公告页显示发布入口、长标题公告和“编辑公告 <标题>”按钮,讨论页显示创建入口、长标题讨论链接和“锁定讨论 <标题>”按钮,两个页面 documentWidth/bodyWidth <= 390;公告在用例结束清理,讨论因当前无删除接口保留 E2E 前缀残留;teacher-course-content-mobile-real-flow.spec.ts chromium 项目 1 个用例通过
真实后端 Playwright 教师成员管理移动端辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。390x844 视口打开动态教师课程成员管理页,API 临时创建长名称学生并加入课程,页面筛选控件可通过“搜索 / 教学班 / 角色 / 状态”定位,长名称成员的停用与转班操作可见,停用确认、添加成员和批量导入 Dialog 均在视口内,documentWidth/bodyWidth <= 390teacher-course-members-mobile-real-flow.spec.ts chromium 项目 RED 后修复并通过
Playwright MCP 可用性检查2026-06-06 题库移动端批次调用 browser_tabs list 仍返回 Transport closed,本轮真实浏览器证据降级为本地真实后端 Playwright 辅助回归,待 MCP 恢复后复核
真实后端 Playwright 教师题库移动端辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。新增 teacher-course-question-bank-mobile-real-flow.spec.ts 先 RED 于搜索框无法通过“搜索题目”可访问名称定位;修复后 390x844 视口打开动态教师课程题库页,API 临时创建长标题题目,筛选控件可通过 label 定位且高度不低于 44px,长标题题目行操作可见,归档确认和新增题目 Dialog 在视口内,documentWidth/bodyWidth <= 390;chromium 项目 1 个用例通过
npm test -- --run src/tests/unit/assignment/question-bank-page.test.tsx题库页面单测 1 文件 / 2 测试通过
cd web && npm run lint2026-06-06 题库移动端批次通过
cd web && npm run typecheck2026-06-06 题库移动端批次通过
真实后端 Playwright 教师判题环境移动端辅助回归Playwright MCP 当前返回 Transport closed;本轮降级使用本地 Playwright 真实后端用例补充验证。新增 teacher-course-judge-environments-mobile-real-flow.spec.ts 先 RED 于“新增配置”按钮高度仅 36px;修复后 390x844 视口打开动态教师课程判题环境页,API 临时创建长配置名环境,筛选和主/行操作触控高度不低于 44px,长配置名行操作可见,归档确认和新增配置 Dialog 在视口内,documentWidth/bodyWidth <= 390;chromium 项目 1 个用例通过
npm run test:e2e -- src/tests/e2e/teacher-course-judge-environments-mobile-real-flow.spec.ts --project=chromium2026-06-06 11:24 CST 真实后端辅助复跑通过;chromium 1 个用例通过(仅 Node module.register() deprecation warning)
npm test -- --run src/tests/unit/course/teacher-judge-environments-page.test.tsx判题环境页面单测 1 文件 / 4 测试通过
cd web && npm run lint2026-06-06 判题环境移动端批次通过
cd web && npm run typecheck2026-06-06 判题环境移动端批次通过
just verify2026-06-06 11:22 CST 通过;server 320 测试 0 失败 / 0 错误 / 0 跳过,web lint/typecheck 通过,docs build 通过(仅 VitePress chunk size warning)
Playwright MCP 可用性检查2026-06-06 学生成绩移动端批次调用 browser_tabs list 仍返回 Transport closed,本轮真实浏览器证据降级为本地真实后端 Playwright 辅助回归,待 MCP 恢复后复核
npm run test:e2e -- src/tests/e2e/student-grades-mobile-real-flow.spec.ts --project=chromiumRED:新增学生成绩移动端用例先失败于 getByLabel("选择课程") 找不到课程筛选;修复后 2026-06-06 11:34 CST 真实后端辅助回归通过,chromium 1 个用例通过(仅 Node module.register() deprecation warning)
cd web && npm run lint2026-06-06 学生成绩移动端批次通过
cd web && npm run typecheck2026-06-06 学生成绩移动端批次通过
just verify2026-06-06 11:42 CST 通过;server 320 测试 0 失败 / 0 错误 / 0 跳过,web lint/typecheck 通过,docs build 通过(仅 VitePress chunk size warning)
Playwright MCP 可用性检查2026-06-06 学生实验移动端批次调用 browser_tabs list 仍返回 Transport closed,本轮真实浏览器证据降级为本地真实后端 Playwright 辅助回归,待 MCP 恢复后复核
npm run test:e2e -- src/tests/e2e/student-labs-mobile-real-flow.spec.ts --project=chromiumRED:新增学生实验移动端用例先失败于“选择实验 <标题>”按钮无法定位;补充控件名称后继续暴露确认弹窗移动端安全边距问题;修复后 2026-06-06 11:52 CST 真实后端辅助回归通过,chromium 1 个用例通过(仅 Node module.register() deprecation warning)
cd web && npm run lint2026-06-06 学生实验移动端批次通过
cd web && npm run typecheck2026-06-06 学生实验移动端批次通过
just verify2026-06-06 12:00 CST 通过;server 320 测试 0 失败 / 0 错误 / 0 跳过,web lint/typecheck 通过,docs build 通过(仅 VitePress chunk size warning)
Playwright MCP 可用性检查2026-06-06 学生通知移动端批次调用 browser_tabs list 仍返回 Transport closed,本轮真实浏览器证据降级为本地真实后端 Playwright 辅助回归,待 MCP 恢复后复核
npm run test:e2e -- src/tests/e2e/student-notifications-mobile-real-flow.spec.ts --project=chromiumRED:新增学生通知移动端用例先失败于“标记已读 <通知标题>”按钮无法定位;修复后 2026-06-06 12:06 CST 真实后端辅助回归通过,chromium 1 个用例通过(仅 Node module.register() deprecation warning)
cd web && npm run lint2026-06-06 学生通知移动端批次通过
cd web && npm run typecheck2026-06-06 学生通知移动端批次通过
just healthcheck-strict2026-06-06 12:43 CST 通过;严格 E2E 环境变量、后端 18080、前端 3000、后端 readiness/OpenAPI、前端登录页均可用
just e2e-real2026-06-06 12:51 CST 通过;chromium 50 个真实后端 E2E 全部通过
Playwright MCP 学生通知行操作复核2026-06-06 12:56 CST,390x844 视口 /student/notifications 中“标记已读 <通知标题>”按钮高度 44px,documentWidth/bodyWidth=390;点击后 POST /api/v1/me/notifications/1086/read 返回 200,目标按钮消失,控制台 warning/error 为 0