367 lines
9.8 KiB
Go
367 lines
9.8 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 系统初始化向导")
|
||
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,
|
||
)
|
||
}
|