Files
tuiche/lib/pages/sleep_report/component/SnoreViewWidget.dart
2025-08-14 15:53:22 +08:00

347 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 'dart:math';
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/LineChartByRange.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();
}
double maxY = 60;
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']));
print(snoreValues);
List<BarData> barDataList = snoreValues.map<BarData>((item) {
return BarData(
st: item['st'],
et: item['et'],
value: (item['value'] as num).toDouble() > maxY
? maxY + 3
: (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();
// List<Map<String, dynamic>> data =
// (widget.sleepReport['ssp'] as List).cast<Map<String, dynamic>>();
// List<Map<String, dynamic>> showLabel = convertToShowLabel(data);
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), // 外部 padding 移到内部
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: LineChartByRange(
// showLabel: showLabel,
// startTime: startTime,
// endTime: endTime,
// ),
child: BarChartWidget(
data: barDataList,
startTime: startTime,
endTime: endTime,
maxYValue: maxY, // 最大值可自定义
yStepCount: 6, // 分4段0, 5, 10, 15, 20
),
),
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;
}
}