优化环境安装进度提示
This commit is contained in:
Binary file not shown.
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user