feat: 完成班级模块全量功能迭代
本次提交完成了班级模块的多项核心功能开发与优化: 1. 新增DELETE请求封装,支持业务删除接口且不自动重试 2. 完善UserPostCommonDto模型,新增头像字段适配详情接口 3. 重构路由架构,使用StatefulShellRoute实现Tab页面保活 4. 新增我的互动页面,包含我的动态/点赞/留言三个子页 5. 新增全部同学页面,展示班级全员信息与在线状态 6. 新增动态详情页面,支持查看完整评论与点赞头像 7. 抽离通用PostListBody组件,复用列表分页与交互逻辑 8. 优化班级列表页加载逻辑与图片预览交互 9. 新增评论删除、多图预览等细节交互功能
This commit is contained in:
@@ -6,7 +6,11 @@ import 'package:new_learn/features/auth/legal_document_page.dart';
|
||||
import 'package:new_learn/features/auth/legal_documents.dart';
|
||||
import 'package:new_learn/features/auth/login_page.dart';
|
||||
import 'package:new_learn/features/auth/privacy_consent_page.dart';
|
||||
import 'package:new_learn/features/class/all_student_view.dart';
|
||||
import 'package:new_learn/features/class/class_page.dart';
|
||||
import 'package:new_learn/features/class/my_interact_page.dart';
|
||||
import 'package:new_learn/features/class/my_update_detail_page.dart';
|
||||
import 'package:new_learn/core/api/class/model.dart';
|
||||
import 'package:new_learn/features/my/my_page.dart';
|
||||
import 'package:new_learn/features/my/my_point/my_point_page.dart';
|
||||
import 'package:new_learn/features/recite/recite_page.dart';
|
||||
@@ -76,14 +80,47 @@ final GoRouter appRouter = GoRouter(
|
||||
privacyAcceptedNotifier,
|
||||
]), // 响应式登录守卫:监听登录态变化信号,变化时自动重算 redirect
|
||||
routes: [
|
||||
// ---------- 4 tab 主框架(ShellRoute:子页面共享这个壳) ----------
|
||||
ShellRoute(
|
||||
builder: (context, state, child) => MainTabPage(child: child),
|
||||
routes: [
|
||||
GoRoute(path: '/', builder: (_, _) => const TaskPage()),
|
||||
GoRoute(path: '/recite', builder: (_, _) => const RecitePage()),
|
||||
GoRoute(path: '/class', builder: (_, _) => const ClassPage()),
|
||||
GoRoute(path: '/my', builder: (_, _) => const MyPage()),
|
||||
// ---------- 4 tab 主框架(StatefulShellRoute:切 tab 用 IndexedStack 保活页面状态) ----------
|
||||
StatefulShellRoute.indexedStack(
|
||||
builder: (context, state, navigationShell) =>
|
||||
MainTabPage(navigationShell: navigationShell),
|
||||
branches: [
|
||||
// 任务
|
||||
StatefulShellBranch(
|
||||
routes: [GoRoute(path: '/', builder: (_, _) => const TaskPage())],
|
||||
),
|
||||
// 背诵
|
||||
StatefulShellBranch(
|
||||
routes: [
|
||||
GoRoute(path: '/recite', builder: (_, _) => const RecitePage()),
|
||||
],
|
||||
),
|
||||
// 班级(含班级模块子页:全部同学 / 我的互动 / 动态详情)
|
||||
StatefulShellBranch(
|
||||
routes: [
|
||||
GoRoute(path: '/class', builder: (_, _) => const ClassPage()),
|
||||
GoRoute(
|
||||
path: '/class/all-student',
|
||||
builder: (_, _) => const AllStudentPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/class/my-interact',
|
||||
builder: (_, _) => const MyInteractPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/class/my-update-detail',
|
||||
builder: (_, state) =>
|
||||
MyUpdateDetailPage(initialPost: state.extra as UserPostDto),
|
||||
),
|
||||
],
|
||||
),
|
||||
// 我的(含我的积分页)
|
||||
StatefulShellBranch(
|
||||
routes: [
|
||||
GoRoute(path: '/my', builder: (_, _) => const MyPage()),
|
||||
GoRoute(path: '/myPoint', builder: (_, _) => const MyPointPage()),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
// ---------- 首次启动隐私协议页 ----------
|
||||
@@ -107,8 +144,6 @@ final GoRouter appRouter = GoRouter(
|
||||
),
|
||||
// ---------- 登录页 ----------
|
||||
GoRoute(path: '/login', builder: (_, _) => const LoginPage()),
|
||||
// ---------- 业务子页(从 tab 页 push 进来,不占 tab) ----------
|
||||
GoRoute(path: '/myPoint', builder: (_, _) => const MyPointPage()),
|
||||
// app_router.dart 的 routes 里加,不用管跳转逻辑
|
||||
// GoRoute(path: '/task/:id', builder: (_, _) => const TaskDetailPage()),
|
||||
// ---------- 以后新业务页在这里加,一行一个 ----------
|
||||
|
||||
@@ -37,10 +37,11 @@ import 'package:new_learn/core/version/app_version_service.dart';
|
||||
/// 底部导航不消失、子页面盖在内容区上——这是 ShellRoute 的价值。
|
||||
/// ============================================================
|
||||
class MainTabPage extends StatefulWidget {
|
||||
const MainTabPage({super.key, required this.child});
|
||||
const MainTabPage({super.key, required this.navigationShell});
|
||||
|
||||
/// 当前 tab 页面(由 go_router ShellRoute 提供)
|
||||
final Widget child;
|
||||
/// go_router 的导航壳(StatefulShellRoute.indexedStack 提供):
|
||||
/// 内部用 IndexedStack 保活各 tab 页面,来回切 tab 不丢页面状态。
|
||||
final StatefulNavigationShell navigationShell;
|
||||
|
||||
@override
|
||||
State<MainTabPage> createState() => _MainTabPageState();
|
||||
@@ -100,37 +101,19 @@ class _MainTabPageState extends State<MainTabPage> {
|
||||
'assets/img/tabbar/default/myChoose.png',
|
||||
];
|
||||
|
||||
/// 当前路由 path → tab 序号(默认第 1 个"任务")
|
||||
int _indexOf(String path) {
|
||||
return switch (path) {
|
||||
'/recite' => 1,
|
||||
'/class' => 2,
|
||||
'/my' => 3,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
/// tab 序号 → 路由 path(点击底部导航时跳转)
|
||||
String _pathOf(int index) {
|
||||
return switch (index) {
|
||||
1 => '/recite',
|
||||
2 => '/class',
|
||||
3 => '/my',
|
||||
_ => '/',
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 从 go_router 拿当前路由,反推底部高亮 tab
|
||||
final path = GoRouterState.of(context).uri.path;
|
||||
final currentIndex = _indexOf(path);
|
||||
final navigationShell = widget.navigationShell;
|
||||
final currentIndex = navigationShell.currentIndex;
|
||||
|
||||
return Scaffold(
|
||||
body: widget.child,
|
||||
body:
|
||||
navigationShell, // StatefulNavigationShell 内部用 IndexedStack 保活各 tab 页
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: currentIndex,
|
||||
onTap: (i) => context.go(_pathOf(i)),
|
||||
// 切 tab:进对应 branch;点当前 tab 则回到其栈顶
|
||||
onTap: (i) =>
|
||||
navigationShell.goBranch(i, initialLocation: i == currentIndex),
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: Colors.white,
|
||||
selectedItemColor: const Color(0xFF3B82F6),
|
||||
|
||||
Reference in New Issue
Block a user