Files
yoyo/taolun.md
titor 063b14add7
All checks were successful
Release / build (push) Successful in 6m29s
refactor: 重构版本号管理规则,更新文档
- 扩展 AGENTS.md 版本号管理规则
- 整理 changelog.md,添加 v1.2.0 版本记录
- 更新 taolun.md,添加版本管理讨论
- 更新 memory.md,添加 CI 构建经验
2026-04-08 02:57:21 +08:00

963 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 讨论记录 (taolun.md)
> 本文档记录开发过程中的重要讨论,以时间轴方式存储,便于版本追溯。
## 使用说明
- 每次重要讨论后更新此文件
- 使用上下文压缩总结,突出重点
- 格式:时间 - 版本号 - 主题
## 时间轴记录
### [2026-03-28 22:30] 版本 0.0.1 - 确定技术栈
**原因**: 项目启动,需要确定技术栈
**分析**:
- 比较Go、Deno+TS、Node.js+TS
- Go优势原生二进制、性能好、CLI工具友好
- 用户不会Go但愿意学习
**解决方案**:
- 使用Go语言开发
- 采用面向对象设计模式
- 支持多个大模型厂商
**相关决策**:
- 项目结构采用`cmd/``internal/`布局
- 使用YAML配置文件
- 实现工厂模式和策略模式
**关联版本**: [changelog.md#0.0.1](changelog.md#001)
---
### [2026-03-28 23:00] 版本 0.0.1 - 设计OOP架构
**原因**: 用户要求面向对象开发模式
**分析**:
- Go不是传统OOP语言但可通过结构体和接口实现
- 需要三个核心类:配置、厂商、翻译器
**解决方案**:
- `Config`类:全局配置管理
- `Provider`接口:厂商抽象
- `Translator`类:核心翻译逻辑
- `ProviderFactory`:工厂模式创建厂商实例
**相关链接**:
- [AGENTS.md#OOP设计模式](AGENTS.md#oop设计模式)
- [changelog.md#0.0.1](changelog.md#001)
---
### [2026-03-28 23:30] 版本 0.0.1 - 制定开发规范
**原因**: 建立规范的开发流程
**分析**:
- 需要记录讨论过程、版本变更和知识积累
- 版本号需要遵循语义化版本规范
**解决方案**:
- 创建taolun.md记录讨论
- 创建changelog.md记录版本
- 创建memory.md记录知识纠正
- 版本号格式:大版本.新功能.小修复(00-99)
**关联文档**:
- [changelog.md#0.0.1](changelog.md#001)
- [memory.md#版本管理](memory.md#版本管理)
---
### [2026-03-28 23:45] 版本 0.0.1 - 创建项目初衷文档
**原因**: 需要一个地方记录项目初衷和愿景
**分析**:
- 项目需要明确的目标和方向
- 创始人需要记录个人想法和灵感
- 与其他文档taolun.md、changelog.md、memory.md区分
**解决方案**:
- 创建`why.md`文件专门记录项目初衷
- 规定只能由项目所有者编辑
- 提供基本结构建议,但不强制内容
**文档规范**:
- 文件位置:项目根目录
- 权限:仅用户可编辑
- 内容:项目愿景、目标、个人笔记等
**关联文档**:
- [AGENTS.md#文档管理](AGENTS.md#开发规范)
- [changelog.md#0.0.1](changelog.md#001)
---
### [2026-03-28 23:50] 版本 0.0.2 - 实现核心架构
**原因**: 开始实现项目核心功能
**分析**:
- 根据OOP设计模式实现三个核心类
- 需要先实现配置加载和厂商接口
- 创建基本的CLI入口点
**解决方案**:
1. **Config类实现**
- 支持YAML配置文件加载
- 环境变量替换
- 配置验证和默认值
2. **Provider接口实现**
- 定义统一的翻译接口
- 工厂模式创建厂商实例
- 实现硅基流动厂商作为示例
3. **Translator类实现**
- 核心翻译逻辑
- Prompt管理
- 超时控制
4. **CLI入口点**
- 命令行参数解析
- 配置加载
- 翻译执行
**技术细节**:
- 使用`gopkg.in/yaml.v3`处理YAML
- 实现工厂模式注册机制
- 使用context处理超时和取消
- 添加基本单元测试
**关联文档**:
- [AGENTS.md#OOP设计模式](AGENTS.md#oop设计模式)
- [changelog.md#0.0.2](changelog.md#002)
---
### [2026-03-29 00:00] 版本 0.0.3 - 环境变量加载修复
**原因**: 测试CLI时发现环境变量没有正确加载
**分析**:
- 配置文件中使用`${ENV_VAR}`语法
- Go的`os.ExpandEnv`只在加载时替换
- 需要先加载.env文件到环境变量
**解决方案**:
1. 添加`github.com/joho/godotenv`依赖
2. 在main函数开始时调用`godotenv.Load()`
3. 更新memory.md记录踩坑经验
**技术细节**:
- godotenv会自动查找当前目录的.env文件
- 如果文件不存在会返回错误,可以忽略
- 不影响已有的环境变量
**关联文档**:
- [memory.md#环境变量加载问题](memory.md#环境变量加载问题)
- [changelog.md#0.0.3](changelog.md#003)
---
### [2026-03-29 10:00] 版本 0.2.0 - 语言代码解析设计
**原因**: 用户需要通过 `--lang` 参数指定目标语言,支持多种语言代码格式
**分析**:
- 需要支持标准BCP47格式`zh-CN``en-US`
- 需要支持简短别名(如 `cn``en`
- 需要支持中文名称(如 `chinese``english`
- 需要智能解析和错误提示
**解决方案**:
1. 创建 `internal/lang/lang.go` 模块
2. 实现语言代码映射表和解析函数
3. 支持大小写不敏感和模糊匹配
4. 提供语言名称获取和建议功能
**技术细节**:
- 使用 `map[string]string` 存储语言代码映射
- 实现 `ParseLanguageCode()` 函数进行智能解析
- 支持30+种语言和变体
- 添加完整的单元测试
**关联文档**:
- [AGENTS.md#语言代码处理](AGENTS.md#语言代码处理)
- [changelog.md#0.2.0](changelog.md#020)
---
### [2026-03-29 10:30] 版本 0.2.0 - onboard配置向导
**原因**: 用户需要友好的配置界面,特别是第一次使用时
**分析**:
- 需要交互式配置向导
- 需要支持选择厂商、输入API密钥、设置默认值
- 需要生成标准的YAML配置文件
- 需要支持强制重新配置
**解决方案**:
1. 使用 `github.com/AlecAivazis/survey/v2`
2. 实现分步配置流程:选择厂商 → 配置厂商 → 全局设置 → 保存
3. 提供友好的错误处理和用户提示
4. 支持 `--force` 参数强制重新配置
**技术细节**:
- 使用 `survey.Select``survey.Input``survey.Confirm` 组件
- 实现厂商默认配置和自定义选项
- 生成完整的配置文件包含所有必要字段
- 支持配置文件存在性检查
**关联文档**:
- [AGENTS.md#Onboard配置向导](AGENTS.md#onboard配置向导)
- [changelog.md#0.2.0](changelog.md#020)
---
### [2026-03-29 11:00] 版本 0.2.0 - 分阶段迁移策略
**原因**: 需要平衡开发便利性和最终上线需求
**分析**:
- 开发阶段需要简单配置方式(`.env` + `configs/config.yaml`
- 上线前需要迁移到用户配置目录(`~/.config/yoo/yoo.yml`
- 需要平滑的迁移路径和向后兼容性
**解决方案**:
1. **第一阶段(当前)**: 继续使用 `.env` + `configs/config.yaml`
2. **第二阶段(上线前)**: 实现配置文件路径查找和迁移工具
3. **第三阶段(最终)**: 移除 `.env` 依赖,完全使用配置文件
**技术细节**:
- 配置文件路径优先级:命令行 > 环境变量 > 用户目录 > 当前目录
- 保持向后兼容性,支持旧配置格式
- 提供配置验证和错误提示
- 实现配置迁移工具(计划)
**关联文档**:
- [AGENTS.md#分阶段迁移策略](AGENTS.md#分阶段迁移策略)
- [changelog.md#0.2.0](changelog.md#020)
---
### [2026-03-29 12:00] 版本 0.4.0 - 管道符功能
**原因**: 用户需要与其他命令行工具联合使用
**分析**:
- 用户希望支持管道符功能,如 `cat a.txt | yoyo | grep "who are you"`
- 需要检测管道输入并从stdin读取内容
- 需要控制统计信息输出,避免污染管道输出
- 需要保持向后兼容性
**解决方案**:
1. **管道输入检测**: 实现 `isPipeInput()` 函数,使用 `os.Stdin.Stat()` 检测管道
2. **stdin读取**: 实现 `readFromStdin()` 函数,使用 `bufio.Scanner` 读取所有输入
3. **静默模式**: 添加 `--quiet``-q` 参数,控制统计信息输出
4. **输出重定向**: 将统计信息输出到stderr避免污染管道输出
**技术细节**:
- 使用 `os.ModeCharDevice` 检测是否为管道设备
- 使用 `strings.Join()` 合并多行输入为单个字符串
- 统计信息输出到 `os.Stderr` 而不是 `os.Stdout`
- 修复 content/filter.go 中的正则表达式转义问题
**使用示例**:
```bash
# 基本管道功能
echo "Hello world" | yoyo
cat file.txt | yoyo --lang=en
# 静默模式
echo "Hello world" | yoyo -q
echo "Hello world" | yoyo --quiet
# 与其他命令组合
cat file.txt | yoyo | grep "你好"
yoyo "Hello" | wc -l
```
**关联文档**:
- [AGENTS.md#管道符功能](AGENTS.md#管道符功能)
- [changelog.md#0.4.0](changelog.md#040)
---
### [2026-03-29 15:00] 版本 0.5.0 - 本地缓存功能设计
**原因**: 用户希望减少API调用添加本地缓存功能
**分析**:
- 需要存储翻译结果避免重复调用API
- 需要设计缓存键策略,确保缓存准确性
- 需要考虑数据库选择、事务处理、性能优化
- 需要设计缓存管理策略
**解决方案**:
1. **数据库选择**: 使用SQLite
- 轻量级,无需服务器
- 支持ACID事务
- Go生态支持良好 (`github.com/mattn/go-sqlite3`)
- 适合嵌入式应用
2. **缓存键设计**:
- 使用文本内容 + 源语言 + 目标语言
- 生成SHA256哈希作为缓存键
- 规范化输入:移除多余空白字符,统一语言代码格式
3. **事务处理**:
- 使用事务保证数据一致性
- 插入操作在事务中执行
- 查询操作不需要显式事务
4. **保存时机**:
- 在输出结果之前保存到数据库
- 确保数据持久化
- 异步保存,不阻塞翻译结果返回
5. **性能优化**:
- 为缓存键创建索引
- 使用哈希键减少存储空间
- 限制缓存表大小(可配置)
- 使用WAL模式提高并发性能
6. **缓存策略**:
- 采用组合策略:数量限制+时间过期
- 默认启用缓存功能
- 提供手动清理命令
7. **存储位置**:
- 数据库文件存储在用户配置目录 `~/.config/yoyo/cache.db`
- 符合XDG规范
- 支持自定义路径配置
**技术细节**:
- 使用 `github.com/mattn/go-sqlite3` 驱动
- 实现 `internal/cache/cache.go` 模块
- 缓存表结构:`id`, `cache_key`, `original_text`, `translated_text`, `from_lang`, `to_lang`, `model`, `prompt`, `created_at`
- 缓存键生成:`sha256(text + "|" + fromLang + "|" + toLang)`
- 查询缓存时使用 `SELECT translated_text FROM cache WHERE cache_key = ?`
- 插入缓存时使用 `INSERT OR IGNORE INTO cache (...) VALUES (...)`
**关联文档**:
- [AGENTS.md#本地缓存功能设计](AGENTS.md#本地缓存功能设计)
- [changelog.md#0.5.0](changelog.md#050)
---
### [2026-03-29 20:00] 版本 0.5.1 - 缓存功能修复
**原因**: 缓存功能测试中发现的问题
**分析**:
1. **VACUUM事务错误**: 缓存清空命令中VACUUM不能在事务中执行
2. **NULL值转换错误**: 缓存统计查询在空表时MIN(created_at)返回NULL导致转换错误
3. **过期清理策略**: 当expire_days=0时清理逻辑不工作
**解决方案**:
1. **修复VACUUM事务错误**:
- 将VACUUM移到事务之外执行
- 先删除记录再执行VACUUM
2. **修复NULL值转换错误**:
- 使用 `sql.NullString``sql.NullFloat64` 类型
- 检查 `Valid` 字段判断是否为NULL
- 只在有记录时才查询时间范围
3. **修复过期清理策略**:
- 当cleanupTTL为0时清理所有记录
- 添加条件判断:`if c.cleanupTTL == 0 { ... }`
**技术细节**:
```go
// 修复VACUUM事务错误
func (c *SQLiteCache) Clear(ctx context.Context) error {
// 先删除所有记录
_, err := c.db.ExecContext(ctx, `DELETE FROM translation_cache`)
if err != nil {
return fmt.Errorf("清空缓存失败: %w", err)
}
// 然后执行VACUUM不能在事务中执行
_, err = c.db.ExecContext(ctx, `VACUUM`)
if err != nil {
return fmt.Errorf("清理数据库失败: %w", err)
}
return nil
}
// 修复NULL值转换错误
var oldestStr, newestStr sql.NullString
var avgTokens sql.NullFloat64
err = c.db.QueryRowContext(ctx, `SELECT MIN(created_at), MAX(created_at), AVG(total_tokens) FROM translation_cache`).Scan(&oldestStr, &newestStr, &avgTokens)
if oldestStr.Valid {
stats.OldestRecord, _ = time.Parse("2006-01-02 15:04:05", oldestStr.String)
}
```
**关联文档**:
- [changelog.md#0.5.1](changelog.md#051)
- [memory.md#本地缓存实现经验](memory.md#本地缓存实现经验)
---
### [2026-04-06 10:00] 版本 0.6.0 - TUI界面模块拆分计划
**原因**: 当前TUI目录(tui/components、tui/theme)已创建但完全为空,需要从零实现终端交互界面
**分析**:
- 采用分模块逐步实现策略减少Token消耗和上下文负担
- 每次只实现一个模块,完成后再进入下一个
- 讨论内容仅保存到taolun.md/changelog.md/memory.md不新增md文件
**解决方案 - TUI模块拆分**:
| 步骤 | 模块 | 内容 | 预计工作量 |
|------|------|------|-----------|
| 1 | TUI框架搭建 | 选择库(bubbletea)、基础App结构、运行循环 | 小 |
| 2 | 输入组件 | 文本输入框、光标、基础编辑 | 中 |
| 3 | 翻译显示区 | 结果展示、格式化、滚动 | 中 |
| 4 | 状态栏/主题 | 底部状态栏、语言选择、主题配色 | 小 |
| 5 | 快捷键系统 | 退出、清空、切换语言等 | 小 |
| 6 | 集成翻译 | 对接现有Translator、加载动画 | 中 |
**技术选型**:
- 优先使用 `charmbracelet/bubbletea` (Elm架构、Go生态最流行)
- 配合 `charmbracelet/lipgloss` 实现样式和主题
- 配合 `charmbracelet/bubbles/textinput` 实现输入框
**当前状态**: ✅ 模块1已完成模块2待实现
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 10:30] 版本 0.6.0 - 模块1: TUI框架搭建 (已完成)
**原因**: 实现TUI界面的第一步建立基础框架结构
**分析**:
- 需要创建基本的App结构和model
- 需要支持config和translator的注入
- 需要修复main.go中版本检查顺序问题
**解决方案**:
1. 创建 `internal/tui/app.go` 基础文件
2. 定义model结构体包含config和translator字段
3. 实现Init/Update/View三个基本方法
4. 添加bubbletea、bubbles、lipgloss依赖
5. 修复main.go中--version在interactive之前检查
**技术实现**:
```go
type model struct {
config *config.Config
translator *translator.Translator
}
func NewApp(cfg *config.Config, t *translator.Translator) *tea.Program {
return tea.NewProgram(model{...})
}
```
**下一步**: 实现模块2: 输入组件
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 11:00] 版本 0.6.0 - 模块2: 输入组件 (已完成)
**原因**: 实现TUI输入功能
**分析**:
- 使用bubbletea的textinput组件
- 需要焦点管理和键盘事件处理
**解决方案**:
1. 添加textinput字段到model
2. 初始化时设置placeholder和prompt
3. Update中处理KeyMsg
4. View中渲染输入框
5. 支持Ctrl+C和Esc退出
**技术实现**:
```go
type model struct {
textInput textinput.Model
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if msg.Type == tea.KeyCtrlC || msg.Type == tea.KeyEsc {
return m, tea.Quit
}
}
m.textInput, cmd = m.textInput.Update(msg)
return m, cmd
}
```
**下一步**: 实现模块3: 翻译显示区
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 11:30] 版本 0.6.0 - 模块3: 翻译显示区 (已完成)
**原因**: 添加翻译结果显示区域
**分析**:
- 需要定义结果展示区域
- 需要为不同区域定义不同样式
**解决方案**:
1. 添加result字段到model
2. 定义headerStyle、resultStyle、helpStyle
3. 实现renderResult()辅助方法
4. View中组合各个区域
**下一步**: 实现模块4: 状态栏/主题
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 12:00] 版本 0.6.0 - 模块4: 状态栏/主题 (已完成)
**原因**: 添加底部状态栏和主题配色
**分析**:
- 需要显示当前目标语言
- 需要完善配色方案
- 需要定义状态栏样式
**解决方案**:
1. 添加targetLang字段到model
2. 定义statusBarStyle、langStyle等新样式
3. 实现renderStatusBar()方法
4. View中渲染状态栏
**下一步**: 实现模块5: 快捷键系统
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 12:30] 版本 0.6.0 - 模块5: 快捷键系统 (已完成)
**原因**: 添加键盘快捷键提升用户体验
**分析**:
- 需要常用操作快捷键
- 需要清晰显示快捷键提示
**解决方案**:
1. 添加Ctrl+L: 清空输入和结果
2. 添加Ctrl+T: 循环切换语言
3. 添加keyStyle样式高亮快捷键
4. 更新帮助提示显示所有快捷键
**快捷键列表**:
- `Ctrl+L`: 清空输入框和翻译结果
- `Ctrl+T`: 循环切换目标语言 (zh-CN→en-US→ja→ko→...)
- `Ctrl+C`/`Esc`: 退出程序
- `Enter`: 翻译 (后续模块实现)
**下一步**: 实现模块6: 集成翻译
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 13:00] 版本 0.6.0 - 模块6: 集成翻译 (已完成)
**原因**: 将Translator集成到TUI实现真正的翻译功能
**分析**:
- 需要在Enter键时调用翻译API
- 需要异步执行避免阻塞UI
- 需要显示loading状态和错误处理
**解决方案**:
1. 添加translateMsg消息类型处理异步结果
2. 添加loading和errMsg字段
3. 实现doTranslate()函数执行异步翻译
4. Update中处理translateMsg消息
5. View中显示loading状态或错误信息
**技术实现**:
```go
type translateMsg struct {
result string
err error
}
func (m model) doTranslate(text, toLang string) tea.Cmd {
return func() tea.Msg {
result, err := m.translator.Translate(...)
if err != nil {
return translateMsg{err: err}
}
return translateMsg{result: result.Translated}
}
}
```
**下一步**: 测试TUI界面、优化体验
**关联文档**:
- [changelog.md#0.6.0](changelog.md#060)
---
### [2026-04-06 14:00] 版本 0.7.0 - TUI界面改进计划
**原因**: TUI基础功能完成后讨论改进方向和用户体验优化
**分析**:
- 当前单行textinput无法输入多行文本
- 快捷键固定显示在底部不够美观
- 缺少命令菜单系统
- 长翻译结果无法滚动
**解决方案 - 新增模块**:
| 步骤 | 模块 | 内容 |
|------|------|------|
| 7 | 多行输入 | textarea组件替换textinput |
| 8 | 弹出框组件 | 通用modal支持快捷键帮助 |
| 9 | 斜杠命令菜单 | / 触发命令选择器类似opencode |
| 10 | 翻译结果滚动 | viewport组件 |
| 11 | 复制功能 | clipboard集成 |
| 12 | 状态栏扩展 | 耗时、token用量 |
**斜杠命令设计**:
| 命令 | 功能 |
|------|------|
| `/help` | 显示快捷键帮助 |
| `/clear` | 清空内容 |
| `/copy` | 复制翻译结果 |
| `/lang` | 切换语言 |
| `/history` | 翻译历史 |
| `/quit` | 退出 |
**设计亮点**:
1. 隐藏底部快捷键提示,改为按 ? 或 F1 弹出帮助框
2. 输入 / 触发命令菜单,上下键选择,回车执行
3. 命令菜单支持模糊匹配
4. modal组件通用化可复用于其他弹窗场景
**关联文档**:
- [changelog.md#0.7.0](changelog.md#070)
---
### [2026-04-06 14:30] 版本 0.7.0 - 模块7: 多行输入 (已完成)
**原因**: 当前textinput只支持单行需要支持多行文本输入
**分析**:
- 长段落、多行文本无法输入
- 需要换用bubbles的textarea组件
**解决方案**:
1. 将textinput替换为textarea
2. 调整样式和布局宽50高5
3. 底部状态栏提示按 / 显示命令
**技术实现**:
- 使用 `github.com/charmbracelet/bubbles/textarea`
- textarea.SetWidth(50)、SetHeight(5) 设置尺寸
- 移除底部固定快捷键提示,改为按需显示
- 隐藏行号: `ShowLineNumbers = false`
- 移除左侧提示符: `Prompt = ""`
- Enter执行翻译Ctrl+J换行
**下一步**: 实现模块8: 弹出框组件
**关联文档**:
- [changelog.md#0.7.0](changelog.md#070)
---
### [2026-04-06 15:00] 版本 0.8.0 - TUI重构: 聊天风格界面
**原因**: 用户希望使用类似 charmbracelet/crush 的聊天风格界面
**分析**:
- 当前界面:标题在上 → 输入框在中 → 结果在下
- 期望界面:标题在上 → 聊天消息区域(可滚动历史)→ 输入框固定底部 → 状态栏最底部
- 原文+译文成对显示,类似聊天软件
**解决方案**:
1. 界面布局重构:
```
┌─────────────────────────────────────────┐
│ ✦ YOYO 翻译 [Ctrl+C退出] │
├─────────────────────────────────────────┤
│ (聊天消息区域,可滚动查看历史) │
│ ── 用户输入 ── │
│ Hello world │
│ ── 翻译结果 ── │
│ 你好世界 │
│ ... │
├─────────────────────────────────────────┤
│ 输入框... [回车] │
├─────────────────────────────────────────┤
│ 目标:zh-CN │ 模型:gpt-3.5 │ Tokens:125 │
└─────────────────────────────────────────┘
```
2. 技术方案:
- 消息结构:原文+译文成对显示
- 底部固定输入框textarea
- 状态栏显示完整信息
- Ctrl+J 换行Enter 发送
- 自动调整输入框高度
**下一步**: 模块1: 创建TUI模块结构
**关联文档**:
- [changelog.md#0.8.0](changelog.md#080)
---
### [2026-04-06 16:00] 版本 0.8.0 - 输入框踩坑与修复
**原因**: Ctrl+J换行后第一行被遮住显示错乱
**分析**:
- 换行后 textarea 内部渲染3行但只显示2行
- 第一行内容往上滚动被遮住光标在第2行第3行是空行
- 尝试多种方案均无效移除Width限制、设置SetWidth/SetHeight顺序、动态调整高度
**解决方案**:
1. 放弃动态调整高度方案固定高度为5行
2. 超过5行时textarea内部自动滚动光标始终可见
**技术细节**:
- textarea内部使用viewport组件频繁SetHeight导致滚动位置错乱
- 使用 FocusedStyle/BlurredStyle + Style.Base 设置背景色
**代码变更**:
```go
ta.SetWidth(60)
ta.SetHeight(5) // 固定高度,不动态调整
```
**下一步**: 完善其他UI功能
**关联文档**:
- [memory.md#TUI输入框踩坑记录](memory.md#tui输入框踩坑记录)
- [changelog.md#0.8.0](changelog.md#080)
---
### [2026-04-07 10:00] 版本 0.8.1 - 翻译结果卡片组件设计
**原因**: 用户希望改进翻译结果显示样式使用lipgloss构建更美观的组件
**分析**:
- 当前翻译结果显示比较简单,只有标签和内容
- 需要设计一个结构化的翻译卡片组件
- 组件需要显示Tokens、翻译时间、模型名称等元信息
**解决方案**:
1. **卡片组件结构**:
```
┌─ 标题栏 ─────────────────────────────────────────┐
│ Tokens: 150 │ 耗时: 1.2s │ 模型: gpt-4 │
└─────────────────────────────────────────────────┘
┌─ 用户输入 ───────────────────────────────────────┐
│ ██████████ 碳黑背景 ████████████████████████████ │
└─────────────────────────────────────────────────┘
┌─ 翻译结果 ───────────────────────────────────────┐
│ AI 翻译的文本内容... │
└─────────────────────────────────────────────────┘
```
2. **技术实现**:
- 使用 lipgloss.Div() 和 lipgloss.JoinVertical() 构建组件
- 背景色: #1A1A1A (碳黑色)
- 用户输入区域: 纯背景色,无边框
- 组件间距: 5px marginBottom
3. **样式定义**:
- CardStyle: 卡片容器marginBottom(5)
- CardMetaStyle: 元信息行样式,#6B7280 灰色
- CardInputStyle: 用户输入,#1A1A1A 背景 + #E5E7EB 文字
- CardOutputStyle: 翻译结果,白色文字
**下一步**: 实现组件代码
**关联文档**:
- [changelog.md#0.8.1](changelog.md#081)
---
### [2026-04-07] 版本 1.0.0-beta - Logo和信息栏改造
**原因**: 用户希望改进TUI界面的视觉效果使标题更独特输入框和信息栏更美观
**分析**:
- 原标题 "✦ YOYO 翻译" 过于简单
- 输入框需要更好的视觉分隔
- 需要添加翻译状态动画
**解决方案**:
1. **标题Logo**:
- 使用ASCII艺术 "l_ _ _____ _____"
- 实现紫色→粉色渐变效果 (ANSI True Color)
- 右侧显示版本号 [v1.0.0-beta]
2. **输入框改造**:
- 去掉边框
- 上下使用紫色 `:::` 分隔符
- Ctrl+J 启用换行
3. **信息栏改造**:
- 合并显示:语言(红色) + 模型名(白色) + 缓存记录(碳黑)
- 翻译时显示 Spinner 动画 (MiniDot)
4. **翻译卡片优化**:
- `` 图标边距调整
**版本号规则**:
- 版本号需与 git 标签、changelog.md 中的版本号保持三方同步
- 遵循语义化版本:主版本.次版本.修订版本
- beta版使用 `-beta` 后缀
**关联版本**: [changelog.md#1.0.0-beta](changelog.md#100-beta-2026-04-07)
---
### [2026-04-07] 版本 1.1.0 - 配置路径修复和huh迁移
**原因**:
1. 管道模式下(如 `cd /docs && cat readme.md | yoyo`)找不到配置文件
2. onboard配置保存到错误的相对路径
3. 希望用 `charmbracelet/huh` 替代 `survey` 获得更好的UX
**分析**:
- 所有配置路径硬编码为 `configs/config.yaml`相对CWD
- 从不同目录运行程序时路径解析失败
- survey库API较老huh提供更现代的表单体验
**解决方案**:
1. 新增 `internal/config/path.go` 路径解析工具
2. 配置查找优先级:`--config` > `~/.config/yoyo/config.yaml` > `./configs/config.yaml`
3. onboard保存到 `~/.config/yoyo/config.yaml`
4. .env从 `~/.config/yoyo/.env` 加载
5. onboard使用huh重写Form+Group模式链式API泛型支持
**技术细节**:
```go
// 路径解析
config.ResolveConfigPath(userPath) // 智能查找配置
config.GetUserConfigPath() // ~/.config/yoyo/config.yaml
config.GetUserEnvPath() // ~/.config/yoyo/.env
```
**huh迁移要点**:
- `survey.Select` → `huh.NewSelect[string]().Options(huh.NewOption(...)...)`
- `survey.Input` → `huh.NewInput().Value(&var).Validate(fn)`
- `survey.Confirm` → `huh.NewConfirm().Affirmative("是").Negative("否")`
- 分步表单 → `huh.NewForm(huh.NewGroup(...), huh.NewGroup(...))`
**关联版本**: [changelog.md#1.1.0](changelog.md#110-2026-04-07)
---
### [2026-04-08 00:40] 版本 1.1.1 - Logo模块化与渐变色统一
**原因**:
1. `--help` `-h` `-?` `--version` 在默认交互式模式下无响应
2. 帮助信息头部需要彩色logo展示
**问题分析**:
1. 交互模式判断优先于help/version检查导致flags被忽略
2. 帮助信息使用硬编码版本号 `YOYO翻译工具 v1.1.0`无logo
**解决方案**:
1. 修复flag检查顺序在进入交互模式前先检查 `-h` `--help` `-?` `--version`
2. 新增 `internal/logo/logo.go` 模块统一管理logo
3. 编译时通过 `ldflags` 注入版本号
4. 渐变色使用与TUI一致的紫→青色方案
**技术实现**:
```go
// logo模块核心函数
func GradientText(text string, startColor, endColor string) string { ... }
func GetLogoPattern() string // 返回4行ascii art
func GetVersionSuffix() string // 返回 " (v1.1.1-dirty )" 或 " ( )"
func PrintLogoWithVersion() // 打印完整logo--help/--version使用
```
**build.sh版本注入**:
```bash
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "")
go build -ldflags "-X github.com/titor/fanyi/internal/logo.version=${VERSION}" -o yoyo ./cmd/yoyo
```
**TUI整合**:
- 移除 `internal/tui/model.go` 中的本地 `logoPattern` 和 `gradientText`
- 直接调用 `logo.GradientText(logo.GetLogoPattern(), "#B413DC", "#00C8C8")`
- 移除 `[Ctrl+C 退出]` 显示
**最终输出格式**(所有位置统一):
```
_ _ _____ _____
( \/ ( _ ( _ )
\ / )(_)( )(_)(
(__)(_____(_____( v1.1.1-dirty )
```
---
### [2026-04-08] TUI界面帮助功能与样式改进
**原因**:
1. 用户需要在TUI底部添加帮助信息栏
2. 优化翻译卡片的显示样式
**分析**:
- 使用 bubbletea 的 help 组件实现帮助栏
- 翻译卡片需要与输入区域保持间距
**解决方案**:
1. **帮助功能实现**:
- 导入 `charm.land/bubbles/v2/help`
- 在 `model` 结构体添加 `help help.Model` 字段
- `KeyMap` 实现 `ShortHelp()` 和 `FullHelp()` 接口
- 按键绑定: Help -> Ctrl+H (原 ? 和 ctrl+? 不兼容)
- View 中添加 help.View(m.keys) 到底部
2. **翻译卡片样式**:
- 翻译结果 outputBlock 的 Padding 从 `(0,3,1,3)` 改为 `(1,3,1,3)` 增加上方空隙
- viewport 内容区域第一个卡片前添加 `"\n"` 作为上边距
3. **版本号注入**:
- 扩展 build.sh 支持跨平台编译
- 添加 -h 帮助选项
- 添加 -o 自定义输出文件名
- release.yaml 使用 build.sh 构建
**按键绑定历史**:
- 初始: `?` → shift+? 切换,且会输入到文本框
- 尝试: `ctrl+?` → 不兼容,无响应
- 最终: `ctrl+h` → 正常工作
**相关文件**:
- `internal/tui/keys.go` - KeyMap 定义和 ShortHelp/FullHelp
- `internal/tui/model.go` - help 组件集成、样式调整
- `build.sh` - 跨平台编译支持
- `.gitea/workflows/release.yaml` - CI 构建脚本
**关联版本**: [changelog.md#0.7.1](changelog.md#071-2026-04-08---tui界面改进)
**关联版本**: [changelog.md#1.1.1](changelog.md#111-2026-04-08)
---
### [2026-04-08] 版本号管理规则制定
**原因**: 版本号历史混乱,需要规范化管理
**讨论内容**:
1. **版本现状分析**:
- 历史标签混乱: v0.0.1 → v1.1.1 → v6.0 等
- changelog 中版本状态标记混乱
2. **确定版本规则**:
- 当前版本: v1.2.0 (TUI基础功能完成)
- 采用简化分支策略: main + feature 分支
- 合并时使用 --no-ff 保留分支历史
- 在 AGENTS.md 中详细定义版本号规则
3. **v1.2.0 发布标准**:
- TUI交互界面 ✅
- 多行输入 ✅
- 翻译卡片展示 ✅
- 状态栏 ✅
- 帮助信息 ✅
- 版本注入 ✅
- 跨平台编译 ✅
- CI构建 ✅
4. **保留历史标签**:
- 过去的版本作为来时的路,不再删除
- 从现在开始规范维护
**相关文件**:
- `AGENTS.md` - 版本号管理规则(扩展)
- `changelog.md` - 版本历史整理
- `build.sh` - 跨平台编译脚本
**关联版本**: [changelog.md#v1.2.0](changelog.md#v120-2026-04-08)