# 第3次:收件箱界面改版讨论 ## 日期 2026-04-10 ## 背景 参考 charmbracelet/glow 的 TUI 设计,将 inbox 界面改为更现代化的双栏布局。 ## 最终实现效果 ### 双栏布局(终端宽度 ≥ 80) ``` ┌───────────────────────────────────────────────────────────────────────┐ │ 收件箱 (5 封新邮件) │ 邮件详情 │ ├─────────────────────────────────────────┴────────────────────────────────┤ │ 新设备登录提醒 │ 主题:新设备登录提醒 │ │ ▣ 163 · 11小时前 │ 发件人: xxx@163.com │ │─────────────────────────────────────────│ 账户: 163 │ │ 您的账号正在一台新设备上登录 │ 时间: 2026-04-10 10:30 │ │ ▣ 163 · 11小时前 │ │ │─────────────────────────────────────────│ 预览: 您的账号正在一台新设备上登录... │ │ 项目进度更新 │ │ │ ▣ work · 昨天 │ │ ├─────────────────────────────────────────┴────────────────────────────────┤ │ ↑ 上移 · ↓ 下移 · enter 查看详情 · / 搜索 · q 退出 │ └───────────────────────────────────────────────────────────────────────┘ ``` ### 布局说明 - **整体布局**:全屏 TTY 模式,清屏后占满整个终端窗口 - **列表区域**:占窗口宽度的 45%,高度的 80% - **详情区域**:占窗口宽度的 55% - **帮助栏**:固定在窗口最底部,使用系统内置帮助组件 ## 卡片样式 ### 卡片结构(每封邮件两行) ``` ┌─────────────────────────────────────────┐ │ 主题:邮件标题内容... │ ← 第一行:白色主题,Bold │ ▣ 账户 · 11小时前 │ ← 第二行:灰色账户+时间,有▣标记 └─────────────────────────────────────────┘ ``` ### 样式细节 - **未选中卡片**: - 主题行:白色前景,无背景,上内边距1,左右内边距1,下内边距0 - 元信息行:灰色前景(#241),无背景,上内边距0,左右内边距1,下内边距1 - **选中卡片**: - 主题行:白色前景,浅紫色背景(#99),上内边距1,左右内边距1,下内边距0 - 元信息行:浅紫色前景(#186),浅紫色背景(#99),上内边距0,左右内边距1,下内边距1 ### 主题色 - 背景色:`#99`(浅紫色) - 选中背景:`#99` - 标题前景:`#219`(粉色紫) ## 功能需求 | 功能 | 状态 | 说明 | |------|------|------| | 双栏布局(列表 + 详情) | ✅ | 列表45%,详情55% | | 全屏 TTY 模式 | ✅ | 使用 AltScreen,清屏 | | 卡片式邮件列表 | ✅ | 两行结构:主题 + 元信息 | | 选中高亮 | ✅ | 浅紫色背景 | | 帮助栏固定底部 | ✅ | 使用系统内置帮助组件 | | 列表高度80% | ✅ | 根据窗口高度动态计算 | | 搜索过滤功能 | ⏳ | 待实现 | | 详情面板显示完整邮件 | ⏳ | 待实现(需要按需获取) | ## 功能需求 | 功能 | 状态 | 说明 | |------|------|------| | 双栏布局(列表 + 详情) | ✅ | 列表45%,详情55% | | 全屏 TTY 模式 | ✅ | 使用 AltScreen,清屏 | | 卡片式邮件列表 | ✅ | 两行结构:主题 + 元信息 | | 选中高亮 | ✅ | 浅紫色背景 | | 帮助栏固定底部 | ✅ | 使用系统内置帮助组件 | | 列表高度80% | ✅ | 根据窗口高度动态计算 | | 搜索过滤功能 | ⏳ | 待实现 | | 详情面板显示完整邮件 | ✅ | 按回车获取完整邮件内容 | ## 技术要点 ### 关键实现 1. **TTY 模式**:`v.AltScreen = true` 在 View() 方法中设置 2. **宽度计算**:`int(float64(totalWidth) * 0.45)` 计算列表宽度 3. **高度计算**:`int(float64(msg.Height) * 0.8)` 设置列表高度为窗口的80% 4. **帮助栏**: - `l.SetShowHelp(true)` 启用内置帮助 - 自定义 `inboxHelpKeyMap` 实现 `ShortHelp()` 和 `FullHelp()` 接口 5. **卡片渲染**: - `emailDelegate.Height()` 返回 2(每卡片2行) - `emailDelegate.Spacing()` 返回 0(卡片间无间距) - 使用 `lipgloss.NewStyle().Width(width)` 固定宽度 - 使用 `truncateString()` 函数实现超出截断 ### 按回车获取详情实现 1. **InboxModel 新增字段**: - `loadingDetail bool` - 是否正在加载详情 - `selectedDetail *EmailDetail` - 已获取的详情数据 - `detailFetcher DetailFetcher` - 详情获取回调函数 2. **DetailFetcher 模式**:通过回调函数解耦获取逻辑,便于测试和扩展 3. **DetailResultMsg 消息**:异步获取完成后通过消息传递结果 4. **Spinner 加载动画**:使用 bubbles spinner 组件显示加载状态 5. **IMAP ID 命令**:QQ 邮箱需要发送 ID 命令通过 "Unsafe Login" 检查 ### 文件修改 - `inbox/model.go`:主要实现文件 - `inbox.go`:使用 `tea.NewProgram()` 创建程序 - `imap.go`:新增 `FetchEmailDetailByUID` 函数获取完整邮件内容 ## 实施步骤 | 步骤 | 描述 | 状态 | |------|------|------| | 1 | 创建讨论文档 | ✅ | | 2 | 升级 charm.land v2 依赖 | ✅ | | 3 | 实现双栏布局基础结构 | ✅ | | 4 | 实现 View() 全屏渲染 | ✅ | | 5 | 实现卡片样式(两行结构) | ✅ | | 6 | 实现选中高亮效果 | ✅ | | 7 | 添加帮助栏(系统内置) | ✅ | | 8 | 调整列表高度为80% | ✅ | | 9 | 移除边框,优化间距 | ✅ | | 10 | 实现右侧详情面板 | ✅ | | 11 | 添加搜索过滤功能 | ⏳ | | 12 | 实现按需获取完整邮件内容 | ✅ | ## 待优化项 1. **搜索功能**:启用 `list.SetFilteringEnabled(true)` 后需要实现过滤逻辑 2. **邮件数量**:当前只显示未读邮件,可扩展为支持所有邮件 3. **邮件操作**:查看、删除、标记已读等操作待实现