✨Feat: 构建对话终端
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user