feat:增加查询朋友朋友圈功能
This commit is contained in:
@@ -1,25 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_common/flutter_common.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/provider/user_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 {
|
||||
class MomentCard extends StatefulWidget {
|
||||
final Moment moment;
|
||||
final bool isUser;
|
||||
|
||||
const MomentCard({super.key, required this.moment, required this.isUser});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => MomentCardState();
|
||||
}
|
||||
|
||||
class MomentCardState extends State<MomentCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonCard(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildAvatar(context),
|
||||
InkWell(onTap: () => _onTapUser(context), child: _buildAvatar()),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
@@ -28,15 +35,15 @@ class MomentCard extends StatelessWidget {
|
||||
_buildNickname(),
|
||||
const SizedBox(height: 5),
|
||||
_buildContent(),
|
||||
if (moment.imageList.isNotEmpty) ...[
|
||||
if (widget.moment.imageList.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
_buildPostImages(context),
|
||||
_buildPostImages(),
|
||||
],
|
||||
const SizedBox(height: 10),
|
||||
_buildTime(),
|
||||
const SizedBox(height: 5),
|
||||
_buildActionButtons(context),
|
||||
if (moment.commentList!.isNotEmpty) ...[
|
||||
_buildActionButtons(),
|
||||
if (widget.moment.commentList!.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
_buildCommentList(),
|
||||
],
|
||||
@@ -48,22 +55,35 @@ class MomentCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void _onTapUser(BuildContext context) async {
|
||||
final provider = context.read<UserProvider>();
|
||||
|
||||
if (widget.moment.userId != SPUtil.getInt('userId')) {
|
||||
await provider.refreshUser(widget.moment.userId!);
|
||||
await provider.queryMomentByUserId(widget.moment.userId!);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.pushNamed(context, '/ProfileUser');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构建头像组件
|
||||
Widget _buildAvatar(BuildContext context) {
|
||||
if (moment.avatar!.isEmpty) {
|
||||
Widget _buildAvatar() {
|
||||
if (widget.moment.avatar!.isEmpty) {
|
||||
return TDAvatar(
|
||||
size: TDAvatarSize.medium,
|
||||
type: TDAvatarType.customText,
|
||||
shape: TDAvatarShape.circle,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
text: moment.username?[0],
|
||||
text: widget.moment.username?[0],
|
||||
);
|
||||
} else {
|
||||
return TDAvatar(
|
||||
size: TDAvatarSize.medium,
|
||||
type: TDAvatarType.normal,
|
||||
fit: BoxFit.contain,
|
||||
avatarUrl: '${AppConfig.imageBaseUrl}/${moment.avatar}',
|
||||
avatarUrl: '${AppConfig.imageBaseUrl}/${widget.moment.avatar}',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -71,7 +91,7 @@ class MomentCard extends StatelessWidget {
|
||||
// 构建昵称组件
|
||||
Widget _buildNickname() {
|
||||
return Text(
|
||||
moment.username ?? "",
|
||||
widget.moment.username ?? "",
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||
);
|
||||
}
|
||||
@@ -79,14 +99,14 @@ class MomentCard extends StatelessWidget {
|
||||
// 构建内容组件
|
||||
Widget _buildContent() {
|
||||
return Text(
|
||||
moment.content,
|
||||
widget.moment.content,
|
||||
style: const TextStyle(fontSize: 15, height: 1.3),
|
||||
);
|
||||
}
|
||||
|
||||
// 构建朋友圈图片列表(网格布局)
|
||||
Widget _buildPostImages(BuildContext context) {
|
||||
final imageCount = moment.imageList.length;
|
||||
Widget _buildPostImages() {
|
||||
final imageCount = widget.moment.imageList.length;
|
||||
|
||||
// 计算网格列数
|
||||
int crossAxisCount;
|
||||
@@ -106,7 +126,7 @@ class MomentCard extends StatelessWidget {
|
||||
|
||||
// 生成图片URL列表(用于预览时切换)
|
||||
final List<String> imageUrls =
|
||||
moment.imageList.map((path) => path).toList();
|
||||
widget.moment.imageList.map((path) => path).toList();
|
||||
|
||||
return GridView.count(
|
||||
shrinkWrap: true,
|
||||
@@ -124,33 +144,30 @@ class MomentCard extends StatelessWidget {
|
||||
// 构建时间组件
|
||||
Widget _buildTime() {
|
||||
return Text(
|
||||
moment.date ?? "",
|
||||
widget.moment.date ?? "",
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
|
||||
);
|
||||
}
|
||||
|
||||
void _onTapEdit(BuildContext context) {
|
||||
void _onTapEdit() {
|
||||
final provider = Provider.of<FoodProvider>(context, listen: false);
|
||||
provider.isEditing = true;
|
||||
provider.momentFormItem = moment;
|
||||
provider.momentFormItem = widget.moment;
|
||||
Navigator.pushNamed(context, '/momentForm');
|
||||
}
|
||||
|
||||
// 构建点赞和评论按钮
|
||||
Widget _buildActionButtons(BuildContext context) {
|
||||
Widget _buildActionButtons() {
|
||||
return Row(
|
||||
children: [
|
||||
if (isUser)
|
||||
if (widget.isUser)
|
||||
SizedBox(
|
||||
width: 42,
|
||||
height: 36,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomLeft,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () => _onTapEdit(context),
|
||||
child: Icon(Icons.edit),
|
||||
),
|
||||
InkWell(onTap: () => _onTapEdit(), child: Icon(Icons.edit)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -166,7 +183,7 @@ class MomentCard extends StatelessWidget {
|
||||
bottom: 15,
|
||||
child: TDBadge(
|
||||
TDBadgeType.message,
|
||||
count: (moment.likeList?.length ?? 0).toString(),
|
||||
count: (widget.moment.likeList?.length ?? 0).toString(),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -184,7 +201,7 @@ class MomentCard extends StatelessWidget {
|
||||
bottom: 15,
|
||||
child: TDBadge(
|
||||
TDBadgeType.message,
|
||||
count: (moment.commentList?.length ?? 0).toString(),
|
||||
count: (widget.moment.commentList?.length ?? 0).toString(),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -236,10 +253,10 @@ class MomentCard extends StatelessWidget {
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: moment.commentList!.length,
|
||||
itemCount: widget.moment.commentList!.length,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8),
|
||||
itemBuilder: (context, index) {
|
||||
return _buildCommentItem(moment.commentList![index]);
|
||||
return _buildCommentItem(widget.moment.commentList![index]);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
21
lib/widgets/moment/list.dart
Normal file
21
lib/widgets/moment/list.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:food_hub_app/models/moment.dart';
|
||||
import 'package:food_hub_app/widgets/moment/card.dart';
|
||||
|
||||
class MomentList extends StatelessWidget {
|
||||
final List<Moment> momentList;
|
||||
final bool isUser;
|
||||
|
||||
const MomentList({super.key, required this.momentList, required this.isUser});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.separated(
|
||||
itemCount: momentList.length,
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8),
|
||||
itemBuilder: (context, index) {
|
||||
return MomentCard(moment: momentList[index], isUser: isUser);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
113
lib/widgets/profile/basic_info.dart
Normal file
113
lib/widgets/profile/basic_info.dart
Normal file
@@ -0,0 +1,113 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_common/utils/date_utils.dart';
|
||||
import 'package:flutter_common/widget/common_widget.dart';
|
||||
import 'package:food_hub_app/config/app_config.dart';
|
||||
import 'package:food_hub_app/models/session.dart';
|
||||
import 'package:food_hub_app/widgets/common/index.dart';
|
||||
import 'package:tdesign_flutter/tdesign_flutter.dart';
|
||||
|
||||
class ProfileInfo extends StatelessWidget {
|
||||
final User user;
|
||||
|
||||
const ProfileInfo({super.key, required this.user});
|
||||
|
||||
Widget _buildAvatar(BuildContext context, User user) {
|
||||
if (user.avatar == null) {
|
||||
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 BuildContext context,
|
||||
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),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonCard(
|
||||
child: Column(
|
||||
children: [
|
||||
_buildAvatar(context, 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(
|
||||
context: context,
|
||||
icon: Icons.location_on,
|
||||
text: '${user.area![0]}-${user.area![1]}',
|
||||
),
|
||||
if (user.birthDate != null)
|
||||
_buildInfoItem(
|
||||
context: context,
|
||||
icon: Icons.cake,
|
||||
text: formatDate(user.birthDate!),
|
||||
),
|
||||
if (user.job != null && user.job!.isNotEmpty)
|
||||
_buildInfoItem(
|
||||
context: context,
|
||||
icon: Icons.work,
|
||||
text: user.job!,
|
||||
),
|
||||
if (user.phoneNumber != null && user.phoneNumber!.isNotEmpty)
|
||||
_buildInfoItem(
|
||||
context: context,
|
||||
icon: Icons.phone_android,
|
||||
text: user.phoneNumber!,
|
||||
),
|
||||
if (user.email != null && user.email!.isNotEmpty)
|
||||
_buildInfoItem(
|
||||
context: context,
|
||||
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!),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user