Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
smart_hotel_app
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张宏
smart_hotel_app
Commits
1244f87e
Commit
1244f87e
authored
Jun 17, 2026
by
huqu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix bugs
parent
5a154d67
Show whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
798 additions
and
398 deletions
+798
-398
AndroidManifest.xml
android/app/src/main/AndroidManifest.xml
+4
-0
launch_background.xml
android/app/src/main/res/drawable-v21/launch_background.xml
+1
-1
dashboard_bo.dart
lib/models/bo/dashboard_bo.dart
+6
-2
device_list_bo.dart
lib/models/bo/device_list_bo.dart
+4
-4
inspection_device_bo.dart
lib/models/bo/inspection_device_bo.dart
+4
-0
device_list_repository.dart
lib/repositories/device_list_repository.dart
+2
-2
device_list_service.dart
lib/services/device_list_service.dart
+1
-1
temperature_char_block.dart
lib/views/home/abnormal/widget/temperature_char_block.dart
+19
-16
device_cubit.dart
lib/views/home/device/cubit/device_cubit.dart
+4
-0
device_state.dart
lib/views/home/device/cubit/device_state.dart
+3
-0
device_parms_block.dart
lib/views/home/device/widget/device_parms_block.dart
+36
-10
power_char_block.dart
lib/views/home/device/widget/power_char_block.dart
+57
-20
inspection_state.dart
lib/views/home/inspection/cubit/inspection_state.dart
+2
-2
inspection_detail_view.dart
lib/views/home/inspection/inspection_detail_view.dart
+18
-1
device_list_item.dart
lib/views/home/inspection/widget/device_list_item.dart
+14
-22
filter_panel.dart
lib/views/home/inspection/widget/filter_panel.dart
+59
-7
inspection_device_cubit.dart
...home/inspection_device/cubit/inspection_device_cubit.dart
+2
-2
inspection_device_view.dart
lib/views/home/inspection_device/inspection_device_view.dart
+2
-2
device_overview_card.dart
...s/home/inspection_device/widget/device_overview_card.dart
+2
-2
inspection_topology_cubit.dart
.../inspection_topology/cubit/inspection_topology_cubit.dart
+16
-4
inspection_topology_view.dart
...ws/home/inspection_topology/inspection_topology_view.dart
+8
-2
network_topology_widget.dart
...e/inspection_topology/widget/network_topology_widget.dart
+108
-10
status_legend_widget.dart
...home/inspection_topology/widget/status_legend_widget.dart
+4
-4
device_list_cubit.dart
lib/views/report/device/cubit/device_list_cubit.dart
+2
-1
device_list_state.dart
lib/views/report/device/cubit/device_list_state.dart
+9
-6
device_list_view.dart
lib/views/report/device/device_list_view.dart
+5
-5
device_card.dart
lib/views/report/device/widget/device_card.dart
+48
-35
device_filter_tab.dart
lib/views/report/device/widget/device_filter_tab.dart
+19
-8
energy_cubit.dart
lib/views/report/energy/cubit/energy_cubit.dart
+5
-1
energy_state.dart
lib/views/report/energy/cubit/energy_state.dart
+5
-0
energy_detail_view.dart
lib/views/report/energy/energy_detail_view.dart
+1
-0
energy_stats_card_block.dart
lib/views/report/energy/widget/energy_stats_card_block.dart
+14
-6
hourly_chart_block.dart
lib/views/report/energy/widget/hourly_chart_block.dart
+55
-54
zone_chart_block.dart
lib/views/report/energy/widget/zone_chart_block.dart
+2
-2
report_index_cubit.dart
lib/views/report/index/cubit/report_index_cubit.dart
+26
-24
device_online_rate.dart
lib/views/report/index/widget/device_online_rate.dart
+6
-6
quick_actions_block.dart
lib/views/report/index/widget/quick_actions_block.dart
+1
-1
report_header_block.dart
lib/views/report/index/widget/report_header_block.dart
+1
-1
report_metrics_block.dart
lib/views/report/index/widget/report_metrics_block.dart
+22
-19
room_status_distribution.dart
lib/views/report/index/widget/room_status_distribution.dart
+6
-5
weekly_power_chart.dart
lib/views/report/index/widget/weekly_power_chart.dart
+96
-36
floor_selector.dart
lib/views/report/room/widget/floor_selector.dart
+8
-11
room_detail_card.dart
lib/views/report/room/widget/room_detail_card.dart
+30
-18
room_grid.dart
lib/views/report/room/widget/room_grid.dart
+11
-4
status_stats.dart
lib/views/report/room/widget/status_stats.dart
+16
-7
rule_management_cubit.dart
lib/views/report/rule/cubit/rule_management_cubit.dart
+16
-16
rule_management_view.dart
lib/views/report/rule/rule_management_view.dart
+2
-1
rule_card.dart
lib/views/report/rule/widget/rule_card.dart
+16
-17
No files found.
android/app/src/main/AndroidManifest.xml
View file @
1244f87e
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.ACCESS_NETWORK_STATE"
/>
<application
<application
android:label=
"@string/app_name"
android:label=
"@string/app_name"
android:name=
"${applicationName}"
android:name=
"${applicationName}"
...
...
android/app/src/main/res/drawable-v21/launch_background.xml
View file @
1244f87e
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<!-- Modify this file to customize your launch splash screen -->
<layer-list
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<layer-list
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item
android:drawable=
"
?android:colorBackground
"
/>
<item
android:drawable=
"
@android:color/white
"
/>
<item>
<item>
<bitmap
<bitmap
...
...
lib/models/bo/dashboard_bo.dart
View file @
1244f87e
...
@@ -52,11 +52,15 @@ class ElectricityTodayBO extends Equatable {
...
@@ -52,11 +52,15 @@ class ElectricityTodayBO extends Equatable {
class
AlertPendingBO
extends
Equatable
{
class
AlertPendingBO
extends
Equatable
{
final
int
count
;
final
int
count
;
final
int
todayTotal
;
const
AlertPendingBO
({
required
this
.
count
});
const
AlertPendingBO
({
required
this
.
count
,
required
this
.
todayTotal
});
factory
AlertPendingBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
factory
AlertPendingBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
return
AlertPendingBO
(
count:
_parseInt
(
json
[
'count'
]));
return
AlertPendingBO
(
count:
_parseInt
(
json
[
'count'
]),
todayTotal:
_parseInt
(
json
[
'todayTotal'
]),
);
}
}
@override
@override
...
...
lib/models/bo/device_list_bo.dart
View file @
1244f87e
...
@@ -136,13 +136,13 @@ class DeviceListTabCountBO extends Equatable {
...
@@ -136,13 +136,13 @@ class DeviceListTabCountBO extends Equatable {
final
int
all
;
final
int
all
;
final
int
airSwitch
;
final
int
airSwitch
;
final
int
guestControl
;
final
int
guestControl
;
final
int
network
;
final
int
gateway
;
const
DeviceListTabCountBO
({
const
DeviceListTabCountBO
({
required
this
.
all
,
required
this
.
all
,
required
this
.
airSwitch
,
required
this
.
airSwitch
,
required
this
.
guestControl
,
required
this
.
guestControl
,
required
this
.
network
,
required
this
.
gateway
,
});
});
factory
DeviceListTabCountBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
factory
DeviceListTabCountBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
...
@@ -150,12 +150,12 @@ class DeviceListTabCountBO extends Equatable {
...
@@ -150,12 +150,12 @@ class DeviceListTabCountBO extends Equatable {
all:
_parseInt
(
json
[
'all'
]),
all:
_parseInt
(
json
[
'all'
]),
airSwitch:
_parseInt
(
json
[
'airSwitch'
]),
airSwitch:
_parseInt
(
json
[
'airSwitch'
]),
guestControl:
_parseInt
(
json
[
'guestControl'
]),
guestControl:
_parseInt
(
json
[
'guestControl'
]),
network:
_parseInt
(
json
[
'network
'
]),
gateway:
_parseInt
(
json
[
'gateway
'
]),
);
);
}
}
@override
@override
List
<
Object
?>
get
props
=>
[
all
,
airSwitch
,
guestControl
,
network
];
List
<
Object
?>
get
props
=>
[
all
,
airSwitch
,
guestControl
,
gateway
];
}
}
class
DeviceListBO
extends
Equatable
{
class
DeviceListBO
extends
Equatable
{
...
...
lib/models/bo/inspection_device_bo.dart
View file @
1244f87e
...
@@ -13,6 +13,7 @@ class InspectionDeviceBO extends Equatable {
...
@@ -13,6 +13,7 @@ class InspectionDeviceBO extends Equatable {
final
String
onlineStatus
;
final
String
onlineStatus
;
final
String
powerStatus
;
final
String
powerStatus
;
final
int
roomId
;
final
int
roomId
;
final
String
deviceCategory
;
const
InspectionDeviceBO
({
const
InspectionDeviceBO
({
required
this
.
deviceId
,
required
this
.
deviceId
,
...
@@ -27,6 +28,7 @@ class InspectionDeviceBO extends Equatable {
...
@@ -27,6 +28,7 @@ class InspectionDeviceBO extends Equatable {
required
this
.
onlineStatus
,
required
this
.
onlineStatus
,
required
this
.
powerStatus
,
required
this
.
powerStatus
,
required
this
.
roomId
,
required
this
.
roomId
,
required
this
.
deviceCategory
,
});
});
factory
InspectionDeviceBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
factory
InspectionDeviceBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
...
@@ -43,6 +45,7 @@ class InspectionDeviceBO extends Equatable {
...
@@ -43,6 +45,7 @@ class InspectionDeviceBO extends Equatable {
onlineStatus:
json
[
'onlineStatus'
]
as
String
?
??
''
,
onlineStatus:
json
[
'onlineStatus'
]
as
String
?
??
''
,
powerStatus:
json
[
'powerStatus'
]
as
String
?
??
''
,
powerStatus:
json
[
'powerStatus'
]
as
String
?
??
''
,
roomId:
int
.
tryParse
(
json
[
'roomId'
]?.
toString
()
??
''
)
??
0
,
roomId:
int
.
tryParse
(
json
[
'roomId'
]?.
toString
()
??
''
)
??
0
,
deviceCategory:
json
[
'deviceCategory'
]
as
String
?
??
''
,
);
);
}
}
...
@@ -60,6 +63,7 @@ class InspectionDeviceBO extends Equatable {
...
@@ -60,6 +63,7 @@ class InspectionDeviceBO extends Equatable {
onlineStatus
,
onlineStatus
,
powerStatus
,
powerStatus
,
roomId
,
roomId
,
deviceCategory
,
];
];
}
}
...
...
lib/repositories/device_list_repository.dart
View file @
1244f87e
...
@@ -8,14 +8,14 @@ class DeviceListRepository {
...
@@ -8,14 +8,14 @@ class DeviceListRepository {
Future
<
ResponseModel
<
DeviceListBO
>>
getList
({
Future
<
ResponseModel
<
DeviceListBO
>>
getList
({
required
int
pageSize
,
required
int
pageSize
,
required
int
pageNum
,
required
int
pageNum
,
int
?
deviceTypeId
,
String
?
deviceTypeId
,
})
{
})
{
final
params
=
<
String
,
dynamic
>{
final
params
=
<
String
,
dynamic
>{
'pageSize'
:
pageSize
,
'pageSize'
:
pageSize
,
'pageNum'
:
pageNum
,
'pageNum'
:
pageNum
,
};
};
if
(
deviceTypeId
!=
null
)
{
if
(
deviceTypeId
!=
null
)
{
params
[
'
deviceTypeId
'
]
=
deviceTypeId
;
params
[
'
accessType
'
]
=
deviceTypeId
;
}
}
return
DioRequest
.
instance
.
get
<
DeviceListBO
>(
return
DioRequest
.
instance
.
get
<
DeviceListBO
>(
...
...
lib/services/device_list_service.dart
View file @
1244f87e
...
@@ -10,7 +10,7 @@ class DeviceListService {
...
@@ -10,7 +10,7 @@ class DeviceListService {
Future
<
DeviceListBO
>
getList
({
Future
<
DeviceListBO
>
getList
({
required
int
pageSize
,
required
int
pageSize
,
required
int
pageNum
,
required
int
pageNum
,
int
?
deviceTypeId
,
String
?
deviceTypeId
,
})
async
{
})
async
{
final
result
=
await
_repository
.
getList
(
final
result
=
await
_repository
.
getList
(
pageSize:
pageSize
,
pageSize:
pageSize
,
...
...
lib/views/home/abnormal/widget/temperature_char_block.dart
View file @
1244f87e
...
@@ -12,22 +12,27 @@ class TemperatureCharBlock extends StatelessWidget {
...
@@ -12,22 +12,27 @@ class TemperatureCharBlock extends StatelessWidget {
double
get
_maxX
=>
alarmInfo
.
temperatureSpots
.
length
>
1
double
get
_maxX
=>
alarmInfo
.
temperatureSpots
.
length
>
1
?
(
alarmInfo
.
temperatureSpots
.
length
-
1
).
toDouble
()
?
(
alarmInfo
.
temperatureSpots
.
length
-
1
).
toDouble
()
:
24
;
:
1
;
double
get
_minY
=>
alarmInfo
.
yaxisMin
;
double
get
_minY
=>
alarmInfo
.
yaxisMin
;
double
get
_maxY
=>
alarmInfo
.
yaxisMax
>
alarmInfo
.
yaxisMin
double
get
_maxY
{
final
raw
=
alarmInfo
.
yaxisMax
>
alarmInfo
.
yaxisMin
?
alarmInfo
.
yaxisMax
?
alarmInfo
.
yaxisMax
:
alarmInfo
.
yaxisMin
+
100
;
:
alarmInfo
.
yaxisMin
+
100
;
// 留 10% 余量,防止顶部标签贴边
double
get
_horizontalInterval
{
return
raw
*
1.1
;
final
interval
=
(
_maxY
-
_minY
)
/
5
;
return
interval
>
0
?
interval
:
20
;
}
}
double
get
_bottomInterval
=>
alarmInfo
.
temperatureSpots
.
length
>
1
double
get
_horizontalInterval
=>
_maxY
/
5
;
?
(
alarmInfo
.
temperatureSpots
.
length
-
1
)
/
4
:
6
;
double
get
_bottomInterval
{
final
len
=
alarmInfo
.
temperatureSpots
.
length
;
if
(
len
<=
1
)
return
1
;
if
(
len
<=
6
)
return
1
;
if
(
len
<=
12
)
return
2
;
return
(
len
-
1
)
/
4
;
}
String
_formatBottomTitle
(
double
value
)
{
String
_formatBottomTitle
(
double
value
)
{
final
index
=
value
.
toInt
();
final
index
=
value
.
toInt
();
...
@@ -46,7 +51,7 @@ class TemperatureCharBlock extends StatelessWidget {
...
@@ -46,7 +51,7 @@ class TemperatureCharBlock extends StatelessWidget {
return
Container
(
return
Container
(
width:
double
.
infinity
,
width:
double
.
infinity
,
margin:
EdgeInsets
.
only
(
top:
10
.
h
),
margin:
EdgeInsets
.
only
(
top:
10
.
h
),
padding:
EdgeInsets
.
all
(
25
.
w
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
50
.
w
,
vertical:
25
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
25
.
r
),
borderRadius:
BorderRadius
.
circular
(
25
.
r
),
color:
Colors
.
white
,
color:
Colors
.
white
,
...
@@ -58,9 +63,7 @@ class TemperatureCharBlock extends StatelessWidget {
...
@@ -58,9 +63,7 @@ class TemperatureCharBlock extends StatelessWidget {
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
children:
[
Text
(
Text
(
alarmInfo
.
chartTitle
.
isEmpty
alarmInfo
.
chartTitle
,
?
'24小时温度趋势'
:
alarmInfo
.
chartTitle
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
...
@@ -75,7 +78,7 @@ class TemperatureCharBlock extends StatelessWidget {
...
@@ -75,7 +78,7 @@ class TemperatureCharBlock extends StatelessWidget {
),
),
],
],
),
),
SizedBox
(
height:
2
0
.
h
),
SizedBox
(
height:
3
0
.
h
),
SizedBox
(
SizedBox
(
height:
250
.
h
,
height:
250
.
h
,
child:
LineChart
(
child:
LineChart
(
...
@@ -109,7 +112,7 @@ class TemperatureCharBlock extends StatelessWidget {
...
@@ -109,7 +112,7 @@ class TemperatureCharBlock extends StatelessWidget {
_formatBottomTitle
(
value
),
_formatBottomTitle
(
value
),
style:
TextStyle
(
style:
TextStyle
(
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
fontSize:
1
4
.
sp
,
fontSize:
2
4
.
sp
,
),
),
);
);
},
},
...
@@ -125,7 +128,7 @@ class TemperatureCharBlock extends StatelessWidget {
...
@@ -125,7 +128,7 @@ class TemperatureCharBlock extends StatelessWidget {
'
${value.toInt()}
'
,
'
${value.toInt()}
'
,
style:
TextStyle
(
style:
TextStyle
(
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
fontSize:
1
4
.
sp
,
fontSize:
2
4
.
sp
,
),
),
);
);
},
},
...
...
lib/views/home/device/cubit/device_cubit.dart
View file @
1244f87e
...
@@ -42,6 +42,9 @@ class DeviceCubit extends Cubit<DeviceState> {
...
@@ -42,6 +42,9 @@ class DeviceCubit extends Cubit<DeviceState> {
final
tempData
=
detail
.
trendChart
.
dataPoints
final
tempData
=
detail
.
trendChart
.
dataPoints
.
map
((
p
)
=>
p
.
temperature
.
toInt
())
.
map
((
p
)
=>
p
.
temperature
.
toInt
())
.
toList
();
.
toList
();
final
timeLabels
=
detail
.
trendChart
.
dataPoints
.
map
((
p
)
=>
p
.
time
)
.
toList
();
return
DeviceInfo
(
return
DeviceInfo
(
deviceName:
basic
.
deviceName
,
deviceName:
basic
.
deviceName
,
...
@@ -55,6 +58,7 @@ class DeviceCubit extends Cubit<DeviceState> {
...
@@ -55,6 +58,7 @@ class DeviceCubit extends Cubit<DeviceState> {
temperature:
params
.
deviceTemperature
,
temperature:
params
.
deviceTemperature
,
powerData:
powerData
,
powerData:
powerData
,
tempData:
tempData
,
tempData:
tempData
,
timeLabels:
timeLabels
,
);
);
}
}
...
...
lib/views/home/device/cubit/device_state.dart
View file @
1244f87e
...
@@ -11,6 +11,7 @@ class DeviceInfo extends Equatable {
...
@@ -11,6 +11,7 @@ class DeviceInfo extends Equatable {
final
String
temperature
;
final
String
temperature
;
final
List
<
int
>
powerData
;
final
List
<
int
>
powerData
;
final
List
<
int
>
tempData
;
final
List
<
int
>
tempData
;
final
List
<
String
>
timeLabels
;
const
DeviceInfo
({
const
DeviceInfo
({
required
this
.
deviceName
,
required
this
.
deviceName
,
...
@@ -23,6 +24,7 @@ class DeviceInfo extends Equatable {
...
@@ -23,6 +24,7 @@ class DeviceInfo extends Equatable {
required
this
.
temperature
,
required
this
.
temperature
,
required
this
.
powerData
,
required
this
.
powerData
,
required
this
.
tempData
,
required
this
.
tempData
,
required
this
.
timeLabels
,
});
});
@override
@override
...
@@ -37,6 +39,7 @@ class DeviceInfo extends Equatable {
...
@@ -37,6 +39,7 @@ class DeviceInfo extends Equatable {
temperature
,
temperature
,
powerData
,
powerData
,
tempData
,
tempData
,
timeLabels
,
];
];
}
}
...
...
lib/views/home/device/widget/device_parms_block.dart
View file @
1244f87e
...
@@ -32,11 +32,11 @@ class DeviceParmsBlock extends StatelessWidget {
...
@@ -32,11 +32,11 @@ class DeviceParmsBlock extends StatelessWidget {
Row
(
Row
(
children:
[
children:
[
Expanded
(
Expanded
(
child:
_buildParamCard
(
deviceInfo
.
voltage
,
'电压'
),
child:
_buildParamCard
(
deviceInfo
.
voltage
,
'电压'
,
'V'
),
),
),
SizedBox
(
width:
15
.
w
),
SizedBox
(
width:
15
.
w
),
Expanded
(
Expanded
(
child:
_buildParamCard
(
deviceInfo
.
current
,
'电流'
),
child:
_buildParamCard
(
deviceInfo
.
current
,
'电流'
,
'A'
),
),
),
],
],
),
),
...
@@ -44,11 +44,11 @@ class DeviceParmsBlock extends StatelessWidget {
...
@@ -44,11 +44,11 @@ class DeviceParmsBlock extends StatelessWidget {
Row
(
Row
(
children:
[
children:
[
Expanded
(
Expanded
(
child:
_buildParamCard
(
deviceInfo
.
power
,
'有
功功率
'
,
isGreen:
true
),
child:
_buildParamCard
(
deviceInfo
.
power
,
'有
公功率'
,
'W
'
,
isGreen:
true
),
),
),
SizedBox
(
width:
15
.
w
),
SizedBox
(
width:
15
.
w
),
Expanded
(
Expanded
(
child:
_buildParamCard
(
deviceInfo
.
temperature
,
'设备温度'
),
child:
_buildParamCard
(
deviceInfo
.
temperature
,
'设备温度'
,
'°C'
),
),
),
],
],
),
),
...
@@ -57,30 +57,56 @@ class DeviceParmsBlock extends StatelessWidget {
...
@@ -57,30 +57,56 @@ class DeviceParmsBlock extends StatelessWidget {
);
);
}
}
Widget
_buildParamCard
(
String
value
,
String
label
,
{
bool
isGreen
=
false
})
{
String
_formatValue
(
String
raw
)
{
final
d
=
double
.
tryParse
(
raw
);
if
(
d
==
null
)
return
raw
;
// 去掉末尾多余的 0,整数不显示小数点
final
formatted
=
d
.
toStringAsFixed
(
2
);
final
parts
=
formatted
.
split
(
'.'
);
if
(
parts
.
length
==
2
&&
parts
[
1
]
==
'00'
)
return
parts
[
0
];
return
formatted
.
replaceAll
(
RegExp
(
r'0+$'
),
''
).
replaceAll
(
RegExp
(
r'\.$'
),
''
);
}
Widget
_buildParamCard
(
String
value
,
String
label
,
String
unit
,
{
bool
isGreen
=
false
})
{
return
Container
(
return
Container
(
padding:
EdgeInsets
.
all
(
25
.
w
),
padding:
EdgeInsets
.
all
(
25
.
w
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
25
.
r
),
borderRadius:
BorderRadius
.
circular
(
25
.
r
),
color:
Color
.
fromRGBO
(
229
,
241
,
255
,
1
),
color:
const
Color
.
fromRGBO
(
229
,
241
,
255
,
1
),
),
),
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Text
(
Text
.
rich
(
value
,
TextSpan
(
children:
[
TextSpan
(
text:
_formatValue
(
value
),
style:
TextStyle
(
fontSize:
40
.
sp
,
color:
isGreen
?
const
Color
.
fromRGBO
(
20
,
184
,
166
,
1
)
:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
),
fontWeight:
FontWeight
.
bold
,
),
),
TextSpan
(
text:
unit
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
40
.
sp
,
fontSize:
40
.
sp
,
color:
isGreen
?
Color
.
fromRGBO
(
20
,
184
,
166
,
1
)
:
Color
.
fromRGBO
(
73
,
149
,
234
,
1
),
color:
isGreen
?
const
Color
.
fromRGBO
(
20
,
184
,
166
,
1
)
:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
),
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
],
),
),
SizedBox
(
height:
8
.
h
),
SizedBox
(
height:
8
.
h
),
Text
(
Text
(
label
,
label
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
color:
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
),
),
),
),
],
],
...
...
lib/views/home/device/widget/power_char_block.dart
View file @
1244f87e
import
'dart:math'
;
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'
;
...
@@ -35,7 +36,7 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -35,7 +36,7 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
'24小时功率趋势'
,
'24小时功率趋势'
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
color:
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
),
),
),
),
Container
(
Container
(
...
@@ -43,7 +44,7 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -43,7 +44,7 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
color:
Colors
.
transparent
,
color:
Colors
.
transparent
,
border:
Border
.
all
(
border:
Border
.
all
(
color:
Color
.
fromRGBO
(
73
,
149
,
234
,
0.5
),
color:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
0.5
),
width:
1.5
.
w
,
width:
1.5
.
w
,
),
),
),
),
...
@@ -57,12 +58,12 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -57,12 +58,12 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
],
],
),
),
SizedBox
(
height:
20
.
h
),
SizedBox
(
height:
20
.
h
),
Container
(
SizedBox
(
height:
250
.
h
,
height:
250
.
h
,
child:
BarChart
(
child:
BarChart
(
BarChartData
(
BarChartData
(
alignment:
BarChartAlignment
.
spaceBetween
,
alignment:
BarChartAlignment
.
spaceBetween
,
maxY:
100
,
maxY:
_calcMaxY
(
_selectedIndex
)
,
minY:
0
,
minY:
0
,
groupsSpace:
10
,
groupsSpace:
10
,
barTouchData:
BarTouchData
(
enabled:
false
),
barTouchData:
BarTouchData
(
enabled:
false
),
...
@@ -70,9 +71,9 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -70,9 +71,9 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
show:
true
,
show:
true
,
drawHorizontalLine:
true
,
drawHorizontalLine:
true
,
drawVerticalLine:
false
,
drawVerticalLine:
false
,
horizontalInterval:
20
,
horizontalInterval:
_calcInterval
(
_selectedIndex
)
,
getDrawingHorizontalLine:
(
value
)
{
getDrawingHorizontalLine:
(
value
)
{
return
FlLine
(
return
const
FlLine
(
color:
Color
.
fromRGBO
(
209
,
213
,
219
,
1
),
color:
Color
.
fromRGBO
(
209
,
213
,
219
,
1
),
strokeWidth:
1.5
,
strokeWidth:
1.5
,
dashArray:
[
5
,
5
],
dashArray:
[
5
,
5
],
...
@@ -81,18 +82,18 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -81,18 +82,18 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
),
),
titlesData:
FlTitlesData
(
titlesData:
FlTitlesData
(
show:
true
,
show:
true
,
rightTitles:
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
)),
rightTitles:
const
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
)),
topTitles:
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
)),
topTitles:
const
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
)),
leftTitles:
AxisTitles
(
leftTitles:
AxisTitles
(
sideTitles:
SideTitles
(
sideTitles:
SideTitles
(
showTitles:
true
,
showTitles:
true
,
interval:
20
,
interval:
_calcInterval
(
_selectedIndex
)
,
getTitlesWidget:
(
value
,
meta
)
{
getTitlesWidget:
(
value
,
meta
)
{
return
Text
(
return
Text
(
'
${value.toInt()}
'
,
'
${value.toInt()}
'
,
style:
TextStyle
(
style:
TextStyle
(
color:
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
fontSize:
1
4
.
sp
,
fontSize:
2
4
.
sp
,
),
),
);
);
},
},
...
@@ -102,13 +103,19 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -102,13 +103,19 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
bottomTitles:
AxisTitles
(
bottomTitles:
AxisTitles
(
sideTitles:
SideTitles
(
sideTitles:
SideTitles
(
showTitles:
true
,
showTitles:
true
,
interval:
3
,
interval:
_calcBottomInterval
()
,
getTitlesWidget:
(
value
,
meta
)
{
getTitlesWidget:
(
value
,
meta
)
{
return
Text
(
final
i
=
value
.
toInt
();
'11:04'
,
final
labels
=
widget
.
deviceInfo
.
timeLabels
;
final
label
=
i
>=
0
&&
i
<
labels
.
length
?
labels
[
i
]
:
''
;
return
Padding
(
padding:
EdgeInsets
.
only
(
top:
8
.
h
),
child:
Text
(
label
,
style:
TextStyle
(
style:
TextStyle
(
color:
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
fontSize:
14
.
sp
,
fontSize:
20
.
sp
,
),
),
),
);
);
},
},
...
@@ -138,13 +145,14 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -138,13 +145,14 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
padding:
EdgeInsets
.
symmetric
(
horizontal:
16
.
w
,
vertical:
8
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
16
.
w
,
vertical:
8
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
color:
isSelected
?
Color
.
fromRGBO
(
219
,
234
,
254
,
1
)
:
Colors
.
transparent
,
color:
isSelected
?
const
Color
.
fromRGBO
(
219
,
234
,
254
,
1
)
:
Colors
.
transparent
,
),
),
child:
Text
(
child:
Text
(
title
,
title
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
color:
isSelected
?
Color
.
fromRGBO
(
73
,
149
,
234
,
1
)
:
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
color:
isSelected
?
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
)
:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
),
),
),
),
),
),
...
@@ -154,8 +162,8 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -154,8 +162,8 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
List
<
BarChartGroupData
>
_buildBarGroups
(
int
index
)
{
List
<
BarChartGroupData
>
_buildBarGroups
(
int
index
)
{
final
data
=
index
==
0
?
widget
.
deviceInfo
.
powerData
:
widget
.
deviceInfo
.
tempData
;
final
data
=
index
==
0
?
widget
.
deviceInfo
.
powerData
:
widget
.
deviceInfo
.
tempData
;
final
Color
mainColor
=
index
==
0
final
Color
mainColor
=
index
==
0
?
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
?
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
:
Color
.
fromRGBO
(
251
,
191
,
36
,
1
);
:
const
Color
.
fromRGBO
(
251
,
191
,
36
,
1
);
return
List
.
generate
(
return
List
.
generate
(
data
.
length
,
data
.
length
,
...
@@ -175,4 +183,32 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
...
@@ -175,4 +183,32 @@ class _PowerCharBlockState extends State<PowerCharBlock> {
},
},
).
where
((
group
)
=>
group
.
barRods
.
isNotEmpty
).
toList
();
).
where
((
group
)
=>
group
.
barRods
.
isNotEmpty
).
toList
();
}
}
double
_calcMaxY
(
int
index
)
{
final
data
=
index
==
0
?
widget
.
deviceInfo
.
powerData
:
widget
.
deviceInfo
.
tempData
;
if
(
data
.
isEmpty
)
return
100
;
final
max
=
data
.
reduce
((
a
,
b
)
=>
a
>
b
?
a
:
b
).
toDouble
();
if
(
max
==
0
)
return
100
;
// 向上取整到最近的 nice number,并留 20% 余量
final
raw
=
max
*
1.2
;
final
magnitude
=
pow
(
10
,
(
log
(
raw
)
/
ln10
).
floor
()).
toDouble
();
final
normalized
=
raw
/
magnitude
;
final
nice
=
normalized
<=
1
?
1
:
normalized
<=
2
?
2
:
normalized
<=
5
?
5
:
10
;
return
nice
*
magnitude
;
}
double
_calcInterval
(
int
index
)
{
return
_calcMaxY
(
index
)
/
5
;
}
double
_calcBottomInterval
()
{
final
length
=
widget
.
deviceInfo
.
timeLabels
.
length
;
if
(
length
<=
6
)
return
1
;
if
(
length
<=
12
)
return
2
;
if
(
length
<=
24
)
return
3
;
return
(
length
/
6
).
ceilToDouble
();
}
}
}
\ No newline at end of file
lib/views/home/inspection/cubit/inspection_state.dart
View file @
1244f87e
...
@@ -49,7 +49,7 @@ class InspectionDevice {
...
@@ -49,7 +49,7 @@ class InspectionDevice {
factory
InspectionDevice
.
fromInspectionDeviceBO
(
InspectionDeviceBO
bo
)
{
factory
InspectionDevice
.
fromInspectionDeviceBO
(
InspectionDeviceBO
bo
)
{
return
InspectionDevice
(
return
InspectionDevice
(
id:
bo
.
deviceId
.
toString
(),
id:
bo
.
deviceId
.
toString
(),
icon:
_mapIcon
(
bo
.
device
TypeIcon
),
icon:
_mapIcon
(
bo
.
device
Category
),
name:
bo
.
deviceName
,
name:
bo
.
deviceName
,
type:
bo
.
deviceTypeName
,
type:
bo
.
deviceTypeName
,
location:
bo
.
roomName
,
location:
bo
.
roomName
,
...
@@ -67,7 +67,7 @@ class InspectionDevice {
...
@@ -67,7 +67,7 @@ class InspectionDevice {
return
Icons
.
thermostat
;
return
Icons
.
thermostat
;
case
'camera'
:
case
'camera'
:
return
Icons
.
videocam
;
return
Icons
.
videocam
;
case
'l
ight
'
:
case
'l
amp
'
:
return
Icons
.
light
;
return
Icons
.
light
;
case
'air_conditioner'
:
case
'air_conditioner'
:
case
'ac'
:
case
'ac'
:
...
...
lib/views/home/inspection/inspection_detail_view.dart
View file @
1244f87e
...
@@ -145,7 +145,24 @@ class _InspectionDetailBodyState extends State<_InspectionDetailBody> {
...
@@ -145,7 +145,24 @@ class _InspectionDetailBodyState extends State<_InspectionDetailBody> {
),
),
),
),
SliverToBoxAdapter
(
SliverToBoxAdapter
(
child:
SizedBox
(
height:
20
.
h
),
child:
Column
(
children:
[
Row
(
children:
[
SizedBox
(
width:
28
.
w
),
Text
(
'设备列表(
${pagingState.items != null ? pagingState.items!.length : 0}
)'
,
style:
TextStyle
(
fontSize:
28
.
sp
,
color:
const
Color
.
fromRGBO
(
10
,
13
,
20
,
1.0
),
fontWeight:
FontWeight
.
w500
,
),
),
],
),
SizedBox
(
height:
16
.
h
),
],
),
),
),
DeviceList
(
DeviceList
(
pagingState:
pagingState
,
pagingState:
pagingState
,
...
...
lib/views/home/inspection/widget/device_list_item.dart
View file @
1244f87e
...
@@ -26,21 +26,21 @@ class DeviceListItem extends StatelessWidget {
...
@@ -26,21 +26,21 @@ class DeviceListItem extends StatelessWidget {
child:
Row
(
child:
Row
(
children:
[
children:
[
Container
(
Container
(
width:
64
.
w
,
width:
80
.
w
,
height:
6
6
.
h
,
height:
6
4
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
235
,
244
,
255
,
1.0
),
color:
const
Color
.
fromRGBO
(
235
,
244
,
255
,
1.0
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
border:
Border
.
all
(
//
border: Border.all(
color:
const
Color
.
fromRGBO
(
66
,
165
,
245
,
1.0
),
//
color: const Color.fromRGBO(66, 165, 245, 1.0),
width:
1
.
w
,
//
width: 1.w,
style:
BorderStyle
.
solid
,
//
style: BorderStyle.solid,
),
//
),
),
),
child:
Icon
(
child:
Icon
(
device
.
icon
,
device
.
icon
,
color:
const
Color
.
fromRGBO
(
66
,
165
,
245
,
1.0
),
color:
const
Color
.
fromRGBO
(
66
,
165
,
245
,
1.0
),
size:
3
2
.
sp
,
size:
4
2
.
sp
,
),
),
),
),
SizedBox
(
width:
16
.
w
),
SizedBox
(
width:
16
.
w
),
...
@@ -58,7 +58,7 @@ class DeviceListItem extends StatelessWidget {
...
@@ -58,7 +58,7 @@ class DeviceListItem extends StatelessWidget {
color:
const
Color
.
fromRGBO
(
10
,
13
,
20
,
1.0
),
color:
const
Color
.
fromRGBO
(
10
,
13
,
20
,
1.0
),
),
),
),
),
SizedBox
(
width:
8
.
w
),
SizedBox
(
width:
1
8
.
w
),
Text
(
Text
(
device
.
status
,
device
.
status
,
style:
TextStyle
(
style:
TextStyle
(
...
@@ -83,13 +83,13 @@ class DeviceListItem extends StatelessWidget {
...
@@ -83,13 +83,13 @@ class DeviceListItem extends StatelessWidget {
Icon
(
Icon
(
Icons
.
access_time
,
Icons
.
access_time
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
size:
2
0
.
sp
,
size:
2
8
.
sp
,
),
),
SizedBox
(
width:
4
.
w
),
SizedBox
(
width:
4
.
w
),
Text
(
Text
(
device
.
time
,
device
.
time
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
2
0
.
sp
,
fontSize:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
),
),
),
),
...
@@ -98,18 +98,10 @@ class DeviceListItem extends StatelessWidget {
...
@@ -98,18 +98,10 @@ class DeviceListItem extends StatelessWidget {
],
],
),
),
),
),
Container
(
Icon
(
width:
48
.
w
,
height:
48
.
h
,
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
242
,
243
,
245
,
1.0
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
),
child:
Icon
(
Icons
.
chevron_right
,
Icons
.
chevron_right
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
size:
24
.
sp
,
size:
56
.
sp
,
),
),
),
],
],
),
),
...
...
lib/views/home/inspection/widget/filter_panel.dart
View file @
1244f87e
...
@@ -142,16 +142,65 @@ class FilterPanel extends StatelessWidget {
...
@@ -142,16 +142,65 @@ class FilterPanel extends StatelessWidget {
),
),
)
)
else
else
Wrap
(
// Wrap(
spacing:
5
.
w
,
// spacing: 12.w,
runSpacing:
12
.
h
,
// runSpacing: 12.h,
children:
roomEntries
.
map
((
entry
)
{
// children: roomEntries.map((entry) {
// final isSelected = selectedRoomIds.contains(entry.key);
// return GestureDetector(
// onTap: () => onRoomToggle(entry.key),
// child: Container(
// width: 120.w,
// height: 60.h,
// alignment: Alignment.center,
// padding: EdgeInsets.symmetric(horizontal: 5.w),
// decoration: BoxDecoration(
// color: isSelected
// ? const Color.fromRGBO(235, 244, 255, 1.0)
// : Colors.white,
// borderRadius: BorderRadius.circular(12.r),
// border: Border.all(
// color: isSelected
// ? const Color.fromRGBO(66, 165, 245, 1.0)
// : const Color.fromRGBO(200, 208, 220, 1.0),
// width: 1.w,
// ),
// ),
// child: Text(
// entry.value,
// style: TextStyle(
// fontSize: 24.sp,
// color: isSelected
// ? const Color.fromRGBO(66, 165, 245, 1.0)
// : const Color.fromRGBO(100, 116, 139, 1.0),
// fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
// ),
// textAlign: TextAlign.center,
// maxLines: 2,
// overflow: TextOverflow.ellipsis,
// ),
// ),
// );
// }).toList(),
// ),
GridView
.
builder
(
shrinkWrap:
true
,
physics:
const
NeverScrollableScrollPhysics
(),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount
(
crossAxisCount:
5
,
childAspectRatio:
50
/
30
,
crossAxisSpacing:
12
.
w
,
mainAxisSpacing:
12
.
h
,
),
itemCount:
roomEntries
.
length
,
itemBuilder:
(
context
,
index
)
{
final
entry
=
roomEntries
[
index
];
final
isSelected
=
selectedRoomIds
.
contains
(
entry
.
key
);
final
isSelected
=
selectedRoomIds
.
contains
(
entry
.
key
);
return
GestureDetector
(
return
GestureDetector
(
onTap:
()
=>
onRoomToggle
(
entry
.
key
),
onTap:
()
=>
onRoomToggle
(
entry
.
key
),
child:
Container
(
child:
Container
(
width:
120
.
w
,
alignment:
Alignment
.
center
,
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
,
vertical:
12
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
5
.
w
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
isSelected
color:
isSelected
?
const
Color
.
fromRGBO
(
235
,
244
,
255
,
1.0
)
?
const
Color
.
fromRGBO
(
235
,
244
,
255
,
1.0
)
...
@@ -173,10 +222,13 @@ class FilterPanel extends StatelessWidget {
...
@@ -173,10 +222,13 @@ class FilterPanel extends StatelessWidget {
:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1.0
),
fontWeight:
isSelected
?
FontWeight
.
bold
:
FontWeight
.
normal
,
fontWeight:
isSelected
?
FontWeight
.
bold
:
FontWeight
.
normal
,
),
),
textAlign:
TextAlign
.
center
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
),
),
),
),
);
);
}
).
toList
()
,
},
),
),
],
],
);
);
...
...
lib/views/home/inspection_device/cubit/inspection_device_cubit.dart
View file @
1244f87e
...
@@ -22,8 +22,8 @@ class InspectionDeviceCubit extends Cubit<InspectionDeviceState> {
...
@@ -22,8 +22,8 @@ class InspectionDeviceCubit extends Cubit<InspectionDeviceState> {
area:
''
,
area:
''
,
responsiblePerson:
''
,
responsiblePerson:
''
,
lastInspectionTime:
''
,
lastInspectionTime:
''
,
inspectionHistory:
[],
inspectionHistory:
const
[],
inspectionItems:
[],
inspectionItems:
const
[],
icon:
Icons
.
devices
,
icon:
Icons
.
devices
,
))
{
))
{
loadDeviceData
();
loadDeviceData
();
...
...
lib/views/home/inspection_device/inspection_device_view.dart
View file @
1244f87e
...
@@ -54,9 +54,9 @@ class InspectionDeviceView extends StatelessWidget {
...
@@ -54,9 +54,9 @@ class InspectionDeviceView extends StatelessWidget {
fontWeight:
FontWeight
.
w500
,
fontWeight:
FontWeight
.
w500
,
),
),
),
),
Icon
(
const
Icon
(
Icons
.
arrow_forward
,
Icons
.
arrow_forward
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
color:
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
),
),
],
],
),
),
...
...
lib/views/home/inspection_device/widget/device_overview_card.dart
View file @
1244f87e
...
@@ -41,8 +41,8 @@ class DeviceOverviewCard extends StatelessWidget {
...
@@ -41,8 +41,8 @@ class DeviceOverviewCard extends StatelessWidget {
Container
(
Container
(
width:
100
.
w
,
width:
100
.
w
,
height:
100
.
h
,
height:
100
.
h
,
decoration:
BoxDecoration
(
decoration:
const
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
235
,
244
,
255
,
1.0
),
color:
Color
.
fromRGBO
(
235
,
244
,
255
,
1.0
),
shape:
BoxShape
.
circle
,
shape:
BoxShape
.
circle
,
),
),
child:
Icon
(
child:
Icon
(
...
...
lib/views/home/inspection_topology/cubit/inspection_topology_cubit.dart
View file @
1244f87e
...
@@ -87,16 +87,26 @@ class InspectionTopologyCubit extends Cubit<InspectionTopologyState> {
...
@@ -87,16 +87,26 @@ class InspectionTopologyCubit extends Cubit<InspectionTopologyState> {
}
}
// 递归构建节点并计算布局位置
// 递归构建节点并计算布局位置
// depth < 3:水平排列;depth ≥ 3:垂直向下延申
TopologyNode
buildNode
(
TreeNodeBO
node
,
int
depth
,
double
xCenter
,
double
xSpan
)
{
TopologyNode
buildNode
(
TreeNodeBO
node
,
int
depth
,
double
xCenter
,
double
xSpan
)
{
final
children
=
childrenMap
[
node
.
deviceId
]
??
[];
final
children
=
childrenMap
[
node
.
deviceId
]
??
[];
final
childNodes
=
<
TopologyNode
>[];
final
childNodes
=
<
TopologyNode
>[];
const
verticalFromDepth
=
3
;
if
(
children
.
isNotEmpty
)
{
if
(
children
.
isNotEmpty
)
{
if
(
depth
>=
verticalFromDepth
)
{
// 垂直排列:每个子节点深度递增,挂在父节点正下方
for
(
int
i
=
0
;
i
<
children
.
length
;
i
++)
{
childNodes
.
add
(
buildNode
(
children
[
i
],
depth
+
1
+
i
,
xCenter
,
xSpan
));
}
}
else
{
// 水平排列:子节点同深度,x 分散
for
(
int
i
=
0
;
i
<
children
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
children
.
length
;
i
++)
{
final
childX
=
children
.
length
==
1
final
childX
=
children
.
length
==
1
?
xCenter
?
xCenter
:
xCenter
-
xSpan
/
2
+
(
xSpan
*
i
/
(
children
.
length
-
1
));
:
xCenter
-
xSpan
/
2
+
(
xSpan
*
i
/
(
children
.
length
-
1
));
childNodes
.
add
(
buildNode
(
children
[
i
],
depth
+
1
,
childX
,
xSpan
*
0.55
));
childNodes
.
add
(
buildNode
(
children
[
i
],
depth
+
1
,
childX
,
xSpan
));
}
}
}
}
}
...
@@ -107,19 +117,21 @@ class InspectionTopologyCubit extends Cubit<InspectionTopologyState> {
...
@@ -107,19 +117,21 @@ class InspectionTopologyCubit extends Cubit<InspectionTopologyState> {
statusText:
node
.
statusText
,
statusText:
node
.
statusText
,
gatewayId:
node
.
gatewayId
?.
toString
(),
gatewayId:
node
.
gatewayId
?.
toString
(),
x:
xCenter
.
clamp
(
0.05
,
0.95
),
x:
xCenter
.
clamp
(
0.05
,
0.95
),
y:
(
0.08
+
depth
*
0.17
).
clamp
(
0.02
,
0.98
),
y:
depth
<
3
?
(
0.05
+
depth
*
0.25
).
clamp
(
0.02
,
0.98
)
:
(
0.78
+
(
depth
-
3
)
*
0.10
).
clamp
(
0.02
,
0.98
),
children:
childNodes
,
children:
childNodes
,
);
);
}
}
if
(
roots
.
length
==
1
)
{
if
(
roots
.
length
==
1
)
{
return
buildNode
(
roots
.
first
,
0
,
0.5
,
0.
7
);
return
buildNode
(
roots
.
first
,
0
,
0.5
,
0.
95
);
}
else
{
}
else
{
// 多个根节点:创建一个虚拟根,将所有根均匀分布在第二层
// 多个根节点:创建一个虚拟根,将所有根均匀分布在第二层
final
virtualChildren
=
<
TopologyNode
>[];
final
virtualChildren
=
<
TopologyNode
>[];
for
(
int
i
=
0
;
i
<
roots
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
roots
.
length
;
i
++)
{
final
xPos
=
0.1
+
(
0.8
*
i
/
(
roots
.
length
-
1
));
final
xPos
=
0.1
+
(
0.8
*
i
/
(
roots
.
length
-
1
));
virtualChildren
.
add
(
buildNode
(
roots
[
i
],
1
,
xPos
,
0.
3
5
));
virtualChildren
.
add
(
buildNode
(
roots
[
i
],
1
,
xPos
,
0.5
));
}
}
return
TopologyNode
(
return
TopologyNode
(
id:
'0'
,
id:
'0'
,
...
...
lib/views/home/inspection_topology/inspection_topology_view.dart
View file @
1244f87e
...
@@ -98,13 +98,19 @@ class InspectionTopologyPage extends StatelessWidget {
...
@@ -98,13 +98,19 @@ class InspectionTopologyPage extends StatelessWidget {
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
,
vertical:
24
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
,
vertical:
24
.
h
),
child:
Column
(
child:
Column
(
children:
[
children:
[
SizedBox
(
height:
10
.
h
),
const
StatusLegendWidget
(),
StatusLegendWidget
(),
SizedBox
(
height:
20
.
h
),
SizedBox
(
height:
20
.
h
),
DeviceHeaderWidget
(
DeviceHeaderWidget
(
deviceName:
state
.
deviceName
,
deviceName:
state
.
deviceName
,
deviceModel:
state
.
deviceModel
,
deviceModel:
state
.
deviceModel
,
),
),
Divider
(
height:
0.5
.
h
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
0.2
),
thickness:
0.5
,
indent:
28
.
w
,
endIndent:
28
.
w
,
),
NetworkTopologyWidget
(
NetworkTopologyWidget
(
topologyNodes:
state
.
topologyNodes
,
topologyNodes:
state
.
topologyNodes
,
deviceCount:
state
.
deviceCount
,
deviceCount:
state
.
deviceCount
,
...
...
lib/views/home/inspection_topology/widget/network_topology_widget.dart
View file @
1244f87e
...
@@ -16,8 +16,30 @@ class NetworkTopologyWidget extends StatelessWidget {
...
@@ -16,8 +16,30 @@ class NetworkTopologyWidget extends StatelessWidget {
required
this
.
onNodeTap
,
required
this
.
onNodeTap
,
});
});
/// 找到最大深度,并返回每个深度的节点总数
Map
<
int
,
int
>
_countByDepth
(
TopologyNode
node
,
int
depth
)
{
final
map
=
<
int
,
int
>{};
_collectDepthCounts
(
node
,
depth
,
map
);
return
map
;
}
void
_collectDepthCounts
(
TopologyNode
node
,
int
depth
,
Map
<
int
,
int
>
map
)
{
map
[
depth
]
=
(
map
[
depth
]
??
0
)
+
1
;
for
(
var
child
in
node
.
children
)
{
_collectDepthCounts
(
child
,
depth
+
1
,
map
);
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
// 计算最大深度 & 每个深度有多少节点
final
depthCounts
=
topologyNodes
.
isNotEmpty
?
_countByDepth
(
topologyNodes
[
0
],
0
)
:
<
int
,
int
>{};
final
maxDepth
=
depthCounts
.
keys
.
isEmpty
?
0
:
depthCounts
.
keys
.
reduce
((
a
,
b
)
=>
a
>
b
?
a
:
b
);
// 最后一层节点数 > 3 时,叶子节点用竖向容器
final
lastLevelCount
=
depthCounts
[
maxDepth
]
??
0
;
final
useVerticalLeaf
=
lastLevelCount
>
3
;
return
Container
(
return
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
24
.
w
,
vertical:
32
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
24
.
w
,
vertical:
32
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
...
@@ -77,6 +99,9 @@ class NetworkTopologyWidget extends StatelessWidget {
...
@@ -77,6 +99,9 @@ class NetworkTopologyWidget extends StatelessWidget {
clickableNodes
,
clickableNodes
,
constraints
.
maxWidth
,
constraints
.
maxWidth
,
constraints
.
maxHeight
,
constraints
.
maxHeight
,
0
,
maxDepth
,
useVerticalLeaf
,
);
);
return
Stack
(
children:
clickableNodes
);
return
Stack
(
children:
clickableNodes
);
},
},
...
@@ -95,13 +120,75 @@ class NetworkTopologyWidget extends StatelessWidget {
...
@@ -95,13 +120,75 @@ class NetworkTopologyWidget extends StatelessWidget {
List
<
Widget
>
nodes
,
List
<
Widget
>
nodes
,
double
maxWidth
,
double
maxWidth
,
double
maxHeight
,
double
maxHeight
,
int
depth
,
int
maxDepth
,
bool
useVerticalLeaf
,
)
{
)
{
final
centerX
=
maxWidth
*
node
.
x
;
final
centerX
=
maxWidth
*
node
.
x
;
final
centerY
=
maxHeight
*
node
.
y
;
final
centerY
=
maxHeight
*
node
.
y
;
final
nodeWidth
=
150
.
w
;
// final nodeHeight = node.name.length > 4 ? 160.h : 100.h;
final
nodeHeight
=
80
.
h
;
// 跳过虚拟根节点
final
isVirtualRoot
=
node
.
id
==
'0'
&&
node
.
name
==
'根节点'
;
// depth ≥ 3 全部竖向;否则只有最后一层且叶子多时竖向
final
isVerticalNode
=
depth
>=
3
||
(
depth
==
maxDepth
&&
node
.
children
.
isEmpty
&&
useVerticalLeaf
);
if
(!
isVirtualRoot
)
{
if
(
isVerticalNode
)
{
// 竖向椭圆容器
final
vw
=
48
.
w
;
final
vh
=
144
.
h
;
nodes
.
add
(
Positioned
(
left:
centerX
-
vw
/
2
,
top:
centerY
-
vh
/
2
,
width:
vw
,
height:
vh
,
child:
GestureDetector
(
onTap:
()
=>
onNodeTap
(
node
),
child:
Container
(
alignment:
Alignment
.
center
,
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
229
,
241
,
255
,
1
),
border:
Border
.
all
(
color:
const
Color
.
fromRGBO
(
80
,
162
,
255
,
1
),
width:
1
.
w
,
),
borderRadius:
BorderRadius
.
circular
(
vw
/
2
),
),
child:
Padding
(
padding:
EdgeInsets
.
symmetric
(
vertical:
8
.
h
),
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
()
{
const
maxChars
=
4
;
final
chars
=
node
.
name
.
split
(
''
);
final
display
=
chars
.
length
>
maxChars
?
[...
chars
.
take
(
maxChars
-
1
),
'…'
]
:
chars
;
return
display
.
map
((
char
)
=>
Text
(
char
,
style:
TextStyle
(
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
fontSize:
24
.
sp
,
fontWeight:
FontWeight
.
w500
,
),
))
.
toList
();
}(),
),
),
),
),
),
);
}
else
{
// 普通水平椭圆容器
final
nodeWidth
=
140
.
w
;
final
nodeHeight
=
54
.
h
;
nodes
.
add
(
nodes
.
add
(
Positioned
(
Positioned
(
left:
centerX
-
nodeWidth
/
2
,
left:
centerX
-
nodeWidth
/
2
,
...
@@ -111,32 +198,35 @@ class NetworkTopologyWidget extends StatelessWidget {
...
@@ -111,32 +198,35 @@ class NetworkTopologyWidget extends StatelessWidget {
child:
GestureDetector
(
child:
GestureDetector
(
onTap:
()
=>
onNodeTap
(
node
),
onTap:
()
=>
onNodeTap
(
node
),
child:
Container
(
child:
Container
(
alignment:
Alignment
.
center
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
239
,
246
,
255
,
1
),
color:
const
Color
.
fromRGBO
(
229
,
241
,
255
,
1
),
border:
Border
.
all
(
border:
Border
.
all
(
color:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
color:
const
Color
.
fromRGBO
(
80
,
162
,
255
,
1
),
width:
1
.
w
,
width:
1
.
w
,
),
),
borderRadius:
BorderRadius
.
circular
(
6
0
.
r
),
borderRadius:
BorderRadius
.
circular
(
4
0
.
r
),
),
),
child:
Center
(
child:
Text
(
child:
Text
(
node
.
name
,
node
.
name
,
style:
TextStyle
(
style:
TextStyle
(
color:
const
Color
.
fromRGBO
(
71
,
85
,
105
,
1
),
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
),
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
fontWeight:
FontWeight
.
w500
,
fontWeight:
FontWeight
.
w500
,
),
),
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
),
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
),
),
),
),
),
),
),
),
);
);
}
}
for
(
var
child
in
node
.
children
)
{
for
(
var
child
in
node
.
children
)
{
_collectNodes
(
child
,
nodes
,
maxWidth
,
maxHeight
);
_collectNodes
(
child
,
nodes
,
maxWidth
,
maxHeight
,
depth
+
1
,
maxDepth
,
useVerticalLeaf
);
}
}
}
}
}
}
...
@@ -159,6 +249,14 @@ class TopologyPainter extends CustomPainter {
...
@@ -159,6 +249,14 @@ class TopologyPainter extends CustomPainter {
}
}
void
_drawConnections
(
Canvas
canvas
,
Size
size
,
TopologyNode
node
,
Paint
paint
)
{
void
_drawConnections
(
Canvas
canvas
,
Size
size
,
TopologyNode
node
,
Paint
paint
)
{
final
isVirtualRoot
=
node
.
id
==
'0'
&&
node
.
name
==
'根节点'
;
if
(
isVirtualRoot
)
{
for
(
var
child
in
node
.
children
)
{
_drawConnections
(
canvas
,
size
,
child
,
paint
);
}
return
;
}
final
centerX
=
size
.
width
*
node
.
x
;
final
centerX
=
size
.
width
*
node
.
x
;
final
centerY
=
size
.
height
*
node
.
y
;
final
centerY
=
size
.
height
*
node
.
y
;
...
...
lib/views/home/inspection_topology/widget/status_legend_widget.dart
View file @
1244f87e
...
@@ -26,7 +26,7 @@ class StatusLegendWidget extends StatelessWidget {
...
@@ -26,7 +26,7 @@ class StatusLegendWidget extends StatelessWidget {
),
),
SizedBox
(
height:
24
.
h
),
SizedBox
(
height:
24
.
h
),
Wrap
(
Wrap
(
spacing:
32
.
w
,
spacing:
24
.
w
,
runSpacing:
20
.
h
,
runSpacing:
20
.
h
,
children:
[
children:
[
_buildLegendItem
(
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
'开启'
),
_buildLegendItem
(
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
'开启'
),
...
@@ -47,14 +47,14 @@ class StatusLegendWidget extends StatelessWidget {
...
@@ -47,14 +47,14 @@ class StatusLegendWidget extends StatelessWidget {
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
children:
[
children:
[
Container
(
Container
(
width:
32
.
w
,
width:
24
.
w
,
height:
32
.
h
,
height:
24
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
color
,
color:
color
,
shape:
BoxShape
.
circle
,
shape:
BoxShape
.
circle
,
),
),
),
),
SizedBox
(
width:
12
.
w
),
SizedBox
(
width:
8
.
w
),
Text
(
Text
(
label
,
label
,
style:
TextStyle
(
style:
TextStyle
(
...
...
lib/views/report/device/cubit/device_list_cubit.dart
View file @
1244f87e
...
@@ -39,7 +39,7 @@ class DeviceListCubit extends Cubit<DeviceListState> {
...
@@ -39,7 +39,7 @@ class DeviceListCubit extends Cubit<DeviceListState> {
tabAll:
result
.
tabCount
.
all
,
tabAll:
result
.
tabCount
.
all
,
tabAirSwitch:
result
.
tabCount
.
airSwitch
,
tabAirSwitch:
result
.
tabCount
.
airSwitch
,
tabGuestControl:
result
.
tabCount
.
guestControl
,
tabGuestControl:
result
.
tabCount
.
guestControl
,
tabNetwork:
result
.
tabCount
.
network
,
tabNetwork:
result
.
tabCount
.
gateway
,
totalCount:
result
.
total
,
totalCount:
result
.
total
,
));
));
}
}
...
@@ -54,6 +54,7 @@ class DeviceListCubit extends Cubit<DeviceListState> {
...
@@ -54,6 +54,7 @@ class DeviceListCubit extends Cubit<DeviceListState> {
status:
row
.
statusTag
.
text
.
isNotEmpty
status:
row
.
statusTag
.
text
.
isNotEmpty
?
row
.
statusTag
.
text
?
row
.
statusTag
.
text
:
(
row
.
onlineStatus
==
'1'
?
'正常'
:
'离线'
),
:
(
row
.
onlineStatus
==
'1'
?
'正常'
:
'离线'
),
color:
row
.
statusTag
.
color
,
lastUpdate:
row
.
subtitle
.
text
,
lastUpdate:
row
.
subtitle
.
text
,
);
);
}).
toList
();
}).
toList
();
...
...
lib/views/report/device/cubit/device_list_state.dart
View file @
1244f87e
...
@@ -7,17 +7,17 @@ enum DeviceTypeEnum {
...
@@ -7,17 +7,17 @@ enum DeviceTypeEnum {
network
,
network
,
}
}
/// deviceTypeId 映射: all→null, smartBreaker→
1, guestControl→2, network→3
/// deviceTypeId 映射: all→null, smartBreaker→
airSwitch, guestControl→guestControl, network→gateway
int
?
deviceTypeIdFromEnum
(
DeviceTypeEnum
type
)
{
String
?
deviceTypeIdFromEnum
(
DeviceTypeEnum
type
)
{
switch
(
type
)
{
switch
(
type
)
{
case
DeviceTypeEnum
.
all
:
case
DeviceTypeEnum
.
all
:
return
null
;
return
null
;
case
DeviceTypeEnum
.
smartBreaker
:
case
DeviceTypeEnum
.
smartBreaker
:
return
1
;
return
'airSwitch'
;
case
DeviceTypeEnum
.
guestControl
:
case
DeviceTypeEnum
.
guestControl
:
return
2
;
return
'guestControl'
;
case
DeviceTypeEnum
.
network
:
case
DeviceTypeEnum
.
network
:
return
3
;
return
'gateway'
;
}
}
}
}
...
@@ -44,6 +44,7 @@ class DeviceInfo extends Equatable {
...
@@ -44,6 +44,7 @@ class DeviceInfo extends Equatable {
final
bool
online
;
final
bool
online
;
final
String
status
;
final
String
status
;
final
String
lastUpdate
;
final
String
lastUpdate
;
final
String
color
;
const
DeviceInfo
({
const
DeviceInfo
({
this
.
deviceId
=
0
,
this
.
deviceId
=
0
,
...
@@ -53,10 +54,12 @@ class DeviceInfo extends Equatable {
...
@@ -53,10 +54,12 @@ class DeviceInfo extends Equatable {
this
.
online
=
false
,
this
.
online
=
false
,
this
.
status
=
''
,
this
.
status
=
''
,
this
.
lastUpdate
=
''
,
this
.
lastUpdate
=
''
,
this
.
color
=
''
,
});
});
@override
@override
List
<
Object
?>
get
props
=>
[
deviceId
,
name
,
room
,
type
,
online
,
status
,
lastUpdate
];
List
<
Object
?>
get
props
=>
[
deviceId
,
name
,
room
,
type
,
online
,
status
,
lastUpdate
,
color
];
}
}
class
DeviceListState
extends
Equatable
{
class
DeviceListState
extends
Equatable
{
...
...
lib/views/report/device/device_list_view.dart
View file @
1244f87e
...
@@ -97,10 +97,11 @@ class _ReportDeviceListBodyState extends State<_ReportDeviceListBody> {
...
@@ -97,10 +97,11 @@ class _ReportDeviceListBodyState extends State<_ReportDeviceListBody> {
SizedBox
(
height:
10
.
h
),
SizedBox
(
height:
10
.
h
),
DeviceFilterTab
(
DeviceFilterTab
(
selectedType:
state
.
selectedType
,
selectedType:
state
.
selectedType
,
tabAirSwitch:
state
.
tabAirSwitch
,
tabGuestControl:
state
.
tabGuestControl
,
tabNetwork:
state
.
tabNetwork
,
onSelect:
(
type
)
{
onSelect:
(
type
)
{
context
context
.
read
<
DeviceListCubit
>().
selectType
(
type
);
.
read
<
DeviceListCubit
>()
.
selectType
(
type
);
},
},
),
),
SizedBox
(
height:
10
.
h
),
SizedBox
(
height:
10
.
h
),
...
@@ -113,8 +114,7 @@ class _ReportDeviceListBodyState extends State<_ReportDeviceListBody> {
...
@@ -113,8 +114,7 @@ class _ReportDeviceListBodyState extends State<_ReportDeviceListBody> {
sliver:
PagedSliverList
<
int
,
DeviceInfo
>(
sliver:
PagedSliverList
<
int
,
DeviceInfo
>(
state:
pagingState
,
state:
pagingState
,
fetchNextPage:
fetchNextPage
,
fetchNextPage:
fetchNextPage
,
builderDelegate:
builderDelegate:
PagedChildBuilderDelegate
<
DeviceInfo
>(
PagedChildBuilderDelegate
<
DeviceInfo
>(
firstPageErrorIndicatorBuilder:
(
_
)
=>
Center
(
firstPageErrorIndicatorBuilder:
(
_
)
=>
Center
(
child:
Column
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
...
...
lib/views/report/device/widget/device_card.dart
View file @
1244f87e
...
@@ -61,10 +61,10 @@ class DeviceCard extends StatelessWidget {
...
@@ -61,10 +61,10 @@ class DeviceCard extends StatelessWidget {
child:
Row
(
child:
Row
(
children:
[
children:
[
Container
(
Container
(
width:
80
.
w
,
width:
64
.
w
,
height:
80
.
h
,
height:
58
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
16
.
r
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
color:
_getIconColor
(
device
.
type
).
withOpacity
(
0.1
),
color:
_getIconColor
(
device
.
type
).
withOpacity
(
0.1
),
),
),
child:
Icon
(
child:
Icon
(
...
@@ -77,6 +77,7 @@ class DeviceCard extends StatelessWidget {
...
@@ -77,6 +77,7 @@ class DeviceCard extends StatelessWidget {
Expanded
(
Expanded
(
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
spacing:
8
.
h
,
children:
[
children:
[
Text
(
Text
(
device
.
name
,
device
.
name
,
...
@@ -86,8 +87,8 @@ class DeviceCard extends StatelessWidget {
...
@@ -86,8 +87,8 @@ class DeviceCard extends StatelessWidget {
color:
const
Color
.
fromRGBO
(
31
,
41
,
55
,
1
),
color:
const
Color
.
fromRGBO
(
31
,
41
,
55
,
1
),
),
),
),
),
SizedBox
(
height:
8
.
h
),
Row
(
Row
(
spacing:
16
.
w
,
children:
[
children:
[
Text
(
Text
(
_getTypeLabel
(
device
.
type
),
_getTypeLabel
(
device
.
type
),
...
@@ -96,7 +97,6 @@ class DeviceCard extends StatelessWidget {
...
@@ -96,7 +97,6 @@ class DeviceCard extends StatelessWidget {
color:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
color:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
),
),
),
),
SizedBox
(
width:
16
.
w
),
Text
(
Text
(
'房间
${device.room}
'
,
'房间
${device.room}
'
,
style:
TextStyle
(
style:
TextStyle
(
...
@@ -109,38 +109,51 @@ class DeviceCard extends StatelessWidget {
...
@@ -109,38 +109,51 @@ class DeviceCard extends StatelessWidget {
],
],
),
),
),
),
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
children:
[
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
16
.
w
,
vertical:
8
.
h
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
color:
device
.
online
?
const
Color
.
fromRGBO
(
220
,
252
,
231
,
1
)
:
const
Color
.
fromRGBO
(
254
,
226
,
226
,
1
),
),
child:
Text
(
device
.
status
,
style:
TextStyle
(
fontSize:
20
.
sp
,
color:
device
.
online
?
const
Color
.
fromRGBO
(
21
,
128
,
61
,
1
)
:
const
Color
.
fromRGBO
(
220
,
38
,
38
,
1
),
fontWeight:
FontWeight
.
bold
,
),
),
),
SizedBox
(
height:
8
.
h
),
Text
(
Text
(
device
.
lastUpdate
,
device
.
status
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
18
.
sp
,
fontSize:
24
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
),
device
.
color
==
'danger'
?
const
Color
.
fromRGBO
(
220
,
38
,
38
,
1
)
:
),
device
.
color
==
'success'
?
const
Color
.
fromRGBO
(
20
,
184
,
166
,
1
)
:
],
device
.
color
==
'warning'
?
const
Color
.
fromRGBO
(
250
,
204
,
21
,
1
)
:
),
device
.
color
==
'info'
?
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
)
:
const
Color
.
fromRGBO
(
20
,
184
,
166
,
1
),
fontWeight:
FontWeight
.
w500
,
),
),
// Column(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// Container(
// padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(12.r),
// color: device.online
// ? const Color.fromRGBO(220, 252, 231, 1)
// : const Color.fromRGBO(254, 226, 226, 1),
// ),
// child: Text(
// device.status,
// style: TextStyle(
// fontSize: 20.sp,
// color: device.online
// ? const Color.fromRGBO(21, 128, 61, 1)
// : const Color.fromRGBO(220, 38, 38, 1),
// fontWeight: FontWeight.bold,
// ),
// ),
// ),
// SizedBox(height: 8.h),
// Text(
// device.lastUpdate,
// style: TextStyle(
// fontSize: 18.sp,
// color: const Color.fromRGBO(156, 163, 175, 1),
// ),
// ),
// ],
// ),
],
],
),
),
);
);
...
...
lib/views/report/device/widget/device_filter_tab.dart
View file @
1244f87e
...
@@ -5,20 +5,26 @@ import 'package:smart_hotel_app/views/report/device/cubit/device_list_state.dart
...
@@ -5,20 +5,26 @@ import 'package:smart_hotel_app/views/report/device/cubit/device_list_state.dart
class
DeviceFilterTab
extends
StatelessWidget
{
class
DeviceFilterTab
extends
StatelessWidget
{
final
DeviceTypeEnum
selectedType
;
final
DeviceTypeEnum
selectedType
;
final
Function
(
DeviceTypeEnum
)
onSelect
;
final
Function
(
DeviceTypeEnum
)
onSelect
;
final
int
tabAirSwitch
;
final
int
tabGuestControl
;
final
int
tabNetwork
;
const
DeviceFilterTab
({
const
DeviceFilterTab
({
super
.
key
,
super
.
key
,
required
this
.
selectedType
,
required
this
.
selectedType
,
required
this
.
onSelect
,
required
this
.
onSelect
,
required
this
.
tabAirSwitch
,
required
this
.
tabGuestControl
,
required
this
.
tabNetwork
,
});
});
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
tabs
=
[
final
tabs
=
[
{
'type'
:
DeviceTypeEnum
.
all
,
'label'
:
'全部'
},
{
'type'
:
DeviceTypeEnum
.
all
,
'label'
:
'全部'
},
{
'type'
:
DeviceTypeEnum
.
smartBreaker
,
'label'
:
'空开'
},
{
'type'
:
DeviceTypeEnum
.
smartBreaker
,
'label'
:
'空开
(
$tabAirSwitch
)
'
},
{
'type'
:
DeviceTypeEnum
.
guestControl
,
'label'
:
'客控'
},
{
'type'
:
DeviceTypeEnum
.
guestControl
,
'label'
:
'客控
(
$tabGuestControl
)
'
},
{
'type'
:
DeviceTypeEnum
.
network
,
'label'
:
'网络'
},
{
'type'
:
DeviceTypeEnum
.
network
,
'label'
:
'网络
(
$tabNetwork
)
'
},
];
];
return
Container
(
return
Container
(
...
@@ -35,18 +41,23 @@ class DeviceFilterTab extends StatelessWidget {
...
@@ -35,18 +41,23 @@ class DeviceFilterTab extends StatelessWidget {
return
GestureDetector
(
return
GestureDetector
(
onTap:
()
=>
onSelect
(
tab
[
'type'
]
as
DeviceTypeEnum
),
onTap:
()
=>
onSelect
(
tab
[
'type'
]
as
DeviceTypeEnum
),
child:
Container
(
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
2
4
.
w
,
vertical:
12
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
2
0
.
w
,
vertical:
8
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
16
.
r
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
color:
isSelected
color:
isSelected
?
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
?
const
Color
.
fromRGBO
(
73
,
149
,
234
,
0.2
)
:
const
Color
.
fromRGBO
(
243
,
244
,
246
,
1
),
:
const
Color
.
fromRGBO
(
243
,
244
,
246
,
1
),
border:
isSelected
?
Border
.
all
(
width:
1
.
w
,
color:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
0.5
),
)
:
null
,
),
),
child:
Text
(
child:
Text
(
tab
[
'label'
]
as
String
,
tab
[
'label'
]
as
String
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
color:
isSelected
?
Colors
.
white
:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
color:
isSelected
?
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
)
:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
fontWeight:
isSelected
?
FontWeight
.
bold
:
FontWeight
.
normal
,
fontWeight:
isSelected
?
FontWeight
.
bold
:
FontWeight
.
normal
,
),
),
),
),
...
...
lib/views/report/energy/cubit/energy_cubit.dart
View file @
1244f87e
...
@@ -45,9 +45,12 @@ class EnergyCubit extends Cubit<EnergyState> {
...
@@ -45,9 +45,12 @@ class EnergyCubit extends Cubit<EnergyState> {
100
;
100
;
}
}
// 将逐小时数据点提取为 List<double>
// 将逐小时数据点提取为 List<double>
和时间标签
final
hourlyData
=
final
hourlyData
=
data
.
hourlyUsageToday
.
hourlyPoints
.
map
((
p
)
=>
p
.
value
).
toList
();
data
.
hourlyUsageToday
.
hourlyPoints
.
map
((
p
)
=>
p
.
value
).
toList
();
final
hourlyTimeLabels
=
data
.
hourlyUsageToday
.
hourlyPoints
.
map
((
p
)
=>
p
.
time
.
length
>=
5
?
p
.
time
.
substring
(
0
,
5
)
:
p
.
time
)
.
toList
();
// 将分区数据映射为 ZoneData 列表
// 将分区数据映射为 ZoneData 列表
final
totalToday
=
data
.
zoneUsageRatio
.
totalToday
;
final
totalToday
=
data
.
zoneUsageRatio
.
totalToday
;
...
@@ -69,6 +72,7 @@ class EnergyCubit extends Cubit<EnergyState> {
...
@@ -69,6 +72,7 @@ class EnergyCubit extends Cubit<EnergyState> {
monthBill:
data
.
monthCostEstimate
,
monthBill:
data
.
monthCostEstimate
,
hourlyMaxValue:
data
.
hourlyUsageToday
.
maxValue
,
hourlyMaxValue:
data
.
hourlyUsageToday
.
maxValue
,
hourlyData:
hourlyData
,
hourlyData:
hourlyData
,
hourlyTimeLabels:
hourlyTimeLabels
,
zoneData:
zoneData
,
zoneData:
zoneData
,
);
);
}
}
...
...
lib/views/report/energy/cubit/energy_state.dart
View file @
1244f87e
...
@@ -25,6 +25,7 @@ class EnergyState extends Equatable {
...
@@ -25,6 +25,7 @@ class EnergyState extends Equatable {
final
double
monthBill
;
final
double
monthBill
;
final
double
hourlyMaxValue
;
final
double
hourlyMaxValue
;
final
List
<
double
>
hourlyData
;
final
List
<
double
>
hourlyData
;
final
List
<
String
>
hourlyTimeLabels
;
final
List
<
ZoneData
>
zoneData
;
final
List
<
ZoneData
>
zoneData
;
const
EnergyState
({
const
EnergyState
({
...
@@ -37,6 +38,7 @@ class EnergyState extends Equatable {
...
@@ -37,6 +38,7 @@ class EnergyState extends Equatable {
this
.
monthBill
=
6982
,
this
.
monthBill
=
6982
,
this
.
hourlyMaxValue
=
0
,
this
.
hourlyMaxValue
=
0
,
this
.
hourlyData
=
const
[],
this
.
hourlyData
=
const
[],
this
.
hourlyTimeLabels
=
const
[],
this
.
zoneData
=
const
[
this
.
zoneData
=
const
[
ZoneData
(
name:
'客房区域'
,
percentage:
68
,
energy:
873
),
ZoneData
(
name:
'客房区域'
,
percentage:
68
,
energy:
873
),
ZoneData
(
name:
'公共区域'
,
percentage:
18
,
energy:
231
),
ZoneData
(
name:
'公共区域'
,
percentage:
18
,
energy:
231
),
...
@@ -55,6 +57,7 @@ class EnergyState extends Equatable {
...
@@ -55,6 +57,7 @@ class EnergyState extends Equatable {
double
?
monthBill
,
double
?
monthBill
,
double
?
hourlyMaxValue
,
double
?
hourlyMaxValue
,
List
<
double
>?
hourlyData
,
List
<
double
>?
hourlyData
,
List
<
String
>?
hourlyTimeLabels
,
List
<
ZoneData
>?
zoneData
,
List
<
ZoneData
>?
zoneData
,
bool
clearError
=
false
,
bool
clearError
=
false
,
})
{
})
{
...
@@ -68,6 +71,7 @@ class EnergyState extends Equatable {
...
@@ -68,6 +71,7 @@ class EnergyState extends Equatable {
monthBill:
monthBill
??
this
.
monthBill
,
monthBill:
monthBill
??
this
.
monthBill
,
hourlyMaxValue:
hourlyMaxValue
??
this
.
hourlyMaxValue
,
hourlyMaxValue:
hourlyMaxValue
??
this
.
hourlyMaxValue
,
hourlyData:
hourlyData
??
this
.
hourlyData
,
hourlyData:
hourlyData
??
this
.
hourlyData
,
hourlyTimeLabels:
hourlyTimeLabels
??
this
.
hourlyTimeLabels
,
zoneData:
zoneData
??
this
.
zoneData
,
zoneData:
zoneData
??
this
.
zoneData
,
);
);
}
}
...
@@ -83,6 +87,7 @@ class EnergyState extends Equatable {
...
@@ -83,6 +87,7 @@ class EnergyState extends Equatable {
monthBill
,
monthBill
,
hourlyMaxValue
,
hourlyMaxValue
,
hourlyData
,
hourlyData
,
hourlyTimeLabels
,
zoneData
,
zoneData
,
];
];
}
}
lib/views/report/energy/energy_detail_view.dart
View file @
1244f87e
...
@@ -78,6 +78,7 @@ class ReportEnergyDetailView extends StatelessWidget {
...
@@ -78,6 +78,7 @@ class ReportEnergyDetailView extends StatelessWidget {
HourlyChartBlock
(
HourlyChartBlock
(
hourlyData:
state
.
hourlyData
,
hourlyData:
state
.
hourlyData
,
maxValue:
state
.
hourlyMaxValue
,
maxValue:
state
.
hourlyMaxValue
,
timeLabels:
state
.
hourlyTimeLabels
,
),
),
SizedBox
(
height:
16
.
h
),
SizedBox
(
height:
16
.
h
),
ZoneChartBlock
(
zoneData:
state
.
zoneData
),
ZoneChartBlock
(
zoneData:
state
.
zoneData
),
...
...
lib/views/report/energy/widget/energy_stats_card_block.dart
View file @
1244f87e
...
@@ -17,6 +17,13 @@ class EnergyStatsCardBlock extends StatelessWidget {
...
@@ -17,6 +17,13 @@ class EnergyStatsCardBlock extends StatelessWidget {
required
this
.
monthBill
,
required
this
.
monthBill
,
});
});
String
_fmt
(
double
d
)
{
if
(
d
==
d
.
truncateToDouble
())
return
d
.
truncate
().
toString
();
return
d
.
toStringAsFixed
(
2
)
.
replaceAll
(
RegExp
(
r'0+$'
),
''
)
.
replaceAll
(
RegExp
(
r'\.$'
),
''
);
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Padding
(
return
Padding
(
...
@@ -25,9 +32,9 @@ class EnergyStatsCardBlock extends StatelessWidget {
...
@@ -25,9 +32,9 @@ class EnergyStatsCardBlock extends StatelessWidget {
children:
[
children:
[
Expanded
(
Expanded
(
child:
_buildCard
(
child:
_buildCard
(
'
${todayEnergy.toInt()}
'
,
_fmt
(
todayEnergy
)
,
'今日(kwh)'
,
'今日(kwh)'
,
'
${
todayEnergyChange.toInt(
)}
%'
,
'
${
_fmt(todayEnergyChange
)}
%'
,
true
,
true
,
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
),
),
...
@@ -35,9 +42,9 @@ class EnergyStatsCardBlock extends StatelessWidget {
...
@@ -35,9 +42,9 @@ class EnergyStatsCardBlock extends StatelessWidget {
SizedBox
(
width:
12
.
w
),
SizedBox
(
width:
12
.
w
),
Expanded
(
Expanded
(
child:
_buildCard
(
child:
_buildCard
(
'
${monthEnergy.toInt()}
'
,
_fmt
(
monthEnergy
)
,
'本月(kWh)'
,
'本月(kWh)'
,
'
${
monthEnergyChange.toInt(
)}
%'
,
'
${
_fmt(monthEnergyChange
)}
%'
,
true
,
true
,
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
),
),
...
@@ -45,7 +52,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
...
@@ -45,7 +52,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
SizedBox
(
width:
12
.
w
),
SizedBox
(
width:
12
.
w
),
Expanded
(
Expanded
(
child:
_buildCard
(
child:
_buildCard
(
'¥
${
monthBill.toInt(
)}
'
,
'¥
${
_fmt(monthBill
)}
'
,
'本月电费预估'
,
'本月电费预估'
,
null
,
null
,
null
,
null
,
...
@@ -59,7 +66,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
...
@@ -59,7 +66,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
Widget
_buildCard
(
String
value
,
String
label
,
String
?
change
,
bool
?
isDown
,
Color
valueColor
)
{
Widget
_buildCard
(
String
value
,
String
label
,
String
?
change
,
bool
?
isDown
,
Color
valueColor
)
{
return
Container
(
return
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
24
.
h
,
horizontal:
16
.
w
),
padding:
EdgeInsets
.
symmetric
(
vertical:
24
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
Colors
.
white
,
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
20
.
r
),
borderRadius:
BorderRadius
.
circular
(
20
.
r
),
...
@@ -73,6 +80,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
...
@@ -73,6 +80,7 @@ class EnergyStatsCardBlock extends StatelessWidget {
fontSize:
40
.
sp
,
fontSize:
40
.
sp
,
fontWeight:
FontWeight
.
w500
,
fontWeight:
FontWeight
.
w500
,
),
),
textAlign:
TextAlign
.
center
,
),
),
SizedBox
(
height:
4
.
h
),
SizedBox
(
height:
4
.
h
),
Text
(
Text
(
...
...
lib/views/report/energy/widget/hourly_chart_block.dart
View file @
1244f87e
...
@@ -5,27 +5,42 @@ import 'package:fl_chart/fl_chart.dart';
...
@@ -5,27 +5,42 @@ import 'package:fl_chart/fl_chart.dart';
class
HourlyChartBlock
extends
StatelessWidget
{
class
HourlyChartBlock
extends
StatelessWidget
{
final
List
<
double
>
hourlyData
;
final
List
<
double
>
hourlyData
;
final
double
maxValue
;
final
double
maxValue
;
final
List
<
String
>
timeLabels
;
const
HourlyChartBlock
({
const
HourlyChartBlock
({
super
.
key
,
super
.
key
,
required
this
.
hourlyData
,
required
this
.
hourlyData
,
required
this
.
maxValue
,
required
this
.
maxValue
,
required
this
.
timeLabels
,
});
});
double
get
_chartMaxY
{
double
get
_chartMaxY
{
final
dataMaxValue
=
maxValue
>
0
?
maxValue
:
0.0
;
final
listMax
=
final
listMaxValue
=
hourlyData
.
isEmpty
?
0.0
:
hourlyData
.
reduce
((
a
,
b
)
=>
a
>
b
?
a
:
b
);
hourlyData
.
isEmpty
?
0.0
:
hourlyData
.
reduce
((
a
,
b
)
=>
a
>
b
?
a
:
b
);
final
chartMaxValue
=
final
raw
=
maxValue
>
listMax
?
maxValue
:
listMax
;
dataMaxValue
>
listMaxValue
?
dataMaxValue
:
listMaxValue
;
if
(
raw
<=
0
)
return
100
;
if
(
chartMaxValue
<=
0
)
{
// 留 10% 余量
return
100
;
return
raw
*
1.1
;
}
return
chartMaxValue
*
1.2
;
}
}
double
get
_chartInterval
=>
_chartMaxY
/
5
;
double
get
_chartInterval
=>
_chartMaxY
/
5
;
double
get
_bottomInterval
{
final
len
=
hourlyData
.
length
;
if
(
len
<=
1
)
return
1
;
// 最多显示约 5 个标签,按间距计算
return
(
len
/
5
).
ceilToDouble
();
}
String
_formatTimeLabel
(
int
index
)
{
if
(
index
<
0
||
index
>=
timeLabels
.
length
)
return
''
;
final
label
=
timeLabels
[
index
];
// "00:00:00" / "00:00" → 只取整点小时,去掉前导 0
final
parts
=
label
.
split
(
':'
);
final
hour
=
parts
.
isNotEmpty
?
parts
[
0
]
:
label
;
return
'
${int.tryParse(hour) ?? 0}
'
;
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Container
(
return
Container
(
...
@@ -41,18 +56,19 @@ class HourlyChartBlock extends StatelessWidget {
...
@@ -41,18 +56,19 @@ class HourlyChartBlock extends StatelessWidget {
Text
(
Text
(
'今日逐时用电'
,
'今日逐时用电'
,
style:
TextStyle
(
style:
TextStyle
(
color:
Colors
.
black87
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
)
,
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
fontWeight:
FontWeight
.
w500
,
fontWeight:
FontWeight
.
w500
,
),
),
),
),
SizedBox
(
height:
10
0
.
h
),
SizedBox
(
height:
2
0
.
h
),
SizedBox
(
SizedBox
(
height:
200
.
h
,
height:
200
.
h
,
child:
BarChart
(
child:
BarChart
(
BarChartData
(
BarChartData
(
alignment:
BarChartAlignment
.
spaceAround
,
alignment:
BarChartAlignment
.
spaceBetween
,
maxY:
_chartMaxY
,
maxY:
_chartMaxY
,
minY:
0
,
barTouchData:
BarTouchData
(
enabled:
false
),
barTouchData:
BarTouchData
(
enabled:
false
),
titlesData:
FlTitlesData
(
titlesData:
FlTitlesData
(
show:
true
,
show:
true
,
...
@@ -65,15 +81,37 @@ class HourlyChartBlock extends StatelessWidget {
...
@@ -65,15 +81,37 @@ class HourlyChartBlock extends StatelessWidget {
bottomTitles:
AxisTitles
(
bottomTitles:
AxisTitles
(
sideTitles:
SideTitles
(
sideTitles:
SideTitles
(
showTitles:
true
,
showTitles:
true
,
interval:
_bottomInterval
,
reservedSize:
30
,
reservedSize:
30
,
getTitlesWidget:
_getBottomTitleWidget
,
getTitlesWidget:
(
value
,
meta
)
{
final
label
=
_formatTimeLabel
(
value
.
toInt
());
return
Padding
(
padding:
EdgeInsets
.
only
(
top:
8
.
h
),
child:
Text
(
label
,
style:
TextStyle
(
fontSize:
20
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
);
},
),
),
),
),
leftTitles:
AxisTitles
(
leftTitles:
AxisTitles
(
sideTitles:
SideTitles
(
sideTitles:
SideTitles
(
showTitles:
true
,
showTitles:
true
,
reservedSize:
40
,
interval:
_chartInterval
,
getTitlesWidget:
_getLeftTitleWidget
,
reservedSize:
55
,
getTitlesWidget:
(
value
,
meta
)
{
return
Text
(
'
${value.toInt()}
'
,
style:
TextStyle
(
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
fontSize:
20
.
sp
,
),
);
},
),
),
),
),
),
),
...
@@ -84,8 +122,8 @@ class HourlyChartBlock extends StatelessWidget {
...
@@ -84,8 +122,8 @@ class HourlyChartBlock extends StatelessWidget {
horizontalInterval:
_chartInterval
,
horizontalInterval:
_chartInterval
,
getDrawingHorizontalLine:
(
value
)
{
getDrawingHorizontalLine:
(
value
)
{
return
const
FlLine
(
return
const
FlLine
(
color:
Color
.
fromRGBO
(
200
,
200
,
200
,
1
),
color:
Color
.
fromRGBO
(
209
,
213
,
219
,
1
),
strokeWidth:
1
,
strokeWidth:
1.5
,
dashArray:
[
5
,
5
],
dashArray:
[
5
,
5
],
);
);
},
},
...
@@ -99,48 +137,11 @@ class HourlyChartBlock extends StatelessWidget {
...
@@ -99,48 +137,11 @@ 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.toString().padLeft(2, '0')}
:00'
;
}
}
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
,
);
final
text
=
value
%
_chartInterval
==
0
?
value
.
toStringAsFixed
(
value
.
truncateToDouble
()
==
value
?
0
:
1
)
:
''
;
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
;
final
value
=
entry
.
value
;
final
value
=
entry
.
value
;
if
(
value
==
0
)
return
BarChartGroupData
(
x:
index
);
return
BarChartGroupData
(
return
BarChartGroupData
(
x:
index
,
x:
index
,
barRods:
[
barRods:
[
...
...
lib/views/report/energy/widget/zone_chart_block.dart
View file @
1244f87e
...
@@ -22,7 +22,7 @@ class ZoneChartBlock extends StatelessWidget {
...
@@ -22,7 +22,7 @@ class ZoneChartBlock extends StatelessWidget {
Text
(
Text
(
'分区用电占比'
,
'分区用电占比'
,
style:
TextStyle
(
style:
TextStyle
(
color:
Colors
.
black87
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
)
,
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
fontWeight:
FontWeight
.
w500
,
fontWeight:
FontWeight
.
w500
,
),
),
...
@@ -49,7 +49,7 @@ class ZoneChartBlock extends StatelessWidget {
...
@@ -49,7 +49,7 @@ class ZoneChartBlock extends StatelessWidget {
color:
index
==
0
color:
index
==
0
?
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
?
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
borderRadius:
BorderRadius
.
circular
(
3
.
r
)
,
shape:
BoxShape
.
circle
,
),
),
),
),
SizedBox
(
width:
8
.
w
),
SizedBox
(
width:
8
.
w
),
...
...
lib/views/report/index/cubit/report_index_cubit.dart
View file @
1244f87e
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:fl_chart/fl_chart.dart'
;
import
'package:smart_hotel_app/models/bo/dashboard_bo.dart'
;
import
'package:smart_hotel_app/models/bo/dashboard_bo.dart'
;
import
'package:smart_hotel_app/repositories/dashboard_repository.dart'
;
import
'package:smart_hotel_app/repositories/dashboard_repository.dart'
;
import
'package:smart_hotel_app/services/dashboard_service.dart'
;
import
'package:smart_hotel_app/services/dashboard_service.dart'
;
...
@@ -29,10 +30,9 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
...
@@ -29,10 +30,9 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
}
}
ReportIndexState
_mapOverviewToState
(
DashboardOverviewBO
overview
)
{
ReportIndexState
_mapOverviewToState
(
DashboardOverviewBO
overview
)
{
// 今日用电指标
// 今日用电
final
elec
=
overview
.
electricityToday
;
final
yesterdayVal
=
overview
.
electricityToday
.
yesterdayValue
;
final
yesterdayVal
=
elec
.
yesterdayValue
;
final
todayVal
=
overview
.
electricityToday
.
value
;
final
todayVal
=
elec
.
value
;
double
changePercent
=
0
;
double
changePercent
=
0
;
if
(
yesterdayVal
>
0
)
{
if
(
yesterdayVal
>
0
)
{
changePercent
=
((
todayVal
-
yesterdayVal
)
/
yesterdayVal
*
100
);
changePercent
=
((
todayVal
-
yesterdayVal
)
/
yesterdayVal
*
100
);
...
@@ -40,6 +40,10 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
...
@@ -40,6 +40,10 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
final
isDown
=
changePercent
<=
0
;
final
isDown
=
changePercent
<=
0
;
final
changeAbs
=
changePercent
.
abs
().
round
();
final
changeAbs
=
changePercent
.
abs
().
round
();
//待处理告警
final
count
=
overview
.
alertPending
.
count
;
final
todayTotal
=
overview
.
alertPending
.
todayTotal
;
return
state
.
copyWith
(
return
state
.
copyWith
(
isLoading:
false
,
isLoading:
false
,
reportHeader:
{
reportHeader:
{
...
@@ -48,25 +52,30 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
...
@@ -48,25 +52,30 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
},
},
reportMetrics:
{
reportMetrics:
{
'powerUsage'
:
{
'powerUsage'
:
{
'value'
:
todayVal
.
to
Int
(),
'value'
:
todayVal
.
to
String
(),
'unit'
:
'kWh'
,
'unit'
:
'kWh'
,
'change'
:
isDown
?
-
changeAbs
:
changeAbs
,
'change'
:
isDown
?
-
changeAbs
:
changeAbs
,
'changeText'
:
isDown
?
'↓
$changeAbs
%'
:
'↑
$changeAbs
%'
,
'changeText'
:
isDown
?
'↓
$changeAbs
%'
:
'↑
$changeAbs
%'
,
'progress'
:
(
todayVal
/
2000
).
clamp
(
0.0
,
1.0
),
'progress'
:
(
todayVal
/
yesterdayVal
).
clamp
(
0.0
,
1.0
),
},
},
'pendingAlerts'
:
{
'pendingAlerts'
:
{
'value'
:
overview
.
alertPending
.
count
,
'value'
:
count
.
toString
()
,
'unit'
:
'条'
,
'unit'
:
'条'
,
'change'
:
null
,
'change'
:
null
,
'changeText'
:
overview
.
alertPending
.
count
>
0
?
'需关注'
:
'无告警'
,
'changeText'
:
count
>
0
?
'需关注'
:
'无告警'
,
'progress'
:
(
overview
.
alertPending
.
count
/
10
).
clamp
(
0.0
,
1.0
),
'progress'
:
(
count
/
todayTotal
).
clamp
(
0.0
,
1.0
),
},
},
},
},
weeklyPowerUsage:
{
weeklyPowerUsage:
{
'title'
:
'本周用电趋势'
,
'title'
:
'本周用电趋势'
,
'unit'
:
'kWh'
,
'unit'
:
'kWh'
,
'dateRange'
:
overview
.
electricityTrend
.
dateRange
,
'dateRange'
:
overview
.
electricityTrend
.
dateRange
,
'data'
:
_mapWeekDays
(
overview
.
electricityTrend
.
points
),
'maxValue'
:
overview
.
electricityTrend
.
maxValue
,
'spots'
:
_buildSpots
(
overview
.
electricityTrend
.
points
),
'timeLabels'
:
overview
.
electricityTrend
.
points
.
map
((
p
)
{
// "06-10 19:21:47" → "06-10"
return
p
.
time
.
split
(
' '
).
first
;
}).
toList
(),
},
},
roomStatusDistribution:
{
roomStatusDistribution:
{
'title'
:
'客房状态分布'
,
'title'
:
'客房状态分布'
,
...
@@ -76,7 +85,7 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
...
@@ -76,7 +85,7 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
deviceOnlineRate:
{
deviceOnlineRate:
{
'title'
:
'设备在线率'
,
'title'
:
'设备在线率'
,
'rate'
:
1.0
,
'rate'
:
1.0
,
'rateText'
:
'
${overview.deviceTypeDistribution.totalDeviceCount}
台
'
,
'rateText'
:
'
${overview.deviceTypeDistribution.totalDeviceCount}
'
,
'devices'
:
_mapDeviceTypes
(
overview
.
deviceTypeDistribution
.
items
),
'devices'
:
_mapDeviceTypes
(
overview
.
deviceTypeDistribution
.
items
),
},
},
quickActions:
{
quickActions:
{
...
@@ -89,26 +98,19 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
...
@@ -89,26 +98,19 @@ class ReportIndexCubit extends Cubit<ReportIndexState> {
);
);
}
}
/// 将趋势点映射为周几标签
List
<
FlSpot
>
_buildSpots
(
List
<
DashboardTrendPointBO
>
points
)
{
List
<
Map
<
String
,
dynamic
>>
_mapWeekDays
(
List
<
DashboardTrendPointBO
>
points
)
{
const
dayLabels
=
[
'一'
,
'二'
,
'三'
,
'四'
,
'五'
,
'六'
,
'日'
];
return
points
.
asMap
().
entries
.
map
((
entry
)
{
return
points
.
asMap
().
entries
.
map
((
entry
)
{
final
index
=
entry
.
key
;
return
FlSpot
(
entry
.
key
.
toDouble
(),
entry
.
value
.
value
);
final
point
=
entry
.
value
;
return
{
'day'
:
index
<
dayLabels
.
length
?
dayLabels
[
index
]
:
'
${index + 1}
'
,
'value'
:
point
.
value
.
toInt
(),
};
}).
toList
();
}).
toList
();
}
}
/// 映射客房状态并分配颜色
/// 映射客房状态并分配颜色
List
<
Map
<
String
,
dynamic
>>
_mapRoomStatuses
(
List
<
RoomStatusItemBO
>
items
)
{
List
<
Map
<
String
,
dynamic
>>
_mapRoomStatuses
(
List
<
RoomStatusItemBO
>
items
)
{
const
statusColors
=
[
const
statusColors
=
[
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
Color
.
fromRGBO
(
73
,
149
,
234
,
1
),
Color
.
fromRGBO
(
1
48
,
163
,
184
,
1
),
Color
.
fromRGBO
(
1
00
,
116
,
139
,
1
),
Color
.
fromRGBO
(
96
,
165
,
250
,
1
),
Color
.
fromRGBO
(
139
,
193
,
255
,
1
),
Color
.
fromRGBO
(
2
49
,
115
,
22
,
1
),
Color
.
fromRGBO
(
2
50
,
204
,
21
,
1
),
];
];
return
items
.
asMap
().
entries
.
map
((
entry
)
{
return
items
.
asMap
().
entries
.
map
((
entry
)
{
final
index
=
entry
.
key
;
final
index
=
entry
.
key
;
...
...
lib/views/report/index/widget/device_online_rate.dart
View file @
1244f87e
...
@@ -46,15 +46,15 @@ class DeviceOnlineRate extends StatelessWidget {
...
@@ -46,15 +46,15 @@ class DeviceOnlineRate extends StatelessWidget {
Row
(
Row
(
children:
[
children:
[
Text
(
Text
(
'共
$totalDevices
台'
,
'共
$totalDevices
台'
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
2
2
.
sp
,
fontSize:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
),
),
SizedBox
(
width:
8
.
w
),
SizedBox
(
width:
8
.
w
),
Icon
(
Icon
(
Icons
.
chevron_right
,
Icons
.
arrow_forward_ios
,
size:
24
.
sp
,
size:
24
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
...
@@ -76,9 +76,9 @@ class DeviceOnlineRate extends StatelessWidget {
...
@@ -76,9 +76,9 @@ class DeviceOnlineRate extends StatelessWidget {
sections:
[
sections:
[
PieChartSectionData
(
PieChartSectionData
(
value:
rate
,
value:
rate
,
color:
const
Color
.
fromRGBO
(
34
,
197
,
94
,
1
),
color:
const
Color
.
fromRGBO
(
49
,
193
,
177
,
1
),
title:
''
,
title:
''
,
radius:
3
0
.
w
,
radius:
2
0
.
w
,
),
),
PieChartSectionData
(
PieChartSectionData
(
// value: 1 - rate,
// value: 1 - rate,
...
@@ -97,7 +97,7 @@ class DeviceOnlineRate extends StatelessWidget {
...
@@ -97,7 +97,7 @@ class DeviceOnlineRate extends StatelessWidget {
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
bold
,
color:
const
Color
.
fromRGBO
(
31
,
41
,
55
,
1
),
color:
const
Color
.
fromRGBO
(
20
,
184
,
166
,
1
),
),
),
),
),
],
],
...
...
lib/views/report/index/widget/quick_actions_block.dart
View file @
1244f87e
...
@@ -49,7 +49,7 @@ class QuickActionsBlock extends StatelessWidget {
...
@@ -49,7 +49,7 @@ class QuickActionsBlock extends StatelessWidget {
children:
[
children:
[
Container
(
Container
(
width:
80
.
w
,
width:
80
.
w
,
height:
80
.
h
,
height:
64
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
239
,
246
,
255
,
1
),
color:
const
Color
.
fromRGBO
(
239
,
246
,
255
,
1
),
borderRadius:
BorderRadius
.
circular
(
16
.
r
),
borderRadius:
BorderRadius
.
circular
(
16
.
r
),
...
...
lib/views/report/index/widget/report_header_block.dart
View file @
1244f87e
...
@@ -15,7 +15,7 @@ class ReportHeaderBlock extends StatelessWidget {
...
@@ -15,7 +15,7 @@ class ReportHeaderBlock extends StatelessWidget {
reportHeader
[
'title'
]
as
String
,
reportHeader
[
'title'
]
as
String
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
36
.
sp
,
fontSize:
36
.
sp
,
fontWeight:
FontWeight
.
normal
,
fontWeight:
FontWeight
.
w500
,
color:
const
Color
.
fromRGBO
(
71
,
71
,
71
,
1
),
color:
const
Color
.
fromRGBO
(
71
,
71
,
71
,
1
),
),
),
),
),
...
...
lib/views/report/index/widget/report_metrics_block.dart
View file @
1244f87e
...
@@ -19,9 +19,10 @@ class ReportMetricsBlock extends StatelessWidget {
...
@@ -19,9 +19,10 @@ class ReportMetricsBlock extends StatelessWidget {
value:
powerUsage
[
'value'
],
value:
powerUsage
[
'value'
],
unit:
powerUsage
[
'unit'
]
as
String
,
unit:
powerUsage
[
'unit'
]
as
String
,
changeText:
powerUsage
[
'changeText'
]
as
String
,
changeText:
powerUsage
[
'changeText'
]
as
String
,
changeColor:
const
Color
.
fromRGBO
(
16
,
185
,
129
,
1
),
changeColor:
const
Color
.
fromRGBO
(
20
,
184
,
166
,
1
),
valueColor:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
),
progress:
powerUsage
[
'progress'
]
as
double
,
progress:
powerUsage
[
'progress'
]
as
double
,
progressColor:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
progressColor:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
),
),
),
),
),
SizedBox
(
width:
20
.
w
),
SizedBox
(
width:
20
.
w
),
...
@@ -31,9 +32,10 @@ class ReportMetricsBlock extends StatelessWidget {
...
@@ -31,9 +32,10 @@ class ReportMetricsBlock extends StatelessWidget {
value:
pendingAlerts
[
'value'
],
value:
pendingAlerts
[
'value'
],
unit:
pendingAlerts
[
'unit'
]
as
String
,
unit:
pendingAlerts
[
'unit'
]
as
String
,
changeText:
pendingAlerts
[
'changeText'
]
as
String
,
changeText:
pendingAlerts
[
'changeText'
]
as
String
,
changeColor:
const
Color
.
fromRGBO
(
251
,
191
,
36
,
1
),
changeColor:
const
Color
.
fromRGBO
(
250
,
204
,
21
,
1
),
valueColor:
const
Color
.
fromRGBO
(
250
,
204
,
21
,
1
),
progress:
pendingAlerts
[
'progress'
]
as
double
,
progress:
pendingAlerts
[
'progress'
]
as
double
,
progressColor:
const
Color
.
fromRGBO
(
25
1
,
191
,
36
,
1
),
progressColor:
const
Color
.
fromRGBO
(
25
0
,
204
,
21
,
1
),
),
),
),
),
],
],
...
@@ -42,10 +44,11 @@ class ReportMetricsBlock extends StatelessWidget {
...
@@ -42,10 +44,11 @@ class ReportMetricsBlock extends StatelessWidget {
Widget
_buildMetricCard
({
Widget
_buildMetricCard
({
required
String
title
,
required
String
title
,
required
int
value
,
required
String
value
,
required
String
unit
,
required
String
unit
,
required
String
changeText
,
required
String
changeText
,
required
Color
changeColor
,
required
Color
changeColor
,
required
Color
valueColor
,
required
double
progress
,
required
double
progress
,
required
Color
progressColor
,
required
Color
progressColor
,
})
{
})
{
...
@@ -58,6 +61,9 @@ class ReportMetricsBlock extends StatelessWidget {
...
@@ -58,6 +61,9 @@ class ReportMetricsBlock extends StatelessWidget {
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Text
(
Text
(
title
,
title
,
style:
TextStyle
(
style:
TextStyle
(
...
@@ -65,16 +71,25 @@ class ReportMetricsBlock extends StatelessWidget {
...
@@ -65,16 +71,25 @@ class ReportMetricsBlock extends StatelessWidget {
color:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
color:
const
Color
.
fromRGBO
(
107
,
114
,
128
,
1
),
),
),
),
),
Text
(
changeText
,
style:
TextStyle
(
fontSize:
24
.
sp
,
color:
changeColor
,
),
),
],
),
SizedBox
(
height:
12
.
h
),
SizedBox
(
height:
12
.
h
),
Row
(
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
crossAxisAlignment:
CrossAxisAlignment
.
end
,
children:
[
children:
[
Text
(
Text
(
'
$value
'
,
value
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
40
.
sp
,
fontSize:
40
.
sp
,
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
bold
,
color:
const
Color
.
fromRGBO
(
31
,
41
,
55
,
1
)
,
color:
valueColor
,
),
),
),
),
SizedBox
(
width:
4
.
w
),
SizedBox
(
width:
4
.
w
),
...
@@ -90,18 +105,6 @@ class ReportMetricsBlock extends StatelessWidget {
...
@@ -90,18 +105,6 @@ class ReportMetricsBlock extends StatelessWidget {
),
),
],
],
),
),
SizedBox
(
height:
8
.
h
),
Row
(
children:
[
Text
(
changeText
,
style:
TextStyle
(
fontSize:
20
.
sp
,
color:
changeColor
,
),
),
],
),
SizedBox
(
height:
12
.
h
),
SizedBox
(
height:
12
.
h
),
ClipRRect
(
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
4
.
r
),
borderRadius:
BorderRadius
.
circular
(
4
.
r
),
...
...
lib/views/report/index/widget/room_status_distribution.dart
View file @
1244f87e
...
@@ -43,16 +43,16 @@ class RoomStatusDistribution extends StatelessWidget {
...
@@ -43,16 +43,16 @@ class RoomStatusDistribution extends StatelessWidget {
Row
(
Row
(
children:
[
children:
[
Text
(
Text
(
'共
$totalRooms
间'
,
'共
$totalRooms
间'
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
2
2
.
sp
,
fontSize:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
),
),
SizedBox
(
width:
8
.
w
),
SizedBox
(
width:
8
.
w
),
Icon
(
Icon
(
Icons
.
arrow_forward_ios
,
Icons
.
arrow_forward_ios
,
size:
2
0
.
sp
,
size:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
],
],
...
@@ -65,6 +65,7 @@ class RoomStatusDistribution extends StatelessWidget {
...
@@ -65,6 +65,7 @@ class RoomStatusDistribution extends StatelessWidget {
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
;
final
percentText
=
'
${(percentage * 100).toInt()}
%'
;
return
Padding
(
return
Padding
(
padding:
EdgeInsets
.
only
(
bottom:
16
.
h
),
padding:
EdgeInsets
.
only
(
bottom:
16
.
h
),
...
@@ -95,10 +96,10 @@ class RoomStatusDistribution extends StatelessWidget {
...
@@ -95,10 +96,10 @@ class RoomStatusDistribution extends StatelessWidget {
],
],
),
),
Text
(
Text
(
'
$count
间
'
,
'
$count
间(
$percentText
)
'
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
24
.
sp
,
fontSize:
24
.
sp
,
color:
co
nst
Color
.
fromRGBO
(
55
,
65
,
81
,
1
)
,
color:
co
lor
,
),
),
),
),
],
],
...
...
lib/views/report/index/widget/weekly_power_chart.dart
View file @
1244f87e
...
@@ -9,17 +9,51 @@ class WeeklyPowerChart extends StatelessWidget {
...
@@ -9,17 +9,51 @@ class WeeklyPowerChart extends StatelessWidget {
const
WeeklyPowerChart
({
super
.
key
,
required
this
.
weeklyPowerUsage
});
const
WeeklyPowerChart
({
super
.
key
,
required
this
.
weeklyPowerUsage
});
List
<
FlSpot
>
get
_spots
=>
(
weeklyPowerUsage
[
'spots'
]
as
List
<
dynamic
>?)?.
cast
<
FlSpot
>()
??
[];
List
<
String
>
get
_timeLabels
=>
(
weeklyPowerUsage
[
'timeLabels'
]
as
List
<
dynamic
>?)?.
cast
<
String
>()
??
[];
double
get
_minX
=>
0
;
double
get
_maxX
=>
_spots
.
length
>
1
?
(
_spots
.
length
-
1
).
toDouble
()
:
1
;
double
get
_minY
=>
0
;
double
get
_maxY
{
final
raw
=
(
weeklyPowerUsage
[
'maxValue'
]
as
num
?)?.
toDouble
()
??
100
;
// 留 10% 余量,防止顶部标签贴边
return
raw
*
1.1
;
}
double
get
_horizontalInterval
=>
_maxY
/
5
;
double
get
_bottomInterval
{
final
len
=
_spots
.
length
;
if
(
len
<=
1
)
return
1
;
if
(
len
<=
6
)
return
1
;
if
(
len
<=
12
)
return
2
;
return
(
len
-
1
)
/
4
;
}
String
_formatBottomTitle
(
double
value
)
{
final
index
=
value
.
toInt
();
if
(
index
<
0
||
index
>=
_timeLabels
.
length
)
return
''
;
return
_timeLabels
[
index
];
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
data
=
weeklyPowerUsage
[
'data'
]
as
List
<
Map
<
String
,
dynamic
>>;
return
GestureDetector
(
return
GestureDetector
(
onTap:
()
{
onTap:
()
{
context
.
pushRoute
(
const
ReportEnergyDetailRoute
());
context
.
pushRoute
(
const
ReportEnergyDetailRoute
());
},
},
child:
Container
(
child:
Container
(
width:
double
.
infinity
,
width:
double
.
infinity
,
padding:
EdgeInsets
.
all
(
28
.
w
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
,
vertical:
28
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
24
.
r
),
borderRadius:
BorderRadius
.
circular
(
24
.
r
),
color:
Colors
.
white
,
color:
Colors
.
white
,
...
@@ -41,16 +75,16 @@ class WeeklyPowerChart extends StatelessWidget {
...
@@ -41,16 +75,16 @@ class WeeklyPowerChart extends StatelessWidget {
Row
(
Row
(
children:
[
children:
[
Text
(
Text
(
weeklyPowerUsage
[
'dateRange'
]
as
String
,
weeklyPowerUsage
[
'dateRange'
]
as
String
?
??
''
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
2
2
.
sp
,
fontSize:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
),
),
SizedBox
(
width:
8
.
w
),
SizedBox
(
width:
8
.
w
),
Icon
(
Icon
(
Icons
.
arrow_forward_ios
,
Icons
.
arrow_forward_ios
,
size:
2
0
.
sp
,
size:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
],
],
...
@@ -58,15 +92,25 @@ class WeeklyPowerChart extends StatelessWidget {
...
@@ -58,15 +92,25 @@ class WeeklyPowerChart extends StatelessWidget {
],
],
),
),
SizedBox
(
height:
20
.
h
),
SizedBox
(
height:
20
.
h
),
SizedBox
(
Container
(
height:
200
.
h
,
height:
200
.
h
,
child:
BarChart
(
padding:
EdgeInsets
.
only
(
right:
28
.
w
),
BarChartData
(
child:
LineChart
(
alignment:
BarChartAlignment
.
spaceBetween
,
LineChartData
(
maxY:
300
,
gridData:
FlGridData
(
barTouchData:
BarTouchData
(
enabled:
false
),
titlesData:
FlTitlesData
(
show:
true
,
show:
true
,
drawHorizontalLine:
true
,
drawVerticalLine:
false
,
horizontalInterval:
_horizontalInterval
,
getDrawingHorizontalLine:
(
value
)
{
return
const
FlLine
(
color:
Color
.
fromRGBO
(
209
,
213
,
219
,
1
),
strokeWidth:
2
,
dashArray:
[
5
,
5
],
);
},
),
titlesData:
FlTitlesData
(
rightTitles:
const
AxisTitles
(
rightTitles:
const
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
),
sideTitles:
SideTitles
(
showTitles:
false
),
),
),
...
@@ -76,49 +120,65 @@ class WeeklyPowerChart extends StatelessWidget {
...
@@ -76,49 +120,65 @@ class WeeklyPowerChart extends StatelessWidget {
bottomTitles:
AxisTitles
(
bottomTitles:
AxisTitles
(
sideTitles:
SideTitles
(
sideTitles:
SideTitles
(
showTitles:
true
,
showTitles:
true
,
reservedSize:
28
,
interval:
_bottomInterval
,
getTitlesWidget:
(
value
,
meta
)
{
getTitlesWidget:
(
value
,
meta
)
{
final
index
=
value
.
toInt
();
if
(
index
>=
0
&&
index
<
data
.
length
)
{
return
Padding
(
return
Padding
(
padding:
EdgeInsets
.
only
(
top:
8
.
h
),
padding:
EdgeInsets
.
only
(
top:
8
.
h
),
child:
Text
(
child:
Text
(
data
[
index
][
'day'
]
as
String
,
_formatBottomTitle
(
value
)
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
22
.
sp
,
fontSize:
22
.
sp
,
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
),
),
);
);
}
return
const
SizedBox
.
shrink
();
},
},
reservedSize:
28
,
),
),
),
),
leftTitles:
const
AxisTitles
(
leftTitles:
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
),
sideTitles:
SideTitles
(
showTitles:
true
,
interval:
_horizontalInterval
,
getTitlesWidget:
(
value
,
meta
)
{
return
Text
(
'
${value.toInt()}
'
,
style:
TextStyle
(
color:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
fontSize:
22
.
sp
,
),
);
},
reservedSize:
50
,
),
),
),
),
),
borderData:
FlBorderData
(
show:
false
),
borderData:
FlBorderData
(
show:
false
),
gridData:
const
FlGridData
(
show:
false
),
minX:
_minX
,
barGroups:
data
.
asMap
().
entries
.
map
((
entry
)
{
maxX:
_maxX
,
final
index
=
entry
.
key
;
minY:
_minY
,
final
value
=
(
entry
.
value
[
'value'
]
as
int
).
toDouble
();
maxY:
_maxY
,
return
BarChartGroupData
(
lineBarsData:
[
x:
index
,
LineChartBarData
(
barRods:
[
spots:
_spots
,
BarChartRodData
(
isCurved:
true
,
toY:
value
,
color:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
color:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
width:
24
.
w
,
barWidth:
3
,
borderRadius:
const
BorderRadius
.
only
(
isStrokeCapRound:
true
,
topLeft:
Radius
.
circular
(
4
),
dotData:
const
FlDotData
(
show:
false
),
topRight:
Radius
.
circular
(
4
),
belowBarData:
BarAreaData
(
show:
true
,
gradient:
const
LinearGradient
(
colors:
[
Color
.
fromRGBO
(
191
,
219
,
254
,
1
),
Color
.
fromRGBO
(
219
,
234
,
254
,
0.1
),
],
begin:
Alignment
.
topCenter
,
end:
Alignment
.
bottomCenter
,
),
),
),
),
),
],
],
);
}).
toList
(),
),
),
),
),
),
),
...
...
lib/views/report/room/widget/floor_selector.dart
View file @
1244f87e
...
@@ -17,16 +17,13 @@ class FloorSelector extends StatelessWidget {
...
@@ -17,16 +17,13 @@ class FloorSelector extends StatelessWidget {
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Container
(
return
Container
(
width:
double
.
infinity
,
width:
double
.
infinity
,
child:
SingleChildScrollView
(
padding:
EdgeInsets
.
symmetric
(
vertical:
20
.
h
),
scrollDirection:
Axis
.
horizontal
,
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
,
vertical:
16
.
h
),
child:
Row
(
child:
Row
(
children:
floorNames
.
asMap
().
entries
.
map
((
entry
)
{
children:
floorNames
.
asMap
().
entries
.
map
((
entry
)
{
final
index
=
entry
.
key
;
final
index
=
entry
.
key
;
final
name
=
entry
.
value
;
final
name
=
entry
.
value
;
final
isSelected
=
index
==
selectedIndex
;
final
isSelected
=
index
==
selectedIndex
;
return
Padding
(
return
Expanded
(
padding:
EdgeInsets
.
only
(
right:
32
.
w
),
child:
GestureDetector
(
child:
GestureDetector
(
onTap:
()
{
onTap:
()
{
context
.
read
<
RoomReportCubit
>().
selectFloor
(
index
);
context
.
read
<
RoomReportCubit
>().
selectFloor
(
index
);
...
@@ -38,18 +35,18 @@ class FloorSelector extends StatelessWidget {
...
@@ -38,18 +35,18 @@ class FloorSelector extends StatelessWidget {
style:
TextStyle
(
style:
TextStyle
(
fontSize:
28
.
sp
,
fontSize:
28
.
sp
,
color:
isSelected
color:
isSelected
?
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
?
const
Color
.
fromRGBO
(
80
,
162
,
255
,
1
)
:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
:
const
Color
.
fromRGBO
(
10
,
13
,
20
,
1
),
fontWeight:
isSelected
?
FontWeight
.
bold
:
FontWeight
.
normal
,
fontWeight:
isSelected
?
FontWeight
.
w500
:
FontWeight
.
normal
,
),
),
),
),
SizedBox
(
height:
4
.
h
),
SizedBox
(
height:
4
.
h
),
Container
(
Container
(
width:
4
0
.
w
,
width:
5
0
.
w
,
height:
3
.
h
,
height:
3
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
isSelected
color:
isSelected
?
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
)
?
const
Color
.
fromRGBO
(
80
,
162
,
255
,
1
)
:
Colors
.
transparent
,
:
Colors
.
transparent
,
borderRadius:
BorderRadius
.
circular
(
2
.
r
),
borderRadius:
BorderRadius
.
circular
(
2
.
r
),
),
),
...
@@ -60,7 +57,7 @@ class FloorSelector extends StatelessWidget {
...
@@ -60,7 +57,7 @@ class FloorSelector extends StatelessWidget {
);
);
}).
toList
(),
}).
toList
(),
),
),
),
);
);
}
}
}
}
lib/views/report/room/widget/room_detail_card.dart
View file @
1244f87e
...
@@ -20,10 +20,11 @@ class RoomDetailCard extends StatelessWidget {
...
@@ -20,10 +20,11 @@ class RoomDetailCard extends StatelessWidget {
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
children:
[
Row
(
Row
(
spacing:
16
.
w
,
children:
[
children:
[
Container
(
Container
(
width:
6
0
.
w
,
width:
6
4
.
w
,
height:
60
.
h
,
height:
53
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
219
,
234
,
254
,
1
),
color:
const
Color
.
fromRGBO
(
219
,
234
,
254
,
1
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
...
@@ -34,9 +35,9 @@ class RoomDetailCard extends StatelessWidget {
...
@@ -34,9 +35,9 @@ class RoomDetailCard extends StatelessWidget {
size:
32
.
sp
,
size:
32
.
sp
,
),
),
),
),
SizedBox
(
width:
16
.
w
),
Column
(
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
spacing:
12
.
h
,
children:
[
children:
[
Row
(
Row
(
children:
[
children:
[
...
@@ -58,23 +59,23 @@ class RoomDetailCard extends StatelessWidget {
...
@@ -58,23 +59,23 @@ class RoomDetailCard extends StatelessWidget {
),
),
],
],
),
),
SizedBox
(
height:
12
.
h
),
Row
(
Row
(
spacing:
12
.
w
,
children:
[
children:
[
if
(
room
.
statusTags
.
isOccupied
)
_StatusTag
(
_StatusTag
(
label:
'有人'
,
label:
'有人'
,
isActive:
room
.
statusTags
.
isOccupied
,
isActive:
room
.
statusTags
.
isOccupied
,
),
),
SizedBox
(
width:
12
.
w
),
if
(
room
.
statusTags
.
powerSupplyStatus
)
_StatusTag
(
_StatusTag
(
label:
'通电中'
,
label:
'通电中'
,
isActive:
room
.
statusTags
.
powerSupplyStatus
,
isActive:
room
.
statusTags
.
powerSupplyStatus
,
),
),
SizedBox
(
width:
12
.
w
),
// _StatusTag(
_StatusTag
(
// label: 'wifi正常',
label:
'wifi正常'
,
// isActive: room.statusTags.wifiNormalStatus,
isActive:
room
.
statusTags
.
wifiNormalStatus
,
// ),
),
],
],
),
),
],
],
...
@@ -84,13 +85,23 @@ class RoomDetailCard extends StatelessWidget {
...
@@ -84,13 +85,23 @@ class RoomDetailCard extends StatelessWidget {
SizedBox
(
height:
24
.
h
),
SizedBox
(
height:
24
.
h
),
Divider
(
Divider
(
height:
1
.
h
,
height:
1
.
h
,
thickness:
0.5
,
color:
const
Color
.
fromRGBO
(
229
,
231
,
235
,
1
),
color:
const
Color
.
fromRGBO
(
229
,
231
,
235
,
1
),
),
),
SizedBox
(
height:
24
.
h
),
SizedBox
(
height:
24
.
h
),
// GridView.count(
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// crossAxisCount: 2,
// mainAxisSpacing: 16.h,
// crossAxisSpacing: 16.w,
// children: room.deviceList.map((device) => _DeviceControl(device: device)).toList(),
// ),
GridView
.
count
(
GridView
.
count
(
shrinkWrap:
true
,
shrinkWrap:
true
,
physics:
const
NeverScrollableScrollPhysics
(),
physics:
const
NeverScrollableScrollPhysics
(),
crossAxisCount:
2
,
crossAxisCount:
2
,
childAspectRatio:
3
,
mainAxisSpacing:
16
.
h
,
mainAxisSpacing:
16
.
h
,
crossAxisSpacing:
16
.
w
,
crossAxisSpacing:
16
.
w
,
children:
room
.
deviceList
.
map
((
device
)
=>
_DeviceControl
(
device:
device
)).
toList
(),
children:
room
.
deviceList
.
map
((
device
)
=>
_DeviceControl
(
device:
device
)).
toList
(),
...
@@ -113,21 +124,20 @@ class _StatusTag extends StatelessWidget {
...
@@ -113,21 +124,20 @@ class _StatusTag extends StatelessWidget {
padding:
EdgeInsets
.
symmetric
(
horizontal:
12
.
w
,
vertical:
8
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
12
.
w
,
vertical:
8
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
isActive
color:
isActive
?
const
Color
.
fromRGBO
(
167
,
243
,
208
,
1
)
?
const
Color
.
fromRGBO
(
20
,
184
,
166
,
0.2
)
:
const
Color
.
fromRGBO
(
229
,
231
,
235
,
1
),
:
const
Color
.
fromRGBO
(
229
,
231
,
235
,
1
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
),
),
child:
Row
(
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
spacing:
4
.
w
,
children:
[
children:
[
if
(
isActive
)
if
(
isActive
)
Icon
(
Icon
(
Icons
.
check
,
Icons
.
check
,
size:
2
0
.
sp
,
size:
2
4
.
sp
,
color:
const
Color
.
fromRGBO
(
16
,
185
,
129
,
1
),
color:
const
Color
.
fromRGBO
(
16
,
185
,
129
,
1
),
),
),
if
(
isActive
)
SizedBox
(
width:
4
.
w
),
Text
(
Text
(
label
,
label
,
style:
TextStyle
(
style:
TextStyle
(
...
@@ -165,7 +175,6 @@ class _DeviceControl extends StatelessWidget {
...
@@ -165,7 +175,6 @@ class _DeviceControl extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
isOn
=
device
.
powerStatus
==
'1'
;
return
Container
(
return
Container
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
24
.
w
,
vertical:
24
.
h
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
24
.
w
,
vertical:
24
.
h
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
...
@@ -180,20 +189,23 @@ class _DeviceControl extends StatelessWidget {
...
@@ -180,20 +189,23 @@ class _DeviceControl extends StatelessWidget {
size:
40
.
sp
,
size:
40
.
sp
,
),
),
SizedBox
(
width:
16
.
w
),
SizedBox
(
width:
16
.
w
),
Text
(
Expanded
(
child:
Text
(
device
.
deviceName
,
device
.
deviceName
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
28
.
sp
,
fontSize:
28
.
sp
,
color:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
color:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
fontWeight:
FontWeight
.
w500
,
fontWeight:
FontWeight
.
w500
,
),
),
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
),
),
),
const
Spacer
(),
Text
(
Text
(
device
.
paramDisplayText
.
isNotEmpty
?
device
.
paramDisplayText
:
device
.
powerStatusText
,
device
.
paramDisplayText
.
isNotEmpty
?
device
.
paramDisplayText
:
device
.
powerStatusText
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
26
.
sp
,
fontSize:
26
.
sp
,
color:
isOn
color:
device
.
powerStatus
==
'1'
?
const
Color
.
fromRGBO
(
16
,
185
,
129
,
1
)
?
const
Color
.
fromRGBO
(
16
,
185
,
129
,
1
)
:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
:
const
Color
.
fromRGBO
(
156
,
163
,
175
,
1
),
),
),
...
...
lib/views/report/room/widget/room_grid.dart
View file @
1244f87e
...
@@ -97,23 +97,30 @@ class _RoomItem extends StatelessWidget {
...
@@ -97,23 +97,30 @@ class _RoomItem extends StatelessWidget {
room
.
roomNumber
,
room
.
roomNumber
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
28
.
sp
,
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
w500
,
color:
_textColor
,
color:
_textColor
,
),
),
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
),
),
SizedBox
(
height:
4
.
h
),
SizedBox
(
height:
4
.
h
),
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
if
(
room
.
hasAlarmIcon
)
if
(
room
.
hasAlarmIcon
)
Icon
(
Icons
.
warning_amber_outlined
,
color:
_textColor
,
size:
20
.
sp
),
Icon
(
Icons
.
warning_amber_outlined
,
color:
_textColor
,
size:
24
.
sp
),
if
(!
room
.
hasAlarmIcon
)
Text
(
Text
(
room
.
statusText
,
room
.
statusText
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
20
.
sp
,
fontSize:
24
.
sp
,
color:
_textColor
,
color:
_textColor
,
),
),
),
),
],
],
),
),
],
),
);
);
}
}
}
}
lib/views/report/room/widget/status_stats.dart
View file @
1244f87e
...
@@ -10,10 +10,10 @@ class StatusStats extends StatelessWidget {
...
@@ -10,10 +10,10 @@ class StatusStats extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
items
=
[
final
items
=
[
_StatItemData
(
label:
'入住'
,
count:
summary
.
occupiedCount
,
color:
const
Color
(
0xFF4A7CF7
)),
_StatItemData
(
label:
'入住'
,
count:
summary
.
occupiedCount
,
color:
const
Color
.
fromRGBO
(
73
,
149
,
234
,
1
)),
_StatItemData
(
label:
'空闲'
,
count:
summary
.
vacantCount
,
color:
const
Color
(
0xFF4CAF50
)),
_StatItemData
(
label:
'空闲'
,
count:
summary
.
vacantCount
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
1
)),
_StatItemData
(
label:
'预定'
,
count:
summary
.
reservedCount
,
color:
const
Color
(
0xFF9C27B0
)),
_StatItemData
(
label:
'预定'
,
count:
summary
.
reservedCount
,
color:
const
Color
.
fromRGBO
(
139
,
193
,
255
,
1
)),
_StatItemData
(
label:
'告警'
,
count:
summary
.
alarmCount
,
color:
const
Color
(
0xFFFF9800
)),
_StatItemData
(
label:
'告警'
,
count:
summary
.
alarmCount
,
color:
const
Color
.
fromRGBO
(
250
,
204
,
21
,
1
)),
];
];
return
Container
(
return
Container
(
...
@@ -24,7 +24,7 @@ class StatusStats extends StatelessWidget {
...
@@ -24,7 +24,7 @@ class StatusStats extends StatelessWidget {
borderRadius:
BorderRadius
.
circular
(
24
.
r
),
borderRadius:
BorderRadius
.
circular
(
24
.
r
),
),
),
child:
Row
(
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
spacing:
10
.
w
,
children:
items
.
map
((
item
)
=>
_StatItem
(
item:
item
)).
toList
(),
children:
items
.
map
((
item
)
=>
_StatItem
(
item:
item
)).
toList
(),
),
),
);
);
...
@@ -45,13 +45,20 @@ class _StatItem extends StatelessWidget {
...
@@ -45,13 +45,20 @@ class _StatItem extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Column
(
return
Expanded
(
child:
Container
(
padding:
EdgeInsets
.
symmetric
(
vertical:
12
.
h
,
horizontal:
8
.
w
),
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
229
,
231
,
235
,
1
),
borderRadius:
BorderRadius
.
circular
(
24
.
r
),
),
child:
Column
(
children:
[
children:
[
Text
(
Text
(
item
.
count
.
toString
(),
item
.
count
.
toString
(),
style:
TextStyle
(
style:
TextStyle
(
fontSize:
40
.
sp
,
fontSize:
40
.
sp
,
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
w600
,
color:
item
.
color
,
color:
item
.
color
,
),
),
),
),
...
@@ -64,6 +71,8 @@ class _StatItem extends StatelessWidget {
...
@@ -64,6 +71,8 @@ class _StatItem extends StatelessWidget {
),
),
),
),
],
],
),
)
);
);
}
}
}
}
lib/views/report/rule/cubit/rule_management_cubit.dart
View file @
1244f87e
...
@@ -27,22 +27,22 @@ class RuleManagementCubit extends Cubit<RuleManagementState> {
...
@@ -27,22 +27,22 @@ class RuleManagementCubit extends Cubit<RuleManagementState> {
/// 根据规则名称映射图标
/// 根据规则名称映射图标
IconData
_mapIcon
(
String
ruleName
)
{
IconData
_mapIcon
(
String
ruleName
)
{
final
name
=
ruleName
.
toLowerCase
();
//
final name = ruleName.toLowerCase();
if
(
name
.
contains
(
'退房'
)
||
name
.
contains
(
'logout'
))
{
//
if (name.contains('退房') || name.contains('logout')) {
return
Icons
.
logout_outlined
;
//
return Icons.logout_outlined;
}
//
}
if
(
name
.
contains
(
'清洁'
)
||
name
.
contains
(
'灯'
)
||
name
.
contains
(
'clean'
))
{
//
if (name.contains('清洁') || name.contains('灯') || name.contains('clean')) {
return
Icons
.
cleaning_services_outlined
;
//
return Icons.cleaning_services_outlined;
}
//
}
if
(
name
.
contains
(
'温度'
)
||
name
.
contains
(
'thermostat'
))
{
//
if (name.contains('温度') || name.contains('thermostat')) {
return
Icons
.
thermostat_outlined
;
//
return Icons.thermostat_outlined;
}
//
}
if
(
name
.
contains
(
'深夜'
)
||
name
.
contains
(
'night'
))
{
//
if (name.contains('深夜') || name.contains('night')) {
return
Icons
.
nightlight_outlined
;
//
return Icons.nightlight_outlined;
}
//
}
if
(
name
.
contains
(
'定时'
)
||
name
.
contains
(
'巡检'
)
||
name
.
contains
(
'time'
))
{
//
if (name.contains('定时') || name.contains('巡检') || name.contains('time')) {
return
Icons
.
access_time_outlined
;
//
return Icons.access_time_outlined;
}
//
}
return
Icons
.
tune
;
return
Icons
.
tune
;
}
}
...
...
lib/views/report/rule/rule_management_view.dart
View file @
1244f87e
...
@@ -51,7 +51,8 @@ class ReportRuleManagementView extends StatelessWidget {
...
@@ -51,7 +51,8 @@ class ReportRuleManagementView extends StatelessWidget {
itemCount:
state
.
rules
.
length
,
itemCount:
state
.
rules
.
length
,
separatorBuilder:
(
context
,
index
)
=>
Divider
(
separatorBuilder:
(
context
,
index
)
=>
Divider
(
height:
1
.
h
,
height:
1
.
h
,
color:
const
Color
.
fromRGBO
(
229
,
231
,
235
,
1
),
thickness:
0.5
,
color:
const
Color
.
fromRGBO
(
100
,
116
,
139
,
0.2
),
indent:
28
.
w
,
indent:
28
.
w
,
endIndent:
28
.
w
,
endIndent:
28
.
w
,
),
),
...
...
lib/views/report/rule/widget/rule_card.dart
View file @
1244f87e
...
@@ -19,17 +19,16 @@ class RuleCard extends StatelessWidget {
...
@@ -19,17 +19,16 @@ class RuleCard extends StatelessWidget {
padding:
EdgeInsets
.
symmetric
(
vertical:
24
.
h
,
horizontal:
28
.
w
),
padding:
EdgeInsets
.
symmetric
(
vertical:
24
.
h
,
horizontal:
28
.
w
),
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
Colors
.
white
,
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
24
.
r
),
),
),
child:
Column
(
child:
Row
(
children:
[
Row
(
children:
[
children:
[
Container
(
Container
(
width:
72
.
w
,
width:
64
.
w
,
height:
72
.
h
,
height:
53
.
h
,
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
color:
const
Color
.
fromRGBO
(
219
,
234
,
254
,
1
),
color:
const
Color
.
fromRGBO
(
219
,
234
,
254
,
1
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
),
),
child:
Icon
(
child:
Icon
(
rule
.
icon
,
rule
.
icon
,
...
@@ -45,9 +44,9 @@ class RuleCard extends StatelessWidget {
...
@@ -45,9 +44,9 @@ class RuleCard extends StatelessWidget {
Text
(
Text
(
rule
.
name
,
rule
.
name
,
style:
TextStyle
(
style:
TextStyle
(
fontSize:
32
.
sp
,
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
bold
,
color:
const
Color
.
fromRGBO
(
31
,
41
,
55
,
1
),
color:
const
Color
.
fromRGBO
(
0
,
0
,
0
,
1
),
),
),
),
),
SizedBox
(
height:
8
.
h
),
SizedBox
(
height:
8
.
h
),
...
@@ -62,21 +61,21 @@ class RuleCard extends StatelessWidget {
...
@@ -62,21 +61,21 @@ class RuleCard extends StatelessWidget {
),
),
),
),
FlutterSwitch
(
FlutterSwitch
(
width:
88
.
w
,
// width: 64.w,
height:
48
.
h
,
// height: 29.h,
width:
80
.
w
,
height:
35
.
h
,
valueFontSize:
20
.
sp
,
valueFontSize:
20
.
sp
,
toggleSize:
40
.
h
,
toggleSize:
25
.
h
,
value:
rule
.
enabled
,
borderRadius:
20
.
r
,
borderRadius:
24
.
r
,
padding:
4
.
w
,
padding:
4
.
w
,
activeColor:
const
Color
.
fromRGBO
(
59
,
130
,
246
,
1
),
value:
rule
.
enabled
,
inactiveColor:
const
Color
.
fromRGBO
(
209
,
213
,
219
,
1
),
activeColor:
const
Color
.
fromRGBO
(
80
,
162
,
255
,
1
),
inactiveColor:
const
Color
.
fromRGBO
(
210
,
213
,
218
,
1
),
onToggle:
(
_
)
=>
onToggle
(
rule
.
id
),
onToggle:
(
_
)
=>
onToggle
(
rule
.
id
),
),
),
],
],
),
),
],
),
);
);
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment