package tui import ( "fmt" "strings" "time" tea "charm.land/bubbletea/v2" "charm.land/lipgloss/v2" "superwork-tui/internal/logging" ) // ── message types ───────────────────────────────────────────────────────────── type logsSnapshotMsg struct { entries []logging.Entry } type logsTickMsg struct{} func logsTickCmd() tea.Cmd { return tea.Tick(time.Second, func(t time.Time) tea.Msg { return logsTickMsg{} }) } // ── styles ──────────────────────────────────────────────────────────────────── var ( logInfoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("2")) logWarnStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("3")) logErrorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("1")) ) // ── open ────────────────────────────────────────────────────────────────────── func (m Model) openLogs() (Model, tea.Cmd) { m.state = stateLogs m.logEntries = logging.Default.Snapshot() return m, logsTickCmd() } // ── key handling ────────────────────────────────────────────────────────────── func (m Model) handleLogsKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { switch msg.String() { case "esc", "ctrl+l": m.state = stateLoaded } return m, nil } // ── view ────────────────────────────────────────────────────────────────────── func (m Model) logsView() string { var sb strings.Builder sb.WriteString(helpStyle.Render("日志 (Logs)") + "\n") sb.WriteString(strings.Repeat("─", 70) + "\n") if len(m.logEntries) == 0 { sb.WriteString(" (暂无日志)\n") } else { for _, e := range m.logEntries { ts := time.UnixMilli(e.Ts).Format("15:04:05") level := renderLogLevel(e.Level) line := fmt.Sprintf(" %s %s [%s] %s", ts, level, e.Source, e.Message) if e.Details != "" { line += " " + e.Details } sb.WriteString(line + "\n") } } sb.WriteString("\n") sb.WriteString(helpStyle.Render("esc close")) return sb.String() } func renderLogLevel(l logging.Level) string { switch l { case logging.LevelInfo: return logInfoStyle.Render("INFO ") case logging.LevelWarn: return logWarnStyle.Render("WARN ") case logging.LevelError: return logErrorStyle.Render("ERROR") default: return fmt.Sprintf("%-5d", int(l)) } }