feat:更新好友菜谱功能
This commit is contained in:
@@ -25,10 +25,10 @@ Future<bool> deleteRecipeApi(int id) {
|
||||
return httpUtil.delete<bool>("/food/recipe/$id");
|
||||
}
|
||||
|
||||
Future<List<Recipe>> queryRecipeByUserApi(int id) {
|
||||
return httpUtil.get<List<Recipe>>(
|
||||
Future<List<RecipeSummary>> queryRecipeByUserApi(int id) {
|
||||
return httpUtil.get<List<RecipeSummary>>(
|
||||
"/food/recipe/user/$id",
|
||||
converter: (data) => convertList<Recipe>(data, Recipe.fromJson),
|
||||
converter: (data) => convertList<RecipeSummary>(data, RecipeSummary.fromJson),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,6 @@ class RecipeSummary {
|
||||
int commentCount;
|
||||
int userId;
|
||||
String username;
|
||||
String avatar;
|
||||
|
||||
RecipeSummary({
|
||||
required this.id,
|
||||
@@ -186,7 +185,6 @@ class RecipeSummary {
|
||||
required this.isShare,
|
||||
required this.userId,
|
||||
required this.username,
|
||||
required this.avatar,
|
||||
required this.recordList,
|
||||
required this.likeCount,
|
||||
required this.favouriteCount,
|
||||
|
||||
@@ -149,7 +149,6 @@ RecipeSummary _$RecipeSummaryFromJson(Map<String, dynamic> json) =>
|
||||
isShare: json['isShare'] as bool,
|
||||
userId: (json['userId'] as num).toInt(),
|
||||
username: json['username'] as String,
|
||||
avatar: json['avatar'] as String,
|
||||
recordList:
|
||||
(json['recordList'] as List<dynamic>)
|
||||
.map((e) => FoodRecord.fromJson(e as Map<String, dynamic>))
|
||||
@@ -172,7 +171,6 @@ Map<String, dynamic> _$RecipeSummaryToJson(RecipeSummary instance) =>
|
||||
'commentCount': instance.commentCount,
|
||||
'userId': instance.userId,
|
||||
'username': instance.username,
|
||||
'avatar': instance.avatar,
|
||||
};
|
||||
|
||||
RecipeDetail _$RecipeDetailFromJson(Map<String, dynamic> json) => RecipeDetail(
|
||||
|
||||
@@ -116,6 +116,26 @@ class FoodProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> queryRecipeByUserId(int userId) async {
|
||||
if (isLoading) return;
|
||||
|
||||
try {
|
||||
isLoading = true;
|
||||
error = null;
|
||||
notifyListeners();
|
||||
|
||||
final result = await queryRecipeByUserApi(userId);
|
||||
recipeSummaryList = result;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
error = '加载数据失败: $e';
|
||||
debugPrint('加载数据失败: $e');
|
||||
} finally {
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshRecipeList() async {
|
||||
if (isLoading) return;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class LoginPage extends StatefulWidget {
|
||||
class _LoginPage extends State<LoginPage> {
|
||||
final GlobalKey _formKey = GlobalKey<FormState>();
|
||||
|
||||
String _username = "Cxx0822", _password = "19940822Cxx";
|
||||
String _username = "", _password = "";
|
||||
bool _isRemember = false;
|
||||
bool _isObscure = true;
|
||||
bool _isLoading = false;
|
||||
|
||||
@@ -158,7 +158,10 @@ class ProfilePageState extends State<ProfilePage> {
|
||||
else if (provider.error.isNotEmpty)
|
||||
Text(provider.error)
|
||||
else
|
||||
SingleChildScrollView(child: _buildContent(provider, context)),
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(bottom: 90),
|
||||
child: _buildContent(provider, context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -74,7 +74,7 @@ class ProfileUserPageState extends State<ProfileUserPage> {
|
||||
index: currentTab.index,
|
||||
children: [
|
||||
MomentList(momentList: provider.momentList, isUser: false),
|
||||
Text('个人菜谱'),
|
||||
RecipeList(userId: provider.currentUser.id!),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -91,11 +91,11 @@ class ProfileUserPageState extends State<ProfileUserPage> {
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
'${provider.currentUser.username}的个人信息',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
backgroundColor: colors.primary,
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
icon: Icon(Icons.arrow_back, color: colors.primary),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -82,8 +82,17 @@ class _RecipeDetailState extends State<RecipeDetailPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('菜谱信息')),
|
||||
appBar: AppBar(
|
||||
title: Text('菜谱信息', style: Theme.of(context).textTheme.titleLarge),
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: colors.primary),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
|
||||
@@ -36,7 +36,7 @@ class _RecordPageState extends State<RecordPage> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
bool _showScrollToTop = false;
|
||||
final List<Widget> _tabPages = [
|
||||
RecipeList(),
|
||||
RecipeList(userId: 0),
|
||||
RecipeCalendar(),
|
||||
RecipeTimeline(),
|
||||
];
|
||||
|
||||
@@ -40,6 +40,7 @@ class _StatsPage extends State<StatsPage> {
|
||||
GlassCard(
|
||||
useOwnLayer: true,
|
||||
settings: LiquidGlassSettings(glassColor: colors.surface),
|
||||
padding: EdgeInsetsGeometry.all(10),
|
||||
child: StatsCard(
|
||||
icon: Icons.restaurant_menu,
|
||||
title: '菜谱总数',
|
||||
@@ -50,6 +51,7 @@ class _StatsPage extends State<StatsPage> {
|
||||
GlassCard(
|
||||
useOwnLayer: true,
|
||||
settings: LiquidGlassSettings(glassColor: colors.surface),
|
||||
padding: EdgeInsetsGeometry.all(10),
|
||||
child: StatsCard(
|
||||
icon: Icons.grid_view_rounded,
|
||||
title: '菜谱类别',
|
||||
@@ -60,6 +62,7 @@ class _StatsPage extends State<StatsPage> {
|
||||
GlassCard(
|
||||
useOwnLayer: true,
|
||||
settings: LiquidGlassSettings(glassColor: colors.surface),
|
||||
padding: EdgeInsetsGeometry.all(10),
|
||||
child: StatsCard(
|
||||
icon: Icons.flag,
|
||||
title: '做菜次数',
|
||||
@@ -70,6 +73,7 @@ class _StatsPage extends State<StatsPage> {
|
||||
GlassCard(
|
||||
useOwnLayer: true,
|
||||
settings: LiquidGlassSettings(glassColor: colors.surface),
|
||||
padding: EdgeInsetsGeometry.all(10),
|
||||
child: StatsCard(
|
||||
icon: Icons.show_chart,
|
||||
title: '平均次数',
|
||||
@@ -116,13 +120,10 @@ class _StatsPage extends State<StatsPage> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: chartHeight,
|
||||
child: GlassCard(
|
||||
useOwnLayer: true,
|
||||
settings: LiquidGlassSettings(glassColor: colors.surface),
|
||||
child: RankChart(title: '排行榜', data: provider.rankStats, unit: '次'),
|
||||
),
|
||||
GlassCard(
|
||||
useOwnLayer: true,
|
||||
settings: LiquidGlassSettings(glassColor: colors.surface),
|
||||
child: RankChart(title: '排行榜', data: provider.rankStats, unit: '次'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ class ProfileInfo extends StatelessWidget {
|
||||
children: [
|
||||
Icon(icon, size: 16, color: colors.primary),
|
||||
const SizedBox(width: 6),
|
||||
Text(text, style: Theme.of(context).textTheme.bodyMedium),
|
||||
Text(text, style: Theme.of(context).textTheme.bodySmall),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ class RecipeCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CommonImage(imageUrls: imageUrls, index: 0),
|
||||
SizedBox(height: 8),
|
||||
InkWell(
|
||||
onTap: () => navigatorToRecipeDetail(context),
|
||||
child: _buildRecipeContent(context),
|
||||
@@ -56,6 +55,11 @@ class RecipeCard extends StatelessWidget {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
_buildIconText(
|
||||
icon: Icons.star,
|
||||
text: recipe.recommendRate.toString(),
|
||||
color: colors.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
@@ -70,7 +74,7 @@ class RecipeCard extends StatelessWidget {
|
||||
const SizedBox(width: 12),
|
||||
_buildIconText(
|
||||
icon: Icons.note_add,
|
||||
text: recipe.recordList.length.toString(),
|
||||
text: '${recipe.recordList.length.toString()}次',
|
||||
color: colors.primary,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -5,7 +5,9 @@ import 'package:food_hub_app/widgets/recipe/card.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class RecipeList extends StatefulWidget {
|
||||
const RecipeList({super.key});
|
||||
final int userId;
|
||||
|
||||
const RecipeList({super.key, required this.userId});
|
||||
|
||||
@override
|
||||
State<RecipeList> createState() => _RecipeListState();
|
||||
@@ -18,8 +20,11 @@ class _RecipeListState extends State<RecipeList> {
|
||||
|
||||
// 初始化加载数据
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<FoodProvider>().refreshRecipeList();
|
||||
context.read<FoodProvider>().queryCategoryList();
|
||||
if (widget.userId == 0) {
|
||||
context.read<FoodProvider>().refreshRecipeList();
|
||||
} else {
|
||||
context.read<FoodProvider>().queryRecipeByUserId(widget.userId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,7 +35,7 @@ class _RecipeListState extends State<RecipeList> {
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisSpacing: 8,
|
||||
childAspectRatio: 0.9,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemCount: provider.recipeSummaryList.length,
|
||||
itemBuilder: (context, index) {
|
||||
|
||||
Reference in New Issue
Block a user