Files
2026-03-20 14:26:24 +08:00

186 lines
4.6 KiB
Go

package tui
import (
"fmt"
"github.com/charmbracelet/lipgloss"
"learning-assistant/internal/ai/generators"
)
// inputView 输入视图
func (m Model) inputView() string {
title := headerStyle.Render("🎓 学习助手")
subtitle := baseStyle.Render("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
inputPrompt := baseStyle.Render("请输入您想学习的知识点,按 Enter 开始生成:\n")
return fmt.Sprintf(
"\n%s\n%s\n\n%s\n\n%s[按 Ctrl+C 退出]\n",
title,
subtitle,
inputPrompt,
baseStyle.Render("> "),
)
}
// loadingView 加载视图
func (m Model) loadingView() string {
title := headerStyle.Render("⏳ 正在生成学习内容...")
subtitle := baseStyle.Render("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
knowledge := fmt.Sprintf("知识点:%s", m.inputText)
knowledgeStyled := baseStyle.Render(knowledge)
status := "生成状态:\n"
// Mermaid
if m.loadingStatus[generators.GeneratorMermaid] {
status += fmt.Sprintf(" ✓ Mermaid 图表\n")
} else {
status += fmt.Sprintf(" ◯ Mermaid 图表\n")
}
// Guodegang
if m.loadingStatus[generators.GeneratorGuodegang] {
status += fmt.Sprintf(" ✓ 郭德纲式讲解\n")
} else {
status += fmt.Sprintf(" ◯ 郭德纲式讲解\n")
}
// Quiz
if m.loadingStatus[generators.GeneratorQuiz] {
status += fmt.Sprintf(" ✓ 十道考核题\n")
} else {
status += fmt.Sprintf(" ◯ 十道考核题\n")
}
// Card
if m.loadingStatus[generators.GeneratorCard] {
status += fmt.Sprintf(" ✓ 记忆卡片\n")
} else {
status += fmt.Sprintf(" ◯ 记忆卡片\n")
}
// Scenario
if m.loadingStatus[generators.GeneratorScenario] {
status += fmt.Sprintf(" ✓ 工程场景案例\n")
} else {
status += fmt.Sprintf(" ◯ 工程场景案例\n")
}
return fmt.Sprintf(
"\n%s\n%s\n\n%s\n\n%s %s[按 Ctrl+C 退出]\n",
title,
subtitle,
knowledgeStyled,
baseStyle.Render(status),
"",
"",
)
}
// resultView 结果视图
func (m Model) resultView() string {
title := headerStyle.Render("🎓 学习助手")
// Tab栏
tabBar := m.renderTabs()
// 分隔线
separator := lipgloss.NewStyle().
Foreground(lipgloss.Color("#586069")).
Render("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
// 当前Tab内容
currentTab := m.tabs[m.activeTab]
content, ok := m.results[currentTab.Type]
if !ok {
content = "内容生成中..."
}
// 内容区域(简化渲染,实际应该用viewport)
contentView := m.renderContent(content, currentTab)
// Mermaid复制提示
clipboardHint := ""
if currentTab.Type == TabGuodegang || currentTab.Type == TabQuiz || currentTab.Type == TabCard || currentTab.Type == TabScenario {
clipboardHint = baseStyle.Render("\n✅ Mermaid 图表已自动复制到剪切板")
}
// 底部帮助
help := m.renderHelp()
return fmt.Sprintf(
"%s\n%s\n\n%s\n\n%s\n%s\n%s\n%s",
title,
tabBar,
separator,
contentView,
"",
clipboardHint,
"",
help,
)
}
// errorView 错误视图
func (m Model) errorView() string {
title := errorStyle.Render("❌ 生成失败")
content := errorStyle.Render(m.errorMsg)
help := baseStyle.Render("[按 Ctrl+C 退出,或按 Enter 重新输入]")
return fmt.Sprintf(
"\n%s\n\n%s\n\n%s\n",
title,
content,
help,
)
}
// renderTabs 渲染Tab栏
func (m Model) renderTabs() string {
var tabs []string
for i, tab := range m.tabs {
var style lipgloss.Style
if i == m.activeTab {
style = lipgloss.NewStyle().
Foreground(lipgloss.Color("#7D56F4")).
Bold(true)
} else {
style = lipgloss.NewStyle().
Foreground(lipgloss.Color("#586069"))
}
tabs = append(tabs, style.Render(fmt.Sprintf("[%s%s]", tab.Icon, tab.Label)))
}
exitHint := lipgloss.NewStyle().
Foreground(lipgloss.Color("#FAFAFA")).
Render("q退出")
tabs = append(tabs, exitHint)
return lipgloss.JoinHorizontal(lipgloss.Top, tabs...)
}
// renderContent 渲染内容
func (m Model) renderContent(content string, tab TabItem) string {
header := lipgloss.NewStyle().
Foreground(lipgloss.Color("#04B575")).
Bold(true).
Render(fmt.Sprintf("%s %s", tab.Icon, tab.Label))
return fmt.Sprintf("%s\n\n%s", header, baseStyle.Render(content))
}
// renderHelp 渲染帮助信息
func (m Model) renderHelp() string {
help := baseStyle.Render("←/→ 切换标签页 | ↑/↓ 滚动内容 | q 退出")
var style lipgloss.Style
style = lipgloss.NewStyle().
Foreground(lipgloss.Color("#586069"))
return style.Render(help)
}