Commit 3a517340 authored by 张宏's avatar 张宏

.

parent 4f547179
...@@ -13,45 +13,55 @@ class ServiceRoomCubit extends Cubit<ServiceRoomState> { ...@@ -13,45 +13,55 @@ class ServiceRoomCubit extends Cubit<ServiceRoomState> {
final num = roomNumber ?? '302'; final num = roomNumber ?? '302';
final numInt = int.tryParse(num) ?? 302; final numInt = int.tryParse(num) ?? 302;
final statuses = ['空闲', '入住中', '待清洁']; final statuses = ['空闲', '入住中', '待清洁'];
final roomTypes = ['标准大床房', '豪华双床房', '商务套房', '总统套房'];
final guestNames = ['张先生', '李女士', '王先生', '赵女士', '刘先生'];
final months = ['5月', '6月', '7月', '8月'];
final statusIndex = numInt % 3; final statusIndex = numInt % 3;
final typeIndex = numInt % 4;
final guestIndex = numInt % 5;
final monthIndex = (numInt ~/ 100) % 4;
final hasGuest = numInt % 2 == 0;
final now = DateTime.now();
final refreshTime = '${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}';
emit(state.copyWith( emit(state.copyWith(
roomDetail: { roomNumber: num,
'roomNumber': num, roomStatus: statuses[statusIndex],
'status': statuses[statusIndex],
'guestName': statusIndex == 0 ? null : guestNames[guestIndex],
'checkInDate': statusIndex == 0 ? null : '${months[monthIndex]}${(numInt % 20) + 1}日',
'checkOutDate': statusIndex == 0 ? null : '${months[monthIndex]}${(numInt % 20) + 3}日',
'roomType': roomTypes[typeIndex],
},
roomStatus: {
'hasGuest': hasGuest,
'guestRefreshTime': refreshTime,
'powerOn': true,
'currentPower': '1.24kW',
'wifiNormal': true,
'wifiSignal': '-45dBm',
},
mainPowerOn: numInt % 2 == 0, mainPowerOn: numInt % 2 == 0,
devices: [ roomDevices: [
{'name': '空调', 'icon': Icons.air_outlined, 'status': '24°C·开', 'isOn': true}, const RoomDevice(
{'name': '照明', 'icon': Icons.light_outlined, 'status': '关', 'isOn': false}, name: '空调',
{'name': '电视', 'icon': Icons.tv_outlined, 'status': '开', 'isOn': true}, icon: Icons.air_outlined,
{'name': '窗帘', 'icon': Icons.curtains_closed_outlined, 'status': '关', 'isOn': false}, isOn: true,
statusText: '24°C·开',
),
const RoomDevice(
name: '照明',
icon: Icons.light_outlined,
isOn: false,
statusText: '关',
),
const RoomDevice(
name: '电视',
icon: Icons.tv_outlined,
isOn: true,
statusText: '开',
),
const RoomDevice(
name: '窗帘',
icon: Icons.curtains_closed_outlined,
isOn: false,
statusText: '关',
),
], ],
deviceControls: [ controlDevices: [
{'name': '空调', 'icon': Icons.air_outlined, 'status': '当前:制冷24°C·风速:自动', 'isOn': true}, const ControlDevice(
{'name': '主照明', 'icon': Icons.light_outlined, 'status': null, 'isOn': false}, name: '空调',
{'name': '电视', 'icon': Icons.tv_outlined, 'status': null, 'isOn': true}, icon: Icons.air_outlined,
isOn: true,
detailText: '当前:制冷24°C·风速:自动',
),
const ControlDevice(
name: '主照明',
icon: Icons.light_outlined,
isOn: false,
),
const ControlDevice(
name: '电视',
icon: Icons.tv_outlined,
isOn: true,
),
], ],
)); ));
} }
...@@ -59,4 +69,17 @@ class ServiceRoomCubit extends Cubit<ServiceRoomState> { ...@@ -59,4 +69,17 @@ class ServiceRoomCubit extends Cubit<ServiceRoomState> {
void toggleMainPower(bool value) { void toggleMainPower(bool value) {
emit(state.copyWith(mainPowerOn: value)); emit(state.copyWith(mainPowerOn: value));
} }
void toggleControlDevice(int index, bool value) {
final updatedDevices = List<ControlDevice>.from(state.controlDevices);
if (index >= 0 && index < updatedDevices.length) {
updatedDevices[index] = ControlDevice(
name: updatedDevices[index].name,
icon: updatedDevices[index].icon,
isOn: value,
detailText: updatedDevices[index].detailText,
);
emit(state.copyWith(controlDevices: updatedDevices));
}
}
} }
\ No newline at end of file
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
enum RoomStatusTag { hasPerson, powerOn, wifiNormal }
class RoomDevice {
final String name;
final IconData icon;
final bool isOn;
final String? statusText;
const RoomDevice({
required this.name,
required this.icon,
this.isOn = false,
this.statusText,
});
}
class ControlDevice {
final String name;
final IconData icon;
final bool isOn;
final String? detailText;
const ControlDevice({
required this.name,
required this.icon,
this.isOn = false,
this.detailText,
});
}
class ServiceRoomState extends Equatable { class ServiceRoomState extends Equatable {
final Map<String, dynamic> roomDetail; final String roomNumber;
final Map<String, dynamic> roomStatus; final String roomStatus;
final List<RoomStatusTag> statusTags;
final List<RoomDevice> roomDevices;
final bool mainPowerOn; final bool mainPowerOn;
final List<Map<String, dynamic>> devices; final List<ControlDevice> controlDevices;
final List<Map<String, dynamic>> deviceControls;
const ServiceRoomState({ const ServiceRoomState({
this.roomDetail = const {}, this.roomNumber = '302',
this.roomStatus = const {}, this.roomStatus = '入住中',
this.statusTags = const [RoomStatusTag.hasPerson, RoomStatusTag.powerOn, RoomStatusTag.wifiNormal],
this.roomDevices = const [],
this.mainPowerOn = false, this.mainPowerOn = false,
this.devices = const [], this.controlDevices = const [],
this.deviceControls = const [],
}); });
ServiceRoomState copyWith({ ServiceRoomState copyWith({
Map<String, dynamic>? roomDetail, String? roomNumber,
Map<String, dynamic>? roomStatus, String? roomStatus,
List<RoomStatusTag>? statusTags,
List<RoomDevice>? roomDevices,
bool? mainPowerOn, bool? mainPowerOn,
List<Map<String, dynamic>>? devices, List<ControlDevice>? controlDevices,
List<Map<String, dynamic>>? deviceControls,
}) { }) {
return ServiceRoomState( return ServiceRoomState(
roomDetail: roomDetail ?? this.roomDetail, roomNumber: roomNumber ?? this.roomNumber,
roomStatus: roomStatus ?? this.roomStatus, roomStatus: roomStatus ?? this.roomStatus,
statusTags: statusTags ?? this.statusTags,
roomDevices: roomDevices ?? this.roomDevices,
mainPowerOn: mainPowerOn ?? this.mainPowerOn, mainPowerOn: mainPowerOn ?? this.mainPowerOn,
devices: devices ?? this.devices, controlDevices: controlDevices ?? this.controlDevices,
deviceControls: deviceControls ?? this.deviceControls,
); );
} }
@override @override
List<Object?> get props => [ List<Object?> get props => [
roomDetail, roomNumber,
roomStatus, roomStatus,
statusTags,
roomDevices,
mainPowerOn, mainPowerOn,
devices, controlDevices,
deviceControls,
]; ];
} }
\ No newline at end of file
...@@ -4,9 +4,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; ...@@ -4,9 +4,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/cubit/service_room_cubit.dart'; import 'package:smart_hotel_app/views/service/room/cubit/service_room_cubit.dart';
import 'package:smart_hotel_app/views/service/room/cubit/service_room_state.dart'; import 'package:smart_hotel_app/views/service/room/cubit/service_room_state.dart';
import 'package:smart_hotel_app/views/service/room/widget/bottom_operation_block.dart'; import 'package:smart_hotel_app/views/service/room/widget/room_overview_card.dart';
import 'package:smart_hotel_app/views/service/room/widget/device_control_block.dart'; import 'package:smart_hotel_app/views/service/room/widget/room_device_status_card.dart';
import 'package:smart_hotel_app/views/service/room/widget/room_info_block.dart'; import 'package:smart_hotel_app/views/service/room/widget/device_control_card.dart';
import 'package:smart_hotel_app/views/service/room/widget/room_bottom_buttons.dart';
@RoutePage() @RoutePage()
class ServiceRoomDetailView extends StatelessWidget { class ServiceRoomDetailView extends StatelessWidget {
...@@ -44,21 +45,28 @@ class ServiceRoomDetailView extends StatelessWidget { ...@@ -44,21 +45,28 @@ class ServiceRoomDetailView extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 28.w), padding: EdgeInsets.symmetric(horizontal: 28.w),
child: BlocBuilder<ServiceRoomCubit, ServiceRoomState>( child: BlocBuilder<ServiceRoomCubit, ServiceRoomState>(
builder: (context, state) { builder: (context, state) {
final cubit = context.read<ServiceRoomCubit>();
return Column( return Column(
children: [ children: [
SizedBox(height: 20.h), SizedBox(height: 20.h),
RoomInfoBlock( RoomOverviewCard(
roomDetail: state.roomDetail, roomNumber: state.roomNumber,
roomStatus: state.roomStatus, roomStatus: state.roomStatus,
statusTags: state.statusTags,
), ),
SizedBox(height: 20.h), SizedBox(height: 20.h),
DeviceControlBlock( RoomDeviceStatusCard(
devices: state.roomDevices,
),
SizedBox(height: 20.h),
DeviceControlCard(
mainPowerOn: state.mainPowerOn, mainPowerOn: state.mainPowerOn,
deviceControls: state.deviceControls, controlDevices: state.controlDevices,
devices: state.devices, onMainPowerToggle: (value) => cubit.toggleMainPower(value),
onDeviceToggle: (index, value) => cubit.toggleControlDevice(index, value),
), ),
SizedBox(height: 20.h), SizedBox(height: 20.h),
const BottomOperationBlock(), const RoomBottomButtons(),
SizedBox(height: 20.h), SizedBox(height: 20.h),
], ],
); );
......
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_switch/flutter_switch.dart';
import 'package:smart_hotel_app/views/service/room/cubit/service_room_state.dart';
class DeviceControlCard extends StatelessWidget {
final bool mainPowerOn;
final List<ControlDevice> controlDevices;
final Function(bool) onMainPowerToggle;
final Function(int, bool) onDeviceToggle;
const DeviceControlCard({
super.key,
required this.mainPowerOn,
required this.controlDevices,
required this.onMainPowerToggle,
required this.onDeviceToggle,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.r),
),
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'设备控制',
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(10, 13, 20, 1.0),
),
),
SizedBox(height: 20.h),
_buildMainPowerControl(),
SizedBox(height: 24.h),
Text(
'分设备控制',
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(10, 13, 20, 1.0),
),
),
SizedBox(height: 20.h),
...controlDevices.asMap().entries.map((entry) {
final index = entry.key;
final device = entry.value;
return Padding(
padding: EdgeInsets.only(bottom: index < controlDevices.length - 1 ? 20.h : 0),
child: _buildDeviceControl(index, device),
);
}).toList(),
],
),
);
}
Widget _buildMainPowerControl() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 64.w,
height: 64.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(235, 244, 255, 1.0),
borderRadius: BorderRadius.circular(12.r),
),
child: Icon(
Icons.access_time_outlined,
color: const Color.fromRGBO(66, 165, 245, 1.0),
size: 36.sp,
),
),
SizedBox(width: 16.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'房间总电源',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(10, 13, 20, 1.0),
),
),
Text(
'控制整个房间供电',
style: TextStyle(
fontSize: 24.sp,
color: const Color.fromRGBO(100, 116, 139, 1.0),
),
),
],
),
],
),
FlutterSwitch(
value: mainPowerOn,
onToggle: onMainPowerToggle,
activeColor: const Color.fromRGBO(59, 130, 246, 1),
inactiveColor: const Color.fromRGBO(209, 213, 219, 1),
width: 60.w,
height: 30.h,
toggleSize: 26,
),
],
),
SizedBox(height: 20.h),
Divider(
color: const Color.fromRGBO(242, 243, 245, 1.0),
thickness: 1.h,
),
],
);
}
Widget _buildDeviceControl(int index, ControlDevice device) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
device.icon,
color: const Color.fromRGBO(66, 165, 245, 1.0),
size: 36.sp,
),
SizedBox(width: 8.w),
Text(
device.name,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(10, 13, 20, 1.0),
),
),
],
),
if (device.detailText != null) ...[
SizedBox(height: 8.h),
Text(
device.detailText!,
style: TextStyle(
fontSize: 24.sp,
color: const Color.fromRGBO(100, 116, 139, 1.0),
),
),
],
],
),
),
FlutterSwitch(
value: device.isOn,
onToggle: (value) => onDeviceToggle(index, value),
activeColor: const Color.fromRGBO(66, 165, 245, 1.0),
inactiveColor: const Color.fromRGBO(200, 208, 220, 1.0),
width: 60.w,
height: 30.h,
toggleSize: 26,
),
],
),
if (index < controlDevices.length - 1) ...[
SizedBox(height: 20.h),
Divider(
color: const Color.fromRGBO(242, 243, 245, 1.0),
thickness: 1.h,
),
],
],
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class RoomBottomButtons extends StatelessWidget {
const RoomBottomButtons({super.key});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: Container(
height: 88.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(66, 165, 245, 1.0),
borderRadius: BorderRadius.circular(20.r),
),
child: Center(
child: Text(
'送电',
style: TextStyle(
color: Colors.white,
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(width: 12.w),
Expanded(
child: Container(
height: 88.h,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.r),
border: Border.all(
color: const Color.fromRGBO(66, 165, 245, 1.0),
width: 2.w,
),
),
child: Center(
child: Text(
'断电',
style: TextStyle(
color: const Color.fromRGBO(66, 165, 245, 1.0),
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(width: 12.w),
Expanded(
child: Container(
height: 88.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(200, 208, 220, 1.0),
borderRadius: BorderRadius.circular(20.r),
),
child: Center(
child: Text(
'设备控制',
style: TextStyle(
color: const Color.fromRGBO(100, 116, 139, 1.0),
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/cubit/service_room_state.dart';
class RoomDeviceStatusCard extends StatelessWidget {
final List<RoomDevice> devices;
const RoomDeviceStatusCard({
super.key,
required this.devices,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.r),
),
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'房间设备状态',
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(10, 13, 20, 1.0),
),
),
SizedBox(height: 20.h),
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16.w,
mainAxisSpacing: 16.h,
childAspectRatio: 2,
),
itemCount: devices.length,
itemBuilder: (context, index) {
final device = devices[index];
return Container(
decoration: BoxDecoration(
color: const Color.fromRGBO(235, 244, 255, 1.0),
borderRadius: BorderRadius.circular(28.r),
),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
device.icon,
color: const Color.fromRGBO(66, 165, 245, 1.0),
size: 36.sp,
),
SizedBox(width: 8.w),
Text(
device.name,
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(66, 165, 245, 1.0),
fontWeight: FontWeight.bold,
),
),
],
),
SizedBox(height: 12.h),
if (device.statusText != null)
Text(
device.statusText!,
style: TextStyle(
fontSize: 26.sp,
color: device.isOn
? const Color.fromRGBO(26, 188, 156, 1.0)
: const Color.fromRGBO(100, 116, 139, 1.0),
),
),
],
),
);
},
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/cubit/service_room_state.dart';
class RoomOverviewCard extends StatelessWidget {
final String roomNumber;
final String roomStatus;
final List<RoomStatusTag> statusTags;
const RoomOverviewCard({
super.key,
required this.roomNumber,
required this.roomStatus,
required this.statusTags,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(24.r),
),
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 88.w,
height: 88.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(235, 244, 255, 1.0),
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
Icons.bed_outlined,
color: const Color.fromRGBO(66, 165, 245, 1.0),
size: 48.sp,
),
),
SizedBox(width: 20.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
roomNumber,
style: TextStyle(
fontSize: 36.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(10, 13, 20, 1.0),
),
),
SizedBox(width: 12.w),
Text(
roomStatus,
style: TextStyle(
fontSize: 28.sp,
color: const Color.fromRGBO(66, 165, 245, 1.0),
),
),
],
),
],
),
],
),
SizedBox(height: 24.h),
Wrap(
spacing: 8.w,
children: statusTags.map((tag) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
decoration: BoxDecoration(
color: const Color.fromRGBO(225, 245, 238, 1.0),
borderRadius: BorderRadius.circular(12.r),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.check,
color: const Color.fromRGBO(26, 188, 156, 1.0),
size: 20.sp,
),
SizedBox(width: 4.w),
Text(
_getTagLabel(tag),
style: TextStyle(
fontSize: 24.sp,
color: const Color.fromRGBO(26, 188, 156, 1.0),
),
),
],
),
);
}).toList(),
),
],
),
);
}
String _getTagLabel(RoomStatusTag tag) {
switch (tag) {
case RoomStatusTag.hasPerson:
return '有人';
case RoomStatusTag.powerOn:
return '通电中';
case RoomStatusTag.wifiNormal:
return 'wifi正常';
}
}
}
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