Commit 165f6cbb authored by 张宏's avatar 张宏

.

parent e12f65bf
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "smart_hotel_app",
"request": "launch",
"type": "dart"
},
{
"name": "smart_hotel_app (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "smart_hotel_app (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}
\ No newline at end of file
This diff is collapsed.
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/index/controller.dart';
class ServiceHeadBlock extends StatefulWidget {
const ServiceHeadBlock({super.key});
......@@ -9,80 +10,65 @@ class ServiceHeadBlock extends StatefulWidget {
}
class _ServiceHeadBlockState extends State<ServiceHeadBlock> {
late final ServiceIndexController _controller;
@override
void initState() {
super.initState();
_controller = ServiceIndexController(context);
}
@override
Widget build(BuildContext context) {
final pendingCount = _controller.getPendingCount();
return Container(
width: double.infinity,
height: 140.h,
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight, left: 20.w, right: 20.w),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color.fromRGBO(30, 41, 59, 1),
width: 1.w,
),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 4.w,
height: 20.h,
decoration: BoxDecoration(
color: Color.fromRGBO(239, 68, 68, 1),
borderRadius: BorderRadius.circular(2.r),
),
),
SizedBox(width: 10.w),
Text(
'客房服务看板',
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
SizedBox(height: 8.h),
Text(
'服务员视角 · 2条待响应需求',
style: TextStyle(
fontSize: 16.sp,
color: Color.fromRGBO(61, 79, 106, 1.0),
),
),
],
),
Container(
width: 50.w,
height: 50.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: Color.fromRGBO(51, 65, 85, 1),
border: Border.all(
color: Color.fromRGBO(71, 85, 105, 1),
width: 1.w,
),
Text(
'客房服务看板',
style: TextStyle(
fontSize: 40.sp,
fontWeight: FontWeight.w200,
color: Color.fromRGBO(10, 13, 20, 1),
),
child: Icon(
Icons.person,
color: Colors.white,
size: 24.sp,
),
SizedBox(height: 8.h),
Text(
'服务员视角·$pendingCount条待响应需求',
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
],
),
Container(
width: 64.w,
height: 64.h,
margin: EdgeInsets.only(top: 5.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(48.r),
color: Color.fromRGBO(229, 241, 255, 1),
border: Border.all(
color: Color.fromRGBO(73, 149, 234, 1),
width: 1.w,
),
),
child:
Image.asset("lib/assets/icon/person1.png",width: 38.w,height: 38.h),
// Icon(
// Icons.person,
// color: Color.fromRGBO(64, 158, 255, 1),
// size: 26.sp,
// ),
),
],
),
);
......
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/index/controller.dart';
class ServiceStatsBlock extends StatefulWidget {
const ServiceStatsBlock({super.key});
......@@ -9,34 +10,45 @@ class ServiceStatsBlock extends StatefulWidget {
}
class _ServiceStatsBlockState extends State<ServiceStatsBlock> {
late final ServiceIndexController _controller;
@override
void initState() {
super.initState();
_controller = ServiceIndexController(context);
}
@override
Widget build(BuildContext context) {
final pendingCount = _controller.getPendingCount();
final occupiedCount = _controller.getOccupiedRooms();
final vacantCount = _controller.getVacantRooms();
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 20.h),
child: Row(
children: [
Expanded(
child: _buildStatCard(
'2',
pendingCount.toString(),
'待响应',
Color.fromRGBO(59, 130, 246, 1),
Color.fromRGBO(73, 149, 234, 1),
),
),
SizedBox(width: 12.w),
Expanded(
child: _buildStatCard(
'45',
occupiedCount.toString(),
'入住中',
Color.fromRGBO(34, 197, 94, 1),
Color.fromRGBO(20, 184, 166, 1),
),
),
SizedBox(width: 12.w),
Expanded(
child: _buildStatCard(
'7',
vacantCount.toString(),
'空闲可清洁',
Colors.white,
Color.fromRGBO(10, 13, 20, 1),
),
),
],
......@@ -48,25 +60,32 @@ class _ServiceStatsBlockState extends State<ServiceStatsBlock> {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
color: Color.fromRGBO(30, 41, 59, 1),
borderRadius: BorderRadius.circular(24.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.05),
blurRadius: 10.r,
offset: Offset(0, 2),
),
],
),
child: Column(
children: [
Text(
value,
style: TextStyle(
fontSize: 28.sp,
fontSize: 60.sp,
fontWeight: FontWeight.bold,
color: valueColor,
),
),
SizedBox(height: 8.h),
// SizedBox(height: 5.h),
Text(
label,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
],
......
......@@ -34,10 +34,12 @@ class _ServiceIndexViewState extends State<ServiceIndexView> {
),
child: Container(
width: double.infinity,
color: Color.fromRGBO(15, 23, 42, 1),
color: Color.fromRGBO(242, 243, 245, 1),
padding: EdgeInsets.symmetric(horizontal: 28.w),
child: Column(
children: [
ServiceHeadBlock(),
SizedBox(height: 10.h),
ServiceStatsBlock(),
SizedBox(height: 10.h),
RoomManagementBlock(),
......
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class BottomOperationBlock extends StatefulWidget {
const BottomOperationBlock({super.key});
@override
State<BottomOperationBlock> createState() => _BottomOperationBlockState();
}
class _BottomOperationBlockState extends State<BottomOperationBlock> {
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: _buildOperationButton(
'送电',
Color.fromRGBO(73, 149, 234, 1),
Colors.white,
null,
),
),
SizedBox(width: 16.w),
Expanded(
child: _buildOperationButton(
'断电',
Color.fromRGBO(229, 241, 255, 1),
Color.fromRGBO(73, 149, 234, 1),
BorderSide(
color: Color.fromRGBO(73, 149, 234, 1),
width: 1.w,
),
),
),
SizedBox(width: 16.w),
Expanded(
child: _buildOperationButton(
'设备控制',
Color.fromRGBO(100, 116, 139, 0.2),
Color.fromRGBO(100, 116, 139, 1),
null,
),
),
],
);
}
Widget _buildOperationButton(
String text,
Color backgroundColor,
Color textColor,
BorderSide? borderSide,
) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor,
minimumSize: Size(double.infinity, 88.h),
padding: EdgeInsets.zero,
shape: borderSide != null
? RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
side: borderSide,
)
: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
),
onPressed: () {},
child: Text(
text,
style: TextStyle(
fontSize: 28.sp,
color: textColor,
fontWeight: FontWeight.w500,
),
),
);
}
}
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/controller.dart';
class DeviceControlBlock extends StatefulWidget {
const DeviceControlBlock({super.key});
@override
State<DeviceControlBlock> createState() => _DeviceControlBlockState();
}
class _DeviceControlBlockState extends State<DeviceControlBlock> {
late final ServiceRoomController _controller;
late bool _mainPowerOn;
late List<bool> _devicePowerStates;
@override
void initState() {
super.initState();
_controller = ServiceRoomController(context);
_mainPowerOn = _controller.getMainPowerOn();
final deviceControls = _controller.getDeviceControls();
_devicePowerStates = deviceControls.map((d) => d['isOn'] as bool).toList();
}
@override
Widget build(BuildContext context) {
final deviceControls = _controller.getDeviceControls();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'设备控制',
style: TextStyle(
fontSize: 28.sp,
color: Color.fromRGBO(0, 0, 0, 1),
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 20.h),
Container(
width: double.infinity,
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.r),
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildMainPowerControl(),
SizedBox(height: 20.h),
_buildDivider(),
SizedBox(height: 20.h),
_buildSubDeviceTitle(),
SizedBox(height: 20.h),
...deviceControls.asMap().entries.map((entry) {
final index = entry.key;
final device = entry.value;
return Column(
children: [
_buildDeviceControlItem(device, index),
if (index < deviceControls.length - 1) SizedBox(height: 20.h),
if (index < deviceControls.length - 1) _buildDivider(),
if (index < deviceControls.length - 1) SizedBox(height: 20.h),
],
);
}).toList(),
],
),
),
],
);
}
Widget _buildMainPowerControl() {
return Row(
children: [
Container(
width: 60.w,
height: 60.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.r),
color: Color.fromRGBO(229, 241, 255, 1),
),
child: Icon(
Icons.power_settings_new_outlined,
size: 36.sp,
color: Color.fromRGBO(73, 149, 234, 1),
),
),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'房间总电源',
style: TextStyle(
fontSize: 28.sp,
color: Color.fromRGBO(0, 0, 0, 1),
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 4.h),
Text(
'控制整个房间供电',
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
],
),
),
FlutterSwitch(
value: _mainPowerOn,
onToggle: (value) {
setState(() {
_mainPowerOn = value;
});
},
width: 60.w,
height: 30.h,
toggleSize: 26.sp,
borderRadius: 16.r,
padding: 3.r,
activeColor: Color.fromRGBO(80, 162, 255, 1),
inactiveColor: Color.fromRGBO(200, 200, 200, 1),
toggleColor: Colors.white,
),
],
);
}
Widget _buildDivider() {
return Container(
height: 1.h,
color: Color.fromRGBO(229, 231, 235, 1),
);
}
Widget _buildSubDeviceTitle() {
return Text(
'分设备控制',
style: TextStyle(
fontSize: 28.sp,
color: Color.fromRGBO(0, 0, 0, 1),
fontWeight: FontWeight.bold,
),
);
}
Widget _buildDeviceControlItem(Map<String, dynamic> device, int index) {
return Row(
children: [
Icon(
device['icon'] as IconData,
size: 40.sp,
color: Color.fromRGBO(73, 149, 234, 1),
),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
device['name'] as String,
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(0, 0, 0, 1),
),
),
if (device['status'] != null) ...[
SizedBox(height: 4.h),
Text(
device['status'] as String,
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
],
],
),
),
FlutterSwitch(
value: _devicePowerStates[index],
onToggle: (value) {
setState(() {
_devicePowerStates[index] = value;
});
},
width: 60.w,
height: 30.h,
toggleSize: 26.sp,
borderRadius: 16.r,
padding: 3.r,
activeColor: Color.fromRGBO(80, 162, 255, 1),
inactiveColor: Color.fromRGBO(200, 200, 200, 1),
toggleColor: Colors.white,
),
],
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/controller.dart';
class RoomStatusBlock extends StatefulWidget {
final ServiceRoomController controller;
const RoomStatusBlock({
super.key,
required this.controller,
});
@override
State<RoomStatusBlock> createState() => _RoomStatusBlockState();
}
class _RoomStatusBlockState extends State<RoomStatusBlock> {
@override
Widget build(BuildContext context) {
final roomStatus = widget.controller.getRoomStatus();
final hasGuest = roomStatus['hasGuest'] as bool;
final guestRefreshTime = roomStatus['guestRefreshTime'] as String;
final powerOn = roomStatus['powerOn'] as bool;
final currentPower = roomStatus['currentPower'] as String;
final wifiNormal = roomStatus['wifiNormal'] as bool;
final wifiSignal = roomStatus['wifiSignal'] as String;
return Container(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 20.w),
child: Column(
children: [
SizedBox(height: 20.h),
Row(
children: [
Expanded(
child: _buildStatusCard(
icon: Icons.person_outline,
title: '有客人',
subtitle: hasGuest ? '有人在房内' : '无人在房内',
extraInfo: '感应器刷新 · $guestRefreshTime',
isActive: hasGuest,
),
),
SizedBox(width: 12.w),
Expanded(
child: _buildStatusCard(
icon: Icons.flash_on,
title: '没有电',
subtitle: powerOn ? '通电运行中' : '断电中',
extraInfo: '当前功率 $currentPower',
isActive: powerOn,
),
),
],
),
SizedBox(height: 12.h),
Row(
children: [
Expanded(
child: _buildStatusCard(
icon: Icons.wifi,
title: '没有网',
subtitle: wifiNormal ? 'WiFi正常' : 'WiFi异常',
extraInfo: '信号强度 $wifiSignal',
isActive: wifiNormal,
),
),
SizedBox(width: 12.w),
Expanded(child: Container()),
],
),
],
),
);
}
Widget _buildStatusCard({
required IconData icon,
required String title,
required String subtitle,
required String extraInfo,
required bool isActive,
}) {
final activeColor = Color.fromRGBO(34, 197, 94, 1);
final inactiveColor = Color.fromRGBO(148, 163, 184, 1);
final bgColor = isActive
? Color.fromRGBO(34, 197, 94, 0.1)
: Color.fromRGBO(51, 65, 85, 1);
final color = isActive ? activeColor : inactiveColor;
return Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
color: Color.fromRGBO(30, 41, 59, 1),
border: Border.all(
color: Color.fromRGBO(71, 85, 105, 1),
width: 1.w,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(icon, color: color, size: 20.sp),
SizedBox(width: 8.w),
Text(
title,
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey,
),
),
],
),
SizedBox(height: 12.h),
Row(
children: [
Icon(
isActive ? Icons.check_circle : Icons.cancel,
color: color,
size: 18.sp,
),
SizedBox(width: 6.w),
Text(
subtitle,
style: TextStyle(
fontSize: 14.sp,
color: color,
fontWeight: FontWeight.w500,
),
),
],
),
SizedBox(height: 8.h),
Text(
extraInfo,
style: TextStyle(
fontSize: 11.sp,
color: Colors.grey,
),
),
],
),
);
}
}
......@@ -48,4 +48,68 @@ class ServiceRoomController {
'wifiSignal': '-45dBm',
};
}
bool getMainPowerOn() {
final num = roomNumber ?? '302';
final numInt = int.tryParse(num) ?? 302;
return numInt % 2 == 0;
}
List<Map<String, dynamic>> getDevices() {
final num = roomNumber ?? '302';
final numInt = int.tryParse(num) ?? 302;
return [
{
'name': '空调',
'icon': Icons.air_outlined,
'status': '24°C·开',
'isOn': true,
},
{
'name': '照明',
'icon': Icons.light_outlined,
'status': '关',
'isOn': false,
},
{
'name': '电视',
'icon': Icons.tv_outlined,
'status': '开',
'isOn': true,
},
{
'name': '窗帘',
'icon': Icons.curtains_closed_outlined,
'status': '关',
'isOn': false,
},
];
}
List<Map<String, dynamic>> getDeviceControls() {
final num = roomNumber ?? '302';
final numInt = int.tryParse(num) ?? 302;
return [
{
'name': '空调',
'icon': Icons.air_outlined,
'status': '当前:制冷24°C·风速:自动',
'isOn': true,
},
{
'name': '主照明',
'icon': Icons.light_outlined,
'status': null,
'isOn': false,
},
{
'name': '电视',
'icon': Icons.tv_outlined,
'status': null,
'isOn': true,
},
];
}
}
\ No newline at end of file
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/child/room_info_block.dart';
import 'package:smart_hotel_app/views/service/room/child/room_status_block.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/controller.dart';
import 'package:smart_hotel_app/views/service/room/child/room_info_block.dart';
import 'package:smart_hotel_app/views/service/room/child/device_control_block.dart';
import 'package:smart_hotel_app/views/service/room/child/bottom_operation_block.dart';
@RoutePage()
class ServiceRoomDetailView extends StatefulWidget {
......@@ -28,32 +29,38 @@ class _ServiceRoomDetailViewState extends State<ServiceRoomDetailView> {
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(15, 23, 42, 1),
backgroundColor: Color.fromRGBO(242, 243, 245, 1),
appBar: AppBar(
backgroundColor: Color.fromRGBO(15, 23, 42, 1),
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
icon: Icon(Icons.arrow_back_ios, color: Color.fromRGBO(100, 116, 139, 1),),
onPressed: () {
context.popRoute();
},
),
title: Text(
'${widget.roomNumber ?? '客房'}详情',
// '${widget.roomNumber ?? '客房'}详情',
'客房详情',
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(10, 13, 20, 1),
fontSize: 32.sp,
fontWeight: FontWeight.w200,
),
),
centerTitle: true,
),
body: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 28.w),
child: Column(
children: [
SizedBox(height: 20.h),
RoomInfoBlock(),
SizedBox(height: 20.h),
DeviceControlBlock(),
SizedBox(height: 20.h),
BottomOperationBlock(),
SizedBox(height: 20.h),
RoomInfoBlock(controller: _controller),
RoomStatusBlock(controller: _controller),
],
),
),
......
......@@ -350,6 +350,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.2"
flutter_switch:
dependency: "direct main"
description:
name: flutter_switch
sha256: b91477f926bba135d2d203d7b24367492662d8d9c3aa6adb960b14c1087d3c41
url: "https://pub.dev"
source: hosted
version: "0.3.2"
flutter_test:
dependency: "direct dev"
description: flutter
......
......@@ -44,6 +44,7 @@ dependencies:
fluttertoast: ^8.2.5
loading_animation_widget: ^1.3.0
fl_chart: ^1.2.0
flutter_switch: ^0.3.2
dev_dependencies:
flutter_test:
......
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