Files
food_hub_app/lib/widgets/moment/card.dart
2025-11-19 16:35:20 +08:00

211 lines
5.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:food_hub_app/config/app_config.dart';
import 'package:food_hub_app/models/moment.dart';
import 'package:food_hub_app/widgets/common/image.dart';
import 'package:food_hub_app/widgets/common/index.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 buildCard(
context: context,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildAvatar(context),
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(context),
],
const SizedBox(height: 10),
_buildTime(),
const SizedBox(height: 5),
_buildActionButtons(),
],
),
),
],
),
);
}
// 构建头像组件
Widget _buildAvatar(BuildContext context) {
if (moment.avatar!.isEmpty) {
return TDAvatar(
size: TDAvatarSize.medium,
type: TDAvatarType.customText,
shape: TDAvatarShape.circle,
backgroundColor: Theme.of(context).primaryColor,
text: moment.username?[0],
);
} else {
return TDAvatar(
size: TDAvatarSize.medium,
type: TDAvatarType.normal,
fit: BoxFit.contain,
avatarUrl: '${AppConfig.imageBaseUrl}/${moment.avatar}',
);
}
}
// 构建昵称组件
Widget _buildNickname() {
return Text(
moment.username ?? "",
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
);
}
// 构建内容组件
Widget _buildContent() {
return Text(
moment.content,
style: const TextStyle(fontSize: 15, height: 1.3),
);
}
// 构建朋友圈图片列表(网格布局)
Widget _buildPostImages(BuildContext context) {
final imageCount = moment.imageList.length;
// 计算网格列数
int crossAxisCount;
if (imageCount == 1) {
crossAxisCount = 1;
} else if (imageCount == 2 || imageCount == 4) {
crossAxisCount = 2;
} else {
crossAxisCount = 3;
}
// 计算宽高比
double itemAspectRatio = 1.0;
if (imageCount == 1) {
itemAspectRatio = 1.5;
}
// 生成图片URL列表用于预览时切换
final List<String> imageUrls =
moment.imageList.map((path) => path).toList();
void imageTapClick(int index) {
Navigator.push(
context,
MaterialPageRoute(
builder:
(context) =>
ImagePreviewPage(images: imageUrls, initialIndex: index),
),
);
}
return GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: crossAxisCount,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
childAspectRatio: itemAspectRatio,
children: List.generate(imageCount, (index) {
// 单个图片项:添加点击事件
return GestureDetector(
// 点击图片时,跳转到预览页面
onTap: () => imageTapClick(index),
// 原图片组件
child: buildNetworkImage(context, imageUrls[index]),
);
}),
);
}
// 构建时间组件
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]),
),
],
);
}
}