# rc **Repository Path**: cxcy666_admin/rc ## Basic Information - **Project Name**: rc - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-11 - **Last Updated**: 2026-10-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AlgoAgent —— 数据结构与算法智能学习平台 > 软件测试课程实验项目 | 本仓库当前完成**第二次实验课(账号与权限模块)**、**第三次实验课(题目管理与课程模块)**、 > **第四、五次实验课(判题模块:提交、异步队列、判题执行与结果回写)**、**第五次实验课的作业与成绩模块(布置、提交、 > 完成情况统计、成绩统计与导出)**的前后端代码,已连通线上 MySQL / Redis / RabbitMQ。 ## 一、技术栈 | 层次 | 技术 | | --- | --- | | 后端 | Spring Boot 4.1.1 + MyBatis-Plus 3.5.17 + JWT(jjwt 0.12.6)+ BCrypt | | 数据库 | MySQL 8(库名 `algo`)、Redis(验证码 / 登录失败计数 / 令牌黑名单) | | 消息队列 | RabbitMQ(判题队列、死信队列与判题消费者已接入,第四、五次实验课实现) | | 导出 | Apache POI 5.2.5(作业成绩与课程成绩导出 xlsx) | | 前端 | Vue 3 + Vite + Element Plus + axios + vue-router(成绩文件下载走 blob) | | AI | Spring AI(已接入依赖与占位配置,第七次实验课使用) | ## 二、目录结构 ``` rc/(仓库根目录) ├── README.md # 本文件:项目总说明 ├── pom.xml # 后端依赖(Maven 工程位于仓库根目录) ├── docs/ # 课程文档:需求分析文档、测试用例表、小组分工与进度安排 ├── figures/ # 需求文档插图(用例图、功能结构图、架构图、流程图) ├── scripts/ # 文档与插图的生成脚本 ├── deploy/ # 服务器部署配置与一键打包脚本(详见 deploy/README.md) ├── src/main/java/com/example/algoagent/ │ ├── common/ # Result、错误码、全局异常、脱敏工具 │ ├── config/ # MyBatis-Plus、拦截器注册、配置属性、Bean │ ├── security/ # JWT 工具、登录拦截器、角色注解、用户上下文 │ ├── entity/ mapper/ # 实体与 MyBatis-Plus Mapper │ ├── dto/ vo/ # 请求参数与返回对象 │ ├── service/ # 认证、用户、题目、课程业务逻辑 │ ├── controller/ # REST 接口 │ ├── support/ # 邮件验证码服务 │ └── init/ # 演示数据初始化 ├── src/main/resources/ │ ├── application.yaml # 数据库 / Redis / MQ / JWT / 邮件配置 │ └── db/schema.sql # 建表脚本(已在服务器执行) └── front/ # 前端工程(Vue3 + Element Plus) ├── vite.config.js # /api 代理到 localhost:8080 └── src/{api,router,store,utils,views} ``` > 课程文档索引:需求分析文档与测试用例表见 `docs/`;交付物清单、小组分工与实验进度见 > `docs/交付物说明.md`;服务器部署与运维命令见 `deploy/README.md`。 ## 三、快速开始 ### 1. 后端 ```bash cd AlgoAgent ./mvnw spring-boot:run # 启动后访问 http://localhost:8080 ``` 首次启动会自动建演示数据(可用 `algo.init-demo-data=false` 关闭): | 角色 | 用户名 | 密码 | 说明 | | --- | --- | --- | --- | | 教师 | `teacher01` | `Teacher@123` | 工号 T2026001,创建了 3 道示例题目 | | 学生 | `student01` | `Student@123` | 学号 20260001,已加入课程(课程码 `ALGO66`) | ### 2. 前端 ```bash cd AlgoAgent/front npm install npm run dev # http://localhost:5173 ``` ### 3. 数据库 建表脚本:`src/main/resources/db/schema.sql`(已在 `algo` 库执行)。如需重建: ```bash mysql -h159.75.37.44 -ualgo -p algo < src/main/resources/db/schema.sql ``` ## 四、环境配置说明 所有连接信息集中在 `src/main/resources/application.yaml`: | 项目 | 配置值 | | --- | --- | | MySQL | `159.75.37.44:3306/algo`,账号 `algo`,密码 `cxcy666` | | Redis | `159.75.37.44:6379`,密码 `cxcy666`,库 0 | | RabbitMQ | `159.75.37.44:5672`(管理端 `http://159.75.37.44:15672`),账号 `cxcy`,密码见配置文件(结尾带三个点,是密码本身的字符) | | JWT | `algo.jwt.secret`(生产环境请改用环境变量注入) | | 邮件 | 已配置 QQ 邮箱 SMTP(`smtp.qq.com:465`,SSL),发件人为 `3394202065@qq.com`,授权码写在配置中 | > 消息队列说明:判题链路只连接上表这一套 RabbitMQ。另起一个 broker(例如再建一个 RabbitMQ 容器)会让两边 > 队列不同步,出现判题任务积压或同一条消息被两个消费者重复执行;排查积压时用管理端看 `algo.judge.queue` > 的 ready 条数与消费者数即可。 > 邮件说明: > 1. `algo.mail.enabled=true` 为真实发送;临时关闭(改为 `false`)时验证码只打印到日志, > 日志形如`【开发模式】邮箱 xxx 的验证码为:123456`,便于没有网络或不想发信时联调。 > 2. QQ 邮箱的"密码"必须填 **SMTP 授权码**(不是 QQ 登录密码),授权码在 QQ 邮箱 > 「设置 → 账号 → POP3/SMTP 服务」中生成。 > 3. **发件地址必须与授权账号一致**,否则 QQ 会返回 > `501 Mail from address must be same as authorization user`,代码中已通过 > `spring.mail.username` 作为发件人地址处理。 > 4. 授权码属于敏感信息:提交到公开仓库前请改为环境变量 > `MAIL_USERNAME` / `MAIL_PASSWORD` 注入,或直接删除默认值。 ## 五、已实现功能(对照需求编号) ### 第二次实验课:账号与权限 | 需求 | 功能 | 说明 | | --- | --- | --- | | FR-AUTH-01 | 注册 | 学生填学号、教师填工号;邮箱验证码校验;用户名/邮箱/学号/工号唯一 | | FR-AUTH-02 | 登录 / 退出 | BCrypt 校验密码;连续 5 次失败锁定 15 分钟;退出后令牌进入 Redis 黑名单 | | FR-AUTH-03 | 权限控制 | JWT + 拦截器 + `@RequireRole`;学生访问教师接口返回 403,未登录返回 401 | | FR-AUTH-04 | 个人信息 | 查看资料、修改昵称/邮箱(改邮箱需验证码)、修改密码 | | FR-AUTH-05 | 邮箱验证码 | 6 位、5 分钟有效、一次性使用、同一邮箱 60 秒限发一次 | | FR-AUTH-06 | 登录会话 | 令牌 2 小时有效,过期需重新登录 | | 补充 | 找回密码 | 通过邮箱验证码重置密码,同时作为账号锁定后的自助解锁方式 | ### 第三次实验课:题目管理与课程 | 需求 | 功能 | 说明 | | --- | --- | --- | | FR-QST-01/02/03 | 题目增删改查 | 单选、多选、填空、编程题;编程题维护测试用例 | | FR-QST-04 | 上下架 | 下架题目对学生不可见、不可作答 | | FR-QST-05 | 检索分页 | 按题型、难度、知识点、关键词筛选,分页查询 | | FR-QST-06 | 题目权限 | 教师只能维护自己创建的题目;非创建者看不到答案与隐藏用例 | | FR-QST-07 | 学生作答 | 客观题在线作答并即时判分,返回正确答案与解析 | | FR-SYS-03 | 做题记录与错题本 | 每次客观题作答落库,可查看做题记录(按题型/对错筛选);错题本自动收录最近一次仍答错的题目,重做正确后自动移出 | | FR-CRS-01/02 | 课程管理 | 新增/修改/归档课程;自动生成唯一课程码,支持重置 | | FR-CRS-03/04 | 加入课程 | 学生凭课程码加入;重复加入、已归档课程均有明确提示;支持退课与再次加入 | | FR-CRS-09 | 课程权限 | 教师只能管理自己的课程,学生看不到课程码与课程名单 | ### 第四次实验课:判题提交与异步队列 | 需求 | 功能 | 说明 | | --- | --- | --- | | FR-JDG-01 | 代码提交 | 编程题在线编辑与提交;校验题型、语言、代码非空与长度上限(64 KB) | | FR-JDG-04 | 提交限流 | 同一学生两次提交间隔 10 秒、每分钟最多 6 次,超限给出明确提示 | | FR-JDG-08 | 提交记录 | 「我的提交」列表与详情(语言、状态、用例、耗时、内存、代码);只能看本人数据,教师可查 | | FR-JDG-07 | 异常处理 | 判题队列不可用时投递失败,提交直接标记「判题失败」并写明原因,不会停在「排队中」 | | FR-JDG-02 | 判题状态 | 提交后返回「排队中」,前端轮询状态;状态机覆盖 AC/WA/TLE/MLE/RE/CE/OLE/SE | > 说明:按需求约定,判题的**执行**(编译、运行、用例比对与计分)属于第五次实验课内容, > 本次课完成提交、入队、限流与状态查询;判题消费者、作业与成绩模块在第五次实验课实现。 ### 第五次实验课:作业与成绩(教学流程闭环) | 需求 | 功能 | 说明 | | --- | --- | --- | | FR-CRS-05 | 布置作业 | 教师选题目与分值(合计必须 100 分)、设置截止时间后发布;可撤回、删除(已有学生提交时拒绝) | | FR-CRS-06 | 学生作业 | 课程作业列表(待完成 / 已完成筛选)、作业详情(每题得分与作答情况)、提交作业 | | FR-CRS-07 | 完成情况 | 已交 / 未交(已作答未提交)/ 未开始三类统计,可下钻到单个学生的每题得分与代码 | | FR-CRS-08 | 成绩与导出 | 课程成绩表(行=学生、列=作业、末列总分),作业成绩与课程成绩均可导出 xlsx | | FR-CRS-10 | 学生查看成绩 | 学生查看自己的课程成绩(各次作业得分、总分与满分),接口只返回本人数据 | | FR-CRS-08 | 计分规则 | 每题得分 = 该题历史最高百分制得分 × 题目分值 ÷ 100;重复提交取最高分不累加;截止后提交标记迟交 | > 作业总分固定 100 分,分值合计不为 100 的作业不允许发布;课程归档后学生不能提交作业(错误码 5009)。 ## 六、接口清单 统一返回结构:`{"code":200,"message":"成功","data":...}`;错误码与 HTTP 状态对应(400 参数错误、401 未登录、403 越权)。 ### 公开接口 | 方法 | 路径 | 说明 | | --- | --- | --- | | POST | `/api/auth/send-code` | 发送邮箱验证码(scene:REGISTER / RESET / CHANGE_EMAIL) | | POST | `/api/auth/register` | 注册 | | POST | `/api/auth/login` | 登录,返回 token 与用户信息 | | POST | `/api/auth/reset-password` | 找回密码 | ### 需登录接口 | 方法 | 路径 | 权限 | 说明 | | --- | --- | --- | --- | | POST | `/api/auth/logout` | 学生/教师 | 退出登录(令牌加入黑名单) | | GET/PUT | `/api/user/profile` | 学生/教师 | 查看 / 修改个人信息 | | PUT | `/api/user/password` | 学生/教师 | 修改密码 | | GET | `/api/question/list` | 学生/教师 | 已发布题目列表(筛选、搜索、分页) | | GET | `/api/question/{id}` | 学生/教师 | 题目详情(学生不含答案与隐藏用例) | | POST | `/api/question/{id}/answer` | 学生/教师 | 客观题作答与即时判分 | | GET | `/api/answer/records` | 学生 | 我的做题记录(可按题型、对错筛选,分页) | | GET | `/api/answer/wrong-questions` | 学生 | 我的错题本(最近一次仍答错的题目) | | GET | `/api/course/my` | 学生/教师 | 我的课程(教师=我创建的,学生=已加入的) | | POST | `/api/course/join` | 学生 | 使用课程码加入课程 | | DELETE | `/api/course/{id}/quit` | 学生 | 退出课程 | | GET | `/api/teacher/question/list` | 教师 | 我的题目(含已下架) | | GET | `/api/teacher/question/{id}` | 教师 | 题目详情(含答案与全部用例) | | POST/PUT | `/api/teacher/question` | 教师 | 新增 / 编辑题目 | | DELETE | `/api/teacher/question/{id}` | 教师 | 删除题目 | | PUT | `/api/teacher/question/{id}/status` | 教师 | 题目上下架 | | POST/PUT/DELETE | `/api/teacher/question/{id}/test-case`、`/test-case/{caseId}` | 教师 | 测试用例增删改 | | GET | `/api/teacher/course/list` | 教师 | 我创建的课程 | | POST/PUT | `/api/teacher/course` | 教师 | 新增 / 修改课程 | | POST | `/api/teacher/course/{id}/archive` | 教师 | 归档课程 | | POST | `/api/teacher/course/{id}/reset-code` | 教师 | 重置课程码 | | GET | `/api/teacher/course/{id}/members` | 教师 | 课程学生名单(邮箱脱敏) | | DELETE | `/api/teacher/course/{id}/member/{studentId}` | 教师 | 将学生移出课程 | ### 判题接口(第四次实验课) | 方法 | 路径 | 角色 | 说明 | | --- | --- | --- | --- | | POST | `/api/judge/submit` | 学生 / 教师 | 提交编程题代码,返回提交号与「排队中」 | | GET | `/api/judge/submissions` | 学生 / 教师 | 我的提交记录(分页,可按题目、状态筛选) | | GET | `/api/judge/submission/{id}` | 本人 / 教师 | 提交详情(含代码、状态、用例、耗时与内存) | 判题相关错误码:4001 提交过于频繁、4002 每分钟提交次数超限、4003 判题任务投递失败(HTTP 503)、 4004 语言不支持、4005 提交内容过大、4006 非编程题、4009 提交记录不存在、4010 只能查看自己的提交记录。 ### 作业与成绩接口(第五次实验课) | 方法 | 路径 | 角色 | 说明 | | --- | --- | --- | --- | | GET | `/api/assignment/list` | 学生 | 课程作业列表(`status=TO_DO` / `DONE` 筛选,分页) | | GET | `/api/assignment/{id}` | 学生 | 作业详情(题目、我的每题得分与提交情况) | | POST | `/api/assignment/{id}/submit` | 学生 | 提交作业(按每题历史最高分计分,重复提交取最高分) | | GET | `/api/assignment/course/{courseId}/grade` | 学生 | 我的课程成绩(各次作业得分与总分,只返回本人数据) | | POST | `/api/teacher/assignment` | 教师 | 布置作业(题目与分值、截止时间) | | GET | `/api/teacher/assignment/list` | 教师 | 课程下的作业列表 | | GET | `/api/teacher/assignment/{id}` | 教师 | 作业详情(题目与分值、提交情况) | | POST | `/api/teacher/assignment/{id}/withdraw` | 教师 | 撤回作业(已有提交时拒绝) | | DELETE | `/api/teacher/assignment/{id}` | 教师 | 删除作业(已有提交时拒绝) | | GET | `/api/teacher/assignment/{id}/statistics` | 教师 | 完成情况统计(已交 / 未交 / 未开始) | | GET | `/api/teacher/assignment/{id}/student/{studentId}` | 教师 | 单个学生的答题明细 | | GET | `/api/teacher/assignment/{id}/export` | 教师 | 导出作业成绩 xlsx | | GET | `/api/teacher/course/{courseId}/grade` | 教师 | 课程成绩表 | | GET | `/api/teacher/course/{courseId}/grade/export` | 教师 | 导出课程成绩 xlsx | 作业与成绩相关错误码:5001 作业不存在或已撤回、5002 只能管理自己课程下的作业、5003 截止时间不能早于当前时间、 5004 分值合计必须为 100 分、5005 至少选择 1 道题目、5006 已有学生提交不能撤回或删除、5007 作业已撤回、 5008 作业中含不存在或已下架的题目、5009 课程已归档无法提交作业。 ## 七、数据库表 | 表名 | 说明 | | --- | --- | | `sys_user` | 用户(学生 / 教师共用,role 区分;密码 BCrypt 存储) | | `question` | 题目(题型、选项、答案、解析、难度、知识点、语言、时空限制、上下架) | | `question_test_case` | 编程题测试用例(区分样例用例与隐藏用例) | | `course` | 课程(课程码唯一、状态:进行中 / 已归档) | | `course_member` | 课程成员(唯一约束避免重复加入;退课后可恢复) | | `answer_record` | 客观题作答记录(做题记录与错题本的数据来源) | | `submission` | 判题提交记录(语言、代码、判题状态、得分、通过用例数、耗时与内存) | | `assignment` | 作业(课程、标题、截止时间、总分 100、题目数、发布 / 撤回状态) | | `assignment_question` | 作业题目与分值(同一作业内题目不重复,分值合计 100) | | `assignment_submission` | 作业提交记录(每题取历史最高分计算的总分、提交次数、是否迟交) | | `assignment_answer` | 作业逐题作答明细快照(提交时的题目标题、得分与作答内容) | ## 八、前端页面清单 | 页面 | 路径 | 说明 | | --- | --- | --- | | 登录 / 注册 | `/login`、`/register` | 含邮箱验证码与倒计时 | | 题库练习 | `/questions` | 学生按题型、难度、知识点、关键词筛选题目 | | 题目详情 / 作答 | `/questions/:id` | 客观题作答与即时判分;编程题含代码编辑器(语言切换、语法高亮)、提交与判题状态轮询 | | 做题记录 / 错题本 | `/answer-records` | 两个页签:做题记录(可筛选)与错题本(可重做) | | 我的课程 | `/my-courses` | 已加入课程、使用课程码加入、退出课程;课程卡片显示作业数与待完成作业数 | | 课程作业 | `/courses/:courseId/assignments` | 课程作业列表(全部 / 待完成 / 已完成),显示截止时间、我的得分与状态 | | 作业详情 | `/assignments/:id` | 作业信息与逐题得分、去作答入口、提交作业(截止后可提交但标记迟交) | | 我的成绩 | `/courses/:courseId/grade` | 学生查看自己的课程总成绩与各次作业得分,可跳转到对应作业详情 | | 我的提交 | `/submissions` | 提交记录列表与详情(状态标签、通过用例、耗时内存、代码查看),判题中自动刷新 | | 个人中心 | `/profile` | 查看/修改昵称与邮箱(改邮箱需验证码)、修改密码(学生与教师通用) | | 题目管理 | `/teacher/questions` | 教师题目列表、上下架、删除、进入编辑 | | 新增 / 编辑题目 | `/teacher/questions/edit/:id?` | 四种题型,编程题含语言、时空限制与测试用例配置 | | 课程管理 | `/teacher/courses` | 课程增改、课程码重置、归档、学生名单与移出学生,可进入作业与成绩 | | 作业管理 | `/teacher/course/:courseId/assignments` | 布置作业(选题、设分值、截止时间)、完成情况、学生答题明细、导出成绩 | | 课程成绩 | `/teacher/course/:courseId/grade` | 成绩表(学生 × 作业 × 总分)与导出 xlsx | ## 九、联调验证记录 后端接口用 curl 完成 52 项验证,第四次实验课补充 8 项判题接口自动化用例(MockMvc), 前端用 Playwright(Edge)完成页面流程验证,主要结果: | 场景 | 结果 | | --- | --- | | 教师 / 学生登录、退出(黑名单生效) | ✅ 退出后原令牌返回 401 | | 未登录访问、学生访问教师接口 | ✅ 分别返回 401 / 403 | | 注册(真实邮箱验证码)、重复用户名、验证码错误/过期/一次性 | ✅ 提示准确 | | 连续密码错误提示剩余次数、验证码发送频率限制 | ✅ 60 秒内重复发送被拦截 | | 题目增删改查、上下架、学生端不返回答案与隐藏用例 | ✅ 通过 | | 客观题作答即时判分(含正确答案与解析) | ✅ 通过 | | 课程创建、课程码加入、重复加入、归档课程、课程码重置 | ✅ 通过 | | 教师越权编辑他人题目 / 查看他人课程名单 | ✅ 返回 403 | | 编程题提交后返回「排队中」并写入提交记录 | ✅ 提交返回「排队中」,消息入队后被判题消费者取走并回写终态(2026-10-13 复测 5672 端口已可达,正向入队与消费跑通) | | 判题执行:正确的 Python 代码 | ✅ 状态 AC、100 分、3/3 用例通过、138 ms(提交 48) | | 判题执行:输出错误的代码 | ✅ 状态 WA、33 分(通过 1/3 用例),失败原因「样例用例未通过:第 1 个用例输出与预期不一致」(提交 49) | | 10 秒内连续两次提交 | ✅ 第二次返回 429 与「提交过于频繁,请 N 秒后再试」 | | 提交空代码 / 70KB 代码 / 不支持的 Go 语言 / 对客观题提交代码 | ✅ 分别返回 400 与对应提示,且不产生提交记录 | | 学生查看他人提交详情、我的提交列表 | ✅ 分别返回 403、列表不含他人记录 | | 判题队列不可用时提交代码 | ✅ 提交被标记为「判题失败」并写明原因,不停留在「排队中」 | | 前端页面:登录、题库列表、作答、我的课程、题目管理、课程管理、学生名单 | ✅ 页面渲染与交互正常,无 JS 报错 | | 前端页面:代码编辑器、代码提交与状态轮询、我的提交列表与详情 | ✅ 渲染与交互正常 | | 布置作业、撤回 / 删除、分值合计与截止时间校验 | ✅ 布置成功;分值非 100 分、截止时间早于当前时间均被拦截并提示 | | 学生作业列表筛选、作业详情与提交 | ✅ 待完成 / 已完成筛选正确;提交后按每题历史最高分计分 | | 重复提交作业与截止后提交 | ✅ 重复提交取最高分不累加(0 → 50 分仍是 50 分);截止后提交标记迟交 | | 完成情况统计与学生答题明细 | ✅ 已交 / 未交 / 未开始人数与名单一致,明细可看到每题得分与作答代码 | | 20 名学生并发提交作业 | ✅ 20 个请求全部成功,统计 20 人已交,提交记录 20 行无重复 | | 成绩表与导出 | ✅ 页面成绩表与导出的 xlsx 一致(文件用 POI 重新打开校验表头与总分),中文文件名不乱码 | | 非课程内学生查看作业、教师越权管理他人课程作业 | ✅ 分别返回 403(3006)与 403(5002),数据未变化 | | 前端页面:作业列表、作业详情、教师布置作业、完成情况、成绩表 | ✅ 使用 Node 24 完成生产构建自检,页面渲染与交互正常 | | 学生查看作业得分与课程成绩 | ✅ 作业列表分组、作业详情逐题得分与「我的成绩」页数值一致;非课程成员与教师访问学生成绩接口分别返回 403 | 第四次实验课的判题提交链路用 8 条 MockMvc 自动化用例(`src/test/java/com/example/algoagent/api/JudgeSubmitApiTest.java`) 加 curl 复核;第五次实验课补上判题执行侧与作业成绩模块,`mvn test` 全量 47 条通过(判题端到端 2 条、 本机执行器 7 条、作业与成绩 18 条,含 20 名学生并发提交、导出文件校验与学生成绩越权校验)。环境是本机 `localhost:8080` 连接线上 MySQL / Redis / RabbitMQ,2026-10-13 复测服务器 5672 端口已可达,正向入队与消费路径跑通。判题结果实测:正确的 Python 代码 AC / 100 分 / 3 个用例全通过 / 138 ms, 输出错误的代码 WA / 33 分 / 通过 1 个用例。限流与并发方面:同一学生 10 个并发提交,修复前有 3 次通过限流校验被 重复受理,修复后只放行 1 次、其余返回 429。完整执行结果、缺陷与回归结论见 `docs/判题模块测试记录.md`;作业与成绩部分的执行结果见 `docs/作业与成绩模块测试记录.md`(含 BUG-006)。 ## 十、后续实验课待办 1. 第四次实验课(已完成,2026-10-11):判题提交链路——提交接口、Redis 提交限流、RabbitMQ 入队与生产者确认、 代码编辑器与状态轮询、我的提交记录;执行与缺陷记录见 `docs/判题模块测试记录.md`。 2. 第五次实验课(进行中,2026-10-13 已完成判题执行侧与作业成绩模块):判题消费者、判题执行器(本机进程与 go-judge 沙箱两种方式)、用例比对与计分、结果回写与失败重试已端到端验证;作业布置 / 提交、完成情况统计、 成绩统计与 xlsx 导出已实现并通过 16 条接口自动化用例。剩余:判题结果详情页(逐用例耗时与内存、失败用例的 输入与期望输出,缺陷 BUG-004)、被引用题目删除后的成绩处理(BUG-006)、课程与作业消息通知(第 6 次课)、 25 个作业的分页边界数据补测、线上后端重新构建部署、服务器与沙箱环境补测 C / Java 语言路径与 MLE, 见 `docs/判题模块测试记录.md` 第八、九节与 `docs/作业与成绩模块测试记录.md` 第八节。 3. 第六次实验课:AI 答疑与主观题评分(Spring AI)、系统集成。 4. 第七、八次实验课:系统测试、缺陷修复、性能与兼容性优化、验收答辩。