更新睡眠报告时区显示问题。
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:ef/ef.dart';
|
import 'package:ef/ef.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -104,21 +105,49 @@ class MyUtils {
|
|||||||
return formattedDate;
|
return formattedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static String hidePhoneNumber(String phoneNumber) {
|
||||||
|
// if (phoneNumber.length != 11) {
|
||||||
|
// // 检查手机号是否为11位
|
||||||
|
// throw Exception("手机号格式不正确");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 将中间四位替换为星号
|
||||||
|
// return phoneNumber.replaceRange(3, 7, '****');
|
||||||
|
// }
|
||||||
|
|
||||||
static String hidePhoneNumber(String phoneNumber) {
|
static String hidePhoneNumber(String phoneNumber) {
|
||||||
if (phoneNumber.length != 11) {
|
if (phoneNumber.isEmpty) {
|
||||||
// 检查手机号是否为11位
|
return phoneNumber;
|
||||||
throw Exception("手机号格式不正确");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将中间四位替换为星号
|
// 提取所有数字
|
||||||
return phoneNumber.replaceRange(3, 7, '****');
|
final digits = phoneNumber.replaceAll(RegExp(r'[^\d]'), '');
|
||||||
|
|
||||||
|
if (digits.isEmpty) {
|
||||||
|
return phoneNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示最后4位(如果长度足够)
|
||||||
|
final visibleDigits = min(4, digits.length);
|
||||||
|
final hiddenCount = digits.length - visibleDigits;
|
||||||
|
|
||||||
|
// 构建结果:隐藏部分 + 可见部分
|
||||||
|
final result =
|
||||||
|
'*' * hiddenCount + digits.substring(digits.length - visibleDigits);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double initialScrollOffset = 0.0;
|
static double initialScrollOffset = 0.0;
|
||||||
// 判断手机号格式是否正确的方法
|
// 判断手机号格式是否正确的方法
|
||||||
|
// static bool isValidPhoneNumber(String phoneNumber) {
|
||||||
|
// final RegExp phoneRegExp = RegExp(r'^1[3-9]\d{9}$');
|
||||||
|
// return phoneRegExp.hasMatch(phoneNumber);
|
||||||
|
// }
|
||||||
static bool isValidPhoneNumber(String phoneNumber) {
|
static bool isValidPhoneNumber(String phoneNumber) {
|
||||||
final RegExp phoneRegExp = RegExp(r'^1[3-9]\d{9}$');
|
// 匹配大多数国家的手机号(去掉空格和特殊字符后)
|
||||||
return phoneRegExp.hasMatch(phoneNumber);
|
final RegExp phoneRegExp = RegExp(r'^\+?[1-9]\d{1,14}$');
|
||||||
|
return phoneRegExp.hasMatch(phoneNumber.replaceAll(RegExp(r'\s+'), ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isValidEmail(String email) {
|
static bool isValidEmail(String email) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:vbvs_app/common/color/ServiceConstant.dart';
|
|||||||
import 'package:vbvs_app/common/util/MyUtils.dart';
|
import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||||
import 'package:vbvs_app/common/util/requestWithLog.dart';
|
import 'package:vbvs_app/common/util/requestWithLog.dart';
|
||||||
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
||||||
|
import 'package:vbvs_app/controller/sleep/sleep_time_convert.dart';
|
||||||
import 'package:vbvs_app/pages/main_bottom/component/main_page_b_bottom_change.dart';
|
import 'package:vbvs_app/pages/main_bottom/component/main_page_b_bottom_change.dart';
|
||||||
|
|
||||||
part 'sleep_report_controller.g.dart'; // 由json_serializable自动生成的部分
|
part 'sleep_report_controller.g.dart'; // 由json_serializable自动生成的部分
|
||||||
@@ -65,10 +66,23 @@ class SleepReportController extends GetControllerEx<SleepReportModel> {
|
|||||||
logTitle: "查询睡眠报告",
|
logTitle: "查询睡眠报告",
|
||||||
method: MyHttpMethod.get,
|
method: MyHttpMethod.get,
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
|
// onSuccess: (res) {
|
||||||
|
// isLoading.value = false;
|
||||||
|
// print(res);
|
||||||
|
// final Map<String, dynamic> data = res.data;
|
||||||
|
// sleepReport.value = res.data;
|
||||||
|
// updateAll();
|
||||||
|
// },
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
print(res);
|
print(res);
|
||||||
sleepReport.value = res.data;
|
|
||||||
|
// 获取原始数据
|
||||||
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
|
||||||
|
sleepReport.value = sleepData;
|
||||||
updateAll();
|
updateAll();
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
|
|||||||
107
lib/controller/sleep/sleep_time_convert.dart
Normal file
107
lib/controller/sleep/sleep_time_convert.dart
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// 时区转换函数
|
||||||
|
void applyTimezoneConversion(Map<String, dynamic> data) {
|
||||||
|
final dynamic timeZoneValue = data['utc'];
|
||||||
|
if (timeZoneValue == null) return;
|
||||||
|
|
||||||
|
// 解析目标时区
|
||||||
|
final int? targetOffset = _parseTimezone(timeZoneValue);
|
||||||
|
if (targetOffset == null) return;
|
||||||
|
|
||||||
|
// 原始数据是UTC+8的时间戳
|
||||||
|
const int sourceOffset = 8; // UTC+8
|
||||||
|
final int diffHours = targetOffset - sourceOffset;
|
||||||
|
final int diffMs = diffHours * 3600 * 1000;
|
||||||
|
|
||||||
|
// 转换startTime和endTime
|
||||||
|
if (data['startTime'] != null && data['startTime'] is int) {
|
||||||
|
data['startTime'] = data['startTime'] + diffMs;
|
||||||
|
}
|
||||||
|
if (data['endTime'] != null && data['endTime'] is int) {
|
||||||
|
data['endTime'] = data['endTime'] + diffMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归转换所有时间戳,但要跳过hrsp数组
|
||||||
|
_convertTimestampsRecursive(data, diffMs, skipField: 'hrsp');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析时区值 - 支持多种类型
|
||||||
|
int? _parseTimezone(dynamic timeZoneValue) {
|
||||||
|
if (timeZoneValue == null) return null;
|
||||||
|
|
||||||
|
// 如果是整数类型
|
||||||
|
if (timeZoneValue is int) {
|
||||||
|
return timeZoneValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是字符串类型
|
||||||
|
if (timeZoneValue is String) {
|
||||||
|
// 移除空白字符
|
||||||
|
final String trimmed = timeZoneValue.trim();
|
||||||
|
|
||||||
|
// 处理纯数字字符串,如 "9"、"-2"
|
||||||
|
if (RegExp(r'^[+-]?\d+$').hasMatch(trimmed)) {
|
||||||
|
return int.parse(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理带UTC前缀的字符串,如 "utc+9"、"UTC-2"
|
||||||
|
final match =
|
||||||
|
RegExp(r'utc([+-]?\d+)', caseSensitive: false).firstMatch(trimmed);
|
||||||
|
if (match != null) {
|
||||||
|
return int.parse(match.group(1)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理其他格式,如 "+9"、"-2"
|
||||||
|
if (trimmed.startsWith('+') || trimmed.startsWith('-')) {
|
||||||
|
return int.parse(trimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是数字类型(double等)
|
||||||
|
if (timeZoneValue is num) {
|
||||||
|
return timeZoneValue.toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归转换所有时间戳,可指定跳过的字段
|
||||||
|
void _convertTimestampsRecursive(dynamic data, int diffMs, {String? skipField}) {
|
||||||
|
if (data is Map) {
|
||||||
|
// 如果不是跳过的字段类型,转换时间戳
|
||||||
|
if (!(skipField != null && data.containsKey(skipField))) {
|
||||||
|
_convertMapTimestamps(data, diffMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归处理所有子元素
|
||||||
|
data.forEach((key, value) {
|
||||||
|
if (value is Map || value is List) {
|
||||||
|
// 如果当前key是要跳过的字段,则不深入处理其内容
|
||||||
|
if (skipField != null && key == skipField) {
|
||||||
|
return; // 跳过hrsp数组的处理
|
||||||
|
}
|
||||||
|
_convertTimestampsRecursive(value, diffMs, skipField: skipField);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (data is List) {
|
||||||
|
for (final item in data) {
|
||||||
|
if (item is Map || item is List) {
|
||||||
|
_convertTimestampsRecursive(item, diffMs, skipField: skipField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换map中的时间戳字段
|
||||||
|
void _convertMapTimestamps(Map map, int diffMs) {
|
||||||
|
// 要转换的字段名
|
||||||
|
const timestampFields = ['startTime', 'endTime', 'st', 'et'];
|
||||||
|
|
||||||
|
for (final field in timestampFields) {
|
||||||
|
if (map.containsKey(field) && map[field] != null) {
|
||||||
|
final value = map[field];
|
||||||
|
if (value is int) {
|
||||||
|
map[field] = value + diffMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import 'package:vbvs_app/common/color/app_uri_status.dart';
|
|||||||
import 'package:vbvs_app/common/util/DailyLogUtils.dart';
|
import 'package:vbvs_app/common/util/DailyLogUtils.dart';
|
||||||
import 'package:vbvs_app/common/util/FirmwareVersionService.dart';
|
import 'package:vbvs_app/common/util/FirmwareVersionService.dart';
|
||||||
import 'package:vbvs_app/common/util/MyUtils.dart';
|
import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||||
|
import 'package:vbvs_app/common/util/base64Tool.dart';
|
||||||
import 'package:vbvs_app/common/util/requestWithLog.dart';
|
import 'package:vbvs_app/common/util/requestWithLog.dart';
|
||||||
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
||||||
import 'package:vbvs_app/model/api_response.dart';
|
import 'package:vbvs_app/model/api_response.dart';
|
||||||
@@ -418,26 +419,36 @@ class MHTBlueToothController extends GetControllerEx<MHTBlueToothModel> {
|
|||||||
return result; // 在 requestWithLog 完成之后返回 result
|
return result; // 在 requestWithLog 完成之后返回 result
|
||||||
}
|
}
|
||||||
|
|
||||||
sendCommand(Map commandData) async {
|
//下发wifi指令
|
||||||
//todo 下发wifi指令
|
sendCommand(Map<String, dynamic> commandData) async {
|
||||||
if (commandData == null || commandData.isEmpty) {
|
if (commandData == null || commandData.isEmpty) {
|
||||||
throw "指令数据不能为空";
|
throw "指令数据不能为空";
|
||||||
|
}
|
||||||
|
commandData['data'] = Base64Tool.encode(commandData['data']);
|
||||||
|
if (Base64Tool.decode(commandData['data']) != "FFFFFFFF00031000010014FD" &&
|
||||||
|
Base64Tool.decode(commandData['data']).length <= 24) {
|
||||||
|
ef.log("下发指令: ${Base64Tool.decode(commandData['data'])}");
|
||||||
|
commandData['wfr'] = false;
|
||||||
|
//todo 填充蓝牙指令
|
||||||
|
String serviceAddress = ServiceConstant.service_address;
|
||||||
|
String serviceName = ServiceConstant.server_service;
|
||||||
|
String serviceApi = ServiceConstant.sendWifiCommand;
|
||||||
|
String queryUrl = "${serviceAddress}${serviceName}${serviceApi}";
|
||||||
|
await requestWithLog(
|
||||||
|
logTitle: "下发wifi控制指令",
|
||||||
|
method: MyHttpMethod.post,
|
||||||
|
queryUrl: queryUrl,
|
||||||
|
data: commandData,
|
||||||
|
onSuccess: (res) {
|
||||||
|
ef.log("下发指令成功: ${res.msg}");
|
||||||
|
},
|
||||||
|
onFailure: (res) {
|
||||||
|
throw "下发wifi控制指令失败: ${res.msg}";
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// ef.log("下发指令: ${Base64Tool.decode(commandData['data'])}");
|
||||||
}
|
}
|
||||||
//todo 填充蓝牙指令
|
|
||||||
String serviceAddress = ServiceConstant.service_address;
|
|
||||||
String serviceName = ServiceConstant.server_service;
|
|
||||||
String serviceApi = ServiceConstant.sendWifiCommand;
|
|
||||||
String queryUrl = "${serviceAddress}${serviceName}${serviceApi}";
|
|
||||||
await requestWithLog(
|
|
||||||
logTitle: "下发wifi控制指令",
|
|
||||||
method: MyHttpMethod.post,
|
|
||||||
queryUrl: queryUrl,
|
|
||||||
onSuccess: (res) {
|
|
||||||
},
|
|
||||||
onFailure: (res) {
|
|
||||||
throw "下发wifi控制指令失败: ${res.msg}";
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo 解绑的时候删除自己所拥有的所有设备的睡眠习惯
|
//todo 解绑的时候删除自己所拥有的所有设备的睡眠习惯
|
||||||
|
|||||||
@@ -1087,7 +1087,7 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
|
|||||||
newDiseaseIds;
|
newDiseaseIds;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
title: "选择慢病".tr,
|
title: "请选择慢病".tr,
|
||||||
colors: DiseaseSelectionColors(
|
colors: DiseaseSelectionColors(
|
||||||
pickerBackgroundColor:
|
pickerBackgroundColor:
|
||||||
stringToColor("#003058"),
|
stringToColor("#003058"),
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:vbvs_app/common/color/ServiceConstant.dart';
|
import 'package:vbvs_app/common/color/ServiceConstant.dart';
|
||||||
import 'package:vbvs_app/common/util/FitTool.dart';
|
import 'package:vbvs_app/common/util/FitTool.dart';
|
||||||
import 'package:vbvs_app/common/util/MyUtils.dart';
|
import 'package:vbvs_app/common/util/MyUtils.dart';
|
||||||
|
import 'package:vbvs_app/common/util/base64Tool.dart';
|
||||||
import 'package:vbvs_app/common/util/requestWithLog.dart';
|
import 'package:vbvs_app/common/util/requestWithLog.dart';
|
||||||
import 'package:vbvs_app/controller/user_info_controller.dart';
|
import 'package:vbvs_app/controller/user_info_controller.dart';
|
||||||
import 'package:vbvs_app/model/WebSocketMessage.dart';
|
import 'package:vbvs_app/model/WebSocketMessage.dart';
|
||||||
@@ -39,6 +40,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
|
|||||||
RxBool initFlag = false.obs;
|
RxBool initFlag = false.obs;
|
||||||
Timer? _resourceLoadTimer;
|
Timer? _resourceLoadTimer;
|
||||||
Widget webviewWidget = Container();
|
Widget webviewWidget = Container();
|
||||||
|
var wifiResponseData;
|
||||||
|
|
||||||
WebviewTestController() : super(WebviewTestModel()) {
|
WebviewTestController() : super(WebviewTestModel()) {
|
||||||
web = WebviewHelper(
|
web = WebviewHelper(
|
||||||
@@ -147,6 +149,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
|
|||||||
'mac'.tr: selectDevice['mac'.tr],
|
'mac'.tr: selectDevice['mac'.tr],
|
||||||
})));
|
})));
|
||||||
dealInstantData(selectDevice);
|
dealInstantData(selectDevice);
|
||||||
|
dealDeviceData(selectDevice);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ef.log("[切换设备失败]$e");
|
ef.log("[切换设备失败]$e");
|
||||||
}
|
}
|
||||||
@@ -189,26 +192,26 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
|
|||||||
return instantData;
|
return instantData;
|
||||||
});
|
});
|
||||||
bridge.sdk.startTimer((args) async {
|
bridge.sdk.startTimer((args) async {
|
||||||
ef.log('queryInstantData: $args');
|
ef.log('开启定时: $args');
|
||||||
MHTHomeController homeController = Get.find();
|
MHTHomeController homeController = Get.find();
|
||||||
homeController.startTimer(args);
|
homeController.startTimer(args);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
bridge.sdk.cancelTimer((args) async {
|
bridge.sdk.cancelTimer((args) async {
|
||||||
ef.log('queryInstantData: $args');
|
ef.log('退出定时: $args');
|
||||||
MHTHomeController homeController = Get.find();
|
MHTHomeController homeController = Get.find();
|
||||||
homeController.cancelTimer(args);
|
homeController.cancelTimer(args);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
bridge.sdk.restoreTimer((args) async {
|
bridge.sdk.restoreTimer((args) async {
|
||||||
ef.log('更新定时: $args[0]');
|
ef.log('更新定时: $args[0]');
|
||||||
ef.log('queryInstantData: $args');
|
ef.log('更新定时: $args');
|
||||||
MHTHomeController homeController = Get.find();
|
MHTHomeController homeController = Get.find();
|
||||||
var data = await homeController.restoreTimer(args);
|
var data = await homeController.restoreTimer(args);
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
bridge.sdk.toBindDevice((args) async {
|
bridge.sdk.toBindDevice((args) async {
|
||||||
ef.log('queryInstantData: $args');
|
ef.log('绑定设备: $args');
|
||||||
Get.toNamed("/mHTDeviceTypePage");
|
Get.toNamed("/mHTDeviceTypePage");
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -471,7 +474,100 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
|
|||||||
);
|
);
|
||||||
ws.connect();
|
ws.connect();
|
||||||
}
|
}
|
||||||
//EasyFlutter End
|
|
||||||
|
void dealDeviceData(selectDevice) {
|
||||||
|
// 处理设备本身的数据
|
||||||
|
var ws;
|
||||||
|
ws = Easyws(
|
||||||
|
url: ServiceConstant.webSocketService,
|
||||||
|
onData: (data) {
|
||||||
|
try {
|
||||||
|
var tmp;
|
||||||
|
if (data is String) {
|
||||||
|
tmp = jsonDecode(data);
|
||||||
|
} else if (data is Map<String, dynamic>) {
|
||||||
|
tmp = data; // 直接用
|
||||||
|
} else {
|
||||||
|
print("未知数据格式".tr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp['data'] != null && tmp['data'] is Map) {
|
||||||
|
var newData = tmp['data'];
|
||||||
|
var mac = newData['mac'];
|
||||||
|
String order = Base64Tool.decode(newData['data']);
|
||||||
|
final webviewTestController = Get.find<WebviewTestController>();
|
||||||
|
webviewTestController.web.jsbridge?.dart
|
||||||
|
?.updateDeviceStatusByWifi(order);
|
||||||
|
// 检查是否是当前设备的MAC
|
||||||
|
// if (mac != null && mac == selectDevice['mac']) {
|
||||||
|
// // 更新或添加设备数据
|
||||||
|
// int index = wifiResponseData
|
||||||
|
// .indexWhere((element) => element['mac'] == mac);
|
||||||
|
// if (index >= 0) {
|
||||||
|
// // 更新现有数据
|
||||||
|
// wifiResponseData[index] = newData;
|
||||||
|
// } else {
|
||||||
|
// // 添加新数据
|
||||||
|
// wifiResponseData.add(newData);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 可以在这里触发UI更新或其他处理
|
||||||
|
// // 例如:Get.find<SomeController>().updateDeviceData(newData);
|
||||||
|
// print("✅ 收到设备数据: ${newData.toString()}");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ef.log("ws error =>$e");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onStateChange: (x) {
|
||||||
|
ef.log("ws状态变化 =>$x");
|
||||||
|
if (x == EasywsState.connected) {
|
||||||
|
try {
|
||||||
|
// 1. 先取消可能存在的旧设备监听
|
||||||
|
if (lastSelectDevice != null && lastSelectDevice.isNotEmpty) {
|
||||||
|
String? oldMac = lastSelectDevice['mac'];
|
||||||
|
if (oldMac != null && oldMac.isNotEmpty) {
|
||||||
|
bool success = ws.send({
|
||||||
|
"type": 2, // 取消监听
|
||||||
|
"path": "/vsbs/web/rt/marttress", // 注意:可能需要不同的路径
|
||||||
|
"data": {"mac": oldMac},
|
||||||
|
});
|
||||||
|
if (success) {
|
||||||
|
ef.log("✅ 已取消监听旧设备:$oldMac");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ef.log("❌ 取消旧设备监听失败: $e");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 2. 开始监听新设备
|
||||||
|
if (selectDevice != null && selectDevice.isNotEmpty) {
|
||||||
|
String? newMac = selectDevice['mac'];
|
||||||
|
if (newMac != null && newMac.isNotEmpty) {
|
||||||
|
bool success = ws.send({
|
||||||
|
"type": 1, // 开始监听
|
||||||
|
"path": "/vsbs/web/rt/marttress", // 设备数据的路径,可能需要确认
|
||||||
|
"data": {"mac": newMac},
|
||||||
|
});
|
||||||
|
if (success) {
|
||||||
|
ef.log("✅ 开始监听设备:$newMac");
|
||||||
|
// 更新记录
|
||||||
|
lastSelectDevice = selectDevice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ef.log("❌ 监听新设备失败: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
ws.connect();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
|
|||||||
@@ -196,32 +196,36 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
|
|||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding:
|
||||||
EdgeInsetsDirectional.fromSTEB(0.rpx, 0.rpx, 30.rpx, 0.rpx),
|
EdgeInsetsDirectional.fromSTEB(0.rpx, 0.rpx, 0.rpx, 0.rpx),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Padding(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
padding: EdgeInsetsDirectional.fromSTEB(
|
||||||
children: [
|
0.rpx, 0.rpx, 30.rpx, 0.rpx),
|
||||||
// 圆形小球容器
|
child: Row(
|
||||||
Container(
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
width: 14.rpx, // 圆球的直径
|
children: [
|
||||||
height: 14.rpx,
|
// 圆形小球容器
|
||||||
decoration: BoxDecoration(
|
Container(
|
||||||
color: themeController.currentColor.sc2, // 小球的颜色
|
width: 14.rpx, // 圆球的直径
|
||||||
shape: BoxShape.circle, // 设置为圆形
|
height: 14.rpx,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: themeController.currentColor.sc2, // 小球的颜色
|
||||||
|
shape: BoxShape.circle, // 设置为圆形
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
SizedBox(width: 15.rpx), // 圆球和文字之间的间隔
|
||||||
SizedBox(width: 15.rpx), // 圆球和文字之间的间隔
|
// 文字
|
||||||
// 文字
|
Text(
|
||||||
Text(
|
'正常范围'.tr + "${range}",
|
||||||
'正常范围'.tr + "${range}",
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize:
|
||||||
fontSize:
|
AppConstants().smaller_text_fontSize, // 文字的大小
|
||||||
AppConstants().smaller_text_fontSize, // 文字的大小
|
color: themeController.currentColor.sc3, // 文字颜色
|
||||||
color: themeController.currentColor.sc3, // 文字颜色
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
// Container(
|
// Container(
|
||||||
// // color: Colors.red,
|
// // color: Colors.red,
|
||||||
@@ -235,18 +239,22 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
|
|||||||
// dataPoints: dataPoints,
|
// dataPoints: dataPoints,
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
Container(
|
Padding(
|
||||||
// color: Colors.red,
|
padding: EdgeInsetsDirectional.fromSTEB(
|
||||||
width: double.infinity,
|
0.rpx, 0.rpx, 30.rpx, 0.rpx),
|
||||||
// height: 300.rpx,
|
child: Container(
|
||||||
child: TimeSeriesChart(
|
// color: Colors.red,
|
||||||
startTime: startTime,
|
width: double.infinity,
|
||||||
endTime: endTime,
|
// height: 300.rpx,
|
||||||
yMin: 50,
|
child: TimeSeriesChart(
|
||||||
yMax: 150,
|
startTime: startTime,
|
||||||
dataPoints: dataPoints,
|
endTime: endTime,
|
||||||
// actYMin: min.toDouble(),
|
yMin: 50,
|
||||||
// actYMax: max.toDouble(),
|
yMax: 150,
|
||||||
|
dataPoints: dataPoints,
|
||||||
|
// actYMin: min.toDouble(),
|
||||||
|
// actYMax: max.toDouble(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Padding(
|
// Padding(
|
||||||
@@ -406,7 +414,7 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
|
|||||||
// ),
|
// ),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsetsDirectional.fromSTEB(
|
padding: EdgeInsetsDirectional.fromSTEB(
|
||||||
30.rpx, 0.rpx, 0.rpx, 0.rpx),
|
0.rpx, 0.rpx, 0.rpx, 0.rpx),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
_buildHeartRateItem(avgHeartRate),
|
_buildHeartRateItem(avgHeartRate),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import 'package:vbvs_app/component/tool/ClickableContainer.dart';
|
|||||||
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
|
||||||
import 'package:vbvs_app/controller/date/CalendarController.dart';
|
import 'package:vbvs_app/controller/date/CalendarController.dart';
|
||||||
import 'package:vbvs_app/controller/sleep/sleep_report_controller.dart';
|
import 'package:vbvs_app/controller/sleep/sleep_report_controller.dart';
|
||||||
|
import 'package:vbvs_app/controller/sleep/sleep_time_convert.dart';
|
||||||
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
|
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
|
||||||
import 'package:vbvs_app/language/AppLanguage.dart';
|
import 'package:vbvs_app/language/AppLanguage.dart';
|
||||||
import 'package:vbvs_app/pages/common/selectDialog.dart';
|
import 'package:vbvs_app/pages/common/selectDialog.dart';
|
||||||
@@ -106,7 +107,11 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=$date&type=${sleepReportController.model.type}",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=$date&type=${sleepReportController.model.type}",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
sleepReportController.sleepReport.value = res.data;
|
// 获取原始数据
|
||||||
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
_scrollToTargetComponent(sleepReportController.sleepReport);
|
_scrollToTargetComponent(sleepReportController.sleepReport);
|
||||||
},
|
},
|
||||||
@@ -997,8 +1002,10 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
print(res);
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
sleepReportController.sleepReport.value = res.data;
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
@@ -1088,8 +1095,10 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
print(res);
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
sleepReportController.sleepReport.value = res.data;
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
@@ -1138,8 +1147,10 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
print(res);
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
sleepReportController.sleepReport.value = res.data;
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
@@ -1237,8 +1248,11 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
print(res);
|
final sleepData =
|
||||||
sleepReportController.sleepReport.value = res.data;
|
Map<String, dynamic>.from(res.data);
|
||||||
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
@@ -1285,9 +1299,12 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=${data}&type=${sleepReportController.model.type}",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
print(res);
|
final sleepData =
|
||||||
|
Map<String, dynamic>.from(res.data);
|
||||||
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
sleepReportController.sleepReport.value =
|
sleepReportController.sleepReport.value =
|
||||||
res.data;
|
sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
@@ -1400,7 +1417,10 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=$data&type=$type",
|
// "https://sleepdata.he-info.com/api/analysis/sleep/analysis?mac=${widget.data['mac']}&time=$data&type=$type",
|
||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
sleepReportController.sleepReport.value = res.data;
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
},
|
},
|
||||||
onFailure: (res) {
|
onFailure: (res) {
|
||||||
TopSlideNotification.show(
|
TopSlideNotification.show(
|
||||||
@@ -1485,7 +1505,10 @@ class _NewSleepReportPageState extends State<NewSleepReportPage> {
|
|||||||
queryUrl: queryUrl,
|
queryUrl: queryUrl,
|
||||||
onSuccess: (res) {
|
onSuccess: (res) {
|
||||||
sleepReportController.isLoading.value = false;
|
sleepReportController.isLoading.value = false;
|
||||||
sleepReportController.sleepReport.value = res.data;
|
final sleepData = Map<String, dynamic>.from(res.data);
|
||||||
|
// 处理时区转换
|
||||||
|
applyTimezoneConversion(sleepData);
|
||||||
|
sleepReportController.sleepReport.value = sleepData;
|
||||||
sleepReportController.updateAll();
|
sleepReportController.updateAll();
|
||||||
_scrollToTargetComponent(sleepReportController.sleepReport);
|
_scrollToTargetComponent(sleepReportController.sleepReport);
|
||||||
},
|
},
|
||||||
|
|||||||
24
pubspec.lock
24
pubspec.lock
@@ -1336,6 +1336,22 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
|
network_info_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: network_info_plus
|
||||||
|
sha256: "5bd4b86e28fed5ed4e6ac7764133c031dfb7d3f46aa2a81b46f55038aa78ecc0"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.3"
|
||||||
|
network_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: network_info_plus_platform_interface
|
||||||
|
sha256: "7e7496a8a9d8136859b8881affc613c4a21304afeb6c324bcefc4bd0aff6b94b"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
nm:
|
nm:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2317,6 +2333,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "0.5.1"
|
||||||
|
wifi_scan:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: wifi_scan
|
||||||
|
sha256: "78896ea3db8838769053accd47cab02a62ead6480557e235295320603f84c9c7"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.1+2"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
Reference in New Issue
Block a user