Commit a49802fa authored by 张宏's avatar 张宏

告警看板 添加告警分类处理

parent 186e3157
......@@ -84,6 +84,7 @@ class AlertItemBO extends Equatable {
final int waitingDuration;
final String waitingDurationDesc;
final String alertTime;
final String alertCategory;
const AlertItemBO({
required this.alertId,
......@@ -103,6 +104,7 @@ class AlertItemBO extends Equatable {
required this.waitingDuration,
required this.waitingDurationDesc,
required this.alertTime,
required this.alertCategory,
});
factory AlertItemBO.fromJson(Map<String, dynamic> json) {
......@@ -124,6 +126,7 @@ class AlertItemBO extends Equatable {
waitingDuration: json['waitingDuration'] as int? ?? 0,
waitingDurationDesc: json['waitingDurationDesc'] as String? ?? '',
alertTime: json['alertTime'] as String? ?? '',
alertCategory: json['alertCategory'] as String? ?? '',
);
}
......@@ -146,6 +149,7 @@ class AlertItemBO extends Equatable {
waitingDuration,
waitingDurationDesc,
alertTime,
alertCategory,
];
}
......
class DeviceControlBO {
final DeviceBasicInfoBO deviceBasicInfo;
final RealtimeParamsBO realtimeParams;
final DeviceTrendChartBO trendChart;
const DeviceControlBO({
required this.deviceBasicInfo,
required this.realtimeParams,
required this.trendChart,
});
factory DeviceControlBO.fromJson(Map<String, dynamic> json) {
return DeviceControlBO(
deviceBasicInfo: DeviceBasicInfoBO.fromJson(
json['deviceBasicInfo'] as Map<String, dynamic>? ?? {},
),
realtimeParams: RealtimeParamsBO.fromJson(
json['realtimeParams'] as Map<String, dynamic>? ?? {},
),
trendChart: DeviceTrendChartBO.fromJson(
json['trendChart'] as Map<String, dynamic>? ?? {},
),
);
}
}
class DeviceBasicInfoBO {
final int deviceId;
final String deviceName;
final String deviceCode;
final String roomName;
final String deviceTypeIcon;
final String onlineStatus;
const DeviceBasicInfoBO({
required this.deviceId,
required this.deviceName,
required this.deviceCode,
required this.roomName,
required this.deviceTypeIcon,
required this.onlineStatus,
});
factory DeviceBasicInfoBO.fromJson(Map<String, dynamic> json) {
return DeviceBasicInfoBO(
deviceId: json['deviceId'] as int? ?? 0,
deviceName: json['deviceName'] as String? ?? '',
deviceCode: json['deviceCode'] as String? ?? '',
roomName: json['roomName'] as String? ?? '',
deviceTypeIcon: json['deviceTypeIcon'] as String? ?? '',
onlineStatus: json['onlineStatus'] as String? ?? '',
);
}
}
class RealtimeParamsBO {
final String voltage;
final String current;
final String activePower;
final String deviceTemperature;
const RealtimeParamsBO({
required this.voltage,
required this.current,
required this.activePower,
required this.deviceTemperature,
});
factory RealtimeParamsBO.fromJson(Map<String, dynamic> json) {
return RealtimeParamsBO(
voltage: json['voltage'] as String? ?? '',
current: json['current'] as String? ?? '',
activePower: json['activePower'] as String? ?? '',
deviceTemperature: json['deviceTemperature'] as String? ?? '',
);
}
}
class DeviceTrendChartBO {
final String chartTitle;
final String unit;
final List<DeviceDataPointBO> dataPoints;
final int yaxisMax;
final int yaxisMin;
const DeviceTrendChartBO({
required this.chartTitle,
required this.unit,
required this.dataPoints,
required this.yaxisMax,
required this.yaxisMin,
});
factory DeviceTrendChartBO.fromJson(Map<String, dynamic> json) {
return DeviceTrendChartBO(
chartTitle: json['chartTitle'] as String? ?? '',
unit: json['unit'] as String? ?? '',
dataPoints: (json['dataPoints'] as List<dynamic>?)
?.map(
(e) => DeviceDataPointBO.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
yaxisMax: json['yaxisMax'] as int? ?? 100,
yaxisMin: json['yaxisMin'] as int? ?? 0,
);
}
}
class DeviceDataPointBO {
final String time;
final double power;
final double temperature;
const DeviceDataPointBO({
required this.time,
required this.power,
required this.temperature,
});
factory DeviceDataPointBO.fromJson(Map<String, dynamic> json) {
return DeviceDataPointBO(
time: json['time'] as String? ?? '',
power: (json['power'] as num?)?.toDouble() ?? 0,
temperature: (json['temperature'] as num?)?.toDouble() ?? 0,
);
}
}
\ No newline at end of file
......@@ -12,4 +12,12 @@ class AlertDetailRepository {
AlertDetailBO.fromJson(data as Map<String, dynamic>),
);
}
/// 确认处理告警
Future<ResponseModel<Map<String, dynamic>>> handleAlert({required int alertId}) {
return DioRequest.instance.post<Map<String, dynamic>>(
'/app/alert/handle',
data: {'alertId': alertId},
);
}
}
\ No newline at end of file
import '../utils/http/response_model.dart';
import '../utils/http/dio_request.dart';
import '../models/bo/device_control_bo.dart';
class DeviceControlRepository {
/// 获取设备控制详情
Future<ResponseModel<DeviceControlBO>> getDetail({required int deviceId}) {
return DioRequest.instance.get<DeviceControlBO>(
'/app/device/control/detail',
queryParameters: {'deviceId': deviceId},
fromJsonT: (data) =>
DeviceControlBO.fromJson(data as Map<String, dynamic>),
);
}
/// 远程送电
Future<ResponseModel<Map<String, dynamic>>> powerOn({required int deviceId}) {
return DioRequest.instance.post<Map<String, dynamic>>(
'/app/device/control/powerOn',
data: {'deviceId': deviceId},
);
}
/// 远程断电
Future<ResponseModel<Map<String, dynamic>>> powerOff({required int deviceId}) {
return DioRequest.instance.post<Map<String, dynamic>>(
'/app/device/control/powerOff',
data: {'deviceId': deviceId},
);
}
}
\ No newline at end of file
......@@ -72,9 +72,13 @@ abstract class $AppRouter extends _i21.RootStackRouter {
);
},
DeviceDetailRoute.name: (routeData) {
final args = routeData.argsAs<DeviceDetailRouteArgs>();
return _i21.AutoRoutePage<dynamic>(
routeData: routeData,
child: const _i4.DeviceDetailView(),
child: _i4.DeviceDetailView(
key: args.key,
deviceId: args.deviceId,
),
);
},
HomeRoute.name: (routeData) {
......@@ -270,16 +274,40 @@ class DefaultLayoutRoute extends _i21.PageRouteInfo<void> {
/// generated route for
/// [_i4.DeviceDetailView]
class DeviceDetailRoute extends _i21.PageRouteInfo<void> {
const DeviceDetailRoute({List<_i21.PageRouteInfo>? children})
: super(
class DeviceDetailRoute extends _i21.PageRouteInfo<DeviceDetailRouteArgs> {
DeviceDetailRoute({
_i22.Key? key,
required int deviceId,
List<_i21.PageRouteInfo>? children,
}) : super(
DeviceDetailRoute.name,
args: DeviceDetailRouteArgs(
key: key,
deviceId: deviceId,
),
initialChildren: children,
);
static const String name = 'DeviceDetailRoute';
static const _i21.PageInfo<void> page = _i21.PageInfo<void>(name);
static const _i21.PageInfo<DeviceDetailRouteArgs> page =
_i21.PageInfo<DeviceDetailRouteArgs>(name);
}
class DeviceDetailRouteArgs {
const DeviceDetailRouteArgs({
this.key,
required this.deviceId,
});
final _i22.Key? key;
final int deviceId;
@override
String toString() {
return 'DeviceDetailRouteArgs{key: $key, deviceId: $deviceId}';
}
}
/// generated route for
......
......@@ -14,4 +14,11 @@ class AlertDetailService {
}
throw Exception(result.msg);
}
Future<void> handleAlert({required int alertId}) async {
final result = await _repository.handleAlert(alertId: alertId);
if (!result.success) {
throw Exception(result.msg);
}
}
}
\ No newline at end of file
import '../models/bo/device_control_bo.dart';
import '../repositories/device_control_repository.dart';
class DeviceControlService {
final DeviceControlRepository _repository;
DeviceControlService({required DeviceControlRepository repository})
: _repository = repository;
Future<DeviceControlBO> getDetail({required int deviceId}) async {
final result = await _repository.getDetail(deviceId: deviceId);
if (result.success && result.data != null) {
return result.data!;
}
throw Exception(result.msg);
}
Future<void> powerOn({required int deviceId}) async {
final result = await _repository.powerOn(deviceId: deviceId);
if (!result.success) {
throw Exception(result.msg);
}
}
Future<void> powerOff({required int deviceId}) async {
final result = await _repository.powerOff(deviceId: deviceId);
if (!result.success) {
throw Exception(result.msg);
}
}
}
\ No newline at end of file
......@@ -96,23 +96,41 @@ class AbnormalDetailView extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: double.infinity,
height: 88.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(16.r),
),
child: TextButton(
onPressed: () => cubit.handleConfirm(),
child: Text(
'确认处理',
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(237, 245, 255, 1),
BlocBuilder<AbnormalCubit, AbnormalState>(
builder: (context, state) {
final isDisabled = state.isHandling || state.isHandled;
return Container(
width: double.infinity,
height: 88.h,
decoration: BoxDecoration(
color: isDisabled
? const Color.fromRGBO(73, 149, 234, 0.4)
: const Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(16.r),
),
),
),
child: TextButton(
onPressed: isDisabled
? null
: () => _handleConfirm(context, cubit),
child: state.isHandling
? SizedBox(
width: 32.sp,
height: 32.sp,
child: CircularProgressIndicator(
strokeWidth: 3,
color: const Color.fromRGBO(237, 245, 255, 1),
),
)
: Text(
state.isHandled ? '已处理' : '确认处理',
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(237, 245, 255, 1),
),
),
),
);
},
),
SizedBox(height: 20.h),
Container(
......@@ -124,7 +142,8 @@ class AbnormalDetailView extends StatelessWidget {
),
child: TextButton(
onPressed: () {
context.pushRoute(const DeviceDetailRoute());
// TODO: 替换为真实的 deviceId
context.pushRoute(DeviceDetailRoute(deviceId: 0));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
......@@ -150,4 +169,21 @@ class AbnormalDetailView extends StatelessWidget {
),
);
}
Future<void> _handleConfirm(BuildContext context, AbnormalCubit cubit) async {
try {
await cubit.handleConfirm();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('操作成功')),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('操作失败: $e')),
);
}
}
}
}
\ No newline at end of file
......@@ -63,7 +63,15 @@ class AbnormalCubit extends Cubit<AbnormalState> {
}
}
void handleConfirm() {
print('确认处理');
Future<void> handleConfirm() async {
if (state.isHandling || state.isHandled) return;
emit(state.copyWith(isHandling: true));
try {
await _service.handleAlert(alertId: _alertId);
emit(state.copyWith(isHandling: false, isHandled: true));
} catch (e) {
emit(state.copyWith(isHandling: false));
rethrow;
}
}
}
\ No newline at end of file
......@@ -38,10 +38,30 @@ class AbnormalState {
final bool isLoading;
final String? error;
final AlarmInfo? alarmInfo;
final bool isHandling;
final bool isHandled;
const AbnormalState({
this.isLoading = false,
this.error,
this.alarmInfo,
this.isHandling = false,
this.isHandled = false,
});
AbnormalState copyWith({
bool? isLoading,
String? error,
AlarmInfo? alarmInfo,
bool? isHandling,
bool? isHandled,
}) {
return AbnormalState(
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
alarmInfo: alarmInfo ?? this.alarmInfo,
isHandling: isHandling ?? this.isHandling,
isHandled: isHandled ?? this.isHandled,
);
}
}
\ No newline at end of file
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/models/bo/device_control_bo.dart';
import 'package:smart_hotel_app/services/device_control_service.dart';
import 'package:smart_hotel_app/views/home/device/cubit/device_state.dart';
class DeviceCubit extends Cubit<DeviceState> {
DeviceCubit() : super(DeviceState(deviceInfo: _getDeviceInfo()));
static DeviceInfo _getDeviceInfo() {
return const DeviceInfo(
deviceName: '客房305 智能空开',
deviceId: 'A-305',
location: '3楼客房区',
status: '在线',
voltage: '220V',
current: '2.36A',
power: '520W',
temperature: '38°C',
powerData: [
40, 60, 85, 98, 85, 72, 60, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
],
tempData: [
28, 30, 32, 35, 33, 31, 30, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0
],
final DeviceControlService _service;
final int _deviceId;
DeviceCubit({
required DeviceControlService service,
required int deviceId,
}) : _service = service,
_deviceId = deviceId,
super(const DeviceState()) {
loadDetail();
}
Future<void> loadDetail() async {
emit(const DeviceState(isLoading: true));
try {
final detail = await _service.getDetail(deviceId: _deviceId);
emit(DeviceState(deviceInfo: _mapToDeviceInfo(detail)));
} catch (e) {
emit(DeviceState(error: e.toString()));
}
}
DeviceInfo _mapToDeviceInfo(DeviceControlBO detail) {
final basic = detail.deviceBasicInfo;
final params = detail.realtimeParams;
final status = basic.onlineStatus == '1' ? '在线' : '离线';
final powerData = detail.trendChart.dataPoints
.map((p) => p.power.toInt())
.toList();
final tempData = detail.trendChart.dataPoints
.map((p) => p.temperature.toInt())
.toList();
return DeviceInfo(
deviceName: basic.deviceName,
deviceId: basic.deviceCode,
location: basic.roomName,
status: status,
voltage: params.voltage,
current: params.current,
power: params.activePower,
temperature: params.deviceTemperature,
powerData: powerData,
tempData: tempData,
);
}
void remotePowerOn() {}
Future<void> remotePowerOn() async {
if (state.isPoweringOn) return;
emit(state.copyWith(isPoweringOn: true));
try {
await _service.powerOn(deviceId: _deviceId);
emit(state.copyWith(isPoweringOn: false));
} catch (e) {
emit(state.copyWith(isPoweringOn: false));
rethrow;
}
}
void remotePowerOff() {}
Future<void> remotePowerOff() async {
if (state.isPoweringOff) return;
emit(state.copyWith(isPoweringOff: true));
try {
await _service.powerOff(deviceId: _deviceId);
emit(state.copyWith(isPoweringOff: false));
} catch (e) {
emit(state.copyWith(isPoweringOff: false));
rethrow;
}
}
}
\ No newline at end of file
......@@ -25,7 +25,33 @@ class DeviceInfo {
}
class DeviceState {
final DeviceInfo deviceInfo;
final bool isLoading;
final String? error;
final DeviceInfo? deviceInfo;
final bool isPoweringOn;
final bool isPoweringOff;
const DeviceState({required this.deviceInfo});
const DeviceState({
this.isLoading = false,
this.error,
this.deviceInfo,
this.isPoweringOn = false,
this.isPoweringOff = false,
});
DeviceState copyWith({
bool? isLoading,
String? error,
DeviceInfo? deviceInfo,
bool? isPoweringOn,
bool? isPoweringOff,
}) {
return DeviceState(
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
deviceInfo: deviceInfo ?? this.deviceInfo,
isPoweringOn: isPoweringOn ?? this.isPoweringOn,
isPoweringOff: isPoweringOff ?? this.isPoweringOff,
);
}
}
\ No newline at end of file
......@@ -2,6 +2,8 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/repositories/device_control_repository.dart';
import 'package:smart_hotel_app/services/device_control_service.dart';
import 'package:smart_hotel_app/views/home/device/cubit/device_cubit.dart';
import 'package:smart_hotel_app/views/home/device/cubit/device_state.dart';
import 'package:smart_hotel_app/views/home/device/widget/device_parms_block.dart';
......@@ -10,12 +12,18 @@ import 'package:smart_hotel_app/views/home/device/widget/state_info_block.dart';
@RoutePage()
class DeviceDetailView extends StatelessWidget {
const DeviceDetailView({super.key});
final int deviceId;
const DeviceDetailView({super.key, required this.deviceId});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => DeviceCubit(),
create: (_) {
final repository = DeviceControlRepository();
final service = DeviceControlService(repository: repository);
return DeviceCubit(service: service, deviceId: deviceId);
},
child: Scaffold(
backgroundColor: const Color.fromRGBO(242, 243, 245, 1),
appBar: AppBar(
......@@ -38,31 +46,50 @@ class DeviceDetailView extends StatelessWidget {
),
centerTitle: true,
),
body: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 28.w),
child: BlocBuilder<DeviceCubit, DeviceState>(
builder: (context, state) {
final cubit = context.read<DeviceCubit>();
return Column(
body: BlocBuilder<DeviceCubit, DeviceState>(
builder: (context, state) {
if (state.isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (state.error != null) {
return Center(
child: Text(
'加载失败: ${state.error}',
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(255, 100, 101, 1),
),
),
);
}
final deviceInfo = state.deviceInfo;
if (deviceInfo == null) {
return const SizedBox.shrink();
}
final cubit = context.read<DeviceCubit>();
return SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 28.w),
child: Column(
children: [
StateInfoBlock(deviceInfo: state.deviceInfo),
StateInfoBlock(deviceInfo: deviceInfo),
SizedBox(height: 10.h),
DeviceParmsBlock(deviceInfo: state.deviceInfo),
DeviceParmsBlock(deviceInfo: deviceInfo),
SizedBox(height: 10.h),
PowerCharBlock(deviceInfo: state.deviceInfo),
PowerCharBlock(deviceInfo: deviceInfo),
SizedBox(height: 10.h),
_buildBottomButtons(cubit),
_buildBottomButtons(context, cubit, state),
SizedBox(height: 30.h),
],
);
},
),
),
);
},
),
),
);
}
Widget _buildBottomButtons(DeviceCubit cubit) {
Widget _buildBottomButtons(
BuildContext context, DeviceCubit cubit, DeviceState state) {
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 15.h),
......@@ -74,17 +101,30 @@ class DeviceDetailView extends StatelessWidget {
width: 300.w,
height: 88.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(73, 149, 234, 1),
color: state.isPoweringOn
? const Color.fromRGBO(73, 149, 234, 0.4)
: const Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(16.r),
),
child: TextButton(
onPressed: () => cubit.remotePowerOn(),
child: Text(
"远程送电",
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(237, 245, 255, 1)),
),
onPressed: state.isPoweringOn
? null
: () => _handlePowerOn(context, cubit),
child: state.isPoweringOn
? SizedBox(
width: 32.sp,
height: 32.sp,
child: const CircularProgressIndicator(
strokeWidth: 3,
color: Color.fromRGBO(237, 245, 255, 1),
),
)
: Text(
"远程送电",
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(237, 245, 255, 1)),
),
),
),
SizedBox(width: 30.w),
......@@ -92,25 +132,74 @@ class DeviceDetailView extends StatelessWidget {
width: 300.w,
height: 88.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(229, 241, 255, 1.0),
color: state.isPoweringOff
? const Color.fromRGBO(229, 241, 255, 0.6)
: const Color.fromRGBO(229, 241, 255, 1.0),
border: Border.all(
color: const Color.fromRGBO(73, 149, 234, 1),
color: state.isPoweringOff
? const Color.fromRGBO(73, 149, 234, 0.4)
: const Color.fromRGBO(73, 149, 234, 1),
width: 1.w,
),
borderRadius: BorderRadius.circular(16.r),
),
child: TextButton(
onPressed: () => cubit.remotePowerOff(),
child: Text(
"远程断电",
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(100, 116, 139, 1)),
),
onPressed: state.isPoweringOff
? null
: () => _handlePowerOff(context, cubit),
child: state.isPoweringOff
? SizedBox(
width: 32.sp,
height: 32.sp,
child: const CircularProgressIndicator(
strokeWidth: 3,
color: Color.fromRGBO(100, 116, 139, 1),
),
)
: Text(
"远程断电",
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(100, 116, 139, 1)),
),
),
),
],
),
);
}
Future<void> _handlePowerOn(BuildContext context, DeviceCubit cubit) async {
try {
await cubit.remotePowerOn();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('远程送电成功')),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('远程送电失败: $e')),
);
}
}
}
Future<void> _handlePowerOff(BuildContext context, DeviceCubit cubit) async {
try {
await cubit.remotePowerOff();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('远程断电成功')),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('远程断电失败: $e')),
);
}
}
}
}
\ No newline at end of file
......@@ -30,44 +30,7 @@ class HomeIndexCubit extends Cubit<HomeIndexState> {
highAlarmCount: dashboard.statistics.highAlertCount,
mediumAlarmCount: dashboard.statistics.mediumAlertCount,
onlineDeviceCount: dashboard.statistics.onlineDeviceCount,
temperatureAlarmTitle: dashboard.alerts.isNotEmpty
? dashboard.alerts[0].alertTitle
: '',
temperatureAlarmLocation: dashboard.alerts.isNotEmpty
? '${dashboard.alerts[0].roomName}·${dashboard.alerts[0].deviceName}'
: '',
currentTemperature: dashboard.alerts.isNotEmpty
? dashboard.alerts[0].temperature
: '',
currentVoltage:
dashboard.alerts.isNotEmpty ? dashboard.alerts[0].voltage : '',
currentCurrent:
dashboard.alerts.isNotEmpty ? dashboard.alerts[0].current : '',
waitTime: dashboard.alerts.isNotEmpty
? dashboard.alerts[0].waitingDurationDesc
: '',
alarmLevel: dashboard.alerts.isNotEmpty
? dashboard.alerts[0].alertLevelText
: '',
voltageAlarmTitle: dashboard.alerts.length > 1
? dashboard.alerts[1].alertTitle
: '',
voltageAlarmLocation: dashboard.alerts.length > 1
? '${dashboard.alerts[1].roomName}·${dashboard.alerts[1].deviceName}'
: '',
voltageValue: dashboard.alerts.length > 1
? dashboard.alerts[1].voltage
: '',
normalVoltage: '',
voltageWaitTime: dashboard.alerts.length > 1
? dashboard.alerts[1].waitingDurationDesc
: '',
voltageAlarmLevel: dashboard.alerts.length > 1
? dashboard.alerts[1].alertLevelText
: '',
voltageAlertId: dashboard.alerts.length > 1
? dashboard.alerts[1].alertId
: 0,
alerts: dashboard.alerts,
equipmentList: dashboard.devices
.map((d) => _mapDeviceToEquipment(d))
.toList(),
......
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:smart_hotel_app/models/bo/alert_dashboard_bo.dart';
class EquipmentItem {
final IconData icon;
......@@ -23,20 +24,7 @@ class HomeIndexState extends Equatable {
final int highAlarmCount;
final int mediumAlarmCount;
final int onlineDeviceCount;
final String temperatureAlarmTitle;
final String temperatureAlarmLocation;
final String currentTemperature;
final String currentVoltage;
final String currentCurrent;
final String waitTime;
final String alarmLevel;
final int voltageAlertId;
final String voltageAlarmTitle;
final String voltageAlarmLocation;
final String voltageValue;
final String normalVoltage;
final String voltageWaitTime;
final String voltageAlarmLevel;
final List<AlertItemBO> alerts;
final List<EquipmentItem> equipmentList;
const HomeIndexState({
......@@ -45,20 +33,7 @@ class HomeIndexState extends Equatable {
this.highAlarmCount = 0,
this.mediumAlarmCount = 0,
this.onlineDeviceCount = 0,
this.temperatureAlarmTitle = '',
this.temperatureAlarmLocation = '',
this.currentTemperature = '',
this.currentVoltage = '',
this.currentCurrent = '',
this.waitTime = '',
this.alarmLevel = '',
this.voltageAlarmTitle = '',
this.voltageAlarmLocation = '',
this.voltageValue = '',
this.normalVoltage = '',
this.voltageWaitTime = '',
this.voltageAlarmLevel = '',
this.voltageAlertId = 0,
this.alerts = const [],
this.equipmentList = const [],
});
......@@ -68,20 +43,7 @@ class HomeIndexState extends Equatable {
int? highAlarmCount,
int? mediumAlarmCount,
int? onlineDeviceCount,
String? temperatureAlarmTitle,
String? temperatureAlarmLocation,
String? currentTemperature,
String? currentVoltage,
String? currentCurrent,
String? waitTime,
String? alarmLevel,
int? voltageAlertId,
String? voltageAlarmTitle,
String? voltageAlarmLocation,
String? voltageValue,
String? normalVoltage,
String? voltageWaitTime,
String? voltageAlarmLevel,
List<AlertItemBO>? alerts,
List<EquipmentItem>? equipmentList,
}) {
return HomeIndexState(
......@@ -90,20 +52,7 @@ class HomeIndexState extends Equatable {
highAlarmCount: highAlarmCount ?? this.highAlarmCount,
mediumAlarmCount: mediumAlarmCount ?? this.mediumAlarmCount,
onlineDeviceCount: onlineDeviceCount ?? this.onlineDeviceCount,
temperatureAlarmTitle: temperatureAlarmTitle ?? this.temperatureAlarmTitle,
temperatureAlarmLocation: temperatureAlarmLocation ?? this.temperatureAlarmLocation,
currentTemperature: currentTemperature ?? this.currentTemperature,
currentVoltage: currentVoltage ?? this.currentVoltage,
currentCurrent: currentCurrent ?? this.currentCurrent,
waitTime: waitTime ?? this.waitTime,
alarmLevel: alarmLevel ?? this.alarmLevel,
voltageAlarmTitle: voltageAlarmTitle ?? this.voltageAlarmTitle,
voltageAlarmLocation: voltageAlarmLocation ?? this.voltageAlarmLocation,
voltageValue: voltageValue ?? this.voltageValue,
normalVoltage: normalVoltage ?? this.normalVoltage,
voltageWaitTime: voltageWaitTime ?? this.voltageWaitTime,
voltageAlarmLevel: voltageAlarmLevel ?? this.voltageAlarmLevel,
voltageAlertId: voltageAlertId ?? this.voltageAlertId,
alerts: alerts ?? this.alerts,
equipmentList: equipmentList ?? this.equipmentList,
);
}
......@@ -115,20 +64,7 @@ class HomeIndexState extends Equatable {
highAlarmCount,
mediumAlarmCount,
onlineDeviceCount,
temperatureAlarmTitle,
temperatureAlarmLocation,
currentTemperature,
currentVoltage,
currentCurrent,
waitTime,
alarmLevel,
voltageAlarmTitle,
voltageAlarmLocation,
voltageValue,
normalVoltage,
voltageWaitTime,
voltageAlarmLevel,
voltageAlertId,
alerts,
equipmentList,
];
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/models/bo/alert_dashboard_bo.dart';
import 'package:smart_hotel_app/repositories/alert_dashboard_repository.dart';
import 'package:smart_hotel_app/services/alert_dashboard_service.dart';
import 'package:smart_hotel_app/views/home/index/cubit/home_index_cubit.dart';
......@@ -46,26 +47,7 @@ class HomeView extends StatelessWidget {
mediumAlarmCount: state.mediumAlarmCount,
onlineDeviceCount: state.onlineDeviceCount,
),
SizedBox(height: 20.h),
TemperatureBlock(
temperatureAlarmTitle: state.temperatureAlarmTitle,
temperatureAlarmLocation: state.temperatureAlarmLocation,
currentTemperature: state.currentTemperature,
currentVoltage: state.currentVoltage,
currentCurrent: state.currentCurrent,
waitTime: state.waitTime,
alarmLevel: state.alarmLevel,
),
SizedBox(height: 20.h),
VoltageOperateBlock(
alertId: state.voltageAlertId,
voltageAlarmTitle: state.voltageAlarmTitle,
voltageAlarmLocation: state.voltageAlarmLocation,
voltageValue: state.voltageValue,
normalVoltage: state.normalVoltage,
voltageWaitTime: state.voltageWaitTime,
voltageAlarmLevel: state.voltageAlarmLevel,
),
..._buildAlertBlocks(state.alerts),
SizedBox(height: 20.h),
EquipmentListBlock(
equipmentList: state.equipmentList,
......@@ -82,4 +64,42 @@ class HomeView extends StatelessWidget {
),
);
}
List<Widget> _buildAlertBlocks(List<AlertItemBO> alerts) {
final blocks = <Widget>[];
for (final alert in alerts) {
final location = '${alert.roomName}·${alert.deviceName}';
switch (alert.alertCategory) {
case 'temperature':
blocks.addAll([
SizedBox(height: 20.h),
TemperatureBlock(
temperatureAlarmTitle: alert.alertTitle,
temperatureAlarmLocation: location,
currentTemperature: alert.temperature,
currentVoltage: alert.voltage,
currentCurrent: alert.current,
waitTime: alert.waitingDurationDesc,
alarmLevel: alert.alertLevelText,
),
]);
case 'voltage':
case 'current':
case 'power':
blocks.addAll([
SizedBox(height: 20.h),
VoltageOperateBlock(
alertId: alert.alertId,
voltageAlarmTitle: alert.alertTitle,
voltageAlarmLocation: location,
voltageValue: alert.voltage,
normalVoltage: '',
voltageWaitTime: alert.waitingDurationDesc,
voltageAlarmLevel: alert.alertLevelText,
),
]);
}
}
return blocks;
}
}
\ No newline at end of file
# 智慧酒店 App 接口对接方案
# 智慧酒店 App 接口对接方案
......@@ -183,10 +183,15 @@ class xxxBO extends Equatable {
| 登录页 |POST | /app/auth/login/password | 已对接 | 用户模块 |
| 告警 |GET | /app/alert/dashboard | 已对接 | 设备告警看板 |
| 告警详情 |GET | /app/alert/detail | 已对接 | 告警详情 |
| 告警详情-确认处理 |POST | /app/alert/handle | 未对接 | 告警详情 | 在告警详情页面点击 确认处理 按钮,调用该接口。需要做下防重复提交,处理过程中不可点。处理完成之后弹出操作成功/操作失败提示。成功之后按钮不可再点击 |
| 设备控制 |GET | /app/device/control/detail | 未对接 | 设备控制 | |
| 设备控制 |POST | /app/device/control/powerOn | 未对接 | 设备控制-远程送电 | 需要做下防重复提交,处理过程中不可点。处理完成之后弹出操作成功/操作失败提示 |
| 设备控制 |POST | /app/device/control/powerOff | 未对接 | 设备控制-远程断电 | 需要做下防重复提交,处理过程中不可点。处理完成之后弹出操作成功/操作失败提示|
| 告警详情-确认处理 |POST | /app/alert/handle | 已对接 | 告警详情 | 在告警详情页面点击 确认处理 按钮,调用该接口。需要做下防重复提交,处理过程中不可点。处理完成之后弹出操作成功/操作失败提示。成功之后按钮不可再点击 |
| 设备控制 |GET | /app/device/control/detail | 已对接 | 设备控制 | |
| 设备控制 |POST | /app/device/control/powerOn | 已对接 | 设备控制-远程送电 | 需要做下防重复提交,处理过程中不可点。处理完成之后弹出操作成功/操作失败提示 |
| 设备控制 |POST | /app/device/control/powerOff | 已对接 | 设备控制-远程断电 | 需要做下防重复提交,处理过程中不可点。处理完成之后弹出操作成功/操作失败提示|
| 设备拓扑 |GET | /app/device/topology | 未对接 | 设备拓扑 | 相关页面:InspectionTopologyView |
### 3.2 接口详细定义
......@@ -250,6 +255,7 @@ class xxxBO extends Equatable {
"alertLevel": "string", // 告警级别编码
"alertLevelText": "string", // 告警级别中文描述
"alertStatus": "string",// 告警状态编码(0=待处理,1=处理中,2=已处理,3=忽略,4=误报)
"alertCategory": "string", // 预警分类(temperature=温度 current=电流 voltage=电压 power=用电 device=设备)
"roomName": "string", // 所属房间名称
"deviceName": "string",// 告警设备名称
"alertValue": "string",
......@@ -405,6 +411,83 @@ class xxxBO extends Equatable {
}
```
#### 设备控制-远程送电
**POST /app/device/control/powerOn**
```
求体:
{
"deviceId": 0 // 设备ID
}
应 data:
{
"code": 0,
"msg": "string",
"data": {
"success": true,
"affectedDeviceCount": 0
}
}
```
#### 设备控制-远程断电
**POST /app/device/control/powerOff**
```
求体:
{
"deviceId": 0 // 设备ID
}
应 data:
{
"code": 0,
"msg": "string",
"data": {
"success": true,
"affectedDeviceCount": 0
}
}
```
#### 设备拓扑
**POST /app/device/topology**
```
求体:
{
"deviceId": 0 // 设备ID
}
应 data:
{
"code": 0,
"msg": "string",
"data": {
"deviceInfo": {
"deviceId": 0,
"deviceName": "string",
"deviceCode": "string",
"locationText": "string"
},
"treeNodes": [
{
"deviceId": 0,
"deviceName": "string",
"deviceType": "string",
"icon": "string",
"status": "string",
"statusText": "string",
"deviceCode": "string"
}
]
}
}
```
......
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