diff --git a/docs/02-requirements.md b/docs/02-requirements.md index 49406bc..52d6976 100644 --- a/docs/02-requirements.md +++ b/docs/02-requirements.md @@ -15,7 +15,7 @@ | BR-011 | Chub 启动的 Chrome/Edge 必须启用仅限 loopback 的本地 CDP;端口从设置的起始端口分配,空值默认 9666。 | P1 | | BR-012 | 同一 user data dir 被外部浏览器占用时,只能在其 CDP 端点可验证时关联为外部实例;不得接管生命周期。 | P1 | | BR-013 | 用户可以刷新已保存实例的状态,并编辑未运行实例的名称、浏览器类型、user data dir 和启动 URL;刷新和编辑不得扩大到未授权的浏览器进程。 | P1 | -| BR-014 | 用户可以维护无认证代理配置,并在创建或编辑实例时选择代理;代理认证信息不得保存、记录或进入启动参数。 | P1 | +| BR-014 | 用户可以在完整代理地址下拉框中维护无认证代理,并在创建或编辑实例时选择代理;代理认证信息不得保存、记录或进入启动参数。 | P1 | | BR-015 | GUI 实例主操作在 Chub 托管运行态提供优雅停止、在可启动状态提供启动;外部关联或未知外部实例不得获得生命周期控制。 | P1 | ## 验收标准 @@ -33,6 +33,7 @@ - 刷新仅检查 Chub 已保存的实例;任务执行中不可重复触发,过期结果不得覆盖已经删除或编辑后的记录。 - 实例编辑支持保存、取消和 Escape;有未保存修改时必须先确认,运行中或外部关联实例不能修改浏览器类型或 user data dir。 - 代理仅接受无认证的 `scheme://host:port` 端点。删除仍被实例引用的代理必须被拒绝;实例保存后按稳定代理 ID 解析最新端点。 +- 设置页默认代理输入为空;选择下拉项后回填完整地址,保存更新当前项、未选择时新建。删除未引用项须经确认,确认取消或引用保护不能改变任何实例选择。 - 受管运行实例点击主操作后进入关闭中,成功退出后恢复启动入口;停止失败不自动强制终止,也绝不影响其他 Chrome/Edge。 ## 不做 diff --git a/docs/06-tasks.md b/docs/06-tasks.md index 3fe59b3..fd08167 100644 --- a/docs/06-tasks.md +++ b/docs/06-tasks.md @@ -41,6 +41,7 @@ | T-303 | 实例状态刷新与编辑对话框 | T-302 | DONE | | T-304 | 代理配置库、实例选择与安全启动参数传递 | T-303 | DONE | | T-305 | GUI 受管实例优雅停止与启停状态机 | T-304 | DONE | +| T-306 | 精简代理下拉编辑与实例行安全操作布局 | T-304,T-305 | DOING | ## Backlog diff --git a/docs/07-user-stories.md b/docs/07-user-stories.md index 495ba36..3d50ffd 100644 --- a/docs/07-user-stories.md +++ b/docs/07-user-stories.md @@ -10,7 +10,7 @@ | US-006 | 用户可以通过 CLI/API 查询、启动和关闭实例。 | P1 | | US-007 | 用户可以看到实例关联的本地调试端口;同目录外部浏览器已启用调试时,Chub 只关联并展示状态。 | P1 | | US-008 | 用户可以刷新已保存实例的运行状态,并通过对话框编辑非运行实例的基本配置而不影响其他浏览器。 | P1 | -| US-009 | 用户可以在设置中维护无认证代理,并在新建或编辑实例时从下拉选择器选择代理。 | P1 | +| US-009 | 用户可以在设置中通过完整代理地址下拉框维护无认证代理,并在新建或编辑实例时从下拉选择器选择代理。 | P1 | | US-010 | 用户可以通过实例行的同一主操作启动或优雅停止 Chub 托管的浏览器,而不会关闭外部浏览器。 | P1 | ## 验收场景 @@ -37,7 +37,7 @@ CLI/API 返回稳定错误码和结构化数据;未知 PID、身份不匹配 ### US-009 代理选择 -给定用户在设置中保存的无认证代理,创建和编辑表单可从“无代理”或已命名代理中选择。保存后实例仅关联代理 ID;启动时使用该 ID 的最新端点。含用户名、密码或 URL 路径的端点被拒绝,仍被引用的代理不能删除。 +给定用户在设置中保存的无认证代理,设置下拉框和创建/编辑表单均展示完整地址。设置页默认输入为空;选择项会回填地址,保存会更新当前项或在未选择时新建。实例仅关联代理 ID;启动时使用该 ID 的最新端点。含用户名、密码或 URL 路径的端点被拒绝,仍被引用的代理不能删除;删除未引用项前要求确认。 ### US-010 受管实例启停 diff --git a/docs/08-interaction-checklist.md b/docs/08-interaction-checklist.md index f1d0b3e..4627589 100644 --- a/docs/08-interaction-checklist.md +++ b/docs/08-interaction-checklist.md @@ -9,8 +9,8 @@ | IX-005 | 设置 | 默认路径、日志、数据目录和远程调试起始端口 | 保存成功、路径无效、端口无效、权限拒绝 | P1 | | IX-006 | 本地 CDP 启动 | 从起始端口分配、校验端点、展示实际端口 | 分配中、已关联、端口冲突、端点失效、外部不接管 | P1 | | IX-007 | 实例刷新与编辑 | F5/刷新、双击/Enter/编辑图标、目录选择、保存/取消/Escape | 空闲、刷新中、部分失败、字段错误、脏表单、只读运行态、保存成功 | P1 | -| IX-008 | 代理设置与选择器 | 新增、编辑、删除代理;创建/编辑实例选择代理 | 空列表、无代理、格式错误、重复名称、被引用删除、保存成功 | P1 | -| IX-009 | 实例主启停操作 | 启动图标、停止图标、外部重新检测 | 已退出、启动中、托管运行、停止中、失败恢复、外部关联 | P1 | +| IX-008 | 代理设置与选择器 | 完整地址下拉选择、新增/更新、删除确认;创建/编辑实例选择代理 | 空列表、无代理、格式错误、重复地址、删除取消、被引用删除、保存成功 | P1 | +| IX-009 | 实例主启停操作 | 主操作、编辑、删除的固定顺序与间距;启动图标、停止图标、外部重新检测 | 已退出、启动中、托管运行、停止中、失败恢复、外部关联 | P1 | ## 通用规则 @@ -23,5 +23,5 @@ - 实例列表使用外层边框、文字状态和图标区分归属;端口为空时显示“—”,外部关联时操作区不显示关闭或重启。 - 刷新和编辑是独立命令:刷新为只读状态检查,编辑只保存配置;两者均不接管外部实例。F5 与刷新按钮共用一个去重命令。 - 双击不是唯一入口:单击只选择行,Enter 和编辑图标打开对话框。打开后焦点位于名称,关闭后返回调用行;有未保存编辑时 Escape 先请求确认。 -- 代理选择器必须提供“无代理”和命名项,能用键盘选择;代理端点只展示已校验的无认证 `scheme://host:port`,删除有引用的项时保持当前表单与实例选择不变。 -- 实例主操作根据归属和状态切换启动、停止、重新检测或禁用。停止中禁止重复请求;停止失败恢复原状态并保留焦点。外部关联不显示停止入口。 +- 代理选择器必须提供“无代理”和完整地址项,能用键盘选择;设置页默认输入为空,选择项回填地址。删除前先确认完整地址;有引用时保持当前选择、输入与实例选择不变。 +- 实例主操作根据归属和状态切换启动、停止、重新检测或禁用,并固定排在编辑和删除之前。停止中禁止重复请求;停止失败恢复原状态并保留焦点。外部关联不显示停止入口;行内图标间距与命中区必须避免误操作。 diff --git a/docs/current-state.md b/docs/current-state.md index 52009ba..116fa04 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -3,11 +3,11 @@ ## 快照 - 日期:2026-07-25 -- 阶段:Phase 3 真实实例操作(T-305、T-304、T-303、T-302、T-301 已完成;T-201 至 T-208 已完成) +- 阶段:Phase 3 真实实例操作(T-306 进行中;T-305、T-304、T-303、T-302、T-301 已完成;T-201 至 T-208 已完成) - 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、loopback CDP 端口分配与端点校验、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-208、T-301 至 T-303 已完成 - UI:Gio 双页 Shell 使用左侧“实例/设置”导航;实例页以等宽“新建实例 / 刷新实例状态”命令区开始,窄内容区自动堆叠。列表固定显示实例名称、浏览器类型、用户数据目录、调试端口、状态和紧凑编辑/启动/停止/删除图标,并以外层边框和表头分隔组织。主操作在已退出时启动,在 Chub 托管运行或调试不可用时显示停止,在启动/停止中禁用,在外部关联、外部占用或未知占用时仅重新检测;优雅停止通过后台 adapter 验证 registry 的 PID/profile 身份并等待其释放,绝不按进程名关闭或接管外部 Chrome/Edge。刷新通过后台回调只检查已保存实例,以配置快照丢弃编辑或删除后的过期结果;它结合 Chub registry、指定 profile 的外部占用证据和 loopback CDP 端点更新状态,但不扫描、接管或关闭其他 Chrome/Edge。双击、Enter 或编辑图标打开实例编辑弹层,支持名称、浏览器类型、User Data Dir、启动 URL、代理选择和只读实际端口;保存保留未公开启动选项,Escape 对脏表单先请求确认,活跃/外部关联实例锁定身份约束字段。设置页可维护名称加无认证端点的代理库,删除仍被实例引用的代理会被拒绝。启动通过异步回调接到 Windows 浏览器启动器:未占用目录从已保存的起始端口(空值默认 9666)选择 loopback CDP 端口,并在启动时按已选代理 ID 解析最新的 `--proxy-server` 参数;同目录外部浏览器只有在 `DevToolsActivePort` 与 CDP 端点可验证时才显示“外部已关联”,且不会接管其生命周期。删除使用确认弹层,只删除 Chub 实例配置而不删除 User Data Dir。新建、编辑和删除实例会保存到本地配置;四个设置路径有独立异步可取消搜索,切换页面后输入和任务状态保留;新建实例表单使用 Label、Windows 原生目录选择器和 Chrome/Edge RadioButton;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter - 浏览器核心:设计参考来自 `D:\OPC\shop_helm\internal\platform\chrome`,尚未复制或接入本项目 -- blocker:无;Phase 3 的当前 GUI 启动、代理、刷新、编辑、删除和受管实例优雅停止已闭环。下一步可按 Backlog 决策 CLI BrowserManager adapter、重启/强制关闭确认或 CDP tab/window 管理。 +- blocker:无;当前优先将代理设置改为完整地址下拉编辑并调整实例行操作顺序、间距与代理删除确认(T-306)。 ## 当前目录 diff --git a/docs/tasks/T-306.md b/docs/tasks/T-306.md new file mode 100644 index 0000000..fe5371e --- /dev/null +++ b/docs/tasks/T-306.md @@ -0,0 +1,38 @@ +--- +id: T-306 +title: 精简代理下拉编辑与实例行安全操作布局 +phase: 3 +deps: [T-304, T-305] +status: DOING +created: 2026-07-25 +owner: codex +--- + +## 需求与背景 + +设置页的代理管理需要从“名称加列表行编辑”简化为单一选择器和地址输入。用户需要在下拉框中直接识别完整代理地址,选择后可编辑,未选择时可新增。实例列表需要把高频主操作放在第一位,并增加操作间距以降低误点风险。 + +## 方案与边界 + +- 设置页使用“已保存代理”单选下拉框、单一“代理地址”输入框,以及同一行的“保存代理 / 删除代理”按钮。默认不选任何代理且输入框为空;选择已有项会回填其地址,修改后保存更新同一稳定 `proxyId`,未选择时保存创建新项。 +- UI 只展示完整、已规范化的无认证 `scheme://host:port` 地址。配置与实例关联继续使用稳定 `proxyId`,不以地址字符串作为关联键;为保持已有 JSON 兼容,新增或改写时内部名称同步为地址但不再作为 UI 字段。 +- 保存前拒绝认证信息、非法地址和规范化后重复地址。保存成功保留选中项和输入内容,并通过非模态反馈说明其只影响后续启动。 +- 删除仅针对已选代理,先显示带完整地址的确认对话框;Escape 和取消不做更改,初始焦点在取消。若仍被实例引用,则不打开可执行删除确认,改为说明引用数量并保持选择与输入不变。 +- 新建和编辑实例统一使用同一代理选择器,展示完整地址与“无代理”,只保存 `proxyId`。运行中实例改代理只影响下次启动。 +- 实例行操作顺序固定为“启动/停止/重新检测 → 编辑 → 删除”。图标按钮有至少 8epx 间隔与独立 36–40epx 命中区;删除继续使用危险色和确认弹层。单击行只选中,行内操作不触发行默认编辑。 + +## 验收要点 + +- 设置页初始代理输入为空;下拉项显示完整地址。选择、修改、保存、新增、清空选择、格式错误和重复地址均有可恢复反馈。 +- 删除未引用代理时先展示“删除代理?”确认,包含代理地址、取消和删除按钮;确认成功后下拉框和输入框清空,焦点返回下拉框。引用中代理不可删除且不会改变任何实例选择。 +- 新建和编辑实例的代理选择器展示完整地址;保存和重启后仍关联同一 `proxyId`,地址更新后下一次启动使用新地址。 +- 行操作视觉和键盘顺序为主操作、编辑、删除;各目标互不重叠,删除与相邻操作有更大间隔,启动/停止状态机和外部实例不接管边界保持不变。 +- 覆盖空代理库、选择、地址规范化、重复值、删除取消/确认/引用保护、编辑脏状态、操作顺序、窄窗口、键盘 Escape/Enter 与焦点恢复。 +- `gofmt`、`go test ./...`、`go vet ./...`、`go build -o build/chub.exe ./cmd/chub`、`scripts/smoke-browser.ps1` 与 `scripts/smoke-windows.ps1` 通过。 + +## 执行记录 + +- 状态:DOING +- 变更:待实现。 +- 验证:待执行。 +- 阻塞:无。 diff --git a/docs/ui/browser-manager.html b/docs/ui/browser-manager.html index b1ea3a1..dc7ac48 100644 --- a/docs/ui/browser-manager.html +++ b/docs/ui/browser-manager.html @@ -122,9 +122,9 @@ .status.associated { color: var(--warning); background: var(--warning-soft); } .status.occupied { color: var(--warning); background: var(--warning-soft); } .status.exited { color: var(--muted); background: var(--surface-3); } - .row-actions { display: flex; justify-content: flex-end; gap: 6px; opacity: .7; } + .row-actions { display: flex; justify-content: flex-end; gap: 10px; opacity: .7; } tr:hover .row-actions, tr.selected .row-actions { opacity: 1; } - .row-actions button { background: transparent; color: var(--muted); padding: 6px 8px; border-radius: 6px; } + .row-actions button { background: transparent; color: var(--muted); padding: 8px 10px; border-radius: 6px; } .row-actions button:hover { color: var(--accent-strong); background: var(--accent-soft); } .table-footer { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; color: var(--muted); font-size: 12px; } .drawer-backdrop { position: fixed; inset: 0; background: rgba(16, 24, 40, .28); z-index: 10; opacity: 0; pointer-events: none; transition: opacity .16s ease; } @@ -262,7 +262,7 @@
新建实例时作为默认建议路径;不会移动或删除已有 profile。
日志仅保存必要诊断信息,并过滤敏感参数。
-

代理

仅保存无认证代理;名称可在实例表单中选择。

支持 http、https、socks4、socks5 的 scheme://host:port;不允许用户名、密码或路径。
+

代理

仅保存无认证代理。下拉框、实例创建和编辑均展示完整地址。

选择后会回填地址;选择“新建”会清空输入框。
支持 http、https、socks4、socks5 的 scheme://host:port;不允许用户名、密码或路径。
新建代理:填写地址后保存。
@@ -276,6 +276,7 @@

关闭浏览器实例?

将请求浏览器正常退出。未保存的网页内容由浏览器自行处理。

编辑实例

修改下次启动使用的保存配置。

用于在实例列表中识别此浏览器环境。
浏览器类型
必须是绝对路径;同一目录不能被多个实例同时使用。
仅支持 http/https;留空时启动浏览器默认页。
选择已保存的无认证代理;修改后下次启动生效。
实际端口由全局起始端口在启动时分配,不能在此固定。

放弃未保存的更改?

可以先保存配置,或放弃本次编辑并关闭对话框。

+

删除代理?