Files
food_hub_app/lib/widgets/moment/card.dart
2025-07-23 20:03:03 +08:00

217 lines
5.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:food_hub_app/config/app_config.dart';
import 'package:food_hub_app/models/moment.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';
class MomentCard extends StatelessWidget {
final Moment moment;
const MomentCard({super.key, required this.moment});
@override
Widget build(BuildContext context) {
return Card(
elevation: 0,
color: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
child: Padding(
padding: const EdgeInsets.all(10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildAvatar(),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildNickname(),
const SizedBox(height: 5),
_buildContent(),
if (moment.imageList.isNotEmpty) ...[
const SizedBox(height: 8),
_buildPostImages(),
],
const SizedBox(height: 10),
_buildTime(),
const SizedBox(height: 5),
_buildActionButtons(),
],
),
),
],
),
),
);
}
// 构建头像组件
Widget _buildAvatar() {
return TDAvatar(
size: TDAvatarSize.medium,
type: TDAvatarType.normal,
fit: BoxFit.contain,
avatarUrl: '${AppConfig.baseApiUrl}/${moment.avatar}');
// return SizedBox(
// width: 40,
// height: 40,
// child: ClipRRect(
// borderRadius: BorderRadius.circular(25),
// child: Image.network(
// '${AppConfig.baseApiUrl}/${moment.avatar}',
// fit: BoxFit.contain,
// errorBuilder: (context, error, stackTrace) {
// return Container(
// color: Colors.grey[200],
// child: const Icon(Icons.person, color: Colors.grey),
// );
// },
// ),
// ),
// );
}
// 构建昵称组件
Widget _buildNickname() {
return Text(
moment.username ?? "",
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
);
}
// 构建内容组件
Widget _buildContent() {
return Text(
moment.content,
style: const TextStyle(fontSize: 15, color: Colors.black87, height: 1.3),
);
}
// 构建朋友圈图片列表(网格布局)
Widget _buildPostImages() {
// 图片数量
final imageCount = moment.imageList.length;
// 计算网格布局
int crossAxisCount;
if (imageCount == 1) {
crossAxisCount = 1; // 单张图片
} else if (imageCount == 2 || imageCount == 4) {
crossAxisCount = 2; // 2张或4张图片用2列
} else {
crossAxisCount = 3; // 其他数量用3列
}
// 计算图片尺寸
double itemAspectRatio = 1.0; // 默认正方形
if (imageCount == 1) {
// 单张图片使用宽屏比例
itemAspectRatio = 1.5;
}
return GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: crossAxisCount,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
childAspectRatio: itemAspectRatio,
children: List.generate(imageCount, (index) {
return ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
'${AppConfig.baseApiUrl}/${moment.imageList[index]}',
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Container(
color: Colors.grey[200],
child: const Icon(Icons.image, color: Colors.grey, size: 30),
);
},
),
);
}),
);
}
// 构建时间组件
Widget _buildTime() {
return Text(
moment.date ?? "",
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
);
}
// 构建点赞和评论按钮
Widget _buildActionButtons() {
return Row(
children: [
SizedBox(
width: 42,
height: 36,
child: Stack(
alignment: Alignment.bottomLeft,
children: [
Icon(Icons.thumb_up_alt_outlined),
Positioned(
left: 20,
bottom: 15,
child: TDBadge(
TDBadgeType.message,
count: (moment.likeList?.length ?? 0).toString(),
),
),
],
),
),
SizedBox(
width: 42,
height: 36,
child: Stack(
alignment: Alignment.bottomLeft,
children: [
Icon(Icons.comment_outlined),
Positioned(
left: 20,
bottom: 15,
child: TDBadge(
TDBadgeType.message,
count: (moment.commentList?.length ?? 0).toString(),
),
),
],
),
),
// _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]),
),
],
);
}
}