22 KiB
v0.2 浏览器视觉与交互检查
2026-09-28。Playwright(chromium headless)逐页截图 + 走业务链。截图在 apps/web/test/screenshots/qa-v02/(不进 git),共 310 张。
环境
- 独立 QA 栈:
docker compose -p umtqa,127.0.0.1:4381,独立.env(随机密钥)与 override;/media、/downloads挂/opt/umt-qa/*(属主 10001), 放 18 个假样片(电影 / 剧集 / 整季包目录 / 综艺 / 字幕随行 / 无关文件),视频用truncate做成 400 MB 稀疏文件(主视频下限 50 MB)。 用户的umt栈(4380)全程未动。 - mock:testkit 的 qB / NexusPHP(观众,自定 5 条 + 默认 fixture)/ RSS / TMDB / Emby,跑在同一 compose 网络里的
denoland/deno容器(umtqa-mocks)。 宿主 ufw 的 INPUT 策略是 drop,容器经host.docker.internal/ docker0 访问宿主端口不通,所以没按原计划把 mock 放宿主。 - 镜像:先用
uhd-media-tool:v0.2.0-rc检查;修复后以83498f9 + 本轮改动构建uhd-media-tool:qa替换 app 复测(见"CI 与并行开发")。 - 视口:桌面 1440×900 明(d)/ 暗(dd),手机 390×844(m)。每页记录 console.error/warn、pageerror、失败请求、横向溢出(
scrollWidth+ 越界元素扫描)。
走过的流程
| 流程 | 结果 |
|---|---|
| 首次初始化(空提交 / 口令过短 / 两次密码不一致 / 口令错误)→ 登录 → 改密 → 登出 → 再登录 | 通过;改密时旧密码错误被踢回登录页(#1,已修) |
错误密码限速(另一 X-Real-IP 连续 6 次) |
第 5 次起 429「失败次数过多,15 分钟后再试」 |
设置 9 分区:自动化改检查间隔、库根 /media(哨兵)、路径映射 /downloads(校验)、qB 测试、Emby 测试、观众登记 + 改地址 + Cookie、TMDB key + Base URL、API Key 创建 / 撤销 |
全部成功 |
| Agent 上游:fake 设默认 + 测试 + 最小补全;自定义兼容端点指向不存在地址;fake 订阅登录 browser(粘回 URL)与 device(自动批准)、退出登录 | 成功;错误提示问题见 #13、U2 |
| 定时任务:立即执行、停用 / 启用、运行记录 | 成功 |
| Feed 新建 → 立即抓取 → 识别(5 条:4 条识别、1 条待识别)→ 站点工作台库存叠加 → 快照 | 成功;抓取后列表不自动刷新(U3) |
| 收录策略草案(1080p 模板 + 新作品收录)→ 发布 → 订阅沙丘2 → 下载计划 / qB 任务 → mock 完成 → 自动整理 | 首次因样片 1 MB 被 too_small 拦下(测试数据问题);改 400 MB 后手动整理成功入库 |
| 待处理:待识别事项「手动指定 TMDB ID」(842675) | 资源变为已识别 |
| 文件管理:浏览、重命名、新建目录、移动(预览 → 执行)、移入回收站、还原、批量整理向导(3 组 5 文件) | 成功 |
| Agent 会话:execute、plan_only、spawn 子会话 + await;抽屉 Ctrl+J 开关、Esc 关闭、焦点落输入框、FAB 状态 | 成功(自定义 fake 脚本后未匹配目标失败,见 U11) |
| 引擎面板 runs / 详情;业务任务失败项重试 | 成功;引擎里没有失败 run,重跑按钮只看了详情页 |
| 审计列表 | 成功;动作名缺中文(#11,已修) |
SSE 断线:页面打开时 docker restart umtqa-app-1 |
EventSource 3 次内重连,页面无报错;期间 /dashboard 一次 CONNECTION_RESET 属预期 |
检查矩阵
38 个路由 × 3 视口 = 114 张(文件名 M-<路由>-<d|dd|m>.png),修复后复测截图 V*。无横向溢出、无 pageerror、无非预期 4xx/5xx。
"问题"列指下方清单编号,✓ 为该视口未发现问题。
| 页面 | d | dd | m | 问题 |
|---|---|---|---|---|
| 登录 / 初始化 | ✓ | ✓ | ✓ | — |
| 首页 | 问题 | 问题 | ✓ | #6 #17 |
| 待处理 | 问题 | 问题 | 问题 | #5 #12 U15 U16 |
| 站点工作台 / 详情(整理视图、快照与 Feed、账号) | 问题 | ✓ | 问题 | #3 #15 U8 |
| 来源健康 | 问题 | 问题 | 问题 | #3 U3 |
| 订阅 / 新建订阅 | 问题 | ✓ | ✓ | #5 |
| 收录策略(草案 / 发布) | 问题 | 问题 | 问题 | #4 #5 U4 |
| 偏好标签 | ✓ | ✓ | ✓ | — |
| 下载队列 / 详情 | 问题 | 问题 | 问题 | #2 #6 #9 #14 U7 |
| 下载计划 | 问题 | 问题 | 问题 | #10 |
| 业务任务 / 详情 | 问题 | 问题 | 问题 | #5 |
| 媒体库 / 详情 | 问题 | 问题 | 问题 | #8 U1 U9 |
| 整理记录 / 详情 | 问题 | 问题 | 问题 | #5 #7 |
| 文件管理 / 回收站 / 向导 | 问题 | ✓ | 问题 | #5 U6 U12 U13 |
| 身份与元数据 | ✓ | ✓ | ✓ | — |
| Agent 会话 / 详情 / 抽屉 | ✓ | ✓ | ✓ | U10 |
| 定时任务 | ✓ | ✓ | ✓ | 文案清单 |
| 设置·自动化 / 站点与账号 / 下载器 / 媒体库与目录 / 媒体服务器 / 元数据 | ✓ | ✓ | 问题 | U5 U6 |
| 设置·Agent | 问题 | 问题 | 问题 | #13 U2 U6 |
| 设置·API Key | ✓ | ✓ | ✓ | 文案清单 |
| 设置·账户与安全 | 问题 | ✓ | ✓ | #1 U14 |
| 引擎面板 / 详情 | ✓ | ✓ | ✓ | — |
| 审计日志 | 问题 | 问题 | 问题 | #11 |
| 404 | ✓ | ✓ | ✓ | — |
问题清单
共 34 项:已修 17、未修 17(另有文案清单 13 条,其中 3 条已随 #9/#5/#13 修掉)。
已修
| # | 严重度 | 页面 | 截图 | 现象 | 提交 |
|---|---|---|---|---|---|
| 1 | 高 | 设置·账户与安全 | 02-pwd-wrong-current-d.png → V01-pwd-wrong-current-d.png |
改密时旧密码填错,服务端回 401,全局 401 处理当成会话失效直接跳登录页;开启二次验证填错验证码同样 | 0c0907a |
| 2 | 中 | 下载详情·手动整理 | 45-dl-organize-preview-d.png、45-dl-organize-exec-d.png |
预览显示「无法生成计划:source_size_mismatch」时「执行」仍可点,执行后生成一条「未关联作品 0/0」的失败整理记录 | d7eb6a4 |
| 3 | 中 | 来源健康 / 站点详情(手机) | M-sources-m.png → V12-sources-m.png |
Feed 表名称列 320px,健康、启停、立即抓取被挤出屏幕,只能横滑发现 | d7eb6a4 |
| 4 | 中 | 收录策略·新建草案 | 40-policy-new-d.png、40-rules-err.png |
策略键只有占位符 default,看起来像已填;保存只弹「表单有错误」 |
46d37d8(预填 default) |
| 5 | 中 | 策略版本、订阅、待处理、业务任务、整理记录、回收站 | 40-policy-published-d.png、87-task-retried-d.png、64-trash-d.png |
操作者显示 admin_session:<uuid>、user:<uuid>、system |
46d37d8 |
| 6 | 中 | 下载队列、首页缓存水位 | 42-downloads-d.png → V04-downloads-volume-d.png |
没填缓存卷标识时显示 instance:<uuid> |
46d37d8(显示下载器名) |
| 7 | 中 | 整理记录详情 | 43-organize_4bedfb53-…-d.png → V03-organize-reason-d.png |
失败原因 blocked:no_main_video(blocked) |
46d37d8(取冲突说明「没有可入库的主视频」) |
| 8 | 中 | 媒体库详情·版本目标 | 47-library_…-d.png |
原因显示 blocked:no_main_video、deferred:slot_busy;inflight:<uuid> |
46d37d8 |
| 9 | 低 | 下载详情 | 44-downloads_…-d.png |
时间线「提交下载:succeeded」「复制:failed」,用途 upgrade,说明 added |
46d37d8 |
| 10 | 低 | 下载计划 | M-downloads_plans-m.png → V07-plans-d.png |
「优先级 new_work / upgrade」,说明 organize:succeeded |
46d37d8 |
| 11 | 低 | 审计日志 | M-audit-m.png → V08-audit-d.png |
capability.invoke、files.*、site.*、feed_source.created 等无中文 |
46d37d8 |
| 12 | 低 | 待处理·待识别 | 42-inbox-d.png |
摘要「没有匹配的作品(no_viable_candidate)」 | 46d37d8(新开事项生效) |
| 13 | 低 | 设置·Agent 上游测试 | 72-custom-completion-fail-d.png |
端点不存在时显示「失败 · Connection error.」,没归到「网络错误」也没说怎么办;凭证来源 stored credential |
46d37d8 |
| 14 | 低 | 手动整理预览 | 46-dl-organize-preview-ok-d.png |
徽章 copy / transfer、文件类型 video |
d7eb6a4 |
| 15 | 低 | 站点详情·库存叠加 | M-sites_…-m.png |
候选标签 1080p:deferred |
46d37d8 |
| 16 | 低 | 全站弹窗 / 抽屉 | — | 关闭按钮读屏文本 Close、面包屑 More |
46d37d8 |
| 17 | 低 | 首页·最近产出 | 92-home-after-restart-3s-d.png |
无作品的记录显示「未命名」,与整理记录页「未关联作品」不一致 | 46d37d8 |
未修
| # | 严重度 | 页面 | 截图 | 现象 | 原因 |
|---|---|---|---|---|---|
| U1 | 中 | 媒体库详情 | 47-library_f020597a-…-d.png、V09-library-slot-d.png |
自动整理被拦(版本目标进 attention)后,从下载详情手动整理成功入库、资产已核验,版本目标仍「需处理」、当前资产「无」 | 设计取舍:transitionWithInflight 对静止态 attention 拒绝 verify_passed("可能已被人工处理")。要么放行 attention→verify_passed,要么手动整理成功时自动解决对应「整理冲突」事项,需要定 |
| U2 | 中 | 设置·Agent 上游 | V11-pi-test-network-hint-d.png |
Base URL 不存在,「测试」仍「通过」并把状态改成「可用」;只有「最小补全」会连端点 | 测试语义设计(只查凭证和模型,不产生费用);建议测试结果不改写可用状态,或给自定义端点做一次 /models 探测 |
| U3 | 中 | 来源健康 / 站点详情 | 90-sse-after-event-d.png |
点「立即抓取」后,抓取任务完成不发 SSE 事件,列表只在请求返回那一刻刷新一次;worker 慢时一直显示旧的「最后成功」 | 需要新事件(如 source.feed_fetched)+ 前端失效,超出本轮 |
| U4 | 低 | 收录策略草案 | 40-policy-saved-d.png |
保存失败只弹「表单有错误」,不指明字段、不滚动到错误处(长表单里看不到) | 需要表单级错误定位,改动面大 |
| U5 | 低 | 设置各分区表单 | 10-empty-settings_agent-d.png |
带说明文字的字段,说明与下一个字段标签只隔 4px,节奏不齐 | FormField 间距属设计取舍 |
| U6 | 低 | 全站(手机更明显) | M-settings_agent-m.png、60-files-d.png |
右下 Agent FAB 盖住右对齐开关、文件管理页脚「剩余空间」 | FAB 定位设计取舍 |
| U7 | 低 | 下载计划 / 详情 | 44-downloads_…-d.png |
新作品首次下载的计划用途是「升级」、时间线写「创建下载计划(升级)」 | 业务逻辑待查 |
| U8 | 低 | 站点详情 | 32-site-detail-d.png |
所有资源都是「H&R 未知」,fixture 里标了 H&R 的也一样 | 适配器 / mock 选择器待查 |
| U9 | 低 | 媒体库详情·元数据 | 47-library_…-d.png |
TMDB 已识别,元数据各字段仍「未提供」;别名重复(沙丘2 ×2、Dune: Part Two ×3) | 数据层待查 |
| U10 | 低 | Agent | 83-agent-run-execute-d.png |
配了自定义 fake 脚本后,不匹配的目标直接失败「assistant_error: no fake script matched」,内置演示脚本不再兜底 | fake 仅用于演示,行为与 runbook 一致 |
| U11 | 低 | 全站说明文字 | 多处 | 中文句子里混用半角 ,;: 与全角 。(如「停用后不再访问该站点,也不产生新候选;…」「账号:未验证」) |
全站文案规范问题,留给文案轮 |
| U12 | 低 | 文件管理 | 61-files-incoming-d.png |
单击目录只选中,双击才进入;手机上不便 | 交互设计取舍 |
| U13 | 低 | 文件管理·移动到… | 63-move-preview-d.png |
目标树点到源所在目录即自动预览,返回 400 并在控制台报错 | 预期校验,但应在前端先拦 |
| U14 | 低 | 账户弹层 | 02-account-menu-d.png |
浮层透明度高,底下的「实时」「暂停自动化」透出 | 材质设计取舍 |
| U15 | 低 | 待处理(手机) | M-inbox-m.png |
指标卡说明「待处理 + 调查中 + 等你决定」被截断 | 文案可缩短 |
| U16 | 低 | 身份指定弹窗 | 50-inbox-assign-dialog-d.png |
类型用原生 <select>,输入框只有占位符没有标签 |
组件统一待做 |
| U17 | 低 | 健康检查 | — | v0.2.0-rc 镜像 /health 报 version: 0.1.0 |
当前 main 已有 chore(release): v0.2.0,下次构建复核 |
文案问题清单
| 位置 | 现状 | 建议 |
|---|---|---|
| 下载详情·计划 | 用途 upgrade、说明 added |
已修:升级 / 已添加到下载器 |
| 业务任务·触发 | user:<uuid> |
已修:管理员 |
| 上游测试 | Connection error. |
已修:「连不上上游,检查 Base URL、端口和网络。原始错误:…」 |
| 元数据保存 toast | 「TMDB已保存」 | 「TMDB 已保存」(中英文之间空格) |
| 设置·API Key | 分区标题「API Key / 签发给外部程序的 Key」下小节又是「API Key / 签发给外部程序(…)的 Key」 | 删掉一处 |
| 定时任务 | 「每 168 小时」 | 「每 7 天」 |
| 定时任务·备份 | 「目前由 scripts/backup.sh 在宿主机执行」 | 与 runbook 的 umt backup 对齐 |
| 初始化页 | 字段叫「初始化口令」,服务端报错「setup token 无效」 | 统一一个词 |
| 待处理指标 | 「最高 提示」 | 「最高级别:提示」 |
| 版本目标 | 「延后(单元在途)」 | 「延后:已有计划在途」 |
| 整理记录详情 | 「整理后 · 库根相对 / 未知或未授权」 | 失败记录直接写「未生成目标路径」 |
| Agent 上游列表 | 模型列「provider 默认」 | 「默认模型」 |
| 全站 | 半角 ,;: 混在中文句子里 |
见 U11 |
CI 与并行开发
- 检查期间 main 上有另一路开发在提交(W9 站点中心、命名模板等),工作区还有大量未提交改动。当前 main 的
deno task ci在本轮之前就是红的:instances-routes.ts的SiteCredentialsPut类型错误、release-fields.ts缺challenge、api-registry端点未实现等,都不在本轮改动里。 - 本轮只提交自己的改动,用临时 index 按块提交(
organize.ts里只含本轮 7 行,对方未提交的命名改动未带入),提交后把真实 index 对应路径同步到新 HEAD。 - 验证:在
83498f9(本轮开始时的 HEAD)+ 本轮改动的独立 worktree 跑deno task ci:typecheck、lint、check:tokens、build 全过; 测试 server 275 通过,2 个文件因与并行开发共用开发库(55433)的 schema 被对方删掉而失败,单独重跑通过;tasks 的崩溃恢复用例同理重跑通过。 用这份代码构建的uhd-media-tool:qa在 QA 栈复测了 #1–#17。
值得一看的 5 张截图
apps/web/test/screenshots/qa-v02/47-library_f020597a-d1f5-4ca0-8d16-81b974ad1960-d.png:手动整理成功后版本目标仍「需处理」(U1)apps/web/test/screenshots/qa-v02/83-agent-run-spawn-d.png:fake 模型派生子会话 + await,会话树合计与系统核实apps/web/test/screenshots/qa-v02/66-organize-wizard-1-d.png:批量整理向导识别步骤(整季包 + 电影 + 待选作品)apps/web/test/screenshots/qa-v02/45-dl-organize-exec-d.png:预览失败仍能执行产生的失败记录(#2,已修)apps/web/test/screenshots/qa-v02/V11-pi-test-network-hint-d.png:不存在的端点「测试」通过、状态变「可用」(U2)
W10-pre 后端复核(未修项状态)
2026-09-28。只改后端;前端项留给前端波。验证:HEAD + 本轮改动的独立 worktree 跑 deno task ci。
| # | 归属 | 状态 | 说明 |
|---|---|---|---|
| U1 | 后端 | 已修 | 协调者拍板:状态机新增 manual_verify(attention → verifying,带原因)。下载任务的整理成功入库时,Slot 若是 attention 先回核验,再由 verify_passed 按实际入库资产落 satisfied / empty(部分覆盖);同一下载任务的「整理冲突 / 做种义务阻止移动」事项(organize_blocked:<下载任务>)自动 resolved,resolution = { key: "manual_organize", organizationRecordId, by },自动重试成功记 organize_retry。纵切测试覆盖 |
| U2 | 后端 | 已修 | 自定义 Base URL(非 OAuth)的「测试」只核对凭证和模型,不再把状态改成「可用」、不记核验时间,返回提示「没有连接 Base URL;用「最小补全」确认端点可达」。前端直接显示 message 即可 |
| U3 | 后端 + 前端 | 未修,需定 | 根因比报告写的大:ctx.outbox.emit 写的事件(feed.fetched、decision.*、download.status_changed、organization.changed 等)只进 outbox 路由成任务,没有任何一条镜像到 SSE 总线;浏览器只收得到直接 ctx.events.publish 的事件(agent、settings、files、schedule、heartbeat)。首页订阅的这些类型实际从未到达。要补一个 outbox → SSE 的桥(提交后可见、顺序与裁剪策略),属于设计改动,超出本轮。桥接好后前端来源健康 / 站点详情订阅 feed.fetched 失效列表 |
| U4 | 前端 | 未修 | 表单级错误定位 |
| U5 | 前端 | 未修 | FormField 间距 |
| U6 | 前端 | 未修 | FAB 定位 |
| U7 | 后端 | 已修 | 电影 Slot 缺口的 mode 仍记 upgrade(determineMode 的 slot_gap),但计划用途只在 Slot 已有当前资产时才是「升级」,否则「补缺」;时间线随之显示「创建下载计划(补缺)」 |
| U8 | 后端 | 不改 | 观众站定义(照搬 MP 的 audiences.json)没有 hr 选择器,H&R 三态按设计为 unknown;mock 页面上的 hitandrun 标记不会被读取。要补选择器需先在真实站点核对 |
| U9 | 后端 | 已修 | 按 TMDB 建档(自动识别 / 手动指定 / 按候选建)时同事务写入 TMDB 字段并投影,不再等下一次刷新(不记 last_metadata_refresh_at,剧集季总集数仍由首次刷新补);别名按规范化文本去重(TMDB 译名/别名列表与主标题、原名重复的不再登记,站点标题与已有别名同文本时也不登记)。已有数据里的重复别名不回溯清理 |
| U10 | 后端 | 不改 | fake 仅用于演示,行为与 runbook 一致 |
| U11 | 前端 / 文案 | 未修 | 全站标点规范 |
| U12 | 前端 | 未修 | 文件管理单击进入 |
| U13 | 前端 | 未修 | 移动目标树先拦「目标 = 源所在目录」 |
| U14 | 前端 | 未修 | 浮层材质 |
| U15 | 前端 | 未修 | 指标卡文案缩短 |
| U16 | 前端 | 未修 | 身份指定弹窗 select / 标签 |
| U17 | 后端 | 已核 | /health 与 /system/health 都读 apps/server/deno.json,当前为 0.2.0;rc 镜像构建早于版本号提交,下次构建复核 |
文案清单里的后端项已改:服务端初始化报错改为「初始化口令无效…」(与页面字段同词);定时任务「备份」说明改为「目前用 umt backup(宿主机 cron 调用)」。其余文案(TMDB 空格、API Key 重复小节、「每 7 天」、「最高级别:提示」、「延后:已有计划在途」、失败记录「未生成目标路径」、「默认模型」)在前端。
其他:packages/db/test/schema.test.ts 补 site_user_data(0031),迁移往返用例超时放宽到 60s(35 个迁移 down/up 在共用开发库上超过默认 5s);db-sync 在 HEAD 上已齐。迁移 0031–0035 连续无冲突(0017 历史上空缺,迁移器按文件名排序,不影响);0035 仍是 W9-E 未提交改动,types.ts 已含其列。
前端联调追加的两条站点中心后端 bug(同一提交修):
PUT /sites/{id}/credentials更新已有账号凭证 500:secret 名site_account:<label>撞secret.name唯一约束(各站点都有default,换凭证时新 secret 与旧 secret 同名)。改为同账号同类凭证(主凭证 / passkey / TOTP)原地replace,需要新建时名字带站点 id 与随机后缀;会话 Cookie、POST /site-accounts同样处理。测试夹具的 fake secret 现在按 label 落name,能复现唯一约束。- 馒头刷新登录 "Invalid URL":用户数据解析器在没有
config.apiBaseUrl时按站点地址推https://api.<根域>,站点地址是 IP / 本地 mock 时拼成非法 URL。改为与适配器一致:站点配置 > 定义里的apiBaseUrl(https://api.m-team.cc)。
W10 前端复核(未修项终态)
2026-09-28。前端项与 U3 在 W10 集成里处理,提交见 docs/plan/08-v0.2-closeout.md"W10 集成记录"。
| # | 状态 | 说明 |
|---|---|---|
| U3 | 已修 | OutboxRelay 新增 mirror:feed.*(除 feed.due)、decision.*、download.*、organization.*、subscription.* 投递成功、认领事务提交后按顺序发到 SSE 总线,payload 原样(带业务 id);只镜像不路由的类型也会被认领并标记已投递(以前 feed.fetched、organization.changed 等一直停在 pending)。Feed 表收到 feed.fetched / feed.health_changed 刷新,任务流多听 Feed 与待处理事件。目前没有 subscription.* 事件 |
| U4 | 已修 | lib/form-errors.ts:保存失败 toast 写出第一处问题,滚到第一个 aria-invalid / role=alert 并聚焦;用在收录策略草案、设置分节、实例抽屉、订阅表单 |
| U5 | 已修 | FormField 加 4px 底距,说明文字与下一个标签至少隔 8px |
| U6 | 部分 | 页面底部原已留 pb-24;文件管理状态栏的"剩余空间"改为靠左。滚动途中悬浮按钮仍会暂时盖住右侧控件,属悬浮按钮的定位取舍 |
| U11 | 不改 | 代码与文档自 W1 起统一用半角 ,;: + 句末全角 。,改成全角要先定全站规范并整体替换(数千条),单改几处只会更乱。留给文案规范决定 |
| U12 | 已修(FE-4) | 窄屏单击目录直接进入、长按多选;桌面保持单击选中、双击进入 |
| U13 | 已修 | transferTargetProblem:目标是源所在目录或在源目录之内时,移动 / 复制对话框直接提示,不发预览 |
| U14 | 已修 | 账户弹层用近实底材质 pg-float-solid |
| U15 | 已修 | 指标卡说明改为「含调查中、等你决定」 |
| U16 | 已修 | 手动指定 TMDB 的弹窗改用共享 Select,类型 / TMDB ID / 备注都有标签 |
文案清单前端项已改:「TMDB 已保存」等 toast 的中英文空格、API Key 小节标题改「已签发的 Key」、整天间隔显示「每 7 天」、「最高级别:提示」、「延后:已有计划在途」、失败记录的整理后路径显示「未生成目标路径」、上游模型列「默认模型」。