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
import 'dart:io';
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:smart_hotel_app/blocs/auth/auth_bloc.dart';
......@@ -40,6 +42,15 @@ class _LoginViewState extends State<LoginView> {
storageService: StorageService(),
);
_loadSavedCredentials();
// 设置状态栏样式
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.light,
),
);
}
Future<void> _loadSavedCredentials() async {
......@@ -55,118 +66,129 @@ class _LoginViewState extends State<LoginView> {
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Container(
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.only(left: 50.w, right: 50.w),
decoration: BoxDecoration(
color: Color(0xFFF5F7FA),
),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 150.h),
Container(
margin: EdgeInsets.only(bottom: 80.h),
child: Column(
children: [
Container(
width: 160.w,
height: 160.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40.w),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF00C6FF),
Color(0xFF0072FF),
],
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.light,
),
child: Scaffold(
backgroundColor: Color(0xFFF5F7FA),
resizeToAvoidBottomInset: true,
body: SafeArea(
top: false,
child: Container(
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.only(left: 50.w, right: 50.w),
decoration: BoxDecoration(
color: Color(0xFFF5F7FA),
),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 150.h),
Container(
margin: EdgeInsets.only(bottom: 80.h),
child: Column(
children: [
Container(
width: 160.w,
height: 160.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40.w),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF00C6FF),
Color(0xFF0072FF),
],
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(40.w),
child: Image.asset(
'lib/assets/login/logo@2x.png',
fit: BoxFit.cover,
),
),
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(40.w),
child: Image.asset(
'lib/assets/login/logo@2x.png',
fit: BoxFit.cover,
SizedBox(height: 40.h),
Text(
"智能酒店管理系统",
style: TextStyle(
color: Color(0xFF333333),
fontSize: 36.sp,
fontWeight: FontWeight.bold,
),
),
),
),
SizedBox(height: 40.h),
Text(
"智能酒店管理系统",
style: TextStyle(
color: Color(0xFF333333),
fontSize: 36.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 10.h),
Text(
"Intelligent Hotel Management System",
style: TextStyle(
color: Color(0xFF999999),
fontSize: 24.sp,
),
),
],
),
),
Form(
key: _frmGlobalKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
UsernameField(
controller: _txtUserNameController,
),
SizedBox(height: 20.h),
PasswordField(
controller: _txtPwdController,
),
SizedBox(height: 30.h),
RememberPasswordRow(
value: _rememberPassword,
onChanged: (val) {
setState(() {
_rememberPassword = val ?? false;
});
},
onForgotPassword: _loginController.forgotPwd,
),
SizedBox(height: 10.h),
BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
if (state is AuthFailure) {
Fluttertoast.showToast(
msg: state.error,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 2,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
},
builder: (context, state) {
return BtnLogin(
isLoading: state is AuthLoading,
onPressed: () => _loginController.login(
_frmGlobalKey,
rememberPassword: _rememberPassword,
SizedBox(height: 10.h),
Text(
"Intelligent Hotel Management System",
style: TextStyle(
color: Color(0xFF999999),
fontSize: 24.sp,
),
);
},
),
],
),
),
Form(
key: _frmGlobalKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
UsernameField(
controller: _txtUserNameController,
),
SizedBox(height: 20.h),
PasswordField(
controller: _txtPwdController,
),
SizedBox(height: 30.h),
RememberPasswordRow(
value: _rememberPassword,
onChanged: (val) {
setState(() {
_rememberPassword = val ?? false;
});
},
onForgotPassword: _loginController.forgotPwd,
),
SizedBox(height: 10.h),
BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
if (state is AuthFailure) {
Fluttertoast.showToast(
msg: state.error,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 2,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
},
builder: (context, state) {
return BtnLogin(
isLoading: state is AuthLoading,
onPressed: () => _loginController.login(
_frmGlobalKey,
rememberPassword: _rememberPassword,
),
);
},
),
],
),
],
),
),
],
),
],
),
),
),
),
);
}
}
\ No newline at end of file
}
......@@ -24,7 +24,6 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
_controller = ServiceIndexController(context);
}
List<Map<String, dynamic>> _getFilteredRooms() {
......@@ -69,48 +68,47 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 20.w),
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
color: Color.fromRGBO(30, 41, 59, 1),
border: Border.all(
color: Color.fromRGBO(71, 85, 105, 1),
width: 1.w,
),
borderRadius: BorderRadius.circular(24.r),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.03),
blurRadius: 20.r,
offset: Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 楼层选择
_buildFloorSelector(),
SizedBox(height: 15.h),
SizedBox(height: 18.h),
// 类型选择
_buildTypeSelector(),
SizedBox(height: 15.h),
SizedBox(height: 18.h),
// 搜索框
_buildSearchBox(),
SizedBox(height: 15.h),
SizedBox(height: 32.h),
_buildLine(),
SizedBox(height: 18.h),
// 房间区域
_buildRoomGrid(),
SizedBox(height: 20.h),
// 选中状态提示
if (_selectedRoom != null)
Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 8.h),
decoration: BoxDecoration(
color: Color.fromRGBO(15, 23, 42, 1),
borderRadius: BorderRadius.circular(10.r),
),
Padding(
padding: EdgeInsets.only(bottom: 15.h),
child: Text(
'已选:$_selectedRoom 号房',
'已选:$_selectedRoom号房',
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
),
SizedBox(height: 15.h),
// 底部按钮
_buildBottomButtons(),
],
......@@ -125,8 +123,9 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
child: Row(
children: floors.map((floor) {
final isSelected = _selectedFloor == floor;
final displayFloor = floor.replaceAll('楼', '');
return Padding(
padding: EdgeInsets.only(right: 10.w),
padding: EdgeInsets.only(right: 24.w),
child: GestureDetector(
onTap: () {
setState(() {
......@@ -139,23 +138,26 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
_searchText = '';
});
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 10.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
border: Border.all(
color: isSelected ? Color.fromRGBO(59, 130, 246, 1) : Color.fromRGBO(71, 85, 105, 1),
width: 2.w,
child: Column(
children: [
Text(
'$displayFloor楼',
style: TextStyle(
fontSize: 28.sp,
color: isSelected ? Color.fromRGBO(80, 162, 255, 1) : Color.fromRGBO(0, 0, 0, 1),
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
),
child: Text(
floor,
style: TextStyle(
fontSize: 16.sp,
color: isSelected ? Color.fromRGBO(59, 130, 246, 1) : Colors.white,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
SizedBox(height: 4.h),
Container(
width: 50.w,
height: 3.h,
decoration: BoxDecoration(
color: isSelected ? Color.fromRGBO(80, 162, 255, 1) : Colors.transparent,
borderRadius: BorderRadius.circular(2.r),
),
),
),
],
),
),
);
......@@ -173,7 +175,7 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
final isSelected = _selectedType == type;
return Expanded(
child: Padding(
padding: EdgeInsets.only(right: index < types.length - 1 ? 8.w : 0),
padding: EdgeInsets.only(right: index < types.length - 1 ? 10.w : 0),
child: GestureDetector(
onTap: () {
setState(() {
......@@ -185,17 +187,21 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
});
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 12.h),
padding: EdgeInsets.symmetric(vertical: 8.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.r),
color: isSelected ? Color.fromRGBO(59, 130, 246, 1) : Color.fromRGBO(51, 65, 85, 1),
borderRadius: BorderRadius.circular(8.r),
border: Border.all(
color: isSelected ? Color.fromRGBO(73, 149, 234, 0.5) : Colors.transparent,
width: 1.w,
),
color: isSelected ? Color.fromRGBO(73, 149, 234, 0.2) : Color.fromRGBO(238, 238, 238, 1),
),
child: Center(
child: Text(
type,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontSize: 24.sp,
color: isSelected ? Color.fromRGBO(73, 149, 234, 1) : Color.fromRGBO(100, 116, 139, 1),
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
......@@ -210,14 +216,24 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
Widget _buildSearchBox() {
return Container(
height: 55.h,
padding: EdgeInsets.symmetric(horizontal: 15.w),
height: 80.h,
padding: EdgeInsets.symmetric(horizontal: 16.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.r),
color: Color.fromRGBO(51, 65, 85, 1),
borderRadius: BorderRadius.circular(86.r),
color: Colors.white,
border: Border.all(
color: Color.fromRGBO(146, 191, 243, 1),
width: 1.w,
),
),
child: Row(
children: [
Icon(
Icons.search,
color: Color.fromRGBO(153, 153, 153, 1),
size: 37.sp,
),
SizedBox(width: 26.w),
Expanded(
child: TextField(
controller: _searchController,
......@@ -227,40 +243,41 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
});
},
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
decoration: InputDecoration(
hintText: '输入房号快速查找,如 301...',
hintText: '输入房号快速查找,如301...',
hintStyle: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(vertical: 18.h),
contentPadding: EdgeInsets.symmetric(vertical: 16.h),
isCollapsed: true,
),
),
),
Icon(
Icons.keyboard,
color: Colors.grey,
size: 24.sp,
),
],
),
);
}
Widget _buildLine() {
return Container(
height: 1.h,
color: Color.fromRGBO(100, 116, 139, 1),
);
}
String _buildFilterLabel() {
final typePart = _selectedType ?? '全部类型';
final floorPart = _selectedFloor ?? '全部楼层';
return '$typePart · $floorPart';
final floorPart = _selectedFloor?.replaceAll('楼', '') ?? '';
return floorPart.isNotEmpty ? '客房${floorPart}楼·左右滑动选择' :"左右滑动选择";
}
Widget _buildRoomGrid() {
final filteredRooms = _getFilteredRooms();
final crossAxisCount = 8; // 列
final crossAxisCount = 12;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
......@@ -271,17 +288,15 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
Text(
_buildFilterLabel(),
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
Text(
'共 ${filteredRooms.length} 间',
'共${filteredRooms.length}间',
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 24.sp,
color: Color.fromRGBO(73, 149, 234, 1),
),
),
],
......@@ -293,14 +308,14 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
padding: EdgeInsets.symmetric(vertical: 40.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.r),
color: Color.fromRGBO(51, 65, 85, 1),
color: Color.fromRGBO(245, 245, 245, 1),
),
child: Center(
child: Text(
'未找到匹配的房间',
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey,
fontSize: 15.sp,
color: Color.fromRGBO(153, 153, 153, 1),
),
),
),
......@@ -310,15 +325,15 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
scrollDirection: Axis.horizontal,
controller: _scrollController,
child: SizedBox(
// width: (100.w + 10.w) * (filteredRooms.length / crossAxisCount).ceil(),
width: ScreenUtil().screenWidth,
width: (120.w + 12.w) * crossAxisCount,
child: GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
crossAxisSpacing: 10.w,
mainAxisSpacing: 10.h,
crossAxisSpacing: 12.w,
mainAxisSpacing: 12.h,
childAspectRatio: 1,
),
itemCount: filteredRooms.length,
......@@ -339,28 +354,29 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
Color backgroundColor;
Color borderColor;
Color textColor;
Color statusTextColor;
IconData? statusIcon;
switch (status) {
case '入住':
backgroundColor = Color.fromRGBO(59, 130, 246, 0.3);
borderColor = Color.fromRGBO(59, 130, 246, 1);
textColor = Colors.white;
backgroundColor = Color.fromRGBO(220, 236, 255, 1);
borderColor = isSelected ? Color.fromRGBO(64, 158, 255, 1) : Colors.transparent;
textColor = Color.fromRGBO(100, 116, 139, 1);
statusTextColor = Color.fromRGBO(73, 149, 234, 1);
break;
case '待清洁':
backgroundColor = Color.fromRGBO(246, 158, 11, 0.3);
borderColor = Color.fromRGBO(246, 158, 11, 1);
textColor = Colors.white;
backgroundColor = Color.fromRGBO(238, 238, 238, 1);
borderColor = isSelected ? Color.fromRGBO(64, 158, 255, 1) : Colors.transparent;
textColor = Color.fromRGBO(100, 116, 139, 1);
statusTextColor = Color.fromRGBO(73, 149, 234, 1);
statusIcon = Icons.warning_amber_rounded;
break;
case '空闲':
default:
backgroundColor = Color.fromRGBO(51, 65, 85, 1);
borderColor = Color.fromRGBO(71, 85, 105, 1);
textColor = Colors.white;
}
if (isSelected) {
backgroundColor = Color.fromRGBO(59, 130, 246, 1);
borderColor = Color.fromRGBO(59, 130, 246, 1);
backgroundColor = Color.fromRGBO(238, 238, 238, 1);
borderColor = isSelected ? Color.fromRGBO(64, 158, 255, 1) : Colors.transparent;
textColor = Color.fromRGBO(100, 116, 139, 1);
statusTextColor = Color.fromRGBO(73, 149, 234, 1);
}
return GestureDetector(
......@@ -370,14 +386,12 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
});
},
child: Container(
width: 50.w,
height: 50.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.r),
color: backgroundColor,
border: Border.all(
color: borderColor,
width: isSelected ? 2.w : 1.w,
width: isSelected ? 3.w : 0,
),
),
child: Column(
......@@ -386,20 +400,35 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
Text(
room['number'] as String,
style: TextStyle(
fontSize: 12.sp,
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: textColor,
),
),
if (status != '空闲')
Padding(
padding: EdgeInsets.only(top: 2.h),
child: Icon(
status == '入住' ? Icons.person : Icons.warning,
size: 10.sp,
color: status == '入住' ? Colors.white : Color.fromRGBO(246, 158, 11, 1),
),
),
SizedBox(height: 6.h),
Builder(
builder: (context) {
if (status == '入住') {
return Text(
'入住',
style: TextStyle(
fontSize: 24.sp,
color: statusTextColor,
),
);
} else if (status == '待清洁') {
return Image.asset("lib/assets/icon/jth.png", width: 24.sp, height: 30.sp,);
} else {
return Text(
' ',
style: TextStyle(
fontSize: 24.sp,
color: statusTextColor,
),
);
}
},
),
],
),
),
......@@ -407,97 +436,75 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
}
Widget _buildBottomButtons() {
final isRoomSelected = _selectedRoom != null;
return Row(
children: [
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color.fromRGBO(34, 197, 94, 1),
minimumSize: Size(double.infinity, 55.h),
backgroundColor: Color.fromRGBO(73, 149, 234, 1),
disabledBackgroundColor: Color.fromRGBO(204, 204, 204, 1),
minimumSize: Size(double.infinity, 88.h),
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.r),
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
),
onPressed: () {
if (_selectedRoom != null) {
_controller.powerOnRoom(_selectedRoom!);
} else {
_showMessage('请先选择房间');
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.power, color: Colors.white, size: 20.sp),
SizedBox(width: 8.w),
Text(
'送电',
style: TextStyle(fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.bold),
),
],
onPressed: isRoomSelected ? () {
_controller.powerOnRoom(_selectedRoom!);
} : null,
child: Text(
'送电',
style: TextStyle(fontSize: 28.sp, color: Colors.white, fontWeight: FontWeight.w500),
),
),
),
SizedBox(width: 12.w),
SizedBox(width: 16.w),
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color.fromRGBO(239, 68, 68, 1),
minimumSize: Size(double.infinity, 55.h),
backgroundColor: Color.fromRGBO(229, 241, 255, 1),
disabledBackgroundColor: Color.fromRGBO(204, 204, 204, 1),
minimumSize: Size(double.infinity, 88.h),
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.r),
borderRadius: BorderRadius.circular(16.r),
side: BorderSide(
color: Color.fromRGBO(73, 149, 234, 1),
width: 1.w,
),
),
elevation: 0,
),
onPressed: () {
if (_selectedRoom != null) {
_controller.powerOffRoom(_selectedRoom!);
} else {
_showMessage('请先选择房间');
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.power_off, color: Colors.white, size: 20.sp),
SizedBox(width: 8.w),
Text(
'断电',
style: TextStyle(fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.bold),
),
],
onPressed: isRoomSelected ? () {
_controller.powerOffRoom(_selectedRoom!);
} : null,
child: Text(
'断电',
style: TextStyle(fontSize: 28.sp, color: Color.fromRGBO(100, 116, 139, 1), fontWeight: FontWeight.w500),
),
),
),
SizedBox(width: 12.w),
SizedBox(width: 16.w),
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Color.fromRGBO(71, 85, 105, 1),
minimumSize: Size(double.infinity, 55.h),
backgroundColor: Color.fromRGBO(100, 116, 139, 0.2),
disabledBackgroundColor: Color.fromRGBO(204, 204, 204, 1),
minimumSize: Size(double.infinity, 88.h),
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.r),
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
),
onPressed: () {
if (_selectedRoom != null) {
_controller.viewRoom(_selectedRoom!);
} else {
_showMessage('请先选择房间');
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.settings, color: Colors.white, size: 20.sp),
SizedBox(width: 8.w),
Text(
'查看',
style: TextStyle(fontSize: 16.sp, color: Colors.white, fontWeight: FontWeight.bold),
),
],
onPressed: isRoomSelected ? () {
_controller.viewRoom(_selectedRoom!);
} : null,
child: Text(
'查看',
style: TextStyle(fontSize: 28.sp, color: Color.fromRGBO(100, 116, 139, 1), fontWeight: FontWeight.w500),
),
),
),
......
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,
),
],
);
}
}
......@@ -3,123 +3,240 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/service/room/controller.dart';
class RoomInfoBlock extends StatefulWidget {
final ServiceRoomController controller;
const RoomInfoBlock({
super.key,
required this.controller,
});
const RoomInfoBlock({super.key});
@override
State<RoomInfoBlock> createState() => _RoomInfoBlockState();
}
class _RoomInfoBlockState extends State<RoomInfoBlock> {
@override
Widget build(BuildContext context) {
final roomDetail = widget.controller.getRoomDetail();
final guestName = roomDetail['guestName'] as String?;
final checkInDate = roomDetail['checkInDate'] as String?;
final checkOutDate = roomDetail['checkOutDate'] as String?;
final status = roomDetail['status'] as String;
late final ServiceRoomController _controller;
Color statusColor;
Color statusBgColor;
@override
void initState() {
super.initState();
_controller = ServiceRoomController(context);
}
switch (status) {
case '入住中':
statusColor = Color.fromRGBO(59, 130, 246, 1);
statusBgColor = Color.fromRGBO(59, 130, 246, 0.2);
break;
case '待清洁':
statusColor = Color.fromRGBO(246, 158, 11, 1);
statusBgColor = Color.fromRGBO(246, 158, 11, 0.2);
break;
case '空闲':
default:
statusColor = Color.fromRGBO(34, 197, 94, 1);
statusBgColor = Color.fromRGBO(34, 197, 94, 0.2);
break;
}
@override
Widget build(BuildContext context) {
final roomDetail = _controller.getRoomDetail();
final roomStatus = _controller.getRoomStatus();
return Container(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 20.w),
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
color: Color.fromRGBO(30, 41, 59, 1),
border: Border.all(
color: Color.fromRGBO(71, 85, 105, 1),
width: 1.w,
),
borderRadius: BorderRadius.circular(24.r),
color: Colors.white,
),
child: Row(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 80.w,
height: 80.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
color: Color.fromRGBO(51, 65, 85, 1),
),
child: Icon(
Icons.bed,
color: statusColor,
size: 40.sp,
),
_buildRoomHeader(roomDetail),
SizedBox(height: 20.h),
_buildStatusTags(roomStatus),
SizedBox(height: 20.h),
_buildDivider(),
SizedBox(height: 20.h),
_buildDeviceStatusTitle(),
SizedBox(height: 20.h),
_buildDeviceGrid(),
],
),
);
}
Widget _buildRoomHeader(Map<String, dynamic> roomDetail) {
return Row(
children: [
Container(
width: 64.w,
height: 66.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.r),
color: Color.fromRGBO(229, 241, 255, 1),
),
SizedBox(width: 20.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
roomDetail['roomNumber'] as String,
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(width: 15.w),
Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.r),
color: statusBgColor,
),
child: Text(
status,
style: TextStyle(
fontSize: 14.sp,
color: statusColor,
fontWeight: FontWeight.w500,
),
),
),
],
),
SizedBox(height: 10.h),
if (guestName != null && checkInDate != null && checkOutDate != null)
child: Icon(
Icons.bed_outlined,
size: 36.sp,
color: Color.fromRGBO(73, 149, 234, 1),
),
),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'$guestName · $checkInDate-$checkOutDate · ${roomDetail['roomType']}',
roomDetail['roomNumber'] as String,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
fontSize: 32.sp,
color: Colors.black,
fontWeight: FontWeight.bold,
),
)
else
),
SizedBox(width: 12.w),
Text(
roomDetail['roomType'] as String,
roomDetail['status'] as String,
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
fontSize: 24.sp,
color: Color.fromRGBO(73, 149, 234, 1),
),
),
],
],
),
SizedBox(height: 6.h),
Text(
_buildGuestInfo(roomDetail),
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1),
),
),
],
),
),
],
);
}
String _buildGuestInfo(Map<String, dynamic> roomDetail) {
final guestName = roomDetail['guestName'] as String?;
final checkInDate = roomDetail['checkInDate'] as String?;
final checkOutDate = roomDetail['checkOutDate'] as String?;
final roomType = roomDetail['roomType'] as String;
if (guestName != null && checkInDate != null && checkOutDate != null) {
return '$guestName·$checkInDate-$checkOutDate·$roomType';
}
return roomType;
}
Widget _buildStatusTags(Map<String, dynamic> roomStatus) {
return Wrap(
spacing: 12.w,
children: [
_buildStatusTag(
'有人',
roomStatus['hasGuest'] as bool,
),
_buildStatusTag(
'通电中',
roomStatus['powerOn'] as bool,
),
_buildStatusTag(
'wifi正常',
roomStatus['wifiNormal'] as bool,
),
],
);
}
Widget _buildStatusTag(String text, bool isActive) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.r),
color: Color.fromRGBO(20, 184, 166, 0.2),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.check,
size: 20.sp,
color: Color.fromRGBO(16, 185, 129, 1),
),
SizedBox(width: 6.w),
Text(
text,
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(20, 184, 166, 1),
),
),
],
),
);
}
Widget _buildDivider() {
return Container(
height: 1.h,
color: Color.fromRGBO(229, 231, 235, 1),
);
}
Widget _buildDeviceStatusTitle() {
return Text(
'房间设备状态',
style: TextStyle(
fontSize: 28.sp,
color: Color.fromRGBO(0, 0, 0, 1),
fontWeight: FontWeight.bold,
),
);
}
Widget _buildDeviceGrid() {
final devices = _controller.getDevices();
return GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16.w,
mainAxisSpacing: 16.h,
childAspectRatio: 2.2,
),
itemCount: devices.length,
itemBuilder: (context, index) {
return _buildDeviceItem(devices[index]);
},
);
}
Widget _buildDeviceItem(Map<String, dynamic> device) {
return Container(
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.r),
color: Color.fromRGBO(229, 241, 255, 1),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Icon(
device['icon'] as IconData,
size: 32.sp,
color: Color.fromRGBO(73, 149, 234, 1),
),
SizedBox(width: 10.w),
Text(
device['name'] as String,
style: TextStyle(
fontSize: 28.sp,
color: Color.fromRGBO(73, 149, 234, 1),
fontWeight: FontWeight.bold,
),
),
],
),
SizedBox(height: 10.h),
Text(
device['status'] as String,
style: TextStyle(
fontSize: 24.sp,
color: (device['isOn'] as bool)
? Color.fromRGBO(20, 184, 166, 1)
: Color.fromRGBO(100, 116, 139, 1),
),
),
],
......
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