api实现
This commit is contained in:
259
docs/dev/CRASH_FIX_LOG.md
Normal file
259
docs/dev/CRASH_FIX_LOG.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# 🔥 卡死/闪退问题分析与修复记录
|
||||
|
||||
> 文档创建: 2026-04-09
|
||||
> 最后更新: 2026-04-09
|
||||
> 维护者: 前端工程师
|
||||
> 说明: 记录项目中所有可能导致应用卡死、闪退的潜在问题,跟踪修复进度
|
||||
|
||||
---
|
||||
|
||||
## 📊 问题总览
|
||||
|
||||
| 等级 | 数量 | 已修复 | 待修复 |
|
||||
|------|------|--------|--------|
|
||||
| 🔴 高危 | 4 | 4 | 0 |
|
||||
| 🟠 中危 | 3 | 3 | 0 |
|
||||
| 🟡 低危 | 4 | 3 | 1 |
|
||||
| **合计** | **11** | **10** | **1** |
|
||||
|
||||
---
|
||||
|
||||
## 🔴 高危问题(直接导致闪退)
|
||||
|
||||
### #1 Hive `late` Box 未初始化访问
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P0
|
||||
- **文件**: `lib/src/services/data/hive_service.dart`
|
||||
- **触发路径**:
|
||||
1. `MealRecordController.onInit()` → `_loadDayRecords()` → `HiveService().getMealRecordsByDate()`
|
||||
2. `getMealRecordsByDate()` 访问 `mealRecords.values`,但 `mealRecords` 是 `late Box`
|
||||
3. 如果 `HiveService.init()` 尚未完成,`late` 字段未赋值 → `LateInitializationError` → 闪退
|
||||
- **修复方案**:
|
||||
- `late Box` 改为 `Box?` 可空类型
|
||||
- 所有 getter 加 `_assertInitialized()` 检查
|
||||
- Controller 中所有 Hive 读取操作前加 `if (!hive.isInitialized) return;`
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #2 ApiService 缓存竞态条件
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P0
|
||||
- **文件**: `lib/src/services/api/api_service.dart`
|
||||
- **触发路径**:
|
||||
1. `ApiService._internal()` 构造函数中调用 `_initCacheAsync()` (fire-and-forget)
|
||||
2. `_cacheOptions` 是 `late CacheOptions`,在 `_initCacheAsync()` 完成前未赋值
|
||||
3. 如果首次网络请求在缓存初始化完成前发起 → 访问未初始化的 `late` 字段 → 闪退
|
||||
- **修复方案**:
|
||||
- `late CacheOptions` 改为 `CacheOptions?`
|
||||
- 添加 `Completer<void>` 跟踪初始化状态
|
||||
- `_ensureCacheReady()` 等待 Completer 完成
|
||||
- `_tryGetCache()` 加 null 检查
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #3 Get.find 未注册 Controller 闪退
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P1
|
||||
- **文件**: `lib/src/controllers/what_to_eat_controller.dart`
|
||||
- **触发路径**:
|
||||
1. `_fetchSmartWithPreferences()` 中调用 `Get.find<PreferenceController>()`
|
||||
2. 如果 `PreferenceController` 未被 `Get.put` 注册 → 抛出异常 → 闪退
|
||||
- **修复方案**: 使用 `Get.isRegistered<T>()` 先判断再 `find`
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #4 Platform API 在 Web 平台崩溃
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P1
|
||||
- **文件**: `lib/src/utils/platform_utils.dart`
|
||||
- **触发路径**:
|
||||
1. 直接使用 `Platform.isIOS`、`Platform.isAndroid` 等
|
||||
2. 在 Web 平台调用 → `UnsupportedError` → 闪退
|
||||
- **修复方案**:
|
||||
- 使用条件导入 `import 'dart:io' if (dart.library.html) 'platform_web_stub.dart'`
|
||||
- 所有 `Platform.*` 调用前加 `if (kIsWeb) return false;`
|
||||
- 创建 `platform_web_stub.dart` 提供 Web 平台 stub
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
## 🟠 中危问题(可能导致卡死)
|
||||
|
||||
### #5 网络请求无超时兜底
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P2
|
||||
- **文件**: `lib/src/services/api/api_service.dart`
|
||||
- **触发路径**:
|
||||
1. `_isOffline()` 调用 `Connectivity().checkConnectivity()`
|
||||
2. 该方法本身可能卡住(如网络权限未授予)
|
||||
3. 虽然 Dio 设置了 10s 超时,但连接性检查无超时
|
||||
- **修复方案**: 给 `_isOffline()` 加 `.timeout(Duration(seconds: 3))` 限制,超时默认视为离线
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #6 `runWithLoading` 嵌套调用状态错乱
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P2
|
||||
- **文件**: `lib/src/controllers/base/base_controller.dart`
|
||||
- **触发路径**:
|
||||
1. `isLoading` 是单一 `RxBool`
|
||||
2. 如果外层 `runWithLoading` 内部又调用 `runWithLoading`
|
||||
3. 内层完成后 `isLoading = false`,但外层仍在执行
|
||||
4. UI 显示加载完成,但数据可能不完整 → 用户操作异常
|
||||
- **修复方案**: 使用计数器 `_loadingCount` 替代布尔值,仅当计数归零时设 `isLoading = false`
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #7 Hive Box 同步操作阻塞主线程
|
||||
|
||||
- **状态**: ✅ 已修复(低优先级标记)
|
||||
- **优先级**: P3
|
||||
- **文件**: `lib/src/services/data/hive_service.dart`
|
||||
- **触发路径**:
|
||||
1. `getMealRecordsByDate()`、`getWeeklyCalories()` 等同步遍历 Box
|
||||
2. 数据量大时(如数百条记录)阻塞 UI 线程
|
||||
3. 用户感觉"卡死"
|
||||
- **修复方案**:
|
||||
- 短期: 当前数据量不大,影响可忽略
|
||||
- 长期: 改为 `compute` 或 `Isolate` 执行重计算
|
||||
- **修复日期**: 2026-04-09(标记为低优先级,暂不需要 Isolate)
|
||||
|
||||
---
|
||||
|
||||
## 🟡 低危问题(边界情况)
|
||||
|
||||
### #8 SharedPreferences 初始化前访问
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P3
|
||||
- **文件**: `lib/src/services/data/storage_service.dart`
|
||||
- **触发路径**:
|
||||
1. `_prefs` 是 `late SharedPreferences`
|
||||
2. 如果 `init()` 未完成就调用 `getString()` 等 → `LateInitializationError`
|
||||
- **修复方案**:
|
||||
- `late SharedPreferences` 改为 `SharedPreferences?`
|
||||
- 添加 `isInitialized` 标志
|
||||
- 读取方法用 `_prefs?.` 安全调用,返回 null
|
||||
- 写入方法加 `if (_prefs == null) return;` 静默跳过
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #9 LoggerService 初始化前写日志
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P3
|
||||
- **文件**: `lib/src/services/log/logger_service.dart`
|
||||
- **修复内容**: `_logger` 改为 `Logger?`,所有调用处加 null 检查,降级到 `debugPrint`
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #10 PageRoute 中间件拦截循环
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P3
|
||||
- **文件**: `lib/src/standards/route_middleware.dart`
|
||||
- **触发路径**:
|
||||
1. 如果 `/standards-violation` 页面自身也校验失败
|
||||
2. 中间件再次重定向到 `/standards-violation` → 无限循环
|
||||
- **修复方案**: 对 `/standards-violation` 路由跳过校验,直接 `return null`
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
### #11 MediaQuery 在 Context 不完整时崩溃
|
||||
|
||||
- **状态**: ✅ 已修复
|
||||
- **优先级**: P0
|
||||
- **文件**: `lib/src/standards/page_standards.dart`
|
||||
- **修复内容**: 所有 `MediaQuery.of(context)` 调用加 `try-catch`,降级到默认值
|
||||
- **修复日期**: 2026-04-09
|
||||
|
||||
---
|
||||
|
||||
## 📋 修复进度
|
||||
|
||||
| # | 问题 | 优先级 | 状态 | 修复日期 |
|
||||
|---|------|--------|------|----------|
|
||||
| 1 | Hive late Box 未初始化 | P0 | ✅ 已修复 | 2026-04-09 |
|
||||
| 2 | ApiService 缓存竞态 | P0 | ✅ 已修复 | 2026-04-09 |
|
||||
| 3 | Get.find 未注册 Controller | P1 | ✅ 已修复 | 2026-04-09 |
|
||||
| 4 | Platform API Web 崩溃 | P1 | ✅ 已修复 | 2026-04-09 |
|
||||
| 5 | 网络请求无超时兜底 | P2 | ✅ 已修复 | 2026-04-09 |
|
||||
| 6 | runWithLoading 嵌套 | P2 | ✅ 已修复 | 2026-04-09 |
|
||||
| 7 | Hive 同步操作阻塞 | P3 | ✅ 标记低优 | 2026-04-09 |
|
||||
| 8 | SharedPreferences 未初始化 | P3 | ✅ 已修复 | 2026-04-09 |
|
||||
| 9 | LoggerService 未初始化 | P3 | ✅ 已修复 | 2026-04-09 |
|
||||
| 10 | 中间件拦截循环 | P3 | ✅ 已修复 | 2026-04-09 |
|
||||
| 11 | MediaQuery 空值崩溃 | P0 | ✅ 已修复 | 2026-04-09 |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 修复详情
|
||||
|
||||
### 2026-04-09 修复批次(第二轮)
|
||||
|
||||
1. **Hive late Box 未初始化** (#1)
|
||||
- `late Box<T>` → `Box<T>?`,getter 加 `_assertInitialized()`
|
||||
- `MealRecordController` 所有 Hive 读取加 `if (!hive.isInitialized) return;`
|
||||
|
||||
2. **ApiService 缓存竞态** (#2)
|
||||
- `late CacheOptions` → `CacheOptions?`
|
||||
- 添加 `Completer<void>` 跟踪初始化
|
||||
- `_ensureCacheReady()` 等待 Completer
|
||||
- `_tryGetCache()` 加 null 检查
|
||||
|
||||
3. **Get.find 未注册 Controller** (#3)
|
||||
- `Get.find<T>()` 前加 `Get.isRegistered<T>()` 判断
|
||||
|
||||
4. **Platform API Web 崩溃** (#4)
|
||||
- 条件导入 `dart:io if (dart.library.html)`
|
||||
- 所有 `Platform.*` 调用前加 `kIsWeb` 检查
|
||||
- 创建 `platform_web_stub.dart`
|
||||
|
||||
5. **网络请求超时兜底** (#5)
|
||||
- `_isOffline()` 加 `.timeout(Duration(seconds: 3))`
|
||||
- 超时默认视为离线
|
||||
|
||||
6. **runWithLoading 嵌套** (#6)
|
||||
- `RxBool` → 计数器 `_loadingCount`
|
||||
- 仅当计数归零时设 `isLoading = false`
|
||||
|
||||
7. **SharedPreferences 未初始化** (#8)
|
||||
- `late SharedPreferences` → `SharedPreferences?`
|
||||
- 读取用 `?.` 安全调用,写入加 null 检查
|
||||
|
||||
8. **中间件拦截循环** (#10)
|
||||
- `/standards-violation` 路由跳过校验
|
||||
|
||||
### 2026-04-09 修复批次(第一轮)
|
||||
|
||||
1. **LoggerService 空值崩溃** (#9, #11 相关)
|
||||
- `_logger` 改为 `Logger?`,所有方法加 null 检查
|
||||
- `dispose()` 改为 `_logger?.close()`
|
||||
|
||||
2. **PageStandards MediaQuery 空值崩溃** (#11)
|
||||
- 所有 `MediaQuery.of(context)` 加 try-catch
|
||||
- 降级到安全默认值 (375×812, 44/34 padding)
|
||||
- `l10n` 改为可空 `AppLocalizations?`
|
||||
|
||||
3. **l10n 可空类型连锁修复**
|
||||
- `empty_state.dart`: `l10n?.noData ?? '暂无数据'`
|
||||
- `error_state.dart`: `l10n?.retry ?? '重试'`
|
||||
- `standard_dialog.dart`: 6处 `l10n?.confirm/cancel` 加降级中文
|
||||
- `page_validator.dart`: `l10n?.appTitle.isNotEmpty ?? false`
|
||||
|
||||
4. **代码警告清理** (15项)
|
||||
- 移除未使用的 import / 变量 / 不必要的 `!` / 死代码
|
||||
191
docs/dev/LOCAL_FEATURES_PLAN.md
Normal file
191
docs/dev/LOCAL_FEATURES_PLAN.md
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
## 五、开发阶段
|
||||
|
||||
### 阶段一:基础设施(P1)✅ 已完成
|
||||
**目标**:搭建 Hive 本地数据库 + 数据模型 + 持久化收藏
|
||||
|
||||
| 序号 | 任务 | 产出文件 | 状态 |
|
||||
|------|------|---------|------|
|
||||
| 1.1 | 引入 hive_ce 依赖 | `pubspec.yaml` | ✅ |
|
||||
| 1.2 | 实现 HiveService(初始化/注册适配器/打开Box) | `lib/src/services/data/hive_service.dart` | ✅ |
|
||||
| 1.3 | 创建 MealRecordModel + 手写 TypeAdapter | `lib/src/models/meal_record_model.dart` | ✅ |
|
||||
| 1.4 | 创建 ShoppingItemModel + 手写 TypeAdapter | `lib/src/models/shopping_item_model.dart` | ✅ |
|
||||
| 1.5 | 创建 UserGoalModel + 手写 TypeAdapter | `lib/src/models/user_goal_model.dart` | ✅ |
|
||||
| 1.6 | 创建 CookingNoteModel + 手写 TypeAdapter | `lib/src/models/cooking_note_model.dart` | ✅ |
|
||||
| 1.7 | 手写 TypeAdapter(替代 build_runner 代码生成) | 各模型文件内嵌 | ✅ |
|
||||
| 1.8 | FavoritesController 持久化改造(迁移到 Hive Box) | `lib/src/controllers/favorites_controller.dart` | ✅ |
|
||||
| 1.9 | AppService 初始化 HiveService | `lib/src/services/core/app_service.dart` | ✅ |
|
||||
|
||||
### 阶段二:饮食日记(P1)
|
||||
**目标**:记录每日饮食 + 自动计算营养
|
||||
|
||||
| 序号 | 任务 | 产出文件 |
|
||||
|------|------|---------|
|
||||
| 2.1 | MealRecordController | `lib/src/controllers/meal_record_controller.dart` |
|
||||
| 2.2 | 饮食日记页面(日历+列表) | `lib/src/pages/nutrition/meal_diary_page.dart` |
|
||||
| 2.3 | 添加饮食记录弹窗 | `lib/src/pages/nutrition/add_meal_sheet.dart` |
|
||||
| 2.4 | 餐次选择器(早/午/晚/加餐) | `lib/src/widgets/meal_type_selector.dart` |
|
||||
| 2.5 | 营养自动计算(从 RecipeModel.nutrition 读取) | MealRecordController 内逻辑 |
|
||||
| 2.6 | 发现页增加「营养中心」入口 | `discover_page.dart` 修改 |
|
||||
|
||||
### 阶段三:热量追踪 + 营养分析(P1)
|
||||
**目标**:可视化每日营养摄入 + 目标对比
|
||||
|
||||
| 序号 | 任务 | 产出文件 |
|
||||
|------|------|---------|
|
||||
| 3.1 | 引入 fl_chart 依赖 | `pubspec.yaml` |
|
||||
| 3.2 | NutritionController | `lib/src/controllers/nutrition_controller.dart` |
|
||||
| 3.3 | 热量追踪页面(环形进度+三大营养素) | `lib/src/pages/nutrition/calorie_tracker_page.dart` |
|
||||
| 3.4 | 营养分析报告页面(周/月趋势图) | `lib/src/pages/nutrition/nutrition_report_page.dart` |
|
||||
| 3.5 | 用户目标设置页面 | `lib/src/pages/nutrition/goal_setting_page.dart` |
|
||||
| 3.6 | 环形进度组件 | `lib/src/widgets/charts/calorie_ring.dart` |
|
||||
| 3.7 | 折线趋势图组件 | `lib/src/widgets/charts/nutrition_line_chart.dart` |
|
||||
|
||||
### 阶段四:购物清单(P2)
|
||||
**目标**:从菜谱食材自动生成购物清单
|
||||
|
||||
| 序号 | 任务 | 产出文件 |
|
||||
|------|------|---------|
|
||||
| 4.1 | ShoppingListController | `lib/src/controllers/shopping_list_controller.dart` |
|
||||
| 4.2 | 购物清单页面 | `lib/src/pages/shopping/shopping_list_page.dart` |
|
||||
| 4.3 | 从菜谱添加食材到购物清单 | 首页卡片/菜谱详情页增加入口 |
|
||||
| 4.4 | 食材分类展示 | `lib/src/widgets/shopping_category_group.dart` |
|
||||
| 4.5 | 我的页面增加「购物清单」入口 | `profile_home.dart` 修改 |
|
||||
|
||||
### 阶段五:增强功能(P2/P3)
|
||||
**目标**:烹饪计时器 + 用量换算 + 过敏原检测 + 烹饪笔记
|
||||
|
||||
| 序号 | 任务 | 产出文件 |
|
||||
|------|------|---------|
|
||||
| 5.1 | 烹饪计时器页面 | `lib/src/pages/tools/cooking_timer_page.dart` |
|
||||
| 5.2 | 用量换算工具页面 | `lib/src/pages/tools/unit_converter_page.dart` |
|
||||
| 5.3 | 过敏原检测逻辑 | `lib/src/services/allergen_checker.dart` |
|
||||
| 5.4 | 烹饪笔记功能 | `lib/src/controllers/cooking_note_controller.dart` |
|
||||
| 5.5 | 用餐提醒(需 flutter_local_notifications) | `lib/src/services/notification_service.dart` |
|
||||
| 5.6 | BMI 计算器 | `lib/src/pages/tools/bmi_calculator_page.dart` |
|
||||
| 5.7 | 份量缩放工具 | `lib/src/pages/tools/serving_scaler_page.dart` |
|
||||
|
||||
---
|
||||
|
||||
## 六、页面导航规划
|
||||
|
||||
```
|
||||
发现页
|
||||
└── 📊 营养中心
|
||||
├── 🍽️ 饮食日记(日历视图 + 每日记录列表)
|
||||
│ └── ➕ 添加记录(底部弹窗:选餐次 + 选菜谱/手动输入)
|
||||
├── 🔥 热量追踪(环形进度 + 三大营养素比例 + 目标线)
|
||||
└── 📊 分析报告(周/月趋势折线图 + 营养素饼图)
|
||||
|
||||
我的页面
|
||||
├── 📋 购物清单(分类展示 + 勾选已购)
|
||||
├── ⏱️ 烹饪计时器(多步骤倒计时)
|
||||
├── 🔄 用量换算
|
||||
├── 🎯 BMI 计算器
|
||||
└── ⚙️ 设置
|
||||
├── 🎯 每日营养目标
|
||||
├── 🔔 用餐提醒
|
||||
└── ⚠️ 过敏原管理
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、文件结构规划
|
||||
|
||||
```
|
||||
lib/src/
|
||||
├── models/
|
||||
│ ├── meal_record_model.dart # 饮食记录 + @HiveType
|
||||
│ ├── shopping_item_model.dart # 购物清单项 + @HiveType
|
||||
│ ├── user_goal_model.dart # 用户营养目标 + @HiveType
|
||||
│ └── cooking_note_model.dart # 烹饪笔记 + @HiveType
|
||||
├── controllers/
|
||||
│ ├── meal_record_controller.dart # 饮食记录控制器
|
||||
│ ├── nutrition_controller.dart # 营养分析控制器
|
||||
│ ├── shopping_list_controller.dart # 购物清单控制器
|
||||
│ └── cooking_note_controller.dart # 烹饪笔记控制器
|
||||
├── services/
|
||||
│ └── data/
|
||||
│ └── hive_service.dart # Hive 初始化/Box 管理
|
||||
├── pages/
|
||||
│ ├── nutrition/
|
||||
│ │ ├── nutrition_center_page.dart # 营养中心主页
|
||||
│ │ ├── meal_diary_page.dart # 饮食日记
|
||||
│ │ ├── add_meal_sheet.dart # 添加记录弹窗
|
||||
│ │ ├── calorie_tracker_page.dart # 热量追踪
|
||||
│ │ ├── nutrition_report_page.dart # 营养报告
|
||||
│ │ └── goal_setting_page.dart # 目标设置
|
||||
│ ├── shopping/
|
||||
│ │ └── shopping_list_page.dart # 购物清单
|
||||
│ └── tools/
|
||||
│ ├── cooking_timer_page.dart # 烹饪计时器
|
||||
│ ├── unit_converter_page.dart # 用量换算
|
||||
│ ├── bmi_calculator_page.dart # BMI 计算器
|
||||
│ └── serving_scaler_page.dart # 份量缩放
|
||||
└── widgets/
|
||||
├── charts/
|
||||
│ ├── calorie_ring.dart # 热量环形进度
|
||||
│ └── nutrition_line_chart.dart # 营养趋势折线图
|
||||
├── meal_type_selector.dart # 餐次选择器
|
||||
└── shopping_category_group.dart # 购物清单分类组
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、开发优先级矩阵
|
||||
|
||||
| 功能 | 用户价值 | 技术难度 | 依赖关系 | 优先级 |
|
||||
|------|---------|---------|---------|--------|
|
||||
| Hive 本地数据库 | ⭐⭐⭐⭐⭐ | ⭐⭐ | 无 | P1-0 |
|
||||
| 收藏持久化 | ⭐⭐⭐⭐ | ⭐ | 数据库 | P1-1 |
|
||||
| 饮食日记 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 数据库 | P1-2 |
|
||||
| 热量追踪 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 饮食日记 | P1-3 |
|
||||
| 营养分析报告 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 饮食日记+fl_chart | P1-4 |
|
||||
| 购物清单 | ⭐⭐⭐⭐ | ⭐⭐ | 数据库 | P2-1 |
|
||||
| 烹饪计时器 | ⭐⭐⭐ | ⭐⭐ | 无 | P2-2 |
|
||||
| 用量换算 | ⭐⭐⭐ | ⭐ | 无 | P2-3 |
|
||||
| 过敏原检测 | ⭐⭐⭐ | ⭐⭐ | 偏好数据 | P2-4 |
|
||||
| 烹饪笔记 | ⭐⭐ | ⭐⭐ | 数据库 | P3-1 |
|
||||
| 用餐提醒 | ⭐⭐ | ⭐⭐⭐ | 本地通知 | P3-2 |
|
||||
| BMI 计算器 | ⭐⭐ | ⭐ | 无 | P3-3 |
|
||||
| 份量缩放 | ⭐⭐ | ⭐ | 无 | P3-4 |
|
||||
|
||||
---
|
||||
|
||||
## 九、验收标准
|
||||
|
||||
### 阶段一
|
||||
- [ ] App 重启后收藏数据不丢失
|
||||
- [ ] Hive Box 初始化成功,无报错
|
||||
- [ ] TypeAdapter 注册正确,对象可序列化/反序列化
|
||||
- [ ] HiveService 支持增删改查
|
||||
|
||||
### 阶段二
|
||||
- [ ] 可按日期查看饮食记录
|
||||
- [ ] 可添加/删除饮食记录
|
||||
- [ ] 选择菜谱后自动填充营养数据
|
||||
- [ ] 日历视图正确标记有记录的日期
|
||||
|
||||
### 阶段三
|
||||
- [ ] 环形进度正确显示当日热量占比
|
||||
- [ ] 三大营养素比例饼图正确
|
||||
- [ ] 周/月趋势折线图可交互
|
||||
- [ ] 可设置每日营养目标
|
||||
|
||||
### 阶段四
|
||||
- [ ] 可从菜谱添加食材到购物清单
|
||||
- [ ] 可勾选已购物品
|
||||
- [ ] 食材按分类展示
|
||||
|
||||
---
|
||||
|
||||
## 十、技术决策记录
|
||||
|
||||
| 日期 | 决策 | 理由 | 替代方案 |
|
||||
|------|------|------|---------|
|
||||
| 2026-04-09 | 选择 Hive CE 而非 sqflite | 纯 Dart 零原生依赖,鸿蒙零风险;API 简单开发快;数据量小无需 SQL | sqflite(原生依赖,鸿蒙兼容风险) |
|
||||
| 2026-04-09 | 选择 hive_ce 而非原版 hive | 社区版持续维护,支持 WASM,性能优于 v4 | hive v2.2.3(3年未更新) |
|
||||
| 2026-04-09 | 选择 fl_chart 而非 charts_flutter | 纯 Dart 无平台依赖,社区活跃 | charts_flutter(已停维) |
|
||||
| 2026-04-09 | 营养数据冗余存储到 MealRecordModel | 避免菜谱修改影响历史记录 | 联表查询(数据不一致风险) |
|
||||
| 2026-04-09 | 使用 ISO8601 日期格式 | 跨时区安全,排序方便 | 时间戳(可读性差) |
|
||||
| 2026-04-09 | 聚合查询用 Dart 代码实现 | 数据量极小(~2000条/年),Dart 过滤性能足够 | SQL 聚合(需 sqflite,过度设计) |
|
||||
348
docs/dev/UNFINISHED_FEATURES.md
Normal file
348
docs/dev/UNFINISHED_FEATURES.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# 📋 未完成功能清单
|
||||
|
||||
> 文档创建: 2026-04-09
|
||||
> 最后更新: 2026-04-09
|
||||
> 数据来源: `LOCAL_FEATURES_PLAN.md` 阶段三~五
|
||||
> 说明: 记录所有未完成的功能任务,跟踪开发进度
|
||||
> 优先级说明: P1=核心功能 P2=重要功能 P3=增强功能
|
||||
> 优先级值1-5: 5=最高优先级(多次提及自动提升)
|
||||
|
||||
---
|
||||
|
||||
## 📊 总体进度
|
||||
|
||||
| 阶段 | 总任务 | 已完成 | 未完成 | 完成率 |
|
||||
|------|--------|--------|--------|--------|
|
||||
| 三:热量追踪+营养分析 | 7 | 7 | 0 | 100% ✅ |
|
||||
| 四:购物清单 | 5 | 5 | 0 | 100% ✅ |
|
||||
| 五:增强功能 | 7 | 0 | 7 | 0% |
|
||||
| 六:主页体验优化 | 5 | 3 | 2 | 60% |
|
||||
| Bug 修复 | 9 | 4 | 5 | 44% |
|
||||
| 七:今天吃什么增强 | 5 | 0 | 5 | 0% |
|
||||
| **合计** | **38** | **19** | **19** | **50%** |
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### 开发顺序建议
|
||||
|
||||
```
|
||||
4.1 ShoppingListController ✅
|
||||
→ 4.4 食材分类展示组件 ✅
|
||||
→ 4.2 购物清单页面 ✅
|
||||
→ 4.3 从菜谱添加食材入口 ✅
|
||||
→ 4.5 我的页面增加入口 ✅
|
||||
```
|
||||
|
||||
### 技术要点
|
||||
|
||||
- `ShoppingItemModel` 已有 `category` 字段,分类展示直接用 `groupby`
|
||||
- 勾选已购用 `isChecked` 字段,写入 Hive 持久化
|
||||
- 从菜谱添加需解析 `RecipeModel.ingredients`,转为 `ShoppingItemModel` 列表
|
||||
- 购物清单页面需 iOS26 Liquid Glass 风格
|
||||
|
||||
### 已完成文件清单
|
||||
|
||||
| 文件路径 | 说明 |
|
||||
|---------|------|
|
||||
| `lib/src/controllers/shopping/shopping_list_controller.dart` | 购物清单控制器 |
|
||||
| `lib/src/pages/shopping/shopping_list_page.dart` | 购物清单页面 |
|
||||
| `lib/src/models/shopping/shopping_item_model.dart` | 购物清单模型(已存在) |
|
||||
|
||||
### 路由
|
||||
|
||||
| 路由路径 | 页面 |
|
||||
|---------|------|
|
||||
| `/shopping-list` | 购物清单页面 |
|
||||
|
||||
---
|
||||
|
||||
## 🟡 阶段五:增强功能(P2/P3)
|
||||
|
||||
**目标**:烹饪计时器 + 用量换算 + 过敏原检测 + 烹饪笔记 + 用餐提醒 + BMI + 份量缩放
|
||||
**前置依赖**:各功能独立,无强依赖
|
||||
**关键阻塞**:5.5 用餐提醒需 `flutter_local_notifications`
|
||||
|
||||
| 序号 | 任务 | 产出文件 | 优先级 | 状态 | 说明 |
|
||||
|------|------|---------|--------|------|------|
|
||||
| 5.1 | 烹饪计时器页面 | `lib/src/pages/tools/cooking_timer_page.dart` | P2 | ❌ 未创建 | `pages/tools/` 目录不存在 |
|
||||
| 5.2 | 用量换算工具页面 | `lib/src/pages/tools/unit_converter_page.dart` | P2 | ❌ 未创建 | |
|
||||
| 5.3 | 过敏原检测逻辑 | `lib/src/services/allergen_checker.dart` | P2 | ❌ 未创建 | |
|
||||
| 5.4 | 烹饪笔记功能 | `lib/src/controllers/cooking_note_controller.dart` | P3 | ❌ 未创建 | |
|
||||
| 5.5 | 用餐提醒 | `lib/src/services/notification_service.dart` | P3 | ❌ 未创建 | 需 `flutter_local_notifications` |
|
||||
| 5.6 | BMI 计算器 | `lib/src/pages/tools/bmi_calculator_page.dart` | P3 | ❌ 未创建 | |
|
||||
| 5.7 | 份量缩放工具 | `lib/src/pages/tools/serving_scaler_page.dart` | P3 | ❌ 未创建 | |
|
||||
|
||||
### 开发顺序建议
|
||||
|
||||
```
|
||||
5.1 烹饪计时器(纯 UI,无外部依赖)
|
||||
→ 5.2 用量换算(纯逻辑,无外部依赖)
|
||||
→ 5.6 BMI 计算器(纯逻辑,无外部依赖)
|
||||
→ 5.7 份量缩放(纯逻辑,无外部依赖)
|
||||
→ 5.3 过敏原检测(需偏好数据)
|
||||
→ 5.4 烹饪笔记(需 HiveService)
|
||||
→ 5.5 用餐提醒(需 flutter_local_notifications,鸿蒙兼容性待验证)
|
||||
```
|
||||
|
||||
### 技术要点
|
||||
|
||||
- 烹饪计时器:用 `Stream.periodic` 实现倒计时,支持多步骤
|
||||
- 用量换算:纯 Dart Map 映射,无需外部包
|
||||
- 过敏原检测:比对 `PreferenceController.blockedAllergens` 与菜谱成分
|
||||
- 烹饪笔记:`CookingNoteModel` 已有,Controller 调 `HiveService` CRUD
|
||||
- 用餐提醒:`flutter_local_notifications` 有原生依赖,鸿蒙兼容性需验证
|
||||
- BMI 计算器:`体重 / 身高²`,纯计算
|
||||
- 份量缩放:按比例缩放食材用量,纯计算
|
||||
- 所有工具页面需 iOS26 Liquid Glass 风格
|
||||
|
||||
---
|
||||
|
||||
## 🔗 需引入的外部依赖
|
||||
|
||||
| 依赖 | 用途 | 阶段 | 纯Dart | 鸿蒙兼容 | 状态 |
|
||||
|------|------|------|--------|---------|------|
|
||||
| `fl_chart` | 图表绘制 | 三 | ✅ 是 | ✅ 是 | ✅ 已本地适配 |
|
||||
| `flutter_local_notifications` | 本地通知 | 五 | ❌ 否 | ⚠️ 待验证 | ❌ 未引入 |
|
||||
|
||||
---
|
||||
|
||||
## 📝 验收标准
|
||||
|
||||
### 阶段三 ✅
|
||||
- [x] 环形进度正确显示当日热量占比
|
||||
- [x] 三大营养素比例饼图正确
|
||||
- [x] 周/月趋势折线图可交互
|
||||
- [x] 可设置每日营养目标
|
||||
|
||||
### 阶段四
|
||||
- [ ] 可从菜谱添加食材到购物清单
|
||||
- [ ] 可勾选已购物品
|
||||
- [ ] 食材按分类展示
|
||||
|
||||
### 阶段五
|
||||
- [ ] 烹饪计时器支持多步骤倒计时
|
||||
- [ ] 用量换算覆盖常用单位
|
||||
- [ ] 过敏原检测可标记含过敏原的菜谱
|
||||
- [ ] 烹饪笔记可按菜谱关联
|
||||
- [ ] 用餐提醒可设置时间并准时通知
|
||||
- [ ] BMI 计算器结果含健康建议
|
||||
- [ ] 份量缩放可按比例调整食材用量
|
||||
|
||||
---
|
||||
|
||||
## 🔵 阶段六:主页体验优化(P1)
|
||||
|
||||
**目标**:修复主页交互体验问题,提升可用性
|
||||
**前置依赖**:无
|
||||
**关键阻塞**:无
|
||||
|
||||
| 序号 | 任务 | 产出文件 | 优先级 | 状态 | 问题描述 |
|
||||
|------|------|---------|--------|------|---------|
|
||||
| 6.1 | 增大卡片交互按钮点击区域 | `lib/src/pages/home_page.dart` | P1 | ❌ 未修复 | 图标16px过小,点击困难,需增大到20px+扩大热区 |
|
||||
| 6.2 | 添加骨架屏加载效果 | `lib/src/widgets/skeleton/` | P1 | ❌ 未创建 | 加载中无骨架屏,用户体验差 |
|
||||
| 6.3 | 支持动态主题切换 | `lib/src/services/ui/theme_service.dart` | P2 | ❌ 未实现 | 当前主题固定,需支持跟随系统/手动切换 |
|
||||
| 6.4 | 搜索功能+搜索页面 | `lib/src/pages/search/search_page.dart` | P1 | ❌ 未创建 | 搜索栏只读无跳转,需完整搜索功能 |
|
||||
| 6.5 | 菜谱详情页 | `lib/src/pages/recipe/recipe_detail_page.dart` | P1 | ❌ 未创建 | 点击卡片只显示Toast,需跳转到详情页 |
|
||||
|
||||
### 问题详情
|
||||
|
||||
#### 6.1 交互按钮过小
|
||||
- **现状**:图标 16px,点击热区仅文字区域
|
||||
- **影响**:用户难以准确点击,误触率高
|
||||
- **方案**:图标增大到 20px,Padding 从 2px 增加到 8px,使用 `InkWell` 扩大热区
|
||||
|
||||
#### 6.2 骨架屏缺失
|
||||
- **现状**:加载时显示 `CupertinoActivityIndicator`
|
||||
- **影响**:页面跳动,感知加载时间长
|
||||
- **方案**:使用 `Shimmer` 或自定义骨架屏组件,模拟卡片结构
|
||||
|
||||
#### 6.3 动态主题
|
||||
- **现状**:主题固定,仅支持亮/暗色
|
||||
- **影响**:无法满足个性化需求
|
||||
- **方案**:扩展 ThemeService,支持多主题色(蓝/绿/紫/橙)
|
||||
|
||||
#### 6.4 搜索功能
|
||||
- **现状**:搜索栏 `readOnly: true`,点击无响应
|
||||
- **影响**:核心功能缺失
|
||||
- **方案**:创建 SearchPage,支持历史记录、热门搜索、结果列表
|
||||
|
||||
#### 6.5 详情页缺失
|
||||
- **现状**:点击卡片 `ToastService.show('${item.title} 👀')`
|
||||
- **影响**:无法查看菜谱详情
|
||||
- **方案**:创建 RecipeDetailPage,展示封面、食材、步骤、营养
|
||||
|
||||
### 开发顺序建议
|
||||
|
||||
```
|
||||
6.1 增大交互按钮(最小改动,立竿见影)
|
||||
→ 6.2 骨架屏(提升感知性能)
|
||||
→ 6.4 搜索页面(核心功能)
|
||||
→ 6.5 菜谱详情页(核心功能)
|
||||
→ 6.3 动态主题(增强体验)
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [x] 交互按钮点击成功率 > 95%
|
||||
- [x] 骨架屏与真实内容结构一致
|
||||
- [ ] 主题切换实时生效,无闪烁
|
||||
- [x] 搜索支持关键词高亮、历史记录
|
||||
- [ ] 详情页展示完整菜谱信息
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Bug修复清单(P0)
|
||||
|
||||
**目标**:修复用户反馈的严重问题
|
||||
**发现时间**:2026-04-09
|
||||
|
||||
| 序号 | 问题描述 | 影响页面 | 优先级 | 状态 | 可能原因 |
|
||||
|------|---------|---------|--------|------|---------|
|
||||
| B.1 | 发现页营养中心部分按钮卡死闪退 | `discover_page.dart` | P0 | ❌ 未修复 | 空指针/异步异常未捕获 |
|
||||
| B.2 | goal-setting页面被链接提示 | `goal_setting_page.dart` | P0 | ❌ 未修复 | 路由或依赖注入问题 |
|
||||
| B.3 | 今天吃什么选择无反应 | `what_to_eat_page.dart` | P0 | ❌ 未修复 | 状态管理或逻辑错误 |
|
||||
| B.4 | 主题设置页面不协调 | `personalization_page.dart` | P1 | ❌ 未修复 | 布局比例、缺少分割线 |
|
||||
|
||||
### 问题详情
|
||||
|
||||
#### B.1 发现页营养中心卡死闪退
|
||||
- **现象**:点击部分按钮后应用卡死并闪退
|
||||
- **可能原因**:
|
||||
- 控制器未正确初始化
|
||||
- 异步操作未正确处理异常
|
||||
- 空安全违规访问
|
||||
- **排查方向**:检查 `DiscoverPage` 中的按钮点击事件处理
|
||||
|
||||
#### B.2 goal-setting页面链接问题
|
||||
- **现象**:页面显示"被链接"提示
|
||||
- **可能原因**:
|
||||
- 路由参数传递错误
|
||||
- GetX依赖注入问题
|
||||
- 页面生命周期问题
|
||||
- **排查方向**:检查路由跳转和控制器注册
|
||||
|
||||
#### B.3 今天吃什么无反应
|
||||
- **现象**:点击"开始选择"、"随机"、"智能"按钮后无结果
|
||||
- **可能原因**:
|
||||
- 算法逻辑错误
|
||||
- 数据源为空
|
||||
- 状态未正确更新
|
||||
- **排查方向**:检查 `WhatToEatController` 的选择逻辑
|
||||
|
||||
#### B.4 主题设置页面不协调
|
||||
- **现象**:
|
||||
- 页面比例不均衡
|
||||
- 缺少分割线
|
||||
- 部分参数设置不生效
|
||||
- **可能原因**:
|
||||
- 布局使用固定尺寸
|
||||
- 缺少视觉分隔
|
||||
- 主题持久化逻辑问题
|
||||
- **排查方向**:重构布局,添加分割线,检查主题保存逻辑
|
||||
|
||||
### 修复顺序建议
|
||||
```
|
||||
B.1 卡死闪退(最严重,优先修复)
|
||||
→ B.3 今天吃什么(核心功能)
|
||||
→ B.2 goal-setting链接问题
|
||||
→ B.4 主题设置UI(体验优化)
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 发现页所有按钮正常响应,无闪退
|
||||
- [ ] goal-setting页面正常打开,无异常提示
|
||||
- [ ] 今天吃什么功能完整可用,有结果反馈
|
||||
- [ ] 主题设置页面美观协调,设置实时生效
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Bug修复清单 第二波(P0)
|
||||
|
||||
**发现时间**:2026-04-09(第二轮反馈)
|
||||
|
||||
| 序号 | 问题描述 | 影响页面 | 优先级 | 状态 | 可能原因 |
|
||||
|------|---------|---------|--------|------|---------|
|
||||
| B.5 | 发现页购物清单点击无反应 | `discover_page.dart` | P0 | ✅ 已修复 | 按钮事件未绑定 |
|
||||
| B.6 | 我的页面购物清单被拦截 | `profile_home.dart` | P0 | ✅ 已修复 | PageRegistry 未注册 |
|
||||
| B.7 | 右上角 debug 标签 | `main.dart` | P1 | ✅ 已修复 | debugShowCheckedModeBanner未关闭 |
|
||||
| B.8 | 发现页营养中心报告被拦截 | `discover_page.dart` | P0 | ✅ 已修复 | PageRegistry 未注册 |
|
||||
| B.9 | 收藏页面单一无交互 | `favorites_page.dart` | P2 | ❌ 未修复 | 缺少删除/排序/分类功能 |
|
||||
|
||||
### 问题详情
|
||||
|
||||
#### B.5 发现页购物清单点击无反应
|
||||
- **现象**:点击购物清单入口无响应
|
||||
- **排查方向**:检查按钮onTap事件和路由跳转
|
||||
|
||||
#### B.6 我的页面购物清单被拦截
|
||||
- **现象**:页面显示"被拦截"提示
|
||||
- **排查方向**:检查PageStandardsMiddleware和页面规范
|
||||
|
||||
#### B.7 Debug标签
|
||||
- **现象**:右上角显示DEBUG标签
|
||||
- **修复方案**:设置 `debugShowCheckedModeBanner: false`
|
||||
|
||||
#### B.8 营养中心报告被拦截
|
||||
- **现象**:点击报告入口显示"被拦截"
|
||||
- **排查方向**:检查路由注册和页面规范
|
||||
|
||||
#### B.9 收藏页面单一
|
||||
- **现象**:只有列表,无删除/排序/分类功能
|
||||
- **优化方向**:添加滑动删除、分类筛选、排序选项
|
||||
|
||||
### 修复顺序建议
|
||||
```
|
||||
B.7 去掉 Debug 标签(最简单,立即生效) ✅
|
||||
→ B.5/B.6/B.8 路由/拦截问题(核心功能) ✅ 全部修复
|
||||
→ B.9 收藏页面优化(体验增强)
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [x] 所有购物清单入口正常跳转
|
||||
- [x] 营养中心报告页面正常打开
|
||||
- [x] 无 DEBUG 标签显示
|
||||
- [ ] 收藏页面支持删除和排序
|
||||
|
||||
---
|
||||
|
||||
## 🟡 阶段七:今天吃什么增强(P1)
|
||||
|
||||
**目标**:实现接口支持的动态筛选功能
|
||||
**前置依赖**:接口已支持(`api_what_to_eat.php` v1.24.0)
|
||||
**分析结论**:接口已完整支持随机/智能/分类/标签/营养素筛选,APP端未调用
|
||||
|
||||
| 序号 | 任务 | 产出文件 | 优先级 | 状态 | 说明 |
|
||||
|------|------|---------|--------|------|------|
|
||||
| 7.1 | 实现分类筛选UI | `what_to_eat_page.dart` | P1 | ❌ 未实现 | 显示接口返回的分类列表供选择 |
|
||||
| 7.2 | 实现标签筛选UI | `what_to_eat_page.dart` | P1 | ❌ 未实现 | 显示接口返回的标签列表 |
|
||||
| 7.3 | 实现营养素筛选UI | `what_to_eat_page.dart` | P1 | ❌ 未实现 | 热量/蛋白质/脂肪范围滑块 |
|
||||
| 7.4 | 调用 available_filters 接口 | `what_to_eat_repository.dart` | P1 | ❌ 未实现 | 根据已选条件获取可用筛选 |
|
||||
| 7.5 | 保存筛选偏好 | `HiveService` | P2 | ❌ 未实现 | 本地记住用户偏好 |
|
||||
|
||||
### 接口分析
|
||||
|
||||
| 端点 | APP调用 | 说明 |
|
||||
|------|---------|------|
|
||||
| `act=random` | ✅ 已调用 | 随机模式 |
|
||||
| `act=smart` | ✅ 已调用 | 智能模式(仅用偏好) |
|
||||
| `act=config` | ✅ 已调用 | 获取配置 |
|
||||
| `act=subcategories` | ❌ 未调用 | 获取子分类 |
|
||||
| `act=available_filters` | ❌ 未调用 | 动态筛选 |
|
||||
|
||||
### 筛选参数(接口支持)
|
||||
|
||||
| 参数 | 类型 | APP实现 |
|
||||
|------|------|--------|
|
||||
| `include_categories` | int[] | ❌ |
|
||||
| `exclude_categories` | int[] | ❌ |
|
||||
| `include_tags` | int[] | ❌ |
|
||||
| `exclude_tags` | int[] | ❌ |
|
||||
| `exclude_allergens` | string[] | ⚠️ 仅偏好 |
|
||||
| `nutrition` | string | ❌ |
|
||||
|
||||
### 验收标准
|
||||
- [ ] 支持分类多选筛选
|
||||
- [ ] 支持标签多选筛选
|
||||
- [ ] 支持营养素范围筛选
|
||||
- [ ] 筛选结果实时更新
|
||||
Reference in New Issue
Block a user