Merge remote-tracking branch 'origin/master'

This commit is contained in:
czz
2025-07-11 16:48:40 +08:00
32 changed files with 762 additions and 404 deletions

View File

@@ -57,7 +57,7 @@ class _DynamicReportDetailWidgetState extends State<DynamicReportDetailWidget> {
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 25.rpx, 0, 25.rpx),
padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0.rpx),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
@@ -119,9 +119,19 @@ class _DynamicReportDetailWidgetState extends State<DynamicReportDetailWidget> {
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(
int.parse(selectedWidgets[0].time!));
String time = MyUtils.formatBindTime(dateTime);
String sleepReportUrl =
"${ServiceConstant.sleep_report_url}?mac=$mac&token=${ServiceConstant.sleep_token}&date=$time";
Get.toNamed("/sleepReportPage", arguments: sleepReportUrl);
// String sleepReportUrl =
// "${ServiceConstant.sleep_report_url}?mac=$mac&token=${ServiceConstant.sleep_token}&date=$time";
// Get.toNamed("/sleepReportPage", arguments: sleepReportUrl);
Get.toNamed("/newSleepReportPage", arguments: {
'date': dateTime != null
? dateTime.millisecondsSinceEpoch
: DateTime.now().millisecondsSinceEpoch,
"mac": mac,
'type': 1,
'name': 'sleep', //'sleep', 'heartRate' 或 'breathe'
// 'itemName': widget.data['id'],
'person': widget.targetDevice['person'],
});
} else {
TopSlideNotification.show(context,
text: "当前暂无数据".tr,

View File

@@ -117,7 +117,7 @@ class _SleepDateWidgetState extends State<SleepDateWidget> {
letterSpacing: 0.0,
color: widget.textColor ??
themeController.currentColor.sc4,
fontWeight: FontWeight.bold, // 加粗
fontWeight: FontWeight.w500, // 加粗
),
),
if ((widget.score?.trim().isNotEmpty ?? false))
@@ -158,7 +158,7 @@ class _SleepDateWidgetState extends State<SleepDateWidget> {
iconPadding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: widget.textColor ?? themeController.currentColor.sc4,
textStyle: TextStyle(
fontFamily: 'Inter Tight',
// fontFamily: 'Inter Tight',
color: themeController.currentColor.sc3,
letterSpacing: 0.0,
),

View File

@@ -6,6 +6,7 @@ import 'package:fluwx/fluwx.dart';
import 'package:get_storage/get_storage.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:vbvs_app/common/color/ServiceConstant.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/color/app_uri_status.dart';
import 'package:vbvs_app/common/util/CommonVariables.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
@@ -13,6 +14,8 @@ import 'package:vbvs_app/common/util/requestWithLog.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/controller/time/countdown_controller.dart';
import 'package:vbvs_app/controller/user_info_controller.dart';
import 'package:vbvs_app/enum/APPPackageType.dart';
import 'package:vbvs_app/main.dart';
import 'package:vbvs_app/model/api_response.dart';
import 'package:vbvs_app/model/user_data.dart';
@@ -139,6 +142,7 @@ class LoginController extends GetControllerEx<LoginModel> {
if (languageController.selectLanguage != null) {
language = languageController.selectLanguage.value!.language_code;
}
if (language != null && language.isNotEmpty) {
if (queryUrl.contains("?")) {
queryUrl += "&lang=$language";
@@ -149,6 +153,9 @@ class LoginController extends GetControllerEx<LoginModel> {
var data = {
"userName": model.phone,
};
if (AppConstants().ent_type == APPPackageType.HUANSHUI.code) {
data['code'] = "hzhskj";
}
var response =
await EasyDartModule.dio.post(queryUrl, data: jsonEncode(data));
if (response != null) {
@@ -203,7 +210,7 @@ class LoginController extends GetControllerEx<LoginModel> {
EasyDartModule.logger.error('msg:$data');
if (data) {
//登陆成功
// await dealBindProcess();
await dealBindProcess();
}
});
} catch (e) {

View File

@@ -49,14 +49,19 @@ class WeatherModelController extends GetControllerEx<WeatherModel> {
@override
Future<void> onInit() async {
super.onInit();
await _getCurrentLocation();
_weatherTimer = Timer.periodic(Duration(seconds: 5), (timer) {
_getCurrentWeather(); // 每 5 秒更新一次天气
});
_locationTimer = Timer.periodic(Duration(minutes: 10), (timer) {
_getCurrentLocation(); // 每 10 分钟更新一次位置
});
try {
await _getCurrentLocation();
_weatherTimer = Timer.periodic(Duration(seconds: 5), (timer) {
_getCurrentWeather(); // 每 5 秒更新一次天气
});
_locationTimer = Timer.periodic(Duration(minutes: 10), (timer) {
_getCurrentLocation(); // 每 10 分钟更新一次位置
});
} catch (e) {
ef.log("[天气和定位请求失败]");
}
}
@override
@@ -124,7 +129,13 @@ class WeatherModelController extends GetControllerEx<WeatherModel> {
return Future.error('位置权限被永久拒绝');
}
return await Geolocator.getCurrentPosition();
return await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.low, // 使用高精度定位,但不依赖 Google Play
distanceFilter: 1000, // 设置最小距离过滤
timeLimit: Duration(seconds: 10), // 设置获取位置的最大等待时间
),
);
}
// 获取天气信息
@@ -188,3 +199,166 @@ class WeatherModelController extends GetControllerEx<WeatherModel> {
}
}
}
// import 'dart:async';
// import 'package:EasyDartModule/EasyDartModule.dart';
// import 'package:ef/ef.dart';
// import 'package:amap_flutter_location/amap_flutter_location.dart'; // 导入 amap_flutter_location 插件
// import 'package:geocoding/geocoding.dart';
// import 'package:json_annotation/json_annotation.dart';
// import 'package:vbvs_app/common/util/CommonVariables.dart';
// import 'package:vbvs_app/controller/setting/language/language_controller.dart';
// import 'package:weather/weather.dart';
// part 'weather_controller.g.dart';
// @JsonSerializable()
// class WeatherModel {
// double? longitude; // 经度
// double? latitude; // 纬度
// String? weather_info = ''; // 天气
// int? current_temperature; // 温度
// int? min_temperature; // 最低温度
// int? max_temperature; // 最高温度
// String? wind_direction; // 风向
// int? wind_speed; // 风速等级
// String? cityName; // 城市名
// String? weatherIcon; // 天气图标
// String? weatherIconurl; // 天气图标url
// WeatherModel();
// static WeatherModel fromJson(Map<String, dynamic> json) =>
// _$WeatherModelFromJson(json);
// Map<String, dynamic> toJson() => _$WeatherModelToJson(this);
// }
// class WeatherModelController extends GetControllerEx<WeatherModel> {
// LanguageController languageController = Get.find();
// WeatherModelController() {
// attr = GetModel(WeatherModel()).obs;
// weatherFactory = WeatherFactory(CommonVariables.weather_apiKey,
// language: Language.CHINESE_SIMPLIFIED);
// }
// Timer? _weatherTimer;
// Timer? _locationTimer;
// late WeatherFactory weatherFactory;
// late AMapFlutterLocation location; // 声明 AMapFlutterLocation 实例
// @override
// Future<void> onInit() async {
// super.onInit();
// location = AMapFlutterLocation(); // 初始化 AMapFlutterLocation
// try {
// await _getCurrentLocation();
// _weatherTimer = Timer.periodic(Duration(seconds: 5), (timer) {
// _getCurrentWeather(); // 每 5 秒更新一次天气
// });
// _locationTimer = Timer.periodic(Duration(minutes: 10), (timer) {
// _getCurrentLocation(); // 每 10 分钟更新一次位置
// });
// } catch (e) {
// ef.log("[天气和定位请求失败]");
// }
// }
// @override
// void onClose() {
// _weatherTimer?.cancel(); // 取消天气更新定时器
// _locationTimer?.cancel(); // 取消位置更新定时器
// location.stopLocation(); // 停止高德定位
// super.onClose();
// }
// // 获取当前位置并存储到 model
// Future<void> _getCurrentLocation() async {
// try {
// // 开始定位
// location.startLocation();
// // 监听定位回调
// location.onLocationChanged().listen((Map<String, Object> result) {
// ///result即为定位结果
// ef.log("[位置]:${result}");
// });
// // location.onLocationChanged.listen((locationData) {
// // if (locationData.latitude != null && locationData.longitude != null) {
// // model.latitude = locationData.latitude;
// // model.longitude = locationData.longitude;
// // // 获取位置对应的城市名
// // _getCityName(locationData.latitude!, locationData.longitude!);
// // }
// // });
// } catch (e) {
// print(e);
// EasyDartModule.logger.error("获取位置失败: $e");
// }
// }
// // 获取城市名
// Future<void> _getCityName(double latitude, double longitude) async {
// try {
// List<Placemark> placemarks =
// await placemarkFromCoordinates(latitude, longitude);
// if (placemarks.isNotEmpty) {
// model.cityName = placemarks[0].locality ?? "未知数据".tr;
// }
// // 获取天气
// _getCurrentWeather();
// } catch (e) {
// print(e);
// EasyDartModule.logger.error("获取城市名失败: $e");
// }
// }
// // 获取天气信息
// Future<void> _getCurrentWeather() async {
// if (model.latitude == null || model.longitude == null) {
// EasyDartModule.logger.error("获取天气失败:位置数据获取失败");
// return; // 如果位置数据没有获取到,则不更新天气
// }
// try {
// weatherFactory.language = Language.CHINESE_SIMPLIFIED;
// Weather weather = await weatherFactory.currentWeatherByLocation(
// model.latitude!, model.longitude!);
// model.weather_info = weather.weatherDescription;
// model.min_temperature = weather.tempMin?.celsius?.toInt();
// model.max_temperature = weather.tempMax?.celsius?.toInt();
// model.current_temperature = weather.temperature?.celsius?.toInt();
// model.wind_speed = weather.windSpeed?.toInt();
// model.weatherIcon = weather.weatherIcon;
// if (model.weatherIcon != null) {
// model.weatherIconurl =
// "https://openweathermap.org/img/w/${model.weatherIcon}.png";
// }
// updateAll(); // 更新 UI
// } catch (e) {
// EasyDartModule.logger.error("获取天气失败: $e");
// print('获取天气失败: $e');
// }
// }
// // 获取 5 天天气预报
// Future<List<Weather>> getWeatherForecast(
// double latitude, double longitude) async {
// try {
// return await weatherFactory.fiveDayForecastByLocation(
// latitude, longitude);
// } catch (e) {
// print('获取天气预报失败: $e');
// rethrow;
// }
// }
// }

View File

@@ -69,7 +69,6 @@ import 'package:vbvs_app/pages/mh_page/MattressControl.dart';
import 'package:vbvs_app/pages/mh_page/device/component/mht_device_calibration_controller.dart';
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
import 'package:vbvs_app/pages/mh_page/homepage/controller/mht_home_controller.dart';
import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart';
import 'package:vbvs_app/pages/mh_page/user/controller/mht_login_controller.dart';
import 'package:vbvs_app/pages/mh_page/user/controller/mht_register_controller.dart';
import 'package:vbvs_app/pages/mh_page/user/controller/update_password_controller.dart';
@@ -81,6 +80,7 @@ import 'routers/routers.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final Locale? deviceLocale = Get.deviceLocale;
print('系统语言: ${deviceLocale?.languageCode}');
@@ -369,7 +369,6 @@ class MyApp extends StatelessWidget {
Get.lazyPut(() => CalendarController()),
Get.lazyPut(() => UserPdfController()),
Get.lazyPut(() => PrivacyPdfController()),
Get.put(WebviewTestController()),
]));
}
@@ -399,6 +398,7 @@ class MyApp extends StatelessWidget {
// Get.lazyPut(() => UserInfoController()),
Get.put(GlobalController()),
Get.put(WeatherModelController()),
Get.lazyPut(() => ApplyRepairController()),
Get.lazyPut(() => MainPageController()),
Get.lazyPut(() => BlueteethBindController()),
Get.lazyPut(() => PersonController()),

View File

@@ -1207,11 +1207,19 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
child: CustomCard(
borderRadius: AppConstants().button_container_radius,
onTap: () {
String mac = widget.device['mac'];
String sleepReportUrl =
"${ServiceConstant.sleep_report_url}?mac=${mac}&token=${ServiceConstant.sleep_token}";
Get.toNamed("/sleepReportPage",
arguments: sleepReportUrl);
// String mac = widget.device['mac'];
// String sleepReportUrl =
// "${ServiceConstant.sleep_report_url}?mac=${mac}&token=${ServiceConstant.sleep_token}";
// Get.toNamed("/sleepReportPage",
// arguments: sleepReportUrl);
Get.toNamed("/newSleepReportPage", arguments: {
'date':DateTime.now().millisecondsSinceEpoch,
"mac": widget.device['mac'],
'type': 1,
'name': 'sleep', //'sleep', 'heartRate' 或 'breathe'
// 'itemName': widget.data['id'],
'person': widget.device['person'],
});
},
colors: [
themeController.currentColor.sc1,

View File

@@ -125,9 +125,10 @@ class _InstantBodyPageState extends State<InstantBodyPage>
// 心率 呼吸 体动 呼吸暂停
if ("离床" == inBed) {
breathState = "";
data["breathRate"] = 0;
data["heartRate"] = 0;
data["bodyMotion"] = 0;
bodyMotion = 0;
breathrate = 0;
heartrate = 0;
snores = "";
} else {
breathState = data["breathState"];
bodyMotion = data['bodyMotion'];
@@ -829,10 +830,12 @@ class _InstantBodyPageState extends State<InstantBodyPage>
title: "体动".tr,
iconAsset:
"assets/img/icon/bodymotion.svg",
value: (bodyMotion == null ||
bodyMotion == -1)
? "未知数据".tr
: "$bodyMotion",
value: inBed == "离床"
? ("-")
: (bodyMotion == null ||
bodyMotion == -1)
? "未知数据".tr
: "$bodyMotion",
),
],
),
@@ -844,16 +847,20 @@ class _InstantBodyPageState extends State<InstantBodyPage>
title: "心率".tr,
iconAsset:
"assets/img/icon/heart.svg",
value: (heartrate == null ||
heartrate == -1)
? "未知数据".tr
: "$heartrate",
value: inBed == "离床"
? "-"
: ((heartrate == null ||
heartrate == -1)
? "未知数据".tr
: "$heartrate"),
),
DeviceStatusInfoWidget(
title: "打鼾".tr,
iconAsset:
"assets/img/icon/snore.svg",
value: '${snores}'.tr,
value: inBed == "离床"
? "-"
: ('${snores}'.tr),
),
],
),
@@ -865,16 +872,20 @@ class _InstantBodyPageState extends State<InstantBodyPage>
title: "呼吸".tr,
iconAsset:
"assets/img/icon/breathe.svg",
value: (breathrate == null ||
breathrate == -1)
? "未知数据".tr
: "$breathrate",
value: inBed == "离床"
? ("-")
: ((breathrate == null ||
breathrate == -1)
? "未知数据".tr
: "$breathrate"),
),
DeviceStatusInfoWidget(
title: "呼吸暂停".tr,
iconAsset:
"assets/img/icon/breathe_pause.svg",
value: '${breathState}',
value: inBed == "离床"
? "-"
: ('${breathState}'),
),
],
),

