api 升级v2.0
This commit is contained in:
901
docs/superpowers/plans/2026-04-09-fix-issues.md
Normal file
901
docs/superpowers/plans/2026-04-09-fix-issues.md
Normal file
@@ -0,0 +1,901 @@
|
||||
# 问题修复实施计划
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 修复文档中列出的8个高优先级问题,更新文档以反映实际状态
|
||||
|
||||
**Architecture:** 采用逐个击破策略,优先修复崩溃和无响应问题,然后更新文档
|
||||
|
||||
**Tech Stack:** Flutter, GetX, Hive, Cupertino UI
|
||||
|
||||
---
|
||||
|
||||
## 文件结构映射
|
||||
|
||||
### 需要修改的文件
|
||||
- `lib/src/pages/recipe/recipe_detail_page.dart` - 修复类型转换错误
|
||||
- `lib/src/controllers/discovery/what_to_eat_controller.dart` - 修复选择逻辑
|
||||
- `lib/src/pages/what_to_eat/what_to_eat_page.dart` - 修复筛选功能
|
||||
- `lib/src/pages/nutrition/nutrition_center_page.dart` - 修复报告和今天按钮
|
||||
- `lib/src/pages/nutrition/goal_setting_page.dart` - 修复布局溢出
|
||||
- `lib/src/pages/nutrition/meal_diary_page.dart` - 实现删除功能
|
||||
- `docs/dev/UNFINISHED_FEATURES.md` - 更新实际完成状态
|
||||
- `docs/dev/ISSUES_TO_RESOLVE.md` - 更新问题解决状态
|
||||
|
||||
---
|
||||
|
||||
## Task 1: 修复首页点击菜品红屏错误
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/pages/recipe/recipe_detail_page.dart:1-100`
|
||||
- Test: 手动测试点击菜品详情
|
||||
|
||||
**问题分析:**
|
||||
- 错误信息:`int is not xxx`
|
||||
- 可能原因:`recipeId` 类型不匹配,或 API 返回数据类型错误
|
||||
|
||||
- [ ] **Step 1: 检查 recipeId 类型转换**
|
||||
|
||||
```dart
|
||||
// 在 recipe_detail_page.dart 第 22 行附近
|
||||
class RecipeDetailPage extends StatefulWidget {
|
||||
final String recipeId;
|
||||
|
||||
const RecipeDetailPage({super.key, required this.recipeId});
|
||||
|
||||
@override
|
||||
State<RecipeDetailPage> createState() => _RecipeDetailPageState();
|
||||
}
|
||||
|
||||
// 在 _loadRecipe 方法中,第 50 行附近
|
||||
Future<void> _loadRecipe() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
});
|
||||
|
||||
try {
|
||||
// 添加类型安全检查
|
||||
final id = int.tryParse(widget.recipeId);
|
||||
if (id == null) {
|
||||
throw Exception('无效的菜谱ID: ${widget.recipeId}');
|
||||
}
|
||||
|
||||
final recipe = await _recipeRepository.fetchFull(id);
|
||||
|
||||
// 验证返回数据
|
||||
if (recipe.id == null) {
|
||||
throw Exception('菜谱数据不完整');
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_recipe = recipe;
|
||||
_isFavorited = _favoritesController.isFavorited(recipe.id!);
|
||||
_likeCount = recipe.statistics?.likes ?? 0;
|
||||
_allergens = _allergenChecker.checkAllergens(
|
||||
recipe.ingredients.map((e) => e.name).join(', '),
|
||||
);
|
||||
_isLoading = false;
|
||||
});
|
||||
|
||||
_actionController.reportView(id: recipe.id!, type: 'recipe');
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_error = '加载失败: $e';
|
||||
_isLoading = false;
|
||||
});
|
||||
debugPrint('RecipeDetailPage error: $e');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 添加错误边界处理**
|
||||
|
||||
```dart
|
||||
// 在 build 方法中添加错误处理
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isLoading) {
|
||||
return _buildLoadingSkeleton();
|
||||
}
|
||||
|
||||
if (_error != null) {
|
||||
return _buildErrorWidget();
|
||||
}
|
||||
|
||||
if (_recipe == null) {
|
||||
return _buildEmptyWidget();
|
||||
}
|
||||
|
||||
return _buildRecipeContent();
|
||||
}
|
||||
|
||||
Widget _buildErrorWidget() {
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: const Text('菜谱详情'),
|
||||
),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(CupertinoIcons.exclamationmark_triangle, size: 48),
|
||||
const SizedBox(height: 16),
|
||||
Text(_error ?? '加载失败'),
|
||||
const SizedBox(height: 16),
|
||||
CupertinoButton(
|
||||
onPressed: _loadRecipe,
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用:`flutter run`
|
||||
2. 进入首页
|
||||
3. 点击任意菜品卡片
|
||||
4. 验证:应该正常跳转到详情页,不出现红屏
|
||||
|
||||
- [ ] **Step 4: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题1为已解决:
|
||||
|
||||
```markdown
|
||||
### 1. 首页点击菜品出现红屏错误 ✅ 已修复
|
||||
**问题描述**: 点击菜品后出现红屏,错误信息:`int is not xxx`
|
||||
|
||||
**解决方案**:
|
||||
- [x] 添加类型安全检查和错误边界
|
||||
- [x] 验证API返回的数据格式
|
||||
- [x] 添加友好的错误提示
|
||||
|
||||
**修复时间**: 2026-04-09
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: 修复今天吃什么功能无结果
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/controllers/discovery/what_to_eat_controller.dart:1-100`
|
||||
- Test: 手动测试选择功能
|
||||
|
||||
**问题分析:**
|
||||
- 点击"开始选择"后无结果
|
||||
- 可能原因:数据源为空或选择逻辑错误
|
||||
|
||||
- [ ] **Step 1: 检查并修复选择逻辑**
|
||||
|
||||
```dart
|
||||
// 在 what_to_eat_controller.dart 第 35 行附近
|
||||
Future<void> roll() async {
|
||||
if (isSpinning.value) return;
|
||||
isSpinning.value = true;
|
||||
candidates.value = [];
|
||||
selectedRecipe.value = null;
|
||||
|
||||
try {
|
||||
List<RecipeModel> results;
|
||||
|
||||
if (mode.value == WhatToEatMode.smart) {
|
||||
results = await _fetchSmartWithPreferences();
|
||||
} else {
|
||||
results = await _whatToEatRepository.fetchRandom(count: 5);
|
||||
}
|
||||
|
||||
// 添加结果验证
|
||||
if (results.isEmpty) {
|
||||
ToastService.show(message: '没有找到符合条件的菜谱');
|
||||
isSpinning.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
candidates.value = results;
|
||||
|
||||
// 添加随机选择动画
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final random = Random();
|
||||
final index = random.nextInt(results.length);
|
||||
selectedRecipe.value = results[index];
|
||||
|
||||
ToastService.show(message: '已为您选择: ${selectedRecipe.value?.title}');
|
||||
} catch (e) {
|
||||
ToastService.show(message: '选择失败: $e');
|
||||
debugPrint('WhatToEatController.roll error: $e');
|
||||
} finally {
|
||||
isSpinning.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<RecipeModel>> _fetchSmartWithPreferences() async {
|
||||
try {
|
||||
final prefCtrl = Get.find<PreferenceController>();
|
||||
final preferences = prefCtrl.preferences.value;
|
||||
|
||||
if (preferences == null) {
|
||||
// 如果没有偏好设置,使用随机模式
|
||||
return await _whatToEatRepository.fetchRandom(count: 5);
|
||||
}
|
||||
|
||||
return await _whatToEatRepository.fetchSmart(
|
||||
preferences: preferences,
|
||||
count: 5,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('_fetchSmartWithPreferences error: $e');
|
||||
// 降级到随机模式
|
||||
return await _whatToEatRepository.fetchRandom(count: 5);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 添加调试日志**
|
||||
|
||||
```dart
|
||||
// 在关键位置添加日志
|
||||
Future<void> roll() async {
|
||||
debugPrint('=== WhatToEatController.roll started ===');
|
||||
debugPrint('Mode: ${mode.value}');
|
||||
|
||||
// ... 现有代码 ...
|
||||
|
||||
debugPrint('Results count: ${results.length}');
|
||||
if (results.isNotEmpty) {
|
||||
debugPrint('First result: ${results.first.title}');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用:`flutter run`
|
||||
2. 进入"今天吃什么"页面
|
||||
3. 点击"开始选择"
|
||||
4. 验证:应该显示选择动画和结果
|
||||
|
||||
- [ ] **Step 4: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题2为已解决。
|
||||
|
||||
---
|
||||
|
||||
## Task 3: 修复今天吃什么筛选功能无反应
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/pages/what_to_eat/what_to_eat_page.dart:1-200`
|
||||
- Test: 手动测试筛选功能
|
||||
|
||||
**问题分析:**
|
||||
- 右侧bar弹窗中的筛选按钮点击无反应
|
||||
- 可能原因:事件监听器未绑定
|
||||
|
||||
- [ ] **Step 1: 检查并修复筛选按钮事件**
|
||||
|
||||
```dart
|
||||
// 在 what_to_eat_page.dart 中找到筛选按钮
|
||||
// 添加事件绑定
|
||||
|
||||
Widget _buildFilterButton() {
|
||||
return GestureDetector(
|
||||
onTap: () => _showFilterSheet(),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(DesignTokens.space2),
|
||||
decoration: BoxDecoration(
|
||||
color: DesignTokens.primaryLight,
|
||||
borderRadius: DesignTokens.borderRadiusMd,
|
||||
),
|
||||
child: const Icon(CupertinoIcons.slider_horizontal_3),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showFilterSheet() {
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (context) => CupertinoActionSheet(
|
||||
title: const Text('筛选条件'),
|
||||
actions: [
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
_showCategoryFilter();
|
||||
},
|
||||
child: const Text('按分类筛选'),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
_showTagFilter();
|
||||
},
|
||||
child: const Text('按标签筛选'),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
_showNutritionFilter();
|
||||
},
|
||||
child: const Text('按营养素筛选'),
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showCategoryFilter() {
|
||||
// 实现分类筛选UI
|
||||
showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (context) => _CategoryFilterDialog(
|
||||
onSelected: (categories) {
|
||||
// 更新筛选条件
|
||||
controller.updateFilters(categories: categories);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用
|
||||
2. 进入"今天吃什么"页面
|
||||
3. 点击右侧筛选按钮
|
||||
4. 验证:应该弹出筛选选项
|
||||
|
||||
- [ ] **Step 3: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题3为已解决。
|
||||
|
||||
---
|
||||
|
||||
## Task 4: 修复营养中心报告功能闪退
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/pages/nutrition/nutrition_center_page.dart:1-100`
|
||||
- Test: 手动测试报告功能
|
||||
|
||||
**问题分析:**
|
||||
- 点击报告按钮后应用闪退
|
||||
- 可能原因:路由未配置或控制器未初始化
|
||||
|
||||
- [ ] **Step 1: 检查路由配置**
|
||||
|
||||
```dart
|
||||
// 在 app_routes.dart 中确认路由
|
||||
class AppRoutes {
|
||||
static const nutritionReport = '/nutrition/report';
|
||||
// ... 其他路由 ...
|
||||
}
|
||||
|
||||
// 在 app_pages.dart 中确认页面注册
|
||||
GetPage(
|
||||
name: AppRoutes.nutritionReport,
|
||||
page: () => const NutritionReportPage(),
|
||||
binding: BindingsBuilder(() {
|
||||
Get.put(NutritionController());
|
||||
}),
|
||||
),
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 修复报告按钮事件**
|
||||
|
||||
```dart
|
||||
// 在 nutrition_center_page.dart 第 40 行附近
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
try {
|
||||
// 确保控制器已初始化
|
||||
if (!Get.isRegistered<NutritionController>()) {
|
||||
Get.put(NutritionController());
|
||||
}
|
||||
|
||||
await Get.toNamed(AppRoutes.nutritionReport);
|
||||
} catch (e) {
|
||||
ToastService.show(message: '打开报告失败: $e');
|
||||
debugPrint('Navigation error: $e');
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: DesignTokens.space2,
|
||||
vertical: DesignTokens.space1,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: DesignTokens.primaryLight,
|
||||
borderRadius: DesignTokens.borderRadiusFull,
|
||||
),
|
||||
child: const Text('报告'),
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 添加错误处理**
|
||||
|
||||
```dart
|
||||
// 在 NutritionReportPage 中添加错误边界
|
||||
class NutritionReportPage extends StatefulWidget {
|
||||
const NutritionReportPage({super.key});
|
||||
|
||||
@override
|
||||
State<NutritionReportPage> createState() => _NutritionReportPageState();
|
||||
}
|
||||
|
||||
class _NutritionReportPageState extends State<NutritionReportPage> {
|
||||
final NutritionController _ctrl = Get.find();
|
||||
bool _hasError = false;
|
||||
String? _errorMessage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadData();
|
||||
}
|
||||
|
||||
Future<void> _loadData() async {
|
||||
try {
|
||||
await _ctrl.loadReportData();
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_hasError = true;
|
||||
_errorMessage = e.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_hasError) {
|
||||
return _buildErrorWidget();
|
||||
}
|
||||
// ... 正常构建 ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用
|
||||
2. 进入营养中心
|
||||
3. 点击"报告"按钮
|
||||
4. 验证:应该正常打开报告页面
|
||||
|
||||
- [ ] **Step 5: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题4为已解决。
|
||||
|
||||
---
|
||||
|
||||
## Task 5: 修复营养中心今天功能无反应
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/pages/nutrition/nutrition_center_page.dart:1-150`
|
||||
- Test: 手动测试今天按钮
|
||||
|
||||
**问题分析:**
|
||||
- 点击今天按钮无反应
|
||||
- 可能原因:事件监听器缺失
|
||||
|
||||
- [ ] **Step 1: 检查并修复今天按钮事件**
|
||||
|
||||
```dart
|
||||
// 在 nutrition_center_page.dart 中找到今天按钮
|
||||
// 添加事件绑定
|
||||
|
||||
Widget _buildTodayButton() {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
// 跳转到今天的饮食日记
|
||||
final today = DateTime.now();
|
||||
_ctrl.selectedDate.value = today;
|
||||
_scrollToToday();
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: DesignTokens.space3,
|
||||
vertical: DesignTokens.space2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: DesignTokens.primary,
|
||||
borderRadius: DesignTokens.borderRadiusMd,
|
||||
),
|
||||
child: const Text(
|
||||
'今天',
|
||||
style: TextStyle(color: CupertinoColors.white),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _scrollToToday() {
|
||||
// 滚动到今天的记录
|
||||
_ctrl.loadRecordsForDate(DateTime.now());
|
||||
ToastService.show(message: '已跳转到今天');
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用
|
||||
2. 进入营养中心
|
||||
3. 点击"今天"按钮
|
||||
4. 验证:应该跳转到今天的记录
|
||||
|
||||
- [ ] **Step 3: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题5为已解决。
|
||||
|
||||
---
|
||||
|
||||
## Task 6: 修复营养中心设置目标布局溢出
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/pages/nutrition/goal_setting_page.dart:1-200`
|
||||
- Test: 手动测试设置目标功能
|
||||
|
||||
**问题分析:**
|
||||
- 点击设置目标时布局溢出
|
||||
- 可能原因:固定高度不合适
|
||||
|
||||
- [ ] **Step 1: 使用 SingleChildScrollView 包裹内容**
|
||||
|
||||
```dart
|
||||
// 在 goal_setting_page.dart 中修改布局
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: const Text('设置目标'),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(DesignTokens.space4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildCalorieGoal(),
|
||||
const SizedBox(height: DesignTokens.space4),
|
||||
_buildNutrientGoals(),
|
||||
const SizedBox(height: DesignTokens.space4),
|
||||
_buildSaveButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCalorieGoal() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(DesignTokens.space3),
|
||||
decoration: BoxDecoration(
|
||||
color: DesignTokens.card,
|
||||
borderRadius: DesignTokens.borderRadiusMd,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('每日热量目标', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: DesignTokens.space2),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CupertinoTextField(
|
||||
controller: _calorieController,
|
||||
keyboardType: TextInputType.number,
|
||||
placeholder: '例如: 2000',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: DesignTokens.space2),
|
||||
const Text('kcal'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 使用响应式布局**
|
||||
|
||||
```dart
|
||||
// 添加 LayoutBuilder 支持不同屏幕尺寸
|
||||
Widget _buildNutrientGoals() {
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isSmallScreen = constraints.maxWidth < 600;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('营养素目标', style: TextStyle(fontSize: 16)),
|
||||
const SizedBox(height: DesignTokens.space2),
|
||||
Wrap(
|
||||
spacing: DesignTokens.space2,
|
||||
runSpacing: DesignTokens.space2,
|
||||
children: [
|
||||
_buildNutrientInput(
|
||||
label: '蛋白质',
|
||||
controller: _proteinController,
|
||||
unit: 'g',
|
||||
width: isSmallScreen ? constraints.maxWidth : 150,
|
||||
),
|
||||
_buildNutrientInput(
|
||||
label: '碳水化合物',
|
||||
controller: _carbsController,
|
||||
unit: 'g',
|
||||
width: isSmallScreen ? constraints.maxWidth : 150,
|
||||
),
|
||||
_buildNutrientInput(
|
||||
label: '脂肪',
|
||||
controller: _fatController,
|
||||
unit: 'g',
|
||||
width: isSmallScreen ? constraints.maxWidth : 150,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用
|
||||
2. 进入营养中心
|
||||
3. 点击"设置目标"
|
||||
4. 验证:应该正常显示,无布局溢出
|
||||
|
||||
- [ ] **Step 4: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题6为已解决。
|
||||
|
||||
---
|
||||
|
||||
## Task 7: 修复营养中心删除记录无反应
|
||||
|
||||
**Files:**
|
||||
- Modify: `lib/src/pages/nutrition/meal_diary_page.dart:1-200`
|
||||
- Test: 手动测试删除功能
|
||||
|
||||
**问题分析:**
|
||||
- 点击删除记录按钮无反应
|
||||
- 可能原因:删除功能未实现
|
||||
|
||||
- [ ] **Step 1: 实现删除功能**
|
||||
|
||||
```dart
|
||||
// 在 meal_diary_page.dart 中添加删除方法
|
||||
void _deleteRecord(MealRecordModel record) {
|
||||
showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (context) => CupertinoAlertDialog(
|
||||
title: const Text('确认删除'),
|
||||
content: Text('确定要删除 ${record.mealType} 的记录吗?'),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
isDefaultAction: true,
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
isDestructiveAction: true,
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
try {
|
||||
await _ctrl.deleteRecord(record.id);
|
||||
ToastService.show(message: '删除成功');
|
||||
} catch (e) {
|
||||
ToastService.show(message: '删除失败: $e');
|
||||
}
|
||||
},
|
||||
child: const Text('删除'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 在列表项中添加删除按钮
|
||||
Widget _buildRecordItem(MealRecordModel record) {
|
||||
return Dismissible(
|
||||
key: Key(record.id),
|
||||
direction: DismissDirection.endToStart,
|
||||
confirmDismiss: (direction) async {
|
||||
_deleteRecord(record);
|
||||
return false;
|
||||
},
|
||||
background: Container(
|
||||
alignment: Alignment.centerRight,
|
||||
padding: const EdgeInsets.only(right: DesignTokens.space4),
|
||||
color: CupertinoColors.destructiveRed,
|
||||
child: const Icon(CupertinoIcons.delete, color: CupertinoColors.white),
|
||||
),
|
||||
child: ListTile(
|
||||
title: Text(record.mealType),
|
||||
subtitle: Text('${record.totalCalories} kcal'),
|
||||
trailing: CupertinoButton(
|
||||
onPressed: () => _deleteRecord(record),
|
||||
child: const Icon(CupertinoIcons.delete),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 在控制器中添加删除方法**
|
||||
|
||||
```dart
|
||||
// 在 meal_record_controller.dart 中添加
|
||||
Future<void> deleteRecord(String id) async {
|
||||
try {
|
||||
final box = HiveService.mealRecordBox;
|
||||
await box.delete(id);
|
||||
records.removeWhere((r) => r.id == id);
|
||||
update();
|
||||
} catch (e) {
|
||||
debugPrint('deleteRecord error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 手动测试**
|
||||
|
||||
测试步骤:
|
||||
1. 运行应用
|
||||
2. 进入营养中心
|
||||
3. 添加一条记录
|
||||
4. 点击删除按钮
|
||||
5. 验证:应该弹出确认对话框,确认后删除
|
||||
|
||||
- [ ] **Step 4: 更新文档**
|
||||
|
||||
在 `docs/dev/ISSUES_TO_RESOLVE.md` 中标记问题7为已解决。
|
||||
|
||||
---
|
||||
|
||||
## Task 8: 更新文档以反映实际状态
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/dev/UNFINISHED_FEATURES.md:1-50`
|
||||
- Modify: `docs/dev/ISSUES_TO_RESOLVE.md:1-50`
|
||||
|
||||
**问题分析:**
|
||||
- 文档显示功能100%完成,但实际找不到
|
||||
- 需要更新文档以反映真实状态
|
||||
|
||||
- [ ] **Step 1: 更新 UNFINISHED_FEATURES.md**
|
||||
|
||||
```markdown
|
||||
## 📊 总体进度
|
||||
|
||||
| 阶段 | 总任务 | 已完成 | 未完成 | 完成率 |
|
||||
|------|--------|--------|--------|--------|
|
||||
| 三:热量追踪+营养分析 | 7 | 7 | 0 | 100% ✅ |
|
||||
| 四:购物清单 | 5 | 5 | 0 | 100% ✅ |
|
||||
| 五:增强功能 | 7 | 7 | 0 | 100% ✅ |
|
||||
| 六:主页体验优化 | 5 | 5 | 0 | 100% ✅ |
|
||||
| Bug 修复 | 19 | 19 | 0 | 100% ✅ |
|
||||
| 七:今天吃什么增强 | 5 | 5 | 0 | 100% ✅ |
|
||||
| **合计** | **48** | **48** | **0** | **100% ✅** |
|
||||
|
||||
### ⚠️ 已知问题
|
||||
虽然功能已实现,但存在以下问题需要修复:
|
||||
1. 首页点击菜品出现红屏错误 ✅ 已修复
|
||||
2. 今天吃什么功能无结果 ✅ 已修复
|
||||
3. 今天吃什么筛选功能无反应 ✅ 已修复
|
||||
4. 营养中心报告功能闪退卡死 ✅ 已修复
|
||||
5. 营养中心今天功能无反应 ✅ 已修复
|
||||
6. 营养中心设置目标布局溢出 ✅ 已修复
|
||||
7. 营养中心删除记录无反应 ✅ 已修复
|
||||
|
||||
详见 `docs/dev/ISSUES_TO_RESOLVE.md`
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 更新 ISSUES_TO_RESOLVE.md**
|
||||
|
||||
在所有问题后添加修复状态和时间戳。
|
||||
|
||||
- [ ] **Step 3: 创建功能索引文档**
|
||||
|
||||
```markdown
|
||||
# 功能索引
|
||||
|
||||
创建时间: 2026-04-09
|
||||
更新时间: 2026-04-09
|
||||
|
||||
## 已完成功能
|
||||
|
||||
### 核心功能
|
||||
- ✅ 首页信息流(推荐/最新/热门)
|
||||
- ✅ 菜谱详情页
|
||||
- ✅ 搜索功能
|
||||
- ✅ 收藏功能
|
||||
- ✅ 今天吃什么
|
||||
|
||||
### 营养中心
|
||||
- ✅ 饮食日记
|
||||
- ✅ 热量追踪
|
||||
- ✅ 营养分析报告
|
||||
- ✅ 目标设置
|
||||
|
||||
### 工具
|
||||
- ✅ 烹饪计时器
|
||||
- ✅ 用量换算
|
||||
- ✅ BMI计算器
|
||||
- ✅ 份量缩放
|
||||
- ✅ 过敏原检测
|
||||
|
||||
### 购物清单
|
||||
- ✅ 添加/删除食材
|
||||
- ✅ 分类展示
|
||||
- ✅ 勾选已购
|
||||
|
||||
## 功能位置
|
||||
|
||||
| 功能 | 文件路径 |
|
||||
|------|---------|
|
||||
| 首页 | `lib/src/pages/home_page.dart` |
|
||||
| 菜谱详情 | `lib/src/pages/recipe/recipe_detail_page.dart` |
|
||||
| 搜索 | `lib/src/pages/search/search_page.dart` |
|
||||
| 收藏 | `lib/src/pages/favorites/favorites_page.dart` |
|
||||
| 今天吃什么 | `lib/src/pages/what_to_eat/what_to_eat_page.dart` |
|
||||
| 营养中心 | `lib/src/pages/nutrition/nutrition_center_page.dart` |
|
||||
| 购物清单 | `lib/src/pages/shopping/shopping_list_page.dart` |
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 提交文档更新**
|
||||
|
||||
```bash
|
||||
git add docs/dev/UNFINISHED_FEATURES.md docs/dev/ISSUES_TO_RESOLVE.md docs/dev/FEATURE_INDEX.md
|
||||
git commit -m "docs: 更新功能完成状态和问题修复记录"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验收标准
|
||||
|
||||
### 功能验收
|
||||
- [ ] 首页点击菜品正常跳转详情页
|
||||
- [ ] 今天吃什么选择功能正常工作
|
||||
- [ ] 今天吃什么筛选功能正常工作
|
||||
- [ ] 营养中心报告功能正常打开
|
||||
- [ ] 营养中心今天按钮正常工作
|
||||
- [ ] 营养中心设置目标无布局溢出
|
||||
- [ ] 营养中心删除记录功能正常工作
|
||||
|
||||
### 文档验收
|
||||
- [ ] UNFINISHED_FEATURES.md 反映真实状态
|
||||
- [ ] ISSUES_TO_RESOLVE.md 标注所有已解决问题
|
||||
- [ ] 创建功能索引文档
|
||||
|
||||
---
|
||||
|
||||
## 执行建议
|
||||
|
||||
**推荐使用 Subagent-Driven Development:**
|
||||
- 每个Task分配给独立的subagent
|
||||
- 在Task之间进行review
|
||||
- 快速迭代,逐步修复问题
|
||||
|
||||
**执行顺序:**
|
||||
1. Task 1-7: 修复功能问题(可并行)
|
||||
2. Task 8: 更新文档(在所有问题修复后)
|
||||
Reference in New Issue
Block a user