✨Feat: 构建对话终端
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"learning-assistant/internal/ai"
|
||||
"learning-assistant/internal/ai/generators"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
// State TUI状态
|
||||
type State string
|
||||
|
||||
const (
|
||||
StateInput State = "input"
|
||||
StateLoading State = "loading"
|
||||
StateResult State = "result"
|
||||
StateError State = "error"
|
||||
)
|
||||
|
||||
// TabType Tab类型
|
||||
type TabType string
|
||||
|
||||
const (
|
||||
TabGuodegang TabType = "guodegang"
|
||||
TabQuiz TabType = "quiz"
|
||||
TabCard TabType = "card"
|
||||
TabScenario TabType = "scenario"
|
||||
)
|
||||
|
||||
// TabItem Tab项
|
||||
type TabItem struct {
|
||||
Type TabType
|
||||
Label string
|
||||
Icon string
|
||||
}
|
||||
|
||||
// Model TUI模型
|
||||
type Model struct {
|
||||
state State
|
||||
|
||||
// AI组件
|
||||
client *ai.SiliconFlowClient
|
||||
promptManager *ai.PromptManager
|
||||
generator *generators.BaseGenerator
|
||||
|
||||
// 用户输入
|
||||
inputText string
|
||||
|
||||
// 生成结果
|
||||
results map[TabType]string
|
||||
|
||||
// 加载状态
|
||||
loadingStatus map[generators.GeneratorType]bool
|
||||
|
||||
// Tab管理
|
||||
tabs []TabItem
|
||||
activeTab int
|
||||
|
||||
// 错误信息
|
||||
errorMsg string
|
||||
}
|
||||
|
||||
// NewModel 创建模型
|
||||
func NewModel(client *ai.SiliconFlowClient, promptManager *ai.PromptManager) Model {
|
||||
return Model{
|
||||
state: StateResult,
|
||||
client: client,
|
||||
promptManager: promptManager,
|
||||
generator: generators.NewBaseGenerator(client, promptManager),
|
||||
inputText: "",
|
||||
results: make(map[TabType]string),
|
||||
loadingStatus: make(map[generators.GeneratorType]bool),
|
||||
tabs: []TabItem{
|
||||
{Type: TabGuodegang, Label: "讲解", Icon: "🎭"},
|
||||
{Type: TabQuiz, Label: "考核", Icon: "✍️"},
|
||||
{Type: TabCard, Label: "卡片", Icon: "📝"},
|
||||
{Type: TabScenario, Label: "场景", Icon: "🏗️"},
|
||||
},
|
||||
activeTab: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// SetInput 设置输入
|
||||
func (m *Model) SetInput(input string) {
|
||||
m.inputText = input
|
||||
m.state = StateLoading
|
||||
}
|
||||
|
||||
// Init 初始化
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update 更新
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
return m.handleKeyPress(msg)
|
||||
case contentMsg:
|
||||
return m.handleContentResult(msg)
|
||||
case errorMessage:
|
||||
return m.handleError(msg)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// View 视图
|
||||
func (m Model) View() string {
|
||||
switch m.state {
|
||||
case StateInput:
|
||||
return m.inputView()
|
||||
case StateLoading:
|
||||
return m.loadingView()
|
||||
case StateResult:
|
||||
return m.resultView()
|
||||
case StateError:
|
||||
return m.errorView()
|
||||
default:
|
||||
return "Unknown state"
|
||||
}
|
||||
}
|
||||
|
||||
// contentMsg 内容生成完成消息
|
||||
type contentMsg struct {
|
||||
Type generators.GeneratorType
|
||||
Content string
|
||||
}
|
||||
|
||||
// errorMessage 错误消息
|
||||
type errorMessage struct {
|
||||
Type generators.GeneratorType
|
||||
Error error
|
||||
}
|
||||
|
||||
// 样式定义
|
||||
var (
|
||||
baseStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#FAFAFA"))
|
||||
|
||||
headerStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#7D56F4")).
|
||||
Bold(true)
|
||||
|
||||
errorStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#FF5555"))
|
||||
)
|
||||
Reference in New Issue
Block a user