View File

@@ -360,7 +360,8 @@ class _BlueteethDevicePageState extends State<BlueteethDevicePage> {
'最小信号强度'.tr,
style: TextStyle(
fontFamily: 'Inter',
color: stringToColor("#003058"),
// color: stringToColor("#003058"),
color: Colors.white,
fontSize: 26.rpx,
letterSpacing: 0.0,
),

View File

@@ -1,7 +1,6 @@
import 'package:EasyDartModule/EasyDartModule.dart' as edm;
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:fluwx/fluwx.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
@@ -19,7 +18,6 @@ import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
import 'package:vbvs_app/controller/time/countdown_controller.dart';
import 'package:vbvs_app/controller/user_info_controller.dart';
import 'package:vbvs_app/main.dart';
import 'package:vbvs_app/model/api_response.dart';
class OtherLoginPage extends StatefulWidget {
@@ -68,7 +66,10 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
//首次未注册的用户引导去手机号填写页面
//已注册的用户直接跳转首页
if (CommonVariables.isNetWorkOn == false) {
showToast("网络未连接,请开启设备网络后重试");
TopSlideNotification.show(context,
text: "网络未连接,请开启设备网络后重试".tr,
textColor: themeController.currentColor.sc9);
// showToast("网络未连接,请开启设备网络后重试");
return;
}
ApiResponse msg = await loginController.loginByWechatCode(code);
@@ -82,9 +83,13 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
// TODO 操作全部跳转页面前成功以后移除监听,防止重复监听,其他方式登录成功也需要移出监听
// fluwxCancelable?.cancel();
} else if (errCode == -4) {
showToast("用户拒绝授权");
TopSlideNotification.show(context,
text: "用户拒绝授权".tr, textColor: themeController.currentColor.sc9);
// showToast("用户拒绝授权");
} else if (errCode == -2) {
showToast("用户取消授权");
TopSlideNotification.show(context,
text: "用户取消授权".tr, textColor: themeController.currentColor.sc9);
// showToast("用户取消授权");
}
}
});
@@ -127,13 +132,14 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
},
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
16.rpx, 10.rpx, 16.rpx, 10.rpx),
child: SvgPicture.asset(
'assets/img/icon/arrow_left.svg',
width: 25.rpx,
height: 25.rpx, // 如果 SVG 中没有固定颜色,使用 color 设置
color: themeController.currentColor.sc3,
),
0.rpx, 10.rpx, 16.rpx, 10.rpx),
// child: SvgPicture.asset(
// 'assets/img/icon/arrow_left.svg',
// width: 25.rpx,
// height: 25.rpx, // 如果 SVG 中没有固定颜色,使用 color 设置
// color: themeController.currentColor.sc3,
// ),
child: returnIconButtomNew,
),
),
Expanded(
@@ -152,7 +158,9 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
child: Align(
alignment: AlignmentDirectional(0, 0),
child: Text(
AppConstants().ent_type == 1?'登录页.欢迎使用太和e护'.tr:"欢迎使用欢睡科技",
AppConstants().ent_type == 1
? '登录页.欢迎使用太和e护'.tr
: "欢迎使用欢睡科技",
style: TextStyle(
fontFamily: 'Inter',
fontSize: 48.rpx,
@@ -281,8 +289,7 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
focusedErrorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color:
Colors.red,
color: Colors.red,
width: 1.rpx,
),
borderRadius:
@@ -314,7 +321,6 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
),
),
),
Align(
alignment: AlignmentDirectional(-1, 0),
child: Padding(
@@ -408,8 +414,7 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
focusedErrorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color:
Colors.red,
color: Colors.red,
width: 1.rpx,
),
borderRadius:
@@ -698,8 +703,7 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
),
activeColor:
stringToColor("#FF9F66"), //固定
checkColor:
Colors.white,
checkColor: Colors.white,
),
)),
Expanded(
@@ -804,7 +808,9 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
padding: EdgeInsetsDirectional.fromSTEB(
0, 0, 0, 36.rpx),
child: Text(
'登录页.其他登录方式'.tr,
AppConstants().ent_type == 1
? '登录页.欢迎使用太和e护'.tr
: "欢迎使用欢睡科技",
style: TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,

View File

@@ -1,12 +1,17 @@
import 'dart:convert';
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:vbvs_app/common/util/CommonVariables.dart';
import 'package:vbvs_app/component/NullDataComponentWidget.dart';
import 'package:vbvs_app/model/WebSocketMessage.dart';
import 'package:vbvs_app/pages/common/bezier_bottom_navigation_bar.dart';
import 'package:vbvs_app/pages/mh_page/MattressControl.dart';
import 'package:vbvs_app/pages/mh_page/homepage/mht_sleep_report_page.dart';
import 'package:vbvs_app/pages/mh_page/homepage/new_Home_page.dart';
import 'package:vbvs_app/pages/mh_page/new_mine_page.dart';
import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart';
import 'package:EasyDartModule/EasyDartModule.dart' as edm;
class MainPageBBottomChange extends StatefulWidget {
// 全局 key用于静态访问 _HomePageState
@@ -138,11 +143,24 @@ class _HomePageState extends State<MainPageBBottomChange>
}
Future<void> dealWebSource(int index) async {
WebviewTestController webviewTestController = Get.find();
if (index == 2) {
await webviewTestController.web.jsbridge?.dart.pageActive(true);
} else {
await webviewTestController.web.jsbridge?.dart.pageInActive();
try {
WebviewTestController webviewTestController = Get.find();
if (index == 2) {
await webviewTestController.web.jsbridge?.dart.pageActive(true);
//激活websocket
CommonVariables.callMap["/smartbed/connect"] = (data) {
//订阅连接消息
ef.log("[设备申请连接]:$data");
};
edm.EasyDartModule.websocket.sendData(jsonEncode(WebSocketMessage(
path: "/smartbed/connect",
type: 5,
data: {"mac": webviewTestController.selectDevice['mac']})));
} else {
await webviewTestController.web.jsbridge?.dart.pageInActive();
}
} catch (e) {
ef.log("[激活控制页面报错]:$e");
}
}
}

View File

@@ -994,12 +994,89 @@ class _HomePageState extends State<HomePage> {
);
}
// return Expanded(
// child: SingleChildScrollView(
// child: Column(
// children: List.generate(
// deviceList.length,
// (i) {
// String mac = macList[i];
// List<dynamic> dailyDataList =
// reportData[mac]!;
// Map? targetDevice =
// deviceList.firstWhereOrNull(
// (device) => device['mac'] == mac,
// );
// List stateModule = [];
// String currentTime = "";
// String goalMac = targetDevice?['mac'];
// var person = targetDevice?['person'];
// return DynamicReportDetailWidget(
// key: ValueKey(
// '${targetDevice!['mac']}_${homeController.model.type}'), // 添加唯一key
// targetDevice: targetDevice!,
// sleepDateWidgets: List.generate(
// dailyDataList.length,
// (j) {
// var dayData = dailyDataList[j];
// DateTime date =
// DateTime.fromMillisecondsSinceEpoch(
// dayData['time'] is String
// ? int.parse(dayData['time'])
// : dayData['time'],
// );
// if (dayData['selected'] != null &&
// dayData['selected'] == true &&
// dayData['state'] != null) {
// stateModule = dayData['state'];
// currentTime = dayData['time'];
// }
// return SleepDateWidget(
// mac: mac,
// time: dayData['time'],
// date: date,
// score: dayData['score']?['socre']
// ?.toString() ??
// '',
// comment: dayData['score']?['name'],
// textColor: dayData['score']
// ?['color'] ==
// null
// ? null
// : stringToColor(
// dayData['score']?['color']),
// isSelected: dayData['selected'],
// );
// },
// ),
// sleepDataModuleWidgets: stateModule
// .isNotEmpty
// ? List.generate(
// stateModule.length,
// (j) {
// stateModule[j]['onto'] = true;
// stateModule[j]['time'] =
// currentTime;
// stateModule[j]['mac'] = goalMac;
// stateModule[j]['person'] = person;
// return SleepDataModuleWidget(
// data: stateModule[j],
// );
// },
// )
// : [],
// );
// },
// ),
// ),
// ),
// );
return Expanded(
child: SingleChildScrollView(
child: Column(
children: List.generate(
deviceList.length,
(i) {
children: [
SizedBox(height: 26.rpx), // 第一个上方间距
...List.generate(deviceList.length, (i) {
String mac = macList[i];
List<dynamic> dailyDataList =
reportData[mac]!;
@@ -1011,63 +1088,66 @@ class _HomePageState extends State<HomePage> {
String currentTime = "";
String goalMac = targetDevice?['mac'];
var person = targetDevice?['person'];
return DynamicReportDetailWidget(
key: ValueKey(
'${targetDevice!['mac']}_${homeController.model.type}'), // 添加唯一key
targetDevice: targetDevice!,
sleepDateWidgets: List.generate(
dailyDataList.length,
(j) {
var dayData = dailyDataList[j];
DateTime date =
DateTime.fromMillisecondsSinceEpoch(
dayData['time'] is String
? int.parse(dayData['time'])
: dayData['time'],
);
if (dayData['selected'] != null &&
dayData['selected'] == true &&
dayData['state'] != null) {
stateModule = dayData['state'];
currentTime = dayData['time'];
}
return SleepDateWidget(
mac: mac,
time: dayData['time'],
date: date,
score: dayData['score']?['socre']
?.toString() ??
'',
comment: dayData['score']?['name'],
textColor: dayData['score']
?['color'] ==
null
? null
: stringToColor(
dayData['score']?['color']),
isSelected: dayData['selected'],
);
},
),
sleepDataModuleWidgets: stateModule
.isNotEmpty
? List.generate(
stateModule.length,
(j) {
stateModule[j]['onto'] = true;
stateModule[j]['time'] =
currentTime;
stateModule[j]['mac'] = goalMac;
stateModule[j]['person'] = person;
return SleepDataModuleWidget(
data: stateModule[j],
);
},
)
: [],
return Column(
children: [
DynamicReportDetailWidget(
key: ValueKey(
'${targetDevice!['mac']}_${homeController.model.type}'),
targetDevice: targetDevice!,
sleepDateWidgets: List.generate(
dailyDataList.length, (j) {
var dayData = dailyDataList[j];
DateTime date = DateTime
.fromMillisecondsSinceEpoch(
dayData['time'] is String
? int.parse(dayData['time'])
: dayData['time'],
);
if (dayData['selected'] == true &&
dayData['state'] != null) {
stateModule = dayData['state'];
currentTime = dayData['time'];
}
return SleepDateWidget(
mac: mac,
time: dayData['time'],
date: date,
score: dayData['score']?['socre']
?.toString() ??
'',
comment: dayData['score']?['name'],
textColor: dayData['score']
?['color'] ==
null
? null
: stringToColor(
dayData['score']?['color']),
isSelected: dayData['selected'],
);
}),
sleepDataModuleWidgets: stateModule
.isNotEmpty
? List.generate(stateModule.length,
(j) {
stateModule[j]['onto'] = true;
stateModule[j]['time'] =
currentTime;
stateModule[j]['mac'] = goalMac;
stateModule[j]['person'] =
person;
return SleepDataModuleWidget(
data: stateModule[j]);
})
: [],
),
SizedBox(
height:
26.rpx), // 每个 widget 下方间距(包括最后一个)
],
);
},
),
}),
],
),
),
);

View File

@@ -629,13 +629,13 @@ class _MinePageState extends State<MinePage> {
// textColor:
// themeController.currentColor.sc2,
// );
Get.toNamed("/newSleepReportPage",
arguments: {
'date': DateTime.now()
.millisecondsSinceEpoch,
"mac": 'aaaaaaeeeeeq',
'type': 1
});
// Get.toNamed("/newSleepReportPage",
// arguments: {
// 'date': DateTime.now()
// .millisecondsSinceEpoch,
// "mac": 'aaaaaaeeeeeq',
// 'type': 1
// });
}
},
child: Container(

View File

@@ -17,6 +17,7 @@ import 'package:vbvs_app/pages/mh_page/component/mht_bind_dialog.dart';
import 'package:vbvs_app/pages/mh_page/device/component/DeviceComponentWidget.dart';
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
import 'package:vbvs_app/pages/mh_page/searchWidget.dart';
class MHTBlueteethDevicePage extends StatefulWidget {
var deviceType;
@@ -146,7 +147,8 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
final filteredResults = results.where((r) {
final localName = r.advertisementData.localName;
final isTarget = r.rssi > signalThreshold &&
isTargetDevice(localName, widget.deviceType['reg'].cast<String>());
isTargetDevice(
localName, widget.deviceType['reg'].cast<String>());
if (!isTarget) return false;
final name = r.advertisementData.advName.toLowerCase();
String macAddress = r.device.remoteId.str;
@@ -336,8 +338,8 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
stringToColor("FCFCFC"),
stringToColor("CEECE3")
stringToColor("#003058").withOpacity(0.8),
stringToColor("#003058").withOpacity(0.8),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
@@ -360,7 +362,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
: '扫描中'.tr,
style: TextStyle(
fontFamily: 'Inter',
color: stringToColor("#003058"),
color: stringToColor("#FFFFFF"),
fontSize: 26.rpx,
letterSpacing: 0.0,
),
@@ -375,8 +377,10 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
stringToColor("FCFCFC"),
stringToColor("CEECE3")
// stringToColor("FCFCFC"),
// stringToColor("CEECE3")
Colors.transparent,
Colors.transparent,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
@@ -393,7 +397,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
'最小信号强度'.tr,
style: TextStyle(
fontFamily: 'Inter',
color: stringToColor("#003058"),
color: stringToColor("#FFFFFF"),
fontSize: 26.rpx,
letterSpacing: 0.0,
),
@@ -423,7 +427,7 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
'${mhtBlueToothController.model.singal!.toInt()}',
style: TextStyle(
fontFamily: 'Inter',
color: stringToColor("#003058"),
color: stringToColor("#FFFFFF"),
fontSize: 26.rpx,
letterSpacing: 0.0,
),
@@ -433,164 +437,194 @@ class _MHTBlueteethDevicePageState extends State<MHTBlueteethDevicePage> {
),
),
),
Container(
width: double.infinity,
decoration: BoxDecoration(
color: themeController.currentColor.sc3,
borderRadius: BorderRadius.circular(20.rpx),
),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
35.rpx, 0, 35.rpx, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 0.rpx, 0, 0),
child: Container(
width: 25.rpx,
height: 25.rpx,
decoration: BoxDecoration(),
child: SvgPicture.asset(
'assets/img/icon/query.svg',
fit: BoxFit.cover,
color: stringToColor("#333333"),
),
),
),
Expanded(
child: Container(
width: 100.rpx,
height: 90.rpx,
decoration: BoxDecoration(
color: Colors.white,
),
child: Align(
alignment:
AlignmentDirectional(-1, 0),
child: TextFormField(
initialValue:
mhtBlueToothController
.search.value,
onChanged: (Value) {
mhtBlueToothController
.search.value = Value;
},
autofocus: false,
obscureText: false,
decoration: InputDecoration(
isDense: true,
labelStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
),
hintText: '检索设备'.tr,
hintStyle: TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
),
enabledBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius:
BorderRadius.circular(
8.rpx),
),
focusedBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Color(0x00000000),
width: 1.rpx,
),
borderRadius:
BorderRadius.circular(
8.rpx),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius:
BorderRadius.circular(
8.rpx),
),
focusedErrorBorder:
OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 1.rpx,
),
borderRadius:
BorderRadius.circular(
8.rpx),
),
filled: false,
fillColor: themeController
.currentColor.sc22,
),
style: TextStyle(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
),
cursorColor:
stringToColor("#003058"),
),
),
),
),
].divide(SizedBox(width: 6.rpx)),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
26.rpx, 0, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
SizedBox(
height: 50.rpx,
child: VerticalDivider(
thickness: 2.rpx,
color: stringToColor("#333333"),
),
),
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor:
themeController.currentColor.sc4,
borderRadius: 6.rpx,
padding: EdgeInsets.zero,
onTap: () async {
_startScanning();
},
child: Text(
'搜索'.tr,
style: TextStyle(
fontFamily: 'Inter',
fontSize: 30.rpx,
letterSpacing: 0.0,
color: stringToColor("#333333"),
),
),
),
].divide(SizedBox(width: 26.rpx)),
),
),
],
),
// Container(
// width: double.infinity,
// decoration: BoxDecoration(
// color: themeController.currentColor.sc3,
// borderRadius: BorderRadius.circular(20.rpx),
// ),
// // child: Padding(
// // padding: EdgeInsetsDirectional.fromSTEB(
// // 35.rpx, 0, 35.rpx, 0),
// // child: Row(
// // mainAxisSize: MainAxisSize.max,
// // mainAxisAlignment: MainAxisAlignment.spaceBetween,
// // children: [
// // Expanded(
// // child: Row(
// // mainAxisSize: MainAxisSize.max,
// // children: [
// // Padding(
// // padding: EdgeInsetsDirectional.fromSTEB(
// // 0, 0.rpx, 0, 0),
// // child: Container(
// // width: 25.rpx,
// // height: 25.rpx,
// // decoration: BoxDecoration(),
// // child: SvgPicture.asset(
// // 'assets/img/icon/query.svg',
// // fit: BoxFit.cover,
// // color: stringToColor("#333333"),
// // ),
// // ),
// // ),
// // Expanded(
// // child: Container(
// // width: 100.rpx,
// // height: 90.rpx,
// // decoration: BoxDecoration(
// // color: Colors.white,
// // ),
// // child: Align(
// // alignment:
// // AlignmentDirectional(-1, 0),
// // child: TextFormField(
// // initialValue:
// // mhtBlueToothController
// // .search.value,
// // onChanged: (Value) {
// // mhtBlueToothController
// // .search.value = Value;
// // },
// // autofocus: false,
// // obscureText: false,
// // decoration: InputDecoration(
// // isDense: true,
// // labelStyle: TextStyle(
// // fontFamily: 'Inter',
// // fontSize: 26.rpx,
// // letterSpacing: 0.0,
// // ),
// // hintText: '检索设备'.tr,
// // hintStyle: TextStyle(
// // fontFamily: 'Inter',
// // fontSize: 26.rpx,
// // letterSpacing: 0.0,
// // ),
// // enabledBorder:
// // OutlineInputBorder(
// // borderSide: BorderSide(
// // color: Color(0x00000000),
// // width: 1.rpx,
// // ),
// // borderRadius:
// // BorderRadius.circular(
// // 8.rpx),
// // ),
// // focusedBorder:
// // OutlineInputBorder(
// // borderSide: BorderSide(
// // color: Color(0x00000000),
// // width: 1.rpx,
// // ),
// // borderRadius:
// // BorderRadius.circular(
// // 8.rpx),
// // ),
// // errorBorder: OutlineInputBorder(
// // borderSide: BorderSide(
// // color: Colors.red,
// // width: 1.rpx,
// // ),
// // borderRadius:
// // BorderRadius.circular(
// // 8.rpx),
// // ),
// // focusedErrorBorder:
// // OutlineInputBorder(
// // borderSide: BorderSide(
// // color: Colors.red,
// // width: 1.rpx,
// // ),
// // borderRadius:
// // BorderRadius.circular(
// // 8.rpx),
// // ),
// // filled: false,
// // fillColor: themeController
// // .currentColor.sc22,
// // ),
// // style: TextStyle(
// // fontFamily: 'Inter',
// // fontSize: 26.rpx,
// // letterSpacing: 0.0,
// // ),
// // cursorColor:
// // stringToColor("#003058"),
// // ),
// // ),
// // ),
// // ),
// // ].divide(SizedBox(width: 6.rpx)),
// // ),
// // ),
// // Padding(
// // padding: EdgeInsetsDirectional.fromSTEB(
// // 26.rpx, 0, 0, 0),
// // child: Row(
// // mainAxisSize: MainAxisSize.max,
// // children: [
// // SizedBox(
// // height: 50.rpx,
// // child: VerticalDivider(
// // thickness: 2.rpx,
// // color: stringToColor("#333333"),
// // ),
// // ),
// // ClickableContainer(
// // backgroundColor: Colors.transparent,
// // highlightColor:
// // themeController.currentColor.sc4,
// // borderRadius: 6.rpx,
// // padding: EdgeInsets.zero,
// // onTap: () async {
// // _startScanning();
// // },
// // child: Text(
// // '搜索'.tr,
// // style: TextStyle(
// // fontFamily: 'Inter',
// // fontSize: 30.rpx,
// // letterSpacing: 0.0,
// // color: stringToColor("#333333"),
// // ),
// // ),
// // ),
// // ].divide(SizedBox(width: 26.rpx)),
// // ),
// // ),
// // ],
// // ),
// // ),
// child: Padding(
// padding:
// EdgeInsetsDirectional.fromSTEB(0, 10, 0, 23),
// child: SearchWidget(
// keyword: mhtBlueToothController.search.value,
// color: Colors.red,
// hint: "检索设备",
// onChange: (d) {
// mhtBlueToothController.search.value = d;
// },
// findCallback: () {
// // controller.getDeviceList();
// },
// ),
// ),
// ),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
child: SearchWidget(
padding: EdgeInsets.all(0),
keyword: mhtBlueToothController.search.value,
color: Colors.red,
hint: "检索设备",
onChange: (d) {
mhtBlueToothController.search.value = d;
},
findCallback: () {
_startScanning();
},
),
),
Padding(

View File

@@ -574,6 +574,8 @@ class _NewHomePageState extends State<NewHomePage> {
'date': DateTime
.now()
.millisecondsSinceEpoch,
'person_show':
false,
},
);
}
@@ -665,6 +667,8 @@ class _NewHomePageState extends State<NewHomePage> {
'date':
timeMillis,
// 'backgroundColor':stringToColor("#003058"),
'person_show':
false,
},
);
},

