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
65c9e3b0
Commit
65c9e3b0
authored
Jun 24, 2026
by
akari
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
http://git.ruanyiit.com/zhanghong/laki_icu_app
parents
45154e91
83539172
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
814 additions
and
62 deletions
+814
-62
dev.json
env/dev.json
+1
-1
dialog_alert_bg.png
lib/assets/monitoring/dialog_alert_bg.png
+0
-0
bluetooth_read_bloc.dart
lib/blocs/bluetooth_read/bluetooth_read_bloc.dart
+28
-3
cabin_detail_response.dart
lib/models/bo/cabin_detail_response.dart
+0
-0
camera_alarm_bo.dart
lib/models/bo/camera_alarm_bo.dart
+75
-0
cabin_repository.dart
lib/repositories/cabin_repository.dart
+38
-0
cabin_mock_data.dart
lib/repositories/mock/cabin_mock_data.dart
+84
-0
cabin_service.dart
lib/services/cabin_service.dart
+20
-0
monitoring_index_cubit.dart
lib/views/monitoring/index/cubit/monitoring_index_cubit.dart
+188
-7
monitoring_index_state.dart
lib/views/monitoring/index/cubit/monitoring_index_state.dart
+28
-0
monitoring_index_view.dart
lib/views/monitoring/index/monitoring_index_view.dart
+37
-12
monitoring_alert_card.dart
...views/monitoring/index/widgets/monitoring_alert_card.dart
+45
-39
monitoring_alert_detail_dialog.dart
...itoring/index/widgets/monitoring_alert_detail_dialog.dart
+270
-0
No files found.
env/dev.json
View file @
65c9e3b0
{
{
"APP_ENV"
:
"dev"
,
"APP_ENV"
:
"dev"
,
"SERVICE_URL"
:
"http://1
21.41.173.189/laki-merchant-service
"
"SERVICE_URL"
:
"http://1
92.168.112.129:8089
"
}
}
lib/assets/monitoring/dialog_alert_bg.png
0 → 100644
View file @
65c9e3b0
This diff is collapsed.
Click to expand it.
lib/blocs/bluetooth_read/bluetooth_read_bloc.dart
View file @
65c9e3b0
...
@@ -38,9 +38,34 @@ class BluetoothReadBloc extends Bloc<BluetoothReadEvent, BluetoothReadState> {
...
@@ -38,9 +38,34 @@ class BluetoothReadBloc extends Bloc<BluetoothReadEvent, BluetoothReadState> {
)
async
{
)
async
{
emit
(
state
.
copyWith
(
isLoading:
true
,
clearError:
true
));
emit
(
state
.
copyWith
(
isLoading:
true
,
clearError:
true
));
try
{
try
{
final
info
=
await
_storageService
.
getBluetoothReadInfo
();
BluetoothReadModel
?
info
;
Log
.
warn
(
'**************sn************:
${info.sn}
'
);
const
maxRetries
=
5
;
emit
(
state
.
copyWith
(
info:
info
,
isLoading:
false
,
clearError:
true
));
const
retryInterval
=
Duration
(
seconds:
10
);
for
(
int
i
=
0
;
i
<
maxRetries
;
i
++)
{
try
{
info
=
await
_storageService
.
getBluetoothReadInfo
();
Log
.
warn
(
'**************sn 第
${i + 1}
次获取************:
${info.sn}
'
);
if
(
info
.
hasSn
)
{
Log
.
warn
(
'**************sn 获取成功,停止重试************'
);
break
;
}
}
catch
(
e
)
{
Log
.
warn
(
'**************sn 第
${i + 1}
次获取失败:
$e
************'
);
}
// 如果还没获取到sn且不是最后一次,则等待后重试
if
(
i
<
maxRetries
-
1
&&
(
info
==
null
||
!
info
.
hasSn
))
{
await
Future
.
delayed
(
retryInterval
);
}
}
emit
(
state
.
copyWith
(
info:
info
??
BluetoothReadModel
.
empty
,
isLoading:
false
,
clearError:
true
,
));
}
catch
(
e
)
{
}
catch
(
e
)
{
emit
(
state
.
copyWith
(
isLoading:
false
,
error:
e
.
toString
()));
emit
(
state
.
copyWith
(
isLoading:
false
,
error:
e
.
toString
()));
}
}
...
...
lib/models/bo/cabin_detail_response.dart
0 → 100644
View file @
65c9e3b0
This diff is collapsed.
Click to expand it.
lib/models/bo/camera_alarm_bo.dart
0 → 100644
View file @
65c9e3b0
/// MQTT 摄像头告警消息数据模型
/// 对应 topic: camera/{cabinSn}/to 中 type="abnormal_behavior" 的消息
///
/// 与 Android 项目 qisuanfa_0621 MqttManager.processControlCommand() 保持一致:
/// - 只提取 behaviorCode 和 timestamp 两个字段用于标题映射
/// - 其余字段保留解析,方便后续扩展
class
CameraAlarmBO
{
/// 事件唯一标识(UUID 去横线),用于去重
final
String
eventId
;
/// 仓 SN
final
String
deviceId
;
/// 设备类型,固定 "camera"
final
String
deviceType
;
/// 毫秒时间戳
final
int
timestamp
;
/// 消息类型,如 "abnormal_behavior"
final
String
type
;
/// 告警 ID
final
int
alarmId
;
/// 告警类别
final
String
alarmType
;
/// 行为编码
final
int
?
behaviorCode
;
/// 行为描述
final
String
?
behaviorDesc
;
/// 宠物名称
final
String
?
petName
;
const
CameraAlarmBO
({
required
this
.
eventId
,
required
this
.
deviceId
,
required
this
.
deviceType
,
required
this
.
timestamp
,
required
this
.
type
,
required
this
.
alarmId
,
required
this
.
alarmType
,
this
.
behaviorCode
,
this
.
behaviorDesc
,
this
.
petName
,
});
factory
CameraAlarmBO
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
{
return
CameraAlarmBO
(
eventId:
json
[
'eventId'
]
as
String
?
??
''
,
deviceId:
json
[
'deviceId'
]
as
String
?
??
''
,
deviceType:
json
[
'deviceType'
]
as
String
?
??
''
,
timestamp:
json
[
'timestamp'
]
as
int
?
??
0
,
type:
json
[
'type'
]
as
String
?
??
''
,
alarmId:
json
[
'alarmId'
]
as
int
?
??
0
,
alarmType:
json
[
'alarmType'
]
as
String
?
??
''
,
behaviorCode:
json
[
'behaviorCode'
]
as
int
?,
behaviorDesc:
json
[
'behaviorDesc'
]
as
String
?,
petName:
json
[
'petName'
]
as
String
?,
);
}
/// 与 Android 行为编码映射完全一致:
/// 2 → 异常液体
/// 3 → 检测到排泄物
/// 其他 → 未知异常
String
get
titleByBehaviorCode
{
if
(
behaviorCode
==
2
)
return
'异常液体'
;
if
(
behaviorCode
==
3
)
return
'检测到排泄物'
;
return
'未知异常'
;
}
}
lib/repositories/cabin_repository.dart
0 → 100644
View file @
65c9e3b0
import
'mock/cabin_mock_data.dart'
;
import
'package:laki_icu_app/models/bo/cabin_detail_response.dart'
;
import
'package:laki_icu_app/utils/constants.dart'
;
import
'package:laki_icu_app/utils/http/dio_request.dart'
;
import
'package:laki_icu_app/utils/http/response_model.dart'
;
class
CabinRepository
{
CabinRepository
.
_
();
static
final
CabinRepository
instance
=
CabinRepository
.
_
();
/// 获取舱详情
///
/// [carbinSn] 舱序列号(设备 SN)
Future
<
ResponseModel
<
CabinDetailResponse
>>
getCabinDetail
(
String
carbinSn
,
)
{
return
DioRequest
.
instance
.
get
<
CabinDetailResponse
>(
'/icu/detail'
,
queryParameters:
{
'carbinSn'
:
carbinSn
},
fromJsonT:
(
data
)
=>
CabinDetailResponse
.
fromJson
(
data
as
Map
<
String
,
dynamic
>),
);
}
Future
<
ResponseModel
<
CabinDetailResponse
>>
_mockCabinDetail
()
async
{
await
Future
.
delayed
(
const
Duration
(
milliseconds:
300
));
return
ResponseModel
<
CabinDetailResponse
>(
code:
200
,
msg:
'获取舱详情成功(mock)'
,
data:
CabinMockData
.
getMockCabinDetail
(),
uuid:
'mock_uuid_
${DateTime.now().millisecondsSinceEpoch}
'
,
success:
true
,
timestamp:
DateTime
.
now
().
millisecondsSinceEpoch
,
);
}
}
lib/repositories/mock/cabin_mock_data.dart
0 → 100644
View file @
65c9e3b0
import
'../../models/bo/cabin_detail_response.dart'
;
/// 舱详情模块本地 mock 数据。
///
/// 所有 mock 数据直接使用 models 层构造函数创建,
/// 确保数据结构与 models 定义完全一致。
/// 后续接入真实接口时,只需修改 Repository 层开关即可。
class
CabinMockData
{
CabinMockData
.
_
();
static
CabinDetailResponse
getMockCabinDetail
()
{
return
CabinDetailResponse
(
pageTitle:
'ICU 监护舱'
,
deviceId:
1001
,
deviceName:
'TSAAS ICU 设备'
,
cabinId:
1
,
cabinName:
'1号舱'
,
cabinType:
'ICU'
,
carbinSn:
'VE10085871QOXG'
,
cameraSn:
'VE10085871QOXG'
,
wifiPwd:
'143548'
,
wifiName:
'TSAAS-ICU-WiFi'
,
petInfo:
PetInfoResponse
(
petId:
1
,
name:
'妮蔻'
,
avatar:
''
,
type:
'猫'
,
breedTag:
'长毛三花'
,
disease:
'胃炎'
,
ownerName:
'张先生'
,
ownerPhone:
'130-1111-3333'
,
basicInfo:
'3岁 雌性 4.5kg'
,
petName:
'妮蔻'
,
petType:
'猫'
,
monitoringStatus:
'monitoring'
,
),
cameraInfo:
CameraInfoResponse
(
cameraId:
1
,
cameraName:
'主摄像头'
,
sn:
'VE10085871QOXG'
,
cameraPwd:
'143548'
,
status:
'online'
,
streamUrl:
''
,
),
monitoringData:
MonitoringDataResponse
(
totalDuration:
7200
,
elapsedDuration:
3600
,
status:
'monitoring'
,
careLevel:
'特级'
,
planId:
1
,
planName:
'标准监护方案'
,
planType:
'standard'
,
temperatureSetting:
25
,
mainTemperature:
24
,
humidity:
55
,
humiditySetting:
50
,
oxygenConcentration:
21
,
oxygenSetting:
20
,
co2Measurement:
400
,
co2Setting:
500
,
),
cabinControls:
CabinControlsResponse
(
temperature:
25.0
,
oxygen:
21.0
,
humidity:
55.0
,
co2:
400.0
,
nebulizer:
0
,
sterilize:
0
,
fanMode:
'auto'
,
airMode:
'cycle'
,
newFan:
true
,
openOxygen:
false
,
checkLight:
false
,
light:
true
,
blueLight:
false
,
redLight:
false
,
),
currentPlanId:
1
,
currentPetId:
1
,
status:
'occupied'
,
state:
'normal'
,
);
}
}
lib/services/cabin_service.dart
0 → 100644
View file @
65c9e3b0
import
'package:laki_icu_app/models/bo/cabin_detail_response.dart'
;
import
'package:laki_icu_app/repositories/cabin_repository.dart'
;
class
CabinService
{
final
CabinRepository
_repository
;
CabinService
()
:
_repository
=
CabinRepository
.
instance
;
/// 获取舱详情
///
/// [carbinSn] 舱序列号(设备 SN)
/// 返回 [CabinDetailResponse],包含 cameraSn、wifiPwd、petInfo 等
Future
<
CabinDetailResponse
>
getCabinDetail
(
String
carbinSn
)
async
{
final
result
=
await
_repository
.
getCabinDetail
(
carbinSn
);
if
(
result
.
success
&&
result
.
data
!=
null
)
{
return
result
.
data
!;
}
throw
Exception
(
result
.
msg
);
}
}
lib/views/monitoring/index/cubit/monitoring_index_cubit.dart
View file @
65c9e3b0
This diff is collapsed.
Click to expand it.
lib/views/monitoring/index/cubit/monitoring_index_state.dart
View file @
65c9e3b0
...
@@ -71,6 +71,18 @@ class MonitoringIndexState extends Equatable {
...
@@ -71,6 +71,18 @@ class MonitoringIndexState extends Equatable {
/// 当前 MQTT 连接使用的设备 SN
/// 当前 MQTT 连接使用的设备 SN
final
String
?
mqttDeviceSn
;
final
String
?
mqttDeviceSn
;
/// 设备摄像头序列号(从舱详情接口 /cabin/detail 获取)
final
String
?
cabinCameraSn
;
/// 设备 WiFi 密码(从舱详情接口 /cabin/detail 获取)
final
String
?
cabinWifiPwd
;
/// MQTT 实时推送的摄像头告警列表(来自 camera/{sn}/to)
final
List
<
AlertInfoBO
>
cameraAlerts
;
/// 当前选中的告警(用于弹窗显示)
final
AlertInfoBO
?
selectedAlert
;
const
MonitoringIndexState
({
const
MonitoringIndexState
({
this
.
status
=
MonitoringIndexStatus
.
initial
,
this
.
status
=
MonitoringIndexStatus
.
initial
,
this
.
isLoading
=
false
,
this
.
isLoading
=
false
,
...
@@ -78,6 +90,7 @@ class MonitoringIndexState extends Equatable {
...
@@ -78,6 +90,7 @@ class MonitoringIndexState extends Equatable {
this
.
metrics
=
const
[],
this
.
metrics
=
const
[],
this
.
patientInfo
,
this
.
patientInfo
,
this
.
alerts
=
const
[],
this
.
alerts
=
const
[],
this
.
cameraAlerts
=
const
[],
this
.
videoConnectionState
=
WebrtcConnectionState
.
disconnected
,
this
.
videoConnectionState
=
WebrtcConnectionState
.
disconnected
,
this
.
videoStreamMode
=
VideoStreamMode
.
p2p
,
this
.
videoStreamMode
=
VideoStreamMode
.
p2p
,
this
.
isSwitchingMode
=
false
,
this
.
isSwitchingMode
=
false
,
...
@@ -95,6 +108,9 @@ class MonitoringIndexState extends Equatable {
...
@@ -95,6 +108,9 @@ class MonitoringIndexState extends Equatable {
this
.
mqttConnectionState
=
LakiMqttConnectionState
.
disconnected
,
this
.
mqttConnectionState
=
LakiMqttConnectionState
.
disconnected
,
this
.
mqttMessage
,
this
.
mqttMessage
,
this
.
mqttDeviceSn
,
this
.
mqttDeviceSn
,
this
.
cabinCameraSn
,
this
.
cabinWifiPwd
,
this
.
selectedAlert
,
});
});
MonitoringIndexState
copyWith
({
MonitoringIndexState
copyWith
({
...
@@ -104,6 +120,7 @@ class MonitoringIndexState extends Equatable {
...
@@ -104,6 +120,7 @@ class MonitoringIndexState extends Equatable {
List
<
MonitoringMetricBO
>?
metrics
,
List
<
MonitoringMetricBO
>?
metrics
,
PatientInfoBO
?
patientInfo
,
PatientInfoBO
?
patientInfo
,
List
<
AlertInfoBO
>?
alerts
,
List
<
AlertInfoBO
>?
alerts
,
List
<
AlertInfoBO
>?
cameraAlerts
,
WebrtcConnectionState
?
videoConnectionState
,
WebrtcConnectionState
?
videoConnectionState
,
VideoStreamMode
?
videoStreamMode
,
VideoStreamMode
?
videoStreamMode
,
bool
?
isSwitchingMode
,
bool
?
isSwitchingMode
,
...
@@ -121,6 +138,9 @@ class MonitoringIndexState extends Equatable {
...
@@ -121,6 +138,9 @@ class MonitoringIndexState extends Equatable {
LakiMqttConnectionState
?
mqttConnectionState
,
LakiMqttConnectionState
?
mqttConnectionState
,
String
?
mqttMessage
,
String
?
mqttMessage
,
String
?
mqttDeviceSn
,
String
?
mqttDeviceSn
,
String
?
cabinCameraSn
,
String
?
cabinWifiPwd
,
AlertInfoBO
?
selectedAlert
,
bool
clearBoundBluetoothDevice
=
false
,
bool
clearBoundBluetoothDevice
=
false
,
bool
clearLatestMcuReport
=
false
,
bool
clearLatestMcuReport
=
false
,
bool
clearPatientInfo
=
false
,
bool
clearPatientInfo
=
false
,
...
@@ -133,6 +153,7 @@ class MonitoringIndexState extends Equatable {
...
@@ -133,6 +153,7 @@ class MonitoringIndexState extends Equatable {
metrics:
metrics
??
this
.
metrics
,
metrics:
metrics
??
this
.
metrics
,
patientInfo:
clearPatientInfo
?
null
:
patientInfo
??
this
.
patientInfo
,
patientInfo:
clearPatientInfo
?
null
:
patientInfo
??
this
.
patientInfo
,
alerts:
alerts
??
this
.
alerts
,
alerts:
alerts
??
this
.
alerts
,
cameraAlerts:
cameraAlerts
??
this
.
cameraAlerts
,
videoConnectionState:
videoConnectionState
??
this
.
videoConnectionState
,
videoConnectionState:
videoConnectionState
??
this
.
videoConnectionState
,
videoStreamMode:
videoStreamMode
??
this
.
videoStreamMode
,
videoStreamMode:
videoStreamMode
??
this
.
videoStreamMode
,
isSwitchingMode:
isSwitchingMode
??
this
.
isSwitchingMode
,
isSwitchingMode:
isSwitchingMode
??
this
.
isSwitchingMode
,
...
@@ -159,6 +180,9 @@ class MonitoringIndexState extends Equatable {
...
@@ -159,6 +180,9 @@ class MonitoringIndexState extends Equatable {
mqttMessage:
mqttMessage
??
this
.
mqttMessage
,
mqttMessage:
mqttMessage
??
this
.
mqttMessage
,
mqttDeviceSn:
mqttDeviceSn:
clearMqttDeviceSn
?
null
:
mqttDeviceSn
??
this
.
mqttDeviceSn
,
clearMqttDeviceSn
?
null
:
mqttDeviceSn
??
this
.
mqttDeviceSn
,
cabinCameraSn:
cabinCameraSn
??
this
.
cabinCameraSn
,
cabinWifiPwd:
cabinWifiPwd
??
this
.
cabinWifiPwd
,
selectedAlert:
selectedAlert
??
this
.
selectedAlert
,
);
);
}
}
...
@@ -170,6 +194,7 @@ class MonitoringIndexState extends Equatable {
...
@@ -170,6 +194,7 @@ class MonitoringIndexState extends Equatable {
metrics
,
metrics
,
patientInfo
,
patientInfo
,
alerts
,
alerts
,
cameraAlerts
,
videoConnectionState
,
videoConnectionState
,
videoStreamMode
,
videoStreamMode
,
isSwitchingMode
,
isSwitchingMode
,
...
@@ -187,5 +212,8 @@ class MonitoringIndexState extends Equatable {
...
@@ -187,5 +212,8 @@ class MonitoringIndexState extends Equatable {
mqttConnectionState
,
mqttConnectionState
,
mqttMessage
,
mqttMessage
,
mqttDeviceSn
,
mqttDeviceSn
,
cabinCameraSn
,
cabinWifiPwd
,
selectedAlert
,
];
];
}
}
lib/views/monitoring/index/monitoring_index_view.dart
View file @
65c9e3b0
...
@@ -13,6 +13,7 @@ import 'cubit/monitoring_index_cubit.dart';
...
@@ -13,6 +13,7 @@ import 'cubit/monitoring_index_cubit.dart';
import
'cubit/monitoring_index_state.dart'
;
import
'cubit/monitoring_index_state.dart'
;
import
'widgets/bluetooth_bind_dialog.dart'
;
import
'widgets/bluetooth_bind_dialog.dart'
;
import
'widgets/monitoring_alert_card.dart'
;
import
'widgets/monitoring_alert_card.dart'
;
import
'widgets/monitoring_alert_detail_dialog.dart'
;
import
'widgets/monitoring_metric_card.dart'
;
import
'widgets/monitoring_metric_card.dart'
;
import
'widgets/monitoring_pet_info_card.dart'
;
import
'widgets/monitoring_pet_info_card.dart'
;
import
'widgets/video_player_widget.dart'
;
import
'widgets/video_player_widget.dart'
;
...
@@ -59,19 +60,26 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
...
@@ -59,19 +60,26 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
BlocBuilder
<
MonitoringIndexCubit
,
MonitoringIndexState
>(
return
BlocListener
<
MonitoringIndexCubit
,
MonitoringIndexState
>(
builder:
(
context
,
state
)
{
listener:
(
context
,
state
)
{
if
(
state
.
isLoading
&&
state
.
metrics
.
isEmpty
)
{
if
(
state
.
selectedAlert
!=
null
)
{
return
const
Center
(
_showAlertDetailDialog
(
state
.
selectedAlert
!);
child:
CircularProgressIndicator
(
color:
Colors
.
white
),
);
}
}
if
(
state
.
status
==
MonitoringIndexStatus
.
failure
&&
state
.
metrics
.
isEmpty
)
{
return
_buildError
(
state
.
error
);
}
return
_buildMainArea
(
state
);
},
},
child:
BlocBuilder
<
MonitoringIndexCubit
,
MonitoringIndexState
>(
builder:
(
context
,
state
)
{
if
(
state
.
isLoading
&&
state
.
metrics
.
isEmpty
)
{
return
const
Center
(
child:
CircularProgressIndicator
(
color:
Colors
.
white
),
);
}
if
(
state
.
status
==
MonitoringIndexStatus
.
failure
&&
state
.
metrics
.
isEmpty
)
{
return
_buildError
(
state
.
error
);
}
return
_buildMainArea
(
state
);
},
),
);
);
}
}
...
@@ -121,7 +129,12 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
...
@@ -121,7 +129,12 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
children:
[
children:
[
Expanded
(
Expanded
(
flex:
10
,
flex:
10
,
child:
MonitoringAlertCard
(
alerts:
state
.
alerts
),
child:
MonitoringAlertCard
(
alerts:
[
...
state
.
cameraAlerts
,
...
state
.
alerts
,
],
),
),
),
SizedBox
(
width:
10
.
w
),
SizedBox
(
width:
10
.
w
),
Expanded
(
Expanded
(
...
@@ -244,6 +257,18 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
...
@@ -244,6 +257,18 @@ class _MonitoringIndexContentState extends State<MonitoringIndexContent> {
);
);
}
}
void
_showAlertDetailDialog
(
AlertInfoBO
alert
)
{
showDialog
<
void
>(
context:
context
,
builder:
(
_
)
=>
BlocProvider
.
value
(
value:
_monitoringIndexCubit
,
child:
MonitoringAlertDetailDialog
(
alert:
alert
),
),
).
then
((
_
)
{
_monitoringIndexCubit
.
clearSelectedAlert
();
});
}
List
<
MonitoringMetricBO
>
_environmentMetrics
(
List
<
MonitoringMetricBO
>
_environmentMetrics
(
List
<
MonitoringMetricBO
>
metrics
)
{
List
<
MonitoringMetricBO
>
metrics
)
{
final
matched
=
metrics
final
matched
=
metrics
...
...
lib/views/monitoring/index/widgets/monitoring_alert_card.dart
View file @
65c9e3b0
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_bloc/flutter_bloc.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:flutter_screenutil/flutter_screenutil.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'package:laki_icu_app/models/bo/monitoring_bo.dart'
;
import
'package:laki_icu_app/views/monitoring/index/cubit/monitoring_index_cubit.dart'
;
class
MonitoringAlertCard
extends
StatelessWidget
{
class
MonitoringAlertCard
extends
StatelessWidget
{
final
List
<
AlertInfoBO
>
alerts
;
final
List
<
AlertInfoBO
>
alerts
;
...
@@ -73,53 +75,57 @@ class MonitoringAlertCard extends StatelessWidget {
...
@@ -73,53 +75,57 @@ class MonitoringAlertCard extends StatelessWidget {
itemBuilder:
(
context
,
index
)
{
itemBuilder:
(
context
,
index
)
{
final
item
=
alerts
[
index
];
final
item
=
alerts
[
index
];
final
pending
=
item
.
status
.
contains
(
'待处理'
);
final
pending
=
item
.
status
.
contains
(
'待处理'
);
return
_buildAlertItem
(
item
,
pending
);
return
_buildAlertItem
(
context
,
item
,
pending
);
},
},
);
);
}
}
Widget
_buildAlertItem
(
AlertInfoBO
item
,
bool
pending
)
{
Widget
_buildAlertItem
(
BuildContext
context
,
AlertInfoBO
item
,
bool
pending
)
{
return
IntrinsicHeight
(
return
InkWell
(
child:
Row
(
onTap:
()
=>
context
.
read
<
MonitoringIndexCubit
>().
selectAlert
(
item
),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
borderRadius:
BorderRadius
.
circular
(
16
.
r
),
children:
[
child:
IntrinsicHeight
(
_buildIconBlock
(
pending
),
child:
Row
(
SizedBox
(
width:
20
.
w
),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
Expanded
(
children:
[
child:
Column
(
_buildIconBlock
(
pending
),
crossAxisAlignment:
CrossAxisAlignment
.
start
,
SizedBox
(
width:
20
.
w
),
mainAxisAlignment:
MainAxisAlignment
.
start
,
Expanded
(
children:
[
child:
Column
(
Text
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
item
.
title
,
mainAxisAlignment:
MainAxisAlignment
.
start
,
style:
TextStyle
(
children:
[
color:
pending
?
const
Color
(
0xFFF26522
)
:
const
Color
(
0xFFFFC14A
),
Text
(
fontSize:
28
.
sp
,
item
.
title
,
fontWeight:
FontWeight
.
bold
,
style:
TextStyle
(
color:
pending
?
const
Color
(
0xFFF26522
)
:
const
Color
(
0xFFFFC14A
),
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
SizedBox
(
height:
8
.
h
),
SizedBox
(
height:
8
.
h
),
Text
(
Text
(
item
.
description
,
item
.
description
,
maxLines:
2
,
maxLines:
2
,
overflow:
TextOverflow
.
ellipsis
,
overflow:
TextOverflow
.
ellipsis
,
style:
TextStyle
(
style:
TextStyle
(
color:
Colors
.
white
,
color:
Colors
.
white
,
fontSize:
23
.
sp
,
fontSize:
23
.
sp
,
)
,
),
),
),
// SizedBox(height: 10.h
),
// SizedBox(height: 10.h),
Text
(
Text
(
item
.
time
,
item
.
time
,
style:
TextStyle
(
style:
TextStyle
(
color:
Colors
.
white
,
color:
Colors
.
white
,
fontSize:
20
.
sp
,
fontSize:
20
.
sp
,
)
,
),
),
)
,
]
,
]
,
)
,
),
),
)
,
]
,
]
,
)
,
),
),
);
);
}
}
...
...
lib/views/monitoring/index/widgets/monitoring_alert_detail_dialog.dart
0 → 100644
View file @
65c9e3b0
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
'package:laki_icu_app/views/monitoring/index/cubit/monitoring_index_cubit.dart'
;
class
MonitoringAlertDetailDialog
extends
StatelessWidget
{
final
AlertInfoBO
alert
;
const
MonitoringAlertDetailDialog
({
super
.
key
,
required
this
.
alert
,
});
@override
Widget
build
(
BuildContext
context
)
{
return
Dialog
(
backgroundColor:
Colors
.
transparent
,
insetPadding:
EdgeInsets
.
zero
,
child:
_buildDialogContent
(
context
),
);
}
Widget
_buildDialogContent
(
BuildContext
context
)
{
return
Container
(
width:
1300
.
w
,
height:
800
.
h
,
margin:
EdgeInsets
.
fromLTRB
(
100
.
w
,
100
.
h
,
100
.
w
,
100
.
h
),
decoration:
BoxDecoration
(
image:
const
DecorationImage
(
image:
AssetImage
(
'lib/assets/monitoring/dialog_alert_bg.png'
),
fit:
BoxFit
.
fill
,
),
borderRadius:
BorderRadius
.
circular
(
20
.
r
),
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
_buildHeader
(),
SizedBox
(
height:
30
.
h
),
_buildContent
(
context
),
SizedBox
(
height:
40
.
h
),
_buildBottomButtons
(
context
),
],
),
);
}
Widget
_buildHeader
()
{
return
Container
(
padding:
EdgeInsets
.
fromLTRB
(
40
.
w
,
24
.
h
,
40
.
w
,
24
.
h
),
decoration:
const
BoxDecoration
(
border:
Border
(
bottom:
BorderSide
(
color:
Color
(
0xFF00D4FF
),
width:
2
,
),
),
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
Text
(
'告警详情'
,
style:
TextStyle
(
color:
const
Color
(
0xFF00D4FF
),
fontSize:
36
.
sp
,
fontWeight:
FontWeight
.
bold
,
),
),
],
),
);
}
Widget
_buildContent
(
BuildContext
context
)
{
return
Expanded
(
child:
Padding
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
40
.
w
),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
_buildImagePlaceholder
(),
SizedBox
(
width:
30
.
w
),
Expanded
(
child:
_buildAlertInfo
(),
),
],
),
),
);
}
Widget
_buildImagePlaceholder
()
{
return
Container
(
width:
280
.
w
,
height:
200
.
h
,
decoration:
BoxDecoration
(
color:
const
Color
(
0xFF1A2332
),
borderRadius:
BorderRadius
.
circular
(
12
.
r
),
),
);
}
Widget
_buildAlertInfo
()
{
final
isPending
=
alert
.
status
.
contains
(
'待处理'
);
return
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Text
(
alert
.
title
,
style:
TextStyle
(
color:
const
Color
(
0xFFFFC14A
),
fontSize:
34
.
sp
,
fontWeight:
FontWeight
.
bold
,
),
),
Text
(
alert
.
time
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
24
.
sp
,
),
),
],
),
SizedBox
(
height:
20
.
h
),
_buildInfoRow
(
'处理状态'
,
isPending
?
'待处理'
:
'已处理'
,
isPending
),
_buildInfoRow
(
'处理状态'
,
isPending
?
'待处理'
:
'已处理'
,
isPending
),
_buildInfoRow
(
'处理时间'
,
''
,
false
),
SizedBox
(
height:
30
.
h
),
Expanded
(
child:
SingleChildScrollView
(
child:
Text
(
alert
.
description
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
24
.
sp
,
height:
1.5
,
),
),
),
),
],
);
}
Widget
_buildInfoRow
(
String
label
,
String
value
,
bool
isHighlight
)
{
return
Padding
(
padding:
EdgeInsets
.
symmetric
(
vertical:
8
.
h
),
child:
Row
(
children:
[
SizedBox
(
width:
140
.
w
,
child:
Text
(
label
,
style:
TextStyle
(
color:
Colors
.
white
.
withValues
(
alpha:
153
),
fontSize:
26
.
sp
,
),
),
),
SizedBox
(
width:
20
.
w
),
Text
(
value
,
style:
TextStyle
(
color:
isHighlight
?
const
Color
(
0xFFFFC14A
)
:
Colors
.
white
,
fontSize:
26
.
sp
,
fontWeight:
isHighlight
?
FontWeight
.
bold
:
FontWeight
.
normal
,
),
),
],
),
);
}
Widget
_buildBottomButtons
(
BuildContext
context
)
{
return
Container
(
padding:
EdgeInsets
.
fromLTRB
(
40
.
w
,
20
.
h
,
40
.
w
,
30
.
h
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
_buildButton
(
'关闭窗口'
,
const
Color
(
0xFF2A2E3B
),
Colors
.
white
,
const
Color
(
0xFF4A4E5B
),
()
=>
Navigator
.
of
(
context
).
pop
(),
),
SizedBox
(
width:
30
.
w
),
_buildButton
(
'标记误报'
,
const
Color
(
0xFF2A2E3B
),
Colors
.
white
,
const
Color
(
0xFF4A4E5B
),
()
=>
_handleMarkAsFalse
(
context
),
),
SizedBox
(
width:
30
.
w
),
_buildButton
(
'已处理'
,
const
Color
(
0xFF00D4FF
),
Colors
.
black
,
const
Color
(
0xFF00D4FF
),
()
=>
_handleMarkAsProcessed
(
context
),
isActive:
true
,
),
],
),
);
}
Widget
_buildButton
(
String
text
,
Color
backgroundColor
,
Color
textColor
,
Color
borderColor
,
VoidCallback
onPressed
,
{
bool
isActive
=
false
,
})
{
return
GestureDetector
(
onTap:
onPressed
,
child:
Container
(
width:
220
.
w
,
height:
72
.
h
,
decoration:
BoxDecoration
(
color:
backgroundColor
,
border:
Border
.
all
(
color:
borderColor
,
width:
2
.
w
,
),
borderRadius:
BorderRadius
.
circular
(
8
.
r
),
boxShadow:
isActive
?
[
BoxShadow
(
color:
borderColor
.
withValues
(
alpha:
128
),
blurRadius:
10
.
r
,
offset:
const
Offset
(
0
,
0
),
),
]
:
null
,
),
child:
Center
(
child:
Text
(
text
,
style:
TextStyle
(
color:
textColor
,
fontSize:
28
.
sp
,
fontWeight:
FontWeight
.
bold
,
),
),
),
),
);
}
void
_handleMarkAsFalse
(
BuildContext
context
)
{
context
.
read
<
MonitoringIndexCubit
>().
markAlertAsFalse
(
alert
);
Navigator
.
of
(
context
).
pop
();
}
void
_handleMarkAsProcessed
(
BuildContext
context
)
{
context
.
read
<
MonitoringIndexCubit
>().
markAlertAsProcessed
(
alert
);
Navigator
.
of
(
context
).
pop
();
}
}
\ No newline at end of file
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