更新睡眠的心率基准图不显示
This commit is contained in:
@@ -214,7 +214,7 @@ class BarChartPainter extends CustomPainter {
|
||||
// 缓存 tip 信息
|
||||
if (selectedBar == d) {
|
||||
tipText =
|
||||
'${d.name}\n${d.value.toStringAsFixed(1)}\n${MyUtils.formatToHHmm(d.st)}';
|
||||
'${d.name}\n${d.value.toStringAsFixed(1)}次\n${MyUtils.formatToHHmm(d.st)}';
|
||||
|
||||
final tp = TextPainter(
|
||||
text: TextSpan(
|
||||
|
||||
@@ -84,9 +84,28 @@ class TimeSeriesChart extends StatelessWidget {
|
||||
final xLabels = _generateXLabels();
|
||||
final midY = (yMin + yMax) / 2;
|
||||
|
||||
List<FlSpot> spots = dataPoints.map((p) {
|
||||
return FlSpot(_timeToX(p.timestamp.toDouble(), xLabels), p.value);
|
||||
}).toList();
|
||||
// 将数据点分割成多个连续段,遇到value=-1时断开
|
||||
List<List<FlSpot>> lineSegments = [];
|
||||
List<FlSpot> currentSegment = [];
|
||||
|
||||
for (var point in dataPoints) {
|
||||
if (point.value != -1) {
|
||||
// 有效数据点,添加到当前段
|
||||
currentSegment.add(FlSpot(
|
||||
_timeToX(point.timestamp.toDouble(), xLabels),
|
||||
point.value,
|
||||
));
|
||||
} else if (currentSegment.isNotEmpty) {
|
||||
// 遇到无效点且当前段不为空,结束当前段
|
||||
lineSegments.add(currentSegment);
|
||||
currentSegment = [];
|
||||
}
|
||||
}
|
||||
|
||||
// 添加最后一个段(如果有)
|
||||
if (currentSegment.isNotEmpty) {
|
||||
lineSegments.add(currentSegment);
|
||||
}
|
||||
|
||||
return AspectRatio(
|
||||
aspectRatio: 2,
|
||||
@@ -204,15 +223,16 @@ class TimeSeriesChart extends StatelessWidget {
|
||||
top: BorderSide.none,
|
||||
),
|
||||
),
|
||||
lineBarsData: [
|
||||
LineChartBarData(
|
||||
spots: spots,
|
||||
lineBarsData: lineSegments.map((segment) {
|
||||
return LineChartBarData(
|
||||
spots: segment,
|
||||
isCurved: false,
|
||||
color: themeController.currentColor.sc2,
|
||||
barWidth: 2,
|
||||
dotData: FlDotData(show: false),
|
||||
)
|
||||
],
|
||||
preventCurveOverShooting: true,
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -47,11 +47,21 @@ class _BreatheStandardWidgetState extends State<BreatheStandardWidget> {
|
||||
final endTime = widget.sleepReport['endTime'];
|
||||
List<Map<String, dynamic>> data =
|
||||
(widget.sleepReport['brbc'] as List).cast<Map<String, dynamic>>();
|
||||
final dataPoints = data.map((item) {
|
||||
final x = item['st'] as int;
|
||||
final y = (item['value'] as num).toDouble(); // 安全地转换为 double
|
||||
return TimeSeriesPoint(x, y);
|
||||
}).toList();
|
||||
List<TimeSeriesPoint> dataPoints = [];
|
||||
|
||||
if (data != null && data.isNotEmpty) {
|
||||
data.forEach((item) {
|
||||
final x = item['st'] as int;
|
||||
if (item['value'] == null || item['value'] == '') {
|
||||
// return;
|
||||
dataPoints.add(TimeSeriesPoint(x, -1));
|
||||
return;
|
||||
}
|
||||
final y = (item['value'] as num).toDouble(); // 安全地转换为 double
|
||||
// return TimeSeriesPoint(x, y);
|
||||
dataPoints.add(TimeSeriesPoint(x, y));
|
||||
});
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> brs =
|
||||
(widget.sleepReport['brs'] as List).cast<Map<String, dynamic>>();
|
||||
@@ -130,7 +140,8 @@ class _BreatheStandardWidgetState extends State<BreatheStandardWidget> {
|
||||
Container(
|
||||
child: Text(
|
||||
// "呼吸数据介绍".tr,
|
||||
"呼吸数据是指用户在睡眠过程中呼吸的基本数据,是评估睡眠呼吸质量、筛查睡眠呼吸障碍的核心指标。".tr,
|
||||
"呼吸数据是指用户在睡眠过程中呼吸的基本数据,是评估睡眠呼吸质量、筛查睡眠呼吸障碍的核心指标。"
|
||||
.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 26.rpx,
|
||||
color: themeController.currentColor.sc3,
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
|
||||
import 'package:vbvs_app/pages/sleep_report/chart/TimeSeriesChart.dart';
|
||||
import 'package:EasyDartModule/EasyDartModule.dart' as es;
|
||||
|
||||
//心率基准
|
||||
class HeartRateStandardWidget extends StatefulWidget {
|
||||
var sleepReport;
|
||||
HeartRateStandardWidget({super.key, required this.sleepReport});
|
||||
@@ -48,11 +49,21 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
|
||||
final endTime = widget.sleepReport['endTime'];
|
||||
List<Map<String, dynamic>> data =
|
||||
(widget.sleepReport['hrbc'] as List).cast<Map<String, dynamic>>();
|
||||
final dataPoints = data.map((item) {
|
||||
final x = item['st'] as int;
|
||||
final y = (item['value'] as num).toDouble(); // 安全地转换为 double
|
||||
return TimeSeriesPoint(x, y);
|
||||
}).toList();
|
||||
List<TimeSeriesPoint> dataPoints = [];
|
||||
|
||||
if (data != null && data.isNotEmpty) {
|
||||
data.forEach((item) {
|
||||
final x = item['st'] as int;
|
||||
if (item['value'] == null || item['value'] == '') {
|
||||
// return;
|
||||
dataPoints.add(TimeSeriesPoint(x, -1));
|
||||
return;
|
||||
}
|
||||
final y = (item['value'] as num).toDouble(); // 安全地转换为 double
|
||||
// return TimeSeriesPoint(x, y);
|
||||
dataPoints.add(TimeSeriesPoint(x, y));
|
||||
});
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> hrs =
|
||||
(widget.sleepReport['hrs'] as List).cast<Map<String, dynamic>>();
|
||||
@@ -129,7 +140,8 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
|
||||
Container(
|
||||
child: Text(
|
||||
// "心率数据介绍".tr,
|
||||
"心率数据是指用户在睡眠过程中基本心率数据,可初步判断睡眠中的心血管负荷及自主神经功能状态,为睡眠健康评估提供重要依据。".tr,
|
||||
"心率数据是指用户在睡眠过程中基本心率数据,可初步判断睡眠中的心血管负荷及自主神经功能状态,为睡眠健康评估提供重要依据。"
|
||||
.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 26.rpx,
|
||||
color: themeController.currentColor.sc3,
|
||||
@@ -376,7 +388,7 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
es.EasyDartModule.logger.error("打鼾监测绘制异常${e}");
|
||||
es.EasyDartModule.logger.error("心率基准绘制异常${e}");
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class _MHTNewSleepReportPageState extends State<MHTNewSleepReportPage> {
|
||||
double lineWidth = 115.rpx;
|
||||
return LayoutBuilder(
|
||||
builder: (context, bodySize) => GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
// onTap: () => FocusScope.of(context).unfocus(),,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
|
||||
@@ -88,7 +88,7 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
||||
double lineWidth = 115.rpx;
|
||||
return LayoutBuilder(
|
||||
builder: (context, bodySize) => GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
// onTap: () => FocusScope.of(context).unfocus(),,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
|
||||
@@ -153,7 +153,7 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
||||
double lineWidth = 115.rpx;
|
||||
return LayoutBuilder(
|
||||
builder: (context, bodySize) => GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
// onTap: () => FocusScope.of(context).unfocus(),,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: (widget.data['noBackImg'] != null &&
|
||||
|
||||
@@ -42,7 +42,7 @@ class _SleepReportPageState extends State<SleepReportPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, bodySize) => GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
// onTap: () => FocusScope.of(context).unfocus(),,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
@@ -67,11 +67,11 @@ class _SleepReportPageState extends State<SleepReportPage> {
|
||||
Text(
|
||||
'健康报告'.tr,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Readex Pro',
|
||||
color: themeController.currentColor.sc3,
|
||||
letterSpacing: 0,
|
||||
fontSize: 30.rpx,
|
||||
),
|
||||
fontFamily: 'Readex Pro',
|
||||
color: themeController.currentColor.sc3,
|
||||
letterSpacing: 0,
|
||||
fontSize: 30.rpx,
|
||||
),
|
||||
),
|
||||
|
||||
/// 左边返回按钮
|
||||
@@ -117,6 +117,4 @@ class _SleepReportPageState extends State<SleepReportPage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user