Commit 95ab7cfd authored by 张宏's avatar 张宏

.

parent 3978e40d
......@@ -23,5 +23,7 @@ class AppRouter extends $AppRouter {
AutoRoute(page: AbnormalDetailRoute.page),
AutoRoute(page:DeviceDetailRoute.page),
AutoRoute(page: ServiceRoomDetailRoute.page),
AutoRoute(page: ReportEnergyDetailRoute.page),
AutoRoute(page: ReportRoomDetailRoute.page),
];
}
This diff is collapsed.
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/home/index/controller.dart';
class EquipmentListBlock extends StatefulWidget {
const EquipmentListBlock({super.key});
final HomeIndexController controller;
const EquipmentListBlock({super.key, required this.controller});
@override
State<EquipmentListBlock> createState() => _EquipmentListBlockState();
}
class _EquipmentListBlockState extends State<EquipmentListBlock> {
final List<Map<String, dynamic>> _equipmentList = [
{
'icon': Icons.electrical_services,
'title': '空调主机-01',
'subtitle': '位置:A栋3楼机房',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.thermostat,
'title': '温度传感器-02',
'subtitle': '位置:B栋2楼走廊',
'status': '异常',
'statusColor': Color.fromRGBO(246, 158, 11, 1),
},
{
'icon': Icons.water_drop,
'title': '水管阀门-03',
'subtitle': '位置:C栋1楼大厅',
'status': '待检修',
'statusColor': Color.fromRGBO(239, 68, 68, 1),
},
{
'icon': Icons.lightbulb,
'title': '照明系统-04',
'subtitle': '位置:D栋5楼会议室',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.electrical_services,
'title': '空调主机-05',
'subtitle': '位置:A栋3楼机房',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.thermostat,
'title': '温度传感器-06',
'subtitle': '位置:B栋2楼走廊',
'status': '异常',
'statusColor': Color.fromRGBO(246, 158, 11, 1),
},
{
'icon': Icons.water_drop,
'title': '水管阀门-07',
'subtitle': '位置:C栋1楼大厅',
'status': '待检修',
'statusColor': Color.fromRGBO(239, 68, 68, 1),
},
{
'icon': Icons.lightbulb,
'title': '照明系统-08',
'subtitle': '位置:D栋5楼会议室',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.lightbulb,
'title': '照明系统-08',
'subtitle': '位置:D栋5楼会议室',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.lightbulb,
'title': '照明系统-08',
'subtitle': '位置:D栋5楼会议室',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.lightbulb,
'title': '照明系统-08',
'subtitle': '位置:D栋5楼会议室',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
{
'icon': Icons.lightbulb,
'title': '照明系统-08',
'subtitle': '位置:D栋5楼会议室',
'status': '运行中',
'statusColor': Color.fromRGBO(34, 197, 94, 1),
},
];
Widget _buildEquipmentItem(Map<String, dynamic> item) {
Widget _buildEquipmentItem(EquipmentItem item) {
return Container(
padding: EdgeInsets.symmetric(vertical: 8.h),
padding: EdgeInsets.symmetric(vertical: 16.h),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color.fromRGBO(71, 85, 105, 0.3),
width: 1,
color: Color.fromRGBO(235, 235, 235, 1.0),
width: 1.w,
),
),
),
child: Row(
children: [
Container(
width: 40.w,
height: 40.h,
width: 64.w,
height: 66.h,
decoration: BoxDecoration(
color: Color.fromRGBO(71, 85, 105, 0.3),
borderRadius: BorderRadius.circular(8.r),
color: Color.fromRGBO(235, 244, 255, 1.0),
borderRadius: BorderRadius.circular(12.r),
),
child: Icon(
item['icon'] as IconData,
color: Color.fromRGBO(246, 158, 11, 1),
size: 20.sp,
item.icon,
color: Color.fromRGBO(66, 165, 245, 1.0),
size: 32.sp,
),
),
SizedBox(width: 12.w),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item['title'] as String,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w500,
color: Colors.white,
Transform.translate(
offset: Offset(0, 2.h),
child: Text(
item.title,
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
SizedBox(height: 4.h),
Text(
item['subtitle'] as String,
item.subtitle,
style: TextStyle(
fontSize: 12.sp,
color: Color.fromRGBO(148, 163, 184, 1),
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1.0),
),
),
],
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
decoration: BoxDecoration(
color: (item['statusColor'] as Color).withOpacity(0.2),
borderRadius: BorderRadius.circular(4.r),
),
child: Text(
item['status'] as String,
style: TextStyle(
fontSize: 12.sp,
color: item['statusColor'] as Color,
),
Text(
item.status,
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: item.statusColor,
),
),
],
......@@ -167,9 +80,11 @@ class _EquipmentListBlockState extends State<EquipmentListBlock> {
@override
Widget build(BuildContext context) {
final equipmentList = widget.controller.getEquipmentList();
return Container(
width: double.infinity,
margin: EdgeInsets.only(top: 10.h,left: 20.w,right: 20.w),
// margin: EdgeInsets.symmetric(horizontal: 14.w, vertical: 24.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
......@@ -177,29 +92,38 @@ class _EquipmentListBlockState extends State<EquipmentListBlock> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('设备巡检',style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,color: Colors.white),),
Text('查看全部',style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,color: Colors.white),),
Text(
'设备巡检',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
Text(
'查看全部>',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(73, 149, 234, 1.0),
),
),
],
),
SizedBox(height: 12.h),
Container(
width: double.infinity,
padding: EdgeInsets.all(20.w),
padding: EdgeInsets.only(top: 20.w,bottom: 20.w,left: 42.w,right: 42.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: Color.fromRGBO(30, 41, 59, 1),
border: BoxBorder.all(
color: Color.fromRGBO(246, 158, 11, 1.0),
width: 1.w,
),
borderRadius: BorderRadius.circular(20.r),
color: Colors.white,
),
child: Column(
children: [
..._equipmentList.map((item) => _buildEquipmentItem(item)).toList(),
...equipmentList.map((item) => _buildEquipmentItem(item)).toList(),
],
),
),
SizedBox(height: 20.h),
],
),
);
......
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/home/index/controller.dart';
class TaskHeadBlock extends StatefulWidget {
const TaskHeadBlock({super.key});
final HomeIndexController controller;
const TaskHeadBlock({super.key, required this.controller});
@override
State<TaskHeadBlock> createState() => _TaskHeadBlockState();
......@@ -13,51 +16,28 @@ class _TaskHeadBlockState extends State<TaskHeadBlock> {
Widget build(BuildContext context) {
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: Colors.blueGrey,
width: 1.w,
),
),
// color: Colors.red,
),
// height: 140.h,
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('设备告警看板',style: TextStyle(fontSize: 28.sp,fontWeight: FontWeight.bold,color: Colors.white),),
Text('工程运维视角 今日xx条待处理',style: TextStyle(fontSize: 24.sp,color: Color.fromRGBO(61, 79, 106, 1.0)),),
],
),
Container(
width: 50.w,
height: 50.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: Colors.grey,
border: Border.all(
color: Colors.blueGrey,
width: 1.w,
),
),
),
],
Text(
'设备告警看板',
style: TextStyle(
fontSize: 28.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(51, 51, 51, 1.0),
),
),
SizedBox(height: 8.h),
Text(
'工程运维视角·今日${widget.controller.getPendingTaskCount()}条待处理',
style: TextStyle(
fontSize: 16.sp,
color: Color.fromRGBO(102, 102, 102, 1.0),
),
),
],
),
);
......
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/home/index/controller.dart';
class TaskTotalBlock extends StatefulWidget {
const TaskTotalBlock({super.key});
final HomeIndexController controller;
const TaskTotalBlock({super.key, required this.controller});
@override
State<TaskTotalBlock> createState() => _TaskTotalBlockState();
......@@ -13,143 +16,121 @@ class _TaskTotalBlockState extends State<TaskTotalBlock> {
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: 180.h,
decoration: BoxDecoration(
// color: Colors.red,
border: Border(
bottom: BorderSide(
width: 1.w,
),
),
),
alignment: Alignment.center,
// height: 180.h,
child: Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// 告警待处理
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 190.w,
height: 120.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: Colors.white,
border: Border.all(
color: Colors.blueGrey,
width: 1.w,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('1',style: TextStyle(fontSize: 28.sp,fontWeight: FontWeight.bold,color: Colors.green),),
Text('告警待处理',style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,color: Colors.grey),),
],
),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 高警待处理
Expanded(
child: Container(
margin: EdgeInsets.only(right: 10.w),
height: 120.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
color: Colors.white,
),
Container(
width: 160.w,
height: 1.h,
margin: EdgeInsets.only(top: 5.h),
decoration: BoxDecoration(
color: Colors.white,
border: Border(bottom: BorderSide(
color: Colors.blueGrey,
width: 1.w,
)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'${widget.controller.getHighAlarmCount()}',
style: TextStyle(
fontSize: 48.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(255, 77, 79, 1.0),
),
),
// SizedBox(height: 5.h),
Transform.translate(
offset: Offset(0, -8.h),
child: Text(
'高警待处理',
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1.0),
),
),
),
],
),
],
),
),
// 中警待处理
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 190.w,
height: 120.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: Colors.white,
border: Border.all(
color: Colors.blueGrey,
width: 1.w,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('12',style: TextStyle(fontSize: 28.sp,fontWeight: FontWeight.bold,color: Colors.green),),
Text('中警待处理',style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,color: Colors.grey),),
],
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10.w),
height: 120.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
color: Colors.white,
),
Container(
width: 160.w,
height: 1.h,
margin: EdgeInsets.only(top: 5.h),
decoration: BoxDecoration(
color: Colors.white,
border: Border(bottom: BorderSide(
color: Colors.blueGrey,
width: 1.w,
)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${widget.controller.getMediumAlarmCount()}',
style: TextStyle(
fontSize: 48.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(100, 116, 139, 1.0),
),
),
// SizedBox(height: 8.h),
Transform.translate(
offset: Offset(0, -8.h),
child: Text(
'中警待处理',
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1.0),
),
),
),
],
),
],
),
),
// 设备在线
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 190.w,
height: 120.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.r),
color: Colors.white,
border: Border.all(
color: Colors.blueGrey,
width: 1.w,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('88',style: TextStyle(fontSize: 28.sp,fontWeight: FontWeight.bold,color: Colors.green),),
Text('设备在线',style: TextStyle(fontSize: 14.sp,fontWeight: FontWeight.bold,color: Colors.grey),),
],
),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 10.w),
height: 120.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.r),
color: Colors.white,
),
Container(
width: 160.w,
height: 1.h,
margin: EdgeInsets.only(top: 5.h),
decoration: BoxDecoration(
color: Colors.white,
border: Border(bottom: BorderSide(
color: Colors.blueGrey,
width: 1.w,
)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${widget.controller.getOnlineDeviceCount()}',
style: TextStyle(
fontSize: 48.sp,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(26, 188, 156, 1.0),
),
),
// SizedBox(height: 8.h),
Transform.translate(
offset: Offset(0, -8.h),
child: Text(
'设备在线',
style: TextStyle(
fontSize: 24.sp,
color: Color.fromRGBO(100, 116, 139, 1.0),
),
),
),
],
),
],
),
),
],
),
),
);
}
}
\ No newline at end of file
......@@ -3,6 +3,22 @@ import 'package:flutter/material.dart';
// import 'package:smart_hotel_app/routes/app_router.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
class EquipmentItem {
final IconData icon;
final String title;
final String subtitle;
final String status;
final Color statusColor;
EquipmentItem({
required this.icon,
required this.title,
required this.subtitle,
required this.status,
required this.statusColor,
});
}
class HomeIndexController {
final BuildContext context;
HomeIndexController(this.context);
......@@ -10,4 +26,161 @@ class HomeIndexController {
void handleToAbnormalDetail() {
context.pushRoute(const AbnormalDetailRoute());
}
int getPendingTaskCount() {
return 3;
}
int getHighAlarmCount() {
return 1;
}
int getMediumAlarmCount() {
return 1;
}
int getOnlineDeviceCount() {
return 48;
}
String getTemperatureAlarmTitle() {
return '温度异常告警';
}
String getTemperatureAlarmLocation() {
return '客房301·A-301智能空开';
}
String getCurrentTemperature() {
return '85';
}
String getCurrentVoltage() {
return '220';
}
String getCurrentCurrent() {
return '3.2';
}
String getWaitTime() {
return '2h37m';
}
String getAlarmLevel() {
return '紧急';
}
String getVoltageAlarmTitle() {
return '电压波动告警';
}
String getVoltageAlarmLocation() {
return '会议室2F-01';
}
String getVoltageValue() {
return '248';
}
String getNormalVoltage() {
return '235';
}
String getVoltageWaitTime() {
return '1h19m';
}
String getVoltageAlarmLevel() {
return '中警';
}
List<EquipmentItem> getEquipmentList() {
return [
EquipmentItem(
icon: Icons.power,
title: '客房305空开',
subtitle: '38°C·220V·520W',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.power,
title: '大堂总空开L-01',
subtitle: '380V·42A·28.6kW',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.wifi,
title: '招牌AP-03',
subtitle: '信号弱·RSSI-78dBm',
status: '注意',
statusColor: Color.fromRGBO(255, 193, 7, 1.0),
),
EquipmentItem(
icon: Icons.power,
title: '客房201空开',
subtitle: '25°C·220V·380W',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.power,
title: '水泵控制箱',
subtitle: '运行中·2.2kW',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.thermostat,
title: '冷库温控器',
subtitle: '-18°C·异常波动',
status: '告警',
statusColor: Color.fromRGBO(255, 77, 79, 1.0),
),
EquipmentItem(
icon: Icons.light,
title: '走廊照明回路',
subtitle: '12盏·功率240W',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.wifi,
title: '会议室AP-01',
subtitle: '连接数12·信号强',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.power,
title: '电梯控制柜',
subtitle: '运行中·电压稳定',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
EquipmentItem(
icon: Icons.thermostat,
title: '空调外机',
subtitle: '压力偏高·需检查',
status: '注意',
statusColor: Color.fromRGBO(255, 193, 7, 1.0),
),
EquipmentItem(
icon: Icons.wifi,
title: '楼道AP-05',
subtitle: '离线·需重启',
status: '离线',
statusColor: Color.fromRGBO(102, 102, 102, 1.0),
),
EquipmentItem(
icon: Icons.power,
title: '厨房消毒柜',
subtitle: '消毒中·温度120°C',
status: '正常',
statusColor: Color.fromRGBO(26, 188, 156, 1.0),
),
];
}
}
\ No newline at end of file
......@@ -39,21 +39,26 @@ class _HomeViewState extends State<HomeView> {
),
child: Container(
width: double.infinity,
color: Color.fromRGBO(15, 23, 42, 1),
child: const Column(
children: [
TaskHeadBlock(),
TaskTotalBlock(),
TemperatureBlock(),
VoltageOperateBlock(),
EquipmentListBlock(),
],
color: Color.fromRGBO(242, 243, 245, 1),
padding: EdgeInsets.symmetric(horizontal: 28.w),
child: Column(
children: [
TaskHeadBlock(controller: _controller),
SizedBox(height: 20.h),
TaskTotalBlock(controller: _controller),
SizedBox(height: 20.h),
TemperatureBlock(controller: _controller),
SizedBox(height: 20.h),
VoltageOperateBlock(controller: _controller),
SizedBox(height: 20.h),
EquipmentListBlock(controller: _controller),
SizedBox(height: 20.h),
],
),
),
),
)
);
},
);
},
);
}
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
@RoutePage()
......@@ -29,17 +30,64 @@ class _DefaultLayoutViewState extends State<DefaultLayoutView> {
onTap: tabsRouter.setActiveIndex,
elevation: 0,
backgroundColor: Colors.white,
selectedItemColor: Colors.blue,
selectedItemColor: const Color(0xFF4995EA),
unselectedItemColor: const Color(0xFF666666),
type: BottomNavigationBarType.fixed,
selectedFontSize: 12,
unselectedFontSize: 12,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "告警"),
BottomNavigationBarItem(icon: Icon(Icons.new_label), label: "服务"),
BottomNavigationBarItem(icon: Icon(Icons.message), label: "看板"),
selectedFontSize: 24.sp,
unselectedFontSize: 24.sp,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.my_location), label: "我的")
icon: Image.asset(
'lib/assets/tab/tab1.png',
width: 48.w,
height: 48.h,
),
activeIcon: Image.asset(
'lib/assets/tab/tab1_active.png',
width: 48.w,
height: 48.h,
),
label: "告警",
),
BottomNavigationBarItem(
icon: Image.asset(
'lib/assets/tab/tab2.png',
width: 48.w,
height: 48.h,
),
activeIcon: Image.asset(
'lib/assets/tab/tab2_active.png',
width: 48.w,
height: 48.h,
),
label: "服务",
),
BottomNavigationBarItem(
icon: Image.asset(
'lib/assets/tab/tab3.png',
width: 48.w,
height: 48.h,
),
activeIcon: Image.asset(
'lib/assets/tab/tab3_active.png',
width: 48.w,
height: 48.h,
),
label: "看板",
),
BottomNavigationBarItem(
icon: Image.asset(
'lib/assets/tab/tab4.png',
width: 48.w,
height: 48.h,
),
activeIcon: Image.asset(
'lib/assets/tab/tab4_active.png',
width: 48.w,
height: 48.h,
),
label: "我的",
),
],
),
);
......
......@@ -15,10 +15,10 @@ class BtnLogin extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: 70.h,
height: 96.h,
decoration: BoxDecoration(
color: Color.fromRGBO(89, 109, 243, 1),
borderRadius: BorderRadius.circular(20),
color: Color.fromRGBO(73, 149, 234, 1),
borderRadius: BorderRadius.circular(40.w),
),
child: ElevatedButton(
onPressed: isLoading ? null : onPressed,
......@@ -28,17 +28,21 @@ class BtnLogin extends StatelessWidget {
elevation: 0,
),
child: isLoading
? const SizedBox(
width: 20,
height: 20,
? SizedBox(
width: 40.w,
height: 40.w,
child: CircularProgressIndicator(
strokeWidth: 2,
strokeWidth: 3.w,
color: Colors.white,
),
)
: const Text(
"提交",
style: TextStyle(color: Colors.white),
: Text(
"登录",
style: TextStyle(
color: Colors.white,
fontSize: 32.sp,
fontWeight: FontWeight.bold,
),
),
),
);
......
......@@ -28,7 +28,7 @@ class _PasswordFieldState extends State<PasswordField> {
return TextFormField(
controller: widget.controller,
obscureText: _obscureText,
style: const TextStyle(color: Colors.white, fontSize: 14),
style: TextStyle(color: Color(0xFF333333), fontSize: 28.sp),
validator: (val) {
if (val == null || val.isEmpty) {
return "密码不能为空";
......@@ -37,44 +37,44 @@ class _PasswordFieldState extends State<PasswordField> {
},
decoration: InputDecoration(
filled: true,
hintText: "请输入密码",
hintStyle: const TextStyle(color: Colors.white70, fontSize: 14),
prefixIcon: const Icon(Icons.lock, color: Colors.white, size: 20),
prefixIconConstraints: const BoxConstraints(minWidth: 40, minHeight: 40),
hintText: "password",
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 28.sp),
prefixIcon: Icon(Icons.lock, color: Color(0xFF999999), size: 40.w),
prefixIconConstraints: BoxConstraints(minWidth: 80.w, minHeight: 80.w),
suffixIcon: IconButton(
icon: Icon(
_obscureText ? Icons.visibility_off : Icons.visibility,
color: Colors.white,
size: 20,
color: Color(0xFF999999),
size: 40.w,
),
onPressed: _toggleVisibility,
),
suffixIconConstraints: const BoxConstraints(minWidth: 40, minHeight: 40),
contentPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
suffixIconConstraints: BoxConstraints(minWidth: 80.w, minHeight: 80.w),
contentPadding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 24.w),
helperText: " ",
helperStyle: TextStyle(height: 1.1, fontSize: 12.sp),
errorStyle: TextStyle(color: Colors.red, fontSize: 12.sp, height: 1.1),
helperStyle: TextStyle(height: 1, fontSize: 24.sp),
errorStyle: TextStyle(color: Colors.red, fontSize: 24.sp, height: 1),
errorMaxLines: 1,
fillColor: const Color(0xFF1A2B3C),
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.white30, width: 1),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.white30, width: 1),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Color(0xFFF5F7FA), width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.white, width: 1.5),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Color(0xFFF5F7FA), width: 1),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.red, width: 1),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Colors.red, width: 1),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.red, width: 1.5),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Colors.red, width: 1.5),
),
),
);
......
......@@ -24,42 +24,41 @@ class RememberPasswordRow extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 32,
height: 32,
width: 40.w,
height: 40.w,
child: Transform.scale(
scale: 0.7,
scale: 0.8,
child: Checkbox(
value: value,
onChanged: onChanged,
activeColor: const Color.fromRGBO(89, 109, 243, 1),
activeColor: Color(0xFF4A90E2),
checkColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
borderRadius: BorderRadius.circular(25.w),
),
side: const BorderSide(color: Colors.white30),
side: BorderSide(color: Color(0xFF4A90E2)),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
),
),
Container(
margin: EdgeInsets.only(bottom: 2.h),
child: Text(
'记住密码',
style: TextStyle(color: Colors.white, fontSize: 18.sp),
SizedBox(width: 10.w),
Text(
'记住密码',
style: TextStyle(
color: Color(0xFF0A0D14),
fontSize: 24.sp,
),
)
),
],
),
),
GestureDetector(
onTap: onForgotPassword,
child: Text(
'忘记密码',
'忘记密码?',
style: TextStyle(
color: Color.fromRGBO(89, 109, 243, 1),
fontSize: 18.sp,
color: Color(0xFF0A0D14),
fontSize: 24.sp,
),
),
),
......
......@@ -13,7 +13,7 @@ class UsernameField extends StatelessWidget {
Widget build(BuildContext context) {
return TextFormField(
controller: controller,
style: const TextStyle(color: Colors.white, fontSize: 14),
style: TextStyle(color: Color(0xFF333333), fontSize: 28.sp),
validator: (val) {
if (val == null || val.isEmpty) {
return "用户名不能为空哦";
......@@ -22,35 +22,35 @@ class UsernameField extends StatelessWidget {
},
decoration: InputDecoration(
filled: true,
hintText: "请输入用户名",
hintStyle: const TextStyle(color: Colors.white70, fontSize: 14),
prefixIcon: const Icon(Icons.person, color: Colors.white, size: 20),
prefixIconConstraints: const BoxConstraints(minWidth: 40, minHeight: 40),
contentPadding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
hintText: "admin",
hintStyle: TextStyle(color: Color(0xFF999999), fontSize: 28.sp),
prefixIcon: Icon(Icons.person, color: Color(0xFF999999), size: 40.w),
prefixIconConstraints: BoxConstraints(minWidth: 80.w, minHeight: 80.w),
contentPadding: EdgeInsets.symmetric(vertical: 20.h, horizontal: 24.w),
helperText: " ",
helperStyle: TextStyle(height: 1, fontSize: 12.sp),
errorStyle: TextStyle(color: Colors.red, fontSize: 12.sp, height: 1),
helperStyle: TextStyle(height: 1, fontSize: 24.sp),
errorStyle: TextStyle(color: Colors.red, fontSize: 24.sp, height: 1),
errorMaxLines: 1,
fillColor: const Color(0xFF1A2B3C),
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.white30, width: 1),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.white30, width: 1),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Color(0xFFF5F7FA), width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.white, width: 1.5),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Color(0xFFF5F7FA), width: 1),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.red, width: 1),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Colors.red, width: 1),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
borderSide: const BorderSide(color: Colors.red, width: 1.5),
borderRadius: BorderRadius.circular(24.w),
borderSide: BorderSide(color: Colors.red, width: 1),
),
),
);
......
......@@ -61,56 +61,86 @@ class _LoginViewState extends State<LoginView> {
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.only(left: 50.w, right: 50.w),
decoration: BoxDecoration(
color: Color(0xFF1A2B3C),
),
decoration: BoxDecoration(
color: Color(0xFFF5F7FA),
),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 150.h),
Container(
margin: EdgeInsets.only(top: 150.h, bottom: 150.h),
margin: EdgeInsets.only(bottom: 80.h),
child: Column(
children: [
Image.asset(
'lib/assets/znjd_logo.png',
width: 100,
height: 100,
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,
),
),
),
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,
),
),
const SizedBox(height: 10),
Text("智能酒店管理系统", style: TextStyle(color: Colors.white, fontSize: 20.sp),),
Text("Intelligent Hotel Management System", style: TextStyle(color: Colors.white, fontSize: 20.sp),),
],
),
),
Container(
child: Form(
key: _frmGlobalKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
UsernameField(
controller: _txtUserNameController,
),
const SizedBox(height: 10),
PasswordField(
controller: _txtPwdController,
),
// const SizedBox(height: 5),
RememberPasswordRow(
value: _rememberPassword,
onChanged: (val) {
setState(() {
_rememberPassword = val ?? false;
});
},
onForgotPassword: _loginController.forgotPwd,
),
const SizedBox(height: 20),
BlocConsumer<AuthBloc, AuthState>(
listener: (context, state) {
if (state is AuthFailure) {
Fluttertoast.showToast(
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,
......@@ -118,24 +148,23 @@ class _LoginViewState extends State<LoginView> {
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
},
builder: (context, state) {
return BtnLogin(
isLoading: state is AuthLoading,
onPressed: () => _loginController.login(
_frmGlobalKey,
rememberPassword: _rememberPassword,
),
);
},
),
],
}
},
builder: (context, state) {
return BtnLogin(
isLoading: state is AuthLoading,
onPressed: () => _loginController.login(
_frmGlobalKey,
rememberPassword: _rememberPassword,
),
);
},
),
],
),
),
),
],
),
])
),
),
);
......
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/report/energy/controller.dart';
class EnergyStatsCardBlock extends StatelessWidget {
const EnergyStatsCardBlock({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Row(
children: [
Expanded(
child: _buildCard(
'${ReportEnergyController.todayEnergy.toInt()}',
'今日(kWh)',
'${ReportEnergyController.todayEnergyChange.toInt()}%',
true,
),
),
SizedBox(width: 12.w),
Expanded(
child: _buildCard(
'${ReportEnergyController.monthEnergy.toInt()}',
'本月(kWh)',
'${ReportEnergyController.monthEnergyChange.toInt()}%',
true,
),
),
SizedBox(width: 12.w),
Expanded(
child: _buildCard(
${ReportEnergyController.monthBill.toInt()}',
'本月电费预估',
null,
null,
),
),
],
),
);
}
Widget _buildCard(String value, String label, String? change, bool? isDown) {
return Container(
padding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 12.w),
decoration: BoxDecoration(
color: const Color.fromRGBO(30, 41, 59, 1),
borderRadius: BorderRadius.circular(12.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
value,
style: TextStyle(
color: Colors.white,
fontSize: 24.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 4.h),
Text(
label,
style: TextStyle(
color: const Color.fromRGBO(148, 163, 184, 1),
fontSize: 12.sp,
),
),
SizedBox(height: 4.h),
if (change != null)
Row(
children: [
Icon(
isDown! ? Icons.arrow_drop_down : Icons.arrow_drop_up,
color: isDown ? const Color.fromRGBO(34, 197, 94, 1) : const Color.fromRGBO(239, 68, 68, 1),
size: 16.sp,
),
Text(
change,
style: TextStyle(
color: isDown ? const Color.fromRGBO(34, 197, 94, 1) : const Color.fromRGBO(239, 68, 68, 1),
fontSize: 12.sp,
),
),
],
)
else
SizedBox(height: 20.h),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:smart_hotel_app/views/report/energy/controller.dart';
class HourlyChartBlock extends StatelessWidget {
const HourlyChartBlock({super.key});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: const Color.fromRGBO(30, 41, 59, 1),
borderRadius: BorderRadius.circular(12.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'今日逐时用电',
style: TextStyle(
color: Colors.white,
fontSize: 16.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 16.h),
SizedBox(
height: 200.h,
child: BarChart(
BarChartData(
alignment: BarChartAlignment.spaceBetween,
maxY: 200,
barTouchData: BarTouchData(enabled: false),
titlesData: FlTitlesData(
show: true,
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
if (value % 4 == 0) {
return Text(
'${value.toInt()}',
style: TextStyle(
color: const Color.fromRGBO(148, 163, 184, 1),
fontSize: 10.sp,
),
);
}
return const SizedBox.shrink();
},
reservedSize: 20,
),
),
leftTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
),
borderData: FlBorderData(show: false),
gridData: const FlGridData(show: false),
barGroups: _buildBarGroups(),
),
),
),
],
),
);
}
List<BarChartGroupData> _buildBarGroups() {
return ReportEnergyController.hourlyData.asMap().entries.map((entry) {
final index = entry.key;
final value = entry.value;
return BarChartGroupData(
x: index,
barRods: [
BarChartRodData(
toY: value,
color: index >= 8 && index <= 12
? const Color.fromRGBO(59, 130, 246, 1)
: const Color.fromRGBO(37, 99, 235, 1),
width: 10.w,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4.r),
topRight: Radius.circular(4.r),
),
),
],
);
}).toList();
}
}
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:smart_hotel_app/views/report/energy/controller.dart';
class ZoneChartBlock extends StatelessWidget {
const ZoneChartBlock({super.key});
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: const Color.fromRGBO(30, 41, 59, 1),
borderRadius: BorderRadius.circular(12.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'分区用电占比',
style: TextStyle(
color: Colors.white,
fontSize: 16.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 16.h),
...ReportEnergyController.zoneData.asMap().entries.map((entry) {
final index = entry.key;
final data = entry.value;
return Padding(
padding: EdgeInsets.only(bottom: index < ReportEnergyController.zoneData.length - 1 ? 16.h : 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
data.name,
style: TextStyle(
color: Colors.white,
fontSize: 14.sp,
),
),
Text(
'${data.percentage.toInt()}% (${data.energy.toInt()} kWh)',
style: TextStyle(
color: const Color.fromRGBO(148, 163, 184, 1),
fontSize: 14.sp,
),
),
],
),
SizedBox(height: 8.h),
Stack(
children: [
Container(
height: 12.h,
decoration: BoxDecoration(
color: const Color.fromRGBO(51, 65, 85, 1),
borderRadius: BorderRadius.circular(6.r),
),
),
FractionallySizedBox(
widthFactor: data.percentage / 100,
child: Container(
height: 12.h,
decoration: BoxDecoration(
color: index == 0
? const Color.fromRGBO(59, 130, 246, 1)
: const Color.fromRGBO(71, 85, 105, 1),
borderRadius: BorderRadius.circular(6.r),
),
),
),
],
),
],
),
);
}).toList(),
],
),
);
}
}
class ReportEnergyController {
static const double todayEnergy = 1284;
static const double todayEnergyChange = -8;
static const double monthEnergy = 38420;
static const double monthEnergyChange = -5;
static const double monthBill = 6982;
static const List<double> hourlyData = [
45, 38, 32, 28, 25, 30, 42, 78, 112, 145, 168, 175,
162, 148, 132, 115, 98, 82, 70, 58, 48, 42, 38, 35
];
static const List<ZoneData> zoneData = [
ZoneData(name: '客房区域', percentage: 68, energy: 873),
ZoneData(name: '公共区域', percentage: 18, energy: 231),
ZoneData(name: '餐饮区域', percentage: 10, energy: 128),
ZoneData(name: '其他', percentage: 4, energy: 52),
];
}
class ZoneData {
final String name;
final double percentage;
final double energy;
const ZoneData({
required this.name,
required this.percentage,
required this.energy,
});
}
\ 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/report/energy/controller.dart';
import 'package:smart_hotel_app/views/report/energy/child/energy_stats_card_block.dart';
import 'package:smart_hotel_app/views/report/energy/child/hourly_chart_block.dart';
import 'package:smart_hotel_app/views/report/energy/child/zone_chart_block.dart';
@RoutePage()
class ReportEnergyDetailView extends StatefulWidget {
const ReportEnergyDetailView({super.key});
@override
State<ReportEnergyDetailView> createState() => _ReportEnergyDetailViewState();
}
class _ReportEnergyDetailViewState extends State<ReportEnergyDetailView> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(15, 23, 42, 1),
appBar: AppBar(
backgroundColor: Color.fromRGBO(15, 23, 42, 1),
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
context.popRoute();
},
),
title: Text(
'能耗分析',
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.bold,
),
),
centerTitle: true,
),
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 10.h),
const EnergyStatsCardBlock(),
SizedBox(height: 20.h),
const HourlyChartBlock(),
SizedBox(height: 20.h),
const ZoneChartBlock(),
SizedBox(height: 20.h),
],
),
),
);
}
}
\ No newline at end of file
......@@ -38,6 +38,7 @@ class _ReportMetricsBlockState extends State<ReportMetricsBlock> {
changeColor: Color.fromRGBO(34, 197, 94, 1),
progress: powerUsage['progress'] as double,
progressColor: Color.fromRGBO(59, 130, 246, 1),
onTap: () => _controller.navigateToEnergyDetail(),
),
),
SizedBox(width: 16.w),
......@@ -65,84 +66,88 @@ class _ReportMetricsBlockState extends State<ReportMetricsBlock> {
required Color changeColor,
required double progress,
required Color progressColor,
VoidCallback? onTap,
}) {
return Container(
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,
return GestureDetector(
onTap: onTap,
child: Container(
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,
),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey,
),
),
),
Text(
changeText,
style: TextStyle(
fontSize: 14.sp,
color: changeColor,
fontWeight: FontWeight.w500,
),
),
],
),
SizedBox(height: 16.h),
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
value.toString().replaceAllMapped(
RegExp(r'(\d)(?=(\d{3})+(?!\d))'),
(Match match) => '${match[1]},',
Text(
changeText,
style: TextStyle(
fontSize: 14.sp,
color: changeColor,
fontWeight: FontWeight.w500,
),
),
style: TextStyle(
fontSize: 36.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
],
),
SizedBox(height: 16.h),
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
value.toString().replaceAllMapped(
RegExp(r'(\d)(?=(\d{3})+(?!\d))'),
(Match match) => '${match[1]},',
),
style: TextStyle(
fontSize: 36.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
SizedBox(width: 4.w),
Text(
unit,
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey,
SizedBox(width: 4.w),
Text(
unit,
style: TextStyle(
fontSize: 16.sp,
color: Colors.grey,
),
),
),
],
),
SizedBox(height: 16.h),
Container(
height: 8.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Color.fromRGBO(51, 65, 85, 1),
],
),
child: FractionallySizedBox(
widthFactor: progress,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: progressColor,
SizedBox(height: 16.h),
Container(
height: 8.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: Color.fromRGBO(51, 65, 85, 1),
),
child: FractionallySizedBox(
widthFactor: progress,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.r),
color: progressColor,
),
),
),
),
),
],
],
),
),
);
}
......
......@@ -24,108 +24,111 @@ class _RoomStatusDistributionState extends State<RoomStatusDistribution> {
final statuses = distributionData['statuses'] as List<Map<String, dynamic>>;
final totalRooms = distributionData['totalRooms'] as int;
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,
return GestureDetector(
onTap: () => _controller.navigateToRoomDetail(),
child: 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,
),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
distributionData['title'] as String,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
distributionData['title'] as String,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
Text(
'共 $totalRooms 间',
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
Text(
'共 $totalRooms 间',
style: TextStyle(
fontSize: 14.sp,
color: Colors.grey,
),
),
),
],
),
SizedBox(height: 20.h),
...statuses.map((status) {
final count = status['count'] as int;
final color = status['color'] as Color;
final percentage = (count / totalRooms * 100).toStringAsFixed(0);
return Padding(
padding: EdgeInsets.only(bottom: 16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(6.r),
],
),
SizedBox(height: 20.h),
...statuses.map((status) {
final count = status['count'] as int;
final color = status['color'] as Color;
final percentage = (count / totalRooms * 100).toStringAsFixed(0);
return Padding(
padding: EdgeInsets.only(bottom: 16.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 12.w,
height: 12.w,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(6.r),
),
),
),
SizedBox(width: 10.w),
Expanded(
child: Text(
status['name'] as String,
SizedBox(width: 10.w),
Expanded(
child: Text(
status['name'] as String,
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
),
),
),
Text(
'$count间 ($percentage%)',
style: TextStyle(
fontSize: 16.sp,
color: Colors.white,
color: color,
fontWeight: FontWeight.bold,
),
),
),
Text(
'$count间 ($percentage%)',
style: TextStyle(
fontSize: 16.sp,
color: color,
fontWeight: FontWeight.bold,
),
),
],
),
SizedBox(height: 8.h),
Container(
width: double.infinity,
height: 12.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: Color.fromRGBO(51, 65, 85, 1),
],
),
child: Align(
alignment: Alignment.centerLeft,
child: FractionallySizedBox(
widthFactor: count / totalRooms,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: color,
SizedBox(height: 8.h),
Container(
width: double.infinity,
height: 12.h,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: Color.fromRGBO(51, 65, 85, 1),
),
child: Align(
alignment: Alignment.centerLeft,
child: FractionallySizedBox(
widthFactor: count / totalRooms,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.r),
color: color,
),
),
),
),
),
),
],
),
);
}).toList(),
],
],
),
);
}).toList(),
],
),
),
);
}
......
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:smart_hotel_app/routes/app_router.gr.dart';
class ReportIndexController {
final BuildContext context;
......@@ -86,4 +88,12 @@ class ReportIndexController {
],
};
}
void navigateToEnergyDetail() {
context.pushRoute(const ReportEnergyDetailRoute());
}
void navigateToRoomDetail() {
context.pushRoute(const ReportRoomDetailRoute());
}
}
\ No newline at end of file
class ReportRoomController {
}
\ 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/report/room/controller.dart';
@RoutePage()
class ReportRoomDetailView extends StatefulWidget {
const ReportRoomDetailView({super.key});
@override
State<ReportRoomDetailView> createState() => _ReportRoomDetailViewState();
}
class _ReportRoomDetailViewState extends State<ReportRoomDetailView> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(15, 23, 42, 1),
appBar: AppBar(
backgroundColor: Color.fromRGBO(15, 23, 42, 1),
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
context.popRoute();
},
),
title: Text(
'能耗分析',
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.bold,
),
),
centerTitle: true,
),
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 10.h),
],
),
),
);
}
}
\ No newline at end of file
......@@ -72,6 +72,8 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
- lib/assets/
- lib/assets/login/
- lib/assets/tab/
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
......
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