From 8cff5228aecff3492120c6168e062b86521b193e Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Mon, 24 Nov 2025 19:56:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=9B=B4=E6=96=B0=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=B8=BB=E9=A1=B5=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/apis/moment.dart | 7 ++ lib/apis/user.dart | 12 ++ lib/config/app_config.dart | 4 +- lib/layout/app_actions.dart | 75 ++++++------ lib/main.dart | 6 +- lib/models/session.dart | 29 ++++- lib/models/session.g.dart | 2 +- lib/provider/food_provider.dart | 20 ++++ lib/provider/user_provider.dart | 28 +++++ lib/views/home.dart | 2 +- lib/views/login.dart | 5 + lib/views/moment.dart | 2 +- lib/views/moment_form.dart | 4 +- lib/views/moment_user.dart | 64 ++++++++++ lib/views/profile.dart | 200 +++++++++++++++++++++++++++++++- lib/widgets/moment/card.dart | 56 ++++----- pubspec.lock | 4 +- pubspec.yaml | 120 +------------------ 18 files changed, 443 insertions(+), 197 deletions(-) create mode 100644 lib/apis/user.dart create mode 100644 lib/provider/user_provider.dart create mode 100644 lib/views/moment_user.dart diff --git a/lib/apis/moment.dart b/lib/apis/moment.dart index e00e139..d0b072d 100644 --- a/lib/apis/moment.dart +++ b/lib/apis/moment.dart @@ -24,6 +24,13 @@ Future> queryMomentListApi() { ); } +Future> queryMomentListByUserIdApi(int userId) { + return httpUtil.get>( + "/moment/$userId", + converter: (data) => convertList(data, Moment.fromJson), + ); +} + Future queryMomentByPageApi(int currentPage, int pageSize) { return httpUtil.get( "/moment/page", diff --git a/lib/apis/user.dart b/lib/apis/user.dart new file mode 100644 index 0000000..f68950b --- /dev/null +++ b/lib/apis/user.dart @@ -0,0 +1,12 @@ +import 'package:flutter_common/utils/http_utils.dart'; +import 'package:food_hub_app/config/app_config.dart'; +import 'package:food_hub_app/models/session.dart'; + +final httpUtil = HttpUtil(baseUrl: AppConfig.baseApiUrl); + +Future queryUserApi(int number) { + return httpUtil.get( + "/user/$number", + converter: (data) => User.fromJson(data), + ); +} diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 4af06f3..ebe193c 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -5,8 +5,8 @@ class AppConfig { // http://14.103.235.151:81/food-service // static const String baseApiUrl = "http://14.103.235.151:81/food-service"; // static const String baseApiUrl = "http://192.168.1.3:8100"; - // static const String baseApiUrl = "https://cxx0822.iepose.cn/food-api"; - static const String baseApiUrl = "http://192.168.1.4:8083"; + static const String baseApiUrl = "https://cxx0822.iepose.cn/food-api"; + // static const String baseApiUrl = "http://192.168.1.4:8083"; // static const String baseApiUrl = "http://192.168.1.103:8083"; static const String rustfsIp = '14.103.235.151'; static const String rustfsFileUrl = 'http://14.103.235.151:9100'; diff --git a/lib/layout/app_actions.dart b/lib/layout/app_actions.dart index 3efa033..1ae15e1 100644 --- a/lib/layout/app_actions.dart +++ b/lib/layout/app_actions.dart @@ -3,23 +3,15 @@ import 'package:food_hub_app/provider/food_provider.dart'; import 'package:provider/provider.dart'; class AppActions extends StatefulWidget { - const AppActions({super.key}); + final int pageIndex; + + const AppActions({super.key, required this.pageIndex}); @override State createState() => AppActionsState(); } class AppActionsState extends State { - void _buildBottomSheet(FoodProvider provider) { - showModalBottomSheet( - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(16)), - ), - builder: (context) => _buildBottomSheetBody(provider), - ); - } - Widget _buildBottomSheetBody(FoodProvider provider) { final colors = Theme.of(context).colorScheme; final provider = context.watch(); @@ -33,25 +25,44 @@ class AppActionsState extends State { style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 10), - ListTile( - leading: Icon(Icons.book, color: colors.primary), - title: const Text('新增菜谱'), - onTap: () => _handleAddRecipe(provider), - ), - ListTile( - leading: Icon(Icons.note_add, color: colors.primary), - title: const Text('新增记录'), - onTap: () => _handleAddRecord(provider), - ), - ListTile( - leading: Icon(Icons.group, color: colors.primary), - title: const Text('发布朋友圈'), - onTap: () => _handleAddMoment(provider), - ), + if (widget.pageIndex == 0) + ListTile( + leading: Icon(Icons.book, color: colors.primary), + title: const Text('新增菜谱'), + onTap: () => _handleAddRecipe(provider), + ), + if (widget.pageIndex == 0) + ListTile( + leading: Icon(Icons.note_add, color: colors.primary), + title: const Text('新增记录'), + onTap: () => _handleAddRecord(provider), + ), + if (widget.pageIndex == 2) + ListTile( + leading: Icon(Icons.group, color: colors.primary), + title: const Text('发布朋友圈'), + onTap: () => _handleAddMoment(provider), + ), ], ); } + void _onPressAdd(FoodProvider provider) { + if (widget.pageIndex == 0) { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + builder: (context) => _buildBottomSheetBody(provider), + ); + } + + if (widget.pageIndex == 2) { + _handleAddMoment(provider); + } + } + void _handleAddRecipe(FoodProvider provider) { // provider.resetRecordForm(); // Navigator.pop(context); @@ -68,7 +79,6 @@ class AppActionsState extends State { void _handleAddMoment(FoodProvider provider) { provider.resetMomentForm(); provider.isEditing = false; - Navigator.pop(context); Navigator.pushNamed(context, "/momentForm"); } @@ -84,12 +94,11 @@ class AppActionsState extends State { // 搜索功能 }, ), - IconButton( - icon: Icon(Icons.add, color: Colors.white), - onPressed: () { - _buildBottomSheet(provider); - }, - ), + if (widget.pageIndex == 0 || widget.pageIndex == 2) + IconButton( + icon: Icon(Icons.add, color: Colors.white), + onPressed: () => _onPressAdd(provider), + ), ], ); } diff --git a/lib/main.dart b/lib/main.dart index 81207e1..c58ce7d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,10 +3,12 @@ import 'package:flutter_common/provider/theme_provider.dart'; import 'package:flutter_common/utils/sp_utils.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:food_hub_app/provider/food_provider.dart'; +import 'package:food_hub_app/provider/user_provider.dart'; import 'package:food_hub_app/views/home.dart'; import 'package:food_hub_app/views/login.dart'; import 'package:food_hub_app/views/moment.dart'; import 'package:food_hub_app/views/moment_form.dart'; +import 'package:food_hub_app/views/moment_user.dart'; import 'package:food_hub_app/views/record_form.dart'; import 'package:food_hub_app/views/recipe_detail.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; @@ -23,6 +25,7 @@ void main() async { providers: [ ChangeNotifierProvider(create: (context) => FoodProvider()), ChangeNotifierProvider(create: (context) => ThemeProvider()), + ChangeNotifierProvider(create: (context) => UserProvider()), ], child: MyApp(), ), @@ -65,7 +68,8 @@ class MyApp extends StatelessWidget { '/recordForm': (context) => RecordFormPage(), '/recipeDetail': (context) => RecipeDetailPage(), '/momentForm': (context) => MomentFormPage(), - '/moment': (context) => MomentPage() + '/moment': (context) => MomentPage(), + '/momentUser': (context) => MomentUserPage() }, ); } diff --git a/lib/models/session.dart b/lib/models/session.dart index b6f7902..6d5898c 100644 --- a/lib/models/session.dart +++ b/lib/models/session.dart @@ -30,14 +30,16 @@ class SaTokenInfo { this.tag, }); - factory SaTokenInfo.fromJson(Map json) => _$SaTokenInfoFromJson(json); + factory SaTokenInfo.fromJson(Map json) => + _$SaTokenInfoFromJson(json); + Map toJson() => _$SaTokenInfoToJson(this); } @JsonSerializable() class User { int? id; - String? username; + String username; int? gender; String? phoneNumber; String? email; @@ -51,7 +53,7 @@ class User { User({ this.id, - this.username, + required this.username, this.gender, this.phoneNumber, this.email, @@ -65,7 +67,24 @@ class User { }); factory User.fromJson(Map json) => _$UserFromJson(json); + Map toJson() => _$UserToJson(this); + + static User getEmpty() { + return User( + username: '', + gender: 0, + phoneNumber: '', + email: '', + birthDate: null, + avatar: '', + area: [], + address: '', + job: '', + tags: [], + description: '', + ); + } } @JsonSerializable() @@ -75,6 +94,8 @@ class Session { Session({required this.saToken, required this.userInfo}); - factory Session.fromJson(Map json) => _$SessionFromJson(json); + factory Session.fromJson(Map json) => + _$SessionFromJson(json); + Map toJson() => _$SessionToJson(this); } diff --git a/lib/models/session.g.dart b/lib/models/session.g.dart index 554fa27..ac7b72d 100644 --- a/lib/models/session.g.dart +++ b/lib/models/session.g.dart @@ -37,7 +37,7 @@ Map _$SaTokenInfoToJson(SaTokenInfo instance) => User _$UserFromJson(Map json) => User( id: (json['id'] as num?)?.toInt(), - username: json['username'] as String?, + username: json['username'] as String, gender: (json['gender'] as num?)?.toInt(), phoneNumber: json['phoneNumber'] as String?, email: json['email'] as String?, diff --git a/lib/provider/food_provider.dart b/lib/provider/food_provider.dart index f7f2b43..94fbd27 100644 --- a/lib/provider/food_provider.dart +++ b/lib/provider/food_provider.dart @@ -306,6 +306,26 @@ class FoodProvider with ChangeNotifier { } } + Future queryMomentByUserId(int userId) async { + if (isLoading) return; + + try { + isLoading = true; + error = null; + notifyListeners(); + + final result = await queryMomentListByUserIdApi(userId); + momentList = result; + notifyListeners(); + } catch (e) { + error = '加载数据失败: $e'; + debugPrint('加载数据失败: $e'); + } finally { + isLoading = false; + notifyListeners(); + } + } + Future loadMoreMomentList() async { if (hasMore && !isLoading) { await queryMomentByPage(isRefresh: false); diff --git a/lib/provider/user_provider.dart b/lib/provider/user_provider.dart new file mode 100644 index 0000000..9529aa8 --- /dev/null +++ b/lib/provider/user_provider.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:food_hub_app/apis/user.dart'; +import 'package:food_hub_app/models/session.dart'; + +class UserProvider with ChangeNotifier { + late User currentUser = User.getEmpty(); + bool isLoading = false; + String error = ''; + + Future refreshUser(int id) async { + if (isLoading) return; + + try { + isLoading = true; + error = ''; + notifyListeners(); + + final result = await queryUserApi(id); + currentUser = result; + } catch (e) { + error = '加载数据失败: $e'; + debugPrint('加载数据失败: $e'); + } finally { + isLoading = false; + notifyListeners(); + } + } +} diff --git a/lib/views/home.dart b/lib/views/home.dart index a2f7bd9..5ecbcc6 100644 --- a/lib/views/home.dart +++ b/lib/views/home.dart @@ -30,7 +30,7 @@ class _HomePage extends State { ); }, ), - actions: [AppActions()], + actions: [AppActions(pageIndex: _currentIndex)], ), // backgroundColor: Color(0xFFF5F5F5), drawer: AppDrawer(), diff --git a/lib/views/login.dart b/lib/views/login.dart index 21334cc..fc6b2c4 100644 --- a/lib/views/login.dart +++ b/lib/views/login.dart @@ -63,6 +63,10 @@ class _LoginPage extends State { SPUtil.set('token', token); } + void handleUserInfo(User user) { + SPUtil.set('userId', user.id); + } + void loginClick() async { setState(() { _isLoading = true; @@ -78,6 +82,7 @@ class _LoginPage extends State { ToastUtil.success('登录成功'); handleRememberState(); handleTokenState(session.saToken.tokenValue); + handleUserInfo(session.userInfo); LoadingDialog.hide(context); Navigator.pushNamed(context, '/home'); diff --git a/lib/views/moment.dart b/lib/views/moment.dart index fb5e307..6e48a39 100644 --- a/lib/views/moment.dart +++ b/lib/views/moment.dart @@ -84,7 +84,7 @@ class _MomentPageState extends State { itemCount: provider.momentList.length, separatorBuilder: (context, index) => SizedBox(height: 8), itemBuilder: (context, index) { - return MomentCard(moment: provider.momentList[index]); + return MomentCard(moment: provider.momentList[index], isUser: false); }, ); } diff --git a/lib/views/moment_form.dart b/lib/views/moment_form.dart index 562b227..5e14117 100644 --- a/lib/views/moment_form.dart +++ b/lib/views/moment_form.dart @@ -32,6 +32,7 @@ class _MomentFormPageState extends State { return FormBuilderTextField( name: _contentField, + initialValue: provider.momentFormItem.content, focusNode: _focusNode, maxLines: 5, minLines: 3, @@ -110,7 +111,7 @@ class _MomentFormPageState extends State { _buildContentField(provider), const SizedBox(height: 8), - buildFormLabel(context: context, text: '上传图片', isRequired: false), + buildFormLabel(context: context, text: '上传图片(最多9张)', isRequired: false), const SizedBox(height: 8), _buildImageField(provider), const SizedBox(height: 8), @@ -218,7 +219,6 @@ class _MomentFormPageState extends State { onPressed: () => Navigator.pop(context), ), ), - backgroundColor: const Color(0xFFF5F5F5), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(10), diff --git a/lib/views/moment_user.dart b/lib/views/moment_user.dart new file mode 100644 index 0000000..e5da6f8 --- /dev/null +++ b/lib/views/moment_user.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_common/utils/sp_utils.dart'; +import 'package:flutter_common/widget/common_widget.dart'; +import 'package:food_hub_app/provider/food_provider.dart'; +import 'package:food_hub_app/widgets/moment/card.dart'; +import 'package:provider/provider.dart'; + +class MomentUserPage extends StatefulWidget { + const MomentUserPage({super.key}); + + @override + State createState() => _MomentUserPageState(); +} + +class _MomentUserPageState extends State { + @override + void initState() { + super.initState(); + + // 初始化加载数据 + WidgetsBinding.instance.addPostFrameCallback((_) { + context.read().queryMomentByUserId(SPUtil.getInt('userId')); + }); + } + + Widget _buildMomentList(FoodProvider provider) { + return ListView.separated( + itemCount: provider.momentList.length, + separatorBuilder: (context, index) => SizedBox(height: 8), + itemBuilder: (context, index) { + return MomentCard(moment: provider.momentList[index], isUser: true); + }, + ); + } + + @override + Widget build(BuildContext context) { + final provider = context.watch(); + + // 空状态显示 + if (provider.momentList.isEmpty) { + return buildEmptyData(); + } + + return Scaffold( + appBar: AppBar( + title: Text('我的朋友圈', style: const TextStyle(color: Colors.white)), + backgroundColor: Theme.of(context).colorScheme.primary, + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.white), + onPressed: () => Navigator.pop(context), + ), + ), + backgroundColor: const Color(0xFFF5F5F5), + body: + provider.isLoading + ? buildLoadingIndicator() + : Padding( + padding: const EdgeInsets.all(10), + child: CommonCard(child: _buildMomentList(provider)), + ), + ); + } +} diff --git a/lib/views/profile.dart b/lib/views/profile.dart index a011369..83c8798 100644 --- a/lib/views/profile.dart +++ b/lib/views/profile.dart @@ -1,15 +1,209 @@ import 'package:flutter/material.dart'; +import 'package:flutter_common/utils/date_utils.dart'; +import 'package:flutter_common/utils/sp_utils.dart'; +import 'package:flutter_common/widget/common_widget.dart'; +import 'package:flutter_common/widget/dialog_widget.dart'; +import 'package:food_hub_app/config/app_config.dart'; +import 'package:food_hub_app/models/session.dart'; +import 'package:food_hub_app/provider/user_provider.dart'; +import 'package:food_hub_app/widgets/common/index.dart'; +import 'package:provider/provider.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; class ProfilePage extends StatefulWidget { const ProfilePage({super.key}); @override - State createState() => _ProfilePage(); + State createState() => ProfilePageState(); } -class _ProfilePage extends State{ +class ProfilePageState extends State { + @override + void initState() { + super.initState(); + + // 初始化加载数据 + WidgetsBinding.instance.addPostFrameCallback((_) { + context.read().refreshUser(SPUtil.getInt('userId')); + }); + } + + Widget _buildAvatar(User user) { + if (user.avatar!.isEmpty) { + return TDAvatar( + size: TDAvatarSize.large, + type: TDAvatarType.customText, + shape: TDAvatarShape.circle, + backgroundColor: Theme.of(context).colorScheme.primary, + text: user.username.isNotEmpty ? user.username[0] : '?', + ); + } else { + return TDAvatar( + size: TDAvatarSize.large, + type: TDAvatarType.normal, + fit: BoxFit.contain, + avatarUrl: '${AppConfig.imageBaseUrl}/${user.avatar}', + ); + } + } + + Widget _buildInfoItem({required IconData icon, required String text}) { + final colors = Theme.of(context).colorScheme; + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 16, color: colors.primary), + const SizedBox(width: 6), + Text(text), + ], + ); + } + + Widget _buildFunctionButton({ + required IconData icon, + required String text, + required VoidCallback onTap, + }) { + final colors = Theme.of(context).colorScheme; + return ListTile( + contentPadding: EdgeInsets.zero, + leading: Icon(icon, color: colors.primary), + title: Text(text), + trailing: Icon(Icons.arrow_forward_ios, size: 16, color: colors.primary), + onTap: onTap, + ); + } + + Widget _buildBasicInfo(User user) { + return CommonCard( + child: Column( + children: [ + _buildAvatar(user), + const SizedBox(height: 8), + Text( + user.username, + style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + if (user.tags != null && user.tags!.isNotEmpty) + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: + user.tags!.map((tag) => buildTag(context, tag)).toList(), + ), + if (user.tags != null && user.tags!.isNotEmpty) + const SizedBox(height: 8), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + if (user.area != null && user.area!.length >= 2) + _buildInfoItem( + icon: Icons.location_on, + text: '${user.area![0]}-${user.area![1]}', + ), + if (user.birthDate != null) + _buildInfoItem( + icon: Icons.cake, + text: formatDate(user.birthDate!), + ), + if (user.job != null && user.job!.isNotEmpty) + _buildInfoItem(icon: Icons.work, text: user.job!), + if (user.phoneNumber != null && user.phoneNumber!.isNotEmpty) + _buildInfoItem( + icon: Icons.phone_android, + text: user.phoneNumber!, + ), + if (user.email != null && user.email!.isNotEmpty) + _buildInfoItem(icon: Icons.email, text: user.email!), + ], + ), + if (user.description != null && user.description!.isNotEmpty) + const SizedBox(height: 8), + if (user.description != null && user.description!.isNotEmpty) + Text(user.description!), + ], + ), + ); + } + + void _onTapMoment() { + Navigator.pushNamed(context, '/momentUser'); + } + + Widget _buildFunctionButtons() { + return CommonCard( + child: Column( + children: [ + _buildFunctionButton( + icon: Icons.account_circle, + text: '基本资料', + onTap: () { + // 跳转到编辑资料页面 + // LogUtils.i('点击编辑资料'); + }, + ), + const Divider(height: 1), + _buildFunctionButton( + icon: Icons.group_outlined, + text: '朋友圈', + onTap: _onTapMoment, + ), + const Divider(height: 1), + _buildFunctionButton( + icon: Icons.favorite, + text: '我的收藏', + onTap: () { + // 跳转到浏览历史页面 + // LogUtils.i('点击浏览历史'); + }, + ), + const Divider(height: 1), + _buildFunctionButton( + icon: Icons.lock, + text: '更改密码', + onTap: () { + // 跳转到帮助与反馈页面 + // LogUtils.i('点击帮助与反馈'); + }, + ), + const Divider(height: 1), + _buildFunctionButton( + icon: Icons.exit_to_app, + text: '退出登录', + onTap: () { + showConfirmDialog(context, '确认要退出吗?'); + }, + ), + ], + ), + ); + } + + Widget _buildContent(UserProvider provider) { + final user = provider.currentUser; + return Column( + children: [ + SizedBox(width: double.infinity, child: _buildBasicInfo(user)), + const SizedBox(height: 16), + _buildFunctionButtons(), + ], + ); + } + @override Widget build(BuildContext context) { - return const Center(child: Text("个人主页")); + final provider = context.watch(); + + return Stack( + children: [ + if (provider.isLoading) + buildLoadingIndicator() + else if (provider.error.isNotEmpty) + Text(provider.error) + else + _buildContent(provider), + ], + ); } } diff --git a/lib/widgets/moment/card.dart b/lib/widgets/moment/card.dart index 061906f..e2188f4 100644 --- a/lib/widgets/moment/card.dart +++ b/lib/widgets/moment/card.dart @@ -2,13 +2,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_common/widget/common_widget.dart'; import 'package:food_hub_app/config/app_config.dart'; import 'package:food_hub_app/models/moment.dart'; +import 'package:food_hub_app/provider/food_provider.dart'; import 'package:food_hub_app/widgets/common/image.dart'; +import 'package:provider/provider.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; class MomentCard extends StatelessWidget { final Moment moment; + final bool isUser; - const MomentCard({super.key, required this.moment}); + const MomentCard({super.key, required this.moment, required this.isUser}); @override Widget build(BuildContext context) { @@ -32,7 +35,7 @@ class MomentCard extends StatelessWidget { const SizedBox(height: 10), _buildTime(), const SizedBox(height: 5), - _buildActionButtons(), + _buildActionButtons(context), if (moment.commentList!.isNotEmpty) ...[ const SizedBox(height: 8), _buildCommentList(), @@ -52,7 +55,7 @@ class MomentCard extends StatelessWidget { size: TDAvatarSize.medium, type: TDAvatarType.customText, shape: TDAvatarShape.circle, - backgroundColor: Theme.of(context).primaryColor, + backgroundColor: Theme.of(context).colorScheme.primary, text: moment.username?[0], ); } else { @@ -126,10 +129,31 @@ class MomentCard extends StatelessWidget { ); } + void _onTapEdit(BuildContext context) { + final provider = Provider.of(context, listen: false); + provider.isEditing = true; + provider.momentFormItem = moment; + Navigator.pushNamed(context, '/momentForm'); + } + // 构建点赞和评论按钮 - Widget _buildActionButtons() { + Widget _buildActionButtons(BuildContext context) { return Row( children: [ + if (isUser) + SizedBox( + width: 42, + height: 36, + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + InkWell( + onTap: () => _onTapEdit(context), + child: Icon(Icons.edit), + ), + ], + ), + ), SizedBox( width: 42, height: 36, @@ -166,30 +190,6 @@ class MomentCard extends StatelessWidget { ], ), ), - // _buildActionButton( - // icon: Icons.thumb_up_alt_outlined, - // count: moment.likeList?.length ?? 0, - // ), - // const SizedBox(width: 20), - // _buildActionButton( - // icon: Icons.comment_outlined, - // count: moment.commentList?.length ?? 0, - // ), - ], - ); - } - - // 构建带数字标记的动作按钮 - Widget _buildActionButton({required IconData icon, required int count}) { - return Row( - children: [ - Icon(icon, color: Colors.grey[500], size: 18), - const SizedBox(width: 4), - if (count > 0) - Text( - count.toString(), - style: TextStyle(fontSize: 12, color: Colors.grey[500]), - ), ], ); } diff --git a/pubspec.lock b/pubspec.lock index b4cfedb..3abd521 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -321,8 +321,8 @@ packages: flutter_common: dependency: "direct main" description: - path: "D:\\Projects\\FlutterProjects\\flutter_common" - relative: false + path: "../flutter_common" + relative: true source: path version: "1.0.0+1" flutter_form_builder: diff --git a/pubspec.yaml b/pubspec.yaml index b923477..dafbf41 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,119 +1 @@ -name: food_hub_app -description: "A new Flutter project." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+1 - -environment: - sdk: ^3.7.0 - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - flutter_localizations: - sdk: flutter - # The following adds the Cupertino Icons fonts to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 - provider: ^6.1.1 - timelines_plus: ^1.0.7 - table_calendar: ^3.1.3 - toggle_switch: ^2.3.0 - flutter_form_builder: ^10.0.0 - form_builder_validators: ^11.1.2 - intl: ^0.19.0 - tdesign_flutter: ^0.2.3 - json_annotation: ^4.9.0 - logger: ^2.6.0 - photo_view: ^0.15.0 - flutter_carousel_widget: ^3.1.0 - easy_refresh: ^3.4.0 - file_picker: ^10.3.3 - share_plus: ^11.0.0 - path_provider: ^2.1.5 - flutter_common: - path: ..\flutter_common - -dependency_overrides: - tdesign_flutter_adaptation: 3.16.0 - image_picker: 1.0.8 - -dev_dependencies: - flutter_test: - sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^5.0.0 - # flutter pub run build_runner build - build_runner: ^2.4.5 - json_serializable: ^6.7.1 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - - # The following line ensures that the Material Icons fonts is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the fonts family name, and a "fonts" key with a - # list giving the asset and other descriptors for the fonts. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package - fonts: - - family: CustomFont - fonts: - - asset: fonts/custom.ttf +name: food_hub_app description: "A new Flutter project." # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +. # Both the version and the builder number may be overridden in flutter # build by specifying --build-name and --build-number, respectively. # In Android, build-name is used as versionName while build-number used as versionCode. # Read more about Android versioning at https://developer.android.com/studio/publish/versioning # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. version: 1.0.0+1 environment: sdk: ^3.7.0 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions # consider running `flutter pub upgrade --major-versions`. Alternatively, # dependencies can be manually updated by changing the version numbers below to # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter # The following adds the Cupertino Icons fonts to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 provider: ^6.1.1 timelines_plus: ^1.0.7 table_calendar: ^3.1.3 toggle_switch: ^2.3.0 flutter_form_builder: ^10.0.0 form_builder_validators: ^11.1.2 intl: ^0.19.0 tdesign_flutter: ^0.2.3 json_annotation: ^4.9.0 logger: ^2.6.0 photo_view: ^0.15.0 flutter_carousel_widget: ^3.1.0 easy_refresh: ^3.4.0 file_picker: ^10.3.3 share_plus: ^11.0.0 path_provider: ^2.1.5 flutter_common: path: ..\flutter_common dependency_overrides: tdesign_flutter_adaptation: 3.16.0 image_picker: 1.0.8 dev_dependencies: flutter_test: sdk: flutter # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. flutter_lints: ^5.0.0 # flutter pub run build_runner build build_runner: ^2.4.5 json_serializable: ^6.7.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec # The following section is specific to Flutter packages. flutter: # The following line ensures that the Material Icons fonts is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/to/resolution-aware-images # For details regarding adding assets from package dependencies, see # https://flutter.dev/to/asset-from-package # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the fonts family name, and a "fonts" key with a # list giving the asset and other descriptors for the fonts. For # example: # fonts: # - family: Schyler # fonts: # - asset: fonts/Schyler-Regular.ttf # - asset: fonts/Schyler-Italic.ttf # style: italic # - family: Trajan Pro # fonts: # - asset: fonts/TrajanPro.ttf # - asset: fonts/TrajanPro_Bold.ttf # weight: 700 # # For details regarding fonts from package dependencies, # see https://flutter.dev/to/font-from-package fonts: - family: CustomFont fonts: - asset: fonts/custom.ttf \ No newline at end of file