Files
MailUI4Agents/docs/MULTI-ACCOUNT-PLAN.md
JianFeeeee 7278fcdf9a docs: MULTI-ACCOUNT-PLAN.md 多账号架构方案 v0.1(单一事实源)
dsh+pi 共同遵守的多账号设计文档:
- 账号数据结构(displayName/gateway/token/username)
- 聚合/单独视图交互(账号选择器)
- 发信账号选择
- SSE 每账号一连接架构
- 配置页 UI
- Gateway API 映射
- 安全要点(已审计)
2026-09-07 16:57:55 +08:00

159 lines
6.4 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.

# 多账号架构方案Multi-Account Plan
> 本文档是 Electron/鸿蒙客户端多账号能力的单一事实源。
> piAPI 维护方编写dsh + pi 共同遵守。
> 版本v0.1 | 日期2026-09-07
---
## 一、需求背景
jianf 要求:像真正的邮箱 app 一样,**支持多账号登录、邮件单独/聚合显示**。只聚合收件箱,其余功能各账号独立。
---
## 二、架构总览
```
┌──────────────────────────────────────────────────┐
│ AccountStore状态管理
│ • accounts: Account[] 所有已添加的账号 │
│ • activeAccount: string 当前选中("all"=聚合) │
│ • add / remove / switch 账号 CRUD + 切换 │
├──────────────────────────────────────────────────┤
│ AccountManager持久层
│ • electron-store / preferences JSON │
│ • 字段:{ id, displayName, gateway, token, │
│ username?, lastUsed? } │
│ • 主进程暴露 IPCElectron/ 本地存储(鸿蒙) │
├──────────────────────────────────────────────────┤
│ MultiSSE多连接管理
│ • 每账号独立 EventSource各带自己的 user_key
│ • 事件打到对应账号的 store │
│ • 账号删除时关停对应连接 │
├──────────────────────────────────────────────────┤
│ UI 层 │
│ • 顶栏账号选择器(全部邮箱 / 单个账号下拉) │
│ • 收件箱:单账号(现状) / 聚合(合并+账号徽标) │
│ • 写信页:默认当前选中账号,顶栏可切换 │
└──────────────────────────────────────────────────┘
```
---
## 三、账号数据结构
```json
{
"id": "acct-uuid-1",
"displayName": "工作邮箱",
"gateway": "http://192.168.2.60:8180",
"token": "833c27ef...",
"username": "gui-lab",
"lastUsed": "2026-09-07T12:00:00Z"
}
```
| 字段 | 必填 | 说明 |
|---|---|---|
| `id` | 自动生成 | 内部唯一标识,不暴露给用户 |
| `displayName` | 是 | 显示用名(如「工作邮箱」),不是登录用户名 |
| `gateway` | 是 | Gateway 地址(`http://ip:port`),不同实例 |
| `token` | 是 | permanent user_keyBearer 认证) |
| `username` | 否 | 登录用户名(仅下次验证用,可留空) |
| `lastUsed` | 自动 | 最近一次选中时间,用于默认主账号 |
头像/别名不做——AgentMail 没有头像概念,显示名够。
---
## 四、聚合/单独视图交互
**顶栏账号选择器**(类似 Outlook account switcher
- 下拉列出所有账号 + 「全部邮箱」聚合项
- 选「全部邮箱」→ 收件箱聚合模式
- 选单个账号 → 只显示该账号邮件(现状)
`AccountStore` 维护当前选中(`"all"` 或某个 account id收件箱组件据此决定单账号请求或多账号合并。聚合时给每封邮件加账号归属徽标。
---
## 五、发信账号选择
- 默认用**当前选中账号**发
- 聚合模式下默认**第一个添加的账号**或最近使用的主账号
- 写信页顶栏加下拉切换(仅影响这一封的发信账号,不改变收件箱当前视图)
- 选了就只影响这一封,下次写信恢复到默认
---
## 六、SSE 多连接架构
**核心原则:每账号各建一条 SSE 连接**,因为服务端按 user_key 归属用户,一条连接只能收到一个用户的消息。
```
AccountManager
├─ acct-1 (Token A, Gateway A) ── EventSource ──> new_mail → acct-1 store
├─ acct-2 (Token B, Gateway B) ── EventSource ──> new_mail → acct-2 store
└─ acct-3 (Token C, Gateway A) ── EventSource ──> new_mail → acct-3 store
```
- `MultiSSE` 维护连接集合:每个 account 一条 `EventSource`
- 新邮件事件打到**对应账号**的 store
- 单独视图:直接刷新对应账号
- 聚合视图:把新邮件汇入合并列表
- 账号删除时关停对应连接
- 账号切换不关停:所有连接并行运行,切换只改变 UI 过滤条件
---
## 七、配置页 UI
**账号列表**:每个账号卡片显示:
- 显示名(大字)
- Gateway 地址(小字)
- 在线状态(🟢/🔴,基于最近一次 API 响应)
- 操作:切换为主账号 / 编辑 / 删除
**添加账号流程**
1. 输入 Gateway 地址
2. 输入 user_key粘贴或扫码暂定粘贴
3. 可选:输入显示名(默认用 gateway 域名/IP 生成)
4. 验证:调用 `GET /auth/me`Bearer token确认连通
5. 保存并加入账号列表
---
## 八、与 Gateway API 的映射
| 客户端操作 | Gateway API | 多账号处理 |
|---|---|---|
| 加载收件箱 | `GET /me/mail/inbox` | 每账号一次请求,合并 |
| 加载会话列表 | `GET /me/sessions` | 单账号(聚合时也只看当前选中) |
| 发信 | `POST /me/mail/send` | 用当前选中账号的 token |
| SSE | `GET /events/stream` | 每账号独立连接 |
| 认证 | `GET /auth/me` | 每个 token 独立验证 |
---
## 九、安全要点(已审计)
- 每个 user_key 只对应一个用户,水平权限由 `UserCanAccessSession` 阻挡
- `?access_token=` 仅 SSE + 附件下载两处接受(桌面客户端用 Bearer header不依赖 query
- 账号配置存储本地加密electron-store 加密),不写磁盘明文
---
## 十、两边实现对齐
| 维度 | 鸿蒙dsh | elepi |
|---|---|---|
| 账号存储 | preferences JSON | electron-storeencrypted |
| SSE 多连接 | 改造中(当前单连接) | 需新增 |
| 聚合收件箱 | 已实现M7 | 需新增 |
| 账号选择器 UI | 需新增 | 需新增 |
| 写信账号切换 | 需新增 | 需新增 |
两边都以此文档为准,不以 cc 里的讨论为依据。