feat:新增菜谱详细信息模块
This commit is contained in:
@@ -14,11 +14,10 @@ class MomentPage extends StatefulWidget {
|
||||
|
||||
class _MomentPageState extends State<MomentPage> {
|
||||
List<Moment> momentList = [];
|
||||
|
||||
// 分页相关变量
|
||||
int _page = 1;
|
||||
int _currentPage = 1;
|
||||
final int _pageSize = 3;
|
||||
bool _hasMore = true;
|
||||
|
||||
// 初始化EasyRefresh控制器
|
||||
final EasyRefreshController _freshController = EasyRefreshController(
|
||||
controlFinishRefresh: true,
|
||||
@@ -49,11 +48,10 @@ class _MomentPageState extends State<MomentPage> {
|
||||
try {
|
||||
// 如果是刷新,重置页码
|
||||
if (isRefresh) {
|
||||
_page = 1;
|
||||
_currentPage = 1;
|
||||
}
|
||||
|
||||
// 调用API获取数据,传入页码和页大小
|
||||
final result = await queryMomentByPageApi(_page, _pageSize);
|
||||
final result = await queryMomentByPageApi(_currentPage, _pageSize);
|
||||
|
||||
setState(() {
|
||||
if (isRefresh) {
|
||||
@@ -68,7 +66,7 @@ class _MomentPageState extends State<MomentPage> {
|
||||
_hasMore = result.current < result.pages;
|
||||
// 如果有更多数据,准备加载下一页
|
||||
if (_hasMore) {
|
||||
_page++;
|
||||
_currentPage++;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
247
lib/views/recipe_detail.dart
Normal file
247
lib/views/recipe_detail.dart
Normal file
@@ -0,0 +1,247 @@
|
||||
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<RecipeDetailPage> createState() => _RecipeDetailState();
|
||||
}
|
||||
|
||||
class _RecipeDetailState extends State<RecipeDetailPage> {
|
||||
RecipeDetail recipe = RecipeDetail(
|
||||
id: 0,
|
||||
name: '',
|
||||
category: '',
|
||||
recommendRate: 0,
|
||||
remark: '',
|
||||
isShare: false,
|
||||
userId: 0,
|
||||
username: '',
|
||||
avatar: '',
|
||||
materialList: [],
|
||||
stepList: [],
|
||||
recordList: [],
|
||||
likeList: [],
|
||||
favouriteList: [],
|
||||
commentList: [],
|
||||
);
|
||||
|
||||
// 定义三个分类列表
|
||||
List<RecipeMaterial> mainMaterialList = []; // 主料
|
||||
List<RecipeMaterial> auxiliaryMaterialList = []; // 配料
|
||||
List<RecipeMaterial> accessoryMaterialList = []; // 辅料
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
refreshRecipeDetail();
|
||||
}
|
||||
|
||||
Future<void> 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<RecipeMaterial> 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,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user