1.修复睡眠日报中睡眠规律性数据显示错误

2.更新时区设置
This commit is contained in:
wyf
2026-01-07 15:19:16 +08:00
parent 36f19a71eb
commit 575f91e8dd
42 changed files with 4236 additions and 1653 deletions

View File

@@ -624,6 +624,9 @@
"手机号登录": "Phone Login", "手机号登录": "Phone Login",
"邮箱登录": "Email Login", "邮箱登录": "Email Login",
"输入邮箱": "Enter Email", "输入邮箱": "Enter Email",
"隐私协议加载失败": "Privacy Agreement Failed to Load", "隐私协议加载失败": "Privacy Agreement Failed to Load",
"请检查网络连接后重试": "Please check the network connection and try again" "请检查网络连接后重试": "Please check the network connection and try again",
"开始": "startTime",
"结束": "endTime",
"时长": "duration"
} }

View File

@@ -615,18 +615,18 @@
"原邮箱号": "原邮箱号", "原邮箱号": "原邮箱号",
"用户拒绝授权": "用户拒绝授权", "用户拒绝授权": "用户拒绝授权",
"用户取消授权": "用户取消授权", "用户取消授权": "用户取消授权",
"请输入邮箱号":"请输入邮箱号", "请输入邮箱号": "请输入邮箱号",
"中国":"中国", "中国": "中国",
"香港":"香港", "香港": "香港",
"选择区号":"选择区号", "选择区号": "选择区号",
"输入邮箱号码":"输入邮箱号码", "输入邮箱号码": "输入邮箱号码",
"通知设置":"通知设置", "通知设置": "通知设置",
"注意!关闭后将无法接受任何消息":"注意!关闭后将无法接受任何消息", "注意!关闭后将无法接受任何消息": "注意!关闭后将无法接受任何消息",
"手机号登录":"手机号登录", "手机号登录": "手机号登录",
"邮箱登录":"邮箱登录", "邮箱登录": "邮箱登录",
"输入邮箱":"输入邮箱", "输入邮箱": "输入邮箱",
"隐私协议加载失败": "隐私协议加载失败", "隐私协议加载失败": "隐私协议加载失败",
"请检查网络连接后重试": "请检查网络连接后重试" "请检查网络连接后重试": "请检查网络连接后重试",
"开始": "开始",
"结束": "结束"
} }

View File

@@ -623,5 +623,8 @@
"邮箱登录": "電子郵件登入", "邮箱登录": "電子郵件登入",
"输入邮箱": "輸入電子郵件", "输入邮箱": "輸入電子郵件",
"隐私协议加载失败": "隱私協議加載失敗", "隐私协议加载失败": "隱私協議加載失敗",
"请检查网络连接后重试": "請檢查網絡連接後重試" "请检查网络连接后重试": "請檢查網絡連接後重試",
"开始": "開始",
"结束": "結束",
"时长": "時長:"
} }

View File

@@ -642,5 +642,9 @@
"安卓启用网络提示": "The network is not enabled. Please enable the network connection", "安卓启用网络提示": "The network is not enabled. Please enable the network connection",
"ios启用网络提示": "The network is not enabled. Please enable the network connection", "ios启用网络提示": "The network is not enabled. Please enable the network connection",
"隐私协议加载失败": "Privacy Agreement Failed to Load", "隐私协议加载失败": "Privacy Agreement Failed to Load",
"请检查网络连接后重试": "Please check the network connection and try again" "请检查网络连接后重试": "Please check the network connection and try again",
"开始": "startTime",
"结束": "endTime",
"时长": "duration",
"请选择时区": "Please select a time zone"
} }

View File

@@ -649,6 +649,9 @@
"安卓启用网络提示": "网络未开启,请打开网络连接", "安卓启用网络提示": "网络未开启,请打开网络连接",
"ios启用网络提示": "网络未开启,请打开网络连接", "ios启用网络提示": "网络未开启,请打开网络连接",
"隐私协议加载失败": "隐私协议加载失败", "隐私协议加载失败": "隐私协议加载失败",
"请检查网络连接后重试": "请检查网络连接后重试" "请检查网络连接后重试": "请检查网络连接后重试",
"开始": "开始",
"结束": "结束",
"时长": "时长:",
"请选择时区": "请选择时区"
} }

View File

@@ -642,5 +642,9 @@
"安卓启用网络提示": "請開啟網絡再使用APP", "安卓启用网络提示": "請開啟網絡再使用APP",
"ios启用网络提示": "請開啟網絡再使用APP", "ios启用网络提示": "請開啟網絡再使用APP",
"隐私协议加载失败": "隱私協議加載失敗", "隐私协议加载失败": "隱私協議加載失敗",
"请检查网络连接后重试": "請檢查網絡連接後重試" "请检查网络连接后重试": "請檢查網絡連接後重試",
"开始": "開始",
"结束": "結束",
"时长": "時長:",
"请选择时区": "請選擇時區"
} }

Binary file not shown.

View File

@@ -59,4 +59,6 @@ class ServiceConstant {
static const String bgUrl = static const String bgUrl =
"https://vsbst-api.he-info.cn/vsbs_sotrage/background-image/taihe.png"; "https://vsbst-api.he-info.cn/vsbs_sotrage/background-image/taihe.png";
static const String localTimeZone =
"/api/city/data/utc/info";
} }

View File

@@ -7,6 +7,37 @@ import 'package:vbvs_app/enum/APPPackageType.dart';
class AppConstants { class AppConstants {
// App-related constants // App-related constants
// 1. 纯字符串列表格式
static const List<String> integerTimeZones = [
'UTC-12',
'UTC-11',
'UTC-10',
'UTC-9',
'UTC-8',
'UTC-7',
'UTC-6',
'UTC-5',
'UTC-4',
'UTC-3',
'UTC-2',
'UTC-1',
'UTC+0',
'UTC+1',
'UTC+2',
'UTC+3',
'UTC+4',
'UTC+5',
'UTC+6',
'UTC+7',
'UTC+8',
'UTC+9',
'UTC+10',
'UTC+11',
'UTC+12',
'UTC+13',
'UTC+14',
];
static const int code_time = 60; //验证码倒计时 static const int code_time = 60; //验证码倒计时
static const int limit = 10; //分页数量 static const int limit = 10; //分页数量

View File

@@ -12,3 +12,5 @@ class SwitchLanguageEvent {
final String language; final String language;
SwitchLanguageEvent(this.language); SwitchLanguageEvent(this.language);
} }
class ScrollNotificationEvent {}

View File

@@ -50,6 +50,8 @@ class MessageController extends GetControllerEx<MessageModel> {
int bodyPage = 1; int bodyPage = 1;
int systemPage = 1; int systemPage = 1;
bool isLoadingMore = false; // 添加加载标志位
Future<void> loadMore(String type) async { Future<void> loadMore(String type) async {
if (type == "app_vsm") { if (type == "app_vsm") {
bodyPage++; bodyPage++;

View File

@@ -55,6 +55,7 @@ class PeopleInfoController extends GetControllerEx<PeopleInfoModel> {
final CityModelController cityController = Get.find<CityModelController>(); final CityModelController cityController = Get.find<CityModelController>();
RxList diseaseList = [].obs; RxList diseaseList = [].obs;
RxString timeZone = "".obs; //选择时区
@override @override
Future<void> onInit() async { Future<void> onInit() async {
@@ -247,4 +248,35 @@ class PeopleInfoController extends GetControllerEx<PeopleInfoModel> {
} }
return ApiResponse(code: -1, msg: "未知错误".tr); // Default return statement return ApiResponse(code: -1, msg: "未知错误".tr); // Default return statement
} }
getTimeZoneByLocalTime() async {
String serviceAddress = ServiceConstant.service_address;
String serviceName = ServiceConstant.server_service;
String serviceApi = ServiceConstant.localTimeZone;
// 获取当前本地时间并格式化为字符串
DateTime now = DateTime.now();
String time = DateFormat("yyyy-MM-dd HH:mm:ss").format(now);
// 构建查询URL对时间参数进行URL编码
String queryUrl =
"${serviceAddress}${serviceName}${serviceApi}?time=${Uri.encodeComponent(time)}";
String serverTimeUtc = "";
// 发起请求
await requestWithLog(
logTitle: "查询本地时区",
method: MyHttpMethod.get,
queryUrl: queryUrl,
onSuccess: (res) {
print("本地时间: $time");
print("接口返回: $res");
serverTimeUtc = res.data;
},
onFailure: (res) {
print("查询时区失败");
},
);
return serverTimeUtc;
}
} }

View File

@@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:EasyDartModule/EasyDartModule.dart'; import 'package:EasyDartModule/EasyDartModule.dart';
import 'package:ef/ef.dart'; import 'package:ef/ef.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import 'package:vbvs_app/common/color/ServiceConstant.dart'; import 'package:vbvs_app/common/color/ServiceConstant.dart';
import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/color/appConstants.dart';
@@ -9,6 +10,7 @@ import 'package:vbvs_app/common/color/app_uri_status.dart';
import 'package:vbvs_app/common/pojo/city.dart'; import 'package:vbvs_app/common/pojo/city.dart';
import 'package:vbvs_app/common/util/DailyLogUtils.dart'; import 'package:vbvs_app/common/util/DailyLogUtils.dart';
import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/common/util/requestWithLog.dart';
import 'package:vbvs_app/enum/APPPackageType.dart'; import 'package:vbvs_app/enum/APPPackageType.dart';
import 'package:vbvs_app/model/api_response.dart'; import 'package:vbvs_app/model/api_response.dart';
@@ -50,6 +52,7 @@ class PersonController extends GetControllerEx<PersonModel> {
RxString height = "".obs; RxString height = "".obs;
DateTime? dateTime = DateTime.now(); //选择时间 DateTime? dateTime = DateTime.now(); //选择时间
CityModel? cityModel; CityModel? cityModel;
RxString timeZone = "".obs; //选择时区
RxList diseaseList = [].obs; RxList diseaseList = [].obs;
RxString update_person_mac = "".obs; RxString update_person_mac = "".obs;
@@ -79,10 +82,10 @@ class PersonController extends GetControllerEx<PersonModel> {
queryUrl += "?lang=$language"; queryUrl += "?lang=$language";
} }
} }
if (name.value.isEmpty) { // if (name.value.isEmpty) {
apiResponse.msg = "请输入姓名".tr; // apiResponse.msg = "请输入姓名".tr;
return apiResponse; // return apiResponse;
} // }
if (birthday.value.isEmpty) { if (birthday.value.isEmpty) {
apiResponse.msg = "请选择生日".tr; apiResponse.msg = "请选择生日".tr;
return apiResponse; return apiResponse;
@@ -95,10 +98,14 @@ class PersonController extends GetControllerEx<PersonModel> {
apiResponse.msg = "请输入身高".tr; apiResponse.msg = "请输入身高".tr;
return apiResponse; return apiResponse;
} }
if (cityModel == null || cityModel!.id == null) { if (timeZone == null || timeZone.value.isEmpty) {
apiResponse.msg = "请选择城市".tr; apiResponse.msg = "请选择时区".tr;
return apiResponse; return apiResponse;
} }
// if (cityModel == null || cityModel!.id == null) {
// apiResponse.msg = "请选择城市".tr;
// return apiResponse;
// }
var data = { var data = {
"id": currentPersonId.value, "id": currentPersonId.value,
@@ -110,8 +117,8 @@ class PersonController extends GetControllerEx<PersonModel> {
"weight": weight!.value, "weight": weight!.value,
"height": height.value, "height": height.value,
"disease": selectedDiseaseIds.value, "disease": selectedDiseaseIds.value,
"city_id": cityModel!.id, "city_id": cityModel?.id,
"UTC": cityModel!.UTC, "UTC": timeZone.value,
}; };
var response = var response =
await EasyDartModule.dio.put(queryUrl, data: jsonEncode(data)); await EasyDartModule.dio.put(queryUrl, data: jsonEncode(data));
@@ -240,4 +247,35 @@ class PersonController extends GetControllerEx<PersonModel> {
} }
return ApiResponse(code: -1, msg: "未知错误".tr); // Default return statement return ApiResponse(code: -1, msg: "未知错误".tr); // Default return statement
} }
getTimeZoneByLocalTime() async {
String serviceAddress = ServiceConstant.service_address;
String serviceName = ServiceConstant.server_service;
String serviceApi = ServiceConstant.localTimeZone;
// 获取当前本地时间并格式化为字符串
DateTime now = DateTime.now();
String time = DateFormat("yyyy-MM-dd HH:mm:ss").format(now);
// 构建查询URL对时间参数进行URL编码
String queryUrl =
"${serviceAddress}${serviceName}${serviceApi}?time=${Uri.encodeComponent(time)}";
String serverTimeUtc = "";
// 发起请求
await requestWithLog(
logTitle: "查询本地时区",
method: MyHttpMethod.get,
queryUrl: queryUrl,
onSuccess: (res) {
print("本地时间: $time");
print("接口返回: $res");
serverTimeUtc = res.data;
},
onFailure: (res) {
print("查询时区失败");
},
);
return serverTimeUtc;
}
} }

