Appearance
二、系统架构设计 (Architecture)
2.1 整体架构图
下图展示了 TodoApp 的整体技术架构,从客户端到服务端的完整层次关系。

2.2 通信协议分工
系统采用两种通信协议,各自承担不同职责,互相配合:
| 协议 | 方向 | 用途 |
|---|---|---|
| REST (HTTPS) | 客户端 → 服务端(主动请求) | 登录 / 注册 / 密码重置 · 待办增 / 改 / 删 · 全量 / 增量数据拉取 |
| SSE (HTTPS) | 服务端 → 客户端(被动推送) | 其他设备修改待办 → 通知本端刷新 · 其他设备删除待办 → 通知本端删除 |
为什么不用 WebSocket?
WebSocket 是双向通信协议,适合聊天、游戏等需要客户端主动向服务端推送消息的场景。本项目的实时通知是严格单向的(服务端广播 → 客户端接收),SSE 完全够用,且实现更简单,对 Nginx 代理的配置要求也更低。
2.3 前端分层架构
| 层级 | 包含模块 | 职责 |
|---|---|---|
| UI 层 | HomeScreen · HomeScreenMobile · TodoItemCard · TodoDetailDialog · TodoFormDialog · LoginScreen … | 渲染界面与处理用户交互,不直接访问网络或数据库 |
| Service 层 | ApiService · SseService · SyncService · AuthService · CryptoService · ReminderService · RoutineScheduler · NotificationService · DeviceService · ThemeService · TrayService | 封装所有副作用:网络请求、SSE 连接、同步调度、E2EE 加解密、提醒与 routine 调度、系统通知、设备标识、主题、托盘 |
| Repository 层 | TodoRepository | 统一数据访问入口,屏蔽本地与远端差异;联网时写操作同时入 sync_queue |
| Database 层 | AppDatabase (Drift/SQLite):todos 表 · sync_queue 表 · kv_store 表 | 本地 SQLite 读写,不感知网络状态 |
2.4 后端模块划分
bin/
└── server.dart ← 入口:启动 HttpServer,注册路由,SSE 原生处理
lib/
├── config.dart ← 环境变量读取(.env)
├── handlers/
│ ├── auth_handler.dart ← 注册 / 登录 / Token 刷新 / 登出
│ ├── todo_handler.dart ← 待办 CRUD,写完触发 SSE 广播
│ ├── reset_handler.dart ← 忘记密码 / 验证码 / 重置密码
│ ├── event_handler.dart ← SSE 长连接建立(已迁移至 server.dart)
│ ├── log_handler.dart ← 日志查看接口(Basic Auth 保护)
│ └── dashboard_handler.dart ← 运维监控后台(Basic Auth 保护)
├── middleware/
│ └── auth_middleware.dart ← JWT 验证,注入 userId 到请求上下文
├── services/
│ └── event_broadcaster.dart ← SSE 连接池,管理多端广播
├── database/
│ └── database.dart ← PostgreSQL 操作封装
└── utils/
├── jwt_util.dart ← Token 签发与验证
├── password_util.dart ← bcrypt 哈希
├── response_util.dart ← 统一响应格式
├── email_util.dart ← 邮件发送(QQ 邮箱 SMTP · mailer 包)
└── server_logger.dart ← 结构化日志工具2.5 数据流向全景
在线写操作(以"新建待办"为例)

离线写操作(断网时新建待办)

SSE 事件处理链路

2.6 跨平台响应式外壳
TodoApp 用一套代码同时支持 Win11 桌面端和 Android 移动端,两端在导航结构和交互方式上差异显著,通过 PlatformUtil 在运行时动态切换。

两端的核心差异:
| 交互维度 | Win11 桌面端 | Android 移动端 |
|---|---|---|
| 导航结构 | 侧边栏 | 底栏 |
| 编辑 / 删除 | 点击卡片进详情,弹窗内操作 | 右滑展开编辑 / 删除按钮 |
| 窗口管理 | 关闭拦截 + 最小化至系统托盘 | 标准 Android 生命周期 |
| 通知方式 | 系统托盘通知 | 推送通知 |