diff --git a/android/version.properties b/android/version.properties index 7d048e4..5d2067c 100644 --- a/android/version.properties +++ b/android/version.properties @@ -1,2 +1,2 @@ -flutter.android.versionName=2.0.2 -flutter.android.versionCode=7 \ No newline at end of file +flutter.android.versionName=2.0.3 +flutter.android.versionCode=8 \ No newline at end of file diff --git a/assets/file.json b/assets/file.json index 434206f..2ab6a9a 100644 --- a/assets/file.json +++ b/assets/file.json @@ -1,3 +1,3 @@ [ - "assets/miniapp/mhtControl_1.0.65.zip" + "assets/miniapp/mhtControl_1.0.66.zip" ] \ No newline at end of file diff --git a/assets/langs/en_US.json b/assets/langs/en_US.json index 20cea61..75efb8c 100644 --- a/assets/langs/en_US.json +++ b/assets/langs/en_US.json @@ -14,8 +14,8 @@ "提示内容2": "2. Grant Bluetooth and location permissions to the app", "提示内容3": "3. If using the scan function, grant camera permission", "扫一扫绑定": "Scan to add new device", - "蓝牙绑定": "Search nearby devices via Bluetooth", - "已关联体征监测设备": "Bound vital sign monitoring devices", + "蓝牙绑定": "Bluetooth Scanning", + "已关联体征监测设备": "My connected devices", "我的e护": "Mine", "云关爱": "Cloud", "报告详情": "Report details" @@ -92,7 +92,7 @@ "不显示密码": "Hide" }, "登录页": { - "欢迎使用太和e护": "Welcome to Taihe eCare", + "欢迎使用太和e护": "Welcome to Hecaring", "科技睡眠 洞悉万千": "Tech sleep, insightful data", "本机号码一键登录/注册": "One-click login/registration with this device's number", "其他手机号码": "Other account login", @@ -102,7 +102,7 @@ "协议4": "Privacy Policy", "协议5": "as well as", "协议6": "Terms of Use", - "其他登录方式": "Welcome to Taihe eCare", + "其他登录方式": "Other login methods", "未同意协议": "Please agree to the terms" }, "人员资料": { @@ -152,7 +152,7 @@ "不正确手机号": "Please enter valid phone number or email", "请输入验证码": "Please enter verification code", "登录成功": "Login successful", - "秒": "seconds", + "秒": "s", "发送成功": "Verification code sent successfully", "发送失败": "Failed to send verification code", "登录失败": "Login failed" @@ -288,7 +288,7 @@ "信号强度": "Signal strength:", "设备升级": "Device upgrade", "设备故障": "Device malfunction!", - "是否在床": "In bed:", + "是否在床": "In/Out:", "在床": "In", "离床": "Out", "较弱": "Weak", @@ -380,11 +380,11 @@ "分钟": "m", "消息提醒设置": "Message notification settings", "APP消息": "APP messages", - "APP消息介绍": "Open 'Taihe eCare' APP to view device messages", - "通用APP消息介绍": "Open 'Taihe eCare' APP to view messages", + "APP消息介绍": "Open APP to view device messages", + "通用APP消息介绍": "Open APP to view messages", "服务号消息": "Service account messages", - "服务号消息介绍": "No need to open 'Taihe eCare' APP. After following Taihe eCare service account, receive device message notifications directly in WeChat", - "通用服务号消息介绍": "No need to open 'Taihe eCare' APP. After following Taihe eCare service account, receive message notifications directly in WeChat", + "服务号消息介绍": "No need to open APP. After following HeCaring service account, receive device message notifications directly in WeChat", + "通用服务号消息介绍": "No need to open APP. After following HeCaring service account, receive message notifications directly in WeChat", "消息通知": "Message notifications", "绑定操作提示": "Device placement instructions", "绑定操作提示介绍": "Enable device placement instructions prompt", @@ -431,7 +431,7 @@ "无报告": "None", "姓名": "Name", "年龄": "Age", - "设备ID": "Device ID", + "设备ID": "Device", "体重": "Weight", "分": "", "位置权限说明": "Location Permission Description", @@ -541,6 +541,10 @@ "同意": "Agree", "保存失败": "Save Failed", "保存成功": "Save Successful", - "设备分享提醒": "Device Sharing Alert", - "有一条新的设备分享消息": "You have a new device sharing message", "去查看": "View now","设备已被用户解绑,将取消当前分享!": "The device has been unbound by the user, and the current sharing will be cancelled." + "设备分享提醒": "Device Sharing Tip", + "浅色": "Light", + "选择主题": "Select Theme", + "有一条新的设备分享消息": "You have a new device sharing message", + "去查看": "View now", + "设备已被用户解绑,将取消当前分享!": "The device has been unbound by the user, and the current sharing will be cancelled." } \ No newline at end of file diff --git a/assets/langs/zh_CN.json b/assets/langs/zh_CN.json index af6c0f0..9fa873e 100644 --- a/assets/langs/zh_CN.json +++ b/assets/langs/zh_CN.json @@ -102,7 +102,7 @@ "协议4": "《隐私政策》", "协议5": "以及", "协议6": "《用户使用条款》", - "其他登录方式": "欢迎使用太和e护", + "其他登录方式": "其他登录方式", "未同意协议": "请确认同意协议" }, "人员资料": { @@ -379,11 +379,11 @@ "分钟": "分钟", "消息提醒设置": "消息提醒设置", "APP消息": "APP消息", - "APP消息介绍": "打开“太和e护”APP,可以查看该设备的消息内容", - "通用APP消息介绍": "打开“太和e护”APP,可以查看消息内容", + "APP消息介绍": "打开APP,可以查看该设备的消息内容", + "通用APP消息介绍": "打开APP,可以查看消息内容", "服务号消息": "服务号消息", - "服务号消息介绍": "无需打开“太和e护”APP,关注太和e护服务号后,微信内即可接收该设备消息推送", - "通用服务号消息介绍": "无需打开“太和e护”APP,关注太和e护服务号后,微信内即可接收消息推送", + "服务号消息介绍": "无需打开APP,关注太和e护服务号后,微信内即可接收该设备消息推送", + "通用服务号消息介绍": "无需打开APP,关注太和e护服务号后,微信内即可接收消息推送", "消息通知": "消息通知", "绑定操作提示": "设备放置说明", "绑定操作提示介绍": "是否打开设备放置说明的提示", @@ -545,7 +545,9 @@ "保存失败": "保存失败", "保存成功": "保存成功", "设备分享提醒": "设备分享提醒", + "选择主题": "选择主题", + "浅色": "浅色", "有一条新的设备分享消息": "有一条新的设备分享消息", "去查看": "去查看", - "设备已被用户解绑,将取消当前分享!": "设备已被用户解绑,将取消当前分享!" + "设备已被用户解绑,将取消当前分享!": "设备已被用户解绑,将取消当前分享!" } \ No newline at end of file diff --git a/assets/langs/zh_TW.json b/assets/langs/zh_TW.json index 3b5a015..6869deb 100644 --- a/assets/langs/zh_TW.json +++ b/assets/langs/zh_TW.json @@ -102,7 +102,7 @@ "协议4": "《隱私政策》", "协议5": "以及", "协议6": "《用戶使用條款》", - "其他登录方式": "歡迎使用太和e護", + "其他登录方式": "其他鄧麗方式", "未同意协议": "請確認同意協議" }, "人员资料": { @@ -380,11 +380,11 @@ "分钟": "分鐘", "消息提醒设置": "消息提醒設置", "APP消息": "APP消息", - "APP消息介绍": "打開“太和e護”APP,可以查看該設備的消息內容", - "通用APP消息介绍": "打開“太和e護”APP,可以查看消息內容", + "APP消息介绍": "打開APP,可以查看該設備的消息內容", + "通用APP消息介绍": "打開APP,可以查看消息內容", "服务号消息": "服務號消息", - "服务号消息介绍": "無需打開“太和e護”APP,關注太和e護服務號後,微信內即可接收該設備消息推送", - "通用服务号消息介绍": "無需打開“太和e護”APP,關注太和e護服務號後,微信內即可接收消息推送", + "服务号消息介绍": "無需打開APP,關注太和e護服務號後,微信內即可接收該設備消息推送", + "通用服务号消息介绍": "無需打開APP,關注太和e護服務號後,微信內即可接收消息推送", "消息通知": "消息通知", "绑定操作提示": "設備放置說明", "绑定操作提示介绍": "是否打開設備放置說明的提示", @@ -539,6 +539,8 @@ "保存失败": "保存失敗", "保存成功": "保存成功", "设备分享提醒": "設備分享提醒", + "选择主题": "選擇主題", + "浅色": "淺色", "有一条新的设备分享消息": "有一條新的設備分享消息", "去查看": "去查看", "设备已被用户解绑,将取消当前分享!": "設備已被用戶解綁,將取消當前分享!" diff --git a/assets/miniapp/mhtControl_1.0.66.zip b/assets/miniapp/mhtControl_1.0.66.zip new file mode 100644 index 0000000..108021b Binary files /dev/null and b/assets/miniapp/mhtControl_1.0.66.zip differ diff --git a/lib/component/home_page/DynamicReportDetailWidget.dart b/lib/component/home_page/DynamicReportDetailWidget.dart index bed3f1a..21d71a4 100644 --- a/lib/component/home_page/DynamicReportDetailWidget.dart +++ b/lib/component/home_page/DynamicReportDetailWidget.dart @@ -2,7 +2,6 @@ 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:vbvs_app/common/color/ServiceConstant.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'; @@ -39,10 +38,10 @@ class _DynamicReportDetailWidgetState extends State { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - Future.delayed(Duration(milliseconds: 500), () { - if (!_hasScrolled && - _scrollController.hasClients && - _scrollController.position.maxScrollExtent > 0) { + Future.delayed(Duration(milliseconds: 1000), () { + if (!_hasScrolled && _scrollController.hasClients + // && _scrollController.position.maxScrollExtent > 0 + ) { _scrollController.animateTo( _scrollController.position.maxScrollExtent, duration: Duration(milliseconds: 300), @@ -196,6 +195,15 @@ class _DynamicReportDetailWidgetState extends State { ), ); } + // if (widget.sleepDataModuleWidgets.isEmpty) { + // return Container( + // height: 200.rpx, + // alignment: Alignment.center, + // child: CircularProgressIndicator( + // color: themeController.currentColor.sc1, + // ), + // ); + // } return Container( width: double.infinity, diff --git a/lib/controller/weather/weather_controller.dart b/lib/controller/weather/weather_controller.dart index 7d91cfd..a601812 100644 --- a/lib/controller/weather/weather_controller.dart +++ b/lib/controller/weather/weather_controller.dart @@ -1,3 +1,395 @@ +// import 'dart:async'; + +// import 'package:EasyDartModule/EasyDartModule.dart'; +// import 'package:ef/ef.dart'; +// import 'package:flutter/material.dart'; +// import 'package:geocoding/geocoding.dart'; +// import 'package:geolocator/geolocator.dart'; +// import 'package:json_annotation/json_annotation.dart'; +// import 'package:path/path.dart'; +// import 'package:vbvs_app/common/color/ServiceConstant.dart'; +// import 'package:vbvs_app/common/color/appConstants.dart'; +// import 'package:vbvs_app/common/util/CommonVariables.dart'; +// import 'package:vbvs_app/common/util/MyUtils.dart'; +// import 'package:vbvs_app/common/util/requestWithLog.dart'; +// import 'package:vbvs_app/controller/setting/language/language_controller.dart'; +// import 'package:vbvs_app/controller/user_info_controller.dart'; +// import 'package:vbvs_app/enum/APPPackageType.dart'; +// import 'package:vbvs_app/pages/common/selectDialog.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 json) => +// _$WeatherModelFromJson(json); + +// Map toJson() => _$WeatherModelToJson(this); +// } + +// class WeatherModelController extends GetControllerEx { +// 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; + +// @override +// Future onInit() async { +// super.onInit(); + +// try { +// await getCurrentLocation(); +// _weatherTimer = Timer.periodic(Duration(minutes: 10), (timer) { +// getCurrentWeather(); // 每 60 秒更新一次天气 +// }); + +// _locationTimer = Timer.periodic(Duration(minutes: 10), (timer) { +// getCurrentLocation(); // 每 10 分钟更新一次位置 +// }); +// } catch (e) { +// ef.log("[天气和定位请求失败]"); +// } +// } + +// @override +// void onClose() { +// _weatherTimer?.cancel(); // 取消天气更新定时器 +// _locationTimer?.cancel(); // 取消位置更新定时器 +// super.onClose(); +// } + +// // 获取当前位置并存储到 model +// Future getCurrentLocation() async { +// try { +// UserInfoController userInfoController = Get.find(); +// if (userInfoController.model.login == null || +// userInfoController.model.login != 1) { +// return; +// } +// Position position = await determinePosition(); +// if (position == null) { +// throw Exception("获取位置失败"); +// } + +// String? language = "zh_CN"; +// if (AppConstants().ent_type == APPPackageType.MHT.code) { +// if (mhLanguageController.selectLanguage != null) { +// language = mhLanguageController.selectLanguage.value!.language_code; +// } +// } else { +// if (languageController.selectLanguage != null) { +// language = languageController.selectLanguage.value!.language_code; +// } +// } +// List placemarks = []; +// // placemarks = await placemarkFromCoordinates(position.latitude, position.longitude, +// // localeIdentifier: language); +// placemarks = await placemarkFromCoordinates( +// position.latitude, +// position.longitude, +// ); + +// if (placemarks.isNotEmpty) { +// // model.cityName = placemarks[0].locality ?? "未知数据".tr; +// model.latitude = position.latitude; +// model.longitude = position.longitude; +// } + +// // 调用获取天气方法 +// // getCurrentWeather(); +// } catch (e) { +// print(e); +// EasyDartModule.logger.error("获取位置失败: $e"); +// } +// } + +// // 获取当前位置 +// // Future determinePosition() async { +// // bool serviceEnabled; +// // LocationPermission permission; + +// // serviceEnabled = await Geolocator.isLocationServiceEnabled(); +// // if (!serviceEnabled) { +// // return Future.error('位置服务未启用'); +// // } +// // try { +// // showPermissionInfoDialog( +// // Get.context!, CommonVariables().locationpermissionInfo); +// // } catch (e) { +// // ef.log("$e"); +// // } +// // try { +// // // 2️⃣ 检查权限(系统弹窗)—— 此时你的提示框仍然显示 +// // permission = await Geolocator.checkPermission(); + +// // if (permission == LocationPermission.denied) { +// // permission = await Geolocator.requestPermission(); +// // } +// // } finally { +// // // 3️⃣ 无论如何都关闭你的提示弹窗 +// // Navigator.of(Get.context!, rootNavigator: true).pop(); +// // } + +// // if (permission == LocationPermission.denied) { +// // return Future.error('位置权限被拒绝'); +// // } + +// // if (permission == LocationPermission.deniedForever) { +// // return Future.error('位置权限被永久拒绝'); +// // } + +// // return await Geolocator.getCurrentPosition( +// // forceAndroidLocationManager: true, +// // locationSettings: const LocationSettings( +// // accuracy: LocationAccuracy.best, +// // distanceFilter: 1000, // 设置最小距离过滤 +// // timeLimit: Duration(seconds: 10), // 设置获取位置的最大等待时间 +// // ), +// // ); +// // } +// Future determinePosition({int retryCount = 1}) async { +// bool serviceEnabled; +// LocationPermission permission; +// int attempt = 0; +// bool dialogShown = false; + +// // 检查定位服务是否启用 +// serviceEnabled = await Geolocator.isLocationServiceEnabled(); +// if (!serviceEnabled) { +// return Future.error('位置服务未启用'); +// } + +// try { +// // 弹出自定义提示 + +// // 检查和请求位置权限 +// permission = await Geolocator.checkPermission(); +// if (permission == LocationPermission.denied) { +// showPermissionInfoDialog( +// Get.context!, CommonVariables().locationpermissionInfo); +// dialogShown = true; + +// await Future.delayed(const Duration(milliseconds: 300)); + +// // 系统权限弹窗 +// permission = await Geolocator.requestPermission(); +// } +// } catch (e) { +// ef.log("申请位置权限出错: $e"); +// rethrow; +// } finally { +// if (dialogShown) { +// if (Get.isDialogOpen ?? false) { +// Get.back(); // 关闭弹窗 +// } +// } +// } + +// // 如果权限被拒绝,直接返回错误 +// if (permission == LocationPermission.denied) { +// return Future.error('位置权限被拒绝'); +// } + +// // 如果权限被永久拒绝,直接返回错误 +// if (permission == LocationPermission.deniedForever) { +// return Future.error('位置权限被永久拒绝'); +// } + +// // 开始获取位置,最多重试 retryCount 次 +// while (attempt < retryCount) { +// attempt++; +// try { +// // 设置定位精度 +// LocationAccuracy accuracy = attempt == 1 +// ? LocationAccuracy.medium // 初次尝试用中等精度 +// : LocationAccuracy.best; // 如果第一次失败,尝试高精度定位 + +// return await Geolocator.getCurrentPosition( +// forceAndroidLocationManager: true, +// locationSettings: LocationSettings( +// accuracy: accuracy, +// distanceFilter: 1000, +// timeLimit: Duration(seconds: 10), +// ), +// ); +// } catch (e) { +// if (attempt >= retryCount) { +// return Future.error('获取位置失败: $e'); +// } +// await Future.delayed(Duration(seconds: 2)); // 重试前等待 +// } +// } + +// return Future.error('获取位置失败,已重试 $retryCount 次'); +// } + +// // 获取天气信息 +// // Future getCurrentWeather() async { +// // await getCurrentLocation(); +// // if (model.latitude == null || model.longitude == null) { +// // EasyDartModule.logger.error("获取天气失败:位置数据获取失败"); +// // return; // 如果位置数据没有获取到,则不更新天气 +// // } +// // try { +// // weatherFactory.language = Language.CHINESE_SIMPLIFIED; +// // String? language = "zh_CN"; +// // if (AppConstants().ent_type == APPPackageType.MHT.code) { +// // if (mhLanguageController.selectLanguage != null) { +// // language = mhLanguageController.selectLanguage.value!.language_code; +// // } +// // } else { +// // if (languageController.selectLanguage != null) { +// // language = languageController.selectLanguage.value!.language_code; +// // } +// // } +// // if (language == "zh_CN") { +// // weatherFactory.language = Language.CHINESE_SIMPLIFIED; +// // } else { +// // weatherFactory.language = Language.ENGLISH; +// // } +// // // Weather weather = await weatherFactory.currentWeatherByLocation( +// // // model.latitude!, model.longitude!); +// // String location = "${model.longitude},${model.latitude}"; +// // String serviceAddress = ServiceConstant.service_address; +// // String serviceName = ServiceConstant.server_service; +// // String serviceApi = ServiceConstant.weather_url; +// // String queryUrl = +// // "${serviceAddress}${serviceName}${serviceApi}?location=$location"; +// // await requestWithLog( +// // logTitle: "获取天气信息", +// // method: MyHttpMethod.get, +// // queryUrl: queryUrl, +// // onSuccess: (res) { +// // print(res.data); +// // model.weather_info = res.data["info"]; +// // model.current_temperature = int.parse(res.data["temp"]); +// // if (res.data['icon'] != null) { +// // model.weatherIconurl = "${res.data['icon']}"; +// // } +// // model.cityName = res.data["city"]; +// // }, +// // onFailure: (res) { +// // print(res.data); +// // }); +// // updateAll(); // 更新 UI +// // } catch (e) { +// // EasyDartModule.logger.error("获取天气失败: $e"); +// // print('获取天气失败: $e'); +// // } +// // } + +// Future getCurrentWeather({int retryCount = 1}) async { +// int attempt = 0; +// bool success = false; +// while (attempt < retryCount && success == false) { +// attempt++; +// try { +// // 先尝试获取定位 +// await getCurrentLocation(); +// if (model.latitude == null || model.longitude == null) { +// EasyDartModule.logger.error("获取天气失败: 位置数据获取失败 (第$attempt次)"); +// if (attempt >= retryCount) return; // 重试到上限退出 +// await Future.delayed(Duration(seconds: 2)); // 延时再试 +// continue; +// } + +// // 设置语言 +// String? language = "zh_CN"; +// if (AppConstants().ent_type == APPPackageType.MHT.code) { +// if (mhLanguageController.selectLanguage != null) { +// language = mhLanguageController.selectLanguage.value!.language_code; +// } +// } else { +// if (languageController.selectLanguage != null) { +// language = languageController.selectLanguage.value!.language_code; +// } +// } +// weatherFactory.language = (language == "zh_CN") +// ? Language.CHINESE_SIMPLIFIED +// : Language.ENGLISH; + +// // 拼接天气请求地址 +// String location = "${model.longitude},${model.latitude}"; +// String serviceAddress = ServiceConstant.service_address; +// String serviceName = ServiceConstant.server_service; +// String serviceApi = ServiceConstant.weather_url; +// String queryUrl = +// "$serviceAddress$serviceName$serviceApi?location=$location"; +// await requestWithLog( +// logTitle: "获取天气信息 (第$attempt次)", +// method: MyHttpMethod.get, +// queryUrl: queryUrl, +// onSuccess: (res) { +// try { +// print(res.data); +// model.weather_info = res.data["info"]; +// model.current_temperature = int.parse(res.data["temp"]); +// if (res.data['icon'] != null) { +// model.weatherIconurl = "${res.data['icon']}"; +// } +// model.cityName = res.data["city"]; +// success = true; +// } catch (e) { +// EasyDartModule.logger.error("天气数据解析失败: $e"); +// } +// }, +// onFailure: (res) { +// EasyDartModule.logger.error("获取天气接口失败: ${res.data}"); +// }, +// ); + +// if (success) { +// updateAll(); // 更新 UI +// return; // ✅ 成功了直接返回 +// } +// } catch (e) { +// EasyDartModule.logger.error("获取天气异常 (第$attempt次): $e"); +// } + +// // 如果还没成功,延迟后重试 +// if (attempt < retryCount) { +// await Future.delayed(Duration(seconds: 2)); +// } +// } + +// EasyDartModule.logger.error("获取天气失败: 已重试 $retryCount 次仍然失败"); +// } + +// // 获取 5 天天气预报 +// Future> getWeatherForecast( +// double latitude, double longitude) async { +// try { +// return await weatherFactory.fiveDayForecastByLocation( +// latitude, longitude); +// } catch (e) { +// print('获取天气预报失败: $e'); +// rethrow; +// } +// } +// } + import 'dart:async'; import 'package:EasyDartModule/EasyDartModule.dart'; @@ -53,6 +445,10 @@ class WeatherModelController extends GetControllerEx { Timer? _weatherTimer; Timer? _locationTimer; + // 添加状态变量来跟踪权限请求状态 + bool _isRequestingPermission = false; + bool _hasShownPermissionDialog = false; + late WeatherFactory weatherFactory; @override @@ -112,13 +508,13 @@ class WeatherModelController extends GetControllerEx { ); if (placemarks.isNotEmpty) { - model.cityName = placemarks[0].locality ?? "未知数据".tr; + // model.cityName = placemarks[0].locality ?? "未知数据".tr; model.latitude = position.latitude; model.longitude = position.longitude; } // 调用获取天气方法 - getCurrentWeather(); + // getCurrentWeather(); } catch (e) { print(e); EasyDartModule.logger.error("获取位置失败: $e"); @@ -126,32 +522,65 @@ class WeatherModelController extends GetControllerEx { } // 获取当前位置 - Future determinePosition() async { + Future determinePosition({int retryCount = 1}) async { bool serviceEnabled; LocationPermission permission; + int attempt = 0; + bool dialogShown = false; + Completer? dialogCompleter; + // 检查定位服务是否启用 serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { return Future.error('位置服务未启用'); } - try { - showPermissionInfoDialog( - Get.context!, CommonVariables().locationpermissionInfo); - } catch (e) { - ef.log("$e"); - } - try { - // 2️⃣ 检查权限(系统弹窗)—— 此时你的提示框仍然显示 - permission = await Geolocator.checkPermission(); - if (permission == LocationPermission.denied) { - permission = await Geolocator.requestPermission(); + // 检查当前权限状态 + permission = await Geolocator.checkPermission(); + + // 如果权限已经被授予,直接获取位置 + if (permission == LocationPermission.always || + permission == LocationPermission.whileInUse) { + return await _getPositionWithRetry(retryCount); + } + + // 如果权限被永久拒绝,直接返回错误 + if (permission == LocationPermission.deniedForever) { + return Future.error('位置权限被永久拒绝'); + } + + // 如果正在请求权限,避免重复请求 + if (_isRequestingPermission) { + return Future.error('权限请求正在进行中'); + } + + // 权限被拒绝或未请求过,需要请求权限 + try { + _isRequestingPermission = true; + + if (!_hasShownPermissionDialog) { + showPermissionInfoDialog( + Get.context!, + CommonVariables().locationpermissionInfo, + ); + _hasShownPermissionDialog = true; } + + // 等待系统弹窗结果(期间自定义弹窗仍显示在屏幕上) + permission = await Geolocator.requestPermission(); + + // 系统弹窗关闭后继续执行,关闭自定义弹窗 + if (_hasShownPermissionDialog) { + Get.back(); + } + } catch (e) { + ef.log("申请位置权限出错: $e"); + rethrow; } finally { - // 3️⃣ 无论如何都关闭你的提示弹窗 - Navigator.of(Get.context!, rootNavigator: true).pop(); + _isRequestingPermission = false; } + // 检查请求后的权限状态 if (permission == LocationPermission.denied) { return Future.error('位置权限被拒绝'); } @@ -160,89 +589,117 @@ class WeatherModelController extends GetControllerEx { return Future.error('位置权限被永久拒绝'); } - return await Geolocator.getCurrentPosition( - locationSettings: const LocationSettings( - accuracy: LocationAccuracy.low, // 使用高精度定位,但不依赖 Google Play - distanceFilter: 1000, // 设置最小距离过滤 - timeLimit: Duration(seconds: 10), // 设置获取位置的最大等待时间 - ), - ); + // 权限已授予,获取位置 + return await _getPositionWithRetry(retryCount); + } + + // 提取获取位置的重复代码到单独的方法 + Future _getPositionWithRetry(int retryCount) async { + int attempt = 0; + + while (attempt < retryCount) { + attempt++; + try { + // 设置定位精度 + LocationAccuracy accuracy = attempt == 1 + ? LocationAccuracy.medium // 初次尝试用中等精度 + : LocationAccuracy.best; // 如果第一次失败,尝试高精度定位 + + return await Geolocator.getCurrentPosition( + forceAndroidLocationManager: true, + locationSettings: LocationSettings( + accuracy: accuracy, + distanceFilter: 1000, + timeLimit: Duration(seconds: 10), + ), + ); + } catch (e) { + if (attempt >= retryCount) { + return Future.error('获取位置失败: $e'); + } + await Future.delayed(Duration(seconds: 2)); // 重试前等待 + } + } + + return Future.error('获取位置失败,已重试 $retryCount 次'); } // 获取天气信息 - Future getCurrentWeather() async { - if (model.latitude == null || model.longitude == null) { - EasyDartModule.logger.error("获取天气失败:位置数据获取失败"); - return; // 如果位置数据没有获取到,则不更新天气 - } - // String? language = "zh_CN"; - // if (languageController.selectLanguage != null) { - // language = languageController.selectLanguage.value!.language_code; - // } - List placemarks = []; - // placemarks = await placemarkFromCoordinates(model.latitude!, model.longitude!, - // localeIdentifier: language); - - if (placemarks.isNotEmpty) { - model.cityName = placemarks[0].locality ?? "未知数据".tr; - } - - try { - weatherFactory.language = Language.CHINESE_SIMPLIFIED; - String? language = "zh_CN"; - if (AppConstants().ent_type == APPPackageType.MHT.code) { - if (mhLanguageController.selectLanguage != null) { - language = mhLanguageController.selectLanguage.value!.language_code; + Future getCurrentWeather({int retryCount = 1}) async { + int attempt = 0; + bool success = false; + while (attempt < retryCount && success == false) { + attempt++; + try { + // 先尝试获取定位 + await getCurrentLocation(); + if (model.latitude == null || model.longitude == null) { + EasyDartModule.logger.error("获取天气失败: 位置数据获取失败 (第$attempt次)"); + if (attempt >= retryCount) return; // 重试到上限退出 + await Future.delayed(Duration(seconds: 2)); // 延时再试 + continue; } - } else { - if (languageController.selectLanguage != null) { - language = languageController.selectLanguage.value!.language_code; + + // 设置语言 + String? language = "zh_CN"; + if (AppConstants().ent_type == APPPackageType.MHT.code) { + if (mhLanguageController.selectLanguage != null) { + language = mhLanguageController.selectLanguage.value!.language_code; + } + } else { + if (languageController.selectLanguage != null) { + language = languageController.selectLanguage.value!.language_code; + } } - } - if (language == "zh_CN") { - weatherFactory.language = Language.CHINESE_SIMPLIFIED; - } else { - weatherFactory.language = Language.ENGLISH; - } - // Weather weather = await weatherFactory.currentWeatherByLocation( - // model.latitude!, model.longitude!); - String location = "${model.longitude},${model.latitude}"; - String serviceAddress = ServiceConstant.service_address; - String serviceName = ServiceConstant.server_service; - String serviceApi = ServiceConstant.weather_url; - String queryUrl = - "${serviceAddress}${serviceName}${serviceApi}?location=$location"; - await requestWithLog( - logTitle: "获取天气信息", + weatherFactory.language = (language == "zh_CN") + ? Language.CHINESE_SIMPLIFIED + : Language.ENGLISH; + + // 拼接天气请求地址 + String location = "${model.longitude},${model.latitude}"; + String serviceAddress = ServiceConstant.service_address; + String serviceName = ServiceConstant.server_service; + String serviceApi = ServiceConstant.weather_url; + String queryUrl = + "$serviceAddress$serviceName$serviceApi?location=$location"; + await requestWithLog( + logTitle: "获取天气信息 (第$attempt次)", method: MyHttpMethod.get, queryUrl: queryUrl, onSuccess: (res) { - print(res.data); - model.weather_info = res.data["info"]; - model.current_temperature = int.parse(res.data["temp"]); - if (res.data['icon'] != null) { - model.weatherIconurl = "${res.data['icon']}"; + try { + print(res.data); + model.weather_info = res.data["info"]; + model.current_temperature = int.parse(res.data["temp"]); + if (res.data['icon'] != null) { + model.weatherIconurl = "${res.data['icon']}"; + } + model.cityName = res.data["city"]; + success = true; + } catch (e) { + EasyDartModule.logger.error("天气数据解析失败: $e"); } - model.cityName = res.data["city"]; }, onFailure: (res) { - print(res.data); - }); - // 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'); + EasyDartModule.logger.error("获取天气接口失败: ${res.data}"); + }, + ); + + if (success) { + updateAll(); // 更新 UI + return; // ✅ 成功了直接返回 + } + } catch (e) { + EasyDartModule.logger.error("获取天气异常 (第$attempt次): $e"); + } + + // 如果还没成功,延迟后重试 + if (attempt < retryCount) { + await Future.delayed(Duration(seconds: 2)); + } } + + EasyDartModule.logger.error("获取天气失败: 已重试 $retryCount 次仍然失败"); } // 获取 5 天天气预报 @@ -256,4 +713,10 @@ class WeatherModelController extends GetControllerEx { rethrow; } } + + // 重置权限状态(可选,用于测试或特定场景) + void resetPermissionState() { + _isRequestingPermission = false; + _hasShownPermissionDialog = false; + } } diff --git a/lib/pages/common/selectDialog.dart b/lib/pages/common/selectDialog.dart index 23aa1c7..b3cdeaa 100644 --- a/lib/pages/common/selectDialog.dart +++ b/lib/pages/common/selectDialog.dart @@ -91,7 +91,8 @@ Widget getOnePickers( if (isMonthName && isEn && arr[index] is int) { displayText = DateFormat.MMMM('en').format(DateTime(0, arr[index])); } else { - displayText = isEn ? "${arr[index]}" : "${arr[index]}$unit"; // 中文附带单位 + // displayText = isEn ? "${arr[index]}" : "${arr[index]}$unit"; // 中文附带单位 + displayText = "${arr[index]}$unit"; // 中文附带单位 } return Center( @@ -100,7 +101,7 @@ Widget getOnePickers( style: TextStyle( fontFamily: 'Readex Pro', color: isSelected - ? const Color(0xFF011D33) + ? themeController.currentColor.sc3 : const Color(0xFF9AA0B3), fontSize: 30.rpx, fontWeight: FontWeight.normal, diff --git a/lib/pages/device/instant_body_page.dart b/lib/pages/device/instant_body_page.dart index 55074fa..b43f433 100644 --- a/lib/pages/device/instant_body_page.dart +++ b/lib/pages/device/instant_body_page.dart @@ -259,8 +259,7 @@ class _InstantBodyPageState extends State 30.rpx, 0.rpx, 30.rpx, 100.rpx), child: ClickableContainer( backgroundColor: themeController.currentColor.sc5, - highlightColor: themeController - .currentColor.sc5, // 或你希望的点击水波纹颜色 + highlightColor: Colors.transparent, // 点击涟漪颜色 borderRadius: AppConstants() .normal_container_radius, // 如果你想加圆角可以设置 eg. 12.rpx padding: EdgeInsets.zero, @@ -547,7 +546,7 @@ class _InstantBodyPageState extends State )), ClickableContainer( backgroundColor: Colors.transparent, // 可自定义背景色 - highlightColor: Colors.white, // 点击涟漪颜色 + highlightColor: Colors.transparent, // 点击涟漪颜色 borderRadius: 16.rpx, // 圆角大小,可按需调整 padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 0.rpx), diff --git a/lib/pages/device_bind/componnet/DeviceShareInfoWidget.dart b/lib/pages/device_bind/componnet/DeviceShareInfoWidget.dart index da70bba..a0dd6cc 100644 --- a/lib/pages/device_bind/componnet/DeviceShareInfoWidget.dart +++ b/lib/pages/device_bind/componnet/DeviceShareInfoWidget.dart @@ -149,6 +149,9 @@ class _DeviceShareInfoWidgetState extends State { item['show'] == false) { return Container(); } + if (item['k'] == null) { + return Container(); + } return Container( constraints: BoxConstraints( minHeight: 62.rpx, diff --git a/lib/pages/device_bind/wifi_page.dart b/lib/pages/device_bind/wifi_page.dart index 3895a68..15cb3d7 100644 --- a/lib/pages/device_bind/wifi_page.dart +++ b/lib/pages/device_bind/wifi_page.dart @@ -177,7 +177,7 @@ class _WifiPageState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - themeController.currentColor.sc1, + themeController.currentColor.sc3, ), ), ); @@ -192,7 +192,7 @@ class _WifiPageState extends State { child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( - themeController.currentColor.sc1, + themeController.currentColor.sc3, ), ), ); @@ -697,7 +697,7 @@ class _WifiPageState extends State { Color>( themeController .currentColor - .sc1, + .sc3, ), ), ) diff --git a/lib/pages/login/other_login.dart b/lib/pages/login/other_login.dart index d24b640..b9ed56e 100644 --- a/lib/pages/login/other_login.dart +++ b/lib/pages/login/other_login.dart @@ -910,9 +910,7 @@ class _OtherLoginPageState extends State { padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 36.rpx), child: Text( - AppConstants().ent_type == 1 - ? '登录页.欢迎使用太和e护'.tr - : "欢迎使用欢睡科技", + "登录页.其他登录方式".tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, diff --git a/lib/pages/main_bottom/home_page.dart b/lib/pages/main_bottom/home_page.dart index 5b23866..29f0168 100644 --- a/lib/pages/main_bottom/home_page.dart +++ b/lib/pages/main_bottom/home_page.dart @@ -219,6 +219,7 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { + weatherModelController.getCurrentWeather(); return LayoutBuilder( builder: (context, bodySize) => GestureDetector( onTap: () { diff --git a/lib/pages/mh_page/LanguagePage.dart b/lib/pages/mh_page/LanguagePage.dart index d13b8d9..21768fd 100644 --- a/lib/pages/mh_page/LanguagePage.dart +++ b/lib/pages/mh_page/LanguagePage.dart @@ -8,6 +8,7 @@ import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/CustomCard.dart'; import 'package:vbvs_app/controller/mh_controller/mh_language_controller.dart'; +import 'package:vbvs_app/controller/weather/weather_controller.dart'; import 'package:vbvs_app/enum/APPPackageType.dart'; import 'package:vbvs_app/language/AppLanguage.dart'; import 'package:vbvs_app/pages/device_bind/componnet/FancyCircleCheckbox.dart'; @@ -147,6 +148,11 @@ class _LanguagePageState extends State { try { // ef.kv.set("language", // language.language_code); + WeatherModelController + weatherModelController = + Get.find(); + weatherModelController + .getCurrentWeather(); await ef.kvdb.write( "mht/language", language.language_code); diff --git a/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart b/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart index 7dbf8f9..e9d0d62 100644 --- a/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart +++ b/lib/pages/mh_page/homepage/component/HomeDeviceStausWidget.dart @@ -61,7 +61,7 @@ class _HomeDeviceStausWidgetState extends State { ), ), Text( - '${(widget.deviceStatus['name'] ?? '').isEmpty ? '未命名'.tr : widget.deviceStatus['name']}', + '${(widget.deviceStatus['name'] ?? '').isEmpty ? (widget.deviceStatus['device_type'] == 2 ? '智能电动床'.tr : widget.deviceStatus['device_type'] == 3 ? '律动智能床垫'.tr : '未命名'.tr) : widget.deviceStatus['name']}', style: TextStyle( color: Colors.white, fontSize: 26.rpx, diff --git a/lib/pages/mh_page/homepage/new_Home_page.dart b/lib/pages/mh_page/homepage/new_Home_page.dart index 16f0fcc..20997ce 100644 --- a/lib/pages/mh_page/homepage/new_Home_page.dart +++ b/lib/pages/mh_page/homepage/new_Home_page.dart @@ -127,6 +127,7 @@ class _NewHomePageState extends State { @override Widget build(BuildContext context) { + weatherModelController.getCurrentWeather(); deviceController.getDeviceList(group: 'room').then((apiResponse) { if (apiResponse.code != HttpStatusCodes.ok) { // TopSlideNotification.show( diff --git a/lib/pages/person/person_page.dart b/lib/pages/person/person_page.dart index b927099..dfcd94f 100644 --- a/lib/pages/person/person_page.dart +++ b/lib/pages/person/person_page.dart @@ -398,7 +398,7 @@ class _EPageState extends State { child: Center( child: Text( personController.dateTime != null - ? DateFormat("yyyy年MM月dd日").format( + ? DateFormat("yyyy/MM/dd").format( personController.dateTime!) : '人员资料.生日输入提示'.tr, textAlign: TextAlign.right, @@ -459,7 +459,8 @@ class _EPageState extends State { child: Center( child: Text( personController.height.value != "" - ? personController.height.value + ? personController.height.value + + "cm".tr : '身高输入提示'.tr, textAlign: TextAlign.right, style: TextStyle( @@ -513,7 +514,8 @@ class _EPageState extends State { child: Center( child: Text( personController.weight.value != "" - ? personController.weight.value + ? personController.weight.value + + "kg".tr : '人员资料.体重输入提示'.tr, textAlign: TextAlign.right, style: TextStyle( diff --git a/lib/pages/person/select_time.dart b/lib/pages/person/select_time.dart index 5892855..41c14ec 100644 --- a/lib/pages/person/select_time.dart +++ b/lib/pages/person/select_time.dart @@ -8,39 +8,339 @@ import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/pages/common/selectDialog.dart'; +// Future showDateSelectionDialog(BuildContext context, +// {required DateTime checkDate, Function? checkChange, String title = "生日"}) { +// ThemeController themeController = Get.find(); +// List years = [], months = [], days = []; +// var days_select = [].obs; +// int day_len = 31; +// int year = DateTime.now().year; +// for (var i = 0; i < 100; i++) { +// years.insert(0, year - i); +// } +// for (var i = 1; i < 13; i++) { +// months.add(i); +// } +// for (var i = 1; i < 32; i++) { +// days.add(i); +// } +// int yearIndex = years.lastIndexOf(checkDate.year); +// int monthIndex = months.lastIndexOf(checkDate.month); +// day_len = DateTime.fromMillisecondsSinceEpoch( +// DateTime(years[yearIndex], months[monthIndex] + 1) +// .millisecondsSinceEpoch - +// 1000) +// .day; +// days_select.value = days.sublist(0, day_len); +// int dayIndex = days.lastIndexOf(checkDate.day); +// return showDialog( +// context: context, +// barrierDismissible: true, // 点击对话框外部可关闭 +// builder: (BuildContext context) { +// return Stack( +// children: [ +// Positioned( +// bottom: 0, // 控制弹窗距离顶部的位置 +// left: 0, +// right: 0, +// child: Material( +// color: Colors.transparent, +// child: Dialog( +// backgroundColor: themeController.currentColor.sc17, +// insetPadding: EdgeInsets.zero, +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(0), +// ), +// child: Container( +// width: double.infinity, +// decoration: BoxDecoration( +// borderRadius: BorderRadius.only( +// topLeft: Radius.circular( +// AppConstants().normal_container_radius), +// topRight: Radius.circular( +// AppConstants().normal_container_radius), +// bottomLeft: Radius.circular(0.rpx), +// bottomRight: Radius.circular(0.rpx), +// ), +// ), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// Container( +// color: themeController.currentColor.sc5, +// alignment: Alignment.centerLeft, +// height: 80.rpx, +// child: Padding( +// padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx), +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// InkWell( +// child: Text( +// "日期.取消".tr, +// style: TextStyle( +// fontFamily: 'Readex Pro', +// color: themeController.currentColor.sc3, +// letterSpacing: 0, +// fontSize: +// AppConstants().normal_text_fontSize), +// ), +// onTap: () { +// Get.back(); +// }, +// ), +// Text( +// "$title", +// style: TextStyle( +// fontFamily: 'Readex Pro', +// color: themeController.currentColor.sc3, +// letterSpacing: 0, +// fontSize: +// AppConstants().title_text_fontSize), +// ), +// // closeIconWhite, +// InkWell( +// child: Text( +// "日期.确定".tr, +// style: TextStyle( +// fontFamily: 'Readex Pro', +// color: themeController.currentColor.sc2, +// letterSpacing: 0, +// fontSize: +// AppConstants().normal_text_fontSize), +// ), +// onTap: () { +// checkChange?.call(DateTime(years[yearIndex], +// months[monthIndex], days[dayIndex])); +// Get.back(); +// }, +// ) +// ], +// ), +// ), +// ), +// // Container( +// // height: 240.rpx, +// // margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx), +// // padding: EdgeInsets.symmetric(horizontal: 30.rpx), +// // child: Row( +// // mainAxisAlignment: MainAxisAlignment.center, // ✅ 整体居中 +// // crossAxisAlignment: CrossAxisAlignment.center, +// // children: [ +// // Row( +// // children: [ +// // SizedBox( +// // width: 120.rpx, +// // child: getOnePicker(context, years, yearIndex, +// // (d) { +// // yearIndex = d; +// // dayIndex = 0; +// // day_len = +// // DateTime.fromMillisecondsSinceEpoch( +// // DateTime( +// // years[yearIndex], +// // months[monthIndex] + +// // 1) +// // .millisecondsSinceEpoch - +// // 1000) +// // .day; +// // days_select.value = +// // days.sublist(0, day_len); +// // }, "".tr), +// // ), +// // ], +// // ), + +// // SizedBox(width: 100.rpx), + +// // // 月 +// // Row( +// // children: [ +// // SizedBox( +// // width: 80.rpx, +// // child: getOnePicker( +// // context, months, monthIndex, (d) { +// // monthIndex = d; +// // dayIndex = 0; +// // day_len = +// // DateTime.fromMillisecondsSinceEpoch( +// // DateTime( +// // years[yearIndex], +// // months[monthIndex] + +// // 1) +// // .millisecondsSinceEpoch - +// // 1000) +// // .day; +// // days_select.value = +// // days.sublist(0, day_len); +// // }, "".tr), +// // ), +// // ], +// // ), + +// // SizedBox(width: 100.rpx), + +// // Row( +// // children: [ +// // SizedBox( +// // width: 80.rpx, +// // child: Obx(() { +// // return getOnePicker( +// // context, days_select, dayIndex, (d) { +// // dayIndex = d; +// // }, "".tr); +// // }), +// // ), +// // ], +// // ), +// // ], +// // ), +// // ) +// //----- +// Container( +// height: 240.rpx, +// margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx), +// padding: EdgeInsets.symmetric(horizontal: 30.rpx), +// child: Stack( +// children: [ +// // ✅ 选中行背景色 +// Positioned.fill( +// child: IgnorePointer( +// child: Center( +// child: Container( +// height: 90.rpx, // 对齐选中行高度 +// margin: EdgeInsets.symmetric( +// horizontal: 10.rpx), +// decoration: BoxDecoration( +// color: themeController.currentColor.sc2, +// borderRadius: +// BorderRadius.circular(16.rpx), +// ), +// ), +// ), +// ), +// ), + +// // ✅ 三列 Picker +// Row( +// mainAxisAlignment: +// MainAxisAlignment.center, // 整体居中 +// crossAxisAlignment: CrossAxisAlignment.center, +// children: [ +// // 年 +// SizedBox( +// width: 120.rpx, +// child: getOnePicker(context, years, yearIndex, +// (d) { +// yearIndex = d; +// dayIndex = 0; +// day_len = +// DateTime.fromMillisecondsSinceEpoch( +// DateTime( +// years[yearIndex], +// months[monthIndex] + +// 1) +// .millisecondsSinceEpoch - +// 1000) +// .day; +// days_select.value = +// days.sublist(0, day_len); +// }, "".tr), +// ), + +// SizedBox(width: 100.rpx), + +// // 月 +// SizedBox( +// width: 80.rpx, +// child: getOnePicker( +// context, months, monthIndex, (d) { +// monthIndex = d; +// dayIndex = 0; +// day_len = +// DateTime.fromMillisecondsSinceEpoch( +// DateTime( +// years[yearIndex], +// months[monthIndex] + +// 1) +// .millisecondsSinceEpoch - +// 1000) +// .day; +// days_select.value = +// days.sublist(0, day_len); +// }, "".tr), +// ), + +// SizedBox(width: 100.rpx), + +// // 日 +// SizedBox( +// width: 80.rpx, +// child: Obx(() { +// return getOnePicker( +// context, days_select, dayIndex, (d) { +// dayIndex = d; +// }, "".tr); +// }), +// ), +// ], +// ), +// ], +// ), +// ), + +// ], +// ), +// ), +// ), +// ), +// ), +// ], +// ); +// }, +// ); +// } + Future showDateSelectionDialog(BuildContext context, - {required DateTime checkDate, Function? checkChange, String title = "生日"}) { + {required DateTime checkDate, + Function? checkChange, + String title = "选择生日"}) { ThemeController themeController = Get.find(); - List years = [], months = [], days = []; - var days_select = [].obs; - int day_len = 31; - int year = DateTime.now().year; - for (var i = 0; i < 100; i++) { - years.insert(0, year - i); + final bool isEn = Get.locale?.languageCode.startsWith('en') ?? false; + Color checkColor = stringToColor("#D3B684"); + + final List years = List.generate(100, (i) => DateTime.now().year - i) + ..sort(); + final List months = List.generate(12, (i) => i + 1); + final List days = List.generate(31, (i) => i + 1); + + final RxList daysSelect = [].obs; + + final RxInt yearIndex = years.indexOf(checkDate.year).obs; + final RxInt monthIndex = months.indexOf(checkDate.month).obs; + final RxInt dayIndex = days.indexOf(checkDate.day).obs; + + void updateDays() { + final int daysInMonth = + DateTime(years[yearIndex.value], months[monthIndex.value] + 1, 0).day; + daysSelect.value = days.sublist(0, daysInMonth); + if (dayIndex.value >= daysInMonth) { + dayIndex.value = daysInMonth - 1; + } } - for (var i = 1; i < 13; i++) { - months.add(i); - } - for (var i = 1; i < 32; i++) { - days.add(i); - } - int yearIndex = years.lastIndexOf(checkDate.year); - int monthIndex = months.lastIndexOf(checkDate.month); - day_len = DateTime.fromMillisecondsSinceEpoch( - DateTime(years[yearIndex], months[monthIndex] + 1) - .millisecondsSinceEpoch - - 1000) - .day; - days_select.value = days.sublist(0, day_len); - int dayIndex = days.lastIndexOf(checkDate.day); + + updateDays(); + return showDialog( context: context, - barrierDismissible: true, // 点击对话框外部可关闭 + barrierDismissible: true, builder: (BuildContext context) { return Stack( children: [ Positioned( - bottom: 0, // 控制弹窗距离顶部的位置 + bottom: 0, left: 0, right: 0, child: Material( @@ -53,151 +353,145 @@ Future showDateSelectionDialog(BuildContext context, ), child: Container( width: double.infinity, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular( - AppConstants().normal_container_radius), - topRight: Radius.circular( - AppConstants().normal_container_radius), - bottomLeft: Radius.circular(0.rpx), - bottomRight: Radius.circular(0.rpx), - ), - ), + padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Container( - color: themeController.currentColor.sc5, - alignment: Alignment.centerLeft, - height: 80.rpx, - child: Padding( - padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - InkWell( - child: Text( - "日期.取消".tr, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.zero, + onTap: () => Navigator.of(context).pop(), + child: Container( + width: 110.rpx, + height: 60.rpx, + alignment: Alignment.center, + child: Text("取消".tr, style: TextStyle( - fontFamily: 'Readex Pro', - color: themeController.currentColor.sc3, - letterSpacing: 0, - fontSize: - AppConstants().normal_text_fontSize), - ), - onTap: () { - Get.back(); - }, - ), - Text( - "$title", - style: TextStyle( - fontFamily: 'Readex Pro', - color: themeController.currentColor.sc3, - letterSpacing: 0, - fontSize: - AppConstants().title_text_fontSize), - ), - // closeIconWhite, - InkWell( - child: Text( - "日期.确定".tr, - style: TextStyle( - fontFamily: 'Readex Pro', - color: themeController.currentColor.sc2, - letterSpacing: 0, - fontSize: - AppConstants().normal_text_fontSize), - ), - onTap: () { - checkChange?.call(DateTime(years[yearIndex], - months[monthIndex], days[dayIndex])); - Get.back(); - }, - ) - ], + fontSize: 30.rpx, color: Colors.white)), + ), ), - ), + Text( + title, + style: TextStyle( + fontFamily: 'Readex Pro', + color: themeController.currentColor.sc3, + fontSize: 30.rpx, + ), + ), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.zero, + onTap: () { + final selectedDate = DateTime( + years[yearIndex.value], + months[monthIndex.value], + daysSelect[dayIndex.value], + ); + checkChange?.call(selectedDate); + Get.back(); + }, + child: Container( + width: 110.rpx, + height: 60.rpx, + alignment: Alignment.center, + child: Text("确定".tr, + style: TextStyle( + fontSize: 30.rpx, + color: themeController.currentColor.sc2, + )), + ), + ), + ], ), - Container( - height: 240.rpx, - margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx), - padding: EdgeInsets.symmetric(horizontal: 30.rpx), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, // ✅ 整体居中 - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - children: [ - SizedBox( - width: 120.rpx, - child: getOnePicker(context, years, yearIndex, - (d) { - yearIndex = d; - dayIndex = 0; - day_len = - DateTime.fromMillisecondsSinceEpoch( - DateTime( - years[yearIndex], - months[monthIndex] + - 1) - .millisecondsSinceEpoch - - 1000) - .day; - days_select.value = - days.sublist(0, day_len); - }, "年".tr), + SizedBox(height: 20.rpx), + Stack( + children: [ + Positioned.fill( + child: IgnorePointer( + child: Center( + child: Container( + height: 90.rpx, + margin: + EdgeInsets.symmetric(horizontal: 70.rpx), + decoration: BoxDecoration( + color: themeController.currentColor.sc2, + borderRadius: BorderRadius.circular(16.rpx), + ), ), - ], + ), ), - - SizedBox(width: 100.rpx), - - // 月 - Row( - children: [ - SizedBox( - width: 80.rpx, - child: getOnePicker( - context, months, monthIndex, (d) { - monthIndex = d; - dayIndex = 0; - day_len = - DateTime.fromMillisecondsSinceEpoch( - DateTime( - years[yearIndex], - months[monthIndex] + - 1) - .millisecondsSinceEpoch - - 1000) - .day; - days_select.value = - days.sublist(0, day_len); - }, "月".tr), - ), - ], + ), + SizedBox( + height: 240.rpx, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 95.rpx), + child: Row( + children: isEn + ? [ + Expanded( + child: getOnePickers( + context, + months, + monthIndex, + isMonthName: true, + onChanged: (_) => updateDays(), + ), + ), + Expanded( + child: getOnePickers( + context, + daysSelect, + dayIndex, + ), + ), + Expanded( + child: getOnePickers( + context, + years, + yearIndex, + onChanged: (_) => updateDays(), + ), + ), + ] + : [ + Expanded( + child: getOnePickers( + context, + years, + yearIndex, + unit: "年", + onChanged: (_) => updateDays(), + ), + ), + Expanded( + child: getOnePickers( + context, + months, + monthIndex, + unit: "月", + onChanged: (_) => updateDays(), + ), + ), + Expanded( + child: getOnePickers( + context, + daysSelect, + dayIndex, + unit: "日", + ), + ), + ], + ), ), - - SizedBox(width: 100.rpx), - - Row( - children: [ - SizedBox( - width: 80.rpx, - child: Obx(() { - return getOnePicker( - context, days_select, dayIndex, (d) { - dayIndex = d; - }, "日".tr); - }), - ), - ], - ), - ], - ), - ) + ), + ], + ), ], ), ), diff --git a/lib/pages/person/update_person_page.dart b/lib/pages/person/update_person_page.dart index c125155..4a4de15 100644 --- a/lib/pages/person/update_person_page.dart +++ b/lib/pages/person/update_person_page.dart @@ -426,7 +426,7 @@ class _UpdatePageState extends State { child: Center( child: Text( personController.dateTime != null - ? DateFormat("yyyy年MM月dd日").format( + ? DateFormat("yyyy/MM/dd").format( personController.dateTime!) : '人员资料.生日输入提示'.tr, textAlign: TextAlign.right, @@ -494,7 +494,8 @@ class _UpdatePageState extends State { child: Center( child: Text( personController.height.value != "" - ? personController.height.value + ? personController.height.value + + "cm".tr : '身高输入提示'.tr, textAlign: TextAlign.right, style: TextStyle( @@ -555,7 +556,8 @@ class _UpdatePageState extends State { child: Center( child: Text( personController.weight.value != "" - ? personController.weight.value + ? personController.weight.value + + "kg".tr : '人员资料.体重输入提示'.tr, textAlign: TextAlign.right, style: TextStyle( diff --git a/lib/pages/setting/Theme_setting.dart b/lib/pages/setting/Theme_setting.dart new file mode 100644 index 0000000..d51f089 --- /dev/null +++ b/lib/pages/setting/Theme_setting.dart @@ -0,0 +1,159 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.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/controller/theme_controller/ThemeController.dart'; +import 'package:vbvs_app/model/CustomThemeColor.dart'; +import 'package:vbvs_app/pages/device_bind/componnet/FancyCircleCheckbox.dart'; + +class ThemeSetting extends StatefulWidget { + const ThemeSetting({super.key}); + + @override + State createState() => _ThemeSettingState(); +} + +class _ThemeSettingState extends State { + ThemeController themeController = Get.find(); + + @override + Widget build(BuildContext context) { + // 主题选项 + final List> themes = [ + { + 'name': '浅色主题'.tr, + 'value': CustomThemeColor.light, + }, + { + 'name': '深色主题'.tr, + 'value': CustomThemeColor.dark, + }, + ]; + + return LayoutBuilder( + builder: (context, bodySize) => GestureDetector( + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/img/bgNoImg.png'), + fit: BoxFit.fill, + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: themeController.currentColor.sc17, + automaticallyImplyLeading: false, + iconTheme: IconThemeData( + color: themeController.currentColor.sc3, + ), + titleSpacing: 0, + title: Container( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + Text( + '选择主题'.tr, + style: TextStyle( + fontFamily: 'Readex Pro', + color: themeController.currentColor.sc3, + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + Positioned( + left: 0, + child: returnIconButtom, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + SizedBox(height: 25.rpx), + Container( + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFF242835), + borderRadius: BorderRadius.circular( + AppConstants().normal_container_radius), + ), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 20.rpx), + child: Column( + children: themes + .map((theme) { + bool isSelected = + themeController.currentColor == + theme['value']; + return ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: + themeController.currentColor.sc21, + padding: EdgeInsets.symmetric( + vertical: 10.rpx, horizontal: 16.rpx), + onTap: () async { + // 切换主题 + themeController + .changeTheme(theme['value']); + }, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + theme['name'], + style: TextStyle( + fontFamily: 'Inter', + color: themeController + .currentColor.sc3, + fontSize: AppConstants() + .title_text_fontSize, + ), + ), + FancyCircleCheckbox( + borderColor: + themeController.currentColor.sc3, + fillColor: + themeController.currentColor.sc2, + value: isSelected, + onChanged: (value) { + themeController + .changeTheme(theme['value']); + }, + ), + ], + ), + ); + }) + .toList() + .divide( + SizedBox(height: 30.rpx), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/setting/common_mesaage_setting.dart b/lib/pages/setting/common_mesaage_setting.dart index adf57f8..2b16c3c 100644 --- a/lib/pages/setting/common_mesaage_setting.dart +++ b/lib/pages/setting/common_mesaage_setting.dart @@ -266,8 +266,7 @@ class _CommonMessageSettingPageState extends State { child: Container( decoration: BoxDecoration( color: themeController.currentColor.sc5, - borderRadius: BorderRadius.circular( - AppConstants().normal_container_radius), + borderRadius: BorderRadius.circular(0), ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( @@ -632,7 +631,7 @@ class _CommonMessageSettingPageState extends State { Padding( padding: - EdgeInsetsDirectional.fromSTEB(0, 30.rpx, 0, 0), + EdgeInsetsDirectional.fromSTEB(0, 21.rpx, 0, 0), child: Container( width: double.infinity, constraints: BoxConstraints( @@ -760,7 +759,7 @@ class _CommonMessageSettingPageState extends State { ), Padding( padding: - EdgeInsetsDirectional.fromSTEB(0, 30.rpx, 0, 0), + EdgeInsetsDirectional.fromSTEB(0, 21.rpx, 0, 0), child: Container( width: double.infinity, constraints: BoxConstraints( diff --git a/lib/pages/sleep_report/new_sleep_report_page.dart b/lib/pages/sleep_report/new_sleep_report_page.dart index 89ea0eb..cca313c 100644 --- a/lib/pages/sleep_report/new_sleep_report_page.dart +++ b/lib/pages/sleep_report/new_sleep_report_page.dart @@ -13,6 +13,7 @@ import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; import 'package:vbvs_app/controller/date/CalendarController.dart'; import 'package:vbvs_app/controller/sleep/sleep_report_controller.dart'; +import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/language/AppLanguage.dart'; import 'package:vbvs_app/pages/common/selectDialog.dart'; import 'package:vbvs_app/pages/main_bottom/component/main_page_b_bottom_change.dart'; @@ -113,7 +114,7 @@ class _NewSleepReportPageState extends State { _initSleepReportData(); }); - double lineWidth = 115.rpx; + double lineWidth = 150.rpx; return LayoutBuilder( builder: (context, bodySize) => GestureDetector( onHorizontalDragEnd: _handleHorizontalDrag, // 添加水平滑动检测 @@ -228,7 +229,7 @@ class _NewSleepReportPageState extends State { children: [ Container( width: - 115.rpx, // 固定宽度为 160.rpx + 150.rpx, // 固定宽度为 160.rpx alignment: Alignment.center, // 文字居中 child: Text( @@ -267,7 +268,7 @@ class _NewSleepReportPageState extends State { mainAxisSize: MainAxisSize.max, children: [ Container( - width: 115 + width: 150 .rpx, // 固定宽度为 160.rpx alignment: Alignment .center, // 文字居中 @@ -309,7 +310,7 @@ class _NewSleepReportPageState extends State { mainAxisSize: MainAxisSize.max, children: [ Container( - width: 115 + width: 150 .rpx, // 固定宽度为 160.rpx alignment: Alignment .center, // 文字居中 @@ -352,8 +353,8 @@ class _NewSleepReportPageState extends State { : sleepReportController .model.type == 2 - ? 115.rpx - : 230.rpx, + ? 150.rpx + : 300.rpx, child: Container( width: lineWidth, height: 4.rpx, @@ -390,172 +391,79 @@ class _NewSleepReportPageState extends State { widget.data['backgroundColor'] != null ? widget.data['backgroundColor'] : themeController.currentColor.sc5, - highlightColor: themeController - .currentColor.sc5, // 或你希望的点击水波纹颜色 - borderRadius: AppConstants() - .normal_container_radius, // 如果你想加圆角可以设置 eg. 12.rpx + highlightColor: themeController.currentColor.sc5, + borderRadius: + AppConstants().normal_container_radius, padding: EdgeInsets.zero, onTap: () {}, - child: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Flexible( - flex: 2, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( + child: Padding( + padding: + EdgeInsets.symmetric(horizontal: 0.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 左侧信息列 (姓名、年龄) + Expanded( + flex: 2, + child: Padding( + padding: EdgeInsets.fromLTRB( + 16.rpx, 0, 0, 0), + child: Column( children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - '姓名'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - Text( - '年龄'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), + _buildBaselineRow( + label: '姓名'.tr, + value: (widget.data['person'] + ?['name'] + ?.toString() + .trim() + .isNotEmpty ?? + false) + ? widget + .data['person']!['name'] + .toString() + : '未知数据'.tr, + themeController: themeController, ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - (widget.data['person'] - ?['name'] - ?.toString() - .trim() - .isNotEmpty ?? - false) - ? widget.data['person']![ - 'name'] - .toString() - : '未知数据'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - ), - Text( + SizedBox(height: 34.rpx), + _buildBaselineRow( + label: '年龄'.tr, + value: '${MyUtils.getAgeByDate(MyUtils.formatBirthdayTime(widget.data['person']?['birthday'])) ?? '未知数据'.tr}', - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), + themeController: themeController, ), - ] - .divide(SizedBox(width: 33.rpx)) - .addToStart( - SizedBox(width: 37.rpx)), + ], ), - ] - .addToStart(SizedBox(height: 36.rpx)) - .addToEnd(SizedBox(height: 36.rpx)), + ), ), - ), - Flexible( - flex: 3, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( + + // 右侧信息列 (设备ID、体重) + Expanded( + flex: 3, + child: Padding( + padding: EdgeInsets.fromLTRB( + 16.rpx, 36.rpx, 0, 36.rpx), + child: Column( children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - '设备ID'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - Text( - '体重'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( + _buildBaselineRow( + label: '设备ID'.tr, + value: '${widget.data['code'] ?? widget.data['mac']}', - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - maxLines: 1, - overflow: - TextOverflow.ellipsis, - ), - Text( - '${widget.data['person']?['weight'] ?? '未知数据'.tr}kg', - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), + themeController: themeController, ), - ] - .divide(SizedBox(width: 33.rpx)) - .addToStart( - SizedBox(width: 37.rpx)), + SizedBox(height: 34.rpx), + _buildBaselineRow( + label: '体重'.tr, + value: + '${widget.data['person']?['weight'] ?? '未知数据'.tr}kg', + themeController: themeController, + ), + ], ), - ] - .addToStart(SizedBox(height: 36.rpx)) - .addToEnd(SizedBox(height: 36.rpx)), + ), ), - ), - ], + ], + ), ), ), ), @@ -652,8 +560,8 @@ class _NewSleepReportPageState extends State { : sleepReportController .model.type == 2 - ? 115.rpx - : 230.rpx, + ? 150.rpx + : 300.rpx, child: Container( width: lineWidth, height: 4.rpx, @@ -699,165 +607,222 @@ class _NewSleepReportPageState extends State { child: Row( mainAxisSize: MainAxisSize.max, children: [ - Flexible( + // Flexible( + // flex: 2, + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Row( + // children: [ + // Column( + // crossAxisAlignment: + // CrossAxisAlignment.end, + // children: [ + // Text( + // '姓名'.tr, + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc4, + // ), + // ), + // Text( + // '年龄'.tr, + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc4, + // ), + // ), + // ].divide( + // SizedBox(height: 34.rpx)), + // ), + // Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Text( + // (widget.data['person'] + // ?['name'] + // ?.toString() + // .trim() + // .isNotEmpty ?? + // false) + // ? widget + // .data['person']![ + // 'name'] + // .toString() + // : '未知数据'.tr, + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc3, + // ), + // ), + // Text( + // '${MyUtils.getAgeByDate(MyUtils.formatBirthdayTime(widget.data['person']?['birthday'])) ?? '未知数据'.tr}', + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc3, + // ), + // ), + // ].divide( + // SizedBox(height: 34.rpx)), + // ), + // ] + // .divide(SizedBox(width: 33.rpx)) + // .addToStart( + // SizedBox(width: 37.rpx)), + // ), + // ] + // .addToStart( + // SizedBox(height: 36.rpx)) + // .addToEnd(SizedBox(height: 36.rpx)), + // ), + // ), + // Flexible( + // flex: 3, + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Row( + // children: [ + // Column( + // crossAxisAlignment: + // CrossAxisAlignment.end, + // children: [ + // Text( + // '设备ID'.tr, + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc4, + // ), + // ), + // Text( + // '体重'.tr, + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc4, + // ), + // ), + // ].divide( + // SizedBox(height: 34.rpx)), + // ), + // Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // Text( + // // '${widget.data['code'] ?? '未知数据'.tr}', + // '${widget.data['code'] ?? widget.data['mac']}', + // // "D11250300003", + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc3, + // ), + // maxLines: 1, + // overflow: + // TextOverflow.ellipsis, + // ), + // Text( + // '${widget.data['person']?['weight'] ?? '未知数据'.tr}kg', + // style: TextStyle( + // fontFamily: 'Inter', + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // color: themeController + // .currentColor.sc3, + // ), + // ), + // ].divide( + // SizedBox(height: 34.rpx)), + // ), + // ] + // .divide(SizedBox(width: 33.rpx)) + // .addToStart( + // SizedBox(width: 37.rpx)), + // ), + // ] + // .addToStart( + // SizedBox(height: 36.rpx)) + // .addToEnd(SizedBox(height: 36.rpx)), + // ), + // ), + + Expanded( flex: 2, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - '姓名'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - Text( - '年龄'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - (widget.data['person'] - ?['name'] - ?.toString() - .trim() - .isNotEmpty ?? - false) - ? widget - .data['person']![ - 'name'] - .toString() - : '未知数据'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - ), - Text( - '${MyUtils.getAgeByDate(MyUtils.formatBirthdayTime(widget.data['person']?['birthday'])) ?? '未知数据'.tr}', - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), - ), - ] - .divide(SizedBox(width: 33.rpx)) - .addToStart( - SizedBox(width: 37.rpx)), - ), - ] - .addToStart( - SizedBox(height: 36.rpx)) - .addToEnd(SizedBox(height: 36.rpx)), + child: Padding( + padding: EdgeInsets.fromLTRB( + 16.rpx, 0, 0, 0), + child: Column( + children: [ + _buildBaselineRow( + label: '姓名'.tr, + value: (widget.data['person'] + ?['name'] + ?.toString() + .trim() + .isNotEmpty ?? + false) + ? widget + .data['person']!['name'] + .toString() + : '未知数据'.tr, + themeController: themeController, + ), + SizedBox(height: 34.rpx), + _buildBaselineRow( + label: '年龄'.tr, + value: + '${MyUtils.getAgeByDate(MyUtils.formatBirthdayTime(widget.data['person']?['birthday'])) ?? '未知数据'.tr}', + themeController: themeController, + ), + ], + ), ), ), - Flexible( + Expanded( flex: 3, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - '设备ID'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - Text( - '体重'.tr, - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc4, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - // '${widget.data['code'] ?? '未知数据'.tr}', - '${widget.data['code'] ?? widget.data['mac']}', - // "D11250300003", - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - maxLines: 1, - overflow: - TextOverflow.ellipsis, - ), - Text( - '${widget.data['person']?['weight'] ?? '未知数据'.tr}kg', - style: TextStyle( - fontFamily: 'Inter', - fontSize: 26.rpx, - letterSpacing: 0.0, - color: themeController - .currentColor.sc3, - ), - ), - ].divide( - SizedBox(height: 34.rpx)), - ), - ] - .divide(SizedBox(width: 33.rpx)) - .addToStart( - SizedBox(width: 37.rpx)), - ), - ] - .addToStart( - SizedBox(height: 36.rpx)) - .addToEnd(SizedBox(height: 36.rpx)), + child: Padding( + padding: EdgeInsets.fromLTRB( + 16.rpx, 36.rpx, 0, 36.rpx), + child: Column( + children: [ + _buildBaselineRow( + label: '设备ID'.tr, + value: + '${widget.data['code'] ?? widget.data['mac']}', + themeController: themeController, + ), + SizedBox(height: 34.rpx), + _buildBaselineRow( + label: '体重'.tr, + value: + '${widget.data['person']?['weight'] ?? '未知数据'.tr}kg', + themeController: themeController, + ), + ], + ), ), ), ], @@ -1382,7 +1347,7 @@ class _NewSleepReportPageState extends State { mainAxisSize: MainAxisSize.max, children: [ Container( - width: 115.rpx, + width: 150.rpx, alignment: Alignment.center, child: Text( title.tr, @@ -1478,4 +1443,42 @@ class _NewSleepReportPageState extends State { loadSleepReport(newType); } } + + Widget _buildBaselineRow({ + required String label, + required String value, + required ThemeController themeController, + }) { + return Row( + crossAxisAlignment: CrossAxisAlignment.baseline, + textBaseline: TextBaseline.alphabetic, + children: [ + // 描述(label) + SizedBox( + width: 100.rpx, + child: Text( + label, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 26.rpx, + color: themeController.currentColor.sc4, + ), + ), + ), + SizedBox(width: 16.rpx), + // 值(value) + Expanded( + child: Text( + value, + style: TextStyle( + fontSize: 26.rpx, + color: themeController.currentColor.sc3, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ); + } } diff --git a/lib/pages/user/setting_page.dart b/lib/pages/user/setting_page.dart index 3f7b7c8..af6388f 100644 --- a/lib/pages/user/setting_page.dart +++ b/lib/pages/user/setting_page.dart @@ -121,8 +121,9 @@ class _SettingPageState extends State { // padding: EdgeInsetsDirectional.fromSTEB( // 40.rpx, 0.rpx, 40.rpx, 0.rpx), // onTap: () { - // TopSlideNotification.show(context, - // text: "待开发功能".tr); + // // TopSlideNotification.show(context, + // // text: "待开发功能".tr); + // Get.toNamed("/themeSetting"); // }, // child: Container( // child: Padding( diff --git a/lib/routers/routers.dart b/lib/routers/routers.dart index 7098fb5..3d6ab78 100644 --- a/lib/routers/routers.dart +++ b/lib/routers/routers.dart @@ -41,6 +41,7 @@ import 'package:vbvs_app/pages/repair/apply_repair_page.dart'; import 'package:vbvs_app/pages/repair/apply_repair_success.dart'; import 'package:vbvs_app/pages/repair/repair_detail_page.dart'; import 'package:vbvs_app/pages/repair/repair_list_page.dart'; +import 'package:vbvs_app/pages/setting/Theme_setting.dart'; import 'package:vbvs_app/pages/setting/common_mesaage_setting.dart'; import 'package:vbvs_app/pages/setting/language_setting.dart'; import 'package:vbvs_app/pages/sleep_report/new_sleep_report_page.dart'; @@ -90,6 +91,7 @@ var routes = { CalibrationPersonPage(type: arguments), "/applyRepairPage": (contxt) => ApplyRepairPage(), "/languageSetting": (contxt) => LanguageSetting(), + "/themeSetting": (contxt) => ThemeSetting(), "/helpPage": (contxt, {arguments}) => HelpPage( url: arguments,), "/followPage": (contxt) => FollowPage(), "/repairListPage": (contxt) => RepairListPage(),