View File

@@ -40,7 +40,7 @@ class RepairController extends GetControllerEx<RepairModel> {
attr = GetModel(RepairModel()).obs; attr = GetModel(RepairModel()).obs;
} }
RxDouble device_type = 0.0.obs; RxInt device_type = 0.obs;
RxList repairList = [].obs; RxList repairList = [].obs;
RxString name = "".obs; RxString name = "".obs;

View File

@@ -69,6 +69,66 @@ Widget getOnePickers(
}) { }) {
ThemeController themeController = Get.find(); ThemeController themeController = Get.find();
final bool isEn = Get.locale?.languageCode.startsWith('en') ?? false; final bool isEn = Get.locale?.languageCode.startsWith('en') ?? false;
final dynamicKey = ValueKey('picker_${arr.length}_${selectedIndex.value}');
return Obx(() {
return CupertinoPicker.builder(
key: pickerKey ?? dynamicKey,
itemExtent: 90.rpx,
useMagnifier: false,
magnification: 1,
diameterRatio: 1.3,
squeeze: 1,
scrollController:
FixedExtentScrollController(initialItem: selectedIndex.value),
selectionOverlay: Container(),
onSelectedItemChanged: (int index) {
selectedIndex.value = index;
if (onChanged != null) onChanged(index);
},
childCount: arr.length,
itemBuilder: (context, index) {
final bool isSelected = index == selectedIndex.value;
// 显示文本
String displayText;
if (isMonthName && isEn && arr[index] is int) {
displayText = DateFormat.MMMM('en').format(DateTime(0, arr[index]));
} else {
displayText = "${arr[index]}$unit";
}
return Center(
child: Text(
displayText,
style: TextStyle(
fontFamily: 'Readex Pro',
color: isSelected
? (selectedColor ??
themeController.currentColor.sc3) // ✅ 优先使用外部颜色
: const Color(0xFF9AA0B3),
fontSize: 30.rpx,
fontWeight: FontWeight.normal,
),
),
);
},
);
});
}
Widget getOnePickersCity(
BuildContext context,
List arr,
RxInt selectedIndex, {
String unit = '',
bool looping = false,
void Function(int)? onChanged,
bool isMonthName = false,
Key? pickerKey,
Color? selectedColor, // ✅ 新增:选中颜色(可选)
}) {
ThemeController themeController = Get.find();
final bool isEn = Get.locale?.languageCode.startsWith('en') ?? false;
return Obx(() { return Obx(() {
final dynamicKey = ValueKey('picker_${arr.length}_${selectedIndex.value}'); final dynamicKey = ValueKey('picker_${arr.length}_${selectedIndex.value}');
@@ -132,9 +192,8 @@ Widget getOnePickersSpe(
}) { }) {
ThemeController themeController = Get.find(); ThemeController themeController = Get.find();
final bool isEn = Get.locale?.languageCode.startsWith('en') ?? false; final bool isEn = Get.locale?.languageCode.startsWith('en') ?? false;
final dynamicKey = ValueKey('picker_${arr.length}_${selectedIndex.value}');
return Obx(() { return Obx(() {
final dynamicKey = ValueKey('picker_${arr.length}_${selectedIndex.value}');
return CupertinoPicker.builder( return CupertinoPicker.builder(
key: pickerKey ?? dynamicKey, key: pickerKey ?? dynamicKey,
itemExtent: 90.rpx, itemExtent: 90.rpx,
@@ -1777,8 +1836,7 @@ Future showCustomConfirmOfWebViewDialog(
bool showCancel = false, bool showCancel = false,
String cancelName = "取消", String cancelName = "取消",
ConfirmDialogIcon icon = ConfirmDialogIcon.warn, ConfirmDialogIcon icon = ConfirmDialogIcon.warn,
int type = 1 int type = 1}) async {
}) async {
return showDialog( return showDialog(
context: context, context: context,
barrierDismissible: true, barrierDismissible: true,
@@ -1865,7 +1923,9 @@ Future showCustomConfirmOfWebViewDialog(
onTap: () { onTap: () {
Get.back(result: "confirm"); Get.back(result: "confirm");
}, },
colors: type == 3?AppConstants().mhtNormalButton:AppConstants().thNormalButton, // 渐变背景 colors: type == 3
? AppConstants().mhtNormalButton
: AppConstants().thNormalButton, // 渐变背景
gradientDirection: GradientDirection.horizontal, gradientDirection: GradientDirection.horizontal,
child: Container( child: Container(
// width: MediaQuery.sizeOf(context).width * 0.5, // 宽度占屏幕一半 // width: MediaQuery.sizeOf(context).width * 0.5, // 宽度占屏幕一半

View File

@@ -5,8 +5,10 @@ import 'package:flutter_svg/svg.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/color/app_uri_status.dart'; import 'package:vbvs_app/common/color/app_uri_status.dart';
import 'package:vbvs_app/common/util/EventBus.dart';
import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/common/util/eventType.dart';
import 'package:vbvs_app/component/NullDataComponentWidget.dart'; import 'package:vbvs_app/component/NullDataComponentWidget.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/component/tool/CustomCard.dart'; import 'package:vbvs_app/component/tool/CustomCard.dart';
@@ -641,16 +643,19 @@ class _BodyDevicePageState extends State<BodyDeviceWidget> {
: Padding( : Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
30.rpx, 26.rpx, 30.rpx, 0), 30.rpx, 26.rpx, 30.rpx, 0),
child: SingleChildScrollView( child: _wrapWithScrollListener(
controller: _myDeviceScrollController, SingleChildScrollView(
child: Column( controller: _myDeviceScrollController,
mainAxisSize: MainAxisSize.max, child: Column(
children: myDeviceList mainAxisSize: MainAxisSize.max,
.map((device) => children: myDeviceList
DeviceDataComponentWidget( .map((device) =>
device: device)) DeviceDataComponentWidget(
.toList() device: device))
.divide(SizedBox(height: 25.rpx)), .toList()
.divide(
SizedBox(height: 25.rpx)),
),
), ),
), ),
); );
@@ -668,17 +673,20 @@ class _BodyDevicePageState extends State<BodyDeviceWidget> {
: Padding( : Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
30.rpx, 26.rpx, 30.rpx, 0), 30.rpx, 26.rpx, 30.rpx, 0),
child: SingleChildScrollView( child: _wrapWithScrollListener(
controller: SingleChildScrollView(
_cloudDeviceScrollController, controller:
child: Column( _cloudDeviceScrollController,
mainAxisSize: MainAxisSize.max, child: Column(
children: cloudDeviceList mainAxisSize: MainAxisSize.max,
.map((device) => children: cloudDeviceList
DeviceDataComponentWidget( .map((device) =>
device: device)) DeviceDataComponentWidget(
.toList() device: device))
.divide(SizedBox(height: 25.rpx)), .toList()
.divide(
SizedBox(height: 25.rpx)),
),
), ),
), ),
); );
@@ -743,3 +751,18 @@ class _BodyDevicePageState extends State<BodyDeviceWidget> {
); );
} }
} }
// 在你的父页面类中添加这个方法
Widget _wrapWithScrollListener(Widget child) {
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification is ScrollStartNotification ||
notification is ScrollUpdateNotification) {
// 发送全局滚动事件
EventBus().emit(ScrollNotificationEvent());
}
return false;
},
child: child,
);
}

View File

@@ -25,7 +25,6 @@ import 'package:vbvs_app/enum/BindType.dart';
import 'package:vbvs_app/model/api_response.dart'; import 'package:vbvs_app/model/api_response.dart';
import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
class DeviceDataComponentWidget extends StatefulWidget { class DeviceDataComponentWidget extends StatefulWidget {
final Map<String, dynamic> device; final Map<String, dynamic> device;
@@ -44,6 +43,7 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
bool _isPopupOpen = false; bool _isPopupOpen = false;
var lisObj; var lisObj;
late StreamSubscription<ScrollNotificationEvent> _scrollSubscription;
@override @override
void dispose() { void dispose() {
@@ -64,6 +64,12 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
cityController.cityList = []; cityController.cityList = [];
await initializeCityData(); await initializeCityData();
}); });
_scrollSubscription =
EventBus().on<ScrollNotificationEvent>().listen((event) {
if (_isPopupOpen) {
_closePopup();
}
});
} }
void _showPopup() { void _showPopup() {
@@ -628,7 +634,7 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
maxWidth: MediaQuery.sizeOf(context).width * 0.6, maxWidth: MediaQuery.sizeOf(context).width * 0.6,
), ),
child: Text( child: Text(
'${widget.device['person']?['name'] ?? '未命名'.tr}', '${(widget.device['person']?['name'] as String?)?.isNotEmpty == true ? widget.device['person']!['name'] : '体征检测设备'.tr}',
style: TextStyle( style: TextStyle(
fontFamily: 'Inter', fontFamily: 'Inter',
fontSize: 30.rpx, fontSize: 30.rpx,
@@ -1180,6 +1186,8 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
personController.dateTime = personController.dateTime =
MyUtils.formatBirthdayTime( MyUtils.formatBirthdayTime(
widget.device['person']['birthday']); widget.device['person']['birthday']);
personController.timeZone.value =
widget.device['person']['UTC'] ?? '';
if (widget.device['person']['city_id'] != null) { if (widget.device['person']['city_id'] != null) {
// 根据city_id查找完整的城市数据 // 根据city_id查找完整的城市数据
final int cityId = final int cityId =
@@ -1208,6 +1216,7 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
personController.weight.value = ""; personController.weight.value = "";
personController.diseaseList.value = []; personController.diseaseList.value = [];
personController.cityModel = null; personController.cityModel = null;
personController.timeZone.value = "";
} }
await Get.toNamed("/updatePersonPage", await Get.toNamed("/updatePersonPage",
arguments: widget.device['bind_type']); arguments: widget.device['bind_type']);
@@ -1701,4 +1710,12 @@ class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
} }
return false; return false;
} }
void _closePopup() {
setState(() {
_isPopupOpen = false;
});
_popupEntry?.remove();
_popupEntry = null;
}
} }

