- Complete MVP with Repository Pattern, SQLite storage - Provider + ChangeNotifier state management - Navigation 2.0 with deep link support - Habit CRUD with twoDayRule, notifications, categories - Backup/Restore via JSON - Statistics with streak tracking - Material You theme support - Biometric lock support - Desktop widget support - 27 languages i18n structure - Comprehensive test suite (87/89 passing)
688 lines
25 KiB
Markdown
688 lines
25 KiB
Markdown
# Habo 开发文档
|
||
|
||
> 版本: 3.1.2+5115 | Flutter 3.41.1+ | Dart 3.11.0+
|
||
|
||
Habo 是一款极简风格的习惯追踪应用,支持 Android、iOS、Linux、macOS 多平台。所有数据存储在本地 SQLite 数据库中,无需服务端。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [项目概览](#1-项目概览)
|
||
2. [技术栈与依赖](#2-技术栈与依赖)
|
||
3. [目录结构](#3-目录结构)
|
||
4. [架构设计](#4-架构设计)
|
||
5. [数据模型](#5-数据模型)
|
||
6. [数据库 Schema](#6-数据库-schema)
|
||
7. [核心模块详解](#7-核心模块详解)
|
||
8. [导航系统](#8-导航系统)
|
||
9. [状态管理](#9-状态管理)
|
||
10. [国际化 (i18n)](#10-国际化-i18n)
|
||
11. [主题系统](#11-主题系统)
|
||
12. [通知系统](#12-通知系统)
|
||
13. [备份与恢复](#13-备份与恢复)
|
||
14. [桌面端小组件](#14-桌面端小组件)
|
||
15. [生物识别认证](#15-生物识别认证)
|
||
16. [CI/CD 与构建](#16-cicd-与构建)
|
||
17. [开发指南](#17-开发指南)
|
||
|
||
---
|
||
|
||
## 1. 项目概览
|
||
|
||
Habo 是一个功能完整的习惯追踪应用,核心功能包括:
|
||
|
||
- **习惯管理** — 创建、编辑、归档、删除习惯,支持拖拽排序
|
||
- **两种习惯类型** — 布尔型(打卡/未打卡)和数值型(进度追踪,如跑步 5km)
|
||
- **日历视图** — 基于 `table_calendar` 的月度视图,标记每日状态
|
||
- **连续天数 (Streak)** — 支持普通模式和"两天法则"(允许间隔一天)
|
||
- **分类系统** — 习惯可归属多个分类,支持按分类筛选
|
||
- **统计分析** — 饼图总览、月度柱状图、个人习惯统计卡片
|
||
- **通知提醒** — 每日提醒和成就/惩罚通知
|
||
- **备份恢复** — JSON 文件导入/导出,支持跨设备迁移
|
||
- **桌面小组件** — iOS/Android 主屏幕小组件显示今日进度
|
||
- **生物识别锁** — 支持指纹/面容锁定应用
|
||
- **Material You** — 支持动态取色主题
|
||
|
||
---
|
||
|
||
## 2. 技术栈与依赖
|
||
|
||
| 类别 | 技术 | 说明 |
|
||
|------|------|------|
|
||
| 框架 | Flutter 3.41.1+ | 跨平台 UI 框架 |
|
||
| 语言 | Dart 3.11.0+ | 支持 null safety |
|
||
| 数据库 | sqflite / sqflite_common_ffi | SQLite(移动端/桌面端) |
|
||
| 状态管理 | provider + ChangeNotifier | 响应式状态管理 |
|
||
| 图表 | fl_chart | 统计图表渲染 |
|
||
| 日历 | table_calendar | 日历视图组件 |
|
||
| 通知 | awesome_notifications | 本地通知调度 |
|
||
| 国际化 | flutter_localizations + intl | ARB 文件管理多语言 |
|
||
| 字体 | google_fonts + 动态取色 | dynamic_color (Material You) |
|
||
| 音效 | flutter_soloud + audio_session | 习惯完成音效反馈 |
|
||
| 认证 | local_auth | 指纹/面容生物识别 |
|
||
| 小组件 | home_widget | iOS/Android 桌面小组件 |
|
||
| 桌面窗口 | window_manager | Linux/macOS 窗口管理 |
|
||
| 测试 | flutter_test + mocktail | 单元测试与 mock |
|
||
| CI | GitHub Actions | 自动测试与 APK 构建 |
|
||
| 发布 | fastlane | 多平台商店发布自动化 |
|
||
|
||
---
|
||
|
||
## 3. 目录结构
|
||
|
||
```
|
||
Habo-master/
|
||
├── lib/ # 应用主源码
|
||
│ ├── main.dart # 应用入口,初始化流程
|
||
│ ├── constants.dart # 枚举类型和颜色常量
|
||
│ ├── themes.dart # 主题定义(亮色/暗色/OLED)
|
||
│ ├── helpers.dart # 工具函数(日期解析等)
|
||
│ │
|
||
│ ├── model/ # 数据模型层
|
||
│ │ ├── habit_data.dart # HabitData 习惯数据模型
|
||
│ │ ├── habo_model.dart # HaboModel 数据库操作层
|
||
│ │ ├── category.dart # Category 分类模型
|
||
│ │ ├── settings_data.dart # 设置数据模型
|
||
│ │ └── backup.dart # 备份数据模型
|
||
│ │
|
||
│ ├── habits/ # 习惯管理模块
|
||
│ │ ├── habit.dart # Habit StatefulWidget(日历卡片)
|
||
│ │ ├── habits_manager.dart # HabitsManager 业务逻辑中心
|
||
│ │ ├── habits_screen.dart # 习惯列表主屏幕
|
||
│ │ ├── create_habit.dart # 创建习惯页面
|
||
│ │ └── edit_habit.dart # 编辑习惯页面
|
||
│ │
|
||
│ ├── statistics/ # 统计分析模块
|
||
│ │ ├── statistics.dart # 统计数据计算逻辑
|
||
│ │ ├── statistics_screen.dart # 统计主屏幕
|
||
│ │ ├── statistics_card.dart # 单个习惯统计卡片
|
||
│ │ ├── overall_statistics_card.dart # 总览饼图卡片
|
||
│ │ └── monthly_graph.dart # 月度柱状图
|
||
│ │
|
||
│ ├── settings/ # 设置模块
|
||
│ │ ├── settings_manager.dart # 设置管理器(持久化)
|
||
│ │ ├── settings_screen.dart # 设置页面 UI
|
||
│ │ └── color_icon.dart # 颜色选择器组件
|
||
│ │
|
||
│ ├── navigation/ # 导航系统
|
||
│ │ ├── routes.dart # 路由常量
|
||
│ │ ├── app_router.dart # RouterDelegate 实现
|
||
│ │ ├── app_state_manager.dart # 导航状态管理
|
||
│ │ ├── route_information_parser.dart # 深度链接解析
|
||
│ │ └── navigation.dart # 导出文件
|
||
│ │
|
||
│ ├── repositories/ # 数据仓库层(Repository Pattern)
|
||
│ │ ├── habit_repository.dart # 习惯仓库接口
|
||
│ │ ├── sqlite_habit_repository.dart # SQLite 实现
|
||
│ │ ├── event_repository.dart # 事件仓库接口
|
||
│ │ ├── category_repository.dart # 分类仓库接口
|
||
│ │ └── repository_factory.dart # 仓库工厂(DI)
|
||
│ │
|
||
│ ├── services/ # 服务层
|
||
│ │ ├── service_locator.dart # 服务定位器(DI 容器)
|
||
│ │ ├── notification_service.dart # 通知服务
|
||
│ │ ├── backup_service.dart # 备份/恢复服务
|
||
│ │ ├── ui_feedback_service.dart # UI 反馈服务(Snackbar)
|
||
│ │ ├── biometric_auth_service.dart # 生物识别服务
|
||
│ │ └── home_widget_service.dart # 桌面小组件服务
|
||
│ │
|
||
│ ├── widgets/ # 可复用 UI 组件
|
||
│ │ ├── habit_progress_indicator.dart # 进度指示器
|
||
│ │ ├── biometric_auth_wrapper.dart # 生物识别包裹组件
|
||
│ │ ├── category_filter_row.dart # 分类筛选行
|
||
│ │ ├── progress_input_modal.dart # 数值进度输入弹窗
|
||
│ │ ├── home_widget_data.dart # 小组件数据模型
|
||
│ │ ├── habo_home_widget.dart # 小组件渲染
|
||
│ │ └── text_container.dart # 文本输入组件
|
||
│ │
|
||
│ ├── onboarding/ # 引导页
|
||
│ │ ├── onboarding_screen.dart
|
||
│ │ └── onboarding.dart
|
||
│ │
|
||
│ ├── l10n/ # 国际化 ARB 文件(27 种语言)
|
||
│ └── generated/ # 自动生成的代码(intl 等)
|
||
│
|
||
├── test/ # 测试目录
|
||
├── assets/ # 静态资源
|
||
│ ├── images/ # 图片(含 onboard/ 引导图)
|
||
│ ├── sounds/ # 音效文件
|
||
│ └── google_fonts/ # 本地字体文件
|
||
│
|
||
├── android/ # Android 平台代码
|
||
├── ios/ # iOS 平台代码
|
||
├── linux/ # Linux 平台代码
|
||
├── macos/ # macOS 平台代码
|
||
├── fastlane/ # 发布自动化配置
|
||
├── .github/workflows/ci.yml # CI/CD 流水线
|
||
└── pubspec.yaml # 项目配置和依赖声明
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 架构设计
|
||
|
||
### 4.1 整体架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ Presentation Layer │
|
||
│ (Screens, Widgets) │
|
||
│ habits_screen statistics_screen settings_screen │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ Business Logic Layer │
|
||
│ HabitsManager (ChangeNotifier) │
|
||
│ SettingsManager │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ Service Layer │
|
||
│ NotificationService BackupService UIFeedbackService│
|
||
│ BiometricAuthService HomeWidgetService │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ Repository Layer │
|
||
│ HabitRepository EventRepository CategoryRepository│
|
||
│ RepositoryFactory │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ Data Layer │
|
||
│ HaboModel → SQLite (sqflite) │
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.2 设计模式
|
||
|
||
| 模式 | 应用场景 |
|
||
|------|----------|
|
||
| **Repository Pattern** | `HabitRepository`、`EventRepository`、`CategoryRepository` 抽象数据访问 |
|
||
| **Service Locator** | `ServiceLocator` 单例管理全局服务实例 |
|
||
| **Factory Pattern** | `RepositoryFactory` 创建各仓库实例 |
|
||
| **Observer Pattern** | `ChangeNotifier` + `Provider` 实现响应式 UI 更新 |
|
||
| **Singleton Pattern** | `HaboModel`、`ServiceLocator` 确保单实例 |
|
||
| **Strategy Pattern** | `HabitType` 枚举区分布尔/数值习惯的不同处理逻辑 |
|
||
|
||
### 4.3 数据流
|
||
|
||
```
|
||
用户操作 → Widget
|
||
→ HabitsManager (ChangeNotifier)
|
||
→ Repository (数据访问抽象)
|
||
→ HaboModel (SQLite 操作)
|
||
→ Database
|
||
|
||
HabitsManager.notifyListeners()
|
||
→ Provider 更新
|
||
→ Widget 重建
|
||
```
|
||
|
||
### 4.4 初始化流程 (`main.dart`)
|
||
|
||
```
|
||
1. SettingsManager 初始化(读取持久化设置)
|
||
2. 创建 HaboModel 实例(共享数据库连接)
|
||
3. 调用 HaboModel.initDatabase() 初始化 SQLite
|
||
4. 初始化 ServiceLocator(注册所有服务)
|
||
5. 创建 HabitsManager(注入仓库和服务依赖)
|
||
6. 调用 HabitsManager.loadHabits() 加载数据
|
||
7. 初始化通知服务
|
||
8. 创建 AppRouter(注入状态管理器)
|
||
9. 启动日变化定时器(检测跨日自动刷新)
|
||
10. 渲染 MaterialApp.router
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 数据模型
|
||
|
||
### 5.1 核心枚举 (`constants.dart`)
|
||
|
||
```dart
|
||
// 习惯类型
|
||
enum HabitType { boolean, numeric }
|
||
|
||
// 日状态类型
|
||
enum DayType { clear, check, fail, skip, progress }
|
||
|
||
// 主题模式
|
||
enum Themes { device, light, dark, oled, materialYou }
|
||
```
|
||
|
||
### 5.2 HabitData (`model/habit_data.dart`)
|
||
|
||
习惯的完整数据模型:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `int?` | 数据库自增主键 |
|
||
| `position` | `int` | 排序位置 |
|
||
| `title` | `String` | 习惯标题 |
|
||
| `twoDayRule` | `bool` | 是否启用两天法则 |
|
||
| `cue` | `String` | 提示(触发器) |
|
||
| `routine` | `String` | 例行动作描述 |
|
||
| `reward` | `String` | 奖励描述 |
|
||
| `showReward` | `bool` | 是否显示奖励通知 |
|
||
| `sanction` | `String` | 惩罚描述 |
|
||
| `showSanction` | `bool` | 是否显示惩罚通知 |
|
||
| `accountant` | `String` | 问责伙伴 |
|
||
| `advanced` | `bool` | 是否显示高级选项(cue/routine/reward) |
|
||
| `notification` | `bool` | 是否启用通知提醒 |
|
||
| `notTime` | `TimeOfDay` | 通知时间 |
|
||
| `events` | `SplayTreeMap<DateTime, List>` | 事件记录(日期→事件列表) |
|
||
| `habitType` | `HabitType` | 布尔型或数值型 |
|
||
| `targetValue` | `double` | 数值型目标值(默认 100) |
|
||
| `partialValue` | `double` | 数值型部分进度增量(默认 10) |
|
||
| `unit` | `String` | 数值型单位 |
|
||
| `categories` | `List<Category>` | 所属分类列表 |
|
||
| `archived` | `bool` | 是否已归档 |
|
||
| `streak` | `int` | 当前连续天数(运行时计算) |
|
||
|
||
**事件列表结构** (`events[date]`):
|
||
|
||
```
|
||
布尔型: [DayType, comment]
|
||
数值型: [DayType, comment, progressValue, targetValue]
|
||
```
|
||
|
||
**关键方法**:
|
||
- `isCompletedForDate(date)` — 判断某日是否完成
|
||
- `getProgressForDate(date)` — 获取某日进度值
|
||
- `getProgressPercentage(date)` — 获取进度百分比
|
||
|
||
### 5.3 Category (`model/category.dart`)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `int?` | 自增主键 |
|
||
| `title` | `String` | 分类名称 |
|
||
| `iconCodePoint` | `int` | 图标 Unicode 码点 |
|
||
| `fontFamily` | `String?` | 图标字体族(如 FontAwesome) |
|
||
|
||
---
|
||
|
||
## 6. 数据库 Schema
|
||
|
||
数据库版本: **9**,文件: `habo_db0.db`
|
||
|
||
### 6.1 habits 表
|
||
|
||
```sql
|
||
CREATE TABLE habits (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
position INTEGER, -- 排序位置
|
||
title TEXT, -- 习惯标题
|
||
twoDayRule INTEGER, -- 两天法则开关 (0/1)
|
||
cue TEXT DEFAULT '', -- 提示触发器
|
||
routine TEXT DEFAULT '', -- 例行动作
|
||
reward TEXT DEFAULT '', -- 奖励
|
||
showReward INTEGER, -- 显示奖励 (0/1)
|
||
advanced INTEGER, -- 高级模式 (0/1)
|
||
notification INTEGER, -- 通知开关 (0/1)
|
||
notTime TEXT, -- 通知时间 (HH:MM)
|
||
sanction TEXT DEFAULT '', -- 惩罚
|
||
showSanction INTEGER DEFAULT 0, -- 显示惩罚 (0/1)
|
||
accountant TEXT DEFAULT '', -- 问责伙伴
|
||
habitType INTEGER DEFAULT 0, -- 习惯类型 (0=布尔, 1=数值)
|
||
targetValue REAL DEFAULT 1.0, -- 目标值
|
||
partialValue REAL DEFAULT 1.0, -- 部分增量
|
||
unit TEXT DEFAULT '', -- 单位
|
||
archived INTEGER DEFAULT 0 -- 归档状态 (0/1)
|
||
);
|
||
```
|
||
|
||
### 6.2 events 表
|
||
|
||
```sql
|
||
CREATE TABLE events (
|
||
id INTEGER, -- 外键 → habits.id
|
||
dateTime TEXT, -- 日期时间字符串
|
||
dayType INTEGER, -- DayType 枚举索引
|
||
comment TEXT DEFAULT '', -- 备注
|
||
progressValue REAL DEFAULT 0.0, -- 进度值(数值习惯)
|
||
targetValue REAL DEFAULT 0.0, -- 目标值快照
|
||
PRIMARY KEY(id, dateTime),
|
||
FOREIGN KEY (id) REFERENCES habits(id) ON DELETE CASCADE
|
||
);
|
||
```
|
||
|
||
**DayType 枚举值**:
|
||
| 值 | 含义 |
|
||
|----|------|
|
||
| 0 | clear — 清除 |
|
||
| 1 | check — 完成 |
|
||
| 2 | fail — 失败 |
|
||
| 3 | skip — 跳过 |
|
||
| 4 | progress — 进行中(数值型部分完成) |
|
||
|
||
### 6.3 categories 表
|
||
|
||
```sql
|
||
CREATE TABLE categories (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
title TEXT NOT NULL, -- 分类名称
|
||
iconCodePoint INTEGER NOT NULL, -- 图标码点
|
||
fontFamily TEXT -- 图标字体族
|
||
);
|
||
```
|
||
|
||
### 6.4 habit_categories 关联表
|
||
|
||
```sql
|
||
CREATE TABLE habit_categories (
|
||
habit_id INTEGER NOT NULL,
|
||
category_id INTEGER NOT NULL,
|
||
PRIMARY KEY (habit_id, category_id),
|
||
FOREIGN KEY (habit_id) REFERENCES habits(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||
);
|
||
```
|
||
|
||
### 6.5 数据库迁移历史
|
||
|
||
| 版本 | 变更 |
|
||
|------|------|
|
||
| V1→V2 | events 表增加 `comment` 字段 |
|
||
| V2→V3 | habits 表增加 `sanction`、`showSanction`、`accountant` 字段 |
|
||
| V3→V4 | habits 表增加 `habitType`、`targetValue`、`partialValue`、`unit`;events 增加 `progressValue` |
|
||
| V4→V5 | events 表增加 `targetValue`;新建 `categories` 和 `habit_categories` 表 |
|
||
| V5→V6 | habits 表增加 `archived` 字段 |
|
||
| V6→V7 | events 表确保有 `targetValue`;categories 增加 `fontFamily` |
|
||
| V7→V8 | events 表确保有 `targetValue` |
|
||
| V8→V9 | events 表确保有 `targetValue` |
|
||
|
||
---
|
||
|
||
## 7. 核心模块详解
|
||
|
||
### 7.1 HabitsManager (`habits/habits_manager.dart`)
|
||
|
||
**中心业务逻辑管理器**,继承 `ChangeNotifier`,是整个应用的核心。
|
||
|
||
**职责**:
|
||
- 管理 habits 和 categories 的内存状态
|
||
- 协调 Repository 层的数据操作
|
||
- 集成通知、备份、UI 反馈等服务
|
||
- 处理拖拽排序、归档、undo 等交互逻辑
|
||
|
||
**核心 API**:
|
||
|
||
```dart
|
||
// 习惯 CRUD
|
||
Future<void> loadHabits()
|
||
Future<void> addHabit(Habit habit)
|
||
Future<void> editHabit(Habit habit)
|
||
Future<void> deleteHabit(int id)
|
||
Future<void> archiveHabit(int id)
|
||
void reorderList(int oldIndex, int newIndex)
|
||
|
||
// 事件操作
|
||
Future<void> addEvent(int id, DateTime date, List event)
|
||
Future<void> deleteEvent(int id, DateTime date)
|
||
|
||
// 分类操作
|
||
Future<void> loadCategories()
|
||
Future<void> addCategory(Category category)
|
||
Future<void> updateCategory(Category category)
|
||
Future<void> deleteCategory(int id)
|
||
Future<void> updateHabitCategories(int habitId, List<Category> categories)
|
||
|
||
// 服务调用
|
||
Future<void> createBackup()
|
||
Future<void> loadBackup(String path)
|
||
Future<void> resetNotifications()
|
||
void updateHomeWidget()
|
||
|
||
// 数据访问
|
||
List<Habit> get activeHabits // 未归档习惯
|
||
List<Habit> get archivedHabits // 已归档习惯
|
||
Habit? findHabitById(int id)
|
||
```
|
||
|
||
### 7.2 HaboModel (`model/habo_model.dart`)
|
||
|
||
**直接操作 SQLite 数据库的底层类**。
|
||
|
||
- 使用 `sqflite`(移动端)或 `sqflite_common_ffi`(Linux/macOS)
|
||
- 管理数据库创建、迁移、CRUD
|
||
- 处理 `PRAGMA foreign_keys = ON` 级联删除
|
||
|
||
### 7.3 Repository 层 (`repositories/`)
|
||
|
||
为 `HaboModel` 提供**抽象接口**,实现关注点分离:
|
||
|
||
- `HabitRepository` — 习惯 CRUD、排序、批量操作
|
||
- `EventRepository` — 事件增删查
|
||
- `CategoryRepository` — 分类 CRUD 及关联管理
|
||
- `RepositoryFactory` — 创建各 Repository 实例,注入 `HaboModel`
|
||
|
||
### 7.4 Service 层 (`services/`)
|
||
|
||
| 服务 | 职责 |
|
||
|------|------|
|
||
| `ServiceLocator` | 单例 DI 容器,初始化并持有所有服务实例 |
|
||
| `NotificationService` | 管理本地通知调度(每日提醒、奖励/惩罚) |
|
||
| `BackupService` | 数据库备份为 JSON 文件、从 JSON 恢复 |
|
||
| `UIFeedbackService` | 统一的 Snackbar 消息展示(成功/失败/警告) |
|
||
| `BiometricAuthService` | 封装 `local_auth` 生物识别认证 |
|
||
| `HomeWidgetService` | 更新 iOS/Android 主屏幕小组件数据 |
|
||
|
||
---
|
||
|
||
## 8. 导航系统
|
||
|
||
采用 **Flutter Navigation 2.0**,基于 `RouterDelegate`。
|
||
|
||
### 路由定义
|
||
|
||
| 常量 | 路径 | 页面 |
|
||
|------|------|------|
|
||
| `splashPath` | `/` | 启动页 |
|
||
| `habitsPath` | `/habits` | 习惯列表主页 |
|
||
| `statisticsPath` | `/statistics` | 统计页 |
|
||
| `settingsPath` | `/settings` | 设置页 |
|
||
| `onboardingPath` | `/onboarding` | 引导页 |
|
||
| `createHabitPath` | `/create` | 创建习惯 |
|
||
| `editHabitPath` | `/edit` | 编辑习惯 |
|
||
| `whatsNewPath` | `/whatsnew` | 更新日志 |
|
||
|
||
### 深度链接
|
||
|
||
支持 `habo://` scheme,例如 `habo://settings` 直接跳转设置页。
|
||
|
||
### 关键类
|
||
|
||
- **`AppRouter`** — `RouterDelegate` 实现,管理页面栈
|
||
- **`AppStateManager`** — 管理各页面的显示状态(bool 标志位)
|
||
- **`HaboRouteInformationParser`** — 解析 URL 到 `HaboRouteConfiguration`
|
||
|
||
---
|
||
|
||
## 9. 状态管理
|
||
|
||
使用 **Provider + ChangeNotifier** 模式:
|
||
|
||
```
|
||
MultiProvider(
|
||
providers:
|
||
- ChangeNotifierProvider<SettingsManager>
|
||
- ChangeNotifierProvider<HabitsManager>
|
||
- ChangeNotifierProvider<AppStateManager>
|
||
)
|
||
```
|
||
|
||
- `HabitsManager` — 习惯数据变化时调用 `notifyListeners()`,驱动 UI 重建
|
||
- `SettingsManager` — 设置变更时通知(主题、音效等)
|
||
- `AppStateManager` — 导航状态变更通知
|
||
- **注意**: `AppRouter` 不监听 `HabitsManager`,避免数据变化导致非预期的导航跳转
|
||
|
||
---
|
||
|
||
## 10. 国际化 (i18n)
|
||
|
||
- 使用 `flutter_intl` + ARB 文件管理
|
||
- 文件位于 `lib/l10n/intl_*.arb`
|
||
- 支持 **27 种语言**:
|
||
- 中文(简体/繁体)、英语、西班牙语、法语、德语、意大利语、葡萄牙语、俄语、日语(未列出但可能有)、阿拉伯语、希伯来语、波兰语、荷兰语、瑞典语、捷克语、越南语、印尼语、土耳其语、乌克兰语、加泰罗尼亚语、斯洛伐克语、巴斯克语、世界语、挪威语等
|
||
- 生成代码在 `lib/generated/` 目录
|
||
|
||
**添加新语言**:
|
||
1. 在 `lib/l10n/` 下创建 `intl_<locale>.arb`
|
||
2. 运行 `flutter gen-l10n` 生成代码
|
||
|
||
---
|
||
|
||
## 11. 主题系统
|
||
|
||
`HaboTheme` 类提供三种主题:
|
||
|
||
| 主题 | 说明 |
|
||
|------|------|
|
||
| `lightTheme` | 浅色主题,浅灰背景 (#FAFAFA) |
|
||
| `darkTheme` | 深色主题,纯黑背景 (#000000) |
|
||
| `oledTheme` | OLED 深色主题,纯黑背景 |
|
||
|
||
**主题模式** (`Themes` 枚举):
|
||
- `device` — 跟随系统
|
||
- `light` — 强制浅色
|
||
- `dark` — 强制深色
|
||
- `oled` — OLED 黑色
|
||
- `materialYou` — Material You 动态取色
|
||
|
||
**特性**:
|
||
- 使用 Google Fonts 自定义字体
|
||
- 主色调: `#09BF30`(绿色)
|
||
- 支持平台差异(iOS/Android 不同组件样式)
|
||
|
||
---
|
||
|
||
## 12. 通知系统
|
||
|
||
使用 `awesome_notifications` 实现本地通知:
|
||
|
||
- **每日提醒** — 用户设定时间推送提醒
|
||
- **奖励通知** — 完成习惯时触发(可配置音效)
|
||
- **惩罚通知** — 习惯失败时触发
|
||
|
||
`NotificationService` 通过 `HabitsManager` 调用:
|
||
- `resetNotifications()` — 重置所有习惯通知
|
||
- `removeNotifications(id)` — 删除指定习惯的通知
|
||
- `handleHabitEventAdded()` — 事件添加后触发通知
|
||
|
||
---
|
||
|
||
## 13. 备份与恢复
|
||
|
||
`BackupService` 提供完整的数据导入/导出:
|
||
|
||
- **导出**: 将所有 habits、events、categories 序列化为 JSON 文件
|
||
- **导入**: 从 JSON 文件解析并恢复到数据库
|
||
- **兼容性**: 支持旧版格式迁移
|
||
- **文件选择**: 使用 `flutter_file_dialog`(移动端)或 `file_picker`(桌面端)
|
||
|
||
---
|
||
|
||
## 14. 桌面端小组件
|
||
|
||
使用 `home_widget` 包实现 iOS/Android 主屏幕小组件:
|
||
|
||
- **小组件类型**: 170x170 圆形进度指示器
|
||
- **数据传递**: 通过 `HomeWidgetService` 更新数据
|
||
- **显示内容**: 今日习惯完成数量 / 总数量
|
||
- **渲染**: `CircularProgressPainter` 自定义绘制多段圆弧
|
||
|
||
---
|
||
|
||
## 15. 生物识别认证
|
||
|
||
- `BiometricAuthService` 封装 `local_auth`
|
||
- `BiometricAuthWrapper` Widget 包裹主内容
|
||
- 支持指纹和面容识别
|
||
- 应用从后台恢复时重新验证
|
||
- 认证失败提供重试对话框
|
||
|
||
---
|
||
|
||
## 16. CI/CD 与构建
|
||
|
||
### GitHub Actions (`ci.yml`)
|
||
|
||
**触发条件**: push/PR 到 `main` 或 `develop` 分支
|
||
|
||
**流水线**:
|
||
1. **test** — `flutter analyze` + `flutter test`
|
||
2. **build-android**(依赖 test 通过):
|
||
- `flutter build apk --release --split-per-abi --no-tree-shake-icons`
|
||
- 按 CPU 架构分拆 APK(arm64-v8a, armeabi-v7a, x86_64)
|
||
- 上传构建产物
|
||
|
||
### 本地构建
|
||
|
||
```bash
|
||
# 安装依赖
|
||
flutter pub get
|
||
|
||
# 生成图标包
|
||
dart run flutter_iconpicker:generate_packs --packs fontAwesomeIcons
|
||
|
||
# 生成国际化代码
|
||
flutter gen-l10n
|
||
|
||
# 运行测试
|
||
flutter test
|
||
|
||
# 构建 APK
|
||
flutter build apk --release
|
||
|
||
# 构建 iOS
|
||
flutter build ios --release
|
||
|
||
# 桌面端
|
||
flutter build linux --release
|
||
flutter build macos --release
|
||
```
|
||
|
||
### Fastlane
|
||
|
||
`fastlane/` 目录包含多平台商店发布的自动化配置。
|
||
|
||
---
|
||
|
||
## 17. 开发指南
|
||
|
||
### 环境要求
|
||
|
||
- Flutter SDK >= 3.41.1
|
||
- Dart SDK >= 3.11.0
|
||
- Android: Java 17, minSdk 21
|
||
- iOS: Xcode (最新版)
|
||
- Linux: 额外依赖 `sqflite_common_ffi`
|
||
|
||
### 项目约定
|
||
|
||
1. **状态管理** — 使用 `ChangeNotifier` + `Provider`,新功能应创建 Manager 类
|
||
2. **数据访问** — 通过 Repository 接口,不直接使用 `HaboModel`
|
||
3. **服务依赖** — 通过 `ServiceLocator` 获取,不手动创建实例
|
||
4. **国际化** — 所有用户可见文本必须使用 `AppLocalizations`,不硬编码字符串
|
||
5. **主题** — 使用 `HaboTheme` 定义的颜色和样式,不直接写色值
|
||
6. **数据库迁移** — 修改 Schema 必须新增迁移方法并更新 `_dbVersion`
|
||
7. **测试** — 使用 `mocktail` mock Repository 层,测试业务逻辑而非 UI 渲染
|
||
|
||
### 添加新功能的典型流程
|
||
|
||
1. 在 `model/` 中定义或修改数据模型
|
||
2. 在 `repositories/` 中添加/更新 Repository 接口和实现
|
||
3. 在 `services/` 中添加服务(如需要)
|
||
4. 在 `HabitsManager` 中添加业务逻辑方法
|
||
5. 在对应的 screen/widget 中实现 UI
|
||
6. 在 `lib/l10n/intl_en.arb` 中添加国际化文本
|
||
7. 编写单元测试
|
||
|
||
### 关键文件速查
|
||
|
||
| 需求 | 文件 |
|
||
|------|------|
|
||
| 添加新习惯字段 | `model/habit_data.dart` + `model/habo_model.dart` + 数据库迁移 |
|
||
| 修改日历行为 | `habits/habit.dart` |
|
||
| 添加新统计图表 | `statistics/` 目录 |
|
||
| 修改通知逻辑 | `services/notification_service.dart` |
|
||
| 添加新设置项 | `settings/settings_manager.dart` + `settings_screen.dart` |
|
||
| 修改导航流程 | `navigation/app_router.dart` + `navigation/app_state_manager.dart` |
|
||
| 添加新语言 | `lib/l10n/intl_<locale>.arb` |
|
||
| 修改主题 | `themes.dart` |
|