八、项目结构 (Project Structure)
本项目分为两个独立仓库:前端(Flutter 客户端)和后端(Dart Shelf 服务)。
8.1 前端目录结构
todo_app/
├── android/ ← Android 平台配置
│ └── app/src/main/
│ └── AndroidManifest.xml ← 权限声明(INTERNET · 通知 · 振动)
├── windows/ ← Windows 平台配置
├── lib/
│ ├── main.dart ← 应用入口,初始化各服务,按平台路由
│ ├── models/
│ │ └── todo.dart ← Todo 数据模型,Priority 枚举
│ ├── database/
│ │ └── database.dart ← Drift 数据库定义,表结构,迁移脚本
│ ├── repositories/
│ │ └── todo_repository.dart ← 数据访问层,CRUD + 离线队列入队
│ ├── services/
│ │ ├── api_service.dart ← REST 请求封装,Token 刷新,Correlation ID
│ │ ├── auth_service.dart ← JWT Token 本地持久化,deviceId 管理
│ │ ├── sse_service.dart ← SSE 长连接,断线重连,事件分发
│ │ ├── sync_service.dart ← 全量同步,增量同步,离线队列重放
│ │ ├── reminder_service.dart ← 到期提醒调度,按平台分发通知
│ │ ├── tray_service.dart ← Windows 系统托盘管理
│ │ └── notifications/
│ │ ├── notification_service.dart ← 通知抽象接口
│ │ ├── notification_service_android.dart ← Android 实现(awesome_notifications)
│ │ └── notification_service_desktop.dart ← Windows 实现(local_notifier)
│ ├── ui/
│ │ ├── screens/
│ │ │ ├── home_screen.dart ← Win11 主界面(侧边栏布局)
│ │ │ ├── home_screen_mobile.dart ← Android 主界面(底部导航栏)
│ │ │ ├── login_screen.dart ← 登录页
│ │ │ ├── register_screen.dart ← 注册页,含访客数据迁移
│ │ │ ├── forgot_password_screen.dart ← 忘记密码,发送验证码
│ │ │ └── reset_password_screen.dart ← 重置密码,验证码 + 新密码
│ │ └── widgets/
│ │ ├── sidebar.dart ← Win11 侧边栏,含日志查看入口
│ │ ├── todo_list_panel.dart ← 待办列表,搜索 + 排序
│ │ ├── todo_item_card.dart ← 单条待办卡片,移动端支持滑动手势
│ │ ├── todo_form_dialog.dart ← 新建 / 编辑弹窗,响应式布局
│ │ └── todo_detail_dialog.dart ← 详情弹窗,含编辑 / 删除入口
│ └── utils/
│ ├── app_logger.dart ← 前端日志工具(talker 封装,文件输出)
│ └── platform_util.dart ← 平台判断工具(isMobile / isDesktop)
├── pubspec.yaml ← 依赖声明
├── .env.example ← 环境变量模板(若有客户端配置)
└── .gitignore
前端各层说明
| 目录 | 层级 | 说明 |
|---|
models/ | 数据模型层 | 定义 Todo 类和 Priority 枚举,前后端共享相同的字段约定 |
database/ | 数据库层 | Drift ORM 表定义、schema 版本管理、迁移脚本,只负责本地 SQLite 读写 |
repositories/ | 数据访问层 | 统一的数据操作入口,联网时写操作同时写入 sync_queue |
services/ | 业务服务层 | 封装所有副作用:网络、推送连接、同步调度、通知、托盘 |
ui/screens/ | 页面层 | 各页面的整体布局与状态管理,调用 Service 层,不直接访问数据库 |
ui/widgets/ | 组件层 | 可复用的 UI 组件,尽量无状态,接收数据和回调作为参数 |
utils/ | 工具层 | 日志、平台判断等横切关注点,无业务逻辑 |
8.2 后端目录结构
todo_backend/
├── bin/
│ └── server.dart ← 应用入口,启动 HttpServer,注册所有路由
├── lib/
│ ├── config.dart ← 环境变量读取,统一配置入口
│ ├── database/
│ │ └── database.dart ← PostgreSQL 操作封装,建表,CRUD 方法
│ ├── handlers/
│ │ ├── auth_handler.dart ← 注册 / 登录 / Token 刷新 / 登出
│ │ ├── todo_handler.dart ← 待办 CRUD,写操作后触发 SSE 广播
│ │ ├── reset_handler.dart ← 忘记密码 / 发送验证码 / 重置密码
│ │ ├── event_handler.dart ← SSE 路由定义(实际处理已移至 server.dart)
│ │ └── log_handler.dart ← 日志查看接口,Basic Auth + Cookie + 限速
│ ├── middleware/
│ │ └── auth_middleware.dart ← JWT 验证,解析 userId 注入请求上下文
│ ├── services/
│ │ └── event_broadcaster.dart ← SSE 连接池,Map<userId, List<Controller>>
│ └── utils/
│ ├── jwt_util.dart ← Token 签发(access + refresh)与验证
│ ├── password_util.dart ← bcrypt 哈希与校验
│ ├── response_util.dart ← 统一 JSON 响应格式封装
│ ├── email_util.dart ← Resend 邮件发送(验证码邮件)
│ └── server_logger.dart ← 结构化日志,文件输出,日志读取接口
├── Dockerfile ← 多阶段构建,编译为原生二进制
├── docker-compose.yml ← api + db 两个容器的编排配置
├── pubspec.yaml ← 依赖声明
├── .env ← 敏感配置(不进仓库)
├── .env.example ← 配置模板(进仓库)
├── logs/ ← 日志文件目录(不进仓库)
└── .gitignore
后端各模块说明
| 目录 | 说明 |
|---|
bin/server.dart | 整个后端的启动入口。初始化 ServerLogger、数据库,注册路由,启动 HttpServer。SSE 请求在此处单独处理,绕过 shelf 直接使用原生 HttpResponse,以便设置 bufferOutput = false |
lib/config.dart | 所有环境变量的唯一读取入口,其他模块通过 Config.xxx 访问配置,不直接读 Platform.environment |
lib/database/ | PostgreSQL 的所有 SQL 操作封装为静态方法,Handler 层不直接拼 SQL |
lib/handlers/ | 每个业务域一个 Handler 文件,返回 shelf 的 Router,在 server.dart 中 mount 挂载 |
lib/middleware/ | authMiddleware 验证 JWT,将解析出的 userId 注入请求上下文,Handler 通过 getUserId(req) 取用 |
lib/services/ | EventBroadcaster 单例维护所有 SSE 连接,Handler 调用 broadcast() 推送事件 |
lib/utils/ | 无状态的工具函数,可被任意模块调用 |
8.3 数据库表结构
前端 SQLite(Drift)
| 表名 | 用途 | 核心字段 |
|---|
todos | 待办本地副本 | id · user_id · title · description · due_date · priority · is_completed · created_at · updated_at |
sync_queue | 离线操作队列(Outbox) | id · todo_id · operation · payload · created_at · user_id |
kv_store | 键值元数据存储 | key · value(存储 last_sync_time 等) |
后端 PostgreSQL
| 表名 | 用途 | 核心字段 |
|---|
users | 用户账号 | id · email · password_hash · nickname · created_at |
todos | 待办云端数据 | id · user_id · title · description · due_date · priority · is_completed · created_at · updated_at |
reset_codes | 密码重置验证码 | id · user_id · code · expires_at · used |