feat: 完成班级模块全量功能迭代
本次提交完成了班级模块的多项核心功能开发与优化: 1. 新增DELETE请求封装,支持业务删除接口且不自动重试 2. 完善UserPostCommonDto模型,新增头像字段适配详情接口 3. 重构路由架构,使用StatefulShellRoute实现Tab页面保活 4. 新增我的互动页面,包含我的动态/点赞/留言三个子页 5. 新增全部同学页面,展示班级全员信息与在线状态 6. 新增动态详情页面,支持查看完整评论与点赞头像 7. 抽离通用PostListBody组件,复用列表分页与交互逻辑 8. 优化班级列表页加载逻辑与图片预览交互 9. 新增评论删除、多图预览等细节交互功能
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:new_learn/core/api/class/model.dart';
|
||||
import 'package:new_learn/core/components/image_preview_viewer.dart';
|
||||
import 'package:new_learn/core/components/user_circle_avatar.dart';
|
||||
import 'package:new_learn/core/utils/img_url.dart';
|
||||
|
||||
@@ -23,12 +24,16 @@ class PostCard extends StatelessWidget {
|
||||
required this.post,
|
||||
required this.onLike,
|
||||
required this.onComment,
|
||||
this.showCommentComposer = true,
|
||||
});
|
||||
|
||||
final UserPostDto post;
|
||||
final VoidCallback onLike;
|
||||
final ValueChanged<String> onComment;
|
||||
|
||||
/// 是否显示卡片内嵌的评论预览 + 输入框(列表页 true;详情页由全量留言接管)
|
||||
final bool showCommentComposer;
|
||||
|
||||
String get _avatar {
|
||||
final url = ImgUrl.build(post.avatar);
|
||||
return url.isEmpty
|
||||
@@ -106,6 +111,7 @@ class PostCard extends StatelessWidget {
|
||||
post: post,
|
||||
onLike: onLike,
|
||||
onComment: onComment,
|
||||
showComposer: showCommentComposer,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -295,11 +301,26 @@ class AlbumGrid extends StatelessWidget {
|
||||
runSpacing: 9.h,
|
||||
children: [
|
||||
for (int i = 0; i < displayed.length; i++)
|
||||
_gridItem(displayed[i], i, urls.length),
|
||||
GestureDetector(
|
||||
onTap: () => _preview(context, urls, i),
|
||||
child: _gridItem(displayed[i], i, urls.length),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 点击相册图:进入整组大图预览,定位到点中的那张
|
||||
void _preview(BuildContext context, List<String> allUrls, int index) {
|
||||
ImagePreviewViewer.show(
|
||||
context,
|
||||
items: [
|
||||
for (final u in allUrls)
|
||||
PreviewImageItem(imageProvider: CachedNetworkImageProvider(u)),
|
||||
],
|
||||
initialIndex: index,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _gridItem(String url, int index, int total) {
|
||||
final more = total > 9 && index == 8 ? total - 9 : 0;
|
||||
return ClipRRect(
|
||||
@@ -344,12 +365,16 @@ class LikeCommentBar extends StatelessWidget {
|
||||
required this.post,
|
||||
required this.onLike,
|
||||
required this.onComment,
|
||||
this.showComposer = true,
|
||||
});
|
||||
|
||||
final UserPostDto post;
|
||||
final VoidCallback onLike;
|
||||
final ValueChanged<String> onComment;
|
||||
|
||||
/// 是否显示评论预览 + 输入框(列表页 true;详情页 false,由全量留言列表接管)
|
||||
final bool showComposer;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
@@ -370,12 +395,14 @@ class LikeCommentBar extends StatelessWidget {
|
||||
MetaButton(icon: Icons.chat_bubble_outline, count: post.replyCount),
|
||||
],
|
||||
),
|
||||
if (post.commons.isNotEmpty) ...[
|
||||
if (showComposer) ...[
|
||||
if (post.commons.isNotEmpty) ...[
|
||||
SizedBox(height: 12.h),
|
||||
CommentPreview(post: post),
|
||||
],
|
||||
SizedBox(height: 12.h),
|
||||
CommentPreview(post: post),
|
||||
CommentInput(onSubmit: onComment),
|
||||
],
|
||||
SizedBox(height: 12.h),
|
||||
CommentInput(onSubmit: onComment),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -517,20 +544,25 @@ class _CommentInputState extends State<CommentInput> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 30.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.w),
|
||||
alignment: Alignment.centerLeft,
|
||||
constraints: BoxConstraints(minHeight: 30.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 5.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(color: const Color(0xFFE3ECFF)),
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
),
|
||||
// multiline:键盘右下角为「换行」,可换行写多条评论
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
style: const TextStyle(fontSize: 12, color: Color(0xFF1D2B47)),
|
||||
keyboardType: TextInputType.multiline,
|
||||
textInputAction: TextInputAction.newline,
|
||||
minLines: 1,
|
||||
maxLines: 4,
|
||||
decoration: const InputDecoration(
|
||||
isDense: true,
|
||||
border: InputBorder.none,
|
||||
|
||||
Reference in New Issue
Block a user