Files
sunhpc-go/pkg/wizard/pages.go
2026-02-21 20:22:21 +08:00

367 lines
9.8 KiB
Go
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.
package wizard
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
)
// View 渲染视图
func (m model) View() string {
if m.done {
return successView()
}
if m.quitting {
return quitView()
}
if m.err != nil {
return errorView(m.err)
}
var page string
switch m.currentPage {
case PageAgreement:
page = m.agreementView()
case PageData:
page = m.dataView()
case PagePublicNetwork:
page = m.publicNetworkView()
case PageInternalNetwork:
page = m.internalNetworkView()
case PageDNS:
page = m.dnsView()
case PageSummary:
page = m.summaryView()
}
content := strings.Builder{}
content.WriteString(page)
content.WriteString("\n\n")
content.WriteString(progressView(m.currentPage, m.totalPages))
return containerStyle.Render(content.String())
}
// agreementView 协议页面
func (m model) agreementView() string {
title := titleStyle.Render("SunHPC 系统初始化向导")
subtitle := subTitleStyle.Render("请先阅读并同意以下协议")
agreement := agreementBox.Render(`
┌─────────────────────────────────────────────────────────────┐
│ SunHPC 软件许可协议 │
└─────────────────────────────────────────────────────────────┘
1. 许可授予
本软件授予您非独占、不可转让的使用许可。
2. 使用限制
- 不得用于非法目的
- 不得反向工程或反编译
- 不得移除版权标识
3. 免责声明
本软件按"原样"提供,不提供任何明示或暗示的保证。
4. 责任限制
在任何情况下,作者不对因使用本软件造成的任何损失负责。
5. 协议终止
如违反本协议条款,许可将自动终止。
───────────────────────────────────────────────────────────────
请仔细阅读以上条款,点击"接受"表示您同意并遵守本协议。
───────────────────────────────────────────────────────────────
`)
var acceptBtn, rejectBtn string
if m.agreementIdx == 0 {
rejectBtn = selectedButton.Render(">> 拒绝 <<")
acceptBtn = selectedButton.Render(" 同意 ")
} else {
rejectBtn = selectedButton.Render(" 拒绝 ")
acceptBtn = selectedButton.Render(">> 同意 <<")
}
buttonGroup := lipgloss.JoinHorizontal(
lipgloss.Center,
acceptBtn, " ", rejectBtn)
// ✅ 添加调试信息(确认 agreementIdx 的值)
// debugInfo := lipgloss.NewStyle().Foreground(lipgloss.Color("#888888")).
// Render(fmt.Sprintf("[DEBUG: idx=%d]", m.agreementIdx),)
hint := hintStyle.Render("使用 <- -> 或 Tab 选择,Enter 确认")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
agreement, "",
buttonGroup, "",
// debugInfo, "", // ✅ 显示调试信息
hint,
)
}
// dataView 数据接收页面
func (m model) dataView() string {
title := titleStyle.Render("集群基础配置")
subtitle := subTitleStyle.Render("请填写系统基本信息")
var inputs strings.Builder
for i, ti := range m.textInputs {
info := fmt.Sprintf("%-10s|", m.inputLabels[i])
input := inputBox.Render(info + ti.View())
inputs.WriteString(input + "\n")
}
buttons := m.renderNavButtons()
hint := hintStyle.Render("使用 Up/Down 或 Tab 切换、Enter 确认")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
inputs.String(), "",
buttons, "",
hint,
)
}
// publicNetworkView 公网设置页面
func (m model) publicNetworkView() string {
title := titleStyle.Render("公网配置")
subtitle := subTitleStyle.Render("请配置网络接口信息")
autoDetect := infoStyle.Render("[*] 自动检测网络接口: eth0, eth1, ens33")
var inputs strings.Builder
for i, ti := range m.textInputs {
info := fmt.Sprintf("%-10s|", m.inputLabels[i])
input := inputBox.Render(info + ti.View())
inputs.WriteString(input + "\n")
}
buttons := m.renderNavButtons()
hint := hintStyle.Render("使用 Up/Down 或 Tab 切换、Enter 确认")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
autoDetect, "",
inputs.String(), "",
buttons, "",
hint,
)
}
// internalNetworkView 内网配置页面
func (m model) internalNetworkView() string {
title := titleStyle.Render("内网配置")
subtitle := subTitleStyle.Render("请配置内网信息")
var inputs strings.Builder
for i, ti := range m.textInputs {
info := fmt.Sprintf("%-10s|", m.inputLabels[i])
input := inputBox.Render(info + ti.View())
inputs.WriteString(input + "\n")
}
buttons := m.renderNavButtons()
hint := hintStyle.Render("使用 Up/Down 或 Tab 切换、Enter 确认")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
inputs.String(), "",
buttons, "",
hint,
)
}
// dnsView DNS 配置页面
func (m model) dnsView() string {
title := titleStyle.Render("DNS 配置")
subtitle := subTitleStyle.Render("请配置 DNS 服务器")
var inputs strings.Builder
for i, ti := range m.textInputs {
info := fmt.Sprintf("%-10s|", m.inputLabels[i])
input := inputBox.Render(info + ti.View())
inputs.WriteString(input + "\n")
}
buttons := m.renderNavButtons()
hint := hintStyle.Render("使用 Up/Down 或 Tab 切换、Enter 确认")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
inputs.String(), "",
buttons, "",
hint,
)
}
// summaryView 总结页面
func (m model) summaryView() string {
title := titleStyle.Render("配置总结")
subtitle := subTitleStyle.Render("请确认以下配置信息")
summary := summaryBox.Render(fmt.Sprintf(`
+---------------------------------------------+
基本信息
+---------------------------------------------+
主机名:%-35s
国 家: %-31s
地 区:%-31s
时 区:%-38s
主 页:%-38s
+---------------------------------------------+
数据库
+---------------------------------------------+
地 址:%-38s
名 称:%-38s
软 件:%-33s
+---------------------------------------------+
公网配置
+---------------------------------------------+
接 口:%-38s
地 址: %-41s
掩 码:%-38s
网 关:%-38s
+---------------------------------------------+
内网配置
+---------------------------------------------+
接 口:%-38s
地 址: %-41s
掩 码:%-38s
+---------------------------------------------+
DNS
+---------------------------------------------+
主 DNS: %-37s
备 DNS: %-37s
+---------------------------------------------+
`,
m.config.Hostname,
m.config.Country,
m.config.Region,
m.config.Timezone,
m.config.HomePage,
m.config.DBAddress,
m.config.DBName,
m.config.DataAddress,
m.config.PublicInterface,
m.config.IPAddress,
m.config.Netmask,
m.config.Gateway,
m.config.InternalInterface,
m.config.InternalIP,
m.config.InternalMask,
m.config.DNSPrimary,
m.config.DNSSecondary,
))
var buttons string
if m.focusIndex == 0 {
buttons = selectedButton.Render("[>] 执行初始化") + " " + normalButton.Render("[ ] 取消")
} else {
buttons = normalButton.Render("[>] 执行初始化") + " " + selectedButton.Render("[ ] 取消")
}
hint := hintStyle.Render("使用 <- -> 或 Tab 选择Enter 确认")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
summary, "",
buttons, "",
hint,
)
}
// progressView 进度条
func progressView(current PageType, total int) string {
progress := ""
for i := 0; i < total; i++ {
if i < int(current) {
progress += "[+]"
} else if i == int(current) {
progress += "[-]"
} else {
progress += "[ ]"
}
if i < total-1 {
progress += " "
}
}
labels := []string{"协议", "数据", "公网", "内网", "DNS", "总结"}
label := labelStyle.Render(labels[current])
return progressStyle.Render(progress) + " " + label
}
// successView 成功视图
func successView() string {
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
successTitle.Render("初始化完成!"), "",
successMsg.Render("系统配置已保存,正在初始化..."), "",
hintStyle.Render("按任意键退出"),
))
}
// quitView 退出视图
func quitView() string {
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
errorTitle.Render("已取消"), "",
errorMsg.Render("初始化已取消,未保存任何配置"),
))
}
// errorView 错误视图
func errorView(err error) string {
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
errorTitle.Render("错误"), "",
errorMsg.Render(err.Error()), "",
hintStyle.Render("按 Ctrl+C 退出"),
))
}
// navButtons 导航按钮
func navButtons(m model, prev, next string) string {
var btns string
if m.currentPage == 0 {
btns = normalButton.Render(prev) + " " + selectedButton.Render(next)
} else {
btns = selectedButton.Render(prev) + " " + normalButton.Render(next)
}
return btns
}
func (m model) renderNavButtons() string {
var prevBtn, nextBtn string
switch m.focusType {
case FocusTypePrev:
// 焦点在"上一步"
prevBtn = selectedButton.Render("<< 上一步 >>")
nextBtn = normalButton.Render("下一步 >>")
case FocusTypeNext:
// 焦点在"下一步"
prevBtn = normalButton.Render("<< 上一步")
nextBtn = selectedButton.Render("<< 下一步 >>")
default:
// 焦点在输入框
prevBtn = normalButton.Render("<< 上一步")
nextBtn = normalButton.Render("下一步 >>")
}
return lipgloss.JoinHorizontal(
lipgloss.Center,
prevBtn,
" ",
nextBtn,
)
}