Commit 7566c742 authored by huqu's avatar huqu

fix bugs

parent 59e6cf59
...@@ -56,5 +56,7 @@ class AppRouter extends $AppRouter { ...@@ -56,5 +56,7 @@ class AppRouter extends $AppRouter {
AutoRoute(page: ReportDeviceListRoute.page), AutoRoute(page: ReportDeviceListRoute.page),
// InspectionTopologyRoute / InspectionTopologyView(巡检拓扑页) // InspectionTopologyRoute / InspectionTopologyView(巡检拓扑页)
AutoRoute(page: InspectionTopologyRoute.page), AutoRoute(page: InspectionTopologyRoute.page),
// AboutRoute / AboutView(关于页)
AutoRoute(page: AboutRoute.page),
]; ];
} }
...@@ -8,52 +8,53 @@ ...@@ -8,52 +8,53 @@
// 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 _i21; import 'package:auto_route/auto_route.dart' as _i22;
import 'package:flutter/material.dart' as _i22; import 'package:flutter/material.dart' as _i23;
import 'package:smart_hotel_app/views/home/abnormal/abnormal_detail_view.dart' import 'package:smart_hotel_app/views/home/abnormal/abnormal_detail_view.dart'
as _i1; as _i1;
import 'package:smart_hotel_app/views/home/abnormal_list/cubit/abnormal_list_state.dart' import 'package:smart_hotel_app/views/home/abnormal_list/cubit/abnormal_list_state.dart'
as _i23; as _i24;
import 'package:smart_hotel_app/views/home/abnormal_list/index_view.dart' import 'package:smart_hotel_app/views/home/abnormal_list/index_view.dart'
as _i2; as _i2;
import 'package:smart_hotel_app/views/home/device/device_detail_view.dart' import 'package:smart_hotel_app/views/home/device/device_detail_view.dart'
as _i4; as _i5;
import 'package:smart_hotel_app/views/home/index/index_view.dart' as _i5; import 'package:smart_hotel_app/views/home/index/index_view.dart' as _i6;
import 'package:smart_hotel_app/views/home/inspection/inspection_detail_view.dart' import 'package:smart_hotel_app/views/home/inspection/inspection_detail_view.dart'
as _i6;
import 'package:smart_hotel_app/views/home/inspection_device/inspection_device_view.dart'
as _i7; as _i7;
import 'package:smart_hotel_app/views/home/inspection_history/inspection_history_view.dart' import 'package:smart_hotel_app/views/home/inspection_device/inspection_device_view.dart'
as _i8; as _i8;
import 'package:smart_hotel_app/views/home/inspection_topology/inspection_topology_view.dart' import 'package:smart_hotel_app/views/home/inspection_history/inspection_history_view.dart'
as _i9; as _i9;
import 'package:smart_hotel_app/views/layout/default_view.dart' as _i3; import 'package:smart_hotel_app/views/home/inspection_topology/inspection_topology_view.dart'
import 'package:smart_hotel_app/views/login/login_view.dart' as _i10; as _i10;
import 'package:smart_hotel_app/views/profile/index/index_view.dart' as _i11; import 'package:smart_hotel_app/views/layout/default_view.dart' as _i4;
import 'package:smart_hotel_app/views/login/login_view.dart' as _i11;
import 'package:smart_hotel_app/views/profile/about/about_view.dart' as _i3;
import 'package:smart_hotel_app/views/profile/index/index_view.dart' as _i12;
import 'package:smart_hotel_app/views/report/device/device_list_view.dart' import 'package:smart_hotel_app/views/report/device/device_list_view.dart'
as _i12;
import 'package:smart_hotel_app/views/report/energy/energy_detail_view.dart'
as _i13; as _i13;
import 'package:smart_hotel_app/views/report/index/index_view.dart' as _i14; import 'package:smart_hotel_app/views/report/energy/energy_detail_view.dart'
as _i14;
import 'package:smart_hotel_app/views/report/index/index_view.dart' as _i15;
import 'package:smart_hotel_app/views/report/room/room_detail_view.dart' import 'package:smart_hotel_app/views/report/room/room_detail_view.dart'
as _i15;
import 'package:smart_hotel_app/views/report/rule/rule_management_view.dart'
as _i16; as _i16;
import 'package:smart_hotel_app/views/search/index_view.dart' as _i17; import 'package:smart_hotel_app/views/report/rule/rule_management_view.dart'
as _i17;
import 'package:smart_hotel_app/views/search/index_view.dart' as _i18;
import 'package:smart_hotel_app/views/service/device/device_detail_view.dart' import 'package:smart_hotel_app/views/service/device/device_detail_view.dart'
as _i18; as _i19;
import 'package:smart_hotel_app/views/service/index/index_view.dart' as _i19; import 'package:smart_hotel_app/views/service/index/index_view.dart' as _i20;
import 'package:smart_hotel_app/views/service/room/room_detail_view.dart' import 'package:smart_hotel_app/views/service/room/room_detail_view.dart'
as _i20; as _i21;
abstract class $AppRouter extends _i21.RootStackRouter { abstract class $AppRouter extends _i22.RootStackRouter {
$AppRouter({super.navigatorKey}); $AppRouter({super.navigatorKey});
@override @override
final Map<String, _i21.PageFactory> pagesMap = { final Map<String, _i22.PageFactory> pagesMap = {
AbnormalDetailRoute.name: (routeData) { AbnormalDetailRoute.name: (routeData) {
final args = routeData.argsAs<AbnormalDetailRouteArgs>(); final args = routeData.argsAs<AbnormalDetailRouteArgs>();
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i1.AbnormalDetailView( child: _i1.AbnormalDetailView(
key: args.key, key: args.key,
...@@ -63,37 +64,43 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -63,37 +64,43 @@ abstract class $AppRouter extends _i21.RootStackRouter {
); );
}, },
AbnormalListRoute.name: (routeData) { AbnormalListRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i2.AbnormalListView(), child: const _i2.AbnormalListView(),
); );
}, },
AboutRoute.name: (routeData) {
return _i22.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i3.AboutView(),
);
},
DefaultLayoutRoute.name: (routeData) { DefaultLayoutRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i3.DefaultLayoutView(), child: const _i4.DefaultLayoutView(),
); );
}, },
DeviceDetailRoute.name: (routeData) { DeviceDetailRoute.name: (routeData) {
final args = routeData.argsAs<DeviceDetailRouteArgs>(); final args = routeData.argsAs<DeviceDetailRouteArgs>();
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i4.DeviceDetailView( child: _i5.DeviceDetailView(
key: args.key, key: args.key,
deviceId: args.deviceId, deviceId: args.deviceId,
), ),
); );
}, },
HomeRoute.name: (routeData) { HomeRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i5.HomeView(), child: const _i6.HomeView(),
); );
}, },
InspectionDetailRoute.name: (routeData) { InspectionDetailRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i6.InspectionDetailView(), child: const _i7.InspectionDetailView(),
); );
}, },
InspectionDeviceRoute.name: (routeData) { InspectionDeviceRoute.name: (routeData) {
...@@ -101,9 +108,9 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -101,9 +108,9 @@ abstract class $AppRouter extends _i21.RootStackRouter {
final args = routeData.argsAs<InspectionDeviceRouteArgs>( final args = routeData.argsAs<InspectionDeviceRouteArgs>(
orElse: () => InspectionDeviceRouteArgs( orElse: () => InspectionDeviceRouteArgs(
deviceId: pathParams.getString('deviceId'))); deviceId: pathParams.getString('deviceId')));
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i7.InspectionDeviceView( child: _i8.InspectionDeviceView(
key: args.key, key: args.key,
deviceId: args.deviceId, deviceId: args.deviceId,
), ),
...@@ -114,9 +121,9 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -114,9 +121,9 @@ abstract class $AppRouter extends _i21.RootStackRouter {
final args = routeData.argsAs<InspectionHistoryRouteArgs>( final args = routeData.argsAs<InspectionHistoryRouteArgs>(
orElse: () => InspectionHistoryRouteArgs( orElse: () => InspectionHistoryRouteArgs(
deviceId: pathParams.getString('deviceId'))); deviceId: pathParams.getString('deviceId')));
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i8.InspectionHistoryView( child: _i9.InspectionHistoryView(
key: args.key, key: args.key,
deviceId: args.deviceId, deviceId: args.deviceId,
), ),
...@@ -124,9 +131,9 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -124,9 +131,9 @@ abstract class $AppRouter extends _i21.RootStackRouter {
}, },
InspectionTopologyRoute.name: (routeData) { InspectionTopologyRoute.name: (routeData) {
final args = routeData.argsAs<InspectionTopologyRouteArgs>(); final args = routeData.argsAs<InspectionTopologyRouteArgs>();
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i9.InspectionTopologyView( child: _i10.InspectionTopologyView(
key: args.key, key: args.key,
deviceId: args.deviceId, deviceId: args.deviceId,
), ),
...@@ -135,53 +142,53 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -135,53 +142,53 @@ abstract class $AppRouter extends _i21.RootStackRouter {
LoginRoute.name: (routeData) { LoginRoute.name: (routeData) {
final args = routeData.argsAs<LoginRouteArgs>( final args = routeData.argsAs<LoginRouteArgs>(
orElse: () => const LoginRouteArgs()); orElse: () => const LoginRouteArgs());
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i10.LoginView(key: args.key), child: _i11.LoginView(key: args.key),
); );
}, },
ProfileRoute.name: (routeData) { ProfileRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i11.ProfileView(), child: const _i12.ProfileView(),
); );
}, },
ReportDeviceListRoute.name: (routeData) { ReportDeviceListRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i12.ReportDeviceListView(), child: const _i13.ReportDeviceListView(),
); );
}, },
ReportEnergyDetailRoute.name: (routeData) { ReportEnergyDetailRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i13.ReportEnergyDetailView(), child: const _i14.ReportEnergyDetailView(),
); );
}, },
ReportIndexRoute.name: (routeData) { ReportIndexRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i14.ReportIndexView(), child: const _i15.ReportIndexView(),
); );
}, },
ReportRoomDetailRoute.name: (routeData) { ReportRoomDetailRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i15.ReportRoomDetailView(), child: const _i16.ReportRoomDetailView(),
); );
}, },
ReportRuleManagementRoute.name: (routeData) { ReportRuleManagementRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i16.ReportRuleManagementView(), child: const _i17.ReportRuleManagementView(),
); );
}, },
SearchRoute.name: (routeData) { SearchRoute.name: (routeData) {
final args = routeData.argsAs<SearchRouteArgs>( final args = routeData.argsAs<SearchRouteArgs>(
orElse: () => const SearchRouteArgs()); orElse: () => const SearchRouteArgs());
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i17.SearchView( child: _i18.SearchView(
key: args.key, key: args.key,
searchKey: args.searchKey, searchKey: args.searchKey,
), ),
...@@ -189,25 +196,25 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -189,25 +196,25 @@ abstract class $AppRouter extends _i21.RootStackRouter {
}, },
ServiceDeviceDetailRoute.name: (routeData) { ServiceDeviceDetailRoute.name: (routeData) {
final args = routeData.argsAs<ServiceDeviceDetailRouteArgs>(); final args = routeData.argsAs<ServiceDeviceDetailRouteArgs>();
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i18.ServiceDeviceDetailView( child: _i19.ServiceDeviceDetailView(
key: args.key, key: args.key,
deviceId: args.deviceId, deviceId: args.deviceId,
), ),
); );
}, },
ServiceIndexRoute.name: (routeData) { ServiceIndexRoute.name: (routeData) {
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: const _i19.ServiceIndexView(), child: const _i20.ServiceIndexView(),
); );
}, },
ServiceRoomDetailRoute.name: (routeData) { ServiceRoomDetailRoute.name: (routeData) {
final args = routeData.argsAs<ServiceRoomDetailRouteArgs>(); final args = routeData.argsAs<ServiceRoomDetailRouteArgs>();
return _i21.AutoRoutePage<dynamic>( return _i22.AutoRoutePage<dynamic>(
routeData: routeData, routeData: routeData,
child: _i20.ServiceRoomDetailView( child: _i21.ServiceRoomDetailView(
key: args.key, key: args.key,
roomId: args.roomId, roomId: args.roomId,
roomNumber: args.roomNumber, roomNumber: args.roomNumber,
...@@ -219,12 +226,12 @@ abstract class $AppRouter extends _i21.RootStackRouter { ...@@ -219,12 +226,12 @@ abstract class $AppRouter extends _i21.RootStackRouter {
/// generated route for /// generated route for
/// [_i1.AbnormalDetailView] /// [_i1.AbnormalDetailView]
class AbnormalDetailRoute extends _i21.PageRouteInfo<AbnormalDetailRouteArgs> { class AbnormalDetailRoute extends _i22.PageRouteInfo<AbnormalDetailRouteArgs> {
AbnormalDetailRoute({ AbnormalDetailRoute({
_i22.Key? key, _i23.Key? key,
required int alertId, required int alertId,
required _i23.AlarmStatus alarmStatus, required _i24.AlarmStatus alarmStatus,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
AbnormalDetailRoute.name, AbnormalDetailRoute.name,
args: AbnormalDetailRouteArgs( args: AbnormalDetailRouteArgs(
...@@ -237,8 +244,8 @@ class AbnormalDetailRoute extends _i21.PageRouteInfo<AbnormalDetailRouteArgs> { ...@@ -237,8 +244,8 @@ class AbnormalDetailRoute extends _i21.PageRouteInfo<AbnormalDetailRouteArgs> {
static const String name = 'AbnormalDetailRoute'; static const String name = 'AbnormalDetailRoute';
static const _i21.PageInfo<AbnormalDetailRouteArgs> page = static const _i22.PageInfo<AbnormalDetailRouteArgs> page =
_i21.PageInfo<AbnormalDetailRouteArgs>(name); _i22.PageInfo<AbnormalDetailRouteArgs>(name);
} }
class AbnormalDetailRouteArgs { class AbnormalDetailRouteArgs {
...@@ -248,11 +255,11 @@ class AbnormalDetailRouteArgs { ...@@ -248,11 +255,11 @@ class AbnormalDetailRouteArgs {
required this.alarmStatus, required this.alarmStatus,
}); });
final _i22.Key? key; final _i23.Key? key;
final int alertId; final int alertId;
final _i23.AlarmStatus alarmStatus; final _i24.AlarmStatus alarmStatus;
@override @override
String toString() { String toString() {
...@@ -262,8 +269,8 @@ class AbnormalDetailRouteArgs { ...@@ -262,8 +269,8 @@ class AbnormalDetailRouteArgs {
/// generated route for /// generated route for
/// [_i2.AbnormalListView] /// [_i2.AbnormalListView]
class AbnormalListRoute extends _i21.PageRouteInfo<void> { class AbnormalListRoute extends _i22.PageRouteInfo<void> {
const AbnormalListRoute({List<_i21.PageRouteInfo>? children}) const AbnormalListRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
AbnormalListRoute.name, AbnormalListRoute.name,
initialChildren: children, initialChildren: children,
...@@ -271,13 +278,27 @@ class AbnormalListRoute extends _i21.PageRouteInfo<void> { ...@@ -271,13 +278,27 @@ class AbnormalListRoute extends _i21.PageRouteInfo<void> {
static const String name = 'AbnormalListRoute'; static const String name = 'AbnormalListRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
}
/// generated route for
/// [_i3.AboutView]
class AboutRoute extends _i22.PageRouteInfo<void> {
const AboutRoute({List<_i22.PageRouteInfo>? children})
: super(
AboutRoute.name,
initialChildren: children,
);
static const String name = 'AboutRoute';
static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i3.DefaultLayoutView] /// [_i4.DefaultLayoutView]
class DefaultLayoutRoute extends _i21.PageRouteInfo<void> { class DefaultLayoutRoute extends _i22.PageRouteInfo<void> {
const DefaultLayoutRoute({List<_i21.PageRouteInfo>? children}) const DefaultLayoutRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
DefaultLayoutRoute.name, DefaultLayoutRoute.name,
initialChildren: children, initialChildren: children,
...@@ -285,16 +306,16 @@ class DefaultLayoutRoute extends _i21.PageRouteInfo<void> { ...@@ -285,16 +306,16 @@ class DefaultLayoutRoute extends _i21.PageRouteInfo<void> {
static const String name = 'DefaultLayoutRoute'; static const String name = 'DefaultLayoutRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i4.DeviceDetailView] /// [_i5.DeviceDetailView]
class DeviceDetailRoute extends _i21.PageRouteInfo<DeviceDetailRouteArgs> { class DeviceDetailRoute extends _i22.PageRouteInfo<DeviceDetailRouteArgs> {
DeviceDetailRoute({ DeviceDetailRoute({
_i22.Key? key, _i23.Key? key,
required int deviceId, required int deviceId,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
DeviceDetailRoute.name, DeviceDetailRoute.name,
args: DeviceDetailRouteArgs( args: DeviceDetailRouteArgs(
...@@ -306,8 +327,8 @@ class DeviceDetailRoute extends _i21.PageRouteInfo<DeviceDetailRouteArgs> { ...@@ -306,8 +327,8 @@ class DeviceDetailRoute extends _i21.PageRouteInfo<DeviceDetailRouteArgs> {
static const String name = 'DeviceDetailRoute'; static const String name = 'DeviceDetailRoute';
static const _i21.PageInfo<DeviceDetailRouteArgs> page = static const _i22.PageInfo<DeviceDetailRouteArgs> page =
_i21.PageInfo<DeviceDetailRouteArgs>(name); _i22.PageInfo<DeviceDetailRouteArgs>(name);
} }
class DeviceDetailRouteArgs { class DeviceDetailRouteArgs {
...@@ -316,7 +337,7 @@ class DeviceDetailRouteArgs { ...@@ -316,7 +337,7 @@ class DeviceDetailRouteArgs {
required this.deviceId, required this.deviceId,
}); });
final _i22.Key? key; final _i23.Key? key;
final int deviceId; final int deviceId;
...@@ -327,9 +348,9 @@ class DeviceDetailRouteArgs { ...@@ -327,9 +348,9 @@ class DeviceDetailRouteArgs {
} }
/// generated route for /// generated route for
/// [_i5.HomeView] /// [_i6.HomeView]
class HomeRoute extends _i21.PageRouteInfo<void> { class HomeRoute extends _i22.PageRouteInfo<void> {
const HomeRoute({List<_i21.PageRouteInfo>? children}) const HomeRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
HomeRoute.name, HomeRoute.name,
initialChildren: children, initialChildren: children,
...@@ -337,13 +358,13 @@ class HomeRoute extends _i21.PageRouteInfo<void> { ...@@ -337,13 +358,13 @@ class HomeRoute extends _i21.PageRouteInfo<void> {
static const String name = 'HomeRoute'; static const String name = 'HomeRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i6.InspectionDetailView] /// [_i7.InspectionDetailView]
class InspectionDetailRoute extends _i21.PageRouteInfo<void> { class InspectionDetailRoute extends _i22.PageRouteInfo<void> {
const InspectionDetailRoute({List<_i21.PageRouteInfo>? children}) const InspectionDetailRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
InspectionDetailRoute.name, InspectionDetailRoute.name,
initialChildren: children, initialChildren: children,
...@@ -351,17 +372,17 @@ class InspectionDetailRoute extends _i21.PageRouteInfo<void> { ...@@ -351,17 +372,17 @@ class InspectionDetailRoute extends _i21.PageRouteInfo<void> {
static const String name = 'InspectionDetailRoute'; static const String name = 'InspectionDetailRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i7.InspectionDeviceView] /// [_i8.InspectionDeviceView]
class InspectionDeviceRoute class InspectionDeviceRoute
extends _i21.PageRouteInfo<InspectionDeviceRouteArgs> { extends _i22.PageRouteInfo<InspectionDeviceRouteArgs> {
InspectionDeviceRoute({ InspectionDeviceRoute({
_i22.Key? key, _i23.Key? key,
required String deviceId, required String deviceId,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
InspectionDeviceRoute.name, InspectionDeviceRoute.name,
args: InspectionDeviceRouteArgs( args: InspectionDeviceRouteArgs(
...@@ -374,8 +395,8 @@ class InspectionDeviceRoute ...@@ -374,8 +395,8 @@ class InspectionDeviceRoute
static const String name = 'InspectionDeviceRoute'; static const String name = 'InspectionDeviceRoute';
static const _i21.PageInfo<InspectionDeviceRouteArgs> page = static const _i22.PageInfo<InspectionDeviceRouteArgs> page =
_i21.PageInfo<InspectionDeviceRouteArgs>(name); _i22.PageInfo<InspectionDeviceRouteArgs>(name);
} }
class InspectionDeviceRouteArgs { class InspectionDeviceRouteArgs {
...@@ -384,7 +405,7 @@ class InspectionDeviceRouteArgs { ...@@ -384,7 +405,7 @@ class InspectionDeviceRouteArgs {
required this.deviceId, required this.deviceId,
}); });
final _i22.Key? key; final _i23.Key? key;
final String deviceId; final String deviceId;
...@@ -395,13 +416,13 @@ class InspectionDeviceRouteArgs { ...@@ -395,13 +416,13 @@ class InspectionDeviceRouteArgs {
} }
/// generated route for /// generated route for
/// [_i8.InspectionHistoryView] /// [_i9.InspectionHistoryView]
class InspectionHistoryRoute class InspectionHistoryRoute
extends _i21.PageRouteInfo<InspectionHistoryRouteArgs> { extends _i22.PageRouteInfo<InspectionHistoryRouteArgs> {
InspectionHistoryRoute({ InspectionHistoryRoute({
_i22.Key? key, _i23.Key? key,
required String deviceId, required String deviceId,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
InspectionHistoryRoute.name, InspectionHistoryRoute.name,
args: InspectionHistoryRouteArgs( args: InspectionHistoryRouteArgs(
...@@ -414,8 +435,8 @@ class InspectionHistoryRoute ...@@ -414,8 +435,8 @@ class InspectionHistoryRoute
static const String name = 'InspectionHistoryRoute'; static const String name = 'InspectionHistoryRoute';
static const _i21.PageInfo<InspectionHistoryRouteArgs> page = static const _i22.PageInfo<InspectionHistoryRouteArgs> page =
_i21.PageInfo<InspectionHistoryRouteArgs>(name); _i22.PageInfo<InspectionHistoryRouteArgs>(name);
} }
class InspectionHistoryRouteArgs { class InspectionHistoryRouteArgs {
...@@ -424,7 +445,7 @@ class InspectionHistoryRouteArgs { ...@@ -424,7 +445,7 @@ class InspectionHistoryRouteArgs {
required this.deviceId, required this.deviceId,
}); });
final _i22.Key? key; final _i23.Key? key;
final String deviceId; final String deviceId;
...@@ -435,13 +456,13 @@ class InspectionHistoryRouteArgs { ...@@ -435,13 +456,13 @@ class InspectionHistoryRouteArgs {
} }
/// generated route for /// generated route for
/// [_i9.InspectionTopologyView] /// [_i10.InspectionTopologyView]
class InspectionTopologyRoute class InspectionTopologyRoute
extends _i21.PageRouteInfo<InspectionTopologyRouteArgs> { extends _i22.PageRouteInfo<InspectionTopologyRouteArgs> {
InspectionTopologyRoute({ InspectionTopologyRoute({
_i22.Key? key, _i23.Key? key,
required String deviceId, required String deviceId,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
InspectionTopologyRoute.name, InspectionTopologyRoute.name,
args: InspectionTopologyRouteArgs( args: InspectionTopologyRouteArgs(
...@@ -453,8 +474,8 @@ class InspectionTopologyRoute ...@@ -453,8 +474,8 @@ class InspectionTopologyRoute
static const String name = 'InspectionTopologyRoute'; static const String name = 'InspectionTopologyRoute';
static const _i21.PageInfo<InspectionTopologyRouteArgs> page = static const _i22.PageInfo<InspectionTopologyRouteArgs> page =
_i21.PageInfo<InspectionTopologyRouteArgs>(name); _i22.PageInfo<InspectionTopologyRouteArgs>(name);
} }
class InspectionTopologyRouteArgs { class InspectionTopologyRouteArgs {
...@@ -463,7 +484,7 @@ class InspectionTopologyRouteArgs { ...@@ -463,7 +484,7 @@ class InspectionTopologyRouteArgs {
required this.deviceId, required this.deviceId,
}); });
final _i22.Key? key; final _i23.Key? key;
final String deviceId; final String deviceId;
...@@ -474,11 +495,11 @@ class InspectionTopologyRouteArgs { ...@@ -474,11 +495,11 @@ class InspectionTopologyRouteArgs {
} }
/// generated route for /// generated route for
/// [_i10.LoginView] /// [_i11.LoginView]
class LoginRoute extends _i21.PageRouteInfo<LoginRouteArgs> { class LoginRoute extends _i22.PageRouteInfo<LoginRouteArgs> {
LoginRoute({ LoginRoute({
_i22.Key? key, _i23.Key? key,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
LoginRoute.name, LoginRoute.name,
args: LoginRouteArgs(key: key), args: LoginRouteArgs(key: key),
...@@ -487,14 +508,14 @@ class LoginRoute extends _i21.PageRouteInfo<LoginRouteArgs> { ...@@ -487,14 +508,14 @@ class LoginRoute extends _i21.PageRouteInfo<LoginRouteArgs> {
static const String name = 'LoginRoute'; static const String name = 'LoginRoute';
static const _i21.PageInfo<LoginRouteArgs> page = static const _i22.PageInfo<LoginRouteArgs> page =
_i21.PageInfo<LoginRouteArgs>(name); _i22.PageInfo<LoginRouteArgs>(name);
} }
class LoginRouteArgs { class LoginRouteArgs {
const LoginRouteArgs({this.key}); const LoginRouteArgs({this.key});
final _i22.Key? key; final _i23.Key? key;
@override @override
String toString() { String toString() {
...@@ -503,9 +524,9 @@ class LoginRouteArgs { ...@@ -503,9 +524,9 @@ class LoginRouteArgs {
} }
/// generated route for /// generated route for
/// [_i11.ProfileView] /// [_i12.ProfileView]
class ProfileRoute extends _i21.PageRouteInfo<void> { class ProfileRoute extends _i22.PageRouteInfo<void> {
const ProfileRoute({List<_i21.PageRouteInfo>? children}) const ProfileRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ProfileRoute.name, ProfileRoute.name,
initialChildren: children, initialChildren: children,
...@@ -513,13 +534,13 @@ class ProfileRoute extends _i21.PageRouteInfo<void> { ...@@ -513,13 +534,13 @@ class ProfileRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ProfileRoute'; static const String name = 'ProfileRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i12.ReportDeviceListView] /// [_i13.ReportDeviceListView]
class ReportDeviceListRoute extends _i21.PageRouteInfo<void> { class ReportDeviceListRoute extends _i22.PageRouteInfo<void> {
const ReportDeviceListRoute({List<_i21.PageRouteInfo>? children}) const ReportDeviceListRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ReportDeviceListRoute.name, ReportDeviceListRoute.name,
initialChildren: children, initialChildren: children,
...@@ -527,13 +548,13 @@ class ReportDeviceListRoute extends _i21.PageRouteInfo<void> { ...@@ -527,13 +548,13 @@ class ReportDeviceListRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ReportDeviceListRoute'; static const String name = 'ReportDeviceListRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i13.ReportEnergyDetailView] /// [_i14.ReportEnergyDetailView]
class ReportEnergyDetailRoute extends _i21.PageRouteInfo<void> { class ReportEnergyDetailRoute extends _i22.PageRouteInfo<void> {
const ReportEnergyDetailRoute({List<_i21.PageRouteInfo>? children}) const ReportEnergyDetailRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ReportEnergyDetailRoute.name, ReportEnergyDetailRoute.name,
initialChildren: children, initialChildren: children,
...@@ -541,13 +562,13 @@ class ReportEnergyDetailRoute extends _i21.PageRouteInfo<void> { ...@@ -541,13 +562,13 @@ class ReportEnergyDetailRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ReportEnergyDetailRoute'; static const String name = 'ReportEnergyDetailRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i14.ReportIndexView] /// [_i15.ReportIndexView]
class ReportIndexRoute extends _i21.PageRouteInfo<void> { class ReportIndexRoute extends _i22.PageRouteInfo<void> {
const ReportIndexRoute({List<_i21.PageRouteInfo>? children}) const ReportIndexRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ReportIndexRoute.name, ReportIndexRoute.name,
initialChildren: children, initialChildren: children,
...@@ -555,13 +576,13 @@ class ReportIndexRoute extends _i21.PageRouteInfo<void> { ...@@ -555,13 +576,13 @@ class ReportIndexRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ReportIndexRoute'; static const String name = 'ReportIndexRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i15.ReportRoomDetailView] /// [_i16.ReportRoomDetailView]
class ReportRoomDetailRoute extends _i21.PageRouteInfo<void> { class ReportRoomDetailRoute extends _i22.PageRouteInfo<void> {
const ReportRoomDetailRoute({List<_i21.PageRouteInfo>? children}) const ReportRoomDetailRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ReportRoomDetailRoute.name, ReportRoomDetailRoute.name,
initialChildren: children, initialChildren: children,
...@@ -569,13 +590,13 @@ class ReportRoomDetailRoute extends _i21.PageRouteInfo<void> { ...@@ -569,13 +590,13 @@ class ReportRoomDetailRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ReportRoomDetailRoute'; static const String name = 'ReportRoomDetailRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i16.ReportRuleManagementView] /// [_i17.ReportRuleManagementView]
class ReportRuleManagementRoute extends _i21.PageRouteInfo<void> { class ReportRuleManagementRoute extends _i22.PageRouteInfo<void> {
const ReportRuleManagementRoute({List<_i21.PageRouteInfo>? children}) const ReportRuleManagementRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ReportRuleManagementRoute.name, ReportRuleManagementRoute.name,
initialChildren: children, initialChildren: children,
...@@ -583,16 +604,16 @@ class ReportRuleManagementRoute extends _i21.PageRouteInfo<void> { ...@@ -583,16 +604,16 @@ class ReportRuleManagementRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ReportRuleManagementRoute'; static const String name = 'ReportRuleManagementRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i17.SearchView] /// [_i18.SearchView]
class SearchRoute extends _i21.PageRouteInfo<SearchRouteArgs> { class SearchRoute extends _i22.PageRouteInfo<SearchRouteArgs> {
SearchRoute({ SearchRoute({
_i22.Key? key, _i23.Key? key,
String? searchKey, String? searchKey,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
SearchRoute.name, SearchRoute.name,
args: SearchRouteArgs( args: SearchRouteArgs(
...@@ -604,8 +625,8 @@ class SearchRoute extends _i21.PageRouteInfo<SearchRouteArgs> { ...@@ -604,8 +625,8 @@ class SearchRoute extends _i21.PageRouteInfo<SearchRouteArgs> {
static const String name = 'SearchRoute'; static const String name = 'SearchRoute';
static const _i21.PageInfo<SearchRouteArgs> page = static const _i22.PageInfo<SearchRouteArgs> page =
_i21.PageInfo<SearchRouteArgs>(name); _i22.PageInfo<SearchRouteArgs>(name);
} }
class SearchRouteArgs { class SearchRouteArgs {
...@@ -614,7 +635,7 @@ class SearchRouteArgs { ...@@ -614,7 +635,7 @@ class SearchRouteArgs {
this.searchKey, this.searchKey,
}); });
final _i22.Key? key; final _i23.Key? key;
final String? searchKey; final String? searchKey;
...@@ -625,13 +646,13 @@ class SearchRouteArgs { ...@@ -625,13 +646,13 @@ class SearchRouteArgs {
} }
/// generated route for /// generated route for
/// [_i18.ServiceDeviceDetailView] /// [_i19.ServiceDeviceDetailView]
class ServiceDeviceDetailRoute class ServiceDeviceDetailRoute
extends _i21.PageRouteInfo<ServiceDeviceDetailRouteArgs> { extends _i22.PageRouteInfo<ServiceDeviceDetailRouteArgs> {
ServiceDeviceDetailRoute({ ServiceDeviceDetailRoute({
_i22.Key? key, _i23.Key? key,
required int deviceId, required int deviceId,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
ServiceDeviceDetailRoute.name, ServiceDeviceDetailRoute.name,
args: ServiceDeviceDetailRouteArgs( args: ServiceDeviceDetailRouteArgs(
...@@ -643,8 +664,8 @@ class ServiceDeviceDetailRoute ...@@ -643,8 +664,8 @@ class ServiceDeviceDetailRoute
static const String name = 'ServiceDeviceDetailRoute'; static const String name = 'ServiceDeviceDetailRoute';
static const _i21.PageInfo<ServiceDeviceDetailRouteArgs> page = static const _i22.PageInfo<ServiceDeviceDetailRouteArgs> page =
_i21.PageInfo<ServiceDeviceDetailRouteArgs>(name); _i22.PageInfo<ServiceDeviceDetailRouteArgs>(name);
} }
class ServiceDeviceDetailRouteArgs { class ServiceDeviceDetailRouteArgs {
...@@ -653,7 +674,7 @@ class ServiceDeviceDetailRouteArgs { ...@@ -653,7 +674,7 @@ class ServiceDeviceDetailRouteArgs {
required this.deviceId, required this.deviceId,
}); });
final _i22.Key? key; final _i23.Key? key;
final int deviceId; final int deviceId;
...@@ -664,9 +685,9 @@ class ServiceDeviceDetailRouteArgs { ...@@ -664,9 +685,9 @@ class ServiceDeviceDetailRouteArgs {
} }
/// generated route for /// generated route for
/// [_i19.ServiceIndexView] /// [_i20.ServiceIndexView]
class ServiceIndexRoute extends _i21.PageRouteInfo<void> { class ServiceIndexRoute extends _i22.PageRouteInfo<void> {
const ServiceIndexRoute({List<_i21.PageRouteInfo>? children}) const ServiceIndexRoute({List<_i22.PageRouteInfo>? children})
: super( : super(
ServiceIndexRoute.name, ServiceIndexRoute.name,
initialChildren: children, initialChildren: children,
...@@ -674,18 +695,18 @@ class ServiceIndexRoute extends _i21.PageRouteInfo<void> { ...@@ -674,18 +695,18 @@ class ServiceIndexRoute extends _i21.PageRouteInfo<void> {
static const String name = 'ServiceIndexRoute'; static const String name = 'ServiceIndexRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name); static const _i22.PageInfo<void> page = _i22.PageInfo<void>(name);
} }
/// generated route for /// generated route for
/// [_i20.ServiceRoomDetailView] /// [_i21.ServiceRoomDetailView]
class ServiceRoomDetailRoute class ServiceRoomDetailRoute
extends _i21.PageRouteInfo<ServiceRoomDetailRouteArgs> { extends _i22.PageRouteInfo<ServiceRoomDetailRouteArgs> {
ServiceRoomDetailRoute({ ServiceRoomDetailRoute({
_i22.Key? key, _i23.Key? key,
required int roomId, required int roomId,
String? roomNumber, String? roomNumber,
List<_i21.PageRouteInfo>? children, List<_i22.PageRouteInfo>? children,
}) : super( }) : super(
ServiceRoomDetailRoute.name, ServiceRoomDetailRoute.name,
args: ServiceRoomDetailRouteArgs( args: ServiceRoomDetailRouteArgs(
...@@ -698,8 +719,8 @@ class ServiceRoomDetailRoute ...@@ -698,8 +719,8 @@ class ServiceRoomDetailRoute
static const String name = 'ServiceRoomDetailRoute'; static const String name = 'ServiceRoomDetailRoute';
static const _i21.PageInfo<ServiceRoomDetailRouteArgs> page = static const _i22.PageInfo<ServiceRoomDetailRouteArgs> page =
_i21.PageInfo<ServiceRoomDetailRouteArgs>(name); _i22.PageInfo<ServiceRoomDetailRouteArgs>(name);
} }
class ServiceRoomDetailRouteArgs { class ServiceRoomDetailRouteArgs {
...@@ -709,7 +730,7 @@ class ServiceRoomDetailRouteArgs { ...@@ -709,7 +730,7 @@ class ServiceRoomDetailRouteArgs {
this.roomNumber, this.roomNumber,
}); });
final _i22.Key? key; final _i23.Key? key;
final int roomId; final int roomId;
......
class DealUtils {
/// 去除多余0
static String cleanNumber(String value) {
return value.replaceAll(RegExp(r'\.?0+$'), '');
}
}
\ No newline at end of file
...@@ -99,4 +99,8 @@ class DeviceCubit extends Cubit<DeviceState> { ...@@ -99,4 +99,8 @@ class DeviceCubit extends Cubit<DeviceState> {
void clearOperationMessage() { void clearOperationMessage() {
emit(state.copyWith(operationMessage: null)); emit(state.copyWith(operationMessage: null));
} }
void selectChartTab(int index) {
emit(state.copyWith(selectedChartTabIndex: index));
}
} }
\ No newline at end of file
...@@ -53,6 +53,7 @@ class DeviceState extends Equatable { ...@@ -53,6 +53,7 @@ class DeviceState extends Equatable {
final bool isPoweringOn; final bool isPoweringOn;
final bool isPoweringOff; final bool isPoweringOff;
final String? operationMessage; final String? operationMessage;
final int selectedChartTabIndex;
const DeviceState({ const DeviceState({
this.isLoading = false, this.isLoading = false,
...@@ -61,6 +62,7 @@ class DeviceState extends Equatable { ...@@ -61,6 +62,7 @@ class DeviceState extends Equatable {
this.isPoweringOn = false, this.isPoweringOn = false,
this.isPoweringOff = false, this.isPoweringOff = false,
this.operationMessage, this.operationMessage,
this.selectedChartTabIndex = 0,
}); });
DeviceState copyWith({ DeviceState copyWith({
...@@ -70,6 +72,7 @@ class DeviceState extends Equatable { ...@@ -70,6 +72,7 @@ class DeviceState extends Equatable {
bool? isPoweringOn, bool? isPoweringOn,
bool? isPoweringOff, bool? isPoweringOff,
Object? operationMessage = _unset, Object? operationMessage = _unset,
int? selectedChartTabIndex,
}) { }) {
return DeviceState( return DeviceState(
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
...@@ -82,6 +85,8 @@ class DeviceState extends Equatable { ...@@ -82,6 +85,8 @@ class DeviceState extends Equatable {
operationMessage: identical(operationMessage, _unset) operationMessage: identical(operationMessage, _unset)
? this.operationMessage ? this.operationMessage
: operationMessage as String?, : operationMessage as String?,
selectedChartTabIndex:
selectedChartTabIndex ?? this.selectedChartTabIndex,
); );
} }
...@@ -93,5 +98,6 @@ class DeviceState extends Equatable { ...@@ -93,5 +98,6 @@ class DeviceState extends Equatable {
isPoweringOn, isPoweringOn,
isPoweringOff, isPoweringOff,
operationMessage, operationMessage,
selectedChartTabIndex,
]; ];
} }
\ No newline at end of file
...@@ -78,7 +78,11 @@ class DeviceDetailView extends StatelessWidget { ...@@ -78,7 +78,11 @@ class DeviceDetailView extends StatelessWidget {
SizedBox(height: 10.h), SizedBox(height: 10.h),
DeviceParmsBlock(deviceInfo: deviceInfo), DeviceParmsBlock(deviceInfo: deviceInfo),
SizedBox(height: 10.h), SizedBox(height: 10.h),
PowerCharBlock(deviceInfo: deviceInfo), PowerCharBlock(
deviceInfo: deviceInfo,
selectedTabIndex: state.selectedChartTabIndex,
onTabChanged: (index) => cubit.selectChartTab(index),
),
SizedBox(height: 10.h), SizedBox(height: 10.h),
_buildBottomButtons(context, cubit, state), _buildBottomButtons(context, cubit, state),
SizedBox(height: 30.h), SizedBox(height: 30.h),
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/utils/deal_utils.dart';
import 'package:smart_hotel_app/views/home/device/cubit/device_state.dart'; import 'package:smart_hotel_app/views/home/device/cubit/device_state.dart';
class DeviceParmsBlock extends StatelessWidget { class DeviceParmsBlock extends StatelessWidget {
...@@ -57,15 +58,15 @@ class DeviceParmsBlock extends StatelessWidget { ...@@ -57,15 +58,15 @@ class DeviceParmsBlock extends StatelessWidget {
); );
} }
String _formatValue(String raw) { // String _formatValue(String raw) {
final d = double.tryParse(raw); // final d = double.tryParse(raw);
if (d == null) return raw; // if (d == null) return raw;
// 去掉末尾多余的 0,整数不显示小数点 // // 去掉末尾多余的 0,整数不显示小数点
final formatted = d.toStringAsFixed(2); // final formatted = d.toStringAsFixed(2);
final parts = formatted.split('.'); // final parts = formatted.split('.');
if (parts.length == 2 && parts[1] == '00') return parts[0]; // if (parts.length == 2 && parts[1] == '00') return parts[0];
return formatted.replaceAll(RegExp(r'0+$'), '').replaceAll(RegExp(r'\.$'), ''); // return formatted.replaceAll(RegExp(r'0+$'), '').replaceAll(RegExp(r'\.$'), '');
} // }
Widget _buildParamCard(String value, String label, String unit, {bool isGreen = false}) { Widget _buildParamCard(String value, String label, String unit, {bool isGreen = false}) {
return Container( return Container(
...@@ -81,7 +82,7 @@ class DeviceParmsBlock extends StatelessWidget { ...@@ -81,7 +82,7 @@ class DeviceParmsBlock extends StatelessWidget {
TextSpan( TextSpan(
children: [ children: [
TextSpan( TextSpan(
text: _formatValue(value), text: DealUtils.cleanNumber(value),
style: TextStyle( style: TextStyle(
fontSize: 40.sp, fontSize: 40.sp,
color: isGreen ? const Color.fromRGBO(20, 184, 166, 1) color: isGreen ? const Color.fromRGBO(20, 184, 166, 1)
......
...@@ -4,17 +4,17 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; ...@@ -4,17 +4,17 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:smart_hotel_app/views/home/device/cubit/device_state.dart'; import 'package:smart_hotel_app/views/home/device/cubit/device_state.dart';
class PowerCharBlock extends StatefulWidget { class PowerCharBlock extends StatelessWidget {
final DeviceInfo deviceInfo; final DeviceInfo deviceInfo;
final int selectedTabIndex;
final ValueChanged<int> onTabChanged;
const PowerCharBlock({super.key, required this.deviceInfo}); const PowerCharBlock({
super.key,
@override required this.deviceInfo,
State<PowerCharBlock> createState() => _PowerCharBlockState(); required this.selectedTabIndex,
} required this.onTabChanged,
});
class _PowerCharBlockState extends State<PowerCharBlock> {
int _selectedIndex = 0;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -61,17 +61,17 @@ class _PowerCharBlockState extends State<PowerCharBlock> { ...@@ -61,17 +61,17 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
SizedBox( SizedBox(
height: 250.h, height: 250.h,
child: BarChart( child: BarChart(
BarChartData( BarChartData(
alignment: BarChartAlignment.spaceBetween, alignment: BarChartAlignment.spaceBetween,
maxY: _calcMaxY(_selectedIndex), maxY: _calcMaxY(selectedTabIndex),
minY: 0, minY: 0,
groupsSpace: 10, groupsSpace: 10,
barTouchData: BarTouchData(enabled: false), barTouchData: BarTouchData(enabled: false),
gridData: FlGridData( gridData: FlGridData(
show: true, show: true,
drawHorizontalLine: true, drawHorizontalLine: true,
drawVerticalLine: false, drawVerticalLine: false,
horizontalInterval: _calcInterval(_selectedIndex), horizontalInterval: _calcInterval(selectedTabIndex),
getDrawingHorizontalLine: (value) { getDrawingHorizontalLine: (value) {
return const FlLine( return const FlLine(
color: Color.fromRGBO(209, 213, 219, 1), color: Color.fromRGBO(209, 213, 219, 1),
...@@ -82,12 +82,14 @@ class _PowerCharBlockState extends State<PowerCharBlock> { ...@@ -82,12 +82,14 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
), ),
titlesData: FlTitlesData( titlesData: FlTitlesData(
show: true, show: true,
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), rightTitles:
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles:
const AxisTitles(sideTitles: SideTitles(showTitles: false)),
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
interval: _calcInterval(_selectedIndex), interval: _calcInterval(selectedTabIndex),
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
return Text( return Text(
'${value.toInt()}', '${value.toInt()}',
...@@ -103,15 +105,20 @@ class _PowerCharBlockState extends State<PowerCharBlock> { ...@@ -103,15 +105,20 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
interval: _calcBottomInterval(), interval: 1,
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
final i = value.toInt(); final i = value.toInt();
final labels = widget.deviceInfo.timeLabels; final labels = deviceInfo.timeLabels;
final label = i >= 0 && i < labels.length ? labels[i] : ''; if (i < 0 || i >= labels.length) {
return const SizedBox.shrink();
}
if (!_visibleLabelIndices.contains(i)) {
return const SizedBox.shrink();
}
return Padding( return Padding(
padding: EdgeInsets.only(top: 8.h), padding: EdgeInsets.only(top: 8.h),
child: Text( child: Text(
label, labels[i],
style: TextStyle( style: TextStyle(
color: const Color.fromRGBO(156, 163, 175, 1), color: const Color.fromRGBO(156, 163, 175, 1),
fontSize: 20.sp, fontSize: 20.sp,
...@@ -124,7 +131,7 @@ class _PowerCharBlockState extends State<PowerCharBlock> { ...@@ -124,7 +131,7 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
), ),
), ),
borderData: FlBorderData(show: false), borderData: FlBorderData(show: false),
barGroups: _buildBarGroups(_selectedIndex), barGroups: _buildBarGroups(),
), ),
), ),
), ),
...@@ -134,81 +141,99 @@ class _PowerCharBlockState extends State<PowerCharBlock> { ...@@ -134,81 +141,99 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
} }
Widget _buildTab(String title, int index) { Widget _buildTab(String title, int index) {
final isSelected = _selectedIndex == index; final isSelected = selectedTabIndex == index;
return GestureDetector( return GestureDetector(
onTap: () { onTap: () => onTabChanged(index),
setState(() {
_selectedIndex = index;
});
},
child: Container( child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
color: isSelected ? const Color.fromRGBO(219, 234, 254, 1) : Colors.transparent, color: isSelected
? const Color.fromRGBO(219, 234, 254, 1)
: Colors.transparent,
), ),
child: Text( child: Text(
title, title,
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
color: isSelected ? const Color.fromRGBO(73, 149, 234, 1) : color: isSelected
const Color.fromRGBO(100, 116, 139, 1), ? const Color.fromRGBO(73, 149, 234, 1)
: const Color.fromRGBO(100, 116, 139, 1),
), ),
), ),
), ),
); );
} }
List<BarChartGroupData> _buildBarGroups(int index) { List<BarChartGroupData> _buildBarGroups() {
final data = index == 0 ? widget.deviceInfo.powerData : widget.deviceInfo.tempData; final data = selectedTabIndex == 0
final Color mainColor = index == 0 ? deviceInfo.powerData
? const Color.fromRGBO(59, 130, 246, 1) : deviceInfo.tempData;
final Color mainColor = selectedTabIndex == 0
? const Color.fromRGBO(80, 162, 255, 1)
: const Color.fromRGBO(251, 191, 36, 1); : const Color.fromRGBO(251, 191, 36, 1);
return List.generate( return List.generate(data.length, (i) {
data.length, if (data[i] == 0) return BarChartGroupData(x: i);
(i) {
if (data[i] == 0) return BarChartGroupData(x: i); return BarChartGroupData(
return BarChartGroupData( x: i,
x: i, barRods: [
barRods: [ BarChartRodData(
BarChartRodData( toY: data[i].toDouble(),
toY: data[i].toDouble(), color: mainColor,
color: mainColor, width: 16.w,
width: 22.w, borderRadius: BorderRadius.vertical(top: Radius.circular(8.r)),
borderRadius: BorderRadius.vertical(top: Radius.circular(8.r)), ),
), ],
], );
); }).where((group) => group.barRods.isNotEmpty).toList();
},
).where((group) => group.barRods.isNotEmpty).toList();
} }
double _calcMaxY(int index) { double _calcMaxY(int index) {
final data = index == 0 ? widget.deviceInfo.powerData : widget.deviceInfo.tempData; final data = index == 0 ? deviceInfo.powerData : deviceInfo.tempData;
if (data.isEmpty) return 100; if (data.isEmpty) return 100;
final max = data.reduce((a, b) => a > b ? a : b).toDouble(); final max = data.reduce((a, b) => a > b ? a : b).toDouble();
if (max == 0) return 100; if (max == 0) return 100;
// 向上取整到最近的 nice number,并留 20% 余量
final raw = max * 1.2; final raw = max * 1.2;
final magnitude = pow(10, (log(raw) / ln10).floor()).toDouble(); final magnitude = pow(10, (log(raw) / ln10).floor()).toDouble();
final normalized = raw / magnitude; final normalized = raw / magnitude;
final nice = normalized <= 1 ? 1 final nice =
: normalized <= 2 ? 2 normalized <= 1 ? 1 :
: normalized <= 5 ? 5 normalized <= 2 ? 2 :
: 10; normalized <= 5 ? 5 : 10;
return nice * magnitude; return nice * magnitude;
} }
Set<int> get _visibleLabelIndices {
final length = deviceInfo.timeLabels.length;
if (length <= 10) {
return Set.from(List.generate(length, (i) => i));
}
final isOdd = length % 2 == 1;
if (isOdd) {
// 基数:7 个标签,首尾都显示,中间 5 个均分 6 段
final step = (length - 1) / 6;
final indices = <int>{};
for (int i = 0; i <= 6; i++) {
indices.add((step * i).round());
}
return indices;
} else {
// 偶数:6 个标签,显示首和倒数第二个,中间 4 个均分 5 段
final step = (length - 2) / 5;
final indices = <int>{};
for (int i = 0; i <= 5; i++) {
indices.add((step * i).round());
}
return indices;
}
}
double _calcInterval(int index) { double _calcInterval(int index) {
return _calcMaxY(index) / 5; return _calcMaxY(index) / 5;
} }
double _calcBottomInterval() {
final length = widget.deviceInfo.timeLabels.length;
if (length <= 6) return 1;
if (length <= 12) return 2;
if (length <= 24) return 3;
return (length / 6).ceilToDouble();
}
} }
\ No newline at end of file
...@@ -5,6 +5,7 @@ import 'package:smart_hotel_app/repositories/alert_dashboard_repository.dart'; ...@@ -5,6 +5,7 @@ import 'package:smart_hotel_app/repositories/alert_dashboard_repository.dart';
import 'package:smart_hotel_app/repositories/alert_detail_repository.dart'; import 'package:smart_hotel_app/repositories/alert_detail_repository.dart';
import 'package:smart_hotel_app/services/alert_dashboard_service.dart'; import 'package:smart_hotel_app/services/alert_dashboard_service.dart';
import 'package:smart_hotel_app/services/alert_detail_service.dart'; import 'package:smart_hotel_app/services/alert_detail_service.dart';
import 'package:smart_hotel_app/utils/deal_utils.dart';
import 'package:smart_hotel_app/views/home/index/cubit/home_index_state.dart'; import 'package:smart_hotel_app/views/home/index/cubit/home_index_state.dart';
class HomeIndexCubit extends Cubit<HomeIndexState> { class HomeIndexCubit extends Cubit<HomeIndexState> {
...@@ -73,8 +74,9 @@ class HomeIndexCubit extends Cubit<HomeIndexState> { ...@@ -73,8 +74,9 @@ class HomeIndexCubit extends Cubit<HomeIndexState> {
icon: _mapDeviceIcon(d.deviceTypeIcon), icon: _mapDeviceIcon(d.deviceTypeIcon),
title: d.deviceName, title: d.deviceName,
subtitle: _buildDeviceSubtitle(d), subtitle: _buildDeviceSubtitle(d),
status: d.onlineStatus == '1' ? d.runStatusText : '离线', // status: d.onlineStatus == '1' ? d.runStatusText : '离线',
statusColor: _mapStatusColor(d.onlineStatus, d.runStatus), status: d.runStatusText,
statusColor: _mapStatusColor(d.runStatus),
); );
} }
...@@ -94,28 +96,26 @@ class HomeIndexCubit extends Cubit<HomeIndexState> { ...@@ -94,28 +96,26 @@ class HomeIndexCubit extends Cubit<HomeIndexState> {
} }
String _buildDeviceSubtitle(DeviceItemBO d) { String _buildDeviceSubtitle(DeviceItemBO d) {
final parts = <String>[]; return [
if (d.roomName.isNotEmpty) parts.add(d.roomName); if (d.roomName.isNotEmpty) d.roomName,
if (d.temperature.isNotEmpty) parts.add('${d.temperature}°C'); if (d.temperature.isNotEmpty) '${DealUtils.cleanNumber(d.temperature)}°C',
if (d.voltage.isNotEmpty) parts.add('${d.voltage}V'); if (d.voltage.isNotEmpty) '${DealUtils.cleanNumber(d.voltage)}V',
if (d.power.isNotEmpty) parts.add('${d.power}kW'); if (d.power.isNotEmpty) '${DealUtils.cleanNumber(d.power)}kW',
if (d.current.isNotEmpty) parts.add('${d.current}A'); if (d.current.isNotEmpty) '${DealUtils.cleanNumber(d.current)}A',
return parts.isNotEmpty ? parts.join('·') : ''; ].join('·');
} }
Color _mapStatusColor(String onlineStatus, String runStatus) { Color _mapStatusColor(String runStatus) {
if (onlineStatus == '0') {
return const Color.fromRGBO(102, 102, 102, 1.0);
}
switch (runStatus) { switch (runStatus) {
case 'alert': case 'normal':
case 'alarm': return const Color.fromRGBO(20, 184, 166, 1.0);
return const Color.fromRGBO(255, 77, 79, 1.0);
case 'warning': case 'warning':
case '注意': return const Color.fromRGBO(250, 204, 21, 1.0);
return const Color.fromRGBO(255, 193, 7, 1.0); case 'fault':
return const Color.fromRGBO(255, 77, 79, 1.0);
case 'offline':
default: default:
return const Color.fromRGBO(26, 188, 156, 1.0); return const Color.fromRGBO(102, 102, 102, 1.0);
} }
} }
} }
...@@ -20,26 +20,30 @@ class HomeView extends StatefulWidget { ...@@ -20,26 +20,30 @@ class HomeView extends StatefulWidget {
} }
class _HomeViewState extends State<HomeView> with AutoRouteAwareStateMixin<HomeView> { class _HomeViewState extends State<HomeView> with AutoRouteAwareStateMixin<HomeView> {
TabsRouter? _tabsRouter;
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
// Subscribe to tab router events // 缓存引用,避免在 dispose 中通过 context 查找(此时树已不稳定)
final tabsRouter = AutoTabsRouter.of(context); final newRouter = AutoTabsRouter.of(context);
tabsRouter.addListener(_onTabChange); if (newRouter != _tabsRouter) {
_tabsRouter?.removeListener(_onTabChange);
_tabsRouter = newRouter;
_tabsRouter?.addListener(_onTabChange);
}
} }
@override @override
void dispose() { void dispose() {
final tabsRouter = AutoTabsRouter.of(context); _tabsRouter?.removeListener(_onTabChange);
tabsRouter.removeListener(_onTabChange);
super.dispose(); super.dispose();
} }
void _onTabChange() { void _onTabChange() {
final tabsRouter = AutoTabsRouter.of(context); if (!mounted) return;
// Check if this tab is now active
if (tabsRouter.activeIndex == 0) { if (_tabsRouter?.activeIndex == 0) {
// Reload data when tab is activated
context.read<HomeIndexCubit>().reloadDashboard(); context.read<HomeIndexCubit>().reloadDashboard();
} }
} }
...@@ -88,7 +92,10 @@ class _HomeViewState extends State<HomeView> with AutoRouteAwareStateMixin<HomeV ...@@ -88,7 +92,10 @@ class _HomeViewState extends State<HomeView> with AutoRouteAwareStateMixin<HomeV
List<Widget> _buildAlertBlocks(List<AlertItemBO> alerts) { List<Widget> _buildAlertBlocks(List<AlertItemBO> alerts) {
final blocks = <Widget>[]; final blocks = <Widget>[];
for (final alert in alerts) { for (final alert in alerts) {
final location = '${alert.roomName}·${alert.deviceName}'; final location = [alert.roomName, alert.deviceName]
.where((s) => s.isNotEmpty)
.join('·');
switch (alert.alertCategory) { switch (alert.alertCategory) {
case 'temperature': case 'temperature':
blocks.addAll([ blocks.addAll([
......
...@@ -107,7 +107,7 @@ class TemperatureBlock extends StatelessWidget { ...@@ -107,7 +107,7 @@ class TemperatureBlock extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
currentTemperature, currentTemperature.isNotEmpty ? currentTemperature : '--℃',
style: TextStyle( style: TextStyle(
fontSize: 40.sp, fontSize: 40.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
...@@ -130,7 +130,7 @@ class TemperatureBlock extends StatelessWidget { ...@@ -130,7 +130,7 @@ class TemperatureBlock extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
currentVoltage, currentVoltage.isNotEmpty ? currentVoltage : '--V',
style: TextStyle( style: TextStyle(
fontSize: 40.sp, fontSize: 40.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
...@@ -153,7 +153,7 @@ class TemperatureBlock extends StatelessWidget { ...@@ -153,7 +153,7 @@ class TemperatureBlock extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
currentCurrent, currentCurrent.isNotEmpty ? currentCurrent : '--A',
style: TextStyle( style: TextStyle(
fontSize: 40.sp, fontSize: 40.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
......
...@@ -177,7 +177,6 @@ class VoltageOperateBlock extends StatelessWidget { ...@@ -177,7 +177,6 @@ class VoltageOperateBlock extends StatelessWidget {
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
), ),
child: Container( child: Container(
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
...@@ -186,33 +185,42 @@ class VoltageOperateBlock extends StatelessWidget { ...@@ -186,33 +185,42 @@ class VoltageOperateBlock extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text(
voltageAlarmTitle,
style: TextStyle(
fontSize: 30.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
GestureDetector( GestureDetector(
onTap: () => Navigator.of(dialogContext).pop(), onTap: () => Navigator.of(dialogContext).pop(),
child: Icon( child: Container(
Icons.close, margin: EdgeInsets.only(top: 20.h, right: 20.h),
color: const Color.fromRGBO(100, 116, 139, 1.0), padding: EdgeInsets.symmetric(horizontal: 2.w, vertical: 2.h),
size: 32.sp, decoration: BoxDecoration(
), shape: BoxShape.circle,
border: Border.all(
width: 2.w,
color: const Color.fromRGBO(100, 116, 139, 1.0),
),
),
child: Icon(
Icons.close,
color: const Color.fromRGBO(100, 116, 139, 1.0),
size: 32.sp,
),
)
), ),
], ],
), ),
SizedBox(height: 16.h), Text(
voltageAlarmTitle,
style: TextStyle(
fontSize: 30.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
SizedBox(height: 20.h),
Container( Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.symmetric( margin: EdgeInsets.symmetric(horizontal: 40.w),
horizontal: 20.w, padding: EdgeInsets.symmetric(horizontal: 30.w, vertical: 30.h),
vertical: 20.h,
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(242, 243, 245, 1), color: const Color.fromRGBO(242, 243, 245, 1),
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
...@@ -230,7 +238,7 @@ class VoltageOperateBlock extends StatelessWidget { ...@@ -230,7 +238,7 @@ class VoltageOperateBlock extends StatelessWidget {
), ),
SizedBox(height: 12.h), SizedBox(height: 12.h),
Text( Text(
'1.检查输入电压是否正常;\n2.确认设备是否正常运行;\n3.若异常,请联系电工。', '1.检查设备是否通风良好;\n2.确认设备负载是否正常;\n3.若异常,请联系电工。',
style: TextStyle( style: TextStyle(
fontSize: 26.sp, fontSize: 26.sp,
color: const Color.fromRGBO(100, 116, 139, 1.0), color: const Color.fromRGBO(100, 116, 139, 1.0),
...@@ -240,8 +248,8 @@ class VoltageOperateBlock extends StatelessWidget { ...@@ -240,8 +248,8 @@ class VoltageOperateBlock extends StatelessWidget {
], ],
), ),
), ),
SizedBox(height: 20.h),
GestureDetector( GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () async { onTap: () async {
Navigator.of(dialogContext).pop(); Navigator.of(dialogContext).pop();
try { try {
...@@ -256,19 +264,13 @@ class VoltageOperateBlock extends StatelessWidget { ...@@ -256,19 +264,13 @@ class VoltageOperateBlock extends StatelessWidget {
} }
}, },
child: Container( child: Container(
width: double.infinity, padding: EdgeInsets.symmetric(horizontal: 30.w, vertical: 30.h),
height: 72.h, child: Text(
decoration: BoxDecoration( '确认',
color: const Color.fromRGBO(66, 165, 245, 1.0), style: TextStyle(
borderRadius: BorderRadius.circular(12.r), fontSize: 28.sp,
), color: const Color.fromRGBO(73, 149, 234, 1.0),
child: Center( fontWeight: FontWeight.bold,
child: Text(
'确认',
style: TextStyle(
fontSize: 28.sp,
color: Colors.white,
),
), ),
), ),
), ),
......
...@@ -133,7 +133,7 @@ class DeviceOverviewCard extends StatelessWidget { ...@@ -133,7 +133,7 @@ class DeviceOverviewCard extends StatelessWidget {
), ),
), ),
Text( Text(
value, value.isNotEmpty ? value : '--',
style: TextStyle( style: TextStyle(
fontSize: 28.sp, fontSize: 28.sp,
color: const Color.fromRGBO(100, 116, 139, 1.0), color: const Color.fromRGBO(100, 116, 139, 1.0),
......
...@@ -37,33 +37,28 @@ class InspectionTopologyCubit extends Cubit<InspectionTopologyState> { ...@@ -37,33 +37,28 @@ class InspectionTopologyCubit extends Cubit<InspectionTopologyState> {
void _emitFromTopology(DeviceTopologyBO topology) { void _emitFromTopology(DeviceTopologyBO topology) {
final info = topology.deviceInfo; final info = topology.deviceInfo;
final nodes = topology.treeNodes; final treeNodes = topology.treeNodes;
final rootNode = _buildTopologyTree(nodes); if (treeNodes.isEmpty) {
emit(InspectionTopologyState(
deviceName: info.deviceName,
deviceModel: '${info.deviceCode}·${info.deviceLocation}',
));
return;
}
final rootNode = _buildTopologyTree(treeNodes);
emit(InspectionTopologyState( emit(InspectionTopologyState(
deviceName: info.deviceName, deviceName: info.deviceName,
deviceModel: '${info.deviceCode}·${info.deviceLocation}', deviceModel: '${info.deviceCode}·${info.deviceLocation}',
topologyNodes: [rootNode], topologyNodes: [rootNode],
deviceCount: _countAllNodes(rootNode), deviceCount: _countAllNodes(rootNode),
connectionCount: _countConnections(rootNode), connectionCount: _countConnections(rootNode),
// statusText:
)); ));
} }
/// 根据 gatewayId 将扁平节点列表构建为树结构,并自动计算布局位置 /// 根据 gatewayId 将扁平节点列表构建为树结构,并自动计算布局位置
TopologyNode _buildTopologyTree(List<TreeNodeBO> nodes) { TopologyNode _buildTopologyTree(List<TreeNodeBO> nodes) {
if (nodes.isEmpty) {
return const TopologyNode(
id: '0',
name: '未知设备',
status: 'offline',
children: [],
x: 0.5,
y: 0.08,
);
}
// 构建子节点映射表:parent deviceId -> [child TreeNodeBO] // 构建子节点映射表:parent deviceId -> [child TreeNodeBO]
final childrenMap = <int, List<TreeNodeBO>>{}; final childrenMap = <int, List<TreeNodeBO>>{};
final nodeMap = <int, TreeNodeBO>{}; final nodeMap = <int, TreeNodeBO>{};
......
...@@ -55,7 +55,7 @@ class InspectionTopologyPage extends StatelessWidget { ...@@ -55,7 +55,7 @@ class InspectionTopologyPage extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
if (state.isLoading) { if (state.isLoading) {
return const Center( return const Center(
child: CircularProgressIndicator(color: const Color.fromRGBO(66, 165, 245, 1.0)), child: CircularProgressIndicator(color: Color.fromRGBO(66, 165, 245, 1.0)),
); );
} }
...@@ -124,7 +124,7 @@ class InspectionTopologyPage extends StatelessWidget { ...@@ -124,7 +124,7 @@ class InspectionTopologyPage extends StatelessWidget {
if (state.selectedNode != null) if (state.selectedNode != null)
DeviceDetailDialog( DeviceDetailDialog(
node: state.selectedNode!, node: state.selectedNode!,
curentState: state, currentState: state,
onClose: () => onClose: () =>
context.read<InspectionTopologyCubit>().selectNode(null), context.read<InspectionTopologyCubit>().selectNode(null),
), ),
......
...@@ -6,13 +6,13 @@ import '../cubit/inspection_topology_state.dart'; ...@@ -6,13 +6,13 @@ import '../cubit/inspection_topology_state.dart';
class DeviceDetailDialog extends StatelessWidget { class DeviceDetailDialog extends StatelessWidget {
final TopologyNode node; final TopologyNode node;
final InspectionTopologyState curentState; final InspectionTopologyState currentState;
final VoidCallback onClose; final VoidCallback onClose;
const DeviceDetailDialog({ const DeviceDetailDialog({
super.key, super.key,
required this.node, required this.node,
required this.curentState, required this.currentState,
required this.onClose, required this.onClose,
}); });
...@@ -26,7 +26,7 @@ class DeviceDetailDialog extends StatelessWidget { ...@@ -26,7 +26,7 @@ class DeviceDetailDialog extends StatelessWidget {
child: GestureDetector( child: GestureDetector(
onTap: onClose, onTap: onClose,
child: Container( child: Container(
color: Colors.black.withOpacity(0.5), color: Colors.black.withValues(alpha: 0.5),
), ),
), ),
), ),
...@@ -91,7 +91,7 @@ class DeviceDetailDialog extends StatelessWidget { ...@@ -91,7 +91,7 @@ class DeviceDetailDialog extends StatelessWidget {
), ),
SizedBox(height: 12.h), SizedBox(height: 12.h),
Text( Text(
curentState.deviceModel, currentState.deviceModel,
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
color: const Color.fromRGBO(148, 163, 184, 1), color: const Color.fromRGBO(148, 163, 184, 1),
......
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/blocs/auth/auth_bloc.dart'; import 'package:smart_hotel_app/blocs/auth/auth_bloc.dart';
import 'package:smart_hotel_app/blocs/auth/auth_event.dart'; import 'package:smart_hotel_app/blocs/auth/auth_event.dart';
...@@ -8,6 +10,7 @@ import 'package:smart_hotel_app/views/login/cubit/login_state.dart'; ...@@ -8,6 +10,7 @@ import 'package:smart_hotel_app/views/login/cubit/login_state.dart';
class LoginCubit extends Cubit<LoginState> { class LoginCubit extends Cubit<LoginState> {
final AuthBloc authBloc; final AuthBloc authBloc;
final StorageService storageService; final StorageService storageService;
late final StreamSubscription _authSubscription;
LoginCubit({ LoginCubit({
required this.authBloc, required this.authBloc,
...@@ -17,18 +20,32 @@ class LoginCubit extends Cubit<LoginState> { ...@@ -17,18 +20,32 @@ class LoginCubit extends Cubit<LoginState> {
} }
void _listenAuthState() { void _listenAuthState() {
authBloc.stream.listen((authState) { _authSubscription = authBloc.stream.listen(
if (authState is AuthFailure) { _onAuthStateChanged,
emit(state.copyWith(isLoading: false, error: authState.error)); onError: _onAuthError,
} else if (authState is AuthLoading) { );
emit(state.copyWith(isLoading: true, error: null)); }
} else if (authState is AuthSuccess) {
emit(state.copyWith(isLoading: false, error: null)); void _onAuthStateChanged(AuthState authState) {
} // 检查 Cubit 是否已关闭
}); if (isClosed) return;
if (authState is AuthFailure) {
emit(state.copyWith(isLoading: false, error: authState.error));
} else if (authState is AuthLoading) {
emit(state.copyWith(isLoading: true, error: null));
} else if (authState is AuthSuccess) {
emit(state.copyWith(isLoading: false, error: null));
}
}
void _onAuthError(error) {
if (isClosed) return;
emit(state.copyWith(isLoading: false, error: error.toString()));
} }
void toggleRememberPassword(bool value) { void toggleRememberPassword(bool value) {
if (isClosed) return;
emit(state.copyWith(rememberPassword: value)); emit(state.copyWith(rememberPassword: value));
} }
...@@ -53,6 +70,8 @@ class LoginCubit extends Cubit<LoginState> { ...@@ -53,6 +70,8 @@ class LoginCubit extends Cubit<LoginState> {
} }
Future<void> loadRememberCredentials() async { Future<void> loadRememberCredentials() async {
if (isClosed) return;
final credentials = await storageService.getRememberCredentials(); final credentials = await storageService.getRememberCredentials();
if (credentials['username'] != null) { if (credentials['username'] != null) {
emit(state.copyWith( emit(state.copyWith(
...@@ -66,4 +85,11 @@ class LoginCubit extends Cubit<LoginState> { ...@@ -66,4 +85,11 @@ class LoginCubit extends Cubit<LoginState> {
void forgotPwd() { void forgotPwd() {
// TODO: 跳转到忘记密码页面 // TODO: 跳转到忘记密码页面
} }
@override
Future<void> close() {
_authSubscription.cancel();
return super.close();
}
} }
\ No newline at end of file
...@@ -17,7 +17,7 @@ class BtnLogin extends StatelessWidget { ...@@ -17,7 +17,7 @@ class BtnLogin extends StatelessWidget {
width: double.infinity, width: double.infinity,
height: 104.h, height: 104.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color.fromRGBO(73, 149, 234, 1), color: const Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(40.w), borderRadius: BorderRadius.circular(40.w),
), ),
child: ElevatedButton( child: ElevatedButton(
......
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
@RoutePage()
class AboutView extends StatelessWidget {
const AboutView({super.key});
Widget _buildRichInfo() {
TextStyle highlightStyle = TextStyle(
fontSize: 30.sp,
color: const Color.fromRGBO(15, 23, 42, 1),
fontWeight: FontWeight.w600,
);
return RichText(
text: TextSpan(
style: TextStyle(
fontSize: 30.sp,
color: const Color.fromRGBO(100, 116, 139, 1),
),
children: [
TextSpan(text: '湖北洲语科技有限公司', style: highlightStyle),
const TextSpan(text: '成立于2020年06月30日,'
'注册地位于武汉市汉阳区龙阳大道98号武汉惠誉大厦6层(1)商号'),
TextSpan(text: '601-603', style: highlightStyle),
const TextSpan(text: ',''法定代表人为'),
TextSpan(text: '严高波', style: highlightStyle),
const TextSpan(text: '。经营范围包括光电、信息、网络技术开发、技术咨询、'
'技术服务、技术转让;电子产品、通讯设施(不含无线发射装置及卫星地面接收装置)、'
'光机电一体化设备技术研发、批发、零售;数据处理及存储服务;计算机软硬件技术开发、'
'技术咨询、技术服务;计算机系统集成;商务信息咨询(不含商务调查);'
'企业管理咨询;市场营销策划;策划创意服务;展示展览服务;会议会展服务;'
'文化艺术交流活动策划;货物或技术进出口(国家禁止或涉及行政审批的货物和技术进出口除外);'
'对农业项目的投资;对生态旅游项目的投资;安防设备、电子产品安装;'
'网络工程、弱电工程、通信工程、楼宇智能化工程、道路工程、园林绿化工程、建筑工程施工;'
'为建筑工程提供劳务服务(涉及许可经营项目,应取得相关部门许可后方可经营)。'),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(242, 243, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios,
color: Color.fromRGBO(100, 116, 139, 1)),
onPressed: () => context.maybePop(),
),
title: Text(
'关于',
style: TextStyle(
color: const Color.fromRGBO(15, 23, 42, 1),
fontSize: 32.sp,
fontWeight: FontWeight.w600,
),
),
centerTitle: true,
),
body: SingleChildScrollView(
padding: EdgeInsets.all(28.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
padding: EdgeInsets.all(28.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'公司简介',
style: TextStyle(
fontSize: 30.sp,
fontWeight: FontWeight.w600,
color: const Color.fromRGBO(15, 23, 42, 1),
),
),
SizedBox(height: 20.h),
_buildRichInfo(),
],
),
),
],
),
),
);
}
}
\ No newline at end of file
...@@ -28,7 +28,7 @@ class ProfileCubit extends Cubit<ProfileState> { ...@@ -28,7 +28,7 @@ class ProfileCubit extends Cubit<ProfileState> {
const MenuItem(icon: 'lib/assets/icon/help_bg.png', title: '帮助'), const MenuItem(icon: 'lib/assets/icon/help_bg.png', title: '帮助'),
const MenuItem(icon: 'lib/assets/icon/about_bg.png', title: '关于'), const MenuItem(icon: 'lib/assets/icon/about_bg.png', title: '关于'),
const MenuItem(icon: 'lib/assets/icon/exit_login_bg.png', title: '退出登录'), const MenuItem(icon: 'lib/assets/icon/exit_login_bg.png', title: '退出登录'),
const MenuItem(icon: 'lib/assets/icon/logout_account_bg.png', title: '注销账号'), // const MenuItem(icon: 'lib/assets/icon/logout_account_bg.png', title: '注销账号'),
], ],
)); ));
} }
......
...@@ -55,8 +55,7 @@ class _ProfileContent extends StatelessWidget { ...@@ -55,8 +55,7 @@ class _ProfileContent extends StatelessWidget {
child: ProfileMenuBlock( child: ProfileMenuBlock(
menuList: state.menuList, menuList: state.menuList,
onLogout: () { onLogout: () {
context.read<AuthBloc>() _showHandleDialog(context);
.add(const AuthLogoutRequestedEvent());
}, },
), ),
), ),
...@@ -70,4 +69,100 @@ class _ProfileContent extends StatelessWidget { ...@@ -70,4 +69,100 @@ class _ProfileContent extends StatelessWidget {
}, },
); );
} }
void _showHandleDialog(BuildContext context) {
showDialog(
context: context,
barrierDismissible: true,
builder: (dialogContext) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24.r),
),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 28.w, vertical: 28.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.r),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'温馨提示',
style: TextStyle(
fontSize: 34.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
SizedBox(height: 30.h),
Text(
'确定退出登录吗?',
style: TextStyle(
fontSize: 32.sp,
color: Colors.black,
),
),
SizedBox(height: 50.h),
Row(
spacing: 28.w,
children: [
Expanded(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(dialogContext).pop();
},
child: Container(
height: 80.h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color.fromRGBO(229, 241, 255, 1),
borderRadius: BorderRadius.circular(16.r),
),
child: Text(
'取消',
style: TextStyle(
fontSize: 32.sp,
color: const Color.fromRGBO(100, 116, 139, 1),
),
),
),
)
),
Expanded(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(dialogContext).pop();
context.read<AuthBloc>().add(const AuthLogoutRequestedEvent());
},
child: Container(
height: 80.h,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(16.r),
),
child: Text(
'确定',
style: TextStyle(
fontSize: 32.sp,
color: Colors.white,
),
),
),
)
),
],
),
],
),
),
);
},
);
}
} }
...@@ -73,6 +73,11 @@ class ProfileMenuBlock extends StatelessWidget { ...@@ -73,6 +73,11 @@ class ProfileMenuBlock extends StatelessWidget {
case '告警信息': case '告警信息':
context.pushRoute(const AbnormalListRoute()); context.pushRoute(const AbnormalListRoute());
break; break;
case '帮助':
break;
case '关于':
context.pushRoute(const AboutRoute());
break;
case '退出登录': case '退出登录':
onLogout?.call(); onLogout?.call();
break; break;
......
...@@ -20,26 +20,29 @@ class ReportIndexView extends StatefulWidget { ...@@ -20,26 +20,29 @@ class ReportIndexView extends StatefulWidget {
} }
class _ReportIndexViewState extends State<ReportIndexView> with AutoRouteAwareStateMixin<ReportIndexView> { class _ReportIndexViewState extends State<ReportIndexView> with AutoRouteAwareStateMixin<ReportIndexView> {
TabsRouter? _tabsRouter;
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
// Subscribe to tab router events final newRouter = AutoTabsRouter.of(context);
final tabsRouter = AutoTabsRouter.of(context); if (newRouter != _tabsRouter) {
tabsRouter.addListener(_onTabChange); _tabsRouter?.removeListener(_onTabChange);
_tabsRouter = newRouter;
_tabsRouter?.addListener(_onTabChange);
}
} }
@override @override
void dispose() { void dispose() {
final tabsRouter = AutoTabsRouter.of(context); _tabsRouter?.removeListener(_onTabChange);
tabsRouter.removeListener(_onTabChange);
super.dispose(); super.dispose();
} }
void _onTabChange() { void _onTabChange() {
final tabsRouter = AutoTabsRouter.of(context); if (!mounted) return;
// Check if this tab is now active (index 2)
if (tabsRouter.activeIndex == 2) { if (_tabsRouter?.activeIndex == 2) {
// Reload data when tab is activated
context.read<ReportIndexCubit>().reloadData(); context.read<ReportIndexCubit>().reloadData();
} }
} }
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/utils/deal_utils.dart';
class ReportMetricsBlock extends StatelessWidget { class ReportMetricsBlock extends StatelessWidget {
final Map<String, dynamic> reportMetrics; final Map<String, dynamic> reportMetrics;
...@@ -16,7 +17,7 @@ class ReportMetricsBlock extends StatelessWidget { ...@@ -16,7 +17,7 @@ class ReportMetricsBlock extends StatelessWidget {
Expanded( Expanded(
child: _buildMetricCard( child: _buildMetricCard(
title: '今日用电', title: '今日用电',
value: powerUsage['value'], value: DealUtils.cleanNumber(powerUsage['value'] as String),
unit: powerUsage['unit'] as String, unit: powerUsage['unit'] as String,
changeText: powerUsage['changeText'] as String, changeText: powerUsage['changeText'] as String,
changeColor: const Color.fromRGBO(20, 184, 166, 1), changeColor: const Color.fromRGBO(20, 184, 166, 1),
...@@ -86,6 +87,7 @@ class ReportMetricsBlock extends StatelessWidget { ...@@ -86,6 +87,7 @@ class ReportMetricsBlock extends StatelessWidget {
children: [ children: [
Text( Text(
value, value,
// cleanNumber(value),
style: TextStyle( style: TextStyle(
fontSize: 40.sp, fontSize: 40.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
......
...@@ -31,6 +31,8 @@ class RoomReportCubit extends Cubit<RoomReportState> { ...@@ -31,6 +31,8 @@ class RoomReportCubit extends Cubit<RoomReportState> {
} }
void selectFloor(int index) { void selectFloor(int index) {
if (state.selectedFloorIndex == index) return;
final floorId = state.floors[index].floorId; final floorId = state.floors[index].floorId;
emit(state.copyWith(selectedFloorIndex: index)); emit(state.copyWith(selectedFloorIndex: index));
loadData(floorId: floorId); loadData(floorId: floorId);
......
...@@ -23,54 +23,6 @@ class ReportRoomDetailView extends StatelessWidget { ...@@ -23,54 +23,6 @@ class ReportRoomDetailView extends StatelessWidget {
), ),
child: BlocBuilder<RoomReportCubit, RoomReportState>( child: BlocBuilder<RoomReportCubit, RoomReportState>(
builder: (context, state) { builder: (context, state) {
if (state.isLoading && state.floors.isEmpty) {
return Scaffold(
backgroundColor: const Color.fromRGBO(242, 243, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => context.maybePop(),
),
title: Text(
'客房状态总览',
style: TextStyle(
color: Colors.black,
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
centerTitle: true,
),
body: const Center(child: CircularProgressIndicator(color: Color.fromRGBO(66, 165, 245, 1.0))),
);
}
if (state.error != null && state.floors.isEmpty) {
return Scaffold(
backgroundColor: const Color.fromRGBO(242, 243, 245, 1),
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () => context.maybePop(),
),
title: Text(
'客房状态总览',
style: TextStyle(
color: Colors.black,
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
centerTitle: true,
),
body: Center(child: Text('加载失败: ${state.error}')),
);
}
return Scaffold( return Scaffold(
backgroundColor: const Color.fromRGBO(242, 243, 245, 1), backgroundColor: const Color.fromRGBO(242, 243, 245, 1),
appBar: AppBar( appBar: AppBar(
...@@ -78,9 +30,7 @@ class ReportRoomDetailView extends StatelessWidget { ...@@ -78,9 +30,7 @@ class ReportRoomDetailView extends StatelessWidget {
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back_ios, color: Colors.black), icon: const Icon(Icons.arrow_back_ios, color: Colors.black),
onPressed: () { onPressed: () => context.maybePop(),
context.maybePop();
},
), ),
title: Text( title: Text(
'客房状态总览', '客房状态总览',
...@@ -92,58 +42,71 @@ class ReportRoomDetailView extends StatelessWidget { ...@@ -92,58 +42,71 @@ class ReportRoomDetailView extends StatelessWidget {
), ),
centerTitle: true, centerTitle: true,
), ),
body: SingleChildScrollView( body: _buildBody(context, state),
child: Column( );
children: [ },
Padding( ),
padding: EdgeInsets.symmetric(horizontal: 28.w), );
child: Column( }
children: [
SizedBox(height: 10.h), Widget _buildBody(BuildContext context, RoomReportState state) {
if (state.floors.isNotEmpty) if (state.isLoading && state.floors.isEmpty) {
Container( return const Center(child: CircularProgressIndicator(color: Color.fromRGBO(66, 165, 245, 1)));
decoration: BoxDecoration( }
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(24.r)), if (state.error != null && state.floors.isEmpty) {
), return Center(child: Text('加载失败: ${state.error}'));
child: FloorSelector( }
floorNames: state.floors.map((f) => f.floorName).toList(),
selectedIndex: state.selectedFloorIndex, return SingleChildScrollView(
), child: Column(
), children: [
if (state.floors.isNotEmpty && state.selectedFloorIndex < state.floors.length) Padding(
Container( padding: EdgeInsets.symmetric(horizontal: 28.w),
decoration: BoxDecoration( child: Column(
color: Colors.white, children: [
borderRadius: BorderRadius.vertical(bottom: Radius.circular(24.r)), SizedBox(height: 10.h),
), if (state.floors.isNotEmpty)
padding: EdgeInsets.only(bottom: 28.w), Container(
child: RoomGrid(rooms: state.roomGrid), decoration: BoxDecoration(
), color: Colors.white,
SizedBox(height: 10.h), borderRadius: BorderRadius.vertical(top: Radius.circular(24.r)),
StatusStats(summary: state.summary), ),
SizedBox(height: 10.h), child: FloorSelector(
if (state.isLoading) floorNames: state.floors.map((f) => f.floorName).toList(),
const Padding( selectedIndex: state.selectedFloorIndex,
padding: EdgeInsets.all(16.0),
child: Center(child: CircularProgressIndicator(color: const Color.fromRGBO(66, 165, 245, 1.0))),
),
...state.detailRooms.map((room) {
return Padding(
padding: EdgeInsets.only(bottom: 10.h),
child: RoomDetailCard(room: room),
);
}).toList(),
SizedBox(height: 10.h),
],
), ),
), ),
], if (state.floors.isNotEmpty && state.selectedFloorIndex < state.floors.length)
), Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(bottom: Radius.circular(24.r)),
),
padding: EdgeInsets.only(bottom: 28.w),
child: RoomGrid(rooms: state.roomGrid),
),
SizedBox(height: 10.h),
StatusStats(summary: state.summary),
SizedBox(height: 10.h),
if (state.isLoading)
const Padding(
padding: EdgeInsets.all(16.0),
child: Center(child: CircularProgressIndicator(color: Color.fromRGBO(66, 165, 245, 1.0))),
),
...state.detailRooms.map((room) {
return Padding(
padding: EdgeInsets.only(bottom: 10.h),
child: RoomDetailCard(room: room),
);
}).toList(),
SizedBox(height: 10.h),
],
), ),
); ),
}, ],
), ),
); );
} }
} }
\ No newline at end of file
...@@ -16,7 +16,7 @@ class RoomGrid extends StatelessWidget { ...@@ -16,7 +16,7 @@ class RoomGrid extends StatelessWidget {
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 5, crossAxisCount: 5,
mainAxisSpacing: 20.h, mainAxisSpacing: 16.h,
crossAxisSpacing: 16.w, crossAxisSpacing: 16.w,
children: rooms.map((room) => _RoomItem(room: room)).toList(), children: rooms.map((room) => _RoomItem(room: room)).toList(),
), ),
...@@ -31,49 +31,38 @@ class _RoomItem extends StatelessWidget { ...@@ -31,49 +31,38 @@ class _RoomItem extends StatelessWidget {
Color get _bgColor { Color get _bgColor {
switch (room.statusColor) { switch (room.statusColor) {
case 'occupied': case 'blue':
return const Color.fromRGBO(219, 234, 254, 1); return const Color.fromRGBO(229, 241, 255, 1);
case 'alarm': case 'yellow':
return const Color.fromRGBO(254, 243, 199, 1); return const Color.fromRGBO(255, 251, 237, 1);
case 'reserved': case 'default':
return const Color.fromRGBO(219, 234, 254, 1); case 'gray':
case 'dnd':
return const Color.fromRGBO(254, 243, 199, 1);
case 'checkout':
case 'idle':
default: default:
return const Color.fromRGBO(229, 231, 235, 1); return const Color.fromRGBO(238, 238, 238, 1);
} }
} }
Color get _textColor { Color get _textColor {
switch (room.statusColor) { switch (room.statusColor) {
case 'occupied': case 'blue':
return const Color.fromRGBO(59, 130, 246, 1); return const Color.fromRGBO(74, 149, 234, 1);
case 'alarm': case 'yellow':
return const Color.fromRGBO(245, 158, 11, 1); return const Color.fromRGBO(250, 204, 21, 1);
case 'reserved': case 'default':
return const Color.fromRGBO(59, 130, 246, 1); case 'gray':
case 'dnd':
return const Color.fromRGBO(245, 158, 11, 1);
case 'checkout':
case 'idle':
default: default:
return const Color.fromRGBO(156, 163, 175, 1); return const Color.fromRGBO(100, 116, 139, 1);
} }
} }
Color? get _borderColor { Color? get _borderColor {
switch (room.statusColor) { switch (room.statusColor) {
case 'idle': case 'blue':
case 'checkout': return const Color.fromRGBO(73, 149, 234, 1);
return null; case 'yellow':
case 'occupied': return const Color.fromRGBO(250, 204, 21, 1);
case 'reserved': case 'default':
return const Color.fromRGBO(59, 130, 246, 1); case 'gray':
case 'alarm':
case 'dnd':
return const Color.fromRGBO(245, 158, 11, 1);
default: default:
return null; return null;
} }
...@@ -81,44 +70,56 @@ class _RoomItem extends StatelessWidget { ...@@ -81,44 +70,56 @@ class _RoomItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return GestureDetector(
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 8.w), behavior: HitTestBehavior.opaque,
decoration: BoxDecoration( onTap: () {
color: _bgColor,
borderRadius: BorderRadius.circular(16.r), },
border: _borderColor != null child: Container(
? Border.all(color: _borderColor!, width: 2.w) padding: EdgeInsets.symmetric(vertical: 12.h),
: null, decoration: BoxDecoration(
), color: _bgColor,
child: Column( borderRadius: BorderRadius.circular(16.r),
mainAxisAlignment: MainAxisAlignment.center, // border: _borderColor != null
children: [ // ? Border.all(color: _borderColor!, width: 1.w)
Text( // : null,
room.roomNumber, ),
style: TextStyle( child: Column(
fontSize: 28.sp, mainAxisAlignment: MainAxisAlignment.center,
fontWeight: FontWeight.w500, spacing: 4.h,
color: _textColor, children: [
Text(
room.roomNumber,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.w500,
color: _textColor,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
), ),
maxLines: 1, Row(
overflow: TextOverflow.ellipsis, mainAxisAlignment: MainAxisAlignment.center,
), children: [
SizedBox(height: 4.h), if (room.hasAlarmIcon)
Row( Icon(Icons.warning_amber_outlined, color: _textColor, size: 24.sp),
mainAxisAlignment: MainAxisAlignment.center, Flexible(
children: [ fit: FlexFit.loose, //让文本只占实际需要的宽度
if (room.hasAlarmIcon) child: Text(
Icon(Icons.warning_amber_outlined, color: _textColor, size: 24.sp), room.statusText,
Text( style: TextStyle(
room.statusText, fontSize: 24.sp,
style: TextStyle( color: _textColor,
fontSize: 24.sp, ),
color: _textColor, textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
), ),
), ],
], ),
), ],
], ),
), ),
); );
} }
......
...@@ -49,7 +49,7 @@ class _StatItem extends StatelessWidget { ...@@ -49,7 +49,7 @@ class _StatItem extends StatelessWidget {
child: Container( child: Container(
padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 8.w), padding: EdgeInsets.symmetric(vertical: 12.h, horizontal: 8.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(229, 231, 235, 1), color: const Color.fromRGBO(238, 238, 238, 1),
borderRadius: BorderRadius.circular(24.r), borderRadius: BorderRadius.circular(24.r),
), ),
child: Column( child: Column(
...@@ -67,7 +67,7 @@ class _StatItem extends StatelessWidget { ...@@ -67,7 +67,7 @@ class _StatItem extends StatelessWidget {
item.label, item.label,
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 24.sp,
color: const Color.fromRGBO(156, 163, 175, 1), color: const Color.fromRGBO(100, 116, 139, 1),
), ),
), ),
], ],
......
...@@ -9,7 +9,6 @@ import 'package:smart_hotel_app/repositories/room_statistics_repository.dart'; ...@@ -9,7 +9,6 @@ import 'package:smart_hotel_app/repositories/room_statistics_repository.dart';
class ServiceIndexCubit extends Cubit<ServiceIndexState> { class ServiceIndexCubit extends Cubit<ServiceIndexState> {
final RoomService _roomService; final RoomService _roomService;
final RoomStatisticsService _statisticsService; final RoomStatisticsService _statisticsService;
final Map<String, List<Map<String, dynamic>>> _roomCache = {};
List<FloorAreaBO> _floorAreasCache = []; List<FloorAreaBO> _floorAreasCache = [];
ServiceIndexCubit() ServiceIndexCubit()
...@@ -51,7 +50,7 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -51,7 +50,7 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
} }
} }
/// 加载楼层和区域信息(仅进入页面时调用一次) /// 加载楼层和区域信息 + 合并房间数据
Future<void> loadFloorAndAreas() async { Future<void> loadFloorAndAreas() async {
emit(state.copyWith(isLoading: true, error: null)); emit(state.copyWith(isLoading: true, error: null));
try { try {
...@@ -65,14 +64,14 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -65,14 +64,14 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
floors: floors, floors: floors,
)); ));
// 默认选中第一个楼层,加载其房间数据 // 默认选中第一个楼层,加载其全部房间数据(不选区域类型)
if (floors.isNotEmpty) { if (floors.isNotEmpty) {
final firstFloor = floors.first; final firstFloor = floors.first;
final firstFloorId = firstFloor.keys.first; final firstFloorId = firstFloor.keys.first;
final firstFloorLabel = firstFloor.values.first; final firstFloorLabel = firstFloor.values.first;
_updateAreasForFloor(firstFloorLabel); _updateAreasForFloor(firstFloorLabel);
selectFloor(firstFloorLabel); selectFloor(firstFloorLabel);
await loadRooms(floorId: firstFloorId); await _loadAllRooms(floorId: firstFloorId);
} }
} catch (e) { } catch (e) {
emit(state.copyWith(isLoading: false, error: e.toString())); emit(state.copyWith(isLoading: false, error: e.toString()));
...@@ -88,95 +87,115 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -88,95 +87,115 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
emit(state.copyWith(areas: areas)); emit(state.copyWith(areas: areas));
} }
/// 加载房间状态列表 /// 加载某楼层的全部房间状态,与 FloorAreaBO.rooms 合并
Future<void> loadRooms({int? floorId, String? areaType}) async { Future<void> _loadAllRooms({required int floorId}) async {
emit(state.copyWith(isLoading: true, error: null)); emit(state.copyWith(isLoading: true, error: null));
try { try {
final roomStatuses = await _roomService.getRoomStatus( // 获取当前楼层的 FloorAreaBO
floorId: floorId, final floorArea = _floorAreasCache.cast<FloorAreaBO?>().firstWhere(
areaType: areaType, (f) => f?.floorId == floorId,
); orElse: () => null,
);
if (floorArea == null) {
emit(state.copyWith(isLoading: false, rooms: []));
return;
}
// 如果指定了楼层,直接缓存到对应楼层key下 // 拉取全楼层房间状态(不传 areaType)
if (floorId != null) { final roomStatuses = await _roomService.getRoomStatus(floorId: floorId);
final floorKey = floorId.toString();
// 更新该楼层的房间数据到 _roomCache // 以 roomId 为 key 建立状态映射
final updatedAllRooms = <Map<String, dynamic>>[]; final statusMap = <int, RoomStatusBO>{};
for (final rs in roomStatuses) { for (final rs in roomStatuses) {
updatedAllRooms.add(_statusBoToRoomMap(rs)); statusMap[rs.roomId] = rs;
}
_roomCache[floorKey] = updatedAllRooms;
} else {
// 未指定楼层,按房间号提取楼层归类(兜底)
_roomCache.clear();
for (final floorMap in (state.floors ?? [])) {
_roomCache[floorMap.values.first] = [];
}
for (final rs in roomStatuses) {
final floorNum = _extractFloor(rs.roomNumber);
final floorKey = floorNum.toString();
_roomCache.putIfAbsent(floorKey, () => []);
_roomCache[floorKey]!.add(_statusBoToRoomMap(rs));
}
} }
// 展平所有房间用于全量展示(可被页面直接使用) // 合并:遍历 floorArea.rooms,匹配状态数据,推断 area
final allRooms = <Map<String, dynamic>>[]; final mergedRooms = <Map<String, dynamic>>[];
for (final floorMap in (state.floors ?? [])) { for (final floorRoom in floorArea.rooms) {
final floorLabel = floorMap.values.first; final status = statusMap[floorRoom.roomId];
allRooms.addAll(_roomCache[floorLabel] ?? []); final area = _getAreaForRoom(floorRoom.roomName, floorArea.areas);
mergedRooms.add(_buildRoomMap(
roomId: floorRoom.roomId,
roomName: floorRoom.roomName,
areaType: area,
status: status,
));
} }
emit(state.copyWith(isLoading: false, rooms: allRooms));
emit(state.copyWith(isLoading: false, rooms: mergedRooms));
} catch (e) { } catch (e) {
emit(state.copyWith(isLoading: false, error: e.toString())); emit(state.copyWith(isLoading: false, error: e.toString()));
} }
} }
/// 将 RoomStatusBO 转为页面所需的 Map /// 根据 roomName 匹配所属区域类型(最长匹配优先)
Map<String, dynamic> _statusBoToRoomMap(RoomStatusBO rs) { String _getAreaForRoom(String roomName, List<String> areas) {
// 状态映射:cleanStatus "2" → 待清洁,occupancyStatus "1" → 入住,其余为 空闲 // 按长度降序排列,避免 "中餐厅" 被 "餐厅" 误匹配
final sorted = List<String>.from(areas)
..sort((a, b) => b.length.compareTo(a.length));
for (final area in sorted) {
if (roomName.contains(area)) {
return area;
}
}
return '其他';
}
/// 构建单个房间的展示 Map
Map<String, dynamic> _buildRoomMap({
required int roomId,
required String roomName,
required String areaType,
RoomStatusBO? status,
}) {
// 状态映射
String displayStatus; String displayStatus;
if (rs.cleanStatus == '2') { String occupancyStatus;
displayStatus = '待清洁'; String roomStatus;
} else if (rs.occupancyStatus == '1') { String cleanStatus;
displayStatus = '入住'; String devicePowerStatus;
String roomNumber;
if (status != null) {
roomNumber = status.roomNumber;
occupancyStatus = status.occupancyStatus;
roomStatus = status.roomStatus;
cleanStatus = status.cleanStatus;
devicePowerStatus = status.devicePowerStatus;
if (status.occupancyStatus == '1') {
displayStatus = '入住';
} else if (status.cleanStatus == '0') {
displayStatus = '待清洁';
} else {
displayStatus = '空闲';
}
} else { } else {
displayStatus = '空闲'; // 无状态数据时用兜底值
roomNumber = roomName;
occupancyStatus = '0';
roomStatus = '0';
cleanStatus = '0';
devicePowerStatus = '0';
displayStatus = '未知';
} }
return { return {
'roomId': rs.roomId, 'roomId': roomId,
'number': rs.roomNumber, 'number': roomNumber,
'roomName': roomName,
'status': displayStatus, 'status': displayStatus,
'type': '客房', 'type': areaType,
'occupancyStatus': rs.occupancyStatus, // 0=无人 1=有人 'areaType': areaType,
'roomStatus': rs.roomStatus, // 0=无人 1=有人 'occupancyStatus': occupancyStatus,
'cleanStatus': rs.cleanStatus, // 0=待清洁 2=已完成 'roomStatus': roomStatus,
'devicePowerStatus': rs.devicePowerStatus, // 0=关 1=开 'cleanStatus': cleanStatus,
'devicePowerStatus': devicePowerStatus,
}; };
} }
/// 从房间号提取楼层,如 "301" → 3
int _extractFloor(String roomNumber) {
if (roomNumber.length >= 2) {
final match = RegExp(r'^(\d+)').firstMatch(roomNumber);
if (match != null) {
final num = int.tryParse(match.group(1) ?? '');
if (num != null) {
if (num > 100) {
return num ~/ 100;
}
return num;
}
}
}
return 1;
}
List<Map<String, dynamic>> getRoomsByFloor(String floor) {
return _roomCache[floor] ?? [];
}
void selectFloor(String? floor) { void selectFloor(String? floor) {
emit(state.copyWith(selectedFloor: floor)); emit(state.copyWith(selectedFloor: floor));
if (floor != null) { if (floor != null) {
...@@ -184,32 +203,7 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -184,32 +203,7 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
} }
} }
/// 加载非客房-相关楼层区域设备 /// UI 层切换楼层(切换时重置类型/房间/搜索,重新加载数据)
Future<void> loadAreaDevices({required int floorId, required String areaType}) async {
emit(state.copyWith(isLoadingAreaDevices: true, error: null));
try {
final devices = await _roomService.getAreaDevices(
floorId: floorId,
areaType: areaType,
);
emit(state.copyWith(
isLoadingAreaDevices: false,
areaDevices: devices,
));
} catch (e) {
emit(state.copyWith(
isLoadingAreaDevices: false,
error: e.toString(),
));
}
}
/// 选择房间
void selectRoom({String? room, int? roomId}) {
emit(state.copyWith(selectedRoom: room, selectedRoomId: roomId));
}
/// UI 层切换楼层(含取消选中、重置类型/房间/搜索、加载房间数据)
void toggleFloor(String floorName, int floorId) { void toggleFloor(String floorName, int floorId) {
final isSameFloor = state.selectedFloor == floorName; final isSameFloor = state.selectedFloor == floorName;
final newFloor = isSameFloor ? null : floorName; final newFloor = isSameFloor ? null : floorName;
...@@ -233,11 +227,11 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -233,11 +227,11 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
)); ));
if (newFloor != null) { if (newFloor != null) {
loadRooms(floorId: floorId); _loadAllRooms(floorId: floorId);
} }
} }
/// UI 层切换区域类型(含取消选中、重置房间、加载非客房设备 /// UI 层切换区域类型(点击切换,再点取消,重置房间
void toggleType(String type) { void toggleType(String type) {
final newType = state.selectedType != type ? type : null; final newType = state.selectedType != type ? type : null;
emit(state.copyWith( emit(state.copyWith(
...@@ -245,28 +239,16 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -245,28 +239,16 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
selectedRoom: null, selectedRoom: null,
selectedRoomId: null, selectedRoomId: null,
)); ));
if (newType != null && newType != '客房') {
_loadAreaDevicesForCurrentFloor(newType);
}
} }
/// 获取当前筛选条件下的房间列表 /// 获取当前筛选条件下的房间列表
List<Map<String, dynamic>> getFilteredRooms() { List<Map<String, dynamic>> getFilteredRooms() {
List<Map<String, dynamic>> allRooms; List<Map<String, dynamic>> allRooms = state.rooms;
if (state.selectedFloor == null) {
allRooms = [];
for (final floorMap in (state.floors ?? [])) {
final floorName = floorMap.values.first;
allRooms.addAll(getRoomsByFloor(floorName));
}
} else {
allRooms = getRoomsByFloor(state.selectedFloor!);
}
if (state.selectedType != null) { if (state.selectedType != null) {
allRooms = allRooms = allRooms
allRooms.where((room) => room['type'] == state.selectedType).toList(); .where((room) => room['areaType'] == state.selectedType)
.toList();
} }
if (state.searchText.isEmpty) { if (state.searchText.isEmpty) {
...@@ -285,22 +267,9 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -285,22 +267,9 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
return _findRoomByNumber(state.selectedRoom!); return _findRoomByNumber(state.selectedRoom!);
} }
/// 根据楼层标签获取楼层 ID /// 选择房间
int? getFloorIdByLabel(String floorLabel) { void selectRoom({String? room, int? roomId}) {
for (final floorMap in (state.floors ?? [])) { emit(state.copyWith(selectedRoom: room, selectedRoomId: roomId));
if (floorMap.values.first == floorLabel) {
return floorMap.keys.first;
}
}
return null;
}
/// 根据当前选中楼层加载非客房区域设备
void _loadAreaDevicesForCurrentFloor(String areaType) {
if (state.selectedFloor == null) return;
final floorId = getFloorIdByLabel(state.selectedFloor!);
if (floorId == null) return;
loadAreaDevices(floorId: floorId, areaType: areaType);
} }
void setSearchText(String text) { void setSearchText(String text) {
...@@ -339,21 +308,23 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -339,21 +308,23 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
} }
} }
/// 从缓存中根据房号查找房间数据 /// 根据楼层标签获取楼层 ID
Map<String, dynamic>? _findRoomByNumber(String roomNumber) { int? getFloorIdByLabel(String floorLabel) {
for (final rooms in _roomCache.values) { for (final floorMap in (state.floors ?? [])) {
for (final room in rooms) { if (floorMap.values.first == floorLabel) {
if (room['number'] == roomNumber) { return floorMap.keys.first;
return room;
}
} }
} }
return null; return null;
} }
@override /// 从当前 rooms 中根据房号查找房间数据
Future<void> close() { Map<String, dynamic>? _findRoomByNumber(String roomNumber) {
return super.close(); for (final room in state.rooms) {
if (room['number'] == roomNumber) {
return room;
}
}
return null;
} }
}
} \ No newline at end of file
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:smart_hotel_app/models/bo/room_bo.dart';
class ServiceIndexState extends Equatable { class ServiceIndexState extends Equatable {
/// copyWith sentinel: 区分「未传参」和「显式传 null」 /// copyWith sentinel: 区分「未传参」和「显式传 null」
...@@ -16,9 +15,7 @@ class ServiceIndexState extends Equatable { ...@@ -16,9 +15,7 @@ class ServiceIndexState extends Equatable {
final int? selectedRoomId; final int? selectedRoomId;
final String searchText; final String searchText;
final List<Map<String, dynamic>> rooms; final List<Map<String, dynamic>> rooms;
final List<AreaDeviceBO> areaDevices;
final bool isLoading; final bool isLoading;
final bool isLoadingAreaDevices;
final String? error; final String? error;
final bool isPoweringOn; final bool isPoweringOn;
final bool isPoweringOff; final bool isPoweringOff;
...@@ -35,9 +32,7 @@ class ServiceIndexState extends Equatable { ...@@ -35,9 +32,7 @@ class ServiceIndexState extends Equatable {
this.selectedRoomId, this.selectedRoomId,
this.searchText = '', this.searchText = '',
this.rooms = const [], this.rooms = const [],
this.areaDevices = const [],
this.isLoading = false, this.isLoading = false,
this.isLoadingAreaDevices = false,
this.error, this.error,
this.isPoweringOn = false, this.isPoweringOn = false,
this.isPoweringOff = false, this.isPoweringOff = false,
...@@ -55,9 +50,7 @@ class ServiceIndexState extends Equatable { ...@@ -55,9 +50,7 @@ class ServiceIndexState extends Equatable {
Object? selectedRoomId = _nothing, Object? selectedRoomId = _nothing,
String? searchText, String? searchText,
List<Map<String, dynamic>>? rooms, List<Map<String, dynamic>>? rooms,
List<AreaDeviceBO>? areaDevices,
bool? isLoading, bool? isLoading,
bool? isLoadingAreaDevices,
Object? error = _nothing, Object? error = _nothing,
bool? isPoweringOn, bool? isPoweringOn,
bool? isPoweringOff, bool? isPoweringOff,
...@@ -74,9 +67,7 @@ class ServiceIndexState extends Equatable { ...@@ -74,9 +67,7 @@ class ServiceIndexState extends Equatable {
selectedRoomId: identical(selectedRoomId, _nothing) ? this.selectedRoomId : selectedRoomId as int?, selectedRoomId: identical(selectedRoomId, _nothing) ? this.selectedRoomId : selectedRoomId as int?,
searchText: searchText ?? this.searchText, searchText: searchText ?? this.searchText,
rooms: rooms ?? this.rooms, rooms: rooms ?? this.rooms,
areaDevices: areaDevices ?? this.areaDevices,
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
isLoadingAreaDevices: isLoadingAreaDevices ?? this.isLoadingAreaDevices,
error: identical(error, _nothing) ? this.error : error as String?, error: identical(error, _nothing) ? this.error : error as String?,
isPoweringOn: isPoweringOn ?? this.isPoweringOn, isPoweringOn: isPoweringOn ?? this.isPoweringOn,
isPoweringOff: isPoweringOff ?? this.isPoweringOff, isPoweringOff: isPoweringOff ?? this.isPoweringOff,
...@@ -96,9 +87,7 @@ class ServiceIndexState extends Equatable { ...@@ -96,9 +87,7 @@ class ServiceIndexState extends Equatable {
selectedRoomId, selectedRoomId,
searchText, searchText,
rooms, rooms,
areaDevices,
isLoading, isLoading,
isLoadingAreaDevices,
error, error,
isPoweringOn, isPoweringOn,
isPoweringOff, isPoweringOff,
......
...@@ -17,26 +17,29 @@ class ServiceIndexView extends StatefulWidget { ...@@ -17,26 +17,29 @@ class ServiceIndexView extends StatefulWidget {
} }
class _ServiceIndexViewState extends State<ServiceIndexView> with AutoRouteAwareStateMixin<ServiceIndexView> { class _ServiceIndexViewState extends State<ServiceIndexView> with AutoRouteAwareStateMixin<ServiceIndexView> {
TabsRouter? _tabsRouter;
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
// Subscribe to tab router events final newRouter = AutoTabsRouter.of(context);
final tabsRouter = AutoTabsRouter.of(context); if (newRouter != _tabsRouter) {
tabsRouter.addListener(_onTabChange); _tabsRouter?.removeListener(_onTabChange);
_tabsRouter = newRouter;
_tabsRouter?.addListener(_onTabChange);
}
} }
@override @override
void dispose() { void dispose() {
final tabsRouter = AutoTabsRouter.of(context); _tabsRouter?.removeListener(_onTabChange);
tabsRouter.removeListener(_onTabChange);
super.dispose(); super.dispose();
} }
void _onTabChange() { void _onTabChange() {
final tabsRouter = AutoTabsRouter.of(context); if (!mounted) return;
// Check if this tab is now active (index 1)
if (tabsRouter.activeIndex == 1) { if (_tabsRouter?.activeIndex == 1) {
// Reload data when tab is activated
context.read<ServiceIndexCubit>().reloadAll(); context.read<ServiceIndexCubit>().reloadAll();
} }
} }
......
...@@ -7,7 +7,6 @@ import 'package:smart_hotel_app/views/service/index/cubit/service_index_cubit.da ...@@ -7,7 +7,6 @@ import 'package:smart_hotel_app/views/service/index/cubit/service_index_cubit.da
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart'; import 'package:smart_hotel_app/routes/app_router.gr.dart';
import 'package:smart_hotel_app/views/service/index/cubit/service_index_state.dart'; import 'package:smart_hotel_app/views/service/index/cubit/service_index_state.dart';
import 'package:smart_hotel_app/views/service/index/widget/area_device_list.dart';
import 'package:smart_hotel_app/utils/toast_utils.dart'; import 'package:smart_hotel_app/utils/toast_utils.dart';
class RoomManagementBlock extends StatelessWidget { class RoomManagementBlock extends StatelessWidget {
...@@ -39,28 +38,19 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -39,28 +38,19 @@ class RoomManagementBlock extends StatelessWidget {
SizedBox(height: 24.h), SizedBox(height: 24.h),
_buildTypeSelector(state, cubit), _buildTypeSelector(state, cubit),
SizedBox(height: 24.h), SizedBox(height: 24.h),
if (state.selectedType == null || state.selectedType == '客房') ...[ _buildSearchBox(state, cubit),
_buildSearchBox(state, cubit), SizedBox(height: 32.h),
SizedBox(height: 32.h), _buildLine(),
_buildLine(), SizedBox(height: 24.h),
SizedBox(height: 24.h), _buildRoomGrid(state, cubit),
_buildRoomGrid(state, cubit), SizedBox(height: 24.h),
SizedBox(height: 24.h), if (state.selectedRoom != null) ...[
if (state.selectedRoom != null) ...[
_buildLine(),
SizedBox(height: 24.h),
_buildRoomDetail(state, cubit),
SizedBox(height: 10.h),
],
_buildBottomButtons(state, cubit, context),
] else ...[
_buildLine(), _buildLine(),
SizedBox(height: 24.h), SizedBox(height: 24.h),
AreaDeviceList( _buildRoomDetail(state, cubit),
devices: state.areaDevices, SizedBox(height: 10.h),
isLoading: state.isLoadingAreaDevices,
),
], ],
_buildBottomButtons(state, cubit, context),
], ],
), ),
); );
...@@ -78,8 +68,7 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -78,8 +68,7 @@ class RoomManagementBlock extends StatelessWidget {
floorName == '3' ? '三' : floorName == '3' ? '三' :
floorName == '4' ? '四' : floorName == '4' ? '四' :
floorName == '5' ? '五' : floorName == '5' ? '五' :
floorName == '6' ? '六' : floorName == '6' ? '六' : '';
floorName == '7' ? '七' : '';
final floorId = floorMap.keys.first; final floorId = floorMap.keys.first;
final isSelected = state.selectedFloor == floorName; final isSelected = state.selectedFloor == floorName;
return Expanded( return Expanded(
...@@ -241,7 +230,10 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -241,7 +230,10 @@ class RoomManagementBlock extends StatelessWidget {
const crossAxisCount = 12; const crossAxisCount = 12;
final floorPart = state.selectedFloor?.replaceAll('楼', '') ?? ''; final floorPart = state.selectedFloor?.replaceAll('楼', '') ?? '';
final filterLabel = floorPart.isNotEmpty ? '客房$floorPart楼·左右滑动选择' : '左右滑动选择'; final areaLabel = state.selectedType ?? '全部';
final filterLabel = floorPart.isNotEmpty
? '$areaLabel·$floorPart楼·左右滑动选择'
: '$areaLabel·左右滑动选择';
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -386,6 +378,8 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -386,6 +378,8 @@ class RoomManagementBlock extends StatelessWidget {
width: 24.sp, width: 24.sp,
height: 30.sp, height: 30.sp,
); );
// return Icon(Icons.cleaning_services_rounded, size: 26.w,
// color: const Color.fromRGBO(255, 138, 139, 1));
} else { } else {
return Text( return Text(
' ', ' ',
...@@ -405,7 +399,6 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -405,7 +399,6 @@ class RoomManagementBlock extends StatelessWidget {
Widget _buildBottomButtons(ServiceIndexState state, ServiceIndexCubit cubit, BuildContext context) { Widget _buildBottomButtons(ServiceIndexState state, ServiceIndexCubit cubit, BuildContext context) {
final isRoomSelected = state.selectedRoom != null; final isRoomSelected = state.selectedRoom != null;
final isProcessing = state.isPoweringOn || state.isPoweringOff;
return Row( return Row(
spacing: 16.w, spacing: 16.w,
children: [ children: [
...@@ -421,7 +414,7 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -421,7 +414,7 @@ class RoomManagementBlock extends StatelessWidget {
), ),
elevation: 0, elevation: 0,
), ),
onPressed: isRoomSelected && !isProcessing onPressed: isRoomSelected && !state.isPoweringOn
? () async { ? () async {
try { try {
await cubit.powerOnRoom(state.selectedRoom!); await cubit.powerOnRoom(state.selectedRoom!);
...@@ -453,14 +446,14 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -453,14 +446,14 @@ class RoomManagementBlock extends StatelessWidget {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
side: BorderSide( // side: BorderSide(
color: const Color.fromRGBO(73, 149, 234, 1), // color: const Color.fromRGBO(73, 149, 234, 1),
width: 1.w, // width: 1.w,
), // ),
), ),
elevation: 0, elevation: 0,
), ),
onPressed: isRoomSelected && !isProcessing onPressed: isRoomSelected && !state.isPoweringOff
? () async { ? () async {
try { try {
await cubit.powerOffRoom(state.selectedRoom!); await cubit.powerOffRoom(state.selectedRoom!);
...@@ -515,6 +508,7 @@ class RoomManagementBlock extends StatelessWidget { ...@@ -515,6 +508,7 @@ class RoomManagementBlock extends StatelessWidget {
], ],
); );
} }
} }
......
...@@ -150,36 +150,55 @@ class ServiceRoomCubit extends Cubit<ServiceRoomState> { ...@@ -150,36 +150,55 @@ class ServiceRoomCubit extends Cubit<ServiceRoomState> {
/// 房间总电源开关 /// 房间总电源开关
Future<void> toggleMainPowerForSwitch(bool value) async { Future<void> toggleMainPowerForSwitch(bool value) async {
if (state.isTogglingPower) return; if (state.isPoweringOn || state.isPoweringOff) return;
emit(state.copyWith(isTogglingPower: true)); final loadingKey = value ? 'isPoweringOn' : 'isPoweringOff';
emit(state.copyWith(
isPoweringOn: value,
isPoweringOff: !value,
));
try { try {
if (value) { if (value) {
await _service.roomPowerOn(roomId: _roomId); await _service.roomPowerOn(roomId: _roomId);
} else { } else {
await _service.roomPowerOff(roomId: _roomId); await _service.roomPowerOff(roomId: _roomId);
} }
emit(state.copyWith(isTogglingPower: false, mainPowerOn: value)); emit(state.copyWith(
isPoweringOn: false,
isPoweringOff: false,
mainPowerOn: value,
));
} catch (e) { } catch (e) {
emit(state.copyWith(isTogglingPower: false)); emit(state.copyWith(
// Re-throw so the view can show error snackbar isPoweringOn: false,
isPoweringOff: false,
));
rethrow; rethrow;
} }
} }
/// 房间总电源开关 /// 房间总电源开关
Future<void> toggleMainPower(bool value) async { Future<void> toggleMainPower(bool value) async {
if (state.isTogglingPower) return; if (state.isPoweringOn || state.isPoweringOff) return;
emit(state.copyWith(isTogglingPower: true)); emit(state.copyWith(
isPoweringOn: value,
isPoweringOff: !value,
));
try { try {
if (value) { if (value) {
await _service.powerOn(roomId: _roomId); await _service.powerOn(roomId: _roomId);
} else { } else {
await _service.powerOff(roomId: _roomId); await _service.powerOff(roomId: _roomId);
} }
emit(state.copyWith(isTogglingPower: false, mainPowerOn: value)); emit(state.copyWith(
isPoweringOn: false,
isPoweringOff: false,
mainPowerOn: value,
));
} catch (e) { } catch (e) {
emit(state.copyWith(isTogglingPower: false)); emit(state.copyWith(
// Re-throw so the view can show error snackbar isPoweringOn: false,
isPoweringOff: false,
));
rethrow; rethrow;
} }
} }
......
...@@ -45,7 +45,8 @@ class ServiceRoomState extends Equatable { ...@@ -45,7 +45,8 @@ class ServiceRoomState extends Equatable {
final List<RoomDevice> roomDevices; final List<RoomDevice> roomDevices;
final bool mainPowerOn; final bool mainPowerOn;
final List<ControlDevice> controlDevices; final List<ControlDevice> controlDevices;
final bool isTogglingPower; final bool isPoweringOn;
final bool isPoweringOff;
const ServiceRoomState({ const ServiceRoomState({
this.isLoading = false, this.isLoading = false,
...@@ -57,7 +58,8 @@ class ServiceRoomState extends Equatable { ...@@ -57,7 +58,8 @@ class ServiceRoomState extends Equatable {
this.roomDevices = const [], this.roomDevices = const [],
this.mainPowerOn = false, this.mainPowerOn = false,
this.controlDevices = const [], this.controlDevices = const [],
this.isTogglingPower = false, this.isPoweringOn = false,
this.isPoweringOff = false,
}); });
ServiceRoomState copyWith({ ServiceRoomState copyWith({
...@@ -70,7 +72,8 @@ class ServiceRoomState extends Equatable { ...@@ -70,7 +72,8 @@ class ServiceRoomState extends Equatable {
List<RoomDevice>? roomDevices, List<RoomDevice>? roomDevices,
bool? mainPowerOn, bool? mainPowerOn,
List<ControlDevice>? controlDevices, List<ControlDevice>? controlDevices,
bool? isTogglingPower, bool? isPoweringOn,
bool? isPoweringOff,
}) { }) {
return ServiceRoomState( return ServiceRoomState(
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
...@@ -82,7 +85,8 @@ class ServiceRoomState extends Equatable { ...@@ -82,7 +85,8 @@ class ServiceRoomState extends Equatable {
roomDevices: roomDevices ?? this.roomDevices, roomDevices: roomDevices ?? this.roomDevices,
mainPowerOn: mainPowerOn ?? this.mainPowerOn, mainPowerOn: mainPowerOn ?? this.mainPowerOn,
controlDevices: controlDevices ?? this.controlDevices, controlDevices: controlDevices ?? this.controlDevices,
isTogglingPower: isTogglingPower ?? this.isTogglingPower, isPoweringOn: isPoweringOn ?? this.isPoweringOn,
isPoweringOff: isPoweringOff ?? this.isPoweringOff,
); );
} }
...@@ -97,6 +101,7 @@ class ServiceRoomState extends Equatable { ...@@ -97,6 +101,7 @@ class ServiceRoomState extends Equatable {
roomDevices, roomDevices,
mainPowerOn, mainPowerOn,
controlDevices, controlDevices,
isTogglingPower, isPoweringOn,
isPoweringOff,
]; ];
} }
...@@ -124,7 +124,8 @@ class ServiceRoomDetailView extends StatelessWidget { ...@@ -124,7 +124,8 @@ class ServiceRoomDetailView extends StatelessWidget {
), ),
SizedBox(height: 20.h), SizedBox(height: 20.h),
RoomBottomButtons( RoomBottomButtons(
isProcessing: state.isTogglingPower, isPoweringOn: state.isPoweringOn,
isPoweringOff: state.isPoweringOff,
onPowerOn: () async { onPowerOn: () async {
try { try {
await cubit.toggleMainPower(true); await cubit.toggleMainPower(true);
......
...@@ -4,15 +4,15 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; ...@@ -4,15 +4,15 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
class RoomBottomButtons extends StatelessWidget { class RoomBottomButtons extends StatelessWidget {
final VoidCallback? onPowerOn; final VoidCallback? onPowerOn;
final VoidCallback? onPowerOff; final VoidCallback? onPowerOff;
// final VoidCallback? onDeviceControl; final bool isPoweringOn;
final bool isProcessing; final bool isPoweringOff;
const RoomBottomButtons({ const RoomBottomButtons({
super.key, super.key,
this.onPowerOn, this.onPowerOn,
this.onPowerOff, this.onPowerOff,
// this.onDeviceControl, this.isPoweringOn = false,
this.isProcessing = false, this.isPoweringOff = false,
}); });
@override @override
...@@ -22,11 +22,11 @@ class RoomBottomButtons extends StatelessWidget { ...@@ -22,11 +22,11 @@ class RoomBottomButtons extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: GestureDetector( child: GestureDetector(
onTap: (onPowerOn != null && !isProcessing) ? onPowerOn : null, onTap: (onPowerOn != null && !isPoweringOn) ? onPowerOn : null,
child: Container( child: Container(
height: 70.h, height: 70.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: (onPowerOn != null && !isProcessing) color: (onPowerOn != null && !isPoweringOn)
? const Color.fromRGBO(73, 149, 234, 1) ? const Color.fromRGBO(73, 149, 234, 1)
: const Color.fromRGBO(204, 204, 204, 1), : const Color.fromRGBO(204, 204, 204, 1),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
...@@ -46,26 +46,20 @@ class RoomBottomButtons extends StatelessWidget { ...@@ -46,26 +46,20 @@ class RoomBottomButtons extends StatelessWidget {
), ),
Expanded( Expanded(
child: GestureDetector( child: GestureDetector(
onTap: (onPowerOff != null && !isProcessing) ? onPowerOff : null, onTap: (onPowerOff != null && !isPoweringOff) ? onPowerOff : null,
child: Container( child: Container(
height: 70.h, height: 70.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(229, 241, 255, 1), color: (onPowerOff != null && !isPoweringOff)
? const Color.fromRGBO(229, 241, 255, 1)
: const Color.fromRGBO(204, 204, 204, 1),
borderRadius: BorderRadius.circular(16.r), borderRadius: BorderRadius.circular(16.r),
border: Border.all(
color: (onPowerOff != null && !isProcessing)
? const Color.fromRGBO(73, 149, 234, 1)
: const Color.fromRGBO(204, 204, 204, 1),
width: 1.w,
),
), ),
child: Center( child: Center(
child: Text( child: Text(
'断电', '断电',
style: TextStyle( style: TextStyle(
color: (onPowerOff != null && !isProcessing) color: const Color.fromRGBO(100, 116, 139, 1),
? const Color.fromRGBO(66, 165, 245, 1.0)
: const Color.fromRGBO(100, 116, 139, 1),
fontSize: 28.sp, fontSize: 28.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
...@@ -74,29 +68,7 @@ class RoomBottomButtons extends StatelessWidget { ...@@ -74,29 +68,7 @@ class RoomBottomButtons extends StatelessWidget {
), ),
), ),
), ),
// Expanded(
// child: GestureDetector(
// onTap: onDeviceControl,
// child: Container(
// height: 70.h,
// decoration: BoxDecoration(
// color: const Color.fromRGBO(100, 116, 139, 0.2),
// borderRadius: BorderRadius.circular(16.r),
// ),
// child: Center(
// child: Text(
// '设备控制',
// style: TextStyle(
// color: const Color.fromRGBO(100, 116, 139, 1.0),
// fontSize: 28.sp,
// fontWeight: FontWeight.w500,
// ),
// ),
// ),
// ),
// ),
// ),
], ],
); );
} }
} }
\ No newline at end of file
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