新增消息中心页面,实现未读消息轮询与展示 为各 Tab 页面顶栏添加通知图标及未读数角标 新增通知 API 接口与未读数状态管理 实现消息标记已读、全部已读及下拉刷新功能
116 lines
4.0 KiB
Dart
116 lines
4.0 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import '../core/app_keys.dart';
|
|
import '../features/auth/application/session_controller.dart';
|
|
import '../features/auth/presentation/login_page.dart';
|
|
import '../features/customer/presentation/customer_detail_page.dart';
|
|
import '../features/customer/presentation/customer_edit_page.dart';
|
|
import '../features/notice/presentation/notice_center_page.dart';
|
|
import '../features/project/presentation/project_detail_page.dart';
|
|
import '../features/survey/presentation/survey_form_page.dart';
|
|
import '../features/survey/presentation/survey_list_page.dart';
|
|
import '../features/visit/presentation/visit_batch_page.dart';
|
|
import '../features/visit/presentation/visit_detail_page.dart';
|
|
import '../features/visit/presentation/visit_execute_page.dart';
|
|
import '../features/visit/presentation/visit_form_page.dart';
|
|
import '../features/visit/presentation/visit_list_page.dart';
|
|
import 'tabs_page.dart';
|
|
|
|
/// 会话语义变化时驱动 go_router 重新执行 `redirect`。
|
|
class _SessionRefresh extends ChangeNotifier {
|
|
void bump() => notifyListeners();
|
|
}
|
|
|
|
/// 路由表,对应 uni-app 版 `pages.json` 的 12 个页面。
|
|
///
|
|
/// 除登录页与 Tab 容器页外,其余均为二级页,统一使用主题里的
|
|
/// `CupertinoPageTransitionsBuilder`(新页面从右侧滑入),
|
|
/// 与源项目 `animationType: slide-in-right` 的表现一致。
|
|
final routerProvider = Provider<GoRouter>((ref) {
|
|
final refresh = _SessionRefresh();
|
|
ref.listen(sessionProvider, (_, _) => refresh.bump());
|
|
ref.onDispose(refresh.dispose);
|
|
|
|
int? queryId(GoRouterState state) =>
|
|
int.tryParse(state.uri.queryParameters['id'] ?? '');
|
|
|
|
return GoRouter(
|
|
navigatorKey: AppKeys.rootNavigator,
|
|
initialLocation: '/login',
|
|
refreshListenable: refresh,
|
|
redirect: (context, state) {
|
|
final loggedIn = ref.read(sessionProvider).isLoggedIn;
|
|
final atLogin = state.matchedLocation == '/login';
|
|
if (!loggedIn) return atLogin ? null : '/login';
|
|
if (atLogin) return '/tabs';
|
|
return null;
|
|
},
|
|
routes: [
|
|
GoRoute(path: '/login', builder: (context, state) => const LoginPage()),
|
|
GoRoute(path: '/tabs', builder: (context, state) => const TabsPage()),
|
|
|
|
// 消息中心(二级页)
|
|
GoRoute(
|
|
path: '/notice',
|
|
builder: (context, state) => const NoticeCenterPage(),
|
|
),
|
|
|
|
// 客户模块
|
|
GoRoute(
|
|
path: '/customer/detail/:id',
|
|
builder: (context, state) =>
|
|
CustomerDetailPage(id: int.parse(state.pathParameters['id']!)),
|
|
),
|
|
GoRoute(
|
|
path: '/customer/edit',
|
|
builder: (context, state) => CustomerEditPage(id: queryId(state)),
|
|
),
|
|
|
|
// 拜访模块
|
|
GoRoute(
|
|
path: '/visit',
|
|
builder: (context, state) => const VisitListPage(),
|
|
),
|
|
GoRoute(
|
|
path: '/visit/detail/:id',
|
|
builder: (context, state) =>
|
|
VisitDetailPage(id: int.parse(state.pathParameters['id']!)),
|
|
),
|
|
GoRoute(
|
|
path: '/visit/form',
|
|
builder: (context, state) => VisitFormPage(id: queryId(state)),
|
|
),
|
|
GoRoute(
|
|
path: '/visit/execute/:id',
|
|
builder: (context, state) =>
|
|
VisitExecutePage(id: int.parse(state.pathParameters['id']!)),
|
|
),
|
|
GoRoute(
|
|
path: '/visit/batch',
|
|
builder: (context, state) => const VisitBatchPage(),
|
|
),
|
|
|
|
// 勘测模块
|
|
GoRoute(
|
|
path: '/survey',
|
|
builder: (context, state) => const SurveyListPage(),
|
|
),
|
|
GoRoute(
|
|
path: '/survey/form',
|
|
builder: (context, state) => SurveyFormPage(
|
|
id: queryId(state),
|
|
customerId: int.tryParse(state.uri.queryParameters['customerId'] ?? ''),
|
|
),
|
|
),
|
|
|
|
// 项目模块(按后端 project-plans 真实字段重做)
|
|
GoRoute(
|
|
path: '/project/detail/:id',
|
|
builder: (context, state) =>
|
|
ProjectDetailPage(id: int.parse(state.pathParameters['id']!)),
|
|
),
|
|
],
|
|
);
|
|
}); |