357 lines
10 KiB
Go
357 lines
10 KiB
Go
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 Software License Agreement")
|
|
|
|
agreement := agreementBox.Render(`
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ SunHPC License Agreement │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
1. License Grant
|
|
This software grants you a non-exclusive, non-transferable
|
|
license to use it.
|
|
2. Disclaimer of Warranties
|
|
This software is provided "as is" without any warranties,
|
|
whether express or implied.
|
|
3. Limitation of Liability
|
|
This software is provided without warranty of any kind,
|
|
either express or implied.
|
|
In no event shall the author be liable for any damages
|
|
arising out of the use of this software.
|
|
4. Termination of Agreement
|
|
If you violate any of the terms of this agreement,
|
|
the license will automatically terminate.
|
|
───────────────────────────────────────────────────────────────
|
|
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)
|
|
|
|
// ✅ 添加调试信息(确认 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,
|
|
title, "",
|
|
agreement, "",
|
|
buttonGroup, "",
|
|
// debugInfo, "", // ✅ 显示调试信息
|
|
hint,
|
|
)
|
|
}
|
|
|
|
// dataView 数据接收页面
|
|
func (m model) dataView() string {
|
|
title := titleStyle.Render("Cluster Information")
|
|
|
|
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("Use Up/Down OR Tab Change,Enter Confirm")
|
|
return lipgloss.JoinVertical(lipgloss.Center,
|
|
title, "",
|
|
inputs.String(), "",
|
|
buttons, "",
|
|
hint,
|
|
)
|
|
}
|
|
|
|
// publicNetworkView 公网设置页面
|
|
func (m model) publicNetworkView() string {
|
|
title := titleStyle.Render("Public Network Configuration")
|
|
|
|
networkInterfaces := getNetworkInterfaces()
|
|
autoDetect := infoStyle.Render(
|
|
"[*] Auto Detect Network 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")
|
|
}
|
|
|
|
buttons := m.renderNavButtons()
|
|
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
|
|
|
|
return lipgloss.JoinVertical(lipgloss.Center,
|
|
title, "",
|
|
autoDetect, "",
|
|
inputs.String(), "",
|
|
buttons, "",
|
|
hint,
|
|
)
|
|
}
|
|
|
|
// internalNetworkView 内网配置页面
|
|
func (m model) internalNetworkView() string {
|
|
title := titleStyle.Render("Internal Network Configuration")
|
|
|
|
networkInterfaces := getNetworkInterfaces()
|
|
autoDetect := infoStyle.Render(
|
|
"[*] Auto Detect Network 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")
|
|
}
|
|
|
|
buttons := m.renderNavButtons()
|
|
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
|
|
|
|
return lipgloss.JoinVertical(lipgloss.Center,
|
|
title, "",
|
|
autoDetect, "",
|
|
inputs.String(), "",
|
|
buttons, "",
|
|
hint,
|
|
)
|
|
}
|
|
|
|
// dnsView DNS 配置页面
|
|
func (m model) dnsView() string {
|
|
title := titleStyle.Render("DNS Configuration")
|
|
|
|
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("Use Up/Down OR Tab Change,Enter Confirm")
|
|
|
|
return lipgloss.JoinVertical(lipgloss.Center,
|
|
title, "",
|
|
inputs.String(), "",
|
|
buttons, "",
|
|
hint,
|
|
)
|
|
}
|
|
|
|
// summaryView 总结页面
|
|
func (m model) summaryView() string {
|
|
title := titleStyle.Render("Summary")
|
|
subtitle := subTitleStyle.Render("Please confirm the following configuration information")
|
|
|
|
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,
|
|
))
|
|
|
|
var buttons string
|
|
if m.focusIndex == 0 {
|
|
buttons = selectedButton.Render("[>] Start Initialization") + " " + normalButton.Render("[ ] Cancel")
|
|
} else {
|
|
buttons = normalButton.Render("[>] Start Initialization") + " " + selectedButton.Render("[ ] Cancel")
|
|
}
|
|
|
|
hint := hintStyle.Render("Use Up/Down OR Tab Change,Enter Confirm")
|
|
|
|
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{"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,
|
|
successTitle.Render("Initialization Completed!"), "",
|
|
successMsg.Render("System configuration has been saved, and the system is initializing..."), "",
|
|
hintStyle.Render("Press any key to exit"),
|
|
))
|
|
}
|
|
|
|
// quitView 退出视图
|
|
func quitView() string {
|
|
return containerStyle.Render(lipgloss.JoinVertical(lipgloss.Center,
|
|
errorTitle.Render("Canceled"), "",
|
|
errorMsg.Render("Initialization canceled, no configuration saved"),
|
|
))
|
|
}
|
|
|
|
// errorView 错误视图
|
|
func errorView(err error) string {
|
|
return containerStyle.Render(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,
|
|
)
|
|
}
|