Commit 983bc0a8 authored by 张宏's avatar 张宏

菜单调整

parent b368f64a
This diff is collapsed.
...@@ -4,6 +4,12 @@ import 'package:auto_route/auto_route.dart'; ...@@ -4,6 +4,12 @@ import 'package:auto_route/auto_route.dart';
import 'package:laki_icu_app/views/login/login_view.dart'; import 'package:laki_icu_app/views/login/login_view.dart';
import 'package:laki_icu_app/views/layout/default_view.dart'; import 'package:laki_icu_app/views/layout/default_view.dart';
import 'package:laki_icu_app/views/monitoring/index/monitoring_index_view.dart'; import 'package:laki_icu_app/views/monitoring/index/monitoring_index_view.dart';
import 'package:laki_icu_app/views/blood_pressure/blood_pressure_index_view.dart';
import 'package:laki_icu_app/views/vital_signs/vital_signs_index_view.dart';
import 'package:laki_icu_app/views/ecg_system/ecg_system_index_view.dart';
import 'package:laki_icu_app/views/tsaas/tsaas_index_view.dart';
import 'package:laki_icu_app/views/record/record_index_view.dart';
import 'package:laki_icu_app/views/settings/settings_index_view.dart';
import 'app_router.gr.dart'; import 'app_router.gr.dart';
@AutoRouterConfig(replaceInRouteName: 'View,Route') @AutoRouterConfig(replaceInRouteName: 'View,Route')
...@@ -16,13 +22,25 @@ class AppRouter extends $AppRouter { ...@@ -16,13 +22,25 @@ class AppRouter extends $AppRouter {
List<AutoRoute> get routes => [ List<AutoRoute> get routes => [
// LoginRoute / LoginView(登录页) // LoginRoute / LoginView(登录页)
AutoRoute(page: LoginRoute.page), AutoRoute(page: LoginRoute.page),
// DefaultLayoutRoute / DefaultLayoutView(默认布局页/主框架 // DefaultLayoutRoute / DefaultLayoutView(主框架 Shell
AutoRoute( AutoRoute(
page: DefaultLayoutRoute.page, page: DefaultLayoutRoute.page,
initial: true, initial: true,
children: [ children: [
// MonitoringIndexRoute / MonitoringIndexView(监控页 // MonitoringIndexRoute / MonitoringIndexView(ICU中控 - Tab 0
AutoRoute(page: MonitoringIndexRoute.page, initial: true), AutoRoute(page: MonitoringIndexRoute.page, initial: true),
// BloodPressureIndexRoute / BloodPressureIndexView(血压监测 - Tab 1)
AutoRoute(page: BloodPressureIndexRoute.page),
// VitalSignsIndexRoute / VitalSignsIndexView(体征仪 - Tab 2)
AutoRoute(page: VitalSignsIndexRoute.page),
// EcgSystemIndexRoute / EcgSystemIndexView(多导心电系统 - Tab 3)
AutoRoute(page: EcgSystemIndexRoute.page),
// TsaasIndexRoute / TsaasIndexView(TSAAS - Tab 4)
AutoRoute(page: TsaasIndexRoute.page),
// RecordIndexRoute / RecordIndexView(记录 - Tab 5)
AutoRoute(page: RecordIndexRoute.page),
// SettingsIndexRoute / SettingsIndexView(设置 - Tab 6)
AutoRoute(page: SettingsIndexRoute.page),
], ],
), ),
]; ];
......
...@@ -8,45 +8,104 @@ ...@@ -8,45 +8,104 @@
// coverage:ignore-file // coverage:ignore-file
// ignore_for_file: no_leading_underscores_for_library_prefixes // ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:auto_route/auto_route.dart' as _i4; import 'package:auto_route/auto_route.dart' as _i10;
import 'package:flutter/material.dart' as _i5; import 'package:flutter/material.dart' as _i11;
import 'package:laki_icu_app/views/layout/default_view.dart' as _i1; import 'package:laki_icu_app/views/blood_pressure/blood_pressure_index_view.dart'
import 'package:laki_icu_app/views/login/login_view.dart' as _i2; as _i1;
import 'package:laki_icu_app/views/monitoring/index/monitoring_index_view.dart' import 'package:laki_icu_app/views/ecg_system/ecg_system_index_view.dart'
as _i3; as _i3;
import 'package:laki_icu_app/views/layout/default_view.dart' as _i2;
abstract class $AppRouter extends _i4.RootStackRouter { import 'package:laki_icu_app/views/login/login_view.dart' as _i4;
import 'package:laki_icu_app/views/monitoring/index/monitoring_index_view.dart'
as _i5;
import 'package:laki_icu_app/views/record/record_index_view.dart' as _i6;
import 'package:laki_icu_app/views/settings/settings_index_view.dart' as _i7;
import 'package:laki_icu_app/views/tsaas/tsaas_index_view.dart' as _i8;
import 'package:laki_icu_app/views/vital_signs/vital_signs_index_view.dart'
as _i9;
abstract class $AppRouter extends _i10.RootStackRouter {
$AppRouter({super.navigatorKey}); $AppRouter({super.navigatorKey});
@override @override
final Map<String, _i4.PageFactory> pagesMap = { final Map<String, _i10.PageFactory> pagesMap = {
BloodPressureIndexRoute.name: (routeData) {
return _i10.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i1.BloodPressureIndexView(),
);
},
DefaultLayoutRoute.name: (routeData) { DefaultLayoutRoute.name: (routeData) {
return _i4.AutoRoutePage<dynamic>( return _i10.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i2.DefaultLayoutView(),
);
},
EcgSystemIndexRoute.name: (routeData) {
return _i10.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i1.DefaultLayoutView(), child: const _i3.EcgSystemIndexView(),
); );
}, },
LoginRoute.name: (routeData) { LoginRoute.name: (routeData) {
final args = routeData.argsAs<LoginRouteArgs>( final args = routeData.argsAs<LoginRouteArgs>(
orElse: () => const LoginRouteArgs()); orElse: () => const LoginRouteArgs());
return _i4.AutoRoutePage<dynamic>( return _i10.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i2.LoginView(key: args.key), child: _i4.LoginView(key: args.key),
); );
}, },
MonitoringIndexRoute.name: (routeData) { MonitoringIndexRoute.name: (routeData) {
return _i4.AutoRoutePage<dynamic>( return _i10.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i5.MonitoringIndexView(),
);
},
RecordIndexRoute.name: (routeData) {
return _i10.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i6.RecordIndexView(),
);
},
SettingsIndexRoute.name: (routeData) {
return _i10.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i7.SettingsIndexView(),
);
},
TsaasIndexRoute.name: (routeData) {
return _i10.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i3.MonitoringIndexView(), child: const _i8.TsaasIndexView(),
);
},
VitalSignsIndexRoute.name: (routeData) {
return _i10.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i9.VitalSignsIndexView(),
); );
}, },
}; };
} }
/// generated route for /// generated route for
/// [_i1.DefaultLayoutView] /// [_i1.BloodPressureIndexView]
class DefaultLayoutRoute extends _i4.PageRouteInfo<void> { class BloodPressureIndexRoute extends _i10.PageRouteInfo<void> {
const DefaultLayoutRoute({List<_i4.PageRouteInfo>? children}) const BloodPressureIndexRoute({List<_i10.PageRouteInfo>? children})
: super(
BloodPressureIndexRoute.name,
initialChildren: children,
);
static const String name = 'BloodPressureIndexRoute';
static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
}
/// generated route for
/// [_i2.DefaultLayoutView]
class DefaultLayoutRoute extends _i10.PageRouteInfo<void> {
const DefaultLayoutRoute({List<_i10.PageRouteInfo>? children})
: super( : super(
DefaultLayoutRoute.name, DefaultLayoutRoute.name,
initialChildren: children, initialChildren: children,
...@@ -54,15 +113,29 @@ class DefaultLayoutRoute extends _i4.PageRouteInfo<void> { ...@@ -54,15 +113,29 @@ class DefaultLayoutRoute extends _i4.PageRouteInfo<void> {
static const String name = 'DefaultLayoutRoute'; static const String name = 'DefaultLayoutRoute';
static const _i4.PageInfo<void> page = _i4.PageInfo<void>(name); static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i2.LoginView] /// [_i3.EcgSystemIndexView]
class LoginRoute extends _i4.PageRouteInfo<LoginRouteArgs> { class EcgSystemIndexRoute extends _i10.PageRouteInfo<void> {
const EcgSystemIndexRoute({List<_i10.PageRouteInfo>? children})
: super(
EcgSystemIndexRoute.name,
initialChildren: children,
);
static const String name = 'EcgSystemIndexRoute';
static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
}
/// generated route for
/// [_i4.LoginView]
class LoginRoute extends _i10.PageRouteInfo<LoginRouteArgs> {
LoginRoute({ LoginRoute({
_i5.Key? key, _i11.Key? key,
List<_i4.PageRouteInfo>? children, List<_i10.PageRouteInfo>? children,
}) : super( }) : super(
LoginRoute.name, LoginRoute.name,
args: LoginRouteArgs(key: key), args: LoginRouteArgs(key: key),
...@@ -71,14 +144,14 @@ class LoginRoute extends _i4.PageRouteInfo<LoginRouteArgs> { ...@@ -71,14 +144,14 @@ class LoginRoute extends _i4.PageRouteInfo<LoginRouteArgs> {
static const String name = 'LoginRoute'; static const String name = 'LoginRoute';
static const _i4.PageInfo<LoginRouteArgs> page = static const _i10.PageInfo<LoginRouteArgs> page =
_i4.PageInfo<LoginRouteArgs>(name); _i10.PageInfo<LoginRouteArgs>(name);
} }
class LoginRouteArgs { class LoginRouteArgs {
const LoginRouteArgs({this.key}); const LoginRouteArgs({this.key});
final _i5.Key? key; final _i11.Key? key;
@override @override
String toString() { String toString() {
...@@ -87,9 +160,9 @@ class LoginRouteArgs { ...@@ -87,9 +160,9 @@ class LoginRouteArgs {
} }
/// generated route for /// generated route for
/// [_i3.MonitoringIndexView] /// [_i5.MonitoringIndexView]
class MonitoringIndexRoute extends _i4.PageRouteInfo<void> { class MonitoringIndexRoute extends _i10.PageRouteInfo<void> {
const MonitoringIndexRoute({List<_i4.PageRouteInfo>? children}) const MonitoringIndexRoute({List<_i10.PageRouteInfo>? children})
: super( : super(
MonitoringIndexRoute.name, MonitoringIndexRoute.name,
initialChildren: children, initialChildren: children,
...@@ -97,5 +170,61 @@ class MonitoringIndexRoute extends _i4.PageRouteInfo<void> { ...@@ -97,5 +170,61 @@ class MonitoringIndexRoute extends _i4.PageRouteInfo<void> {
static const String name = 'MonitoringIndexRoute'; static const String name = 'MonitoringIndexRoute';
static const _i4.PageInfo<void> page = _i4.PageInfo<void>(name); static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
}
/// generated route for
/// [_i6.RecordIndexView]
class RecordIndexRoute extends _i10.PageRouteInfo<void> {
const RecordIndexRoute({List<_i10.PageRouteInfo>? children})
: super(
RecordIndexRoute.name,
initialChildren: children,
);
static const String name = 'RecordIndexRoute';
static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
}
/// generated route for
/// [_i7.SettingsIndexView]
class SettingsIndexRoute extends _i10.PageRouteInfo<void> {
const SettingsIndexRoute({List<_i10.PageRouteInfo>? children})
: super(
SettingsIndexRoute.name,
initialChildren: children,
);
static const String name = 'SettingsIndexRoute';
static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
}
/// generated route for
/// [_i8.TsaasIndexView]
class TsaasIndexRoute extends _i10.PageRouteInfo<void> {
const TsaasIndexRoute({List<_i10.PageRouteInfo>? children})
: super(
TsaasIndexRoute.name,
initialChildren: children,
);
static const String name = 'TsaasIndexRoute';
static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
}
/// generated route for
/// [_i9.VitalSignsIndexView]
class VitalSignsIndexRoute extends _i10.PageRouteInfo<void> {
const VitalSignsIndexRoute({List<_i10.PageRouteInfo>? children})
: super(
VitalSignsIndexRoute.name,
initialChildren: children,
);
static const String name = 'VitalSignsIndexRoute';
static const _i10.PageInfo<void> page = _i10.PageInfo<void>(name);
} }
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class BloodPressureIndexView extends StatelessWidget {
const BloodPressureIndexView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'血压监测',
style: TextStyle(color: Colors.white, fontSize: 24),
),
);
}
}
import 'package:flutter_bloc/flutter_bloc.dart';
import 'blood_pressure_index_state.dart';
class BloodPressureIndexCubit extends Cubit<BloodPressureIndexState> {
BloodPressureIndexCubit() : super(const BloodPressureIndexState());
}
import 'package:equatable/equatable.dart';
class BloodPressureIndexState extends Equatable {
const BloodPressureIndexState();
@override
List<Object?> get props => [];
}
import 'package:flutter_bloc/flutter_bloc.dart';
import 'ecg_system_index_state.dart';
class EcgSystemIndexCubit extends Cubit<EcgSystemIndexState> {
EcgSystemIndexCubit() : super(const EcgSystemIndexState());
}
import 'package:equatable/equatable.dart';
class EcgSystemIndexState extends Equatable {
const EcgSystemIndexState();
@override
List<Object?> get props => [];
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class EcgSystemIndexView extends StatelessWidget {
const EcgSystemIndexView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'多导心电系统',
style: TextStyle(color: Colors.white, fontSize: 24),
),
);
}
}
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:laki_icu_app/services/monitoring_service.dart';
import 'default_layout_state.dart';
/// 菜单 ID 与 Tab 索引的映射
///
/// Tab 顺序必须与 mock 数据中 menuItems 的定义顺序一致:
/// 0: icu_central, 1: blood_pressure, 2: vital_signs,
/// 3: ecg_system, 4: tsaas, 5: record, 6: settings
const _menuIdToIndex = <String, int>{
'icu_central': 0,
'blood_pressure': 1,
'vital_signs': 2,
'ecg_system': 3,
'tsaas': 4,
'record': 5,
'settings': 6,
};
const _indexToMenuId = <int, String>{
0: 'icu_central',
1: 'blood_pressure',
2: 'vital_signs',
3: 'ecg_system',
4: 'tsaas',
5: 'record',
6: 'settings',
};
/// 将 Tab 索引转换为菜单 ID
String menuIdFromIndex(int index) {
return _indexToMenuId[index] ?? 'icu_central';
}
/// 将菜单 ID 转换为 Tab 索引
int indexFromMenuId(String menuId) {
return _menuIdToIndex[menuId] ?? 0;
}
class DefaultLayoutCubit extends Cubit<DefaultLayoutState> {
final MonitoringService _monitoringService;
DefaultLayoutCubit()
: _monitoringService = MonitoringService(),
super(const DefaultLayoutState()) {
_loadMenuItems();
}
Future<void> _loadMenuItems() async {
emit(state.copyWith(isLoading: true, error: null));
try {
final menuItems = await _monitoringService.getMenuItems();
emit(state.copyWith(isLoading: false, menuItems: menuItems));
} catch (e) {
emit(state.copyWith(isLoading: false, error: e.toString()));
}
}
Future<void> refresh() async {
await _loadMenuItems();
}
}
import 'package:equatable/equatable.dart';
import 'package:laki_icu_app/models/bo/monitoring_bo.dart';
class DefaultLayoutState extends Equatable {
final List<MonitoringMenuItemBO> menuItems;
final bool isLoading;
final String? error;
const DefaultLayoutState({
this.menuItems = const [],
this.isLoading = false,
this.error,
});
DefaultLayoutState copyWith({
List<MonitoringMenuItemBO>? menuItems,
bool? isLoading,
String? error,
}) {
return DefaultLayoutState(
menuItems: menuItems ?? this.menuItems,
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
@override
List<Object?> get props => [menuItems, isLoading, error];
}
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../routes/app_router.gr.dart';
import 'cubit/default_layout_cubit.dart';
import 'cubit/default_layout_state.dart';
import 'widgets/monitoring_bottom_menu.dart';
import 'widgets/monitoring_top_status_bar.dart';
@RoutePage() @RoutePage()
class DefaultLayoutView extends StatelessWidget { class DefaultLayoutView extends StatelessWidget {
...@@ -7,6 +15,105 @@ class DefaultLayoutView extends StatelessWidget { ...@@ -7,6 +15,105 @@ class DefaultLayoutView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const AutoRouter(); return BlocProvider(
create: (_) => DefaultLayoutCubit(),
child: const _DefaultLayoutContent(),
);
}
}
class _DefaultLayoutContent extends StatelessWidget {
const _DefaultLayoutContent();
@override
Widget build(BuildContext context) {
return BlocBuilder<DefaultLayoutCubit, DefaultLayoutState>(
builder: (context, state) {
if (state.isLoading) {
return const Scaffold(
backgroundColor: Color(0xFF010B1D),
body: Center(
child: CircularProgressIndicator(color: Colors.white),
),
);
}
if (state.error != null && state.menuItems.isEmpty) {
return Scaffold(
backgroundColor: const Color(0xFF010B1D),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'菜单加载失败: ${state.error}',
style: const TextStyle(color: Colors.white),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () =>
context.read<DefaultLayoutCubit>().refresh(),
child: const Text('重试'),
),
],
),
),
);
}
return AutoTabsScaffold(
backgroundColor: const Color(0xFF010B1D),
resizeToAvoidBottomInset: false,
homeIndex: 0,
routes: const [
MonitoringIndexRoute(),
BloodPressureIndexRoute(),
VitalSignsIndexRoute(),
EcgSystemIndexRoute(),
TsaasIndexRoute(),
RecordIndexRoute(),
SettingsIndexRoute(),
],
appBarBuilder: (context, tabsRouter) {
return PreferredSize(
preferredSize: Size.fromHeight(104.h),
child: Container(
decoration: const BoxDecoration(
// border: BoxBorder.all(width: 1.w,color: Colors.red)
),
child: Stack(
children: [
Positioned(
right: 10,
top: 20,
child: Image.asset(
'lib/assets/monitoring/top_line.png',
width: 906.w,
height: 162.h,
),
),
Container(
height: 104.h,
child: const MonitoringTopStatusBar(),
),
],
),
),
);
},
bottomNavigationBuilder: (context, tabsRouter) {
final selectedMenuId = menuIdFromIndex(tabsRouter.activeIndex);
return MonitoringBottomMenu(
menuItems: state.menuItems,
selectedMenuId: selectedMenuId,
onMenuItemTap: (menuId) {
final index = indexFromMenuId(menuId);
tabsRouter.setActiveIndex(index);
},
);
},
);
},
);
} }
} }
...@@ -67,14 +67,12 @@ class MonitoringBottomMenu extends StatelessWidget { ...@@ -67,14 +67,12 @@ class MonitoringBottomMenu extends StatelessWidget {
Widget _buildMenuItemTSAAS(MonitoringMenuItemBO item) { Widget _buildMenuItemTSAAS(MonitoringMenuItemBO item) {
final isSelected = selectedMenuId == item.id;
return Padding( return Padding(
padding: EdgeInsets.symmetric(horizontal: 40.w), padding: EdgeInsets.symmetric(horizontal: 40.w),
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
debugPrint('[MonitoringBottomMenu] 点击菜单: ${item.id} (${item.title})'); debugPrint('[MonitoringBottomMenu] 点击菜单: ${item.id} (${item.title})');
// onMenuItemTap?.call(item.id); onMenuItemTap?.call(item.id);
}, },
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
...@@ -83,18 +81,12 @@ class MonitoringBottomMenu extends StatelessWidget { ...@@ -83,18 +81,12 @@ class MonitoringBottomMenu extends StatelessWidget {
Container( Container(
width: 167.w, width: 167.w,
height: 62.h, height: 62.h,
decoration: BoxDecoration(
border: isSelected
? Border.all(color: const Color(0xFF00FFFF), width: 1.5.w)
: null,
borderRadius: BorderRadius.circular(item.isTsaas ? 22.w : 24.w),
),
child: Image.asset( child: Image.asset(
item.iconPath, item.iconPath,
fit: BoxFit.contain, fit: BoxFit.contain,
), ),
), ),
], ],
), ),
), ),
...@@ -109,7 +101,7 @@ class MonitoringBottomMenu extends StatelessWidget { ...@@ -109,7 +101,7 @@ class MonitoringBottomMenu extends StatelessWidget {
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
debugPrint('[MonitoringBottomMenu] 点击菜单: ${item.id} (${item.title})'); debugPrint('[MonitoringBottomMenu] 点击菜单: ${item.id} (${item.title})');
// onMenuItemTap?.call(item.id); onMenuItemTap?.call(item.id);
}, },
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
...@@ -118,12 +110,6 @@ class MonitoringBottomMenu extends StatelessWidget { ...@@ -118,12 +110,6 @@ class MonitoringBottomMenu extends StatelessWidget {
Container( Container(
width: 62.w, width: 62.w,
height: 62.h, height: 62.h,
decoration: BoxDecoration(
border: isSelected
? Border.all(color: const Color(0xFF00FFFF), width: 1.5.w)
: null,
borderRadius: BorderRadius.circular(item.isTsaas ? 22.w : 24.w),
),
child: Image.asset( child: Image.asset(
item.iconPath, item.iconPath,
fit: BoxFit.contain, fit: BoxFit.contain,
......
...@@ -66,8 +66,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -66,8 +66,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
if (isClosed) return; if (isClosed) return;
final alerts = await _monitoringService.getAlerts(); final alerts = await _monitoringService.getAlerts();
if (isClosed) return; if (isClosed) return;
final menuItems = await _monitoringService.getMenuItems();
if (isClosed) return;
emit(state.copyWith( emit(state.copyWith(
status: MonitoringIndexStatus.success, status: MonitoringIndexStatus.success,
...@@ -75,7 +73,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -75,7 +73,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
metrics: metrics, metrics: metrics,
patientInfo: patientInfo, patientInfo: patientInfo,
alerts: alerts, alerts: alerts,
menuItems: menuItems,
error: null, error: null,
)); ));
...@@ -184,15 +181,12 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -184,15 +181,12 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
if (isClosed) return; if (isClosed) return;
final alerts = await _monitoringService.getAlerts(); final alerts = await _monitoringService.getAlerts();
if (isClosed) return; if (isClosed) return;
final menuItems = await _monitoringService.getMenuItems();
if (isClosed) return;
emit(state.copyWith( emit(state.copyWith(
status: MonitoringIndexStatus.success, status: MonitoringIndexStatus.success,
metrics: metrics, metrics: metrics,
patientInfo: patientInfo, patientInfo: patientInfo,
alerts: alerts, alerts: alerts,
menuItems: menuItems,
error: null, error: null,
)); ));
} catch (e) { } catch (e) {
...@@ -210,41 +204,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -210,41 +204,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
/// 获取 P2P 视频播放控制器供 UI 层使用 /// 获取 P2P 视频播放控制器供 UI 层使用
P2pVideoService get p2pVideoService => _p2pVideoService; P2pVideoService get p2pVideoService => _p2pVideoService;
// ==================== 菜单点击事件 ====================
/// 处理底部菜单点击
void onMenuItemTap(String menuId) {
debugPrint('[MonitoringIndexCubit] 菜单被点击: $menuId');
emit(state.copyWith(selectedMenuId: menuId));
// 根据菜单ID处理不同的逻辑
switch (menuId) {
case 'icu_central':
debugPrint('[MonitoringIndexCubit] 切换到ICU中控');
break;
case 'blood_pressure':
debugPrint('[MonitoringIndexCubit] 切换到血压监测');
break;
case 'vital_signs':
debugPrint('[MonitoringIndexCubit] 切换到体征仪');
break;
case 'ecg_system':
debugPrint('[MonitoringIndexCubit] 切换到多导心电系统');
break;
case 'tsaas':
debugPrint('[MonitoringIndexCubit] 切换到TSAAS');
break;
case 'record':
debugPrint('[MonitoringIndexCubit] 切换到记录');
break;
case 'settings':
debugPrint('[MonitoringIndexCubit] 切换到设置');
break;
default:
debugPrint('[MonitoringIndexCubit] 未知菜单: $menuId');
}
}
@override @override
Future<void> close() { Future<void> close() {
_webrtcStateSub?.cancel(); _webrtcStateSub?.cancel();
......
...@@ -17,7 +17,6 @@ class MonitoringIndexState extends Equatable { ...@@ -17,7 +17,6 @@ class MonitoringIndexState extends Equatable {
final List<MonitoringMetricBO> metrics; final List<MonitoringMetricBO> metrics;
final PatientInfoBO? patientInfo; final PatientInfoBO? patientInfo;
final List<AlertInfoBO> alerts; final List<AlertInfoBO> alerts;
final List<MonitoringMenuItemBO> menuItems;
/// WebRTC 视频连接状态 /// WebRTC 视频连接状态
final WebrtcConnectionState videoConnectionState; final WebrtcConnectionState videoConnectionState;
...@@ -31,9 +30,6 @@ class MonitoringIndexState extends Equatable { ...@@ -31,9 +30,6 @@ class MonitoringIndexState extends Equatable {
/// P2P 模式是否已连接 /// P2P 模式是否已连接
final bool isP2pConnected; final bool isP2pConnected;
/// 当前选中的菜单ID
final String? selectedMenuId;
const MonitoringIndexState({ const MonitoringIndexState({
this.status = MonitoringIndexStatus.initial, this.status = MonitoringIndexStatus.initial,
this.isLoading = false, this.isLoading = false,
...@@ -41,12 +37,10 @@ class MonitoringIndexState extends Equatable { ...@@ -41,12 +37,10 @@ class MonitoringIndexState extends Equatable {
this.metrics = const [], this.metrics = const [],
this.patientInfo, this.patientInfo,
this.alerts = const [], this.alerts = const [],
this.menuItems = const [],
this.videoConnectionState = WebrtcConnectionState.disconnected, this.videoConnectionState = WebrtcConnectionState.disconnected,
this.videoStreamMode = VideoStreamMode.p2p, this.videoStreamMode = VideoStreamMode.p2p,
this.isSwitchingMode = false, this.isSwitchingMode = false,
this.isP2pConnected = false, this.isP2pConnected = false,
this.selectedMenuId,
}); });
MonitoringIndexState copyWith({ MonitoringIndexState copyWith({
...@@ -56,12 +50,10 @@ class MonitoringIndexState extends Equatable { ...@@ -56,12 +50,10 @@ class MonitoringIndexState extends Equatable {
List<MonitoringMetricBO>? metrics, List<MonitoringMetricBO>? metrics,
PatientInfoBO? patientInfo, PatientInfoBO? patientInfo,
List<AlertInfoBO>? alerts, List<AlertInfoBO>? alerts,
List<MonitoringMenuItemBO>? menuItems,
WebrtcConnectionState? videoConnectionState, WebrtcConnectionState? videoConnectionState,
VideoStreamMode? videoStreamMode, VideoStreamMode? videoStreamMode,
bool? isSwitchingMode, bool? isSwitchingMode,
bool? isP2pConnected, bool? isP2pConnected,
String? selectedMenuId,
}) { }) {
return MonitoringIndexState( return MonitoringIndexState(
status: status ?? this.status, status: status ?? this.status,
...@@ -70,13 +62,11 @@ class MonitoringIndexState extends Equatable { ...@@ -70,13 +62,11 @@ class MonitoringIndexState extends Equatable {
metrics: metrics ?? this.metrics, metrics: metrics ?? this.metrics,
patientInfo: patientInfo ?? this.patientInfo, patientInfo: patientInfo ?? this.patientInfo,
alerts: alerts ?? this.alerts, alerts: alerts ?? this.alerts,
menuItems: menuItems ?? this.menuItems,
videoConnectionState: videoConnectionState:
videoConnectionState ?? this.videoConnectionState, videoConnectionState ?? this.videoConnectionState,
videoStreamMode: videoStreamMode ?? this.videoStreamMode, videoStreamMode: videoStreamMode ?? this.videoStreamMode,
isSwitchingMode: isSwitchingMode ?? this.isSwitchingMode, isSwitchingMode: isSwitchingMode ?? this.isSwitchingMode,
isP2pConnected: isP2pConnected ?? this.isP2pConnected, isP2pConnected: isP2pConnected ?? this.isP2pConnected,
selectedMenuId: selectedMenuId ?? this.selectedMenuId,
); );
} }
...@@ -88,11 +78,9 @@ class MonitoringIndexState extends Equatable { ...@@ -88,11 +78,9 @@ class MonitoringIndexState extends Equatable {
metrics, metrics,
patientInfo, patientInfo,
alerts, alerts,
menuItems,
videoConnectionState, videoConnectionState,
videoStreamMode, videoStreamMode,
isSwitchingMode, isSwitchingMode,
isP2pConnected, isP2pConnected,
selectedMenuId,
]; ];
} }
...@@ -8,10 +8,8 @@ import 'package:laki_icu_app/models/bo/monitoring_bo.dart'; ...@@ -8,10 +8,8 @@ import 'package:laki_icu_app/models/bo/monitoring_bo.dart';
import 'cubit/monitoring_index_cubit.dart'; import 'cubit/monitoring_index_cubit.dart';
import 'cubit/monitoring_index_state.dart'; import 'cubit/monitoring_index_state.dart';
import 'widgets/monitoring_alert_card.dart'; import 'widgets/monitoring_alert_card.dart';
import 'widgets/monitoring_bottom_menu.dart';
import 'widgets/monitoring_metric_card.dart'; import 'widgets/monitoring_metric_card.dart';
import 'widgets/monitoring_pet_info_card.dart'; import 'widgets/monitoring_pet_info_card.dart';
import 'widgets/monitoring_top_status_bar.dart';
import 'widgets/video_player_widget.dart'; import 'widgets/video_player_widget.dart';
@RoutePage() @RoutePage()
...@@ -45,23 +43,19 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> { ...@@ -45,23 +43,19 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return BlocBuilder<MonitoringIndexCubit, MonitoringIndexState>(
resizeToAvoidBottomInset: false, builder: (context, state) {
backgroundColor: const Color(0xFF010B1D), if (state.isLoading && state.metrics.isEmpty) {
body: BlocBuilder<MonitoringIndexCubit, MonitoringIndexState>( return const Center(
builder: (context, state) { child: CircularProgressIndicator(color: Colors.white),
if (state.isLoading && state.metrics.isEmpty) { );
return const Center( }
child: CircularProgressIndicator(color: Colors.white), if (state.status == MonitoringIndexStatus.failure &&
); state.metrics.isEmpty) {
} return _buildError(state.error);
if (state.status == MonitoringIndexStatus.failure && }
state.metrics.isEmpty) { return _buildMainArea(state);
return _buildError(state.error); },
}
return _buildDashboard(state);
},
),
); );
} }
...@@ -84,68 +78,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> { ...@@ -84,68 +78,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
); );
} }
Widget _buildDashboard(MonitoringIndexState state) { Widget _buildMainArea(MonitoringIndexState state) {
return LayoutBuilder(
builder: (context, constraints) {
final topHeight = constraints.maxHeight * 0.11;
final bottomHeight = constraints.maxHeight * 0.15;
final gap = 10.w;
return Column(
children: [
Container(
// height: topHeight.clamp(80.0, 104.0),
decoration: BoxDecoration(
// border: BoxBorder.all(width: 1.w,color: Colors.red)
),
child: Stack(
children: [
Positioned(
right: 10,
top:20,
child: Image.asset(
'lib/assets/monitoring/top_line.png',
width: 906.w,
height: 162.h,
),
),
Container(
height: topHeight.clamp(80.0, 104.0),
child: const MonitoringTopStatusBar(),
),
],
)
),
Expanded(
child: Container(
padding: EdgeInsets.zero,
decoration: BoxDecoration(
// border: BoxBorder.all(width: 1.w,color: Colors.red)
),
child: _buildMainArea(state, gap),
),
),
Container(
height: bottomHeight.clamp(92.0, 134.0),
decoration: BoxDecoration(
// border: BoxBorder.all(width: 1.w,color: Colors.red)
),
child: MonitoringBottomMenu(
menuItems: state.menuItems,
selectedMenuId: state.selectedMenuId,
// onMenuItemTap: _monitoringIndexCubit.onMenuItemTap,
),
),
],
);
},
);
}
Widget _buildMainArea(MonitoringIndexState state, double gap) {
return Row( return Row(
children: [ children: [
Expanded( Expanded(
...@@ -159,17 +92,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> { ...@@ -159,17 +92,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
children: [ children: [
Expanded( Expanded(
flex: 32, flex: 32,
child: Row( child: _buildMetrics(state.metrics),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 4,
child: _buildMetrics(state.metrics, gap), // 4个监控
),
// SizedBox(width: gap),
],
),
), ),
SizedBox(height: 24.h), SizedBox(height: 24.h),
Expanded( Expanded(
...@@ -180,7 +103,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> { ...@@ -180,7 +103,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
flex: 10, flex: 10,
child: MonitoringAlertCard(alerts: state.alerts), child: MonitoringAlertCard(alerts: state.alerts),
), ),
SizedBox(width: gap), SizedBox(width: 10.w),
Expanded( Expanded(
flex: 10, flex: 10,
child: VideoPlayerWidget( child: VideoPlayerWidget(
...@@ -206,7 +129,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> { ...@@ -206,7 +129,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
); );
} }
Widget _buildMetrics(List<MonitoringMetricBO> metrics, double gap) { Widget _buildMetrics(List<MonitoringMetricBO> metrics) {
final displayMetrics = _environmentMetrics(metrics); final displayMetrics = _environmentMetrics(metrics);
final children = <Widget>[]; final children = <Widget>[];
for (int i = 0; i < displayMetrics.length; i++) { for (int i = 0; i < displayMetrics.length; i++) {
......
import 'package:flutter_bloc/flutter_bloc.dart';
import 'record_index_state.dart';
class RecordIndexCubit extends Cubit<RecordIndexState> {
RecordIndexCubit() : super(const RecordIndexState());
}
import 'package:equatable/equatable.dart';
class RecordIndexState extends Equatable {
const RecordIndexState();
@override
List<Object?> get props => [];
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class RecordIndexView extends StatelessWidget {
const RecordIndexView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'记录',
style: TextStyle(color: Colors.white, fontSize: 24),
),
);
}
}
import 'package:flutter_bloc/flutter_bloc.dart';
import 'settings_index_state.dart';
class SettingsIndexCubit extends Cubit<SettingsIndexState> {
SettingsIndexCubit() : super(const SettingsIndexState());
}
import 'package:equatable/equatable.dart';
class SettingsIndexState extends Equatable {
const SettingsIndexState();
@override
List<Object?> get props => [];
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class SettingsIndexView extends StatelessWidget {
const SettingsIndexView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'设置',
style: TextStyle(color: Colors.white, fontSize: 24),
),
);
}
}
import 'package:flutter_bloc/flutter_bloc.dart';
import 'tsaas_index_state.dart';
class TsaasIndexCubit extends Cubit<TsaasIndexState> {
TsaasIndexCubit() : super(const TsaasIndexState());
}
import 'package:equatable/equatable.dart';
class TsaasIndexState extends Equatable {
const TsaasIndexState();
@override
List<Object?> get props => [];
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class TsaasIndexView extends StatelessWidget {
const TsaasIndexView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'TSAAS',
style: TextStyle(color: Colors.white, fontSize: 24),
),
);
}
}
import 'package:flutter_bloc/flutter_bloc.dart';
import 'vital_signs_index_state.dart';
class VitalSignsIndexCubit extends Cubit<VitalSignsIndexState> {
VitalSignsIndexCubit() : super(const VitalSignsIndexState());
}
import 'package:equatable/equatable.dart';
class VitalSignsIndexState extends Equatable {
const VitalSignsIndexState();
@override
List<Object?> get props => [];
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
@RoutePage()
class VitalSignsIndexView extends StatelessWidget {
const VitalSignsIndexView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'体征仪',
style: TextStyle(color: Colors.white, fontSize: 24),
),
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment