Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
laki_icu_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
张宏
laki_icu_app
Commits
d6fc2a2b
Commit
d6fc2a2b
authored
Jun 24, 2026
by
张宏
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
http://git.ruanyiit.com/zhanghong/laki_icu_app
parents
d2db426e
2160220c
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1153 additions
and
230 deletions
+1153
-230
device_control_bloc.dart
lib/blocs/device_control/device_control_bloc.dart
+0
-0
bluetooth_manager.dart
lib/utils/bluetooth/bluetooth_manager.dart
+12
-1
numeric_keyboard.dart
lib/utils/numeric_keyboard.dart
+356
-0
device_control_index_view.dart
.../monitoring/device_control/device_control_index_view.dart
+49
-24
device_control_care_panel.dart
...ing/device_control/widgets/device_control_care_panel.dart
+166
-30
device_control_info_panel.dart
...ing/device_control/widgets/device_control_info_panel.dart
+49
-35
device_control_metric_card.dart
...ng/device_control/widgets/device_control_metric_card.dart
+71
-9
device_control_mode_panel.dart
...ing/device_control/widgets/device_control_mode_panel.dart
+132
-47
device_control_time_panel.dart
...ing/device_control/widgets/device_control_time_panel.dart
+95
-21
device_control_wind_panel.dart
...ing/device_control/widgets/device_control_wind_panel.dart
+91
-45
monitoring_index_cubit.dart
lib/views/monitoring/index/cubit/monitoring_index_cubit.dart
+130
-17
monitoring_index_view.dart
lib/views/monitoring/index/monitoring_index_view.dart
+2
-1
No files found.
lib/blocs/device_control/device_control_bloc.dart
View file @
d6fc2a2b
This diff is collapsed.
Click to expand it.
lib/utils/bluetooth/bluetooth_manager.dart
View file @
d6fc2a2b
...
...
@@ -376,6 +376,15 @@ class BleBluetoothManager<T> {
return
;
}
final
hex
=
bytesToHex
(
data
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG write_data '
'deviceId=
${characteristic.deviceId}
'
'service=
${characteristic.serviceId}
'
'characteristic=
${characteristic.characteristicId}
'
'withoutResponse=
$withoutResponse
'
'hex=
$hex
'
,
);
try
{
if
(
withoutResponse
)
{
await
_ble
.
writeCharacteristicWithoutResponse
(
...
...
@@ -385,9 +394,11 @@ class BleBluetoothManager<T> {
}
else
{
await
_ble
.
writeCharacteristicWithResponse
(
characteristic
,
value:
data
);
}
_notifyMessage
(
'蓝牙数据发送成功:
${bytesToHex(data)}
'
);
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG write_success hex=
$hex
'
);
_notifyMessage
(
'蓝牙数据发送成功:
$hex
'
);
_sendResultController
.
add
(
true
);
}
catch
(
error
)
{
Log
.
warn
(
'🔥🔥🔥 BLE_WRITE_DEBUG write_error hex=
$hex
error=
$error
'
);
_notifyMessage
(
'蓝牙数据发送失败:
$error
'
);
_sendResultController
.
add
(
false
);
}
...
...
lib/utils/numeric_keyboard.dart
0 → 100644
View file @
d6fc2a2b
This diff is collapsed.
Click to expand it.
lib/views/monitoring/device_control/device_control_index_view.dart
View file @
d6fc2a2b
...
...
@@ -2,6 +2,9 @@ import 'package:auto_route/auto_route.dart';
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_bloc.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_event.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_state.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'cubit/device_control_index_cubit.dart'
;
...
...
@@ -130,23 +133,32 @@ class _DeviceControlLayout extends StatelessWidget {
SizedBox
(
height:
24
.
h
),
Expanded
(
flex:
58
,
child:
Row
(
children:
[
const
Expanded
(
flex:
48
,
child:
DeviceControlModePanel
(),
),
SizedBox
(
width:
24
.
w
),
const
Expanded
(
flex:
23
,
child:
DeviceControlWindPanel
(),
),
SizedBox
(
width:
24
.
w
),
const
Expanded
(
flex:
29
,
child:
DeviceControlTimePanel
(),
),
],
child:
LayoutBuilder
(
builder:
(
context
,
constraints
)
{
final
gap
=
24
.
w
;
final
metricCardWidth
=
(
constraints
.
maxWidth
-
gap
*
3
)
/
4
;
final
modePanelWidth
=
metricCardWidth
*
2
+
gap
;
return
Row
(
children:
[
SizedBox
(
width:
modePanelWidth
,
child:
const
DeviceControlModePanel
(),
),
SizedBox
(
width:
gap
),
SizedBox
(
width:
metricCardWidth
,
child:
const
DeviceControlWindPanel
(),
),
SizedBox
(
width:
gap
),
SizedBox
(
width:
metricCardWidth
,
child:
const
DeviceControlTimePanel
(),
),
],
);
},
),
),
],
...
...
@@ -169,14 +181,27 @@ class _DeviceControlLayout extends StatelessWidget {
),
),
SizedBox
(
height:
24
.
h
),
const
Expanded
(
Expanded
(
flex:
20
,
child:
DeviceControlInfoPanel
(
title:
'开放供氧'
,
actionText:
'Off'
,
icon:
Icons
.
air
,
body:
'开启后风扇打开、制冷、加热和
\n
循环等设备暂停。'
,
warning:
'*保持设备周围空气相对禁止,严禁烟火'
,
child:
BlocBuilder
<
DeviceControlBloc
,
DeviceControlState
>(
buildWhen:
(
previous
,
current
)
=>
previous
.
data
.
openOxygen
!=
current
.
data
.
openOxygen
,
builder:
(
context
,
state
)
{
final
isOn
=
state
.
data
.
openOxygen
.
isOn
;
return
DeviceControlInfoPanel
(
title:
'开放供氧'
,
actionText:
isOn
?
'ON'
:
'Off'
,
active:
isOn
,
icon:
Icons
.
air
,
body:
'开启后风扇打开、制冷、加热和
\n
循环等设备暂停。'
,
warning:
'*保持设备周围空气相对禁止,严禁烟火'
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
DeviceControlOpenOxygenSwitchChanged
(!
isOn
),
),
);
},
),
),
SizedBox
(
height:
24
.
h
),
...
...
lib/views/monitoring/device_control/widgets/device_control_care_panel.dart
View file @
d6fc2a2b
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_bloc.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_event.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_state.dart'
;
import
'package:laki_icu_app/models/bo/device_control_bo.dart'
;
import
'device_control_common.dart'
;
...
...
@@ -9,43 +14,174 @@ class DeviceControlCarePanel extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelWide
,
padding:
EdgeInsets
.
fromLTRB
(
30
.
w
,
26
.
h
,
30
.
w
,
24
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'护理等级'
),
const
Spacer
(),
Container
(
height:
20
.
h
,
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
10
.
r
),
gradient:
const
LinearGradient
(
colors:
[
Color
(
0xFFDCEFFC
),
Color
(
0xFF71FFCF
),
Color
(
0xFFE4CF1D
),
Color
(
0xFFFFA11B
),
Color
(
0xFFFF5945
),
Color
(
0xFFFFFFFF
),
return
BlocBuilder
<
DeviceControlBloc
,
DeviceControlState
>(
buildWhen:
(
previous
,
current
)
=>
previous
.
data
.
careLevel
!=
current
.
data
.
careLevel
,
builder:
(
context
,
state
)
{
final
currentLevel
=
state
.
data
.
careLevel
.
currentLevel
;
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelWide
,
padding:
EdgeInsets
.
fromLTRB
(
30
.
w
,
26
.
h
,
30
.
w
,
24
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'护理等级'
),
const
Spacer
(),
_CareLevelBar
(
currentLevel:
currentLevel
),
SizedBox
(
height:
24
.
h
),
Row
(
children:
[
for
(
final
item
in
_careLevelItems
)
Expanded
(
child:
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
DeviceControlCareLevelChanged
(
item
.
level
),
),
child:
Text
(
item
.
label
,
textAlign:
TextAlign
.
center
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
24
.
sp
,
),
),
),
),
],
),
)
,
]
,
),
SizedBox
(
height:
24
.
h
),
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
);
},
);
}
}
class
_CareLevelBar
extends
StatelessWidget
{
const
_CareLevelBar
({
required
this
.
currentLevel
});
final
CareLevel
currentLevel
;
@override
Widget
build
(
BuildContext
context
)
{
final
activeIndex
=
_careLevelItems
.
indexWhere
(
(
item
)
=>
item
.
level
==
currentLevel
,
);
return
LayoutBuilder
(
builder:
(
context
,
constraints
)
{
final
segmentGap
=
4
.
w
;
final
knobSize
=
54
.
w
;
final
segmentWidth
=
(
constraints
.
maxWidth
-
segmentGap
*
(
_careLevelItems
.
length
-
1
))
/
_careLevelItems
.
length
;
final
knobLeft
=
(
segmentWidth
+
segmentGap
)
*
activeIndex
+
segmentWidth
-
knobSize
/
2
;
return
SizedBox
(
height:
knobSize
,
child:
Stack
(
clipBehavior:
Clip
.
none
,
alignment:
Alignment
.
centerLeft
,
children:
[
for
(
final
item
in
const
[
'关闭'
,
'三级'
,
'二级'
,
'一级'
,
'特级'
])
Text
(
item
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
24
.
sp
),
Positioned
(
left:
0
,
right:
0
,
top:
(
knobSize
-
20
.
h
)
/
2
,
child:
Row
(
children:
[
for
(
var
index
=
0
;
index
<
_careLevelItems
.
length
;
index
++)
...[
Expanded
(
child:
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
DeviceControlCareLevelChanged
(
_careLevelItems
[
index
].
level
,
),
),
child:
Container
(
height:
20
.
h
,
decoration:
BoxDecoration
(
color:
index
<=
activeIndex
?
_careLevelItems
[
index
].
color
:
const
Color
(
0xFF6A7481
),
borderRadius:
_segmentRadius
(
index
),
boxShadow:
index
<=
activeIndex
?
[
BoxShadow
(
color:
_careLevelItems
[
index
]
.
color
.
withValues
(
alpha:
0.35
),
blurRadius:
8
.
r
,
),
]
:
null
,
),
),
),
),
if
(
index
<
_careLevelItems
.
length
-
1
)
SizedBox
(
width:
segmentGap
),
],
],
),
),
Positioned
(
left:
knobLeft
.
clamp
(
0
,
constraints
.
maxWidth
-
knobSize
),
child:
Container
(
width:
knobSize
,
height:
knobSize
,
decoration:
BoxDecoration
(
color:
const
Color
(
0xFFF7F7F7
),
shape:
BoxShape
.
circle
,
boxShadow:
[
BoxShadow
(
color:
Colors
.
white
.
withValues
(
alpha:
0.72
),
blurRadius:
10
.
r
,
),
],
),
),
),
],
),
],
)
,
);
}
,
);
}
BorderRadius
_segmentRadius
(
int
index
)
{
final
radius
=
Radius
.
circular
(
12
.
r
);
if
(
index
==
0
)
{
return
BorderRadius
.
horizontal
(
left:
radius
);
}
if
(
index
==
_careLevelItems
.
length
-
1
)
{
return
BorderRadius
.
horizontal
(
right:
radius
);
}
return
BorderRadius
.
zero
;
}
}
const
_careLevelItems
=
[
_CareLevelItem
(
'关闭'
,
CareLevel
.
off
,
Color
(
0xFFE5F7FF
)),
_CareLevelItem
(
'三级'
,
CareLevel
.
level3
,
Color
(
0xFF60F2B6
)),
_CareLevelItem
(
'二级'
,
CareLevel
.
level2
,
Color
(
0xFFFFCE1B
)),
_CareLevelItem
(
'一级'
,
CareLevel
.
level1
,
Color
(
0xFFFF8D2E
)),
_CareLevelItem
(
'特级'
,
CareLevel
.
special
,
Color
(
0xFFFF554C
)),
];
class
_CareLevelItem
{
const
_CareLevelItem
(
this
.
label
,
this
.
level
,
this
.
color
);
final
String
label
;
final
CareLevel
level
;
final
Color
color
;
}
lib/views/monitoring/device_control/widgets/device_control_info_panel.dart
View file @
d6fc2a2b
...
...
@@ -12,6 +12,8 @@ class DeviceControlInfoPanel extends StatelessWidget {
required
this
.
icon
,
required
this
.
body
,
this
.
warning
,
this
.
active
=
false
,
this
.
onTap
,
});
final
String
title
;
...
...
@@ -19,49 +21,61 @@ class DeviceControlInfoPanel extends StatelessWidget {
final
IconData
icon
;
final
String
body
;
final
String
?
warning
;
final
bool
active
;
final
VoidCallback
?
onTap
;
@override
Widget
build
(
BuildContext
context
)
{
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelWide
,
padding:
EdgeInsets
.
fromLTRB
(
30
.
w
,
22
.
h
,
30
.
w
,
24
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
children:
[
Expanded
(
child:
DeviceControlPanelTitle
(
title
)),
DeviceControlPill
(
text:
actionText
),
],
),
const
Spacer
(),
Row
(
children:
[
Icon
(
icon
,
color:
const
Color
(
0xFF6AC6F2
),
size:
54
.
w
),
SizedBox
(
width:
28
.
w
),
Expanded
(
child:
Text
(
body
,
style:
TextStyle
(
color:
const
Color
(
0xFFC9F8FF
),
fontSize:
20
.
sp
,
height:
1.35
,
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
onTap
,
child:
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelWide
,
padding:
EdgeInsets
.
fromLTRB
(
30
.
w
,
22
.
h
,
30
.
w
,
24
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
children:
[
Expanded
(
child:
DeviceControlPanelTitle
(
title
)),
DeviceControlPill
(
text:
actionText
,
active:
active
),
],
),
const
Spacer
(),
Row
(
children:
[
Icon
(
icon
,
color:
active
?
const
Color
(
0xFF45F36F
)
:
const
Color
(
0xFF6AC6F2
),
size:
54
.
w
,
),
SizedBox
(
width:
28
.
w
),
Expanded
(
child:
Text
(
body
,
style:
TextStyle
(
color:
const
Color
(
0xFFC9F8FF
),
fontSize:
20
.
sp
,
height:
1.35
,
),
),
),
],
),
if
(
warning
!=
null
)
...[
SizedBox
(
height:
8
.
h
),
Text
(
warning
!,
style:
TextStyle
(
color:
const
Color
(
0xFFFFC400
),
fontSize:
16
.
sp
,
),
),
],
),
if
(
warning
!=
null
)
...[
SizedBox
(
height:
8
.
h
),
Text
(
warning
!,
style:
TextStyle
(
color:
const
Color
(
0xFFFFC400
),
fontSize:
16
.
sp
,
),
),
],
]
,
)
,
),
);
}
...
...
lib/views/monitoring/device_control/widgets/device_control_metric_card.dart
View file @
d6fc2a2b
...
...
@@ -5,6 +5,7 @@ import 'package:laki_icu_app/blocs/device_control/device_control_bloc.dart';
import
'package:laki_icu_app/blocs/device_control/device_control_event.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_state.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'package:laki_icu_app/utils/numeric_keyboard.dart'
;
import
'device_control_common.dart'
;
...
...
@@ -64,6 +65,12 @@ class DeviceControlMetricCard extends StatelessWidget {
isOxygen:
isOxygen
,
isCo2:
isCo2
,
);
final
setValueEventBuilder
=
_setValueEventBuilder
(
isTemperature:
isTemperature
,
isHumidity:
isHumidity
,
isOxygen:
isOxygen
,
isCo2:
isCo2
,
);
return
DeviceControlPanelFrame
(
active:
isOxygen
,
...
...
@@ -147,15 +154,30 @@ class DeviceControlMetricCard extends StatelessWidget {
),
),
const
Spacer
(),
Text
(
setValue
,
style:
TextStyle
(
color:
isCo2
?
const
Color
(
0xFFFFC400
)
:
const
Color
(
0xFF00B7F4
),
fontSize:
64
.
sp
,
height:
1
,
fontWeight:
FontWeight
.
bold
,
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
setValueEventBuilder
==
null
?
null
:
()
=>
_showSetValueKeyboard
(
context
,
initialValue:
setValue
,
decimalEnabled:
isTemperature
,
eventBuilder:
setValueEventBuilder
,
),
child:
Padding
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
18
.
w
,
vertical:
8
.
h
),
child:
Text
(
setValue
,
style:
TextStyle
(
color:
isCo2
?
const
Color
(
0xFFFFC400
)
:
const
Color
(
0xFF00B7F4
),
fontSize:
64
.
sp
,
height:
1
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
const
Spacer
(),
...
...
@@ -206,6 +228,46 @@ class DeviceControlMetricCard extends StatelessWidget {
}
return
null
;
}
static
DeviceControlEvent
Function
(
String
value
)?
_setValueEventBuilder
({
required
bool
isTemperature
,
required
bool
isHumidity
,
required
bool
isOxygen
,
required
bool
isCo2
,
})
{
if
(
isTemperature
)
{
return
(
value
)
=>
DeviceControlCabinTempSetValueChanged
(
value
);
}
if
(
isHumidity
)
{
return
(
value
)
=>
DeviceControlCabinHumiditySetValueChanged
(
value
);
}
if
(
isOxygen
)
{
return
(
value
)
=>
DeviceControlOxygenConcentrationSetValueChanged
(
value
);
}
if
(
isCo2
)
{
return
(
value
)
=>
DeviceControlCO2ConcentrationAlarmThresholdChanged
(
value
);
}
return
null
;
}
static
Future
<
void
>
_showSetValueKeyboard
(
BuildContext
context
,
{
required
String
initialValue
,
required
bool
decimalEnabled
,
required
DeviceControlEvent
Function
(
String
value
)
eventBuilder
,
})
async
{
final
result
=
await
NumericKeyboard
.
show
(
context
,
initialValue:
initialValue
==
'--'
?
''
:
initialValue
,
decimalEnabled:
decimalEnabled
,
);
if
(!
context
.
mounted
||
result
==
null
)
return
;
final
value
=
result
.
trim
();
if
(
value
.
isEmpty
||
value
==
'.'
)
return
;
context
.
read
<
DeviceControlBloc
>().
add
(
eventBuilder
(
value
));
}
}
class
_MetricAdjustButton
extends
StatelessWidget
{
...
...
lib/views/monitoring/device_control/widgets/device_control_mode_panel.dart
View file @
d6fc2a2b
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_bloc.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_event.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_state.dart'
;
import
'package:laki_icu_app/models/bo/device_control_bo.dart'
;
import
'device_control_common.dart'
;
...
...
@@ -9,33 +14,97 @@ class DeviceControlModePanel extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
const
items
=
[
_ModeItem
(
label:
'外循环'
,
icon:
Icons
.
sync
,
active:
true
),
_ModeItem
(
label:
'检查灯'
,
icon:
Icons
.
light
),
_ModeItem
(
label:
'照明灯'
,
icon:
Icons
.
lightbulb
),
_ModeItem
(
label:
'内循环'
,
icon:
Icons
.
autorenew
),
_ModeItem
(
label:
'蓝光'
,
icon:
Icons
.
wb_sunny_outlined
),
_ModeItem
(
label:
'红光'
,
icon:
Icons
.
wb_sunny
),
];
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelLarge
,
padding:
EdgeInsets
.
all
(
28
.
w
),
child:
GridView
.
count
(
crossAxisCount:
3
,
crossAxisSpacing:
24
.
w
,
mainAxisSpacing:
24
.
h
,
physics:
const
NeverScrollableScrollPhysics
(),
childAspectRatio:
1.1
,
children:
[
for
(
final
item
in
items
)
_ModeButton
(
label:
item
.
label
,
icon:
item
.
icon
,
active:
item
.
active
,
return
BlocBuilder
<
DeviceControlBloc
,
DeviceControlState
>(
buildWhen:
(
previous
,
current
)
=>
previous
.
data
.
circulationMode
!=
current
.
data
.
circulationMode
||
previous
.
data
.
lightControl
!=
current
.
data
.
lightControl
,
builder:
(
context
,
state
)
{
final
circulationMode
=
state
.
data
.
circulationMode
.
currentMode
;
final
lightControl
=
state
.
data
.
lightControl
;
final
items
=
[
_ModeItem
(
label:
'外循环'
,
icon:
Icons
.
sync
,
active:
circulationMode
==
CirculationMode
.
external
,
event:
const
DeviceControlCirculationModeChanged
(
CirculationMode
.
external
,
),
],
),
),
_ModeItem
(
label:
'检查灯'
,
icon:
Icons
.
light
,
active:
lightControl
.
checkLightOn
,
event:
DeviceControlCheckLightSwitchChanged
(
!
lightControl
.
checkLightOn
,
),
),
_ModeItem
(
label:
'照明灯'
,
icon:
Icons
.
lightbulb
,
active:
lightControl
.
illuminationOn
,
event:
DeviceControlIlluminationLightSwitchChanged
(
!
lightControl
.
illuminationOn
,
),
),
_ModeItem
(
label:
'内循环'
,
icon:
Icons
.
autorenew
,
active:
circulationMode
==
CirculationMode
.
internal
,
event:
const
DeviceControlCirculationModeChanged
(
CirculationMode
.
internal
,
),
),
_ModeItem
(
label:
'蓝光'
,
icon:
Icons
.
wb_sunny_outlined
,
active:
lightControl
.
blueLightOn
,
event:
DeviceControlBlueLightSwitchChanged
(
!
lightControl
.
blueLightOn
,
),
),
_ModeItem
(
label:
'红光'
,
icon:
Icons
.
wb_sunny
,
active:
lightControl
.
redLightOn
,
event:
DeviceControlRedLightSwitchChanged
(
!
lightControl
.
redLightOn
,
),
),
];
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelLarge
,
padding:
EdgeInsets
.
fromLTRB
(
30
.
w
,
30
.
h
,
30
.
w
,
30
.
h
),
child:
LayoutBuilder
(
builder:
(
context
,
constraints
)
{
final
horizontalGap
=
22
.
w
;
final
verticalGap
=
22
.
h
;
final
itemWidth
=
(
constraints
.
maxWidth
-
horizontalGap
*
2
)
/
3
;
final
itemHeight
=
(
constraints
.
maxHeight
-
verticalGap
)
/
2
;
return
Wrap
(
spacing:
horizontalGap
,
runSpacing:
verticalGap
,
children:
[
for
(
final
item
in
items
)
SizedBox
(
width:
itemWidth
,
height:
itemHeight
,
child:
_ModeButton
(
label:
item
.
label
,
icon:
item
.
icon
,
active:
item
.
active
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
item
.
event
,
),
),
),
],
);
},
),
);
},
);
}
}
...
...
@@ -45,37 +114,51 @@ class _ModeButton extends StatelessWidget {
required
this
.
label
,
required
this
.
icon
,
this
.
active
=
false
,
this
.
onTap
,
});
final
String
label
;
final
IconData
icon
;
final
bool
active
;
final
VoidCallback
?
onTap
;
@override
Widget
build
(
BuildContext
context
)
{
final
color
=
active
?
const
Color
(
0xFF45F36F
)
:
const
Color
(
0xFF7DC4EA
);
return
Container
(
decoration:
deviceControlButtonDecoration
(
active:
active
,
backgroundAsset:
assetArrowButton
,
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
16
.
w
,
vertical:
18
.
h
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Icon
(
icon
,
color:
color
,
size:
56
.
w
),
SizedBox
(
height:
20
.
h
),
Text
(
label
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
color:
color
,
fontSize:
26
.
sp
,
fontWeight:
FontWeight
.
w700
,
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
onTap
,
child:
Container
(
decoration:
deviceControlButtonDecoration
(
active:
active
,
backgroundAsset:
assetArrowButton
,
),
padding:
EdgeInsets
.
fromLTRB
(
12
.
w
,
6
.
h
,
12
.
w
,
16
.
h
),
child:
Stack
(
alignment:
Alignment
.
center
,
children:
[
Positioned
(
top:
28
.
h
,
child:
Icon
(
icon
,
color:
color
,
size:
100
.
w
),
),
),
],
Positioned
(
left:
0
,
right:
0
,
bottom:
0
,
child:
Text
(
label
,
maxLines:
1
,
textAlign:
TextAlign
.
center
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
color:
color
,
fontSize:
26
.
sp
,
fontWeight:
FontWeight
.
w700
,
),
),
),
],
),
),
);
}
...
...
@@ -85,10 +168,12 @@ class _ModeItem {
final
String
label
;
final
IconData
icon
;
final
bool
active
;
final
DeviceControlEvent
event
;
const
_ModeItem
({
required
this
.
label
,
required
this
.
icon
,
required
this
.
event
,
this
.
active
=
false
,
});
}
lib/views/monitoring/device_control/widgets/device_control_time_panel.dart
View file @
d6fc2a2b
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_bloc.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_event.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_state.dart'
;
import
'package:laki_icu_app/utils/numeric_keyboard.dart'
;
import
'device_control_common.dart'
;
...
...
@@ -9,28 +14,97 @@ class DeviceControlTimePanel extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelTall
,
padding:
EdgeInsets
.
fromLTRB
(
34
.
w
,
28
.
h
,
34
.
w
,
28
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'设置雾化时间'
),
SizedBox
(
height:
18
.
h
),
const
Expanded
(
child:
DeviceControlDigitalValueBox
(
value:
'00'
,
unit:
'分钟'
),
),
Divider
(
color:
Colors
.
white
.
withValues
(
alpha:
0.16
),
height:
36
.
h
),
const
DeviceControlPanelTitle
(
'设置消毒时间'
),
SizedBox
(
height:
18
.
h
),
const
Expanded
(
child:
DeviceControlDigitalValueBox
(
value:
'14'
,
unit:
'分钟'
,
active:
true
,
),
return
BlocBuilder
<
DeviceControlBloc
,
DeviceControlState
>(
buildWhen:
(
previous
,
current
)
=>
previous
.
data
.
nebulizationTime
!=
current
.
data
.
nebulizationTime
||
previous
.
data
.
disinfectionTime
!=
current
.
data
.
disinfectionTime
,
builder:
(
context
,
state
)
{
final
nebulizationMinutes
=
state
.
data
.
nebulizationTime
.
setMinutes
;
final
disinfectionMinutes
=
state
.
data
.
disinfectionTime
.
setMinutes
;
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelTall
,
padding:
EdgeInsets
.
fromLTRB
(
34
.
w
,
28
.
h
,
34
.
w
,
28
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'设置雾化时间'
),
SizedBox
(
height:
18
.
h
),
Expanded
(
child:
_TimeValueButton
(
value:
nebulizationMinutes
,
active:
false
,
onTap:
()
=>
_showTimeKeyboard
(
context
,
initialValue:
nebulizationMinutes
,
eventBuilder:
(
value
)
=>
DeviceControlNebulizationTimeChanged
(
value
),
),
),
),
Divider
(
color:
Colors
.
white
.
withValues
(
alpha:
0.16
),
height:
36
.
h
,
),
const
DeviceControlPanelTitle
(
'设置消毒时间'
),
SizedBox
(
height:
18
.
h
),
Expanded
(
child:
_TimeValueButton
(
value:
disinfectionMinutes
,
active:
true
,
onTap:
()
=>
_showTimeKeyboard
(
context
,
initialValue:
disinfectionMinutes
,
eventBuilder:
(
value
)
=>
DeviceControlDisinfectionTimeChanged
(
value
),
),
),
),
],
),
],
);
},
);
}
static
Future
<
void
>
_showTimeKeyboard
(
BuildContext
context
,
{
required
String
initialValue
,
required
DeviceControlEvent
Function
(
String
value
)
eventBuilder
,
})
async
{
final
result
=
await
NumericKeyboard
.
show
(
context
,
initialValue:
initialValue
==
'--'
?
''
:
initialValue
,
decimalEnabled:
false
,
);
if
(!
context
.
mounted
||
result
==
null
)
return
;
final
value
=
result
.
trim
();
if
(
value
.
isEmpty
)
return
;
context
.
read
<
DeviceControlBloc
>().
add
(
eventBuilder
(
value
));
}
}
class
_TimeValueButton
extends
StatelessWidget
{
const
_TimeValueButton
({
required
this
.
value
,
required
this
.
active
,
required
this
.
onTap
,
});
final
String
value
;
final
bool
active
;
final
VoidCallback
onTap
;
@override
Widget
build
(
BuildContext
context
)
{
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
onTap
,
child:
DeviceControlDigitalValueBox
(
value:
value
,
unit:
'分钟'
,
active:
active
,
),
);
}
...
...
lib/views/monitoring/device_control/widgets/device_control_wind_panel.dart
View file @
d6fc2a2b
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_bloc.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_event.dart'
;
import
'package:laki_icu_app/blocs/device_control/device_control_state.dart'
;
import
'package:laki_icu_app/models/bo/device_control_bo.dart'
;
import
'device_control_common.dart'
;
...
...
@@ -9,33 +14,62 @@ class DeviceControlWindPanel extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelTall
,
padding:
EdgeInsets
.
fromLTRB
(
34
.
w
,
28
.
h
,
34
.
w
,
28
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'风速调节'
),
SizedBox
(
height:
24
.
h
),
const
Expanded
(
child:
_WideModeButton
(
label:
'睡眠模式'
,
icon:
Icons
.
nightlight_round
,
),
),
SizedBox
(
height:
18
.
h
),
const
Expanded
(
child:
_WideModeButton
(
label:
'舒适模式'
,
icon:
Icons
.
favorite_border
,
),
),
SizedBox
(
height:
18
.
h
),
const
Expanded
(
child:
_WideModeButton
(
label:
'强劲模式'
,
icon:
Icons
.
air
),
return
BlocBuilder
<
DeviceControlBloc
,
DeviceControlState
>(
buildWhen:
(
previous
,
current
)
=>
previous
.
data
.
windSpeed
!=
current
.
data
.
windSpeed
,
builder:
(
context
,
state
)
{
final
currentMode
=
state
.
data
.
windSpeed
.
currentMode
;
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelTall
,
padding:
EdgeInsets
.
fromLTRB
(
34
.
w
,
28
.
h
,
34
.
w
,
28
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'风速调节'
),
SizedBox
(
height:
24
.
h
),
Expanded
(
child:
_WideModeButton
(
label:
'睡眠模式'
,
icon:
Icons
.
nightlight_round
,
active:
currentMode
==
WindSpeedMode
.
sleep
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
const
DeviceControlWindSpeedModeChanged
(
WindSpeedMode
.
sleep
,
),
),
),
),
SizedBox
(
height:
18
.
h
),
Expanded
(
child:
_WideModeButton
(
label:
'舒适模式'
,
icon:
Icons
.
favorite_border
,
active:
currentMode
==
WindSpeedMode
.
comfort
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
const
DeviceControlWindSpeedModeChanged
(
WindSpeedMode
.
comfort
,
),
),
),
),
SizedBox
(
height:
18
.
h
),
Expanded
(
child:
_WideModeButton
(
label:
'强劲模式'
,
icon:
Icons
.
air
,
active:
currentMode
==
WindSpeedMode
.
strong
,
onTap:
()
=>
context
.
read
<
DeviceControlBloc
>().
add
(
const
DeviceControlWindSpeedModeChanged
(
WindSpeedMode
.
strong
,
),
),
),
),
],
),
],
)
,
);
}
,
);
}
}
...
...
@@ -44,34 +78,46 @@ class _WideModeButton extends StatelessWidget {
const
_WideModeButton
({
required
this
.
label
,
required
this
.
icon
,
this
.
active
=
false
,
this
.
onTap
,
});
final
String
label
;
final
IconData
icon
;
final
bool
active
;
final
VoidCallback
?
onTap
;
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
width:
double
.
infinity
,
decoration:
deviceControlButtonDecoration
(
backgroundAsset:
assetButton
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
),
child:
Row
(
children:
[
Icon
(
icon
,
color:
const
Color
(
0xFF7DC4EA
),
size:
52
.
w
),
SizedBox
(
width:
34
.
w
),
Expanded
(
child:
Text
(
label
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
26
.
sp
,
fontWeight:
FontWeight
.
w600
,
final
color
=
active
?
const
Color
(
0xFF45F36F
)
:
const
Color
(
0xFF7DC4EA
);
return
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
onTap
,
child:
Container
(
width:
double
.
infinity
,
decoration:
deviceControlButtonDecoration
(
active:
active
,
backgroundAsset:
assetButton
,
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
28
.
w
),
child:
Row
(
children:
[
Icon
(
icon
,
color:
color
,
size:
52
.
w
),
SizedBox
(
width:
34
.
w
),
Expanded
(
child:
Text
(
label
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
color:
color
,
fontSize:
26
.
sp
,
fontWeight:
FontWeight
.
w600
,
),
),
),
)
,
]
,
]
,
)
,
),
);
}
...
...
lib/views/monitoring/index/cubit/monitoring_index_cubit.dart
View file @
d6fc2a2b
...
...
@@ -36,6 +36,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
StreamSubscription
<
BluetoothConnectionStatus
>?
_bluetoothStateSub
;
StreamSubscription
<
String
>?
_bluetoothMessageSub
;
StreamSubscription
<
BluetoothDataPacket
>?
_bluetoothDataSub
;
StreamSubscription
<
BluetoothReadInfoChangedEvent
>?
_bluetoothReadInfoSub
;
StreamSubscription
<
McuReportChangedEvent
>?
_mcuReportChangedSub
;
StreamSubscription
<
LakiMqttConnectionState
>?
_mqttStateSub
;
StreamSubscription
<
LakiMqttMessage
>?
_mqttMessageSub
;
...
...
@@ -69,6 +70,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_listenWebrtcState
();
_listenP2pState
();
_listenBluetoothState
();
_listenBluetoothReadInfo
();
_listenMcuReportChanged
();
_loadBoundBluetoothDevice
();
loadData
();
...
...
@@ -178,13 +180,40 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
void
_listenMcuReportChanged
()
{
_mcuReportChangedSub
=
eventBus
.
on
<
McuReportChangedEvent
>().
listen
((
event
)
{
if
(
isClosed
)
return
;
final
metrics
=
_metricsFromBluetoothReport
(
event
.
report
);
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG index_metrics_from_report '
'
${_metricsLogText(metrics)}
'
,
);
emit
(
state
.
copyWith
(
latestMcuReport:
event
.
report
,
metrics:
_metricsFromBluetoothReport
(
event
.
report
)
,
metrics:
metrics
,
));
});
}
void
_listenBluetoothReadInfo
()
{
_bluetoothReadInfoSub
=
eventBus
.
on
<
BluetoothReadInfoChangedEvent
>().
listen
((
event
)
{
if
(
isClosed
)
return
;
final
metrics
=
_metricsFromBluetoothReadInfo
(
event
.
info
);
if
(
metrics
==
null
)
{
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG index_read_info_no_metrics '
'sn=
${event.info.sn}
temp=
${event.info.mainTemperature}
'
'humidity=
${event.info.humidity}
o2=
${event.info.oxygenConcentration}
'
'co2=
${event.info.co2Measurement}
'
,
);
return
;
}
Log
.
warn
(
'🔥🔥🔥 BLE_READ_DEBUG index_metrics_from_read_info '
'
${_metricsLogText(metrics)}
'
,
);
emit
(
state
.
copyWith
(
metrics:
metrics
));
});
}
String
_appendBluetoothSideToSn
(
String
sn
)
{
final
cleanSn
=
sn
.
trim
();
if
(
cleanSn
.
isEmpty
)
return
''
;
...
...
@@ -241,8 +270,8 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
));
try
{
final
metrics
=
await
_monitoringService
.
getMetrics
();
if
(
isClosed
)
return
;
//
final metrics = await _monitoringService.getMetrics();
//
if (isClosed) return;
final
patientInfo
=
await
_monitoringService
.
getPatientInfo
();
if
(
isClosed
)
return
;
final
alerts
=
await
_monitoringService
.
getAlerts
();
...
...
@@ -251,7 +280,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
emit
(
state
.
copyWith
(
status:
MonitoringIndexStatus
.
success
,
isLoading:
false
,
metrics:
metrics
,
patientInfo:
patientInfo
,
alerts:
alerts
,
error:
null
,
...
...
@@ -430,8 +458,8 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
Future
<
void
>
refreshData
()
async
{
try
{
final
metrics
=
await
_monitoringService
.
getMetrics
();
if
(
isClosed
)
return
;
//
final metrics = await _monitoringService.getMetrics();
//
if (isClosed) return;
final
patientInfo
=
await
_monitoringService
.
getPatientInfo
();
if
(
isClosed
)
return
;
final
alerts
=
await
_monitoringService
.
getAlerts
();
...
...
@@ -439,7 +467,6 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
emit
(
state
.
copyWith
(
status:
MonitoringIndexStatus
.
success
,
metrics:
metrics
,
patientInfo:
patientInfo
,
alerts:
alerts
,
error:
null
,
...
...
@@ -750,36 +777,98 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_mqttClient
=
null
;
}
List
<
MonitoringMetricBO
>
_metricsFromBluetoothReport
(
McuReport
report
)
{
List
<
MonitoringMetricBO
>
_metricsFromBluetoothReport
(
McuReport
report
,
{
List
<
MonitoringMetricBO
>?
baseMetrics
,
})
{
final
metrics
=
baseMetrics
??
state
.
metrics
;
final
replacements
=
<
String
,
MonitoringMetricBO
>{
'舱内温度'
:
_replaceMetricValue
(
'舱内温度'
,
_formatReportTemperatureOrKeep
(
report
.
mainTemperature
,
'舱内温度'
),
fallbackUnit:
'℃'
,
baseMetrics:
metrics
,
),
'舱内湿度'
:
_replaceMetricValue
(
'舱内湿度'
,
_formatReportIntOrKeep
(
report
.
humidity
,
'舱内湿度'
),
fallbackUnit:
'RH'
,
baseMetrics:
metrics
,
),
'氧气浓度'
:
_replaceMetricValue
(
'氧气浓度'
,
_formatReportIntOrKeep
(
report
.
oxygenConcentration
,
'氧气浓度'
),
fallbackUnit:
'%'
,
baseMetrics:
metrics
,
),
'二氧化碳'
:
_replaceMetricValue
(
'二氧化碳'
,
_formatReportIntOrKeep
(
report
.
co2Measurement
,
'二氧化碳'
),
fallbackUnit:
'ppm'
,
baseMetrics:
metrics
,
),
};
if
(
metrics
.
isEmpty
)
{
return
replacements
.
values
.
toList
();
}
return
[
for
(
final
metric
in
metrics
)
replacements
[
metric
.
label
]
??
metric
,
];
}
List
<
MonitoringMetricBO
>?
_metricsFromBluetoothReadInfo
(
BluetoothReadModel
info
,
)
{
final
hasMetric
=
info
.
mainTemperature
!=
null
||
info
.
humidity
!=
null
||
info
.
oxygenConcentration
!=
null
||
info
.
co2Measurement
!=
null
;
if
(!
hasMetric
)
return
null
;
final
metrics
=
state
.
metrics
;
final
replacements
=
<
String
,
MonitoringMetricBO
>{
'舱内温度'
:
_replaceMetricValue
(
'舱内温度'
,
_formatReportTemperature
(
report
.
mainTemperature
),
info
.
mainTemperature
==
null
?
_existingMetricValue
(
'舱内温度'
)
??
'--'
:
_formatReportTemperature
(
info
.
mainTemperature
!),
fallbackUnit:
'℃'
,
baseMetrics:
metrics
,
),
'舱内湿度'
:
_replaceMetricValue
(
'舱内湿度'
,
_formatReportInt
(
report
.
humidity
),
info
.
humidity
==
null
?
_existingMetricValue
(
'舱内湿度'
)
??
'--'
:
'
${info.humidity}
'
,
fallbackUnit:
'RH'
,
baseMetrics:
metrics
,
),
'氧气浓度'
:
_replaceMetricValue
(
'氧气浓度'
,
_formatReportInt
(
report
.
oxygenConcentration
),
info
.
oxygenConcentration
==
null
?
_existingMetricValue
(
'氧气浓度'
)
??
'--'
:
'
${info.oxygenConcentration}
'
,
fallbackUnit:
'%'
,
baseMetrics:
metrics
,
),
'二氧化碳'
:
_replaceMetricValue
(
'二氧化碳'
,
_formatReportInt
(
report
.
co2Measurement
),
info
.
co2Measurement
==
null
?
_existingMetricValue
(
'二氧化碳'
)
??
'--'
:
'
${info.co2Measurement}
'
,
fallbackUnit:
'ppm'
,
baseMetrics:
metrics
,
),
};
if
(
state
.
metrics
.
isEmpty
)
{
if
(
metrics
.
isEmpty
)
{
return
replacements
.
values
.
toList
();
}
return
[
for
(
final
metric
in
state
.
metrics
)
replacements
[
metric
.
label
]
??
metric
,
for
(
final
metric
in
metrics
)
replacements
[
metric
.
label
]
??
metric
,
];
}
...
...
@@ -787,9 +876,11 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
String
label
,
String
value
,
{
required
String
fallbackUnit
,
List
<
MonitoringMetricBO
>?
baseMetrics
,
})
{
final
metrics
=
baseMetrics
??
state
.
metrics
;
MonitoringMetricBO
?
existing
;
for
(
final
metric
in
state
.
metrics
)
{
for
(
final
metric
in
metrics
)
{
if
(
metric
.
label
==
label
)
{
existing
=
metric
;
break
;
...
...
@@ -817,8 +908,29 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
return
fixed
.
endsWith
(
'.0'
)
?
fixed
.
substring
(
0
,
fixed
.
length
-
2
)
:
fixed
;
}
String
_formatReportInt
(
int
value
)
{
return
value
<
0
?
'--'
:
'
$value
'
;
String
_formatReportTemperatureOrKeep
(
double
value
,
String
label
)
{
if
(!
value
.
isNaN
)
return
_formatReportTemperature
(
value
);
return
_existingMetricValue
(
label
)
??
'--'
;
}
String
_formatReportIntOrKeep
(
int
value
,
String
label
)
{
if
(
value
>=
0
)
return
'
$value
'
;
return
_existingMetricValue
(
label
)
??
'--'
;
}
String
?
_existingMetricValue
(
String
label
)
{
for
(
final
metric
in
state
.
metrics
)
{
if
(
metric
.
label
==
label
&&
metric
.
value
!=
'--'
)
{
return
metric
.
value
;
}
}
return
null
;
}
String
_metricsLogText
(
List
<
MonitoringMetricBO
>
metrics
)
{
return
metrics
.
map
((
item
)
=>
'
${item.label}
=
${item.value}${item.unit}
'
)
.
join
(
' '
);
}
/// 清空宠物信息(出舱)
...
...
@@ -907,6 +1019,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_bluetoothStateSub
?.
cancel
();
_bluetoothMessageSub
?.
cancel
();
_bluetoothDataSub
?.
cancel
();
_bluetoothReadInfoSub
?.
cancel
();
_mcuReportChangedSub
?.
cancel
();
_webrtcService
.
dispose
();
_p2pVideoService
.
dispose
();
...
...
lib/views/monitoring/index/monitoring_index_view.dart
View file @
d6fc2a2b
...
...
@@ -120,7 +120,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
children:
[
Expanded
(
flex:
32
,
child:
state
.
metrics
.
isEmpty
?
_buildMetricsEmpty
()
:
_buildMetrics
(
state
.
metrics
),
child:
_buildMetrics
(
state
.
metrics
),
),
SizedBox
(
height:
24
.
h
),
Expanded
(
...
...
@@ -157,6 +157,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
);
}
// ignore: unused_element
Widget
_buildMetricsEmpty
()
{
return
Container
(
width:
double
.
infinity
,
...
...
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