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
dd39c5b7
Commit
dd39c5b7
authored
Jun 23, 2026
by
张宏
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
重构设备控制页面。
parent
6106b9fe
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1094 additions
and
116 deletions
+1094
-116
box_no_device.png
lib/assets/monitoring/box_no_device.png
+0
-0
app_router.dart
lib/routes/app_router.dart
+8
-1
app_router.gr.dart
lib/routes/app_router.gr.dart
+0
-0
default_layout_cubit.dart
lib/views/layout/cubit/default_layout_cubit.dart
+2
-0
default_view.dart
lib/views/layout/default_view.dart
+1
-0
controller_index_cubit.dart
...s/monitoring/controller/cubit/controller_index_cubit.dart
+0
-13
controller_index_state.dart
...s/monitoring/controller/cubit/controller_index_state.dart
+0
-20
monitoring_controller_view.dart
...ews/monitoring/controller/monitoring_controller_view.dart
+0
-58
monitoring_environment_detail_view.dart
...ontroller/widgets/monitoring_environment_detail_view.dart
+0
-0
device_control_index_cubit.dart
...ring/device_control/cubit/device_control_index_cubit.dart
+68
-0
device_control_index_state.dart
...ring/device_control/cubit/device_control_index_state.dart
+45
-0
device_control_index_view.dart
.../monitoring/device_control/device_control_index_view.dart
+195
-0
device_control_care_panel.dart
...ing/device_control/widgets/device_control_care_panel.dart
+51
-0
device_control_common.dart
...itoring/device_control/widgets/device_control_common.dart
+266
-0
device_control_info_panel.dart
...ing/device_control/widgets/device_control_info_panel.dart
+68
-0
device_control_metric_card.dart
...ng/device_control/widgets/device_control_metric_card.dart
+122
-0
device_control_mode_panel.dart
...ing/device_control/widgets/device_control_mode_panel.dart
+94
-0
device_control_oxygen_timer_panel.dart
...ce_control/widgets/device_control_oxygen_timer_panel.dart
+50
-0
device_control_time_panel.dart
...ing/device_control/widgets/device_control_time_panel.dart
+37
-0
device_control_wind_panel.dart
...ing/device_control/widgets/device_control_wind_panel.dart
+78
-0
monitoring_index_view.dart
lib/views/monitoring/index/monitoring_index_view.dart
+9
-24
No files found.
lib/assets/monitoring/box_no_device.png
0 → 100644
View file @
dd39c5b7
This diff is collapsed.
Click to expand it.
lib/routes/app_router.dart
View file @
dd39c5b7
...
...
@@ -4,6 +4,7 @@ import 'package:auto_route/auto_route.dart';
import
'package:laki_icu_app/views/login/login_view.dart'
;
import
'package:laki_icu_app/views/layout/default_view.dart'
;
import
'package:laki_icu_app/views/monitoring/index/monitoring_index_view.dart'
;
import
'package:laki_icu_app/views/monitoring/device_control/device_control_index_view.dart'
;
import
'package:laki_icu_app/views/blood_pressure/blood_pressure_index_view.dart'
;
import
'package:laki_icu_app/views/vital_signs/vital_signs_index_view.dart'
;
import
'package:laki_icu_app/views/ecg_system/ecg_system_index_view.dart'
;
...
...
@@ -28,7 +29,10 @@ class AppRouter extends $AppRouter {
initial:
true
,
children:
[
// MonitoringIndexRoute / MonitoringIndexView(ICU中控 - Tab 0)
AutoRoute
(
page:
MonitoringIndexRoute
.
page
,
initial:
true
),
AutoRoute
(
page:
MonitoringIndexRoute
.
page
,
initial:
true
,
),
// BloodPressureIndexRoute / BloodPressureIndexView(血压监测 - Tab 1)
AutoRoute
(
page:
BloodPressureIndexRoute
.
page
),
// VitalSignsIndexRoute / VitalSignsIndexView(体征仪 - Tab 2)
...
...
@@ -41,7 +45,10 @@ class AppRouter extends $AppRouter {
AutoRoute
(
page:
RecordIndexRoute
.
page
),
// SettingsIndexRoute / SettingsIndexView(设置 - Tab 6)
AutoRoute
(
page:
SettingsIndexRoute
.
page
),
AutoRoute
(
page:
DeviceControlIndexRoute
.
page
),
],
),
];
}
lib/routes/app_router.gr.dart
View file @
dd39c5b7
This diff is collapsed.
Click to expand it.
lib/views/layout/cubit/default_layout_cubit.dart
View file @
dd39c5b7
...
...
@@ -17,6 +17,7 @@ const _menuIdToIndex = <String, int>{
'tsaas'
:
4
,
'record'
:
5
,
'settings'
:
6
,
'device_control'
:
7
};
const
_indexToMenuId
=
<
int
,
String
>{
...
...
@@ -27,6 +28,7 @@ const _indexToMenuId = <int, String>{
4
:
'tsaas'
,
5
:
'record'
,
6
:
'settings'
,
7
:
'device_control'
,
};
/// 将 Tab 索引转换为菜单 ID
...
...
lib/views/layout/default_view.dart
View file @
dd39c5b7
...
...
@@ -74,6 +74,7 @@ class _DefaultLayoutContent extends StatelessWidget {
TsaasIndexRoute
(),
RecordIndexRoute
(),
SettingsIndexRoute
(),
DeviceControlIndexRoute
(),
// index=7,该路由实际不在菜单栏。
],
appBarBuilder:
(
context
,
tabsRouter
)
{
return
PreferredSize
(
...
...
lib/views/monitoring/controller/cubit/controller_index_cubit.dart
deleted
100644 → 0
View file @
6106b9fe
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'controller_index_state.dart'
;
class
ControllerIndexCubit
extends
Cubit
<
ControllerIndexState
>
{
ControllerIndexCubit
({
required
String
selectedMetricLabel
,
})
:
super
(
ControllerIndexState
(
selectedMetricLabel:
selectedMetricLabel
));
void
selectMetric
(
String
label
)
{
emit
(
state
.
copyWith
(
selectedMetricLabel:
label
));
}
}
lib/views/monitoring/controller/cubit/controller_index_state.dart
deleted
100644 → 0
View file @
6106b9fe
import
'package:equatable/equatable.dart'
;
class
ControllerIndexState
extends
Equatable
{
final
String
selectedMetricLabel
;
const
ControllerIndexState
({
required
this
.
selectedMetricLabel
,
});
ControllerIndexState
copyWith
({
String
?
selectedMetricLabel
,
})
{
return
ControllerIndexState
(
selectedMetricLabel:
selectedMetricLabel
??
this
.
selectedMetricLabel
,
);
}
@override
List
<
Object
?>
get
props
=>
[
selectedMetricLabel
];
}
lib/views/monitoring/controller/monitoring_controller_view.dart
deleted
100644 → 0
View file @
6106b9fe
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'cubit/controller_index_cubit.dart'
;
import
'cubit/controller_index_state.dart'
;
import
'widgets/monitoring_environment_detail_view.dart'
;
class
MonitoringControllerView
extends
StatelessWidget
{
const
MonitoringControllerView
({
super
.
key
,
required
this
.
metrics
,
required
this
.
selectedMetricLabel
,
required
this
.
onBack
,
});
final
List
<
MonitoringMetricBO
>
metrics
;
final
String
selectedMetricLabel
;
final
VoidCallback
onBack
;
@override
Widget
build
(
BuildContext
context
)
{
return
BlocProvider
(
create:
(
_
)
=>
ControllerIndexCubit
(
selectedMetricLabel:
selectedMetricLabel
,
),
child:
ControllerIndexContent
(
metrics:
metrics
,
onBack:
onBack
,
),
);
}
}
class
ControllerIndexContent
extends
StatelessWidget
{
const
ControllerIndexContent
({
super
.
key
,
required
this
.
metrics
,
required
this
.
onBack
,
});
final
List
<
MonitoringMetricBO
>
metrics
;
final
VoidCallback
onBack
;
@override
Widget
build
(
BuildContext
context
)
{
return
BlocBuilder
<
ControllerIndexCubit
,
ControllerIndexState
>(
builder:
(
context
,
state
)
{
return
MonitoringEnvironmentDetailView
(
metrics:
metrics
,
selectedLabel:
state
.
selectedMetricLabel
,
onBack:
onBack
,
onMetricSelected:
context
.
read
<
ControllerIndexCubit
>().
selectMetric
,
);
},
);
}
}
lib/views/monitoring/controller/widgets/monitoring_environment_detail_view.dart
deleted
100644 → 0
View file @
6106b9fe
This diff is collapsed.
Click to expand it.
lib/views/monitoring/device_control/cubit/device_control_index_cubit.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'package:laki_icu_app/services/monitoring_service.dart'
;
import
'device_control_index_state.dart'
;
class
DeviceControlIndexCubit
extends
Cubit
<
DeviceControlIndexState
>
{
final
MonitoringService
_monitoringService
;
DeviceControlIndexCubit
({
MonitoringService
?
monitoringService
,
})
:
_monitoringService
=
monitoringService
??
MonitoringService
(),
super
(
DeviceControlIndexState
())
{
loadMetrics
();
}
void
selectMetric
(
String
label
)
{
emit
(
state
.
copyWith
(
selectedMetricLabel:
label
));
}
Future
<
void
>
loadMetrics
()
async
{
emit
(
state
.
copyWith
(
status:
DeviceControlIndexStatus
.
loading
,
isLoading:
true
,
error:
null
,
));
try
{
final
allMetrics
=
await
_monitoringService
.
getMetrics
();
final
envMetrics
=
_environmentMetrics
(
allMetrics
);
emit
(
state
.
copyWith
(
status:
DeviceControlIndexStatus
.
success
,
isLoading:
false
,
metrics:
envMetrics
,
error:
null
,
));
}
catch
(
e
)
{
emit
(
state
.
copyWith
(
status:
DeviceControlIndexStatus
.
failure
,
isLoading:
false
,
error:
e
.
toString
(),
));
}
}
/// 过滤出环境指标(温度/湿度/氧气/二氧化碳),最多取4个
List
<
MonitoringMetricBO
>
_environmentMetrics
(
List
<
MonitoringMetricBO
>
metrics
)
{
final
matched
=
metrics
.
where
((
item
)
=>
item
.
label
.
contains
(
'温度'
)
||
item
.
label
.
contains
(
'湿度'
)
||
item
.
label
.
contains
(
'氧气'
)
||
item
.
label
.
contains
(
'二氧化碳'
)
||
item
.
label
.
toUpperCase
().
contains
(
'CO'
))
.
take
(
4
)
.
toList
();
if
(
matched
.
length
==
4
)
return
matched
;
return
const
[
MonitoringMetricBO
(
value:
'--'
,
unit:
'℃'
,
label:
'舱内温度'
),
MonitoringMetricBO
(
value:
'--'
,
unit:
'RH'
,
label:
'舱内湿度'
),
MonitoringMetricBO
(
value:
'--'
,
unit:
'%'
,
label:
'氧气浓度'
),
MonitoringMetricBO
(
value:
'--'
,
unit:
'%'
,
label:
'二氧化碳'
),
];
}
}
lib/views/monitoring/device_control/cubit/device_control_index_state.dart
0 → 100644
View file @
dd39c5b7
import
'package:equatable/equatable.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
enum
DeviceControlIndexStatus
{
initial
,
loading
,
success
,
failure
}
class
DeviceControlIndexState
extends
Equatable
{
final
DeviceControlIndexStatus
status
;
final
bool
isLoading
;
final
String
?
error
;
final
List
<
MonitoringMetricBO
>
metrics
;
final
String
selectedMetricLabel
;
const
DeviceControlIndexState
({
this
.
status
=
DeviceControlIndexStatus
.
initial
,
this
.
isLoading
=
false
,
this
.
error
,
this
.
metrics
=
const
[],
this
.
selectedMetricLabel
=
''
,
});
DeviceControlIndexState
copyWith
({
DeviceControlIndexStatus
?
status
,
bool
?
isLoading
,
String
?
error
,
List
<
MonitoringMetricBO
>?
metrics
,
String
?
selectedMetricLabel
,
})
{
return
DeviceControlIndexState
(
status:
status
??
this
.
status
,
isLoading:
isLoading
??
this
.
isLoading
,
error:
error
??
this
.
error
,
metrics:
metrics
??
this
.
metrics
,
selectedMetricLabel:
selectedMetricLabel
??
this
.
selectedMetricLabel
,
);
}
@override
List
<
Object
?>
get
props
=>
[
status
,
isLoading
,
error
,
metrics
,
selectedMetricLabel
,
];
}
lib/views/monitoring/device_control/device_control_index_view.dart
0 → 100644
View file @
dd39c5b7
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/models/bo/monitoring_bo.dart'
;
import
'cubit/device_control_index_cubit.dart'
;
import
'cubit/device_control_index_state.dart'
;
import
'widgets/device_control_care_panel.dart'
;
import
'widgets/device_control_info_panel.dart'
;
import
'widgets/device_control_metric_card.dart'
;
import
'widgets/device_control_mode_panel.dart'
;
import
'widgets/device_control_oxygen_timer_panel.dart'
;
import
'widgets/device_control_time_panel.dart'
;
import
'widgets/device_control_wind_panel.dart'
;
@RoutePage
()
class
DeviceControlIndexView
extends
StatelessWidget
{
const
DeviceControlIndexView
({
super
.
key
,
// this.selectedMetricLabel = '',
});
// final String selectedMetricLabel;
@override
Widget
build
(
BuildContext
context
)
{
return
BlocProvider
(
create:
(
_
)
=>
DeviceControlIndexCubit
(),
child:
const
DeviceControlIndexContent
(),
);
}
}
class
DeviceControlIndexContent
extends
StatelessWidget
{
const
DeviceControlIndexContent
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
BlocBuilder
<
DeviceControlIndexCubit
,
DeviceControlIndexState
>(
builder:
(
context
,
state
)
{
if
(
state
.
isLoading
&&
state
.
metrics
.
isEmpty
)
{
return
const
Scaffold
(
backgroundColor:
Color
(
0xFF010B1D
),
body:
Center
(
child:
CircularProgressIndicator
(
color:
Colors
.
white
),
),
);
}
if
(
state
.
status
==
DeviceControlIndexStatus
.
failure
&&
state
.
metrics
.
isEmpty
)
{
return
Scaffold
(
backgroundColor:
const
Color
(
0xFF010B1D
),
body:
Center
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Text
(
'加载失败:
${state.error ?? "未知错误"}
'
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
22
.
sp
),
),
SizedBox
(
height:
22
.
h
),
ElevatedButton
(
onPressed:
()
=>
context
.
read
<
DeviceControlIndexCubit
>().
loadMetrics
(),
child:
const
Text
(
'重试'
),
),
],
),
),
);
}
return
_DeviceControlLayout
(
metrics:
state
.
metrics
,
selectedLabel:
state
.
selectedMetricLabel
,
onBack:
()
=>
context
.
router
.
popForced
(),
onMetricSelected:
context
.
read
<
DeviceControlIndexCubit
>().
selectMetric
,
);
},
);
}
}
/// 设备控制主布局
class
_DeviceControlLayout
extends
StatelessWidget
{
const
_DeviceControlLayout
({
required
this
.
metrics
,
required
this
.
selectedLabel
,
required
this
.
onBack
,
required
this
.
onMetricSelected
,
});
final
List
<
MonitoringMetricBO
>
metrics
;
final
String
selectedLabel
;
final
VoidCallback
onBack
;
final
ValueChanged
<
String
>
onMetricSelected
;
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
backgroundColor:
const
Color
(
0xFF010B1D
),
body:
SafeArea
(
maintainBottomViewPadding:
true
,
child:
Row
(
children:
[
Expanded
(
flex:
74
,
child:
Column
(
children:
[
Expanded
(
flex:
42
,
child:
Row
(
children:
[
for
(
int
index
=
0
;
index
<
metrics
.
length
;
index
++)
...[
Expanded
(
child:
DeviceControlMetricCard
(
metric:
metrics
[
index
],
),
),
if
(
index
<
metrics
.
length
-
1
)
SizedBox
(
width:
24
.
w
),
],
],
),
),
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
(),
),
],
),
),
],
),
),
SizedBox
(
width:
24
.
w
),
Expanded
(
flex:
26
,
child:
Column
(
children:
[
const
Expanded
(
flex:
21
,
child:
DeviceControlCarePanel
()),
SizedBox
(
height:
24
.
h
),
const
Expanded
(
flex:
20
,
child:
DeviceControlInfoPanel
(
title:
'新风进化'
,
actionText:
'Auto'
,
icon:
Icons
.
cyclone
,
body:
'CO₂超过设定值时自动启动外循环
\n
净化,当降至2000ppm后,本
\n
功能自动关闭'
,
),
),
SizedBox
(
height:
24
.
h
),
const
Expanded
(
flex:
20
,
child:
DeviceControlInfoPanel
(
title:
'开放供氧'
,
actionText:
'Off'
,
icon:
Icons
.
air
,
body:
'开启后风扇打开、制冷、加热和
\n
循环等设备暂停。'
,
warning:
'*保持设备周围空气相对禁止,严禁烟火'
,
),
),
SizedBox
(
height:
24
.
h
),
const
Expanded
(
flex:
26
,
child:
DeviceControlOxygenTimerPanel
(),
),
],
),
),
],
),
),
);
}
}
lib/views/monitoring/device_control/widgets/device_control_care_panel.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'device_control_common.dart'
;
/// 护理等级面板
class
DeviceControlCarePanel
extends
StatelessWidget
{
const
DeviceControlCarePanel
({
super
.
key
});
@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
),
],
),
),
),
SizedBox
(
height:
24
.
h
),
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
for
(
final
item
in
const
[
'关闭'
,
'三级'
,
'二级'
,
'一级'
,
'特级'
])
Text
(
item
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
24
.
sp
),
),
],
),
],
),
);
}
}
lib/views/monitoring/device_control/widgets/device_control_common.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
// -- 资源常量 --
const
String
assetMetricBlue
=
'lib/assets/monitoring/box_bg_325x372.png'
;
const
String
assetMetricGreen
=
'lib/assets/monitoring/frame_card_green_325x372.png'
;
const
String
assetPanelWide
=
'lib/assets/monitoring/frame_button_324x164.png'
;
const
String
assetPanelLarge
=
'lib/assets/monitoring/frame_panel_674x509.png'
;
const
String
assetPanelTall
=
'lib/assets/monitoring/box_bg_460x905.png'
;
const
String
assetButton
=
'lib/assets/monitoring/frame_button_324x164.png'
;
const
String
assetArrowButton
=
'lib/assets/monitoring/frame_button_arrows_561x637.png'
;
/// 面板外框容器
class
DeviceControlPanelFrame
extends
StatelessWidget
{
const
DeviceControlPanelFrame
({
super
.
key
,
required
this
.
child
,
required
this
.
padding
,
this
.
active
=
false
,
this
.
backgroundAsset
,
});
final
Widget
child
;
final
EdgeInsetsGeometry
padding
;
final
bool
active
;
final
String
?
backgroundAsset
;
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
width:
double
.
infinity
,
height:
double
.
infinity
,
padding:
padding
,
decoration:
BoxDecoration
(
color:
backgroundAsset
==
null
?
active
?
const
Color
(
0xFF003F14
).
withValues
(
alpha:
0.92
)
:
const
Color
(
0xFF061C34
).
withValues
(
alpha:
0.92
)
:
null
,
image:
backgroundAsset
==
null
?
null
:
DecorationImage
(
image:
AssetImage
(
backgroundAsset
!),
fit:
BoxFit
.
fill
,
),
border:
backgroundAsset
==
null
?
Border
.
all
(
color:
active
?
const
Color
(
0xFF3EFF5F
)
:
const
Color
(
0xFF89DFFF
),
width:
3
.
w
,
)
:
null
,
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
boxShadow:
[
BoxShadow
(
color:
(
active
?
const
Color
(
0xFF3EFF5F
)
:
const
Color
(
0xFF4FC8FF
))
.
withValues
(
alpha:
0.32
),
blurRadius:
18
.
r
,
spreadRadius:
2
.
r
,
),
],
),
child:
child
,
);
}
}
/// 面板标题
class
DeviceControlPanelTitle
extends
StatelessWidget
{
const
DeviceControlPanelTitle
(
this
.
text
,
{
super
.
key
});
final
String
text
;
@override
Widget
build
(
BuildContext
context
)
{
return
Text
(
text
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
w700
,
),
);
}
}
/// 圆角标签
class
DeviceControlPill
extends
StatelessWidget
{
const
DeviceControlPill
({
super
.
key
,
required
this
.
text
,
this
.
active
=
false
,
});
final
String
text
;
final
bool
active
;
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
height:
40
.
h
,
constraints:
BoxConstraints
(
minWidth:
90
.
w
),
padding:
EdgeInsets
.
symmetric
(
horizontal:
18
.
w
),
alignment:
Alignment
.
center
,
decoration:
BoxDecoration
(
color:
Colors
.
white
.
withValues
(
alpha:
active
?
0.14
:
0.06
),
border:
Border
.
all
(
color:
active
?
const
Color
(
0xFF52FFBB
)
:
const
Color
(
0xFF75C1DD
),
width:
1
.
w
,
),
borderRadius:
BorderRadius
.
circular
(
20
.
r
),
),
child:
Text
(
text
,
style:
TextStyle
(
color:
active
?
const
Color
(
0xFF52FFBB
)
:
const
Color
(
0xFF75C1DD
),
fontSize:
22
.
sp
,
fontWeight:
FontWeight
.
w700
,
),
),
);
}
}
/// 加减调节文字
class
DeviceControlAdjustText
extends
StatelessWidget
{
const
DeviceControlAdjustText
(
this
.
text
,
{
super
.
key
,
this
.
active
=
false
});
final
String
text
;
final
bool
active
;
@override
Widget
build
(
BuildContext
context
)
{
return
Text
(
text
,
style:
TextStyle
(
color:
active
?
const
Color
(
0xFF20E5FF
)
:
const
Color
(
0xFF4B7191
),
fontSize:
58
.
sp
,
height:
1
,
fontWeight:
FontWeight
.
w700
,
),
);
}
}
/// 大号操作按钮
class
DeviceControlBigActionButton
extends
StatelessWidget
{
const
DeviceControlBigActionButton
({
super
.
key
,
required
this
.
text
});
final
String
text
;
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
width:
double
.
infinity
,
height:
64
.
h
,
decoration:
deviceControlButtonDecoration
(
backgroundAsset:
assetButton
),
alignment:
Alignment
.
center
,
child:
Text
(
'《《
$text
》》'
,
style:
TextStyle
(
color:
const
Color
(
0xFFC9F8FF
),
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
w700
,
),
),
);
}
}
/// 数字值展示框
class
DeviceControlDigitalValueBox
extends
StatelessWidget
{
const
DeviceControlDigitalValueBox
({
super
.
key
,
required
this
.
value
,
required
this
.
unit
,
this
.
active
=
false
,
});
final
String
value
;
final
String
unit
;
final
bool
active
;
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
width:
double
.
infinity
,
decoration:
deviceControlButtonDecoration
(
active:
active
,
backgroundAsset:
assetButton
,
),
alignment:
Alignment
.
center
,
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Text
(
value
,
style:
TextStyle
(
color:
active
?
const
Color
(
0xFFC8FFFF
)
:
Colors
.
white
,
fontSize:
46
.
sp
,
letterSpacing:
2
,
fontWeight:
FontWeight
.
w500
,
),
),
SizedBox
(
width:
28
.
w
),
Text
(
unit
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
30
.
sp
,
fontWeight:
FontWeight
.
w600
,
),
),
],
),
);
}
}
/// 按钮装饰(公共样式)
BoxDecoration
deviceControlButtonDecoration
(
{
bool
active
=
false
,
String
?
backgroundAsset
,
})
{
return
BoxDecoration
(
color:
backgroundAsset
==
null
?
active
?
const
Color
(
0xFF063F1A
).
withValues
(
alpha:
0.96
)
:
const
Color
(
0xFF0A243F
).
withValues
(
alpha:
0.96
)
:
null
,
image:
backgroundAsset
==
null
?
null
:
DecorationImage
(
image:
AssetImage
(
backgroundAsset
),
fit:
BoxFit
.
fill
,
),
border:
backgroundAsset
==
null
?
Border
.
all
(
color:
active
?
const
Color
(
0xFF2DF765
)
:
const
Color
(
0xFF66BDE8
),
width:
2
,
)
:
null
,
borderRadius:
BorderRadius
.
circular
(
6
),
);
}
/// 指标图标资源映射
String
deviceControlIconAsset
(
String
label
)
{
if
(
label
.
contains
(
'温度'
))
{
return
'lib/assets/monitoring/cabin_temperature.png'
;
}
if
(
label
.
contains
(
'湿度'
))
{
return
'lib/assets/monitoring/cabin_humidity.png'
;
}
if
(
label
.
contains
(
'氧气'
))
{
return
'lib/assets/monitoring/oxygen_concentration.png'
;
}
return
'lib/assets/monitoring/carbon_dioxide_concentration.png'
;
}
lib/views/monitoring/device_control/widgets/device_control_info_panel.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'device_control_common.dart'
;
/// 信息展示面板(新风进化/开放供氧 等)
class
DeviceControlInfoPanel
extends
StatelessWidget
{
const
DeviceControlInfoPanel
({
super
.
key
,
required
this
.
title
,
required
this
.
actionText
,
required
this
.
icon
,
required
this
.
body
,
this
.
warning
,
});
final
String
title
;
final
String
actionText
;
final
IconData
icon
;
final
String
body
;
final
String
?
warning
;
@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
,
),
),
),
],
),
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
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'device_control_common.dart'
;
/// 环境指标控制卡片(温度/湿度/氧气/二氧化碳)
class
DeviceControlMetricCard
extends
StatelessWidget
{
const
DeviceControlMetricCard
({
super
.
key
,
required
this
.
metric
});
final
MonitoringMetricBO
metric
;
@override
Widget
build
(
BuildContext
context
)
{
final
isOxygen
=
metric
.
label
.
contains
(
'氧气'
);
final
isCo2
=
metric
.
label
.
contains
(
'二氧化碳'
)
||
metric
.
label
.
toUpperCase
().
contains
(
'CO'
);
return
DeviceControlPanelFrame
(
active:
isOxygen
,
backgroundAsset:
isOxygen
?
assetMetricGreen
:
assetMetricBlue
,
padding:
EdgeInsets
.
fromLTRB
(
32
.
w
,
26
.
h
,
32
.
w
,
28
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
children:
[
Expanded
(
child:
DeviceControlPanelTitle
(
_title
(
metric
.
label
)),
),
DeviceControlPill
(
text:
isOxygen
?
'ON'
:
isCo2
?
'PPM'
:
'Off'
,
active:
isOxygen
,
),
],
),
const
Spacer
(),
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
end
,
children:
[
Text
(
metric
.
value
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
isCo2
?
60
.
sp
:
82
.
sp
,
height:
0.9
,
fontWeight:
FontWeight
.
bold
,
),
),
SizedBox
(
width:
12
.
w
),
Padding
(
padding:
EdgeInsets
.
only
(
bottom:
8
.
h
),
child:
Text
(
isCo2
?
''
:
metric
.
unit
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
w600
,
),
),
),
const
Spacer
(),
Image
.
asset
(
deviceControlIconAsset
(
metric
.
label
),
width:
72
.
w
,
height:
72
.
w
,
fit:
BoxFit
.
contain
,
),
],
),
Divider
(
color:
Colors
.
white
.
withValues
(
alpha:
0.18
),
height:
28
.
h
),
Text
(
isCo2
?
'告警阈值设定'
:
metric
.
label
.
contains
(
'温度'
)
?
'温度设定'
:
'湿度设定'
,
style:
TextStyle
(
color:
Colors
.
white
.
withValues
(
alpha:
0.78
),
fontSize:
26
.
sp
,
),
),
const
Spacer
(),
Row
(
children:
[
DeviceControlAdjustText
(
'-'
,
active:
isOxygen
||
!
isCo2
),
const
Spacer
(),
Text
(
isCo2
?
'4000'
:
isOxygen
?
'90'
:
metric
.
label
.
contains
(
'湿度'
)
?
'10'
:
'24'
,
style:
TextStyle
(
color:
isCo2
?
const
Color
(
0xFFFFC400
)
:
const
Color
(
0xFF00B7F4
),
fontSize:
64
.
sp
,
height:
1
,
fontWeight:
FontWeight
.
bold
,
),
),
const
Spacer
(),
const
DeviceControlAdjustText
(
'+'
,
active:
true
),
],
),
],
),
);
}
static
String
_title
(
String
label
)
{
if
(
label
.
contains
(
'二氧化碳'
))
return
'二氧化碳浓度'
;
return
label
;
}
}
lib/views/monitoring/device_control/widgets/device_control_mode_panel.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'device_control_common.dart'
;
/// 模式切换面板(外循环/检查灯/照明灯/内循环/蓝光/红光)
class
DeviceControlModePanel
extends
StatelessWidget
{
const
DeviceControlModePanel
({
super
.
key
});
@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
,
),
],
),
);
}
}
class
_ModeButton
extends
StatelessWidget
{
const
_ModeButton
({
required
this
.
label
,
required
this
.
icon
,
this
.
active
=
false
,
});
final
String
label
;
final
IconData
icon
;
final
bool
active
;
@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
,
),
),
],
),
);
}
}
class
_ModeItem
{
final
String
label
;
final
IconData
icon
;
final
bool
active
;
const
_ModeItem
({
required
this
.
label
,
required
this
.
icon
,
this
.
active
=
false
,
});
}
lib/views/monitoring/device_control/widgets/device_control_oxygen_timer_panel.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'device_control_common.dart'
;
/// 供氧计时 + ICU重置面板
class
DeviceControlOxygenTimerPanel
extends
StatelessWidget
{
const
DeviceControlOxygenTimerPanel
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
DeviceControlPanelFrame
(
backgroundAsset:
assetPanelWide
,
padding:
EdgeInsets
.
fromLTRB
(
30
.
w
,
26
.
h
,
30
.
w
,
28
.
h
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
const
DeviceControlPanelTitle
(
'供氧计时'
),
const
Spacer
(),
Row
(
children:
[
Text
(
'00:00:00'
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
42
.
sp
,
letterSpacing:
2
,
fontWeight:
FontWeight
.
w500
,
),
),
const
Spacer
(),
const
DeviceControlPill
(
text:
'清零'
),
],
),
Divider
(
color:
Colors
.
white
.
withValues
(
alpha:
0.16
),
height:
38
.
h
),
Text
(
'ICU舱设置重置'
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
w600
,
),
),
const
Spacer
(),
const
DeviceControlBigActionButton
(
text:
'初始化设置'
),
],
),
);
}
}
lib/views/monitoring/device_control/widgets/device_control_time_panel.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'device_control_common.dart'
;
/// 设置雾化/消毒时间面板
class
DeviceControlTimePanel
extends
StatelessWidget
{
const
DeviceControlTimePanel
({
super
.
key
});
@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
,
),
),
],
),
);
}
}
lib/views/monitoring/device_control/widgets/device_control_wind_panel.dart
0 → 100644
View file @
dd39c5b7
import
'package:flutter/material.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'device_control_common.dart'
;
/// 风速调节面板
class
DeviceControlWindPanel
extends
StatelessWidget
{
const
DeviceControlWindPanel
({
super
.
key
});
@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
),
),
],
),
);
}
}
class
_WideModeButton
extends
StatelessWidget
{
const
_WideModeButton
({
required
this
.
label
,
required
this
.
icon
,
});
final
String
label
;
final
IconData
icon
;
@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
,
),
),
),
],
),
);
}
}
lib/views/monitoring/index/monitoring_index_view.dart
View file @
dd39c5b7
...
...
@@ -8,7 +8,7 @@ import 'package:laki_icu_app/enums/video_stream_mode_enum.dart';
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'package:laki_icu_app/utils/event_bus.dart'
;
import
'../controller/monitoring_controller_view.dart'
;
import
'cubit/monitoring_index_cubit.dart'
;
import
'cubit/monitoring_index_state.dart'
;
import
'widgets/bluetooth_bind_dialog.dart'
;
...
...
@@ -40,7 +40,6 @@ class MonitoringIndexContent extends StatefulWidget {
class
_MonitoringIndexContentState
extends
State
<
MonitoringIndexContent
>
{
late
final
MonitoringIndexCubit
_monitoringIndexCubit
;
StreamSubscription
<
OpenBluetoothScanEvent
>?
_bluetoothScanEventSub
;
String
?
_selectedEnvironmentMetricLabel
;
@override
void
initState
()
{
...
...
@@ -71,9 +70,6 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
state
.
metrics
.
isEmpty
)
{
return
_buildError
(
state
.
error
);
}
if
(
_selectedEnvironmentMetricLabel
!=
null
)
{
return
_buildEnvironmentDetail
(
state
);
}
return
_buildMainArea
(
state
);
},
);
...
...
@@ -116,7 +112,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
children:
[
Expanded
(
flex:
32
,
child:
_buildMetrics
(
state
.
metrics
),
child:
state
.
metrics
.
isEmpty
?
_buildMetricsEmpty
()
:
_buildMetrics
(
state
.
metrics
),
),
SizedBox
(
height:
24
.
h
),
Expanded
(
...
...
@@ -153,6 +149,10 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
);
}
Widget
_buildMetricsEmpty
()
{
return
Text
(
"data"
);
}
Widget
_buildMetrics
(
List
<
MonitoringMetricBO
>
metrics
)
{
final
displayMetrics
=
_environmentMetrics
(
metrics
);
final
children
=
<
Widget
>[];
...
...
@@ -161,7 +161,7 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
Expanded
(
child:
MonitoringMetricCard
(
metric:
displayMetrics
[
i
],
onTap:
()
=>
_open
EnvironmentDetai
l
(
displayMetrics
[
i
]),
onTap:
()
=>
_open
DeviceContro
l
(
displayMetrics
[
i
]),
),
),
);
...
...
@@ -174,23 +174,8 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
);
}
Widget
_buildEnvironmentDetail
(
MonitoringIndexState
state
)
{
final
metrics
=
_environmentMetrics
(
state
.
metrics
);
return
MonitoringControllerView
(
metrics:
metrics
,
selectedMetricLabel:
_selectedEnvironmentMetricLabel
!,
onBack:
()
{
setState
(()
{
_selectedEnvironmentMetricLabel
=
null
;
});
},
);
}
void
_openEnvironmentDetail
(
MonitoringMetricBO
metric
)
{
setState
(()
{
_selectedEnvironmentMetricLabel
=
metric
.
label
;
});
void
_openDeviceControl
(
MonitoringMetricBO
metric
)
{
context
.
tabsRouter
.
setActiveIndex
(
7
);
}
/// 模式切换回调
...
...
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