import 'package:flutter/material.dart'; import 'package:food_hub_app/api/recipe.dart'; import 'package:food_hub_app/models/recipe.dart'; import 'package:food_hub_app/widgets/common/index.dart'; class RecipeDetailPage extends StatefulWidget { const RecipeDetailPage({super.key}); @override State createState() => _RecipeDetailState(); } class _RecipeDetailState extends State { RecipeDetail recipe = RecipeDetail( id: 0, name: '', category: '', recommendRate: 0, remark: '', isShare: false, userId: 0, username: '', avatar: '', materialList: [], stepList: [], recordList: [], likeList: [], favouriteList: [], commentList: [], ); // 定义三个分类列表 List mainMaterialList = []; // 主料 List auxiliaryMaterialList = []; // 配料 List accessoryMaterialList = []; // 辅料 @override void didChangeDependencies() { super.didChangeDependencies(); refreshRecipeDetail(); } Future refreshRecipeDetail() async { // 获取参数 final args = ModalRoute.of(context)?.settings.arguments as Map; final recipeId = args['id']; final result = await queryRecipeByIdApi(recipeId); setState(() { recipe = result; getRecipeMaterial(); }); } void getRecipeMaterial() { for (var material in recipe.materialList) { switch (material.type) { case '主料': mainMaterialList.add(material); break; case '配料': auxiliaryMaterialList.add(material); break; case '辅料': accessoryMaterialList.add(material); break; } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('菜谱信息', style: TextStyle(color: Colors.white)), backgroundColor: Theme.of(context).primaryColor, leading: IconButton( icon: Icon(Icons.arrow_back, color: Colors.white), onPressed: () => Navigator.pop(context), ), ), backgroundColor: Color(0xFFF5F5F5), body: SingleChildScrollView( child: Padding(padding: EdgeInsets.all(5), child: _buildRecipeDetail()), ), ); } Widget _buildRecipeDetail() { return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildTitleSection(), SizedBox(height: 10), _buildInfoCard( context, icon: Icons.info, title: "基础信息", content: _buildTag(context, title: recipe.category), ), _buildInfoCard( context, icon: Icons.shopping_cart, title: "食材信息", content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildMaterialSection(context, '主料', mainMaterialList), _buildMaterialSection(context, '辅料', auxiliaryMaterialList), _buildMaterialSection(context, '调料', accessoryMaterialList), ], ), ), _buildInfoCard( context, icon: Icons.list, title: "步骤信息", content: Column( children: recipe.stepList.map((step) => _buildStepSection(step)).toList(), ), ), _buildInfoCard( context, icon: Icons.note, title: "其他信息", content: Text( '备注:${recipe.remark.isEmpty ? '无' : recipe.remark}', style: const TextStyle(height: 1.5), ), ), ], ); } Widget _buildTag(BuildContext context, {required String title}) { return Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: Color.lerp(Theme.of(context).primaryColor, Colors.white, 0.8), borderRadius: BorderRadius.circular(10), ), child: Text( title, style: TextStyle(color: Theme.of(context).primaryColor), ), ); } Widget _buildTitleSection() { return Text( recipe.name, style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ); } Widget _buildMaterialSection( BuildContext context, String title, List materials, ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(bottom: 8, top: 12), child: Text(title, style: TextStyle(fontWeight: FontWeight.bold)), ), if (materials.isEmpty) _buildTag(context, title: '无') else Wrap( spacing: 8.0, runSpacing: 8.0, children: materials .map( (m) => _buildTag(context, title: '${m.name} ${m.amount}'), ) .toList(), ), ], ); } Widget _buildStepSection(RecipeStep step) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("第${step.sort + 1}步"), SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( step.content, style: const TextStyle( height: 1.4, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), if (step.imageUrl.isNotEmpty) ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.network( step.imageUrl, width: double.infinity, height: 180, fit: BoxFit.contain, ), ), ], ), ), ], ); } Widget _buildInfoCard( BuildContext context, { required IconData icon, required String title, required Widget content, }) { return cardContainer( Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(icon, color: Theme.of(context).primaryColor), const SizedBox(width: 5), Text( title, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ], ), SizedBox(height: 5), content, ], ), ); } }