Commit 7566c742 authored by huqu's avatar huqu

fix bugs

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