feat: add settings path actions

This commit is contained in:
QiuSW
2026-07-22 15:30:03 +08:00
parent 3203a65da5
commit e4dd261abe
4 changed files with 64 additions and 14 deletions
+1 -1
View File
@@ -27,7 +27,7 @@
| T-202 | 本地配置持久化和实例恢复 | T-101 | DONE | | T-202 | 本地配置持久化和实例恢复 | T-101 | DONE |
| T-203 | CLI 合约和本地事件推送 | T-103 | DONE | | T-203 | CLI 合约和本地事件推送 | T-103 | DONE |
| T-204 | UI 全状态验收与 Windows 打包 smoke | T-201,T-202,T-203 | DONE | | T-204 | UI 全状态验收与 Windows 打包 smoke | T-201,T-202,T-203 | DONE |
| T-205 | 设置路径字段增加 Label、选择和搜索操作 | T-201 | TODO | | T-205 | 设置路径字段增加 Label、选择和搜索操作 | T-201 | DONE |
## Backlog ## Backlog
+4 -4
View File
@@ -3,11 +3,11 @@
## 快照 ## 快照
- 日期:2026-07-22 - 日期:2026-07-22
- 阶段:Phase 2 产品外壳(T-201 至 T-204 已完成) - 阶段:Phase 2 产品外壳(T-201 至 T-205 已完成)
- 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-204 已完成 - 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-205 已完成
- UI:已接入 Gio v0.10.1 双页桌面壳,设置保存异步写入本地配置,启动时恢复设置和已保存实例;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter - UI:已接入 Gio v0.10.1 双页桌面壳;设置页四个路径字段均有 Label、输入框、选择按钮和搜索按钮,并提供操作反馈;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter
- 浏览器核心:设计参考来自 `D:\OPC\shop_helm\internal\platform\chrome`,尚未复制或接入本项目 - 浏览器核心:设计参考来自 `D:\OPC\shop_helm\internal\platform\chrome`,尚未复制或接入本项目
- blocker:无;下一个任务为 T-205(设置路径字段增加 Label、选择和搜索操作)。 - blocker:无;下一步可进入 BrowserManager application adapter 和真实 UI 交互接线。
## 当前目录 ## 当前目录
+5 -5
View File
@@ -3,7 +3,7 @@ id: T-205
title: 设置路径字段增加 Label、选择和搜索操作 title: 设置路径字段增加 Label、选择和搜索操作
phase: 2 phase: 2
deps: [T-201] deps: [T-201]
status: TODO status: DONE
created: 2026-07-22 created: 2026-07-22
owner: codex owner: codex
--- ---
@@ -28,8 +28,8 @@ owner: codex
## 执行记录 ## 执行记录
- 状态:TODO - 状态:DONE
- 变更:先建立任务文档和路线图记录。 - 变更:设置页四个路径字段统一增加 Label、输入框、“选择”和“搜索”按钮;每个操作使用独立的持久 Clickable,并在页面中显示文字反馈。
- 验证:待实现。 - 验证:`gofmt`、`go test ./...`、`go vet ./...`、`go build -o build/chub.exe ./cmd/chub` 均通过。
- 阻塞:无。 - 阻塞:无。
- 残余风险:原生选择器和真实搜索需要后续 platform adapter。 - 残余风险:当前选择/搜索按钮完成 UI 反馈,原生 Windows 文件选择器和真实磁盘搜索需要后续异步 platform adapter。
+54 -4
View File
@@ -48,6 +48,14 @@ type Shell struct {
backClick widget.Clickable backClick widget.Clickable
chromeKind widget.Clickable chromeKind widget.Clickable
edgeKind widget.Clickable edgeKind widget.Clickable
chromePick widget.Clickable
chromeSearch widget.Clickable
edgePick widget.Clickable
edgeSearch widget.Clickable
dataPick widget.Clickable
dataSearch widget.Clickable
logPick widget.Clickable
logSearch widget.Clickable
saveClick widget.Clickable saveClick widget.Clickable
cancelClick widget.Clickable cancelClick widget.Clickable
@@ -60,6 +68,7 @@ type Shell struct {
instanceDir widget.Editor instanceDir widget.Editor
instanceURL widget.Editor instanceURL widget.Editor
newBrowser string newBrowser string
pathFeedback string
list widget.List list widget.List
rows []InstanceRow rows []InstanceRow
@@ -187,6 +196,30 @@ func statusLabel(theme *material.Theme, status string) layout.Widget {
} }
func (s *Shell) settings(gtx layout.Context) layout.Dimensions { func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
for s.chromePick.Clicked(gtx) {
s.pathFeedback = "请选择 Chrome 可执行文件"
}
for s.chromeSearch.Clicked(gtx) {
s.pathFeedback = "正在搜索 Chrome 可执行文件…"
}
for s.edgePick.Clicked(gtx) {
s.pathFeedback = "请选择 Edge 可执行文件"
}
for s.edgeSearch.Clicked(gtx) {
s.pathFeedback = "正在搜索 Edge 可执行文件…"
}
for s.dataPick.Clicked(gtx) {
s.pathFeedback = "请选择默认 User Data Dir"
}
for s.dataSearch.Clicked(gtx) {
s.pathFeedback = "正在搜索默认 User Data Dir…"
}
for s.logPick.Clicked(gtx) {
s.pathFeedback = "请选择日志目录"
}
for s.logSearch.Clicked(gtx) {
s.pathFeedback = "正在搜索日志目录…"
}
for s.saveClick.Clicked(gtx) { for s.saveClick.Clicked(gtx) {
if s.onSave != nil { if s.onSave != nil {
s.onSave(SettingsState{ChromePath: s.chromePath.Text(), EdgePath: s.edgePath.Text(), DefaultDir: s.dataDir.Text(), LogDir: s.logDir.Text(), CloseOnExit: s.closeOnExit.Value}) s.onSave(SettingsState{ChromePath: s.chromePath.Text(), EdgePath: s.edgePath.Text(), DefaultDir: s.dataDir.Text(), LogDir: s.logDir.Text(), CloseOnExit: s.closeOnExit.Value})
@@ -199,13 +232,15 @@ func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
layout.Rigid(material.H4(s.theme, "设置").Layout), layout.Rigid(material.H4(s.theme, "设置").Layout),
layout.Rigid(material.Body1(s.theme, "配置浏览器可执行文件、默认目录和本地运行行为").Layout), layout.Rigid(material.Body1(s.theme, "配置浏览器可执行文件、默认目录和本地运行行为").Layout),
layout.Rigid(layout.Spacer{Height: unit.Dp(18)}.Layout), layout.Rigid(layout.Spacer{Height: unit.Dp(18)}.Layout),
layout.Rigid(material.Editor(s.theme, &s.chromePath, "Chrome 可执行文件").Layout), layout.Rigid(s.pathField("Chrome 可执行文件", &s.chromePath, &s.chromePick, &s.chromeSearch)),
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout), layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
layout.Rigid(material.Editor(s.theme, &s.edgePath, "Edge 可执行文件").Layout), layout.Rigid(s.pathField("Edge 可执行文件", &s.edgePath, &s.edgePick, &s.edgeSearch)),
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout), layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
layout.Rigid(material.Editor(s.theme, &s.dataDir, "默认 User Data Dir").Layout), layout.Rigid(s.pathField("默认 User Data Dir", &s.dataDir, &s.dataPick, &s.dataSearch)),
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout), layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
layout.Rigid(material.Editor(s.theme, &s.logDir, "日志目录").Layout), layout.Rigid(s.pathField("日志目录", &s.logDir, &s.logPick, &s.logSearch)),
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
layout.Rigid(material.Caption(s.theme, s.pathFeedback).Layout),
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout), layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
layout.Rigid(material.CheckBox(s.theme, &s.closeOnExit, "退出时关闭托管浏览器").Layout), layout.Rigid(material.CheckBox(s.theme, &s.closeOnExit, "退出时关闭托管浏览器").Layout),
layout.Rigid(layout.Spacer{Height: unit.Dp(16)}.Layout), layout.Rigid(layout.Spacer{Height: unit.Dp(16)}.Layout),
@@ -219,6 +254,21 @@ func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
) )
} }
func (s *Shell) pathField(label string, editor *widget.Editor, pick, search *widget.Clickable) layout.Widget {
return func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Inset{Right: unit.Dp(12)}.Layout(gtx, material.Body2(s.theme, label).Layout)
}),
layout.Flexed(1, material.Editor(s.theme, editor, "请输入或粘贴路径").Layout),
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
layout.Rigid(material.Button(s.theme, pick, "选择").Layout),
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
layout.Rigid(material.Button(s.theme, search, "搜索").Layout),
)
}
}
func (s *Shell) createInstance(gtx layout.Context) layout.Dimensions { func (s *Shell) createInstance(gtx layout.Context) layout.Dimensions {
for s.chromeKind.Clicked(gtx) { for s.chromeKind.Clicked(gtx) {
s.newBrowser = "Chrome" s.newBrowser = "Chrome"