View File

@@ -659,7 +659,7 @@ class _MessageSettingPageState extends State<MessageSettingPage> {
children: [ children: [
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
40.rpx, 40.rpx, 40.rpx, 20.rpx), 30.rpx, 40.rpx, 30.rpx, 20.rpx),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
@@ -681,9 +681,9 @@ class _MessageSettingPageState extends State<MessageSettingPage> {
(data["real"] as List)[i].containsKey("name")) (data["real"] as List)[i].containsKey("name"))
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
40.rpx, 30.rpx,
i == 0 ? 20.rpx : 0, // 第一个元素顶部有20.rpx间距 i == 0 ? 20.rpx : 0, // 第一个元素顶部有20.rpx间距
40.rpx, 30.rpx,
i == (data["real"] as List).length - 1 i == (data["real"] as List).length - 1
? 20.rpx ? 20.rpx
: 0.rpx), : 0.rpx),
@@ -781,7 +781,7 @@ class _MessageSettingPageState extends State<MessageSettingPage> {
children: [ children: [
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
40.rpx, 40.rpx, 40.rpx, 20.rpx), 30.rpx, 40.rpx, 30.rpx, 20.rpx),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
@@ -803,9 +803,9 @@ class _MessageSettingPageState extends State<MessageSettingPage> {
(data["report"] as List)[i].containsKey("name")) (data["report"] as List)[i].containsKey("name"))
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
40.rpx, 30.rpx,
i == 0 ? 20.rpx : 0, // 第一个元素顶部有20.rpx间距 i == 0 ? 20.rpx : 0, // 第一个元素顶部有20.rpx间距
40.rpx, 30.rpx,
i == (data["report"] as List).length - 1 i == (data["report"] as List).length - 1
? 20.rpx ? 20.rpx
: 0.rpx), : 0.rpx),

File diff suppressed because it is too large Load Diff

View File

