-
Notifications
You must be signed in to change notification settings - Fork 18
Mode Alignment Audit
MooreFoss edited this page May 7, 2026
·
1 revision
本文档用于记录 todo.md 各阶段的可核查证据,避免只凭记忆或测试代理信号标记任务完成。
| 命令 | 结果 |
|---|---|
git status -sb |
## dev...origin/dev [ahead 3] |
git status --porcelain |
无输出,工作区无未提交改动 |
git fetch origin |
成功,无输出 |
git rev-list --left-right --count origin/dev...HEAD |
0 3 |
git rev-list --left-right --count origin/main...dev |
0 21 |
git log --oneline --decorate --max-count=20 --all:
c3ee6e1 (HEAD -> dev) 优化成绩加载速度
f8d8ceb 修复希冀作业加载逻辑
8a4f2c0 优化界面体验
f60f6b2 (origin/dev) 优化成绩界面
9ea29e2 将希冀作业添加进首页代办区
f40fc5d chore: auto-format Kotlin code
876abbe refactor shared api package layout
f073f2f 优化希冀作业拉取与详情展示
33100dc Merge branch 'main' into dev
cafcff2 调整希冀作业拉取策略
90276d7 fix(cgyy): fall back when purpose types fail
8151a15 perf(judge): enrich assignments without blocking UI
7bd6253 perf(judge): parallelize local assignment queries
d4de6f4 perf(judge): parallelize relay assignment queries
fc14ab0 feat(auth): expose connection mode on login
e69386d chore: ignore local Serena workspace
f10b647 chore: auto-format Kotlin code
4234c33 Add Judge assignments integration
f008579 Replace grade query with BUAA score source
8c9ce7f fix: address grade feature review feedback
docs/Architecture-Overview.mddocs/Module-Shared.mddocs/Module-Server.mddocs/Module-ComposeApp.mddocs/API-Contracts.mddocs/Testing-and-Quality.mddocs/Development-Workflow.md
| 模块 | shared/API 入口 | server 入口 | composeApp 入口 |
|---|---|---|---|
| 首页 | 聚合调用各 feature API | 依赖各业务路由 |
HomeScreen.kt, HomeTodo.kt, HomeBootstrapCoordinator.kt
|
| 认证/连接模式 |
AuthApi.kt, ConnectionRuntime.kt, ApiFactory.kt
|
AuthRoutes.kt, AuthService.kt, JwtAuth.kt, SessionManager.kt
|
App.kt, AuthViewModel.kt, LoginScreen.kt, ConnectionModeSelectionScreen.kt
|
| 课表 |
ScheduleApi.kt, LocalScheduleApi.kt
|
ScheduleRoutes.kt, ScheduleService.kt
|
ScheduleViewModel.kt, ScheduleScreen.kt, CourseDetailScreen.kt
|
| 考试 |
ScheduleApi.kt 中考试相关 DTO/调用 |
ExamRoutes.kt, ExamService.kt
|
ExamViewModel.kt, ExamScreen.kt
|
| 成绩 |
GradeApi.kt, LocalGradeApi.kt
|
GradeRoutes.kt, GradeService.kt
|
GradeViewModel.kt, GradeScreen.kt
|
| 空教室 |
ClassroomApi.kt, LocalClassroomApi.kt
|
ClassroomRoutes.kt, ClassroomClient.kt
|
ClassroomViewModel.kt, ClassroomQueryScreen.kt
|
| BYKC |
BykcApi.kt, LocalBykcApi.kt, BykcCourseFilterStore.kt
|
BykcRoutes.kt, BykcService.kt, BykcClient.kt
|
BykcViewModel.kt, BykcHomeScreen.kt, BykcCoursesScreen.kt, BykcCourseDetailScreen.kt, BykcChosenCoursesScreen.kt, BykcStatisticsScreen.kt
|
| 课堂签到 |
SigninApi.kt, LocalSigninApi.kt
|
SigninRoutes.kt, SigninService.kt, SigninClient.kt
|
SigninViewModel.kt, SigninScreen.kt
|
| CGYY |
CgyyApi.kt, LocalCgyyApi.kt, CgyyReservationFormStore.kt
|
CgyyRoutes.kt, CgyyService.kt, CgyyZhjsClient.kt
|
CgyyViewModel.kt, CgyyHomeScreen.kt, CgyyReservePickerScreen.kt, CgyyReserveFormScreen.kt, CgyyOrdersScreen.kt, CgyyLockCodeScreen.kt
|
| SPOC |
SpocApi.kt, LocalSpocApi.kt, LocalSpocSupport.kt
|
SpocRoutes.kt, SpocService.kt, SpocClient.kt
|
SpocViewModel.kt, SpocAssignmentsScreen.kt, SpocAssignmentDetailScreen.kt
|
| Judge/希冀 |
JudgeApi.kt, LocalJudgeApi.kt
|
JudgeRoutes.kt, JudgeService.kt, JudgeClient.kt
|
JudgeViewModel.kt, JudgeAssignmentsScreen.kt, JudgeAssignmentDetailScreen.kt
|
| 评教 |
EvaluationService.kt, LocalEvaluationService.kt
|
EvaluationRoutes.kt, EvaluationService.kt, EvaluationClient.kt
|
EvaluationViewModel.kt, EvaluationScreen.kt
|
| YGDK |
YgdkApi.kt, LocalYgdkApi.kt
|
YgdkRoutes.kt, YgdkService.kt, YgdkClient.kt
|
YgdkViewModel.kt, YgdkHomeScreen.kt, YgdkClockinFormScreen.kt
|
| 设置/关于/个人 |
UserServiceBackend, CredentialStore.kt, UpdateService.kt
|
UserRoutes.kt, UserService.kt, AppVersionRoutes.kt
|
SettingsScreen.kt, OtherScreens.kt, UserInfoScreen.kt, Sidebar.kt
|
| 更新检查 |
UpdateService.kt, NetworkUtils.kt
|
AppVersionRoutes.kt, AppVersionService.kt
|
App.kt 更新弹窗与入口状态机 |
- 当前执行分支是
dev,本地有 3 个未推送提交,dev相对origin/main有 21 个提交。 - 工作区在阶段 0 开始时无未提交改动。
- 指定文档已按当前代码阅读,模块清单覆盖
todo.md要求的全部模块。
- Web/Wasm 平台只暴露
SERVER_RELAY:shared/src/wasmJsMain/kotlin/cn/edu/ubaa/Platform.wasmJs.kt和shared/src/jsMain/kotlin/cn/edu/ubaa/Platform.js.kt返回supportsLocalConnectionModes() = false。 - Android、iOS、JVM 支持
DIRECT、WEBVPN、SERVER_RELAY:对应平台supportsLocalConnectionModes() = true。 -
DefaultApiFactory对DIRECT与WEBVPN统一分发到Local*backend,对SERVER_RELAY分发到Relay*backend;本地 WebVPN 通过localUpstreamUrl()将上游 URL 包装为d.buaa.edu.cn。 -
ConnectionRuntime.switchMode()会调用resetSession(),清理 token、clientId、本地会话、本地 Cookie、共享 HttpClient、Judge 缓存、学期缓存,并关闭自动登录。
| 模块 | SERVER_RELAY 行为 | DIRECT 行为 | WEBVPN 行为 | 客户端 UI 期望 | 差异/风险 | 是否需要修复 |
|---|---|---|---|---|---|---|
| 首页 | 聚合各 ViewModel 的 relay 结果 | 聚合各 ViewModel 的 local 结果 | 同 direct,本地 URL 经 WebVPN 包装 | 首页待办不关心模式,只消费各模块状态 | Judge 摘要初始为 UNKNOWN 时必须仍可进入待办/列表 |
已修复 Judge 默认过滤 |
| 认证/连接模式 |
RelayAuthServiceBackend 走 /api/v1/auth/*,使用 token 与 clientId |
LocalAuthServiceBackend 走 SSO/UC,本地 Cookie 和本地会话 |
同 direct,SSO/UC URL 走 WebVPN 包装 | 切换模式后重新 preload,不复用旧登录态 | shared 少了服务端 auth_lock_timeout 提示映射 |
已修复并补 NetworkUtilsTest
|
| 课表 | /api/v1/schedule/* |
LocalScheduleApiBackend 调 BYXT app 接口 |
同 direct,经 localUpstreamUrl()
|
term/week/today/exam DTO 一致 | 未发现模式特有 UI 假设 | 否 |
| 考试 |
ScheduleApi.getExamArrangement() 调 /api/v1/exam/list
|
LocalScheduleApiBackend.getExamArrangement() 调 BYXT |
同 direct |
ExamViewModel 只消费 ExamArrangementData
|
API 入口在 ScheduleApi,server route 独立为 exam |
否 |
| 成绩 |
/api/v1/grade/list,异常统一为 grade_error
|
LocalGradeApiBackend 使用 BUAA score 页面,也映射 grade_error
|
同 direct |
GradeViewModel 只消费 GradeData 和统一错误 |
grade_error 当前 server/shared 已一致 |
否 |
| 空教室 | /api/v1/classroom/query |
LocalClassroomApiBackend 走 app.buaa.edu.cn |
同 direct | 查询参数 xqid/date 和 DTO 一致 |
未发现差异 | 否 |
| BYKC |
/api/v1/bykc/*,选择/退选/签到走 server |
LocalBykcApiBackend 直连 BYKC 接口 |
同 direct | 分页、详情、已选、统计、报名状态一致 | 有副作用操作需浏览器阶段只读或谨慎验证 | 否 |
| 课堂签到 |
/api/v1/signin/today 与 /api/v1/signin/do
|
LocalSigninApiBackend 直连 iClass |
同 direct | 今日课程和签到响应 DTO 一致 | 签到是副作用操作,阶段 2 需只读或确认风险 | 否 |
| CGYY |
CgyyService.getPurposeTypes() 请求失败或解析为空时返回静态类型 |
LocalCgyyApiBackend.getPurposeTypes() 同样 fallback 静态类型 |
同 direct | 预约类型下拉必须有可选项 | 已知 direct fallback 风险已对齐 | 否,已由现有测试覆盖 |
| SPOC |
/api/v1/spoc/assignments 和详情 |
LocalSpocApiBackend 直连 SPOC |
同 direct | 列表/详情分离,待办消费摘要 | 未发现模式对齐差异 | 否 |
| Judge/希冀 |
/api/v1/judge/assignments 现在只返回 raw summary,详情走单个或批量详情接口 |
LocalJudgeApiBackend.getAssignments() 同样只返回 raw summary |
同 direct,Judge URL 和 Cookie 适配 WebVPN | 列表先显示轻量摘要,后台补详情;默认未完成过滤不能隐藏 UNKNOWN
|
初始列表不再产生 historicalCutoffCourseIds,旧的课程跳过优化不会在列表阶段更新;过期隐藏依赖后台详情补齐 |
已修复,风险记录待后续浏览器验证 |
| 评教 |
/api/v1/evaluation/list 和 /submit
|
LocalEvaluationServiceBackend 直连评教系统 |
同 direct | 列表与提交结果 DTO 一致 | 提交有副作用,阶段 2 需谨慎 | 否 |
| YGDK | /api/v1/ygdk/* |
LocalYgdkApiBackend 直连阳光打卡 |
同 direct | 概览、记录、提交 DTO 一致 | 打卡提交有副作用,阶段 2 需只读或确认风险 | 否 |
| 设置/关于/个人 |
/api/v1/user/info,设置页只切换模式 |
LocalUserServiceBackend 读取 UC 用户信息 |
同 direct | 切换模式必须清空旧会话但保留记住的账号密码 | 现有 ConnectionRuntimeTest 覆盖 token/clientId/session/autologin;代码检查覆盖 Judge/term/cache 清理 |
否 |
| 更新检查 | 匿名 /api/v1/app/version
|
仍使用 server relay 版本接口 | 同 direct | App 启动时可显示更新弹窗 | 与连接模式无业务耦合 | 否 |
- shared 端补齐
auth_lock_timeout用户提示映射,与server/src/main/kotlin/cn/edu/ubaa/auth/api/UserFacingErrors.kt对齐。 - server relay Judge 列表去掉同步详情加载,
JudgeService.getAssignments()只用JudgeAssignmentRaw.toSummary()返回轻量摘要。 - direct/WebVPN Judge 列表同样去掉同步详情加载,
LocalJudgeApiBackend.getAssignments()只返回轻量摘要。 - Judge UI 默认未完成过滤将
UNKNOWN视为未完成,避免轻量摘要在详情补齐前被隐藏。
| 命令 | 结果 |
|---|---|
.\gradlew.bat :server:test --tests "cn.edu.ubaa.judge.JudgeServiceTest" |
通过 |
.\gradlew.bat :shared:jvmTest --tests "cn.edu.ubaa.api.LocalJudgeApiBackendTest" |
通过 |
.\gradlew.bat :composeApp:jvmTest --tests "cn.edu.ubaa.ui.JudgeViewModelTest" |
通过 |
.\gradlew.bat :shared:jvmTest --tests "cn.edu.ubaa.api.NetworkUtilsTest" --tests "cn.edu.ubaa.api.ConnectionRuntimeTest" --tests "cn.edu.ubaa.api.ApiFactoryDispatchTest" --tests "cn.edu.ubaa.api.LocalCgyyApiBackendTest" --tests "cn.edu.ubaa.api.LocalJudgeApiBackendTest" |
通过 |
-
SERVER_RELAY与DIRECT/WEBVPN的分发边界清晰,Web/Wasm 平台只进入SERVER_RELAY。 - 已知 CGYY fallback 已在 direct 与 server relay 对齐。
- 已知 Judge 初始列表性能问题已在 server relay 与 direct/WebVPN 同步修复为轻量摘要优先。
- 仍需在阶段 2 用真实 Wasm 页面确认 Judge 轻量摘要、详情后台补齐和首页待办的组合行为。
| 项目 | 结果 |
|---|---|
GET http://127.0.0.1:5432/health/live |
200 OK,status=up
|
GET http://127.0.0.1:5432/health/ready |
200 OK,status=ready,Redis up
|
GET http://localhost:8080/ |
200 OK,Wasm 页面标题为 UBAA
|
| Playwright 会话 |
ubaa-phase2,已登录后执行真实浏览器覆盖 |
| 主要日志 |
output/phase2/server-memurai.log,.playwright-cli/console-2026-05-06T18-51-34-903Z.log
|
说明:Compose/Wasm 控件在多处不能用普通 DOM selector 命中,实际覆盖使用 Playwright 坐标点击、快照和截图确认。登录凭据只从 local.properties 读取用于本地登录,不写入文档。
| 模块 | 操作 | 期望 | 实际 | 证据 | 状态 |
|---|---|---|---|---|---|
| 首页 | 刷新已登录页面,等待待办后台加载 | 今日课表、研讨室、SPOC、Judge 待办可见 | 先出现后台加载中,随后出现近期待办,Judge 待办显示截止时间 |
output/phase2/current-home-refresh.png;日志中 /api/v1/schedule/today、/api/v1/spoc/assignments、/api/v1/judge/assignments
|
通过 |
| 认证/连接模式 | 已登录状态刷新、进入设置 | session 状态可恢复,Web/Wasm 仅显示服务器中转模式 |
/api/v1/auth/status 返回 200,设置页显示当前模式为服务器中转模式 |
output/phase2/current-settings.png |
通过 |
| 课表 | 进入课表、点击下一周、返回 | 周视图可加载并支持周切换 | 第 10 周课程网格加载;下一周请求成功后可返回 |
output/phase2/current-schedule.png;日志中 /api/v1/schedule/week
|
通过 |
| 考试 | 进入考试查询、打开学期菜单 | 空数据态可见,学期下拉可打开 | 显示暂无考试安排;学期菜单列出多个学期 |
output/phase2/current-exam.png、output/phase2/current-exam-term-menu.png
|
部分通过:菜单关闭/选择在 Playwright 坐标下不稳定 |
| 成绩 | 进入成绩查询、点击学期切换并返回 | 成绩概览和课程列表可加载 | 显示 GPA、加权平均分、本学期课程列表,学期切换后可返回 |
output/phase2/current-grade.png;日志中多次 /api/v1/grade/list
|
通过 |
| BYKC | 进入博雅课程、打开我的课程 | 只读查看已选课程,不触发签到/退选 | 已选课程列表加载,未点击自主签到等副作用按钮 |
output/phase2/current-bykc.png、output/phase2/current-bykc-my.png
|
通过 |
| 空教室 | 进入空教室查询 | 校区、日期、楼栋、空闲矩阵可见 | 学院路三号楼空闲教室矩阵加载 |
output/phase2/current-classroom-2.png;日志中 /api/v1/classroom/query
|
通过 |
| SPOC | 进入列表、打开作业详情 | 列表和详情分离,返回导航可用 | 列表显示课程分组、提交状态、截止时间;详情显示提交信息和作业内容 |
output/phase2/current-spoc.png、output/phase2/current-spoc-detail.png
|
通过 |
| Judge/希冀 | 进入列表、打开作业详情 | 轻量摘要先显示,后台详情补齐后仍可进入详情 | 首页待办和列表均显示未提交 Judge 作业;详情页显示题目明细、进度和截止时间 |
output/phase2/current-judge.png、output/phase2/current-judge-detail.png;日志中 /api/v1/judge/assignments 先返回,随后详情批量/单项请求 |
通过,记录到 504 降级风险 |
| 课堂签到 | 进入课程签到 | 今日课程或空数据态可见,不触发签到 | 当前账号显示今日无课程安排,刷新按钮可见,未执行签到 | output/phase2/current-signin.png |
通过 |
| CGYY/研讨室 | 进入预约、选择空闲时段、进入表单但不提交 | 站点、日期、房间时段和预约类型可用 | 预约矩阵加载;进入表单后可见预约类型按钮和提交按钮,未点击提交 |
output/phase2/current-cgyy-picker.png、output/phase2/current-cgyy-form.png;日志中 /api/v1/cgyy/purpose-types
|
通过 |
| YGDK | 进入阳光打卡 | 概览和记录可只读查看,不新增打卡 | 显示本学期认定次数、本周打卡和历史记录,未点击新增打卡 | output/phase2/current-ygdk.png |
通过 |
| 评教 | 进入自动评教 | 列表或空数据态可见,不提交评教 | 显示暂无评教课程和重试按钮,未提交 | output/phase2/current-evaluation.png |
通过 |
| 设置/关于/个人 | 侧边栏进入设置、关于、我的 | 设置、关于、个人信息页可打开并返回 | 设置显示连接模式;关于显示版本和项目入口;我的显示已脱敏个人字段 |
output/phase2/current-menu.png、output/phase2/current-settings.png、output/phase2/current-about.png、output/phase2/current-profile.png
|
通过 |
| 更新检查 | 页面加载和刷新 | 启动时调用版本接口,不阻塞登录状态恢复 |
/api/v1/app/version 返回 200,页面继续恢复 session |
.playwright-cli/console-2026-05-06T18-51-34-903Z.log、output/phase2/server-memurai.log
|
通过 |
使用 Playwright route 对只读业务接口返回受控 503,再从真实 Wasm 页面进入对应模块。路由已在验证后清除,output/phase2/current-home-restored.png 确认首页恢复正常。
| 模块 | Mock 路由 | 浏览器错误态 | 证据 |
|---|---|---|---|
| 首页 |
schedule/today、signin/today、spoc/assignments、judge/assignments、bykc/courses/chosen、cgyy/orders
|
今日课表失败卡片、待办区部分来源失败提示 | output/phase2/current-home-error.png |
| 课表 | **/api/v1/schedule/** |
加载失败: 服务暂时不可用,请稍后重试 |
output/phase2/current-schedule-error.png |
| 考试 | **/api/v1/exam/list** |
加载失败: 服务暂时不可用,请稍后重试 |
output/phase2/current-exam-error.png |
| 成绩 | **/api/v1/grade/list** |
加载失败: 服务暂时不可用,请稍后重试 |
output/phase2/current-grade-error.png |
| BYKC | **/api/v1/bykc/** |
我的课程页显示加载失败和重试 | output/phase2/current-bykc-error.png |
| 空教室 | **/api/v1/classroom/query** |
查询失败: 服务暂时不可用,请稍后重试 |
output/phase2/current-classroom-error.png |
| SPOC | **/api/v1/spoc/** |
列表页显示服务暂不可用和重试 | output/phase2/current-spoc-error.png |
| Judge/希冀 | **/api/v1/judge/** |
列表页显示服务暂不可用和重试 | output/phase2/current-judge-error.png |
| 课堂签到 | **/api/v1/signin/** |
今日签到页显示服务暂不可用和刷新 | output/phase2/current-signin-error.png |
| CGYY/研讨室 | **/api/v1/cgyy/** |
预约页显示服务暂不可用和重试 | output/phase2/current-cgyy-error.png |
| YGDK | **/api/v1/ygdk/** |
首页显示服务暂不可用和重试,未执行新增打卡 | output/phase2/current-ygdk-error.png |
| 评教 | **/api/v1/evaluation/** |
自动评教页显示服务暂不可用和重试 | output/phase2/current-evaluation-error.png |
| 个人信息 | **/api/v1/user/info** |
修复后显示服务暂不可用和重试,不再停留在无限加载 | output/phase2/current-profile-error.png |
错误态覆盖期间发现 MyScreen 在 /api/v1/user/info 失败后只显示无限加载。已新增 AuthViewModelInitializeAppTest.ensureUserInfoLoaded failure exposes profile error and clears loading,并在 AuthViewModel/MyScreen 中加入个人信息专用 loading/error 状态与重试入口。
- 考试学期菜单仍存在自动化交互阻塞:
output/phase2/current-exam-term-selected.png和current-exam-term-keyboard.png显示菜单可打开,但 Playwright locator、坐标点击和键盘 Enter 均不能选择条目;locator 日志显示 canvas 拦截 popup 按钮事件。该问题需继续判断是自动化命中测试限制还是 Wasm 用户可见交互缺陷。 - SPOC/Judge 排序筛选、搜索框仍需在菜单命中问题解决后复核。
- 有副作用的提交类操作(BYKC 签到/退选、课堂签到、CGYY 提交预约、YGDK 新增打卡、评教提交)均未执行,只做只读验证。
- 本地后端、Redis 与 Wasm dev server 可用。
- 首页和主要业务模块的真实浏览器只读流程已覆盖,重点 Judge 轻量列表、首页待办和详情补齐组合行为已确认可用。
- 受控错误态已覆盖并修复个人信息错误态无限加载问题。
- 阶段 2 尚未整体完成,不能在
todo.md标记全阶段完成;下一步应定位并解决 Compose/Wasm 下拉/筛选菜单交互阻塞。
文档以仓库源码为准。若发现不一致,请优先修正文档并在 PR 中说明。 111