Commit 7e849e9f authored by 张宏's avatar 张宏

智能酒店相关页面

parent 3a517340
...@@ -46,4 +46,7 @@ app.*.map.json ...@@ -46,4 +46,7 @@ app.*.map.json
/android/app/release /android/app/release
# FVM Version Cache # FVM Version Cache
.fvm/ .fvm/
\ No newline at end of file
# ai相关
ai_work/
\ No newline at end of file
{ {
"dart.flutterSdkPath": ".fvm/versions/3.38.10" "dart.flutterSdkPath": ".fvm/versions/3.41.9"
} }
\ No newline at end of file
buildscript { buildscript {
ext.kotlin_version = '1.9.22' ext.kotlin_version = '2.2.20'
repositories { repositories {
google() google()
maven { url uri('https://maven.aliyun.com/repository/google') } maven { url uri('https://maven.aliyun.com/repository/google') }
......
...@@ -3,5 +3,5 @@ distributionPath=wrapper/dists ...@@ -3,5 +3,5 @@ distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
# distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip # distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.10.2-bin.zip distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.13-bin.zip
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart'; import 'package:smart_hotel_app/routes/app_router.gr.dart';
import 'package:smart_hotel_app/views/report/rule/rule_management_view.dart';
import 'package:smart_hotel_app/views/report/device/device_list_view.dart';
@AutoRouterConfig(replaceInRouteName: 'View,Route') @AutoRouterConfig(replaceInRouteName: 'View,Route')
class AppRouter extends $AppRouter { class AppRouter extends $AppRouter {
...@@ -29,5 +31,8 @@ class AppRouter extends $AppRouter { ...@@ -29,5 +31,8 @@ class AppRouter extends $AppRouter {
AutoRoute(page: InspectionDetailRoute.page), AutoRoute(page: InspectionDetailRoute.page),
AutoRoute(page: InspectionDeviceRoute.page), AutoRoute(page: InspectionDeviceRoute.page),
AutoRoute(page: InspectionHistoryRoute.page), AutoRoute(page: InspectionHistoryRoute.page),
AutoRoute(page: AbnormalListRoute.page),
AutoRoute(page: ReportRuleManagementRoute.page),
AutoRoute(page: ReportDeviceListRoute.page),
]; ];
} }
This diff is collapsed.
...@@ -133,7 +133,7 @@ class EquipmentListBlock extends StatelessWidget { ...@@ -133,7 +133,7 @@ class EquipmentListBlock extends StatelessWidget {
), ),
padding: EdgeInsets.symmetric(horizontal: 20.w), padding: EdgeInsets.symmetric(horizontal: 20.w),
child: Column( child: Column(
children: equipmentList.take(3).map((item) => _buildEquipmentItem(item)).toList(), children: equipmentList.take(5).map((item) => _buildEquipmentItem(item)).toList(),
), ),
), ),
], ],
......
...@@ -66,7 +66,7 @@ class FilterPanel extends StatelessWidget { ...@@ -66,7 +66,7 @@ class FilterPanel extends StatelessWidget {
child: Text( child: Text(
_getTabLabel(tab), _getTabLabel(tab),
style: TextStyle( style: TextStyle(
fontSize: 36.sp, fontSize: 28.sp,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
color: isSelected color: isSelected
? const Color.fromRGBO(66, 165, 245, 1.0) ? const Color.fromRGBO(66, 165, 245, 1.0)
...@@ -78,17 +78,17 @@ class FilterPanel extends StatelessWidget { ...@@ -78,17 +78,17 @@ class FilterPanel extends StatelessWidget {
top: 0, top: 0,
right: -8.w, right: -8.w,
child: Container( child: Container(
width: 56.w, width: 28.w,
height: 56.h, height: 28.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: _getTabColor(tab), color: _getTabColor(tab),
borderRadius: BorderRadius.circular(28.r), borderRadius: BorderRadius.circular(12.r),
), ),
child: Center( child: Center(
child: Text( child: Text(
count.toString(), count.toString(),
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 20.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.white, color: Colors.white,
), ),
...@@ -163,13 +163,13 @@ class FilterPanel extends StatelessWidget { ...@@ -163,13 +163,13 @@ class FilterPanel extends StatelessWidget {
color: isSelected color: isSelected
? const Color.fromRGBO(66, 165, 245, 1.0) ? const Color.fromRGBO(66, 165, 245, 1.0)
: const Color.fromRGBO(200, 208, 220, 1.0), : const Color.fromRGBO(200, 208, 220, 1.0),
width: 2.w, width: 1.w,
), ),
), ),
child: Text( child: Text(
room, room,
style: TextStyle( style: TextStyle(
fontSize: 28.sp, fontSize: 24.sp,
color: isSelected color: isSelected
? const Color.fromRGBO(66, 165, 245, 1.0) ? const Color.fromRGBO(66, 165, 245, 1.0)
: const Color.fromRGBO(100, 116, 139, 1.0), : const Color.fromRGBO(100, 116, 139, 1.0),
......
...@@ -42,10 +42,10 @@ class InspectionDeviceView extends StatelessWidget { ...@@ -42,10 +42,10 @@ class InspectionDeviceView extends StatelessWidget {
fontWeight: FontWeight.w200, fontWeight: FontWeight.w200,
), ),
), ),
Icon( // Icon(
Icons.arrow_forward, // Icons.arrow_forward,
color: const Color.fromRGBO(100, 116, 139, 1), // color: const Color.fromRGBO(100, 116, 139, 1),
), // ),
], ],
), ),
centerTitle: true, centerTitle: true,
...@@ -71,7 +71,7 @@ class InspectionDeviceView extends StatelessWidget { ...@@ -71,7 +71,7 @@ class InspectionDeviceView extends StatelessWidget {
InspectionHistoryCard( InspectionHistoryCard(
historyList: state.inspectionHistory, historyList: state.inspectionHistory,
), ),
SizedBox(height: 20.h), // SizedBox(height: 20.h),
InspectionItemsCard( InspectionItemsCard(
items: state.inspectionItems, items: state.inspectionItems,
), ),
......
...@@ -15,9 +15,12 @@ class InspectionHistoryCard extends StatelessWidget { ...@@ -15,9 +15,12 @@ class InspectionHistoryCard extends StatelessWidget {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(20.r), borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.r),
topRight: Radius.circular(20.r),
),
), ),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), padding: EdgeInsets.only(left: 20.w, right: 20.w, top: 16.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
......
...@@ -15,7 +15,10 @@ class InspectionItemsCard extends StatelessWidget { ...@@ -15,7 +15,10 @@ class InspectionItemsCard extends StatelessWidget {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(20.r), borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20.r),
bottomRight: Radius.circular(20.r),
),
), ),
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
child: Column( child: Column(
......
...@@ -60,7 +60,7 @@ class _DefaultLayoutViewState extends State<DefaultLayoutView> { ...@@ -60,7 +60,7 @@ class _DefaultLayoutViewState extends State<DefaultLayoutView> {
width: 48.w, width: 48.w,
height: 48.h, height: 48.h,
), ),
label: "服务", label: "管理",
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Image.asset( icon: Image.asset(
...@@ -73,7 +73,7 @@ class _DefaultLayoutViewState extends State<DefaultLayoutView> { ...@@ -73,7 +73,7 @@ class _DefaultLayoutViewState extends State<DefaultLayoutView> {
width: 48.w, width: 48.w,
height: 48.h, height: 48.h,
), ),
label: "看板", label: "能耗",
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Image.asset( icon: Image.asset(
......
...@@ -105,7 +105,7 @@ class LoginView extends StatelessWidget { ...@@ -105,7 +105,7 @@ class LoginView extends StatelessWidget {
'智能酒店管理系统', '智能酒店管理系统',
style: TextStyle( style: TextStyle(
color: Color(0xFF333333), color: Color(0xFF333333),
fontSize: 36, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
...@@ -114,7 +114,7 @@ class LoginView extends StatelessWidget { ...@@ -114,7 +114,7 @@ class LoginView extends StatelessWidget {
'Intelligent Hotel Management System', 'Intelligent Hotel Management System',
style: TextStyle( style: TextStyle(
color: Color(0xFF999999), color: Color(0xFF999999),
fontSize: 24, fontSize: 14,
), ),
), ),
], ],
......
...@@ -15,7 +15,7 @@ class BtnLogin extends StatelessWidget { ...@@ -15,7 +15,7 @@ class BtnLogin extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: double.infinity, width: double.infinity,
height: 96.h, height: 104.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color.fromRGBO(73, 149, 234, 1), color: Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(40.w), borderRadius: BorderRadius.circular(40.w),
...@@ -40,7 +40,7 @@ class BtnLogin extends StatelessWidget { ...@@ -40,7 +40,7 @@ class BtnLogin extends StatelessWidget {
"登录", "登录",
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 32.sp, fontSize: 40.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
......
...@@ -16,7 +16,7 @@ class ProfileHeaderBlock extends StatelessWidget { ...@@ -16,7 +16,7 @@ class ProfileHeaderBlock extends StatelessWidget {
return Container( return Container(
width: double.infinity, width: double.infinity,
color: Colors.white, color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 28.w, vertical: 32.h), padding: EdgeInsets.only(left: 28.w, right: 28.w, top: ScreenUtil().statusBarHeight + 32.h, bottom: 32.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
......
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
import 'package:smart_hotel_app/views/profile/index/cubit/profile_state.dart'; import 'package:smart_hotel_app/views/profile/index/cubit/profile_state.dart';
class ProfileMenuBlock extends StatelessWidget { class ProfileMenuBlock extends StatelessWidget {
...@@ -7,9 +9,15 @@ class ProfileMenuBlock extends StatelessWidget { ...@@ -7,9 +9,15 @@ class ProfileMenuBlock extends StatelessWidget {
const ProfileMenuBlock({super.key, required this.menuList}); const ProfileMenuBlock({super.key, required this.menuList});
Widget _buildMenuItem(MenuItem item) { Widget _buildMenuItem(BuildContext context, MenuItem item) {
return GestureDetector( return GestureDetector(
onTap: () => item.onTap?.call(), onTap: () {
if (item.onTap != null) {
item.onTap!();
} else {
_handleMenuTap(context, item.title);
}
},
child: Container( child: Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 28.h), padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 28.h),
...@@ -38,7 +46,7 @@ class ProfileMenuBlock extends StatelessWidget { ...@@ -38,7 +46,7 @@ class ProfileMenuBlock extends StatelessWidget {
child: Text( child: Text(
item.title, item.title,
style: TextStyle( style: TextStyle(
fontSize: 30.sp, fontSize: 28.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: const Color.fromRGBO(100, 116, 139, 1.0), color: const Color.fromRGBO(100, 116, 139, 1.0),
), ),
...@@ -55,13 +63,23 @@ class ProfileMenuBlock extends StatelessWidget { ...@@ -55,13 +63,23 @@ class ProfileMenuBlock extends StatelessWidget {
); );
} }
void _handleMenuTap(BuildContext context, String title) {
switch (title) {
case '告警信息':
context.pushRoute(const AbnormalListRoute());
break;
default:
break;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: double.infinity, width: double.infinity,
child: Column( child: Column(
children: [ children: [
...menuList.map((item) => _buildMenuItem(item)).toList(), ...menuList.map((item) => _buildMenuItem(context, item)).toList(),
], ],
), ),
); );
......
...@@ -17,12 +17,12 @@ class ReportEnergyDetailView extends StatelessWidget { ...@@ -17,12 +17,12 @@ class ReportEnergyDetailView extends StatelessWidget {
return BlocProvider( return BlocProvider(
create: (_) => EnergyCubit(), create: (_) => EnergyCubit(),
child: Scaffold( child: Scaffold(
backgroundColor: const Color.fromRGBO(15, 23, 42, 1), backgroundColor: const Color.fromRGBO(245, 245, 247, 1),
appBar: AppBar( appBar: AppBar(
backgroundColor: const Color.fromRGBO(15, 23, 42, 1), backgroundColor: Colors.white,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white), icon: const Icon(Icons.arrow_back, color: Colors.black87),
onPressed: () { onPressed: () {
context.popRoute(); context.popRoute();
}, },
...@@ -30,8 +30,8 @@ class ReportEnergyDetailView extends StatelessWidget { ...@@ -30,8 +30,8 @@ class ReportEnergyDetailView extends StatelessWidget {
title: Text( title: Text(
'能耗分析', '能耗分析',
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.black87,
fontSize: 18.sp, fontSize: 32.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
...@@ -42,7 +42,7 @@ class ReportEnergyDetailView extends StatelessWidget { ...@@ -42,7 +42,7 @@ class ReportEnergyDetailView extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return Column( return Column(
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 16.h),
EnergyStatsCardBlock( EnergyStatsCardBlock(
todayEnergy: state.todayEnergy, todayEnergy: state.todayEnergy,
todayEnergyChange: state.todayEnergyChange, todayEnergyChange: state.todayEnergyChange,
...@@ -50,9 +50,9 @@ class ReportEnergyDetailView extends StatelessWidget { ...@@ -50,9 +50,9 @@ class ReportEnergyDetailView extends StatelessWidget {
monthEnergyChange: state.monthEnergyChange, monthEnergyChange: state.monthEnergyChange,
monthBill: state.monthBill, monthBill: state.monthBill,
), ),
SizedBox(height: 20.h), SizedBox(height: 16.h),
HourlyChartBlock(hourlyData: state.hourlyData), HourlyChartBlock(hourlyData: state.hourlyData),
SizedBox(height: 20.h), SizedBox(height: 16.h),
ZoneChartBlock(zoneData: state.zoneData), ZoneChartBlock(zoneData: state.zoneData),
SizedBox(height: 20.h), SizedBox(height: 20.h),
], ],
......
...@@ -26,9 +26,10 @@ class EnergyStatsCardBlock extends StatelessWidget { ...@@ -26,9 +26,10 @@ class EnergyStatsCardBlock extends StatelessWidget {
Expanded( Expanded(
child: _buildCard( child: _buildCard(
'${todayEnergy.toInt()}', '${todayEnergy.toInt()}',
'今日(kWh)', '今日(kwh)',
'${todayEnergyChange.toInt()}%', '${todayEnergyChange.toInt()}%',
true, true,
const Color.fromRGBO(59, 130, 246, 1),
), ),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
...@@ -38,6 +39,7 @@ class EnergyStatsCardBlock extends StatelessWidget { ...@@ -38,6 +39,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
'本月(kWh)', '本月(kWh)',
'${monthEnergyChange.toInt()}%', '${monthEnergyChange.toInt()}%',
true, true,
const Color.fromRGBO(59, 130, 246, 1),
), ),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
...@@ -47,6 +49,7 @@ class EnergyStatsCardBlock extends StatelessWidget { ...@@ -47,6 +49,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
'本月电费预估', '本月电费预估',
null, null,
null, null,
const Color.fromRGBO(16, 185, 129, 1),
), ),
), ),
], ],
...@@ -54,56 +57,56 @@ class EnergyStatsCardBlock extends StatelessWidget { ...@@ -54,56 +57,56 @@ class EnergyStatsCardBlock extends StatelessWidget {
); );
} }
Widget _buildCard(String value, String label, String? change, bool? isDown) { Widget _buildCard(String value, String label, String? change, bool? isDown, Color valueColor) {
return Container( return Container(
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 12.w), padding: EdgeInsets.symmetric(vertical: 24.h, horizontal: 16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(30, 41, 59, 1), color: Colors.white,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(20.r),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
value, value,
style: TextStyle( style: TextStyle(
color: Colors.white, color: valueColor,
fontSize: 24.sp, fontSize: 40.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Text( Text(
label, label,
style: TextStyle( style: TextStyle(
color: const Color.fromRGBO(148, 163, 184, 1), color: Colors.black54,
fontSize: 12.sp, fontSize: 24.sp,
), ),
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
if (change != null) if (change != null)
Row( Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon( Icon(
isDown! ? Icons.arrow_drop_down : Icons.arrow_drop_up, isDown! ? Icons.arrow_downward : Icons.arrow_upward,
color: isDown color: isDown
? const Color.fromRGBO(34, 197, 94, 1) ? const Color.fromRGBO(16, 185, 129, 1)
: const Color.fromRGBO(239, 68, 68, 1), : const Color.fromRGBO(239, 68, 68, 1),
size: 16.sp, size: 24.sp,
), ),
Text( Text(
change, change,
style: TextStyle( style: TextStyle(
color: isDown color: isDown
? const Color.fromRGBO(34, 197, 94, 1) ? const Color.fromRGBO(16, 185, 129, 1)
: const Color.fromRGBO(239, 68, 68, 1), : const Color.fromRGBO(239, 68, 68, 1),
fontSize: 12.sp, fontSize: 24.sp,
), ),
), ),
], ],
) )
else else
SizedBox(height: 20.h), SizedBox(height: 24.h),
], ],
), ),
); );
......
...@@ -11,10 +11,10 @@ class HourlyChartBlock extends StatelessWidget { ...@@ -11,10 +11,10 @@ class HourlyChartBlock extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w), margin: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(24.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(30, 41, 59, 1), color: Colors.white,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(20.r),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -22,39 +22,55 @@ class HourlyChartBlock extends StatelessWidget { ...@@ -22,39 +22,55 @@ class HourlyChartBlock extends StatelessWidget {
Text( Text(
'今日逐时用电', '今日逐时用电',
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.black87,
fontSize: 16.sp, fontSize: 24.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 100.h),
SizedBox( SizedBox(
height: 200.h, height: 200.h,
child: BarChart( child: BarChart(
BarChartData( BarChartData(
alignment: BarChartAlignment.spaceBetween, alignment: BarChartAlignment.spaceAround,
maxY: 200, maxY: 100,
barTouchData: BarTouchData(enabled: false), barTouchData: BarTouchData(enabled: false),
titlesData: const FlTitlesData( titlesData: FlTitlesData(
show: true, show: true,
rightTitles: AxisTitles( rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false), sideTitles: SideTitles(showTitles: false),
), ),
topTitles: AxisTitles( topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false), sideTitles: SideTitles(showTitles: false),
), ),
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
reservedSize: 20, reservedSize: 30,
getTitlesWidget: _getBottomTitleWidget,
), ),
), ),
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false), sideTitles: SideTitles(
showTitles: true,
reservedSize: 40,
getTitlesWidget: _getLeftTitleWidget,
),
), ),
), ),
borderData: FlBorderData(show: false), borderData: FlBorderData(show: false),
gridData: const FlGridData(show: false), gridData: FlGridData(
show: true,
drawVerticalLine: false,
horizontalInterval: 20,
getDrawingHorizontalLine: (value) {
return FlLine(
color: const Color.fromRGBO(200, 200, 200, 1),
strokeWidth: 1,
dashArray: [5, 5],
);
},
),
barGroups: _buildBarGroups(), barGroups: _buildBarGroups(),
), ),
), ),
...@@ -64,6 +80,57 @@ class HourlyChartBlock extends StatelessWidget { ...@@ -64,6 +80,57 @@ class HourlyChartBlock extends StatelessWidget {
); );
} }
Widget _getBottomTitleWidget(double value, TitleMeta meta) {
const style = TextStyle(
color: Colors.black54,
fontSize: 14,
);
String text;
final index = value.toInt();
if (index % 4 == 0) {
if (index == 0) {
text = '00:00';
} else if (index == 24) {
text = '24:00';
} else {
text = '$index:04';
}
} else {
text = '';
}
return SideTitleWidget(
meta: meta,
child: Text(text, style: style),
);
}
Widget _getLeftTitleWidget(double value, TitleMeta meta) {
const style = TextStyle(
color: Colors.black54,
fontSize: 14,
);
String text;
if (value == 0) {
text = '0';
} else if (value == 20) {
text = '20';
} else if (value == 40) {
text = '40';
} else if (value == 60) {
text = '60';
} else if (value == 80) {
text = '80';
} else if (value == 100) {
text = '100';
} else {
text = '';
}
return SideTitleWidget(
meta: meta,
child: Text(text, style: style),
);
}
List<BarChartGroupData> _buildBarGroups() { List<BarChartGroupData> _buildBarGroups() {
return hourlyData.asMap().entries.map((entry) { return hourlyData.asMap().entries.map((entry) {
final index = entry.key; final index = entry.key;
...@@ -73,10 +140,8 @@ class HourlyChartBlock extends StatelessWidget { ...@@ -73,10 +140,8 @@ class HourlyChartBlock extends StatelessWidget {
barRods: [ barRods: [
BarChartRodData( BarChartRodData(
toY: value, toY: value,
color: index >= 8 && index <= 12 color: const Color.fromRGBO(59, 130, 246, 1),
? const Color.fromRGBO(59, 130, 246, 1) width: 12.w,
: const Color.fromRGBO(37, 99, 235, 1),
width: 10.w,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
topLeft: Radius.circular(4), topLeft: Radius.circular(4),
topRight: Radius.circular(4), topRight: Radius.circular(4),
......
...@@ -11,10 +11,10 @@ class ZoneChartBlock extends StatelessWidget { ...@@ -11,10 +11,10 @@ class ZoneChartBlock extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w), margin: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(24.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(30, 41, 59, 1), color: Colors.white,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(20.r),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -22,59 +22,76 @@ class ZoneChartBlock extends StatelessWidget { ...@@ -22,59 +22,76 @@ class ZoneChartBlock extends StatelessWidget {
Text( Text(
'分区用电占比', '分区用电占比',
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.black87,
fontSize: 16.sp, fontSize: 24.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
), ),
), ),
SizedBox(height: 16.h), SizedBox(height: 24.h),
...zoneData.asMap().entries.map((entry) { ...zoneData.asMap().entries.map((entry) {
final index = entry.key; final index = entry.key;
final data = entry.value; final data = entry.value;
return Padding( return Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
bottom: index < zoneData.length - 1 ? 16.h : 0), bottom: index < zoneData.length - 1 ? 20.h : 0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Row(
data.name, children: [
style: TextStyle( Container(
color: Colors.white, width: 12.w,
fontSize: 14.sp, height: 12.h,
), decoration: BoxDecoration(
color: index == 0
? const Color.fromRGBO(59, 130, 246, 1)
: const Color.fromRGBO(107, 114, 128, 1),
borderRadius: BorderRadius.circular(3.r),
),
),
SizedBox(width: 8.w),
Text(
data.name,
style: TextStyle(
color: Colors.black87,
fontSize: 24.sp,
),
),
],
), ),
Text( Text(
'${data.percentage.toInt()}% (${data.energy.toInt()} kWh)', '${data.percentage.toInt()}% (${data.energy.toInt()} kWh)',
style: TextStyle( style: TextStyle(
color: const Color.fromRGBO(148, 163, 184, 1), color: index == 0
fontSize: 14.sp, ? const Color.fromRGBO(59, 130, 246, 1)
: Colors.black54,
fontSize: 24.sp,
), ),
), ),
], ],
), ),
SizedBox(height: 8.h), SizedBox(height: 12.h),
Stack( Stack(
children: [ children: [
Container( Container(
height: 12.h, height: 16.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color.fromRGBO(51, 65, 85, 1), color: const Color.fromRGBO(229, 231, 235, 1),
borderRadius: BorderRadius.circular(6.r), borderRadius: BorderRadius.circular(8.r),
), ),
), ),
FractionallySizedBox( FractionallySizedBox(
widthFactor: data.percentage / 100, widthFactor: data.percentage / 100,
child: Container( child: Container(
height: 12.h, height: 16.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: index == 0 color: index == 0
? const Color.fromRGBO(59, 130, 246, 1) ? const Color.fromRGBO(59, 130, 246, 1)
: const Color.fromRGBO(71, 85, 105, 1), : const Color.fromRGBO(107, 114, 128, 1),
borderRadius: BorderRadius.circular(6.r), borderRadius: BorderRadius.circular(8.r),
), ),
), ),
), ),
......
...@@ -31,7 +31,7 @@ class ReportIndexView extends StatelessWidget { ...@@ -31,7 +31,7 @@ class ReportIndexView extends StatelessWidget {
child: Container( child: Container(
width: double.infinity, width: double.infinity,
color: const Color.fromRGBO(242, 243, 245, 1), color: const Color.fromRGBO(242, 243, 245, 1),
padding: EdgeInsets.symmetric(horizontal: 28.w), padding: EdgeInsets.only(left: 28.w, right: 28.w, top: ScreenUtil().statusBarHeight),
child: Column( child: Column(
children: [ children: [
ReportHeaderBlock( ReportHeaderBlock(
......
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:smart_hotel_app/routes/app_router.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
class DeviceOnlineRate extends StatelessWidget { class DeviceOnlineRate extends StatelessWidget {
final Map<String, dynamic> deviceOnlineRate; final Map<String, dynamic> deviceOnlineRate;
...@@ -15,108 +18,124 @@ class DeviceOnlineRate extends StatelessWidget { ...@@ -15,108 +18,124 @@ class DeviceOnlineRate extends StatelessWidget {
devices.fold<int>(0, (sum, device) => sum + (device['count'] as int)); devices.fold<int>(0, (sum, device) => sum + (device['count'] as int));
final rate = deviceOnlineRate['rate'] as double; final rate = deviceOnlineRate['rate'] as double;
return Container( return GestureDetector(
width: double.infinity, onTap: () {
padding: EdgeInsets.all(28.w), context.pushRoute(const ReportDeviceListRoute());
decoration: BoxDecoration( },
borderRadius: BorderRadius.circular(24.r), child: Container(
color: Colors.white, width: double.infinity,
), padding: EdgeInsets.all(28.w),
child: Column( decoration: BoxDecoration(
crossAxisAlignment: CrossAxisAlignment.start, borderRadius: BorderRadius.circular(24.r),
children: [ color: Colors.white,
Row( ),
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
deviceOnlineRate['title'] as String, Row(
style: TextStyle( mainAxisAlignment: MainAxisAlignment.spaceBetween,
fontSize: 28.sp, children: [
fontWeight: FontWeight.normal, Text(
color: const Color.fromRGBO(107, 114, 128, 1), deviceOnlineRate['title'] as String,
), style: TextStyle(
), fontSize: 28.sp,
Text( fontWeight: FontWeight.normal,
'共 $totalDevices 台', color: const Color.fromRGBO(107, 114, 128, 1),
style: TextStyle( ),
fontSize: 22.sp,
color: const Color.fromRGBO(156, 163, 175, 1),
), ),
), Row(
],
),
SizedBox(height: 20.h),
Row(
children: [
SizedBox(
width: 120.w,
height: 120.h,
child: Stack(
alignment: Alignment.center,
children: [ children: [
PieChart(
PieChartData(
sections: [
PieChartSectionData(
value: rate,
color: const Color.fromRGBO(34, 197, 94, 1),
title: '',
radius: 50.w,
),
PieChartSectionData(
value: 1 - rate,
color: const Color.fromRGBO(229, 231, 235, 1),
title: '',
radius: 50.w,
),
],
sectionsSpace: 0,
centerSpaceRadius: 38.w,
),
),
Text( Text(
deviceOnlineRate['rateText'] as String, '共 $totalDevices 台',
style: TextStyle( style: TextStyle(
fontSize: 24.sp, fontSize: 22.sp,
fontWeight: FontWeight.bold, color: const Color.fromRGBO(156, 163, 175, 1),
color: const Color.fromRGBO(31, 41, 55, 1),
), ),
), ),
SizedBox(width: 8.w),
Icon(
Icons.chevron_right,
size: 24.sp,
color: const Color.fromRGBO(156, 163, 175, 1),
),
], ],
), ),
), ],
SizedBox(width: 24.w), ),
Expanded( SizedBox(height: 20.h),
child: Column( Row(
children: devices.map((device) { children: [
return Padding( SizedBox(
padding: EdgeInsets.only(bottom: 8.h), width: 120.w,
child: Row( height: 120.h,
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: Stack(
children: [ alignment: Alignment.center,
Text( children: [
device['name'] as String, PieChart(
style: TextStyle( PieChartData(
fontSize: 22.sp, sections: [
color: const Color.fromRGBO(107, 114, 128, 1), PieChartSectionData(
value: rate,
color: const Color.fromRGBO(34, 197, 94, 1),
title: '',
radius: 30.w,
), ),
), PieChartSectionData(
Text( // value: 1 - rate,
'${device['count']} 台', value: 1 - rate,
style: TextStyle( color: const Color.fromRGBO(229, 231, 235, 1),
fontSize: 22.sp, title: '',
color: const Color.fromRGBO(55, 65, 81, 1), radius: 30.w,
), ),
), ],
], sectionsSpace: 0,
centerSpaceRadius: 38.w,
),
), ),
); Text(
}).toList(), deviceOnlineRate['rateText'] as String,
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: const Color.fromRGBO(31, 41, 55, 1),
),
),
],
),
),
SizedBox(width: 24.w),
Expanded(
child: Column(
children: devices.map((device) {
return Padding(
padding: EdgeInsets.only(bottom: 8.h),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
device['name'] as String,
style: TextStyle(
fontSize: 22.sp,
color: const Color.fromRGBO(107, 114, 128, 1),
),
),
Text(
'${device['count']} 台',
style: TextStyle(
fontSize: 22.sp,
color: const Color.fromRGBO(55, 65, 81, 1),
),
),
],
),
);
}).toList(),
),
), ),
), ],
], ),
), ],
], ),
), ),
); );
} }
......
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/routes/app_router.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
class QuickActionsBlock extends StatelessWidget { class QuickActionsBlock extends StatelessWidget {
final Map<String, dynamic> quickActions; final Map<String, dynamic> quickActions;
...@@ -31,32 +34,42 @@ class QuickActionsBlock extends StatelessWidget { ...@@ -31,32 +34,42 @@ class QuickActionsBlock extends StatelessWidget {
SizedBox(height: 28.h), SizedBox(height: 28.h),
Row( Row(
children: actions.map((action) { children: actions.map((action) {
final name = action['name'] as String;
return Padding( return Padding(
padding: EdgeInsets.only(right: 60.w), padding: EdgeInsets.only(right: 60.w),
child: Column( child: GestureDetector(
children: [ onTap: () {
Container( if (name == '联动规则') {
width: 80.w, context.pushRoute(const ReportRuleManagementRoute());
height: 80.h, } else if (name == '告警记录') {
decoration: BoxDecoration( context.pushRoute(const AbnormalListRoute());
color: const Color.fromRGBO(239, 246, 255, 1), }
borderRadius: BorderRadius.circular(16.r), },
child: Column(
children: [
Container(
width: 80.w,
height: 80.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(239, 246, 255, 1),
borderRadius: BorderRadius.circular(16.r),
),
child: Icon(
action['icon'] as IconData,
color: const Color.fromRGBO(59, 130, 246, 1),
size: 36.sp,
),
), ),
child: Icon( SizedBox(height: 8.h),
action['icon'] as IconData, Text(
color: const Color.fromRGBO(59, 130, 246, 1), name,
size: 36.sp, style: TextStyle(
fontSize: 22.sp,
color: const Color.fromRGBO(107, 114, 128, 1),
),
), ),
), ],
SizedBox(height: 8.h), ),
Text(
action['name'] as String,
style: TextStyle(
fontSize: 22.sp,
color: const Color.fromRGBO(107, 114, 128, 1),
),
),
],
), ),
); );
}).toList(), }).toList(),
......
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
class RoomStatusDistribution extends StatelessWidget { class RoomStatusDistribution extends StatelessWidget {
final Map<String, dynamic> roomStatusDistribution; final Map<String, dynamic> roomStatusDistribution;
...@@ -13,108 +15,123 @@ class RoomStatusDistribution extends StatelessWidget { ...@@ -13,108 +15,123 @@ class RoomStatusDistribution extends StatelessWidget {
roomStatusDistribution['statuses'] as List<Map<String, dynamic>>; roomStatusDistribution['statuses'] as List<Map<String, dynamic>>;
final totalRooms = roomStatusDistribution['totalRooms'] as int; final totalRooms = roomStatusDistribution['totalRooms'] as int;
return Container( return GestureDetector(
width: double.infinity, onTap: () {
padding: EdgeInsets.all(28.w), context.pushRoute(const ReportRoomDetailRoute());
decoration: BoxDecoration( },
borderRadius: BorderRadius.circular(24.r), child: Container(
color: Colors.white, width: double.infinity,
), padding: EdgeInsets.all(28.w),
child: Column( decoration: BoxDecoration(
crossAxisAlignment: CrossAxisAlignment.start, borderRadius: BorderRadius.circular(24.r),
children: [ color: Colors.white,
Row( ),
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
roomStatusDistribution['title'] as String, Row(
style: TextStyle( mainAxisAlignment: MainAxisAlignment.spaceBetween,
fontSize: 28.sp, children: [
fontWeight: FontWeight.normal, Text(
color: const Color.fromRGBO(107, 114, 128, 1), roomStatusDistribution['title'] as String,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.normal,
color: const Color.fromRGBO(107, 114, 128, 1),
),
), ),
), Row(
Text( children: [
'共 $totalRooms 间', Text(
style: TextStyle( '共 $totalRooms 间',
fontSize: 22.sp, style: TextStyle(
color: const Color.fromRGBO(156, 163, 175, 1), fontSize: 22.sp,
color: const Color.fromRGBO(156, 163, 175, 1),
),
),
SizedBox(width: 8.w),
Icon(
Icons.arrow_forward_ios,
size: 20.sp,
color: const Color.fromRGBO(156, 163, 175, 1),
),
],
), ),
), ],
], ),
), SizedBox(height: 20.h),
SizedBox(height: 20.h), ...statuses.map((status) {
...statuses.map((status) { final count = status['count'] as int;
final count = status['count'] as int; final color = status['color'] as Color;
final color = status['color'] as Color; final name = status['name'] as String;
final name = status['name'] as String; final percentage = totalRooms > 0 ? count / totalRooms : 0.0;
final percentage = totalRooms > 0 ? count / totalRooms : 0.0;
return Padding( return Padding(
padding: EdgeInsets.only(bottom: 16.h), padding: EdgeInsets.only(bottom: 16.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Row( Row(
children: [ children: [
Container( Container(
width: 12.w, width: 12.w,
height: 12.h, height: 12.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: color, color: color,
shape: BoxShape.circle, shape: BoxShape.circle,
),
), ),
), SizedBox(width: 8.w),
SizedBox(width: 8.w), Text(
Text( name,
name, style: TextStyle(
style: TextStyle( fontSize: 24.sp,
fontSize: 24.sp, color: const Color.fromRGBO(55, 65, 81, 1),
color: const Color.fromRGBO(55, 65, 81, 1), ),
), ),
), ],
],
),
Text(
'$count 间',
style: TextStyle(
fontSize: 24.sp,
color: const Color.fromRGBO(55, 65, 81, 1),
), ),
), Text(
], '$count 间',
), style: TextStyle(
SizedBox(height: 8.h), fontSize: 24.sp,
Stack( color: const Color.fromRGBO(55, 65, 81, 1),
children: [ ),
Container(
height: 8.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(229, 231, 235, 1),
borderRadius: BorderRadius.circular(4.r),
), ),
), ],
FractionallySizedBox( ),
widthFactor: percentage, SizedBox(height: 8.h),
child: Container( Stack(
children: [
Container(
height: 8.h, height: 8.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: color, color: const Color.fromRGBO(229, 231, 235, 1),
borderRadius: BorderRadius.circular(4.r), borderRadius: BorderRadius.circular(4.r),
), ),
), ),
), FractionallySizedBox(
], widthFactor: percentage,
), child: Container(
], height: 8.h,
), decoration: BoxDecoration(
); color: color,
}).toList(), borderRadius: BorderRadius.circular(4.r),
], ),
),
),
],
),
],
),
);
}).toList(),
],
),
), ),
); );
} }
} }
\ No newline at end of file
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
class WeeklyPowerChart extends StatelessWidget { class WeeklyPowerChart extends StatelessWidget {
final Map<String, dynamic> weeklyPowerUsage; final Map<String, dynamic> weeklyPowerUsage;
...@@ -11,36 +13,50 @@ class WeeklyPowerChart extends StatelessWidget { ...@@ -11,36 +13,50 @@ class WeeklyPowerChart extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final data = weeklyPowerUsage['data'] as List<Map<String, dynamic>>; final data = weeklyPowerUsage['data'] as List<Map<String, dynamic>>;
return Container( return GestureDetector(
width: double.infinity, onTap: () {
padding: EdgeInsets.all(28.w), context.pushRoute(const ReportEnergyDetailRoute());
decoration: BoxDecoration( },
borderRadius: BorderRadius.circular(24.r), child: Container(
color: Colors.white, width: double.infinity,
), padding: EdgeInsets.all(28.w),
child: Column( decoration: BoxDecoration(
crossAxisAlignment: CrossAxisAlignment.start, borderRadius: BorderRadius.circular(24.r),
children: [ color: Colors.white,
Row( ),
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
'${weeklyPowerUsage['title']} (${weeklyPowerUsage['unit']})', Row(
style: TextStyle( mainAxisAlignment: MainAxisAlignment.spaceBetween,
fontSize: 28.sp, children: [
fontWeight: FontWeight.normal, Text(
color: const Color.fromRGBO(107, 114, 128, 1), '${weeklyPowerUsage['title']} (${weeklyPowerUsage['unit']})',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.normal,
color: const Color.fromRGBO(107, 114, 128, 1),
),
), ),
), Row(
Text( children: [
weeklyPowerUsage['dateRange'] as String, Text(
style: TextStyle( weeklyPowerUsage['dateRange'] as String,
fontSize: 22.sp, style: TextStyle(
color: const Color.fromRGBO(156, 163, 175, 1), fontSize: 22.sp,
color: const Color.fromRGBO(156, 163, 175, 1),
),
),
SizedBox(width: 8.w),
Icon(
Icons.arrow_forward_ios,
size: 20.sp,
color: const Color.fromRGBO(156, 163, 175, 1),
),
],
), ),
), ],
], ),
),
SizedBox(height: 20.h), SizedBox(height: 20.h),
SizedBox( SizedBox(
height: 200.h, height: 200.h,
...@@ -108,6 +124,7 @@ class WeeklyPowerChart extends StatelessWidget { ...@@ -108,6 +124,7 @@ class WeeklyPowerChart extends StatelessWidget {
), ),
], ],
), ),
),
); );
} }
} }
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/views/report/room/cubit/room_report_state.dart'; import 'package:smart_hotel_app/views/report/room/cubit/room_report_state.dart';
class RoomReportCubit extends Cubit<RoomReportState> { class RoomReportCubit extends Cubit<RoomReportState> {
RoomReportCubit() : super(const RoomReportState()); RoomReportCubit() : super(const RoomReportState()) {
_initData();
}
void _initData() {
final floors = [
FloorInfo(
floorName: '一楼',
rooms: List.generate(10, (index) => _createRoom(101 + index)),
),
FloorInfo(
floorName: '二楼',
rooms: List.generate(10, (index) => _createRoom(201 + index)),
),
FloorInfo(
floorName: '三楼',
rooms: List.generate(10, (index) => _createRoom(301 + index)),
),
FloorInfo(
floorName: '四楼',
rooms: List.generate(10, (index) => _createRoom(401 + index)),
),
FloorInfo(
floorName: '五楼',
rooms: List.generate(10, (index) => _createRoom(501 + index)),
),
FloorInfo(
floorName: '六楼',
rooms: List.generate(10, (index) => _createRoom(601 + index)),
),
];
final statusStats = [
const StatusStat(
label: '入住',
count: 45,
color: Color.fromRGBO(59, 130, 246, 1),
),
const StatusStat(
label: '空闲',
count: 7,
color: Color.fromRGBO(156, 163, 175, 1),
),
const StatusStat(
label: '预订',
count: 5,
color: Color.fromRGBO(147, 197, 253, 1),
),
const StatusStat(
label: '告警',
count: 3,
color: Color.fromRGBO(251, 191, 36, 1),
),
];
final detailRooms = [
RoomInfo(
roomNumber: '302',
status: RoomStatus.occupied,
statusText: '入住中',
deviceStatus: const RoomDeviceStatus(
hasPerson: true,
powerOn: true,
wifiNormal: true,
acOn: true,
acTemperature: '24',
lightOn: false,
tvOn: true,
curtainOn: false,
),
),
];
emit(state.copyWith(
floors: floors,
statusStats: statusStats,
detailRooms: detailRooms,
));
}
RoomInfo _createRoom(int number) {
RoomStatus status;
String statusText;
if (number == 303) {
status = RoomStatus.warning;
statusText = '告警';
} else if (number == 309) {
status = RoomStatus.temperature;
statusText = '温度';
} else if ([302, 304, 308].contains(number)) {
status = RoomStatus.occupied;
statusText = number == 308 ? '入住·勿扰' : '入住·在房';
} else if (number == 307) {
status = RoomStatus.reserved;
statusText = '预定';
} else {
status = RoomStatus.vacant;
statusText = '空闲';
}
return RoomInfo(
roomNumber: number.toString(),
status: status,
statusText: statusText,
);
}
void selectFloor(int index) {
emit(state.copyWith(selectedFloorIndex: index));
}
} }
\ No newline at end of file
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
enum RoomStatus {
vacant,
occupied,
reserved,
warning,
temperature,
}
class RoomDeviceStatus {
final bool hasPerson;
final bool powerOn;
final bool wifiNormal;
final bool acOn;
final String acTemperature;
final bool lightOn;
final bool tvOn;
final bool curtainOn;
const RoomDeviceStatus({
this.hasPerson = true,
this.powerOn = true,
this.wifiNormal = true,
this.acOn = false,
this.acTemperature = '24',
this.lightOn = false,
this.tvOn = false,
this.curtainOn = false,
});
RoomDeviceStatus copyWith({
bool? hasPerson,
bool? powerOn,
bool? wifiNormal,
bool? acOn,
String? acTemperature,
bool? lightOn,
bool? tvOn,
bool? curtainOn,
}) {
return RoomDeviceStatus(
hasPerson: hasPerson ?? this.hasPerson,
powerOn: powerOn ?? this.powerOn,
wifiNormal: wifiNormal ?? this.wifiNormal,
acOn: acOn ?? this.acOn,
acTemperature: acTemperature ?? this.acTemperature,
lightOn: lightOn ?? this.lightOn,
tvOn: tvOn ?? this.tvOn,
curtainOn: curtainOn ?? this.curtainOn,
);
}
}
class RoomInfo {
final String roomNumber;
final RoomStatus status;
final String statusText;
final RoomDeviceStatus deviceStatus;
const RoomInfo({
required this.roomNumber,
required this.status,
required this.statusText,
this.deviceStatus = const RoomDeviceStatus(),
});
RoomInfo copyWith({
String? roomNumber,
RoomStatus? status,
String? statusText,
RoomDeviceStatus? deviceStatus,
}) {
return RoomInfo(
roomNumber: roomNumber ?? this.roomNumber,
status: status ?? this.status,
statusText: statusText ?? this.statusText,
deviceStatus: deviceStatus ?? this.deviceStatus,
);
}
}
class FloorInfo {
final String floorName;
final List<RoomInfo> rooms;
const FloorInfo({
required this.floorName,
required this.rooms,
});
FloorInfo copyWith({
String? floorName,
List<RoomInfo>? rooms,
}) {
return FloorInfo(
floorName: floorName ?? this.floorName,
rooms: rooms ?? this.rooms,
);
}
}
class StatusStat {
final String label;
final int count;
final Color color;
const StatusStat({
required this.label,
required this.count,
required this.color,
});
}
class RoomReportState extends Equatable { class RoomReportState extends Equatable {
const RoomReportState(); final List<FloorInfo> floors;
final int selectedFloorIndex;
final List<StatusStat> statusStats;
final List<RoomInfo> detailRooms;
const RoomReportState({
this.floors = const [],
this.selectedFloorIndex = 2,
this.statusStats = const [],
this.detailRooms = const [],
});
RoomReportState copyWith() { RoomReportState copyWith({
return const RoomReportState(); List<FloorInfo>? floors,
int? selectedFloorIndex,
List<StatusStat>? statusStats,
List<RoomInfo>? detailRooms,
}) {
return RoomReportState(
floors: floors ?? this.floors,
selectedFloorIndex: selectedFloorIndex ?? this.selectedFloorIndex,
statusStats: statusStats ?? this.statusStats,
detailRooms: detailRooms ?? this.detailRooms,
);
} }
@override @override
List<Object?> get props => []; List<Object?> get props => [
floors,
selectedFloorIndex,
statusStats,
detailRooms,
];
} }
\ No newline at end of file
...@@ -37,12 +37,12 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> { ...@@ -37,12 +37,12 @@ class ServiceIndexCubit extends Cubit<ServiceIndexState> {
Map<String, List<Map<String, dynamic>>> _buildRoomCache() { Map<String, List<Map<String, dynamic>>> _buildRoomCache() {
return { return {
'1楼': _generateRooms(1, 80), '1楼': _generateRooms(1, 20),
'2楼': _generateRooms(2, Random().nextInt(41) + 10), '2楼': _generateRooms(2, Random().nextInt(21) + 10),
'3楼': _generateRooms(3, Random().nextInt(41) + 10), '3楼': _generateRooms(3, Random().nextInt(21) + 10),
'4楼': _generateRooms(4, Random().nextInt(41) + 10), '4楼': _generateRooms(4, Random().nextInt(21) + 10),
'5楼': _generateRooms(5, Random().nextInt(5) + 10), '5楼': _generateRooms(5, Random().nextInt(5) + 10),
'6楼': _generateRooms(6, Random().nextInt(41) + 10), '6楼': _generateRooms(6, Random().nextInt(21) + 10),
}; };
} }
......
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:smart_hotel_app/views/service/index/cubit/service_index_cubit.dart'; import 'package:smart_hotel_app/views/service/index/cubit/service_index_cubit.dart';
import 'package:smart_hotel_app/views/service/index/cubit/service_index_state.dart'; import 'package:smart_hotel_app/views/service/index/cubit/service_index_state.dart';
...@@ -18,15 +19,17 @@ class ServiceIndexView extends StatelessWidget { ...@@ -18,15 +19,17 @@ class ServiceIndexView extends StatelessWidget {
child: LayoutBuilder( child: LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
return SingleChildScrollView( return SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 28.w),
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight), constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Container( child: Container(
color: const Color.fromRGBO(242, 243, 245, 1), // color: const Color.fromRGBO(242, 243, 245, 1),
color: Color.fromRGBO(242, 243, 245, 1.0),
child: BlocBuilder<ServiceIndexCubit, ServiceIndexState>( child: BlocBuilder<ServiceIndexCubit, ServiceIndexState>(
builder: (context, state) { builder: (context, state) {
return Column( return Column(
children: [ children: [
ServiceHeadBlock(pendingCount: state.pendingCount), const ServiceHeadBlock(),
ServiceStatsBlock( ServiceStatsBlock(
pendingCount: state.pendingCount, pendingCount: state.pendingCount,
occupiedCount: state.occupiedRooms, occupiedCount: state.occupiedRooms,
......
...@@ -525,4 +525,4 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> { ...@@ -525,4 +525,4 @@ class _RoomManagementBlockState extends State<RoomManagementBlock> {
], ],
); );
} }
} }
\ No newline at end of file
...@@ -2,76 +2,47 @@ import 'package:flutter/material.dart'; ...@@ -2,76 +2,47 @@ import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
class ServiceHeadBlock extends StatelessWidget { class ServiceHeadBlock extends StatelessWidget {
final int pendingCount; const ServiceHeadBlock({super.key});
const ServiceHeadBlock({super.key, required this.pendingCount});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.fromLTRB(28.w, 20.h, 28.w, 20.h), height: 150.h,
color: Color.fromRGBO(73, 149, 234, 1), padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight, left: 20.w, right: 20.w),
child: Stack( decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(20.r),
color: Colors.white,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Column( Text(
crossAxisAlignment: CrossAxisAlignment.start, '客房服务看板',
children: [ style: TextStyle(
Row( fontSize: 32.sp,
children: [ fontWeight: FontWeight.bold,
Icon(Icons.emoji_emotions_outlined, color: const Color.fromRGBO(0, 0, 0, 1),
color: Color.fromRGBO(255, 255, 255, 1), size: 40.sp), fontFamily: 'FZLTXH',
SizedBox(width: 10.w), ),
Text(
'早安,张先生',
style: TextStyle(
fontSize: 40.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'FZLTXH',
),
),
],
),
SizedBox(height: 15.h),
Text(
'今日天气:晴 25°C ~ 35°C',
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(255, 255, 255, 1),
fontFamily: 'FZLTXH',
),
),
],
), ),
Positioned( Container(
right: 0, width: 64.w,
bottom: 0, height: 64.w,
child: GestureDetector( decoration: BoxDecoration(
onTap: () {}, shape: BoxShape.circle,
child: Container( border: Border.all(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 3.h), color: const Color.fromRGBO(73, 149, 234, 1),
decoration: BoxDecoration( width: 1.w,
borderRadius: BorderRadius.circular(20.r), ),
color: const Color.fromRGBO(1, 1, 1, 0.1), ),
), child: CircleAvatar(
child: Row( radius: 40.w,
children: [ backgroundColor: Colors.white,
Icon(Icons.notifications_outlined, child: Icon(
color: Colors.white, size: 38.sp), Icons.person,
SizedBox(width: 5.w), color: const Color.fromRGBO(73, 149, 234, 1),
Text( size: 48.sp,
'待响应需求 $pendingCount',
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'FZLTXH',
),
),
],
),
), ),
), ),
), ),
...@@ -79,4 +50,4 @@ class ServiceHeadBlock extends StatelessWidget { ...@@ -79,4 +50,4 @@ class ServiceHeadBlock extends StatelessWidget {
), ),
); );
} }
} }
\ No newline at end of file
...@@ -19,21 +19,21 @@ class ServiceStatsBlock extends StatelessWidget { ...@@ -19,21 +19,21 @@ class ServiceStatsBlock extends StatelessWidget {
width: double.infinity, width: double.infinity,
padding: EdgeInsets.all(20.w), padding: EdgeInsets.all(20.w),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.r), // borderRadius: BorderRadius.circular(24.r),
color: Colors.white, color: Color.fromRGBO(242, 243, 245, 1.0),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( // Text(
'服务概览', // '服务概览',
style: TextStyle( // style: TextStyle(
fontSize: 28.sp, // fontSize: 28.sp,
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
color: const Color.fromRGBO(31, 41, 55, 1), // color: const Color.fromRGBO(31, 41, 55, 1),
), // ),
), // ),
SizedBox(height: 20.h), // SizedBox(height: 20.h),
Row( Row(
children: [ children: [
_buildStatCard( _buildStatCard(
...@@ -74,12 +74,12 @@ class ServiceStatsBlock extends StatelessWidget { ...@@ -74,12 +74,12 @@ class ServiceStatsBlock extends StatelessWidget {
), ),
child: Column( child: Column(
children: [ children: [
Icon(icon, color: color, size: 28.sp), // Icon(icon, color: color, size: 28.sp),
SizedBox(height: 8.h), SizedBox(height: 8.h),
Text( Text(
value, value,
style: TextStyle( style: TextStyle(
fontSize: 32.sp, fontSize: 60.sp,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: color, color: color,
), ),
...@@ -88,7 +88,7 @@ class ServiceStatsBlock extends StatelessWidget { ...@@ -88,7 +88,7 @@ class ServiceStatsBlock extends StatelessWidget {
Text( Text(
label, label,
style: TextStyle( style: TextStyle(
fontSize: 20.sp, fontSize: 24.sp,
color: const Color.fromRGBO(107, 114, 128, 1), color: const Color.fromRGBO(107, 114, 128, 1),
), ),
), ),
...@@ -97,4 +97,4 @@ class ServiceStatsBlock extends StatelessWidget { ...@@ -97,4 +97,4 @@ class ServiceStatsBlock extends StatelessWidget {
), ),
); );
} }
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; ...@@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; 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/routes/app_router.gr.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/room_overview_card.dart'; import 'package:smart_hotel_app/views/service/room/widget/room_overview_card.dart';
...@@ -64,6 +65,11 @@ class ServiceRoomDetailView extends StatelessWidget { ...@@ -64,6 +65,11 @@ class ServiceRoomDetailView extends StatelessWidget {
controlDevices: state.controlDevices, controlDevices: state.controlDevices,
onMainPowerToggle: (value) => cubit.toggleMainPower(value), onMainPowerToggle: (value) => cubit.toggleMainPower(value),
onDeviceToggle: (index, value) => cubit.toggleControlDevice(index, value), onDeviceToggle: (index, value) => cubit.toggleControlDevice(index, value),
onDeviceTap: (index, device) {
if (device.name == '空调') {
context.pushRoute(const ServiceDeviceDetailRoute());
}
},
), ),
SizedBox(height: 20.h), SizedBox(height: 20.h),
const RoomBottomButtons(), const RoomBottomButtons(),
......
...@@ -8,6 +8,7 @@ class DeviceControlCard extends StatelessWidget { ...@@ -8,6 +8,7 @@ class DeviceControlCard extends StatelessWidget {
final List<ControlDevice> controlDevices; final List<ControlDevice> controlDevices;
final Function(bool) onMainPowerToggle; final Function(bool) onMainPowerToggle;
final Function(int, bool) onDeviceToggle; final Function(int, bool) onDeviceToggle;
final Function(int, ControlDevice)? onDeviceTap;
const DeviceControlCard({ const DeviceControlCard({
super.key, super.key,
...@@ -15,6 +16,7 @@ class DeviceControlCard extends StatelessWidget { ...@@ -15,6 +16,7 @@ class DeviceControlCard extends StatelessWidget {
required this.controlDevices, required this.controlDevices,
required this.onMainPowerToggle, required this.onMainPowerToggle,
required this.onDeviceToggle, required this.onDeviceToggle,
this.onDeviceTap,
}); });
@override @override
...@@ -107,14 +109,21 @@ class DeviceControlCard extends StatelessWidget { ...@@ -107,14 +109,21 @@ class DeviceControlCard extends StatelessWidget {
], ],
), ),
FlutterSwitch( FlutterSwitch(
width: 48.0,
height: 25.0,
value: mainPowerOn, value: mainPowerOn,
onToggle: onMainPowerToggle, showOnOff: false,
activeColor: const Color.fromRGBO(59, 130, 246, 1), onToggle: onMainPowerToggle
inactiveColor: const Color.fromRGBO(209, 213, 219, 1),
width: 60.w,
height: 30.h,
toggleSize: 26,
), ),
// FlutterSwitch(
// value: mainPowerOn,
// onToggle: onMainPowerToggle,
// activeColor: const Color.fromRGBO(59, 130, 246, 1),
// inactiveColor: const Color.fromRGBO(209, 213, 219, 1),
// width: 50.w,
// height: 28.h,
// // toggleSize: 26,
// ),
], ],
), ),
SizedBox(height: 20.h), SizedBox(height: 20.h),
...@@ -134,49 +143,62 @@ class DeviceControlCard extends StatelessWidget { ...@@ -134,49 +143,62 @@ class DeviceControlCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded( Expanded(
child: Column( child: Material(
crossAxisAlignment: CrossAxisAlignment.start, color: Colors.transparent,
children: [ child: InkWell(
Row( onTap: onDeviceTap != null ? () => onDeviceTap!(index, device) : null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Icon( Row(
device.icon, children: [
color: const Color.fromRGBO(66, 165, 245, 1.0), Icon(
size: 36.sp, 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),
),
),
],
), ),
SizedBox(width: 8.w), if (device.detailText != null) ...[
Text( SizedBox(height: 8.h),
device.name, Text(
style: TextStyle( device.detailText!,
fontSize: 28.sp, style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 24.sp,
color: const Color.fromRGBO(10, 13, 20, 1.0), color: const Color.fromRGBO(100, 116, 139, 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( FlutterSwitch(
width: 48.0,
height: 25.0,
value: device.isOn, value: device.isOn,
showOnOff: false,
onToggle: (value) => onDeviceToggle(index, value), 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,
), ),
// 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) ...[ if (index < controlDevices.length - 1) ...[
......
...@@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ...@@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)
......
...@@ -6,9 +6,7 @@ import FlutterMacOS ...@@ -6,9 +6,7 @@ import FlutterMacOS
import Foundation import Foundation
import flutter_secure_storage_macos import flutter_secure_storage_macos
import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
} }
This diff is collapsed.
...@@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ...@@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)
......
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