Tui 重构代码逻辑

This commit is contained in:
2026-02-27 22:52:15 +08:00
parent 3a5f5ddd5d
commit d4e214fe23
8 changed files with 934 additions and 718 deletions

View File

@@ -1,12 +1,14 @@
package wizard
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
)
var split_line = splitlineStyle.Render(
"───────────────────────────────────────────────────────────────")
// View 渲染视图
func (m model) View() string {
if m.done {
@@ -19,38 +21,39 @@ func (m model) View() string {
return errorView(m.err)
}
var page string
var pageContent string
switch m.currentPage {
case PageAgreement:
page = m.agreementView()
pageContent = renderLicensePage(m)
case PageData:
page = m.dataView()
pageContent = renderDataInfoPage(m)
case PagePublicNetwork:
page = m.publicNetworkView()
pageContent = renderPublicNetworkPage(m)
case PageInternalNetwork:
page = m.internalNetworkView()
pageContent = renderInternalNetworkPage(m)
case PageDNS:
page = m.dnsView()
pageContent = renderDNSPage(m)
case PageSummary:
page = m.summaryView()
pageContent = renderSummaryPage(m)
default:
pageContent = appStyle.Render("无效页面")
}
content := strings.Builder{}
content.WriteString(page)
content.WriteString("\n\n")
content.WriteString(progressView(m.currentPage, m.totalPages))
return containerStyle.Render(content.String())
return appStyle.Render(pageContent)
}
// agreementView 协议页面
func (m model) agreementView() string {
func makeRow(label, value string) string {
return lipgloss.JoinHorizontal(lipgloss.Left,
labelStyle.Render(label+":"),
valueStyle.Render(value),
)
}
func renderLicensePage(m model) string {
title := titleStyle.Render("SunHPC Software License Agreement")
agreement := agreementBox.Render(`
─────────────────────────────────────────────────────────────
│ SunHPC License Agreement │
└─────────────────────────────────────────────────────────────┘
licenseText := `
───────────────────────────────────────────────────────────────
1. License Grant
This software grants you a non-exclusive, non-transferable
license to use it.
@@ -69,288 +72,265 @@ func (m model) agreementView() string {
PLEASE READ THE ABOVE TERMS CAREFULLY AND CLICK "ACCEPT"
TO AGREE AND FOLLOW THIS AGREEMENT.
───────────────────────────────────────────────────────────────
`)
`
var acceptBtn, rejectBtn string
if m.agreementIdx == 0 {
rejectBtn = selectedButton.Render(">> Reject <<")
acceptBtn = " Accept "
} else {
rejectBtn = " Reject "
acceptBtn = selectedButton.Render(">> Accept <<")
}
buttonGroup := lipgloss.JoinHorizontal(
lipgloss.Center,
acceptBtn, " ", rejectBtn)
pageComps := m.pageComponents[PageAgreement]
acceptBtn := pageComps["accept_btn"].View()
rejectBtn := pageComps["reject_btn"].View()
// ✅ 添加调试信息(确认 agreementIdx 的值)
// debugInfo := lipgloss.NewStyle().Foreground(lipgloss.Color("#888888")).
// Render(fmt.Sprintf("[DEBUG: idx=%d]", m.agreementIdx),)
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
return lipgloss.JoinVertical(lipgloss.Center,
hint := hintStyle.Render("Use Left/Right OR Tab Change,Enter Confirm")
pageContent := lipgloss.JoinVertical(lipgloss.Center,
title, "",
agreement, "",
buttonGroup, "",
// debugInfo, "", // ✅ 显示调试信息
licenseTextStyle.Render(licenseText),
lipgloss.JoinHorizontal(lipgloss.Center, acceptBtn, rejectBtn),
hint,
)
return appStyle.Render(pageContent)
}
// dataView 数据接收页面
func (m model) dataView() string {
title := titleStyle.Render("Cluster Information")
// ---------------- 页2基础信息页渲染 ----------------
func renderDataInfoPage(m model) string {
pageComps := m.pageComponents[PageData]
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")
}
// 拼接基础信息表单
formContent := lipgloss.JoinVertical(lipgloss.Center,
split_line,
makeRow("Homepage", pageComps["Homepage_input"].View()),
split_line,
makeRow("Hostname", pageComps["Hostname_input"].View()),
split_line,
makeRow("Country", pageComps["Country_input"].View()),
split_line,
makeRow("Region", pageComps["Region_input"].View()),
split_line,
makeRow("Timezone", pageComps["Timezone_input"].View()),
split_line,
makeRow("DBPath", pageComps["DBPath_input"].View()),
split_line,
makeRow("Software", pageComps["Software_input"].View()),
split_line,
)
buttons := m.renderNavButtons()
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
inputs.String(), "",
buttons, "",
// 按钮区域
btnArea := lipgloss.JoinHorizontal(
lipgloss.Center,
pageComps["next_btn"].View(),
pageComps["prev_btn"].View(),
)
hint := hintStyle.Render("Use Left/Right OR Tab Change,Enter Confirm")
// 页面整体
pageContent := lipgloss.JoinVertical(
lipgloss.Center,
titleStyle.Render("基础信息配置(页2/6)"),
formContent,
btnArea,
hint,
)
return appStyle.Render(pageContent)
}
// publicNetworkView 公网设置页面
func (m model) publicNetworkView() string {
title := titleStyle.Render("Public Network Configuration")
func renderPublicNetworkPage(m model) string {
pageComps := m.pageComponents[PagePublicNetwork]
// 拼接公网网络表单
formContent := lipgloss.JoinVertical(lipgloss.Center,
split_line,
makeRow("PublicInterface", pageComps["PublicInterface_input"].View()),
split_line,
makeRow("PublicIPAddress", pageComps["PublicIPAddress_input"].View()),
split_line,
makeRow("PublicNetmask", pageComps["PublicNetmask_input"].View()),
split_line,
makeRow("PublicGateway", pageComps["PublicGateway_input"].View()),
split_line,
)
// 按钮区域
btnArea := lipgloss.JoinHorizontal(
lipgloss.Center,
pageComps["next_btn"].View(),
pageComps["prev_btn"].View(),
)
networkInterfaces := getNetworkInterfaces()
autoDetect := infoStyle.Render(
"[*] Auto Detect Network Interfaces: " + strings.Join(networkInterfaces, ", "))
"[*] Auto Detect Interfaces: " + strings.Join(networkInterfaces, ", "))
var inputs strings.Builder
for i, ti := range m.textInputs {
info := fmt.Sprintf("%-20s|", m.inputLabels[i])
input := inputBox.Render(info + ti.View())
inputs.WriteString(input + "\n")
}
hint := hintStyle.Render("Use Left/Right OR Tab Change,Enter Confirm")
buttons := m.renderNavButtons()
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
autoDetect, "",
inputs.String(), "",
buttons, "",
// 页面整体
pageContent := lipgloss.JoinVertical(
lipgloss.Center,
titleStyle.Render("公网网络配置(页3/6)"),
autoDetect,
formContent,
btnArea,
hint,
)
return appStyle.Render(pageContent)
}
// internalNetworkView 内网配置页面
func (m model) internalNetworkView() string {
title := titleStyle.Render("Internal Network Configuration")
func renderInternalNetworkPage(m model) string {
pageComps := m.pageComponents[PageInternalNetwork]
networkInterfaces := getNetworkInterfaces()
autoDetect := infoStyle.Render(
"[*] Auto Detect Network Interfaces: " + strings.Join(networkInterfaces, ", "))
// 拼接内网网络表单
formContent := lipgloss.JoinVertical(lipgloss.Center,
split_line,
makeRow("InternalInterface", pageComps["InternalInterface_input"].View()),
split_line,
makeRow("InternalIPAddress", pageComps["InternalIPAddress_input"].View()),
split_line,
makeRow("InternalNetmask", pageComps["InternalNetmask_input"].View()),
split_line,
)
var inputs strings.Builder
for i, ti := range m.textInputs {
info := fmt.Sprintf("%-20s|", m.inputLabels[i])
input := inputBox.Render(info + ti.View())
inputs.WriteString(input + "\n")
}
// 按钮区域
btnArea := lipgloss.JoinHorizontal(
lipgloss.Center,
pageComps["next_btn"].View(),
pageComps["prev_btn"].View(),
)
buttons := m.renderNavButtons()
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
hint := hintStyle.Render("Use Left/Right OR Tab Change,Enter Confirm")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
autoDetect, "",
inputs.String(), "",
buttons, "",
// 页面整体
pageContent := lipgloss.JoinVertical(
lipgloss.Center,
titleStyle.Render("内网网络配置(页4/6)"),
formContent,
btnArea,
hint,
)
return appStyle.Render(pageContent)
}
// dnsView DNS 配置页面
func (m model) dnsView() string {
title := titleStyle.Render("DNS Configuration")
func renderDNSPage(m model) string {
pageComps := m.pageComponents[PageDNS]
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")
}
// 拼接 DNS 表单
formContent := lipgloss.JoinVertical(lipgloss.Center,
split_line,
makeRow("Pri DNS", pageComps["Pri_DNS_input"].View()),
split_line,
makeRow("Sec DNS", pageComps["Sec_DNS_input"].View()),
split_line,
)
buttons := m.renderNavButtons()
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
// 按钮区域
btnArea := lipgloss.JoinHorizontal(
lipgloss.Center,
pageComps["next_btn"].View(),
pageComps["prev_btn"].View(),
)
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
inputs.String(), "",
buttons, "",
hint := hintStyle.Render("Use Left/Right OR Tab Change,Enter Confirm")
// 页面整体
pageContent := lipgloss.JoinVertical(
lipgloss.Center,
titleStyle.Render("DNS 配置(页5/6)"),
formContent,
btnArea,
hint,
)
return appStyle.Render(pageContent)
}
// summaryView 总结页面
func (m model) summaryView() string {
title := titleStyle.Render("Summary")
subtitle := subTitleStyle.Render("Please confirm the following configuration information")
func renderSummaryPage(m model) string {
pageComps := m.pageComponents[PageSummary]
summary := summaryBox.Render(fmt.Sprintf(`
+----------------------------------------------------+
Basic Information
+----------------------------------------------------+
Homepage : %-38s
Hostname : %-35s
Country : %-31s
Region : %-31s
Timezone : %-38s
Homepage : %-38s
+----------------------------------------------------+
Database Configuration
+----------------------------------------------------+
Database Path : %-38s
Software : %-33s
+----------------------------------------------------+
Public Network Configuration
+----------------------------------------------------+
Public Interface : %-38s
Public IP : %-41s
Public Netmask : %-38s
Public Gateway : %-38s
+----------------------------------------------------+
Internal Network Configuration
+----------------------------------------------------+
Internal Interface: %-38s
Internal IP : %-41s
Internal Netmask : %-38s
+----------------------------------------------------+
DNS Configuration
+----------------------------------------------------+
Primary DNS : %-37s
Secondary DNS : %-37s
+----------------------------------------------------+
`,
m.config.HomePage,
m.config.Hostname,
m.config.Country,
m.config.Region,
m.config.Timezone,
m.config.HomePage,
m.config.DBAddress,
m.config.DataAddress,
m.config.PublicInterface,
m.config.PublicIPAddress,
m.config.PublicNetmask,
m.config.PublicGateway,
m.config.InternalInterface,
m.config.InternalIPAddress,
m.config.InternalNetmask,
m.config.DNSPrimary,
m.config.DNSSecondary,
))
// 拼接 Summary 表单
formContent := lipgloss.JoinVertical(lipgloss.Center,
split_line,
makeRow("Hostname", m.config.Hostname),
split_line,
makeRow("Country", m.config.Country),
split_line,
makeRow("Region", m.config.Region),
split_line,
makeRow("Timezone", m.config.Timezone),
split_line,
makeRow("Homepage", m.config.HomePage),
split_line,
makeRow("DBPath", m.config.DBAddress),
split_line,
makeRow("Software", m.config.Software),
split_line,
makeRow("PublicInterface", m.config.PublicInterface),
split_line,
makeRow("PublicIPAddress", m.config.PublicIPAddress),
split_line,
makeRow("PublicNetmask", m.config.PublicNetmask),
split_line,
makeRow("PublicGateway", m.config.PublicGateway),
split_line,
makeRow("InternalInterface", m.config.InternalInterface),
split_line,
makeRow("InternalIPAddress", m.config.InternalIPAddress),
split_line,
makeRow("InternalNetmask", m.config.InternalNetmask),
split_line,
makeRow("Pri DNS", m.config.DNSPrimary),
split_line,
makeRow("Sec DNS", m.config.DNSSecondary),
split_line,
)
var buttons string
if m.focusIndex == 0 {
buttons = selectedButton.Render("[>] Start Initialization") + " " + normalButton.Render("[ ] Cancel")
} else {
buttons = normalButton.Render("[>] Start Initialization") + " " + selectedButton.Render("[ ] Cancel")
}
// 按钮区域
btnArea := lipgloss.JoinHorizontal(
lipgloss.Center,
pageComps["confirm_btn"].View(),
pageComps["cancel_btn"].View(),
)
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
hint := hintStyle.Render("Use Left/Right OR Tab Change,Enter Confirm")
return lipgloss.JoinVertical(lipgloss.Center,
title, "",
subtitle, "",
summary, "",
buttons, "",
// 页面整体
pageContent := lipgloss.JoinVertical(
lipgloss.Center,
titleStyle.Render("确认信息(页6/6)"),
formContent,
btnArea,
hint,
)
return appStyle.Render(pageContent)
}
// 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{"License", "Data", "Network", "Network", "DNS", "Summary"}
label := labelStyle.Render(labels[current])
return progressStyle.Render(progress) + " " + label
}
// successView 成功视图
func successView() string {
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
content := lipgloss.JoinVertical(lipgloss.Center,
successTitle.Render("Initialization Completed!"), "",
successMsg.Render("System configuration has been saved, and the system is initializing..."), "",
hintStyle.Render("Press any key to exit"),
))
successMsg.Render(
"System configuration has been saved, and the system is initializing..."), "",
)
return appStyle.Render(content)
}
// quitView 退出视图
func quitView() string {
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
content := lipgloss.JoinVertical(lipgloss.Center,
errorTitle.Render("Canceled"), "",
errorMsg.Render("Initialization canceled, no configuration saved"),
))
)
return appStyle.Render(content)
}
// errorView 错误视图
func errorView(err error) string {
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
content := lipgloss.JoinVertical(lipgloss.Center,
errorTitle.Render("Error"), "",
errorMsg.Render(err.Error()), "",
hintStyle.Render("Press Ctrl+C to exit"),
))
}
// navButtons 导航按钮
func navButtons(m model, prev, next string) string {
var btns string
if m.currentPage == 0 {
btns = normalButton.Render(next) + " " + selectedButton.Render(prev)
} else {
btns = selectedButton.Render(next) + " " + normalButton.Render(prev)
}
return btns
}
func (m model) renderNavButtons() string {
var prevBtn, nextBtn string
switch m.focusType {
case FocusTypePrev:
// 焦点在"上一步"
nextBtn = normalButton.Render(" Next ")
prevBtn = selectedButton.Render(" << Prev >>")
case FocusTypeNext:
// 焦点在"下一步"
nextBtn = selectedButton.Render(" << Next >>")
prevBtn = normalButton.Render(" Prev ")
default:
// 焦点在输入框
nextBtn = normalButton.Render(" Next ")
prevBtn = normalButton.Render(" Prev ")
}
return lipgloss.JoinHorizontal(
lipgloss.Center,
nextBtn,
" ",
prevBtn,
)
return appStyle.Render(content)
}