Files
food_hub_app/lib/widgets/moment/card.dart
2026-07-05 20:41:06 +08:00

264 lines
7.4 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: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';
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: [
InkWell(
onTap: () => _onTapUser(context),
child: _buildAvatar(context),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildNickname(context),
const SizedBox(height: 5),
_buildContent(context),
if (widget.moment.imageList.isNotEmpty) ...[
const SizedBox(height: 8),
_buildPostImages(),
],
const SizedBox(height: 10),
_buildTime(context),
const SizedBox(height: 5),
_buildActionButtons(),
if (widget.moment.commentList!.isNotEmpty) ...[
const SizedBox(height: 8),
_buildCommentList(),
],
],
),
),
],
),
);
}
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 (widget.moment.avatar!.isEmpty) {
return CircleAvatar(
radius: 18,
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.surface,
child: Text(widget.moment.username![0], style: TextStyle(fontSize: 14)),
);
} else {
return CircleAvatar(
radius: 18,
backgroundImage: NetworkImage('${AppConfig.imageBaseUrl}/${widget.moment.avatar}')
);
}
}
// 构建昵称组件
Widget _buildNickname(BuildContext context) {
return Text(
widget.moment.username ?? "",
style: Theme.of(context).textTheme.titleMedium,
);
}
// 构建内容组件
Widget _buildContent(BuildContext context) {
return Text(
widget.moment.content,
style: Theme.of(context).textTheme.bodyMedium,
);
}
// 构建朋友圈图片列表(网格布局)
Widget _buildPostImages() {
final imageCount = widget.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 =
widget.moment.imageList.map((path) => path).toList();
return GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: crossAxisCount,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
childAspectRatio: itemAspectRatio,
children: List.generate(imageCount, (index) {
return CommonImage(imageUrls: imageUrls, index: index);
}),
);
}
// 构建时间组件
Widget _buildTime(BuildContext context) {
return Text(
widget.moment.date ?? "",
style: Theme.of(context).textTheme.bodySmall,
);
}
void _onTapEdit() {
final provider = Provider.of<FoodProvider>(context, listen: false);
provider.isEditing = true;
provider.momentFormItem = widget.moment;
Navigator.pushNamed(context, '/momentForm');
}
// 构建点赞和评论按钮
Widget _buildActionButtons() {
return Row(
children: [
if (widget.isUser)
SizedBox(
width: 42,
height: 36,
child: Stack(
alignment: Alignment.bottomLeft,
children: [
InkWell(onTap: () => _onTapEdit(), child: Icon(Icons.edit)),
],
),
),
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: (widget.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: (widget.moment.commentList?.length ?? 0).toString(),
// ),
// ),
],
),
),
],
);
}
Widget _buildCommentItem(Comment comment) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
children: [
TextSpan(
text: comment.username,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
fontFamily: 'CustomFont',
color: Colors.black,
),
),
const TextSpan(text: ': ', style: TextStyle(color: Colors.black)),
TextSpan(
text: comment.content,
style: const TextStyle(
fontSize: 14,
fontFamily: 'CustomFont',
color: Colors.black87,
),
),
],
),
),
],
);
}
Widget _buildCommentList() {
return Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
),
child: ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: widget.moment.commentList!.length,
separatorBuilder: (context, index) => SizedBox(height: 8),
itemBuilder: (context, index) {
return _buildCommentItem(widget.moment.commentList![index]);
},
),
);
}
}