Files
tuiche/lib/pages/sleep_report/component/SnoreViewWidget.dart
2026-01-31 14:43:47 +08:00

349 lines
13 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:EasyDartModule/EasyDartModule.dart' as es;
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/enum/APPPackageType.dart';
import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
import 'package:vbvs_app/pages/sleep_report/chart/SnoreChart.dart';
class SnoreViewWidgetWidget extends StatefulWidget {
var sleepReport;
SnoreViewWidgetWidget({super.key, required this.sleepReport});
@override
State<SnoreViewWidgetWidget> createState() => _SnoreViewWidgetWidgetState();
}
class _SnoreViewWidgetWidgetState extends State<SnoreViewWidgetWidget> {
@override
void setState(VoidCallback callback) {
super.setState(callback);
}
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
try {
if (widget.sleepReport == null ||
widget.sleepReport is! Map ||
widget.sleepReport.isEmpty) {
return Container();
}
// if (APPPackageType.TH.code == AppConstants().ent_type) {
// return Container();
// }
var startTime = widget.sleepReport['startTime'];
var endTime = widget.sleepReport['endTime'];
List snoreValues = [];
List type = widget.sleepReport['ssp']['type'];
List lightSnore = widget.sleepReport['ssp']['data'][0];
List heavySnore = widget.sleepReport['ssp']['data'][1];
List<Map> processedLightSnore = lightSnore.map((item) {
return {
...item,
'id': type[0]['id'],
'name': type[0]['name'],
'color': type[0]['color'],
};
}).toList();
List<Map> processedHeavySnore = heavySnore.map((item) {
return {
...item,
'id': type[1]['id'],
'name': type[1]['name'],
'color': type[1]['color'],
};
}).toList();
snoreValues = [...processedLightSnore, ...processedHeavySnore];
snoreValues.sort((a, b) => a['st'].compareTo(b['st']));
// 动态计算最大值
double maxY = 0;
for (final item in snoreValues) {
if (item['value'] != null) {
final value = (item['value'] as num).toDouble();
if (value > maxY) {
maxY = value;
}
}
}
// 添加20的偏移量确保所有数据都能正常显示
maxY = maxY + 5;
// 如果数据都为空,给一个默认值
if (maxY <= 5) {
maxY = 20; // 或根据业务需要设置一个合理的默认值
}
List<BarData> barDataList = snoreValues.map<BarData>((item) {
return BarData(
st: item['st'],
et: item['et'],
value: (item['value'] as num).toDouble(),
id: item['id'],
name: item['name'],
color: (item['color'] == null || item['color'].isEmpty)
? (item['id'] == 1 ? Colors.green : Colors.red)
: stringToColor(item['color']),
);
}).toList();
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: themeController.currentColor.sc5,
borderRadius:
BorderRadius.circular(AppConstants().normal_container_radius),
),
child: Padding(
padding:
EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 0.rpx),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"打鼾监测".tr,
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: AppConstants().title_text_fontSize),
),
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.white,
padding: EdgeInsetsDirectional.fromSTEB(
14.rpx, 10.rpx, 14.rpx, 10.rpx),
borderRadius: 0.rpx,
onTap: () {
if (AppConstants().ent_type ==
APPPackageType.MHT.code) {
showTipDialog(
context,
Container(
child: Text(
"打鼾监测是指用户在睡眠过程中打鼾频次的图表说明。".tr,
style: TextStyle(
fontSize: 26.rpx,
color: Colors.black,
),
),
),
backgroundColor: Color(0xFFFFFFFF),
colors: [
Color(0XFF1592AA),
Color(0xFF0C83A7),
Color(0xFF006FA3)
],
);
} else {
showTipDialog(
context,
Container(
child: Text(
"打鼾监测是指用户在睡眠过程中打鼾频次的图表说明。".tr,
style: TextStyle(
fontSize: 26.rpx,
color: themeController.currentColor.sc3,
),
),
),
backgroundColor: themeController.currentColor.sc17,
colors: AppConstants().thNormalButton,
);
}
},
child: Container(
padding:
EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0.rpx, 0),
width: 28.rpx,
height: 28.rpx,
child: SvgPicture.asset(
'assets/img/icon/explain.svg',
fit: BoxFit.cover,
color: themeController.currentColor.sc4,
),
),
),
],
),
),
SizedBox(
height: 32.rpx,
),
Row(
children: [
Text(
"".tr,
style: TextStyle(
color: stringToColor("#FFFFFF"), fontSize: 18.rpx),
),
],
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0.rpx, 40.rpx, 20.rpx, 0.rpx),
child: BarChartWidget(
data: barDataList,
startTime: startTime,
endTime: endTime,
maxYValue: maxY,
yStepCount: 5, // 可以保持5段或根据需求调整
),
),
Padding(
padding:
EdgeInsetsDirectional.fromSTEB(0.rpx, 52.rpx, 0.rpx, 0.rpx),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
children: [
Container(
width: 14.rpx,
height: 14.rpx,
decoration: BoxDecoration(
color: (type[0]?['color'] == null ||
type[0]?['color'].isEmpty)
? Colors.green
: stringToColor("${type[0]['color']}"),
shape: BoxShape.circle,
),
),
SizedBox(width: 12.rpx),
Text(
'${type[0]?['name']}',
style: TextStyle(
fontSize:
AppConstants().normal_text_fontSize,
color: themeController.currentColor.sc3),
),
],
),
SizedBox(height: 16.rpx),
Text(
'${(type[0]?['value'] == null || type[0]['value'].toString().isEmpty) ? '未知数据'.tr : '${type[0]?['value']}${(type[0]?['unit'] == null || type[0]['unit'].toString().isEmpty) ? '' : type[0]?['unit']}'}',
style: TextStyle(
fontSize: AppConstants().small_text_fontSize,
color: themeController.currentColor.sc4),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
children: [
Container(
width: 14.rpx,
height: 14.rpx,
decoration: BoxDecoration(
color: (type[1]?['color'] == null ||
type[1]?['color'].isEmpty)
? Colors.red
: stringToColor("${type[1]['color']}"),
shape: BoxShape.circle,
),
),
SizedBox(width: 12.rpx),
Text(
'${type[1]?['name']}',
style: TextStyle(
fontSize:
AppConstants().normal_text_fontSize,
color: themeController.currentColor.sc3),
),
],
),
SizedBox(height: 16.rpx),
Text(
'${(type[1]?['value'] == null || type[1]['value'].toString().isEmpty) ? '未知数据'.tr : '${type[1]?['value']}${(type[1]?['unit'] == null || type[1]['unit'].toString().isEmpty) ? '' : type[1]?['unit']}'}',
style: TextStyle(
fontSize: AppConstants().small_text_fontSize,
color: themeController.currentColor.sc4),
),
],
),
],
),
),
),
SizedBox(
height: 52.rpx,
),
],
),
),
);
} catch (e) {
es.EasyDartModule.logger.error("打鼾监测绘制异常${e}");
return Container();
}
}
List<Map<String, dynamic>> convertToShowLabel(
List<Map<String, dynamic>> data) {
if (data.isEmpty) return [];
data.sort((a, b) => a['st'].compareTo(b['st']));
List<Map<String, dynamic>> result = [];
int startTime = data[0]['st'];
int endTime = data[0]['et'];
int currentValue = data[0]['value'];
for (int i = 1; i < data.length; i++) {
final item = data[i];
final st = item['st'];
final value = item['value'];
final et = item['et'];
if (value == currentValue) {
endTime = st;
} else {
result.add({
"startTime": startTime,
"endTime": endTime,
"times": currentValue,
});
startTime = st;
endTime = et;
currentValue = value;
}
}
result.add({
"startTime": startTime,
"endTime": endTime,
"times": currentValue,
});
return result;
}
}