perf: 优化食物选择

This commit is contained in:
richarjiang
2025-08-29 10:13:59 +08:00
parent 8d567fb4cb
commit f38f495008
2 changed files with 79 additions and 12 deletions

View File

@@ -1,6 +1,7 @@
import { FoodDetailModal } from '@/components/model/food/FoodDetailModal';
import { useFoodLibrary, useFoodSearch } from '@/hooks/useFoodLibrary';
import type { FoodItem, MealType, SelectedFoodItem } from '@/types/food';
import { addDietRecord, type CreateDietRecordDto } from '@/services/dietRecords';
import { Ionicons } from '@expo/vector-icons';
import { Image } from 'expo-image';
import { useLocalSearchParams, useRouter } from 'expo-router';
@@ -45,6 +46,7 @@ export default function FoodLibraryScreen() {
const [selectedFoodItems, setSelectedFoodItems] = useState<SelectedFoodItem[]>([]);
const [showMealSelector, setShowMealSelector] = useState(false);
const [currentMealType, setCurrentMealType] = useState<MealType>(mealType);
const [isRecording, setIsRecording] = useState(false);
// 获取当前选中的分类
const selectedCategory = categories.find(cat => cat.id === selectedCategoryId);
@@ -127,6 +129,47 @@ export default function FoodLibraryScreen() {
setSelectedFood(null);
};
// 处理饮食记录
const handleRecordDiet = async () => {
if (selectedFoodItems.length === 0) return;
setIsRecording(true);
try {
// 逐个记录选中的食物
for (const item of selectedFoodItems) {
const dietRecordData: CreateDietRecordDto = {
mealType: currentMealType,
foodName: item.food.name,
foodDescription: item.food.description,
portionDescription: `${item.amount}${item.unit}`,
estimatedCalories: item.calories,
proteinGrams: item.food.protein ? Number(((item.food.protein * item.amount) / 100).toFixed(2)) : undefined,
carbohydrateGrams: item.food.carbohydrate ? Number(((item.food.carbohydrate * item.amount) / 100).toFixed(2)) : undefined,
fatGrams: item.food.fat ? Number(((item.food.fat * item.amount) / 100).toFixed(2)) : undefined,
fiberGrams: item.food.fiber ? Number(((item.food.fiber * item.amount) / 100).toFixed(2)) : undefined,
sugarGrams: item.food.sugar ? Number(((item.food.sugar * item.amount) / 100).toFixed(2)) : undefined,
sodiumMg: item.food.sodium ? Number(((item.food.sodium * item.amount) / 100).toFixed(2)) : undefined,
additionalNutrition: item.food.additionalNutrition,
source: 'manual',
mealTime: new Date().toISOString(),
imageUrl: item.food.imageUrl,
};
await addDietRecord(dietRecordData);
}
// 记录成功后清空选择列表并返回
setSelectedFoodItems([]);
router.back();
} catch (error) {
console.error('记录饮食失败:', error);
// 这里可以显示错误提示
} finally {
setIsRecording(false);
}
};
// 处理餐次选择
const handleMealTypeSelect = (selectedMealType: MealType) => {
setCurrentMealType(selectedMealType);
@@ -324,20 +367,19 @@ export default function FoodLibraryScreen() {
<TouchableOpacity
style={[
styles.recordButton,
selectedFoodItems.length === 0 && styles.recordButtonDisabled
(selectedFoodItems.length === 0 || isRecording) && styles.recordButtonDisabled
]}
disabled={selectedFoodItems.length === 0}
onPress={() => {
// 这里可以处理记录逻辑
console.log('记录食物:', selectedFoodItems);
// 记录成功后可以清空选择列表或返回上一页
router.back();
}}
disabled={selectedFoodItems.length === 0 || isRecording}
onPress={handleRecordDiet}
>
{isRecording ? (
<ActivityIndicator size="small" color="#FFF" />
) : (
<Text style={[
styles.recordButtonText,
selectedFoodItems.length === 0 && styles.recordButtonTextDisabled
]}></Text>
)}
</TouchableOpacity>
</View>

View File

@@ -3,6 +3,27 @@ import { api } from '@/services/api';
export type MealType = 'breakfast' | 'lunch' | 'dinner' | 'snack' | 'other';
export type RecordSource = 'manual' | 'vision' | 'other';
export type CreateDietRecordDto = {
mealType: MealType;
foodName: string;
foodDescription?: string;
weightGrams?: number;
portionDescription?: string;
estimatedCalories?: number;
proteinGrams?: number;
carbohydrateGrams?: number;
fatGrams?: number;
fiberGrams?: number;
sugarGrams?: number;
sodiumMg?: number;
additionalNutrition?: Record<string, any>;
source?: RecordSource;
mealTime?: string;
imageUrl?: string;
aiAnalysisResult?: Record<string, any>;
notes?: string;
};
export type DietRecord = {
id: number;
mealType: MealType;
@@ -68,6 +89,10 @@ export async function getDietRecords({
}>(`/diet-records${params}`);
}
export async function addDietRecord(dto: CreateDietRecordDto): Promise<DietRecord> {
return await api.post<DietRecord>('/diet-records', dto);
}
export async function deleteDietRecord(recordId: number): Promise<void> {
await api.delete(`/diet-records/${recordId}`);
}