View File

@@ -11,18 +11,21 @@ class SearchWidget extends GetView {
String? hint;
Function? onChange;
Function? findCallback;
final EdgeInsetsGeometry? padding; // 新增 padding 参数
SearchWidget(
{required this.keyword,
required this.color,
this.hint = "请输入关键字",
this.findCallback,
this.onChange});
SearchWidget({
required this.keyword,
required this.color,
this.hint = "请输入关键字",
this.findCallback,
this.onChange,
this.padding, // 传入 padding 参数
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
padding: padding ?? EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0), // 使用传入的 padding 或默认值
child: Container(
width: double.infinity,
decoration: BoxDecoration(
@@ -42,7 +45,6 @@ class SearchWidget extends GetView {
Container(
width: 25.rpx,
height: 25.rpx,
// width: double.infinity,
decoration: BoxDecoration(),
child: SvgPicture.asset(
'assets/img/icon/query.svg',
@@ -112,11 +114,6 @@ class SearchWidget extends GetView {
color: Colors.black,
letterSpacing: 0.0,
),
// cursorColor:
// FlutterFlowTheme.of(context).primaryText,
// validator: _model
// .textControllerValidator
// .asValidator(context),
onChanged: (d) {
onChange?.call(d);
},

View File

@@ -278,13 +278,18 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
class WebviewTestView extends GetComponent<WebviewTestController> {
WebviewTestView({super.key, super.oncreate});
// @override
// WebviewTestController newinstance() {
// if (ef.kvRoot.WebviewTestController == null) {
// ef.kvRoot.WebviewTestController = WebviewTestController();
// }
// return ef.kvRoot.WebviewTestController;
// }
@override
WebviewTestController newinstance() {
if (ef.kvRoot.WebviewTestController == null) {
ef.kvRoot.WebviewTestController = WebviewTestController();
if (Get.isRegistered<WebviewTestController>() == false) {
Get.put<WebviewTestController>(ef.kvRoot.WebviewTestController);
WebviewTestController webviewTestController = Get.find();
return webviewTestController;
}
}
return ef.kvRoot.WebviewTestController;
}
@override
Widget build(BuildContext context) {

View File

@@ -742,6 +742,9 @@ class _EPageState extends State<PersonPage> {
),
),
),
SizedBox(
height: 20.rpx,
),
],
),
),

View File

@@ -160,64 +160,65 @@ class _ApplyRepairPageState extends State<ApplyRepairPage> {
mainAxisSize: MainAxisSize.max,
children: [
Obx(() {
return Row(
mainAxisSize: MainAxisSize.max,
children: deviceTypeController.deviceTypeList.value
.map(
(deviceType) => CustomCard(
borderRadius:
AppConstants().button_container_radius,
onTap: () async {
repairController.device_type.value =
deviceType['type'];
repairController.repairList
.clear(); // 清空旧数据
repairController.repairList
.add({}); // 添加新数据
await bodyDeviceController
.getDeviceList(); // 等待数据加载
_updateRepairItemKeys(); // 清空后更新 keys
repairController
.updateAll(); // 手动触发更新(如果未自动更新)
},
colors: deviceType['type'] ==
repairController.device_type.value
? [
themeController.currentColor.sc1,
themeController.currentColor.sc2,
]
: [themeController.currentColor.sc5],
child: Container(
width: (MediaQuery.sizeOf(context).width *
0.284)
.rpx,
constraints: BoxConstraints(
minWidth: 213.rpx,
minHeight: 91.rpx,
),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(20.rpx),
),
child: Align(
alignment: AlignmentDirectional(0, 0),
child: Text(
deviceType[
'name'], // 假设 deviceType 有 name 字段
style: TextStyle(
letterSpacing: 0.0,
color:
themeController.currentColor.sc3,
fontSize: AppConstants()
.normal_text_fontSize,
return SingleChildScrollView(
scrollDirection: Axis.horizontal, // 横向滚动
child: Row(
mainAxisSize: MainAxisSize.min, // 设置为 min避免撑满父组件宽度
children: deviceTypeController.deviceTypeList.value
.map(
(deviceType) => CustomCard(
borderRadius:
AppConstants().button_container_radius,
onTap: () async {
repairController.device_type.value =
deviceType['type'];
repairController.repairList
.clear(); // 清空旧数据
repairController.repairList
.add({}); // 添加新数据
await bodyDeviceController
.getDeviceList(); // 等待数据加载
_updateRepairItemKeys(); // 清空后更新 keys
repairController.updateAll(); // 手动触发更新
},
colors: deviceType['type'] ==
repairController.device_type.value
? [
themeController.currentColor.sc1,
themeController.currentColor.sc2,
]
: [themeController.currentColor.sc5],
child: Container(
width: (MediaQuery.sizeOf(context).width *
0.284)
.rpx,
constraints: BoxConstraints(
minWidth: 213.rpx,
minHeight: 91.rpx,
),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(20.rpx),
),
child: Align(
alignment: AlignmentDirectional(0, 0),
child: Text(
deviceType['name'],
style: TextStyle(
letterSpacing: 0.0,
color: themeController
.currentColor.sc3,
fontSize: AppConstants()
.normal_text_fontSize,
),
),
),
),
),
),
)
.toList()
.divide(SizedBox(width: 25.rpx)),
)
.toList()
.divide(SizedBox(width: 25.rpx)),
),
);
}),
Obx(() {

View File

@@ -102,7 +102,7 @@ class _RepairListPageState extends State<RepairListPage> {
child: Obx(() {
final isEmpty = repairController.repairHistory.value.isEmpty;
if (isEmpty) {
return Expanded(child: NullDataWidget());
return NullDataWidget();
}
return SingleChildScrollView(
child: Column(

View File

@@ -77,7 +77,7 @@ class _DataShowWidgetState extends State<DataShowWidget> {
),
// 放入传入的 widget3
Container(
width: MediaQuery.sizeOf(context).width * 0.2, // 固定宽度
width: MediaQuery.sizeOf(context).width * 0.25, // 固定宽度
decoration: BoxDecoration(),
child: Align(
alignment: widget.alignment == MainAxisAlignment.start
@@ -90,7 +90,7 @@ class _DataShowWidgetState extends State<DataShowWidget> {
),
// 放入传入的 widget4
Container(
width: MediaQuery.sizeOf(context).width * 0.15, // 固定宽度
width: MediaQuery.sizeOf(context).width * 0.1, // 固定宽度
decoration: BoxDecoration(),
child: Align(
alignment: widget.alignment == MainAxisAlignment.start

View File

@@ -148,7 +148,7 @@ class _HeartChangeWidgetState extends State<HeartChangeWidget> {
alignment: MainAxisAlignment.center,
widget1: Row(
children: [
Expanded(
Flexible(
child: Text(
'${data['name']}',
maxLines: 1,
@@ -186,7 +186,7 @@ class _HeartChangeWidgetState extends State<HeartChangeWidget> {
width: 17.rpx,
height: 17.rpx,
child: SvgPicture.asset(
'assets/img/icon/explain.svg',
'assets/img/icon/question.svg',
fit: BoxFit.cover,
color: Colors.white,
),

View File

@@ -65,7 +65,7 @@ class _XiaoEPageState extends State<XiaoEPage> {
children: [
/// 居中标题
Text(
'健康报告'.tr,
'小e'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,