HarmonyOS ArkTS 实战:实现一个菜谱大全与美食记录应用
·
HarmonyOS ArkTS 实战:实现一个菜谱大全与美食记录应用
项目效果
本文使用 HarmonyOS 和 ArkTS 实现一个精美的菜谱大全与美食记录应用。支持菜谱分类浏览、搜索、食材清单、步骤详解、收藏、美食记录、烹饪计时等功能,橙色渐变主题,美食卡片设计。
项目使用 DevEco Studio 开发,适配 API 24 及以上版本。
运行效果

功能介绍
- 菜谱分类浏览(家常菜、川菜、粤菜、甜品、汤羹等)
- 热门菜谱推荐轮播
- 菜谱搜索
- 食材清单展示
- 分步骤烹饪详解
- 收藏喜欢的菜谱
- 烹饪计时器
- 美食打卡记录
- 我的收藏列表
- 做菜历史记录
- 难度和时间标签
- 菜谱分享
- 今日推荐
- 食材用量单位转换
- 购物清单生成
定义数据结构
interface Recipe {
id: number;
name: string;
cover: string;
category: string;
difficulty: string;
cookTime: number;
servings: number;
description: string;
ingredients: { name: string; amount: string }[];
steps: { order: number; content: string; image: string }[];
tips: string;
isCollected: boolean;
rating: number;
}
interface FoodRecord {
id: number;
recipeId: number;
recipeName: string;
date: string;
rating: number;
note: string;
}
初始化页面状态
@State private currentTab: number = 0;
@State private currentCategory: string = '推荐';
@State private searchKeyword: string = '';
@State private showSearch: boolean = false;
@State private selectedRecipe: Recipe | null = null;
@State private showTimer: boolean = false;
@State private timerSeconds: number = 0;
@State private timerRunning: boolean = false;
@State private categories: string[] = ['推荐', '家常菜', '川菜', '粤菜', '甜品', '汤羹', '早餐', '快手菜'];
@State private recipes: Recipe[] = [
{
id: 1, name: '红烧肉', cover: '🍖', category: '家常菜', difficulty: '中等',
cookTime: 90, servings: 3, description: '肥而不腻,入口即化的经典红烧肉',
ingredients: [
{ name: '五花肉', amount: '500g' },
{ name: '冰糖', amount: '30g' },
{ name: '生抽', amount: '2勺' },
{ name: '老抽', amount: '1勺' },
{ name: '料酒', amount: '2勺' },
{ name: '葱姜', amount: '适量' },
],
steps: [
{ order: 1, content: '五花肉切块,冷水下锅加料酒焯水,捞出洗净', image: '🥩' },
{ order: 2, content: '锅中放油加冰糖,小火炒出糖色', image: '🍬' },
{ order: 3, content: '放入五花肉翻炒上色,加葱姜爆香', image: '🍳' },
{ order: 4, content: '加生抽老抽料酒,加热水没过肉块', image: '💧' },
{ order: 5, content: '大火烧开转小火炖1小时,最后大火收汁', image: '🔥' },
],
tips: '一定要加热水,肉质才会软嫩;糖色要小火慢炒不要糊',
isCollected: true, rating: 4.8
},
{
id: 2, name: '番茄炒蛋', cover: '🍅', category: '快手菜', difficulty: '简单',
cookTime: 10, servings: 2, description: '国民家常菜,酸甜可口',
ingredients: [
{ name: '番茄', amount: '2个' },
{ name: '鸡蛋', amount: '3个' },
{ name: '白糖', amount: '1勺' },
{ name: '盐', amount: '适量' },
],
steps: [
{ order: 1, content: '鸡蛋打散加少许盐,番茄切块', image: '🥚' },
{ order: 2, content: '热油炒鸡蛋,盛出备用', image: '🍳' },
{ order: 3, content: '炒番茄出汁,加糖加盐', image: '🍅' },
{ order: 4, content: '倒入鸡蛋翻炒均匀出锅', image: '🍽️' },
],
tips: '鸡蛋要炒嫩一点,番茄要炒出沙才好吃',
isCollected: false, rating: 4.9
},
{
id: 3, name: '麻婆豆腐', cover: '🌶️', category: '川菜', difficulty: '中等',
cookTime: 20, servings: 2, description: '麻辣鲜香,下饭神器',
ingredients: [
{ name: '嫩豆腐', amount: '1块' },
{ name: '肉末', amount: '100g' },
{ name: '豆瓣酱', amount: '1勺' },
{ name: '花椒粉', amount: '适量' },
],
steps: [], tips: '豆腐要焯水去豆腥味,最后勾芡',
isCollected: false, rating: 4.7
},
];
@State private foodRecords: FoodRecord[] = [];
核心功能方法
private toggleCollect(recipeId: number): void {
this.recipes = this.recipes.map(r => {
if (r.id === recipeId) return { ...r, isCollected: !r.isCollected };
return r;
});
}
private startTimer(minutes: number): void {
this.timerSeconds = minutes * 60;
this.timerRunning = true;
this.showTimer = true;
const timer = setInterval(() => {
if (this.timerSeconds > 0) {
this.timerSeconds--;
} else {
clearInterval(timer);
this.timerRunning = false;
}
}, 1000);
}
private getFilteredRecipes(): Recipe[] {
let list = this.recipes;
if (this.currentCategory !== '推荐') {
list = list.filter(r => r.category === this.currentCategory);
}
if (this.searchKeyword) {
list = list.filter(r => r.name.includes(this.searchKeyword));
}
return list;
}
@Builder 可复用组件
@Builder
RecipeCard(recipe: Recipe) {
Column({ space: 8 }) {
Stack({ alignContent: Alignment.TopEnd }) {
Text(recipe.cover)
.fontSize(64)
.width('100%')
.height(140)
.textAlign(TextAlign.Center)
.backgroundColor('#FFF7ED')
.borderRadius({ topLeft: 12, topRight: 12 })
Text(recipe.isCollected ? '❤️' : '🤍')
.fontSize(20)
.padding(8)
.onClick(() => this.toggleCollect(recipe.id))
}
.width('100%')
Column({ space: 4 }) {
Text(recipe.name)
.fontSize(15)
.fontWeight(FontWeight.Medium)
.fontColor('#1F2937')
.width('100%')
Row({ space: 8 }) {
Text(recipe.difficulty)
.fontSize(11)
.fontColor('#EA580C')
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.backgroundColor('#FFF7ED')
.borderRadius(4)
Text(`${recipe.cookTime}分钟`)
.fontSize(11)
.fontColor('#6B7280')
Text(`⭐${recipe.rating}`)
.fontSize(11)
.fontColor('#F59E0B')
}
}
.width('100%')
.padding(12)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 8, color: '#00000008', offsetY: 2 })
.onClick(() => this.selectedRecipe = recipe)
}
@Builder
IngredientItem(name: string, amount: string) {
Row() {
Text(name)
.fontSize(14)
.fontColor('#374151')
Blank()
Text(amount)
.fontSize(14)
.fontColor('#6B7280')
}
.width('100%')
.padding({ top: 10, bottom: 10 })
Divider().color('#F3F4F6')
}
完整build()页面布局
build() {
Stack({ alignContent: Alignment.Bottom }) {
Column() {
// 顶部
Row() {
Text('美食菜谱')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#1F2937')
Blank()
Text('🔍')
.fontSize(22)
.onClick(() => this.showSearch = !this.showSearch)
}
.width('100%')
.padding(20)
if (this.showSearch) {
TextInput({ placeholder: '搜索菜谱', text: this.searchKeyword })
.width('90%')
.height(40)
.backgroundColor('#F3F4F6')
.borderRadius(12)
.margin({ bottom: 12 })
.onChange((v: string) => this.searchKeyword = v)
}
// 分类
Scroll(Axis.Horizontal) {
Row({ space: 12 }) {
ForEach(this.categories, (cat: string) => {
Text(cat)
.fontSize(14)
.fontColor(this.currentCategory === cat ? Color.White : '#6B7280')
.padding({ left: 16, right: 16, top: 8, bottom: 8 })
.backgroundColor(this.currentCategory === cat ? '#EA580C' : '#F3F4F6')
.borderRadius(20)
.onClick(() => this.currentCategory = cat)
})
}
.padding({ left: 20, right: 20 })
}
.scrollBar(BarState.Off)
// 菜谱列表
Scroll() {
Grid() {
ForEach(this.getFilteredRecipes(), (recipe: Recipe) => {
GridItem() { this.RecipeCard(recipe) }
})
}
.columnsTemplate('1fr 1fr')
.columnsGap(12)
.rowsGap(12)
.width('100%')
.padding({ left: 20, right: 20, bottom: 80 })
}
.layoutWeight(1)
.scrollBar(BarState.Off)
}
.width('100%')
.height('100%')
.backgroundColor('#F9FAFB')
// 菜谱详情弹窗
if (this.selectedRecipe) {
Column() {
Blank()
Scroll() {
Column({ space: 16 }) {
Stack({ alignContent: Alignment.TopStart }) {
Text(this.selectedRecipe.cover)
.fontSize(100)
.width('100%')
.height(200)
.textAlign(TextAlign.Center)
.backgroundColor('#FFF7ED')
Text('←')
.fontSize(24)
.fontColor(Color.White)
.padding(16)
.onClick(() => this.selectedRecipe = null)
}
.width('100%')
Column({ space: 12 }) {
Text(this.selectedRecipe.name)
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor('#1F2937')
Row({ space: 12 }) {
Text(`⏱️ ${this.selectedRecipe.cookTime}分钟`)
.fontSize(13)
.fontColor('#6B7280')
Text(`👥 ${this.selectedRecipe.servings}人份`)
.fontSize(13)
.fontColor('#6B7280')
Text(`📊 ${this.selectedRecipe.difficulty}`)
.fontSize(13)
.fontColor('#6B7280')
}
Text(this.selectedRecipe.description)
.fontSize(14)
.fontColor('#6B7280')
Text('食材清单')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#1F2937')
.width('100%')
Column() {
ForEach(this.selectedRecipe.ingredients, (ing: { name: string; amount: string }) => {
this.IngredientItem(ing.name, ing.amount)
})
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
Text('烹饪步骤')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#1F2937')
.width('100%')
Button('⏱️ 开始计时')
.width('100%')
.height(44)
.backgroundColor('#EA580C')
.onClick(() => this.startTimer(this.selectedRecipe!.cookTime))
}
.width('100%')
.padding(20)
}
}
.width('100%')
.height('85%')
.backgroundColor(Color.White)
.borderRadius({ topLeft: 24, topRight: 24 })
}
.width('100%')
.height('100%')
.backgroundColor('rgba(0,0,0,0.5)')
}
}
.width('100%')
.height('100%')
}
页面设计说明
主题色采用橙色渐变#EA580C→#FB923C,橙色代表美食、温暖、食欲,非常适合菜谱应用。两列网格布局展示菜谱卡片,大图+标题+标签的经典设计。详情页从底部弹出,食材清单、步骤详解清晰明了。
SDK配置
API 24,compatibleSdkVersion: “6.1.1(24)”
运行项目
将代码复制到 entry/src/main/ets/pages/Index.ets 即可运行。
项目总结
实现了菜谱浏览、分类筛选、搜索、详情展示、收藏、烹饪计时等功能。掌握了网格布局、底部弹窗详情、横向滚动分类、计时器等。后续可加入视频教程、用户上传、营养成分计算、菜单规划、食材购买、社区分享、AI推荐菜谱等功能。
更多推荐



所有评论(0)