Files
cmbuyer/docs/tasks/T-006.md
T

173 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-006
title: 桌面端 MVP 交互原型
phase: 0
deps: []
status: DOING
created: 2026-08-03
context_ref: dfe3d56
work_branch: task/t-006-desk-prototype
needs_device: false
needs_human_review: true
write_paths:
- docs/tasks/T-006.md
- docs/design/desk-execution.html
- docs/design/desk-device-settings.html
---
## 问题 / 背景
desk 端将使用 PySide6 / Qt Widgets,但当前没有可确认的桌面应用信息架构。采购执行页同时
承载连接状态、轮询会话、真机步骤、dry-run、真实下单围栏与人工接管,若不先区分状态,
极易把「重新执行」错误地暴露在可能已创建订单的场景。先用 HTML 模拟 Windows 桌面壳,
确认页签、密度、主动作、键盘操作与安全反馈,再转换为 PySide6 控件。
本任务不连接 ADB、web 服务或拼多多,不构成真机验收,也不证明 Qt 原生焦点、主题、
无障碍和性能;这些必须在生产实现中重新验证。
## 关联需求与交互
- 功能:F-005、F-006、F-009、F-010、F-011、F-013、F-017
- 用户故事:US-003、US-005、US-008
- 交互:IX-007、IX-008、IX-011
- 界面:采购执行、设备与参数两个固定页签
- 架构 / API:`04-architecture.md` 第四、五、六节;`api.md` 第二、三节
- 原型约定:`docs/design/README.md`
## 方案
### 文件与页面
1. `desk-execution.html`:Windows 桌面壳、两个页签、web / ADB / 拼多多版本状态、轮询主动作、
当前任务与步骤、租约、倒计时、失败计数、事件日志。原型状态切换器覆盖:未就绪、空闲、
轮询、第一趟试选、dry-run、真实第二趟围栏前、申请围栏中、围栏后核对、结果不明、待人工、
连续失败停止。
2. `desk-device-settings.html`:显式 serial、连接方式、ADB 路径、web 地址、假设备凭据占位、
轮询间隔、超时与连续失败阈值;校验错误、连接检查中、版本失配、保存成功、运行中冻结。
### Windows / Fluent 交互基线
- 使用 `Segoe UI` 和语义 token,适合 Windows 生产力工具的中等偏紧密度;蓝色主操作、红色
危险、黄色不确定、绿色就绪。图标使用内联 SVG 或文字,不用 emoji。
- 导航只保留两个固定页签;同一任务区只有一个主动作。开始 / 停止轮询的位置稳定,
禁用时在控件附近说明原因。
- 适配 compact / medium / wide:窄宽度改为单列,宽屏把当前任务与事件日志并排;不依赖
hover 才能看到关键信息。
- 支持键盘遍历、可见焦点、`aria-live`、高对比媒体查询、深浅色 token 与
`prefers-reduced-motion`。原型可以提供主题 / 状态切换,但必须标注为演示工具。
- 每个文件 CSS / JS 全内联、可复位假数据、零网络请求;不得调用 ADB、shell、API 或打开 App。
### 状态与安全表达
- web、设备、App 版本三项都就绪才允许开始轮询;App 实际版本与已取证版本不一致时
fail closed,并给出「停止轮询、重新取证」的下一步。
- 当前任务始终显示 `TRIAL` / `DRY-RUN` / `ORDER` 的中文含义;dry-run 固定显示
「只读演练,不会提交订单」。
- 申请围栏失败或响应不明时显示「未获点击许可」,不得出现继续 / 提交动作。
- 围栏成功后只恢复同一 `submission_id`;点击结果不明时显示「订单可能已创建」,只提供
导出证据 / 打开人工核查说明,不提供重试、重新领取或放弃授权。
- 外部支付、安全校验和真机断连立即停止;不提供绕过、继续付款或任何扣款操作。
- 运行中冻结设备切换与参数保存;关闭窗口受控并说明将停止轮询,围栏后不得让用户误以为
关闭即可重来。
### HTML 到 PySide6 映射
执行记录必须补一张映射表,至少覆盖:应用壳 / 页签、状态徽标、主动作、表单、进度、日志、
确认对话框、通知 / 错误、焦点与快捷键;说明推荐的 Qt Widgets 控件、信号和状态来源。
## 验收要点
- 两个 HTML 均可本地直接打开,页签入口互通,控制台无 error,除本地导航外无网络请求。
- 所列运行状态均可通过显式原型控制区切换;切换后主动作、说明和可用控件与 IX 一致。
- 版本失配、服务端不可达、围栏响应不明、点击后结果不明、外部支付、安全校验均有明确
停止状态和下一步,且绝无重试提交或付款控件。
- compact / medium / wide 无内容覆盖;键盘可操作、焦点可见、状态不只靠颜色。
- 任务执行记录包含 HTML → PySide6 映射与人工评审清单。
- 运行:`python scripts/validate_agent_context.py`、`git diff --check`,并用浏览器逐页检查
accessibility snapshot、控制台与网络请求。
- 完成自动验证后任务保持 `DOING`,等待人确认页签、信息密度、主动作和安全状态表达。
## 边界
- 只修改 frontmatter `write_paths` 所列文件,不改共享路线图、需求、IX、API 或生产目录。
- 不实现 Python、PySide6、uiautomator2、ADB、HTTP、系统托盘、后台进程或安装包。
- 不从前序项目复制页面判据、选择器、常量或真机结论。
- 不提供任何点击支付、免密支付、先用后付或扣款相关控件;也不提供真实提交按钮。
- 原型 HTML 不能作为 Qt 原生行为、无障碍、主题或性能的验收证据。
## 执行记录
### 2026-08-03 · 原型待人工确认
状态保持 `DOING`。本轮只完成 Phase 0 浏览器原型,不连接 web、ADB 或拼多多,也不把浏览器
行为视为 Qt / 真机验收。
**已修改**
- `docs/design/desk-execution.html`:固定两页签桌面壳、三项就绪状态、当前任务与步骤、会话
指标、事件日志和唯一主动作。显式状态切换器覆盖 18 个状态:未连接、版本失配、空闲、
空轮询、试选、试选完成并释放手机、dry-run、dry-run 完成、真实第二趟围栏前、申请围栏、
围栏失败 / 响应不明、围栏后调和、待付款、结果不明、安全校验、外部支付、围栏前转人工、
连续失败停止。
- `docs/design/desk-device-settings.html`:显式 serial、USB / WiFi 标识、ADB 路径、web 地址、
假设备凭据、轮询 / 请求 / 真机步骤超时和连续失败阈值。覆盖默认、字段校验、检查中、
检查通过、web 失败、版本失配、保存成功、运行中冻结 8 个状态,以及未保存离开协议。
- 两页均使用 `Segoe UI Variable` / `Segoe UI` 回退、集中语义 token、浅色 / 深色 / 高对比
回退、`prefers-reduced-motion`、可见键盘焦点、`aria-live`、本地可复位假数据和内联 CSS / JS。
页面间只有本地相对链接;没有外部资源、生产地址请求或真实动作。
**HTML → PySide6 / Qt Widgets 交接映射**
| 原型项 | 核心交互契约 | 推荐 Qt Widgets 映射 | 信号 / 状态来源 |
| --- | --- | --- | --- |
| 应用壳与两个固定页签 | 固定同级页面;切换保留各页状态 | `QMainWindow` + 不可关闭的 `QTabWidget` | `currentChanged(int)`;稳定 page id,不用标题作业务身份 |
| web / 设备 / App 版本状态 | 三项全就绪才允许普通轮询;版本失配 fail closed | `QWidget` + 3 组 `QLabel`,状态色由语义 palette / 动态属性驱动 | `ReadinessViewModel.changed`;实际版本与证据版本由服务层提供 |
| 页面信息条 | 连接、失败、待人工和围栏状态占稳定位置,不抢焦点 | 语义 Banner `QWidget`(图形 + 标题 + 说明) | `state_changed` 经 GUI 线程队列连接;重要变化触发无障碍事件 |
| 唯一主动作 | 每个状态只暴露一个安全主动作;禁用旁边必须有原因 | 共享 `QAction` + `QPushButton` | `QAction.triggered`;enabled / text 由状态机单向派生 |
| 当前任务摘要 | 只读展示任务、规格、金额、租约和 submission | `QFormLayout` + 可复制的只读 `QLabel` / `QLineEdit` | 当前 execution 快照;金额保持十进制字符串 |
| 步骤列表 | 已完成 / 当前 / 等待不只靠颜色;稳定步骤 id | `QListView` + `QAbstractListModel` + `QStyledItemDelegate` | execution step event;模型更新必须在 GUI 线程 |
| 会话指标与事件日志 | 空任务不算失败;日志不含凭据、地址、手机号或页面全文 | 指标 `QLabel`;日志 `QTableView` + `QAbstractTableModel` | poll/session event;高频更新节流,记录使用稳定 event id |
| 设置表单 | 显式提交;字段错误就近显示,失败保留输入 | `QFormLayout`、`QLineEdit`、`QButtonGroup` + `QRadioButton`、`QSpinBox` | `textChanged` / `valueChanged` 只改草稿;`QValidator` 仅做格式层校验 |
| 保存与连接检查 | 保存是唯一主动作;检查只验证连接和安装,不打开 App | `QAction` + `QPushButton`;后台 worker + 页面进度 | `triggered` → worker;结果带 request id,过期结果忽略 |
| 运行中冻结 | 轮询中禁止换设备和保存参数 | 表单容器 / 相关 `QAction.setEnabled(False)` | session state;禁用原因用可见 `QLabel` 与 accessible description |
| 对话框与关闭协议 | Escape / 关闭使用同一取消路径;围栏后关闭不等于可以重来 | `QDialog` + `QDialogButtonBox` | `accepted` / `rejected`;关闭后焦点返回调用者 |
| 焦点与快捷键 | 自然 Tab 顺序、可见焦点、`Ctrl+S` 保存 | 标签 buddy、`QAction` + `QKeySequence.Save` | Qt 标准焦点链;原生实现重新用 Narrator / Inspect 验证 |
Qt 实现时不复制 DOM、CSS 或 JavaScript 状态对象。业务状态必须来自 web / execution 服务,
View 只渲染;I/O 离开 GUI 线程,通过 PySide6 `Signal` / `Slot` 回到 GUI 线程。PySide6 / Qt 的
精确版本要在 T-002 初始化后核对,版本敏感 API 在此任务中未作事实声明。
**验证证据**
- `python scripts/validate_agent_context.py`:通过(6 个任务路由,18 个有效仓库路径)。
- `git diff --check`:通过。
- Python 标准库 HTML 解析:两页可解析;`desk-execution.html` 39 个 id、
`desk-device-settings.html` 54 个 id,均无重复;除 `data:,` favicon 外无资源引用。
- 静态危险面扫描:未发现 `fetch`、`XMLHttpRequest`、WebSocket、外部脚本 / 图片 / iframe,
也未发现文案为「提交订单」「继续付款」「免密支付」「先用后付」「重试提交」的按钮。
- Chromium 本地逐页检查:最终控制台 0 error / 0 warning;网络面板只有当前本地 HTML 文档。
- 执行页 18 个状态、设置页 8 个状态逐项切换;围栏失败时主动作是「打开围栏核查说明」,
围栏后和结果不明时只显示同一 `submission_id` 的核查入口,危险按钮集合为空。
- 375 / 768 / 1024 / 1440 px 均无横向溢出;表单操作区与内容区在四个宽度下无覆盖。
1440 px 两页均做 full-page 视觉检查。
- 键盘路径检查到页面链接、主题、状态切换、按钮和表单字段,焦点轮廓可见;Enter 打开核查
对话框、Escape 关闭并把焦点还给调用按钮;表单提交聚焦第一个错误且保留输入,模拟异步
检查期间禁用保存,完成后恢复;未保存离开会打开确认对话框。
- 浏览器 accessibility snapshot 可识别 navigation、main、region、表单控件标签、按钮和状态
文本;深色主题已交互检查。`forced-colors` 与减少动画分支已静态检查,但不替代原生测试。
**未验证 / 待人工确认**
- 请人工确认:两个固定页签是否足够;执行页当前任务 / 日志的宽屏比例和紧凑页密度;
「开始 / 停止轮询」作为普通会话唯一主动作是否清楚;待人工、版本失配、围栏失败、围栏后、
结果不明与外部支付的严重度和文案是否足够明确。
- 请人工确认:设置页字段集合,以及轮询间隔、普通请求超时、真机步骤超时、连续失败阈值
是否应该允许用户配置。原型中的数字仅是假数据,不是产品默认值。
- T-103 真机取证后,必须回修 App 实际 / 已取证版本展示、可读字段和文案;本原型没有定义
任何拼多多页面判据、选择器、节点或已验证版本。
- 未验证原生标题栏、系统菜单、Snap Layouts、DPI / 多显示器、Qt palette / QSS、Windows
高对比、输入法、Narrator / UI Automation、线程、性能、打包与关闭真实后台任务。这些不能
由 HTML 证明,需在 T-002 及后续原生实现任务中重新验收。
- 本轮没有真机证据,也没有真实 web / ADB / API / 文件保存。人工确认前任务继续保持
`DOING`,不得自动改为 `DONE`。