优化环境安装进度提示

This commit is contained in:
user123
2026-01-30 19:40:58 +08:00
parent 7edb6fdc34
commit 099e9b88e4
3 changed files with 80 additions and 38 deletions

Binary file not shown.

View File

@@ -105,6 +105,13 @@ type actionResultMsg struct {
successMsg string successMsg string
} }
type installProgressMsg struct {
step string
err error
done bool
channel chan installProgressMsg
}
type progressMsg string type progressMsg string
type tickMsg time.Time type tickMsg time.Time
@@ -224,6 +231,25 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
return m, nil return m, nil
case installProgressMsg:
if msg.err != nil {
m.actionErr = msg.err
m.actionDone = true
m.progressMsg = fmt.Sprintf("安装失败: %v", msg.err)
return m, nil
}
if msg.done {
m.actionDone = true
m.progressMsg = "安装流程完成!"
m.envRefreshActive = true
m.envRefreshAttempt = 0
m.envRefreshMax = 5
m.envRefreshExpectInstalled = true
return m, envRefreshCmd(0)
}
m.progressMsg = msg.step
return m, waitForInstallProgress(msg.channel)
case envRefreshMsg: case envRefreshMsg:
if !m.envRefreshActive { if !m.envRefreshActive {
return m, nil return m, nil
@@ -298,7 +324,7 @@ func (m Model) handleMenuSelect() (tea.Model, tea.Cmd) {
m.actionDone = false m.actionDone = false
m.actionErr = nil m.actionErr = nil
m.progressMsg = "准备安装..." m.progressMsg = "准备安装..."
return m, runInstallFlowCmd return m, runInstallFlowCmd()
case 3: // 卸载 case 3: // 卸载
m.state = StateAction m.state = StateAction
m.actionType = ActionUninstall m.actionType = ActionUninstall
@@ -730,43 +756,66 @@ func runSaveConfigCmd(opts sys.ConfigOptions) tea.Cmd {
} }
} }
func runInstallFlowCmd() tea.Msg { func waitForInstallProgress(sub chan installProgressMsg) tea.Cmd {
// 线性流程: 检查Node -> 安装Node -> 检查Git -> 安装Git -> 配置NPM -> 安装OpenClaw -> 配置系统 return func() tea.Msg {
// 为简化状态,使用阻塞执行 msg, ok := <-sub
if !ok {
err := sys.InstallNode() return nil
if err != nil { }
return actionResultMsg{err: fmt.Errorf("node.js 安装失败: %v", err)} return msg
} }
}
err = sys.InstallGit() func runInstallFlowCmd() tea.Cmd {
if err != nil { ch := make(chan installProgressMsg)
return actionResultMsg{err: fmt.Errorf("git 安装失败: %v", err)}
}
err = sys.ConfigureGitProxy() go func() {
if err != nil { defer close(ch)
return actionResultMsg{err: fmt.Errorf("git 代理配置失败: %v", err)}
}
err = sys.ConfigureNpmMirror() // 1. Install Node
if err != nil { ch <- installProgressMsg{step: "正在安装 Node.js...", channel: ch}
return actionResultMsg{err: fmt.Errorf("npm 配置失败: %v", err)} if err := sys.InstallNode(); err != nil {
} ch <- installProgressMsg{err: fmt.Errorf("node.js 安装失败: %v", err), channel: ch}
return
}
err = sys.InstallOpenclawNpm("latest") // 2. Install Git
if err != nil { ch <- installProgressMsg{step: "正在安装 Git...", channel: ch}
return actionResultMsg{err: fmt.Errorf("openclaw 安装失败: %v", err)} if err := sys.InstallGit(); err != nil {
} ch <- installProgressMsg{err: fmt.Errorf("git 安装失败: %v", err), channel: ch}
return
}
_, err = sys.EnsureOnPath() // 3. Configure Git Proxy
if err != nil { ch <- installProgressMsg{step: "正在配置 Git 代理...", channel: ch}
// 非致命错误 if err := sys.ConfigureGitProxy(); err != nil {
} ch <- installProgressMsg{err: fmt.Errorf("git 代理配置失败: %v", err), channel: ch}
return
}
sys.RunDoctor() // 4. Configure NPM Mirror
ch <- installProgressMsg{step: "正在配置 NPM 镜像...", channel: ch}
if err := sys.ConfigureNpmMirror(); err != nil {
ch <- installProgressMsg{err: fmt.Errorf("npm 配置失败: %v", err), channel: ch}
return
}
return actionResultMsg{err: nil} // 5. Install OpenClaw
ch <- installProgressMsg{step: "正在安装 OpenClaw...", channel: ch}
if err := sys.InstallOpenclawNpm("latest"); err != nil {
ch <- installProgressMsg{err: fmt.Errorf("openclaw 安装失败: %v", err), channel: ch}
return
}
// 6. Finalize
ch <- installProgressMsg{step: "正在配置环境...", channel: ch}
sys.EnsureOnPath()
sys.RunDoctor()
ch <- installProgressMsg{done: true, channel: ch}
}()
return waitForInstallProgress(ch)
} }
func tickCmd() tea.Cmd { func tickCmd() tea.Cmd {

View File

@@ -11,18 +11,11 @@ import (
func main() { func main() {
p := tea.NewProgram(ui.InitialModel()) p := tea.NewProgram(ui.InitialModel())
m, err := p.Run() if _, err := p.Run(); err != nil {
if err != nil {
fmt.Printf("启动失败: %v\n", err) fmt.Printf("启动失败: %v\n", err)
os.Exit(1) os.Exit(1)
} }
if model, ok := m.(ui.Model); ok {
if model.DidStartGateway {
fmt.Println("Web 控制台: http://127.0.0.1:18789/")
}
}
fmt.Println("\n按 Enter 键退出...") fmt.Println("\n按 Enter 键退出...")
fmt.Scanln() fmt.Scanln()
} }