docs: MULTI-ACCOUNT-PLAN.md 多账号架构方案 v0.1(单一事实源)

dsh+pi 共同遵守的多账号设计文档:
- 账号数据结构(displayName/gateway/token/username)
- 聚合/单独视图交互(账号选择器)
- 发信账号选择
- SSE 每账号一连接架构
- 配置页 UI
- Gateway API 映射
- 安全要点(已审计)
This commit is contained in:
2026-09-07 16:57:55 +08:00
parent fe96e197d3
commit 7278fcdf9a

158
docs/MULTI-ACCOUNT-PLAN.md Normal file
View File

@ -0,0 +1,158 @@
# 多账号架构方案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 里的讨论为依据。