186 lines
4.6 KiB
Go
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)
|
|
}
|