Skip to content

八、项目结构 (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 文件,返回 shelfRouter,在 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