@@ -96,7 +96,7 @@ getContentById(data, BuildContext context) {
), ),
child: Padding( child: Padding(
padding: padding:
EdgeInsetsDirectional.fromSTEB(40.rpx, 20.rpx, 40.rpx, 20.rpx), EdgeInsetsDirectional.fromSTEB(30.rpx, 20.rpx, 30.rpx, 20.rpx),
child: Column( child: Column(
children: [ children: [
/// --- 心率小于 --- /// --- 心率小于 ---
@@ -379,8 +379,8 @@ getContentById(data, BuildContext context) {
} else if (id == 100002) { } else if (id == 100002) {
// 呼吸异常 // 呼吸异常
int min = 10; // 默认 int min = 8; // 默认
int max = 40; // 默认 int max = 25; // 默认
int interval = 600; // 默认 int interval = 600; // 默认
// 若有用户配置 // 若有用户配置
@@ -434,7 +434,7 @@ getContentById(data, BuildContext context) {
), ),
child: Padding( child: Padding(
padding: padding:
EdgeInsetsDirectional.fromSTEB(40.rpx, 20.rpx, 40.rpx, 20.rpx), EdgeInsetsDirectional.fromSTEB(30.rpx, 20.rpx, 30.rpx, 20.rpx),
child: Column( child: Column(
children: [ children: [
/// ---- 呼吸小于 ---- /// ---- 呼吸小于 ----
@@ -1025,7 +1025,7 @@ getContentById(data, BuildContext context) {
} else if (id == 100005) { } else if (id == 100005) {
// 未起床 // 未起床
// 1. 优先从 device_type_setting 中查找用户配置 // 1. 优先从 device_type_setting 中查找用户配置
String time = "23:00"; // 默认值 String time = "7:00"; // 默认值
// 2. 如果找到了用户配置,使用用户配置中的 time 值 // 2. 如果找到了用户配置,使用用户配置中的 time 值
if (userConfig != null) { if (userConfig != null) {
@@ -1187,7 +1187,7 @@ getContentById(data, BuildContext context) {
); );
} else if (id == 200001) { } else if (id == 200001) {
// 1. 优先从 device_type_setting 中查找用户配置 // 1. 优先从 device_type_setting 中查找用户配置
int score = 60; // 默认值 int score = 50; // 默认值
// 2. 如果找到了用户配置,使用用户配置中的 max 值 // 2. 如果找到了用户配置,使用用户配置中的 max 值
if (userConfig != null) { if (userConfig != null) {
print('找到用户配置: $userConfig'); print('找到用户配置: $userConfig');
@@ -1195,7 +1195,7 @@ getContentById(data, BuildContext context) {
if (userConfig['max'] != null) { if (userConfig['max'] != null) {
score = userConfig['max'] is int score = userConfig['max'] is int
? userConfig['max'] ? userConfig['max']
: int.tryParse(userConfig['max'].toString()) ?? 60; : int.tryParse(userConfig['max'].toString()) ?? score;
print('从用户配置获取睡眠得分阈值: $score'); print('从用户配置获取睡眠得分阈值: $score');
} }
} else { } else {
@@ -1207,7 +1207,7 @@ getContentById(data, BuildContext context) {
if (defaultConfig['max'] != null) { if (defaultConfig['max'] != null) {
score = defaultConfig['max'] is int score = defaultConfig['max'] is int
? defaultConfig['max'] ? defaultConfig['max']
: int.tryParse(defaultConfig['max'].toString()) ?? 60; : int.tryParse(defaultConfig['max'].toString()) ?? score;
print('从默认配置获取睡眠得分阈值: $score'); print('从默认配置获取睡眠得分阈值: $score');
} }
} else { } else {
@@ -1235,8 +1235,8 @@ getContentById(data, BuildContext context) {
onTap: () async { onTap: () async {
final currentScore = score; final currentScore = score;
final initialScore = currentScore != null final initialScore = currentScore != null
? int.tryParse(currentScore.toString()) ?? 60 ? int.tryParse(currentScore.toString()) ?? score
: 60; : score;
FocusScope.of(context).requestFocus(FocusNode()); FocusScope.of(context).requestFocus(FocusNode());
Future.delayed(const Duration(milliseconds: 250), () { Future.delayed(const Duration(milliseconds: 250), () {
showScorePickerDialog( showScorePickerDialog(

File diff suppressed because it is too large Load Diff

View File

@@ -384,7 +384,7 @@ class _EPageState extends State<DeviceTypePage> {
} }
Widget _buildDeviceCard(BuildContext context, Widget _buildDeviceCard(BuildContext context,
{required String title, required String imageUrl, required double type}) { {required String title, required String imageUrl, required int type}) {
if (type != 1) { if (type != 1) {
return Container(); return Container();
} }

View File

@@ -134,7 +134,7 @@ class _DeviceTypeListPageState extends State<DeviceTypeListPage> {
} }
Widget _buildDeviceCard(BuildContext context, Widget _buildDeviceCard(BuildContext context,
{required String title, required String imageUrl, required double type}) { {required String title, required String imageUrl, required int type}) {
if (type != 1) { if (type != 1) {
return Container(); return Container();
} }

View File

@@ -728,8 +728,8 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
weatherModelController = Get.find(); weatherModelController = Get.find();
await weatherModelController await weatherModelController
.getCurrentLocation(); .getCurrentLocation();
await weatherModelController // await weatherModelController
.getCurrentWeather(); // .getCurrentWeather();
} }
} }
} catch (e) { } catch (e) {

View File

@@ -884,6 +884,7 @@ class _HomePageState extends State<HomePage> {
homeController.model.type = 1; homeController.model.type = 1;
deviceController.model.type = 1; deviceController.model.type = 1;
homeController.updateAll();
await deviceController await deviceController
.getDeviceList(); .getDeviceList();
await deviceController await deviceController
@@ -942,6 +943,7 @@ class _HomePageState extends State<HomePage> {
onTap: () async { onTap: () async {
homeController.model.type = 2; homeController.model.type = 2;
deviceController.model.type = 2; deviceController.model.type = 2;
homeController.updateAll();
await deviceController await deviceController
.getDeviceList(); .getDeviceList();
await deviceController await deviceController

View File

@@ -58,6 +58,16 @@ class _MessagePageState extends State<MessagePage> {
} }
void _onTabChanged(int index) { void _onTabChanged(int index) {
int currentIndex = messageController.model.type == 1 ? 0 : 1;
// 只有当切换到不同tab时才重置加载状态
if (currentIndex != index) {
messageController.isLoadingMore = false;
messageController.bodyPage = 1;
messageController.systemPage = 1;
}
messageController.model.type = index == 0 ? 1 : 2; messageController.model.type = index == 0 ? 1 : 2;
messageController.updateAll(); messageController.updateAll();
_fetchMessageData(); _fetchMessageData();
@@ -298,56 +308,47 @@ class _MessagePageState extends State<MessagePage> {
), ),
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
body: SafeArea( body: SafeArea(
top: true, top: true,
child: PageView( child: Scrollbar(
controller: _pageController, child: PageView(
onPageChanged: _onPageChanged, controller: _pageController,
children: [ onPageChanged: _onPageChanged,
Obx(() { children: [
final list = messageController.messageList.value; Obx(() {
return list.isEmpty final list = messageController.messageList.value;
? const NullDataWidget() return list.isEmpty
: _buildMessageListView(list, "app_vsm"); ? const NullDataWidget()
}), : _buildMessageListView(list, "app_vsm");
Obx(() { }),
final list = messageController.messageList.value; Obx(() {
return list.isEmpty final list = messageController.messageList.value;
? const NullDataWidget() return list.isEmpty
: _buildMessageListView(list, "app_system"); ? const NullDataWidget()
}), : _buildMessageListView(list, "app_system");
], }),
), ],
), ),
)),
), ),
), ),
), ),
); );
} }
// Widget _buildMessageListView(List dataList) {
// return Container(
// width: double.infinity,
// padding: EdgeInsets.symmetric(horizontal: 30.rpx),
// child: SingleChildScrollView(
// child: Column(
// children: [
// SizedBox(height: 30.rpx),
// ...dataList
// .map((item) => MessageWidgetWidget(data: item))
// .toList()
// .divide(SizedBox(height: 30.rpx)),
// SizedBox(height: 30.rpx),
// ],
// ),
// ),
// );
// }
Widget _buildMessageListView(List dataList, String type) { Widget _buildMessageListView(List dataList, String type) {
return NotificationListener<ScrollNotification>( return NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) { onNotification: (scrollInfo) {
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) { // 检查是否滚动到底部,并且没有正在加载
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent &&
!messageController.isLoadingMore) {
messageController.isLoadingMore = true;
// 滑到底部,加载下一页 // 滑到底部,加载下一页
messageController.loadMore(type); messageController.loadMore(type).then((_) {
// 加载完成后重置标志位
messageController.isLoadingMore = false;
}).catchError((_) {
messageController.isLoadingMore = false;
});
} }
return true; return true;
}, },

View File

@@ -48,6 +48,16 @@ class _MessageReturnPageState extends State<MessageReturnPage> {
} }
void _onTabChanged(int index) { void _onTabChanged(int index) {
int currentIndex = messageController.model.type == 1 ? 0 : 1;
// 只有当切换到不同tab时才重置加载状态
if (currentIndex != index) {
messageController.isLoadingMore = false;
messageController.bodyPage = 1;
messageController.systemPage = 1;
}
messageController.model.type = index == 0 ? 1 : 2; messageController.model.type = index == 0 ? 1 : 2;
messageController.updateAll(); messageController.updateAll();
_fetchMessageData(); _fetchMessageData();
@@ -297,7 +307,8 @@ class _MessageReturnPageState extends State<MessageReturnPage> {
height: 4.rpx, height: 4.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
color: themeController.currentColor.sc2, color: themeController.currentColor.sc2,
borderRadius: BorderRadius.circular(2.rpx), borderRadius:
BorderRadius.circular(2.rpx),
), ),
), ),
); );
@@ -338,13 +349,21 @@ class _MessageReturnPageState extends State<MessageReturnPage> {
), ),
); );
} }
Widget _buildMessageListView(List dataList, String type) { Widget _buildMessageListView(List dataList, String type) {
return NotificationListener<ScrollNotification>( return NotificationListener<ScrollNotification>(
onNotification: (scrollInfo) { onNotification: (scrollInfo) {
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) { // 检查是否滚动到底部,并且没有正在加载
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent &&
!messageController.isLoadingMore) {
messageController.isLoadingMore = true;
// 滑到底部,加载下一页 // 滑到底部,加载下一页
messageController.loadMore(type); messageController.loadMore(type).then((_) {
// 加载完成后重置标志位
messageController.isLoadingMore = false;
}).catchError((_) {
messageController.isLoadingMore = false;
});
} }
return true; return true;
}, },
@@ -360,4 +379,4 @@ class _MessageReturnPageState extends State<MessageReturnPage> {
), ),
); );
} }
} }

View File

@@ -703,7 +703,7 @@ class _MinePageState extends State<MinePage> {
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
children: [ children: [
Text( Text(
'V1.0.2512.10', 'V1.0.2601.06',
style: TextStyle( style: TextStyle(
fontFamily: 'Inter', fontFamily: 'Inter',
// color: Color(0xFFD9E3EB), // color: Color(0xFFD9E3EB),

View File

@@ -72,6 +72,21 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
}); });
} }
PeopleInfoController personController = Get.find();
personController.getTimeZoneByLocalTime().then((value) {
personController.timeZone.value = value;
if (value == null || value.isEmpty) {
personController.timeZone.value = "UTC+8";
}
if (peopleList != null && peopleList.length > 0) {
ef.log("msg");
for (int i = 0; i < peopleList.length; i++) {
peopleList[i]['UTC'] = personController.timeZone.value;
}
}
personController.updateAll();
});
// 初始化城市模型列表 // 初始化城市模型列表
cityModels = List.filled(peopleList.length, CityModel()); cityModels = List.filled(peopleList.length, CityModel());
@@ -375,7 +390,7 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
final diseaseIds = diseaseIdsList[i]; final diseaseIds = diseaseIdsList[i];
// 添加城市信息到person数据 // 添加城市信息到person数据
person['UTC'] = cityModel.UTC; // person['UTC'] = cityModel.UTC;
person['city_id'] = cityModel.id; person['city_id'] = cityModel.id;
person['disease_ids'] = diseaseIds; // 添加疾病ID person['disease_ids'] = diseaseIds; // 添加疾病ID
@@ -917,6 +932,98 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
), ),
), ),
getLine(), getLine(),
Container(
height: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx,
right: 35.rpx,
),
child: InkWell(
onTap: () {
FocusScope.of(context)
.requestFocus(FocusNode());
Future.delayed(
const Duration(milliseconds: 250),
() {
// 获取当前时区
String? currentTimeZone;
if (cityModels.isNotEmpty &&
index < cityModels.length) {
currentTimeZone =
cityModels[index].UTC;
}
showTimeMHTZonePickerDialog(
context,
title: "请选择时区".tr,
initialTimeZone:
currentTimeZone ?? "",
onConfirm:
(String selectedTimeZone) {
setState(() {
peopleList[index]['UTC'] =
selectedTimeZone;
});
},
);
},
);
},
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'请选择时区'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0xFF9EA4B7),
fontSize: 30.rpx,
letterSpacing: 0,
),
),
Obx(() {
PeopleInfoController
personController = Get.find();
var aa =
personController.timeZone.value;
return Row(
children: [
Text(
peopleList[index]['UTC'] ==
null ||
peopleList[index]
['UTC'] ==
""
? "请选择时区".tr
: peopleList[index]['UTC'],
style: TextStyle(
color: peopleList[index]
['UTC'] !=
null
? Colors
.white // 有时区时使用白色,保持和参考代码一致
: themeController
.currentColor.sc4,
fontSize: 30
.rpx, // 使用固定的30.rpx而不是AppConstants().title_text_fontSize
),
),
SizedBox(width: 16.rpx),
Icon(
Icons.expand_more,
color: Colors
.white, // 保持白色,和参考代码一致
size: 48.rpx,
),
],
);
})
],
),
),
),
getLine(),
// 慢病管理部分 // 慢病管理部分
Container( Container(
height: 90.rpx, height: 90.rpx,

View File

@@ -253,7 +253,7 @@ class _SettingPageState extends State<SettingPage> {
), ),
].divide(SizedBox(width: 22.rpx)), ].divide(SizedBox(width: 22.rpx)),
), ),
Text('SWES2025.12.30', Text('SWES2026.1.5',
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 26.rpx, fontSize: 26.rpx,

View File

@@ -142,22 +142,6 @@ class PeopleInfoPage extends GetView<PeopleInfoController> {
isValid = false; isValid = false;
break; break;
} }
// if (d['UTC'] == null ||
// d['UTC'].toString().isEmpty) {
// TopSlideNotification.show(context,
// text: "请选择城市".tr,
// textColor: Color(0xFFFF7159));
// isValid = false;
// break;
// }
// if (d['city_id'] ==null ||
// d['city_id'].toString().isEmpty) {
// TopSlideNotification.show(context,
// text: "请选择城市".tr,
// textColor: Color(0xFFFF7159));
// isValid = false;
// break;
// }
} }
// 所有数据合法,开始保存 // 所有数据合法,开始保存
if (isValid) { if (isValid) {
@@ -890,10 +874,10 @@ class PeopleInfoPage extends GetView<PeopleInfoController> {
// 补齐并追加 // 补齐并追加
list.add(newCity); list.add(newCity);
} }
controller.model // controller.model
.peopleList[ // .peopleList[
index]['UTC'] = // index]['UTC'] =
list[index].UTC; // list[index].UTC;
controller.model controller.model
.peopleList[ .peopleList[
index] index]
@@ -952,14 +936,17 @@ class PeopleInfoPage extends GetView<PeopleInfoController> {
: "请选择城市".tr, : "请选择城市".tr,
style: TextStyle( style: TextStyle(
color: getCityModel( color: getCityModel(
index) != index) !=
null null &&
getCityModel(
index)!
.id !=
null
? themeController ? themeController
.currentColor .currentColor
.sc3 .sc3
: themeController : Color(
.currentColor 0xFF9EA4B7),
.sc4,
fontSize: AppConstants() fontSize: AppConstants()
.title_text_fontSize, .title_text_fontSize,
), ),
@@ -981,6 +968,160 @@ class PeopleInfoPage extends GetView<PeopleInfoController> {
), ),
), ),
getLine(), getLine(),
Container(
height: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx,
right: 35.rpx,
),
child: InkWell(
onTap: () {
// if (widget.status ==
// BindType.share.code) {
// TopSlideNotification.show(
// context,
// text: "被分享用户只能修改用户名称",
// textColor:
// themeController
// .currentColor
// .sc9);
// return;
// }
FocusScope.of(context)
.requestFocus(
FocusNode());
Future.delayed(
Duration(
milliseconds: 250),
() {
// 获取当前时区
String? currentTimeZone;
if (controller
.model
.peopleList
.isNotEmpty &&
index <
controller
.model
.peopleList
.length &&
controller.model
.peopleList[
index]['UTC'] !=
null) {
currentTimeZone =
controller.model
.peopleList[
index]['UTC'];
}
showTimeMHTZonePickerDialog(
context,
title: "请选择时区".tr,
initialTimeZone:
currentTimeZone ?? "",
onConfirm: (String
selectedTimeZone) {
controller.model
.peopleList[
index]['UTC'] =
selectedTimeZone;
},
);
});
},
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
'请选择时区'.tr,
style: TextStyle(
fontFamily:
'Readex Pro',
color:
Color(0xFF9EA4B7),
fontSize: 30.rpx,
letterSpacing: 0,
),
),
Row(
children: [
Text(
controller
.model
.peopleList
.isNotEmpty &&
index <
controller
.model
.peopleList
.length &&
controller.model
.peopleList[index]
[
'UTC'] !=
null &&
controller
.model
.peopleList[
index]
[
'UTC']!
.isNotEmpty
? controller.model
.peopleList[
index]['UTC']!
: "请选择时区".tr,
style: TextStyle(
color: controller
.model
.peopleList
.isNotEmpty &&
index <
controller
.model
.peopleList
.length &&
controller.model
.peopleList[index]
[
'UTC'] !=
null &&
controller
.model
.peopleList[
index]
[
'UTC']!
.isNotEmpty
? themeController
.currentColor
.sc3
: Color(
0xFF9EA4B7),
fontSize: AppConstants()
.title_text_fontSize,
),
),
SizedBox(width: 16.rpx),
Container(
height: 30.rpx,
width: 30.rpx,
child:
SvgPicture.asset(
'assets/img/icon/expand_more.svg',
color: Colors.white,
),
),
],
),
],
),
),
),
getLine(),
Container( Container(
height: 90.rpx, height: 90.rpx,
margin: EdgeInsets.only( margin: EdgeInsets.only(

View File

@@ -60,6 +60,13 @@ class _EPageState extends State<PersonPage> {
personController.weight.value = ""; personController.weight.value = "";
personController.height.value = ""; personController.height.value = "";
personController.dateTime = null; personController.dateTime = null;
personController.cityModel = null;
personController.timeZone.value = "";
personController.getTimeZoneByLocalTime().then((value) {
personController.timeZone.value = value;
personController.updateAll();
});
cityDataFuture = cityController.loadAndSetCityData().then((success) { cityDataFuture = cityController.loadAndSetCityData().then((success) {
return cityController.cityList; return cityController.cityList;
@@ -172,7 +179,7 @@ class _EPageState extends State<PersonPage> {
children: [ children: [
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 141.rpx, 70.rpx, 0), 70.rpx, 70.rpx, 70.rpx, 0),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
height: 100.rpx, height: 100.rpx,
@@ -404,30 +411,77 @@ class _EPageState extends State<PersonPage> {
}, title: "选择生日".tr); }, title: "选择生日".tr);
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
personController.dateTime != null // 文字居中
? DateFormat("yyyy/MM/dd").format( Center(
personController.dateTime!) child: Row(
: '人员资料.生日输入提示'.tr, mainAxisSize: MainAxisSize.min,
textAlign: TextAlign.right, children: [
style: TextStyle( Text.rich(
fontFamily: 'Readex Pro', TextSpan(
color: personController.dateTime != null children: [
? themeController.currentColor.sc3 TextSpan(
: themeController.currentColor.sc4, text: personController
fontSize: .dateTime !=
AppConstants().normal_text_fontSize, null
letterSpacing: 0, ? DateFormat(
"yyyy/MM/dd")
.format(
personController
.dateTime!)
: '人员资料.生日输入提示'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.dateTime !=
null
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 50.rpx, 70.rpx, 0), 70.rpx, 25.rpx, 70.rpx, 0),
child: Container( child: Container(
height: 100.rpx, height: 100.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -464,31 +518,76 @@ class _EPageState extends State<PersonPage> {
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
personController.height.value != "" // 文字居中
? personController.height.value + Center(
"cm".tr child: Row(
: '身高输入提示'.tr, mainAxisSize: MainAxisSize.min,
textAlign: TextAlign.right, children: [
style: TextStyle( Text.rich(
fontFamily: 'Readex Pro', TextSpan(
color: personController.height.value != children: [
"" TextSpan(
? themeController.currentColor.sc3 text: personController
: themeController.currentColor.sc4, .height.value !=
fontSize: ""
AppConstants().normal_text_fontSize, ? personController
letterSpacing: 0, .height.value +
"cm".tr
: '身高输入提示'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.height
.value !=
""
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 50.rpx, 70.rpx, 0), 70.rpx, 25.rpx, 70.rpx, 0),
child: Container( child: Container(
height: 100.rpx, height: 100.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -512,38 +611,184 @@ class _EPageState extends State<PersonPage> {
personController.weight.value ?? "", personController.weight.value ?? "",
onConfirm: (int selectedWeight) { onConfirm: (int selectedWeight) {
personController.weight.value = personController.weight.value =
selectedWeight selectedWeight.toString();
.toString(); // ✅ 转成字符串
personController.updateAll(); personController.updateAll();
}, },
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
personController.weight.value != "" // 文字居中
? personController.weight.value + Center(
"kg".tr child: Row(
: '人员资料.体重输入提示'.tr, mainAxisSize: MainAxisSize.min,
textAlign: TextAlign.right, children: [
style: TextStyle( Text.rich(
fontFamily: 'Readex Pro', TextSpan(
color: personController.weight.value != children: [
"" TextSpan(
? themeController.currentColor.sc3 text: personController
: themeController.currentColor.sc4, .weight.value !=
fontSize: ""
AppConstants().normal_text_fontSize, ? personController
letterSpacing: 0, .weight.value +
"kg".tr
: '人员资料.体重输入提示'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.weight
.value !=
""
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 50.rpx, 70.rpx, 0), 70.rpx, 25.rpx, 70.rpx, 0),
child: Container(
height: 100.rpx,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.rpx),
border: Border.all(
color: themeController.currentColor.sc4
.withOpacity(0.5),
width: AppConstants().border_width,
),
),
child: InkWell(onTap: () {
final timeZone =
personController.timeZone.value;
final initialTimeZone = timeZone;
FocusScope.of(context)
.requestFocus(FocusNode());
Future.delayed(
const Duration(milliseconds: 250), () {
showTimeZonePickerDialog(
context,
title: "选择时区".tr,
initialTimeZone: initialTimeZone,
onConfirm: (String selectedtimezone) {
personController.timeZone.value =
selectedtimezone.toString();
personController.updateAll();
print("时区: $selectedtimezone");
},
);
});
}, child: Obx(() {
return Stack(
children: [
// 文字居中
Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text.rich(
TextSpan(
children: [
TextSpan(
text: personController
.timeZone
.value !=
""
? personController
.timeZone.value
: '选择时区'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.timeZone
.value !=
""
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
),
// 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
);
})),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 25.rpx, 70.rpx, 0),
child: Container( child: Container(
height: 100.rpx, height: 100.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -577,32 +822,77 @@ class _EPageState extends State<PersonPage> {
title: "选择城市".tr, title: "选择城市".tr,
cityDataFuture: cityDataFuture:
cityDataFuture, // 传入预加载的数据 cityDataFuture, // 传入预加载的数据
colors: CitySelectionColors(
// pickerBackgroundColor:
// stringToColor("#003058"),
// confirmTextColor:
// stringToColor("#84F5FF"),
selectedCityColor:
themeController.currentColor.sc2,
selectedTextColor: Colors.white,
),
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
_getDetailedCityDisplayText( // 文字居中
personController.cityModel), Center(
textAlign: TextAlign.right, child: Row(
style: TextStyle( mainAxisSize: MainAxisSize.min,
fontFamily: 'Readex Pro', children: [
color: personController.cityModel != Text(
null _getDetailedCityDisplayText(
? themeController.currentColor.sc3 personController.cityModel),
: themeController.currentColor.sc4, textAlign: TextAlign.center,
fontSize: style: TextStyle(
AppConstants().normal_text_fontSize, fontFamily: 'Readex Pro',
letterSpacing: 0, color:
personController
.cityModel !=
null
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
// Text(
// ' *',
// style: TextStyle(
// color: themeController
// .currentColor.sc9,
// fontSize: AppConstants()
// .normal_text_fontSize,
// fontWeight: FontWeight.bold,
// ),
// ),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
0, 117.rpx, 0, 0), 0, 60.rpx, 0, 0),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
decoration: BoxDecoration(), decoration: BoxDecoration(),

View File

@@ -3,9 +3,11 @@ import 'dart:convert';
import 'package:ef/ef.dart'; import 'package:ef/ef.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/pojo/city.dart'; import 'package:vbvs_app/common/pojo/city.dart';
import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/ListSearchWidget.dart'; import 'package:vbvs_app/common/util/ListSearchWidget.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/controller/person/person_controller.dart'; import 'package:vbvs_app/controller/person/person_controller.dart';
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
@@ -666,7 +668,7 @@ Widget _buildCityPickerContent(
Get.find(); Get.find();
cityModelController.tmp; cityModelController.tmp;
ef.log("${cityModelController.tmp.value}"); ef.log("${cityModelController.tmp.value}");
return getOnePickers( return getOnePickersCity(
context, context,
countries, countries,
countryIndex, countryIndex,
@@ -684,7 +686,7 @@ Widget _buildCityPickerContent(
Get.find(); Get.find();
cityModelController.tmp; cityModelController.tmp;
ef.log("${cityModelController.tmp.value}"); ef.log("${cityModelController.tmp.value}");
return getOnePickers( return getOnePickersCity(
context, context,
provinces, provinces,
provinceIndex, provinceIndex,
@@ -702,7 +704,7 @@ Widget _buildCityPickerContent(
Get.find(); Get.find();
cityModelController.tmp; cityModelController.tmp;
ef.log("${cityModelController.tmp.value}"); ef.log("${cityModelController.tmp.value}");
return getOnePickers( return getOnePickersCity(
context, context,
cities, cities,
cityIndex, cityIndex,
@@ -813,3 +815,149 @@ Widget _buildErrorBottomSheet(
), ),
); );
} }
Future<void> showTimeMHTZonePickerDialog(
BuildContext context, {
required String initialTimeZone, // 初始时区字符串,如 "UTC+8"
required Function(String selectedTimeZone) onConfirm,
String title = "选择时区",
}) async {
// 使用 AppConstants.integerTimeZones 作为数据源
List<String> timeZones = AppConstants.integerTimeZones;
int selectedIndex = timeZones.indexOf(initialTimeZone);
// 如果没有找到使用默认的UTC+8北京时间
if (selectedIndex == -1) {
selectedIndex = timeZones.indexOf("UTC+8");
if (selectedIndex == -1) {
selectedIndex = 0; // 如果连UTC+8都没有使用第一个
}
}
final RxInt tempIndex = RxInt(selectedIndex);
ThemeController themeController = Get.find();
await 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: stringToColor("#003058"),
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
padding: EdgeInsets.fromLTRB(0.rpx, 0.rpx, 0.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding:
EdgeInsets.fromLTRB(30.rpx, 0.rpx, 30.rpx, 0.rpx),
color: themeController.currentColor.sc5,
height: 80.rpx,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.only(top: 0),
onTap: () {
Get.back();
},
child: Container(
alignment: Alignment.center,
width: 110.rpx,
height: 60.rpx,
child: Text(
"取消".tr,
style: TextStyle(
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.only(top: 0),
onTap: () {
onConfirm(timeZones[tempIndex.value]);
Get.back();
},
child: Container(
alignment: Alignment.center,
width: 110.rpx,
height: 60.rpx,
child: Text(
"确定".tr,
style: TextStyle(
fontSize: 30.rpx,
color: stringToColor("#84F5FF"),
),
),
),
),
],
),
),
SizedBox(height: 20.rpx),
Stack(
children: [
Positioned.fill(
child: IgnorePointer(
child: Center(
child: Container(
height: 90.rpx,
margin:
EdgeInsets.symmetric(horizontal: 95.rpx),
decoration: BoxDecoration(
color: stringToColor("#84F5FF"),
borderRadius: BorderRadius.circular(16.rpx),
),
),
),
),
),
SizedBox(
height: 240.rpx,
child: getOnePickers(
context,
timeZones, // 传入字符串列表
tempIndex,
unit: "", // 时区不需要单位
selectedColor: stringToColor("#011D33"),
),
),
],
),
],
),
),
),
),
),
],
);
},
);
}

View File

@@ -1306,3 +1306,150 @@ Future<void> showCountryCodePickerDialog(
}, },
); );
} }
Future<void> showTimeZonePickerDialog(
BuildContext context, {
required String initialTimeZone, // 初始时区字符串,如 "UTC+8"
required Function(String selectedTimeZone) onConfirm,
String title = "选择时区",
}) async {
// 使用 AppConstants.integerTimeZones 作为数据源
List<String> timeZones = AppConstants.integerTimeZones;
int selectedIndex = timeZones.indexOf(initialTimeZone);
// 如果没有找到使用默认的UTC+8北京时间
if (selectedIndex == -1) {
selectedIndex = timeZones.indexOf("UTC+8");
if (selectedIndex == -1) {
selectedIndex = 0; // 如果连UTC+8都没有使用第一个
}
}
final RxInt tempIndex = RxInt(selectedIndex);
ThemeController themeController = Get.find();
await 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(
padding: EdgeInsets.fromLTRB(0.rpx, 0.rpx, 0.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding:
EdgeInsets.fromLTRB(30.rpx, 0.rpx, 30.rpx, 0.rpx),
color: themeController.currentColor.sc5,
height: 80.rpx,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.only(top: 0),
onTap: () {
Get.back();
},
child: Container(
alignment: Alignment.center,
width: 110.rpx,
height: 60.rpx,
child: Text(
"取消".tr,
style: TextStyle(
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.only(top: 0),
onTap: () {
onConfirm(timeZones[tempIndex.value]);
Get.back();
},
child: Container(
alignment: Alignment.center,
width: 110.rpx,
height: 60.rpx,
child: Text(
"确定".tr,
style: TextStyle(
fontSize: 30.rpx,
color: themeController.currentColor.sc2,
),
),
),
),
],
),
),
SizedBox(height: 20.rpx),
Stack(
children: [
Positioned.fill(
child: IgnorePointer(
child: Center(
child: Container(
height: 90.rpx,
margin:
EdgeInsets.symmetric(horizontal: 95.rpx),
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius: BorderRadius.circular(16.rpx),
),
),
),
),
),
SizedBox(
height: 240.rpx,
child: getOnePickers(
context,
timeZones, // 传入字符串列表
tempIndex,
unit: "", // 时区不需要单位
),
),
],
),
],
),
),
),
),
),
],
);
},
);
}

View File

@@ -173,7 +173,7 @@ class _UpdatePageState extends State<UpdatePersonPage> {
children: [ children: [
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 141.rpx, 70.rpx, 0), 70.rpx, 70.rpx, 70.rpx, 0),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
height: 100.rpx, height: 100.rpx,
@@ -204,7 +204,12 @@ class _UpdatePageState extends State<UpdatePersonPage> {
letterSpacing: 0.0, letterSpacing: 0.0,
color: themeController.currentColor.sc3, color: themeController.currentColor.sc3,
), ),
hintText: '人员资料.名字输入提示'.tr, hintText: (personController.name.value
as String?)
?.isNotEmpty ==
true
? personController.name.value
: '体征检测设备'.tr,
hintStyle: TextStyle( hintStyle: TextStyle(
fontFamily: 'Inter', fontFamily: 'Inter',
fontSize: 26.rpx, fontSize: 26.rpx,
@@ -432,30 +437,77 @@ class _UpdatePageState extends State<UpdatePersonPage> {
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
personController.dateTime != null // 文字居中
? DateFormat("yyyy/MM/dd").format( Center(
personController.dateTime!) child: Row(
: '人员资料.生日输入提示'.tr, mainAxisSize: MainAxisSize.min,
textAlign: TextAlign.right, children: [
style: TextStyle( Text.rich(
fontFamily: 'Readex Pro', TextSpan(
color: personController.dateTime != null children: [
? themeController.currentColor.sc3 TextSpan(
: themeController.currentColor.sc4, text: personController
fontSize: .dateTime !=
AppConstants().normal_text_fontSize, null
letterSpacing: 0, ? DateFormat(
"yyyy/MM/dd")
.format(
personController
.dateTime!)
: '人员资料.生日输入提示'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.dateTime !=
null
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 50.rpx, 70.rpx, 0), 70.rpx, 25.rpx, 70.rpx, 0),
child: Container( child: Container(
height: 100.rpx, height: 100.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -500,31 +552,76 @@ class _UpdatePageState extends State<UpdatePersonPage> {
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
personController.height.value != "" // 文字居中
? personController.height.value + Center(
"cm".tr child: Row(
: '身高输入提示'.tr, mainAxisSize: MainAxisSize.min,
textAlign: TextAlign.right, children: [
style: TextStyle( Text.rich(
fontFamily: 'Readex Pro', TextSpan(
color: personController.height.value != children: [
"" TextSpan(
? themeController.currentColor.sc3 text: personController
: themeController.currentColor.sc4, .height.value !=
fontSize: ""
AppConstants().normal_text_fontSize, ? personController
letterSpacing: 0, .height.value +
"cm".tr
: '身高输入提示'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.height
.value !=
""
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 50.rpx, 70.rpx, 0), 70.rpx, 25.rpx, 70.rpx, 0),
child: Container( child: Container(
height: 100.rpx, height: 100.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -555,38 +652,193 @@ class _UpdatePageState extends State<UpdatePersonPage> {
personController.weight.value ?? "", personController.weight.value ?? "",
onConfirm: (int selectedWeight) { onConfirm: (int selectedWeight) {
personController.weight.value = personController.weight.value =
selectedWeight selectedWeight.toString();
.toString(); // ✅ 转成字符串
personController.updateAll(); personController.updateAll();
}, },
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
personController.weight.value != "" // 文字居中
? personController.weight.value + Center(
"kg".tr child: Row(
: '人员资料.体重输入提示'.tr, mainAxisSize: MainAxisSize.min,
textAlign: TextAlign.right, children: [
style: TextStyle( Text.rich(
fontFamily: 'Readex Pro', TextSpan(
color: personController.weight.value != children: [
"" TextSpan(
? themeController.currentColor.sc3 text: personController
: themeController.currentColor.sc4, .weight.value !=
fontSize: ""
AppConstants().normal_text_fontSize, ? personController
letterSpacing: 0, .weight.value +
"kg".tr
: '人员资料.体重输入提示'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.weight
.value !=
""
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 50.rpx, 70.rpx, 0), 70.rpx, 25.rpx, 70.rpx, 0),
child: Container(
height: 100.rpx,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.rpx),
border: Border.all(
color: themeController.currentColor.sc4
.withOpacity(0.5),
width: AppConstants().border_width,
),
),
child: InkWell(
onTap: () {
if (widget.status == BindType.share.code) {
TopSlideNotification.show(context,
text: "被分享用户只能修改用户名称",
textColor:
themeController.currentColor.sc9);
return;
}
final timeZone =
personController.timeZone.value;
final initialTimeZone = timeZone;
FocusScope.of(context)
.requestFocus(FocusNode());
Future.delayed(
const Duration(milliseconds: 250), () {
showTimeZonePickerDialog(
context,
title: "选择时区".tr,
initialTimeZone: initialTimeZone,
onConfirm: (String selectedtimezone) {
personController.timeZone.value =
selectedtimezone.toString();
personController.updateAll();
print("时区: $selectedtimezone");
},
);
});
},
child: Stack(
children: [
// 文字居中
Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text.rich(
TextSpan(
children: [
TextSpan(
text: personController
.timeZone
.value !=
""
? personController
.timeZone.value
: '选择时区'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: personController
.timeZone
.value !=
""
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
TextSpan(
text: ' *',
style: TextStyle(
color: themeController
.currentColor.sc9,
fontSize: AppConstants()
.normal_text_fontSize,
fontWeight:
FontWeight.bold,
),
),
],
),
),
],
),
),
// 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
),
),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
70.rpx, 25.rpx, 70.rpx, 0),
child: Container( child: Container(
height: 100.rpx, height: 100.rpx,
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -627,33 +879,80 @@ class _UpdatePageState extends State<UpdatePersonPage> {
title: "选择城市".tr, title: "选择城市".tr,
cityDataFuture: cityDataFuture:
cityDataFuture, // 传入预加载的数据 cityDataFuture, // 传入预加载的数据
colors: CitySelectionColors(
// pickerBackgroundColor:
// stringToColor("#003058"),
// confirmTextColor:
// stringToColor("#84F5FF"),
selectedCityColor:
themeController.currentColor.sc2,
selectedTextColor: Colors.white,
),
); );
}); });
}, },
child: Center( child: Stack(
child: Text( children: [
MyUtils.getDetailedCityDisplayText( // 文字居中
personController.cityModel), Center(
textAlign: TextAlign.right, child: Row(
style: TextStyle( mainAxisAlignment:
fontFamily: 'Readex Pro', MainAxisAlignment.center,
color: personController.cityModel != children: [
null Text(
? themeController.currentColor.sc3 MyUtils
: themeController.currentColor.sc4, .getDetailedCityDisplayText(
fontSize: personController
AppConstants().normal_text_fontSize, .cityModel),
letterSpacing: 0, textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Readex Pro',
color:
personController
.cityModel !=
null
? themeController
.currentColor.sc3
: themeController
.currentColor.sc4,
fontSize: AppConstants()
.normal_text_fontSize,
letterSpacing: 0,
),
),
// Text(
// ' *',
// style: TextStyle(
// color: themeController
// .currentColor.sc9,
// fontSize: AppConstants()
// .normal_text_fontSize,
// fontWeight: FontWeight.bold,
// ),
// ),
],
),
), ),
), // 箭头居右
Positioned(
right: 30.rpx,
top: 0,
bottom: 0,
child: Icon(
Icons.expand_more,
color:
themeController.currentColor.sc4,
size: 30.rpx,
),
),
],
), ),
), ),
), ),
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
0, 117.rpx, 0, 0), 0, 60.rpx, 0, 0),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
decoration: BoxDecoration(), decoration: BoxDecoration(),
@@ -858,5 +1157,4 @@ class _UpdatePageState extends State<UpdatePersonPage> {
onFailure: (res) {}, onFailure: (res) {},
); );
} }
} }

View File

@@ -127,18 +127,66 @@ class BarChartPainter extends CustomPainter {
final textPainter = TextPainter(textDirection: ui.TextDirection.ltr); final textPainter = TextPainter(textDirection: ui.TextDirection.ltr);
final stepValue = maxYValue / yStepCount; final stepValue = maxYValue / yStepCount;
// Y轴刻度
// for (int i = 0; i <= yStepCount; i++) {
// final value = stepValue * i;
// final y = topPadding + chartHeight - (value / maxYValue) * chartHeight;
// final dashPaint = Paint()
// ..color = Colors.grey.withOpacity(0.4)
// ..strokeWidth = 1.rpx;
// drawDashedLine(
// canvas, Offset(leftPadding, y), Offset(size.width, y), dashPaint);
// textPainter.text = TextSpan(
// text: value.toStringAsFixed(0),
// style: TextStyle(
// fontSize: 18.rpx,
// color: themeController.currentColor.sc4,
// ),
// );
// textPainter.layout();
// textPainter.paint(
// canvas,
// Offset(leftPadding - textPainter.width - 4, y - textPainter.height / 2),
// );
// }
// Y轴刻度 // Y轴刻度
for (int i = 0; i <= yStepCount; i++) { for (int i = 0; i <= yStepCount; i++) {
final value = stepValue * i; final value = stepValue * i;
final y = topPadding + chartHeight - (value / maxYValue) * chartHeight; final y = topPadding + chartHeight - (value / maxYValue) * chartHeight;
final dashPaint = Paint() // 判断是否是基线i == 0
..color = Colors.grey.withOpacity(0.4) final bool isBaseline = i == 0;
..strokeWidth = 1.rpx;
drawDashedLine( if (isBaseline) {
canvas, Offset(leftPadding, y), Offset(size.width, y), dashPaint); // 基线画实线
final baselinePaint = Paint()
..color = Colors.grey.withOpacity(0.6)
..strokeWidth = 1.rpx
..style = PaintingStyle.stroke;
canvas.drawLine(
Offset(leftPadding, y),
Offset(size.width, y),
baselinePaint,
);
} else {
// 其他刻度画虚线
final dashPaint = Paint()
..color = Colors.grey.withOpacity(0.4)
..strokeWidth = 1.rpx;
drawDashedLine(
canvas,
Offset(leftPadding, y),
Offset(size.width, y),
dashPaint,
);
}
// 绘制刻度文字
textPainter.text = TextSpan( textPainter.text = TextSpan(
text: value.toStringAsFixed(0), text: value.toStringAsFixed(0),
style: TextStyle( style: TextStyle(
@@ -163,14 +211,14 @@ class BarChartPainter extends CustomPainter {
final startHour = startDate.hour; final startHour = startDate.hour;
// 绘制X轴主线实线 // 绘制X轴主线实线
final xAxisPaint = Paint() // final xAxisPaint = Paint()
..color = Colors.grey.withOpacity(0.4) // ..color = Colors.grey.withOpacity(0.4)
..strokeWidth = 1.rpx; // ..strokeWidth = 1.rpx;
canvas.drawLine( // canvas.drawLine(
Offset(leftPadding, xAxisY), // Offset(leftPadding, xAxisY),
Offset(size.width, xAxisY), // Offset(size.width, xAxisY),
xAxisPaint, // xAxisPaint,
); // );
// 绘制左右两侧时间标签HH:mm格式 // 绘制左右两侧时间标签HH:mm格式
final leftLabel = DateFormat('HH:mm').format(startDate); final leftLabel = DateFormat('HH:mm').format(startDate);

File diff suppressed because it is too large Load Diff

View File

@@ -98,8 +98,9 @@ class _BreatheCardState extends State<BreatheCard>
BorderRadius.circular(AppConstants().normal_container_radius), BorderRadius.circular(AppConstants().normal_container_radius),
), ),
child: Padding( child: Padding(
padding: // padding:
EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx), // EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx),
padding: EdgeInsets.all(0),
child: Wrap( child: Wrap(
spacing: 23.rpx, spacing: 23.rpx,
runSpacing: 25.rpx, runSpacing: 25.rpx,
@@ -110,7 +111,8 @@ class _BreatheCardState extends State<BreatheCard>
_shouldAnimate && item['id'] == _highlightedId; _shouldAnimate && item['id'] == _highlightedId;
return SizedBox( return SizedBox(
width: (MediaQuery.of(context).size.width - 160.rpx) / 3, // width: (MediaQuery.of(context).size.width - 160.rpx) / 3,
width: (MediaQuery.of(context).size.width - 120.rpx) / 3,
child: AnimatedBuilder( child: AnimatedBuilder(
animation: _animationController ?? AlwaysStoppedAnimation(0), animation: _animationController ?? AlwaysStoppedAnimation(0),
builder: (context, child) { builder: (context, child) {
@@ -137,7 +139,7 @@ class _BreatheCardState extends State<BreatheCard>
), ),
); );
} catch (e) { } catch (e) {
es.EasyDartModule.logger.error("呼吸监测绘制异常${e}"); es.EasyDartModule.logger.error("呼吸卡片绘制异常${e}");
return Container(); return Container();
} }
} }

View File

@@ -100,15 +100,17 @@ class _HeartRateCardState extends State<HeartRateCard>
}).toList(); // 添加 .toList() }).toList(); // 添加 .toList()
return Container( return Container(
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( // decoration: BoxDecoration(
color: themeController.currentColor.sc5, // color: themeController.currentColor.sc5,
borderRadius: // borderRadius:
BorderRadius.circular(AppConstants().normal_container_radius), // BorderRadius.circular(AppConstants().normal_container_radius),
), // ),
child: Padding( child: Padding(
padding: // padding:
EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx), // EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx),
padding: EdgeInsets.all(0),
child: Wrap( child: Wrap(
alignment: WrapAlignment.spaceBetween,
spacing: 23.rpx, spacing: 23.rpx,
runSpacing: 25.rpx, runSpacing: 25.rpx,
children: List.generate(data.length, (index) { children: List.generate(data.length, (index) {
@@ -118,7 +120,7 @@ class _HeartRateCardState extends State<HeartRateCard>
_shouldAnimate && item['id'] == _highlightedId; _shouldAnimate && item['id'] == _highlightedId;
return SizedBox( return SizedBox(
width: (MediaQuery.of(context).size.width - 160.rpx) / 3, width: (MediaQuery.of(context).size.width - 120.rpx) / 3,
child: AnimatedBuilder( child: AnimatedBuilder(
animation: _animationController ?? AlwaysStoppedAnimation(0), animation: _animationController ?? AlwaysStoppedAnimation(0),
builder: (context, child) { builder: (context, child) {
@@ -145,7 +147,7 @@ class _HeartRateCardState extends State<HeartRateCard>
), ),
); );
} catch (e) { } catch (e) {
es.EasyDartModule.logger.error("心率监测绘制异常${e}"); es.EasyDartModule.logger.error("心率卡片绘制异常${e}");
return Container(); return Container();
} }
} }

View File

@@ -136,7 +136,8 @@ class _HeartRateStandardWidgetState extends State<HeartRateStandardWidget> {
14.rpx, 10.rpx, 14.rpx, 10.rpx), // 14.rpx, 10.rpx, 14.rpx, 10.rpx), //
borderRadius: 0.rpx, // 圆形点击区域 borderRadius: 0.rpx, // 圆形点击区域
onTap: () { onTap: () {
if (AppConstants().ent_type == APPPackageType.MHT.code) { if (AppConstants().ent_type ==
APPPackageType.MHT.code) {
showTipDialog( showTipDialog(
context, context,
Container( Container(

View File

@@ -104,54 +104,41 @@ class _SleepCardState extends State<SleepCard> with TickerProviderStateMixin {
.where((item) => item['show'] != false) .where((item) => item['show'] != false)
.toList(); .toList();
return Container( return Wrap(
width: double.infinity, alignment: WrapAlignment.spaceBetween,
decoration: BoxDecoration( spacing: 23.rpx,
color: themeController.currentColor.sc5, runSpacing: 25.rpx,
borderRadius: children: List.generate(data.length, (index) {
BorderRadius.circular(AppConstants().normal_container_radius), final item = data[index];
), item['showTip'] = true;
child: Padding( final bool isHighlighted =
padding: _shouldAnimate && item['id'] == _highlightedId;
EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx), return SizedBox(
child: Wrap( width: (MediaQuery.of(context).size.width - 120.rpx) / num,
alignment: WrapAlignment.center, child: AnimatedBuilder(
spacing: 23.rpx, animation: _animationController ?? AlwaysStoppedAnimation(0),
runSpacing: 25.rpx, builder: (context, child) {
children: List.generate(data.length, (index) { return Container(
final item = data[index]; key: isHighlighted ? _highlightKey : null,
item['showTip'] = true; decoration: isHighlighted
final bool isHighlighted = ? BoxDecoration(
_shouldAnimate && item['id'] == _highlightedId; border: Border.all(
return SizedBox( color: themeController.currentColor.sc2
width: (MediaQuery.of(context).size.width - 160.rpx) / num, .withOpacity(_animationController?.value ?? 0),
child: AnimatedBuilder( width: 1.rpx,
animation: _animationController ?? AlwaysStoppedAnimation(0), ),
builder: (context, child) { borderRadius: BorderRadius.circular(8),
return Container( )
key: isHighlighted ? _highlightKey : null, : null,
decoration: isHighlighted child: SleepDataModuleWidget(
? BoxDecoration( data: item,
border: Border.all( sleepReportData: widget.sleepReport,
color: themeController.currentColor.sc2 ),
.withOpacity( );
_animationController?.value ?? 0), },
width: 1.rpx, ),
), );
borderRadius: BorderRadius.circular(8), }),
)
: null,
child: SleepDataModuleWidget(
data: item,
sleepReportData: widget.sleepReport,
),
);
},
),
);
}),
),
),
); );
} catch (e) { } catch (e) {
es.EasyDartModule.logger.error("数据卡片渲染异常${e}"); es.EasyDartModule.logger.error("数据卡片渲染异常${e}");

View File

@@ -70,6 +70,22 @@ class _SleepViewWidgetState extends State<SleepViewWidget> {
// "name": "rem", // "name": "rem",
// "color": "#FFC0CB", // "color": "#FFC0CB",
// }); // });
// List typeZeroStages =
// stages.where((stage) => stage['type'] == 0).toList();
// List snoreStages = stages.where((stage) => stage['type'] == 5).toList();
// for (int i = 0; i < typeZeroStages.length; i++) {
// var stage = typeZeroStages[i];
// int st = stage['st'];
// int et = stage['et'];
// // 转换为DateTime
// DateTime stDate = DateTime.fromMillisecondsSinceEpoch(st);
// DateTime etDate = DateTime.fromMillisecondsSinceEpoch(et);
// // 一行打印所有信息
// print(
// '离床元素 ${i + 1}: st=${formatDate(stDate)} et=${formatDate(etDate)}');
// }
return Container( return Container(
width: double.infinity, width: double.infinity,
@@ -306,7 +322,7 @@ class _SleepViewWidgetState extends State<SleepViewWidget> {
), ),
), ),
SizedBox( SizedBox(
height: 49.rpx, height: 70.rpx,
), ),
Padding( Padding(
padding: EdgeInsetsDirectional.fromSTEB( padding: EdgeInsetsDirectional.fromSTEB(
@@ -359,8 +375,13 @@ class _SleepViewWidgetState extends State<SleepViewWidget> {
), ),
); );
} catch (e) { } catch (e) {
es.EasyDartModule.logger.error("打鼾监测绘制异常${e}"); es.EasyDartModule.logger.error("睡眠规律性异常${e}");
return Container(); return Container();
} }
} }
String formatDate(DateTime date) {
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} '
'${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}:${date.second.toString().padLeft(2, '0')}';
}
} }