Files
App.K12.Student.Miniapp_Flu…/lib/features/class/my_interact_page.dart
T
崔宝新 586c75f841 feat: 完成班级模块全量功能迭代
本次提交完成了班级模块的多项核心功能开发与优化:
1. 新增DELETE请求封装,支持业务删除接口且不自动重试
2. 完善UserPostCommonDto模型,新增头像字段适配详情接口
3. 重构路由架构,使用StatefulShellRoute实现Tab页面保活
4. 新增我的互动页面,包含我的动态/点赞/留言三个子页
5. 新增全部同学页面,展示班级全员信息与在线状态
6. 新增动态详情页面,支持查看完整评论与点赞头像
7. 抽离通用PostListBody组件,复用列表分页与交互逻辑
8. 优化班级列表页加载逻辑与图片预览交互
9. 新增评论删除、多图预览等细节交互功能
2026-09-07 09:20:06 +08:00

180 lines
5.3 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_screenutil/flutter_screenutil.dart';
import 'package:go_router/go_router.dart';
import 'package:new_learn/core/api/class/api.dart';
import 'package:new_learn/core/api/class/model.dart';
import 'package:new_learn/features/class/widgets/post_list_body.dart';
/// ============================================================
/// 【MyInteractPage】「我的互动」页 —— 对标 Vue pages/classPackage/myInteract/myInteract.vue
///
/// 一、入口:从「我的」页等进入。
/// 二、结构:NavBar("我的互动") + 3 颗胶囊 tab + 内容区
/// 「我的动态 / 我的点赞 / 我的留言」
/// 三、子列表用通用 PostListBody:
/// 动态 getUserClassPost(queryType=0);点赞 getMyLikePage;留言 getMyCommentPage。
/// 点赞页取消点赞时从列表移除该项(removeOnUnlike);其余保留。
/// 四、懒加载:默认建第一个 tab,切到再建(对标 renderedTabs)。
/// ============================================================
class MyInteractPage extends StatefulWidget {
const MyInteractPage({super.key});
@override
State<MyInteractPage> createState() => _MyInteractPageState();
}
class _MyInteractPageState extends State<MyInteractPage> {
static const List<String> _tabs = ['我的动态', '我的点赞', '我的留言'];
int _currentTab = 0;
final List<bool> _loadedTabs = [true, false, false];
void _switchTab(int index) {
if (_currentTab == index) return;
setState(() {
_loadedTabs[index] = true;
_currentTab = index;
});
}
void _openDetail(UserPostDto post) {
context.push('/class/my-update-detail', extra: post);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF5F8FA),
appBar: AppBar(
backgroundColor: const Color(0xFFF5F8FA),
elevation: 0,
title: const Text(
'我的互动',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w400,
color: Color(0xFF1D2B47),
),
),
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Color(0xFF1D2B47)),
onPressed: () =>
context.canPop() ? context.pop() : context.go('/class'),
),
),
body: Column(
children: [
_buildTabs(),
Expanded(
child: IndexedStack(
index: _currentTab,
children: [
if (_loadedTabs[0]) _UpdateTab(onTapPost: _openDetail),
if (_loadedTabs[1]) _LikeTab(onTapPost: _openDetail),
if (_loadedTabs[2]) _CommentTab(onTapPost: _openDetail),
],
),
),
],
),
);
}
Widget _buildTabs() {
return Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(14.w, 12.h, 14.w, 22.h),
child: Row(
children: [
for (int i = 0; i < _tabs.length; i++) ...[
if (i > 0) SizedBox(width: 12.w),
_buildTabItem(i),
],
],
),
);
}
Widget _buildTabItem(int index) {
final active = _currentTab == index;
return GestureDetector(
onTap: () => _switchTab(index),
child: Container(
width: 84.w,
height: 37.h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: active ? const Color(0xFF3D7DF5) : Colors.white,
borderRadius: BorderRadius.circular(20.r),
),
child: Text(
_tabs[index],
style: TextStyle(
fontSize: 15,
color: active ? Colors.white : const Color(0xFF687FAD),
),
),
),
);
}
}
class _UpdateTab extends StatelessWidget {
const _UpdateTab({required this.onTapPost});
final ValueChanged<UserPostDto> onTapPost;
@override
Widget build(BuildContext context) {
return PostListBody(
fetchPage: ({required pageIndex, required pageSize, required prevPageId}) =>
ClassApi.instance.getUserClassPost(
queryType: 0,
pageIndex: pageIndex,
pageSize: pageSize,
prevPageId: prevPageId,
),
emptyText: '暂无动态',
onTapPost: onTapPost,
);
}
}
class _LikeTab extends StatelessWidget {
const _LikeTab({required this.onTapPost});
final ValueChanged<UserPostDto> onTapPost;
@override
Widget build(BuildContext context) {
return PostListBody(
fetchPage: ({required pageIndex, required pageSize, required prevPageId}) =>
ClassApi.instance.getMyLikePage(
pageIndex: pageIndex,
pageSize: pageSize,
prevPageId: prevPageId,
),
emptyText: '暂无点赞',
removeOnUnlike: true,
onTapPost: onTapPost,
);
}
}
class _CommentTab extends StatelessWidget {
const _CommentTab({required this.onTapPost});
final ValueChanged<UserPostDto> onTapPost;
@override
Widget build(BuildContext context) {
return PostListBody(
fetchPage: ({required pageIndex, required pageSize, required prevPageId}) =>
ClassApi.instance.getMyCommentPage(
pageIndex: pageIndex,
pageSize: pageSize,
prevPageId: prevPageId,
),
emptyText: '暂无留言',
onTapPost: onTapPost,
);
}
}