// import 'dart:async'; // import 'dart:ui' as ui; // import 'package:EasyDartModule/EasyDartModule.dart' as edm; // import 'package:ef/ef.dart'; // import 'package:flutter/material.dart'; // import 'package:flutter/services.dart'; // import 'package:flutter_svg/svg.dart'; // import 'package:flutterflow_ui/flutterflow_ui.dart'; // import 'package:vbvs_app/common/color/appConstants.dart'; // import 'package:vbvs_app/common/util/CommonVariables.dart'; // import 'package:vbvs_app/common/util/DailyLogUtils.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/component/tool/CustomCard.dart'; // import 'package:vbvs_app/component/tool/NewTopSlideNotification.dart'; // import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart'; // import 'package:vbvs_app/controller/device/device_type_controller.dart'; // import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; // import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; // import 'package:vbvs_app/controller/user_info_controller.dart'; // import 'package:vbvs_app/enum/APPQuickCheckStatus.dart'; // import 'package:vbvs_app/model/WebSocketMessage.dart'; // import 'package:vbvs_app/pages/device/component/DeviceStatusInfoWidget.dart'; // import 'package:vbvs_app/pages/device/component/health_experience_tool.dart'; // import 'package:vbvs_app/pages/device_bind/componnet/CalibrationProgressWidget.dart'; // import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; // import 'package:vibration/vibration.dart'; // import 'component/SpeedControlledGif.dart'; // class HealthCheckPage extends StatefulWidget { // var personInfo; // HealthCheckPage({super.key, required this.personInfo}); // @override // State createState() => _HealthCheckPageState(); // } // class _HealthCheckPageState extends State // with WidgetsBindingObserver { // GlobalController globalController = Get.find(); // UserInfoController userInfoController = Get.find(); // BlueteethBindController blueteethBindController = Get.find(); // ThemeController themeController = Get.find(); // DeviceTypeController deviceTypeController = Get.find(); // int maxBodyMotion = 1; // String breathState = "-"; // String inBed = "-"; // String onlineState = "离线".tr; // Timer? _onlineTimer; // 添加 Timer 引用 // int bodyMotion = -1; // int breathrate = -1; // String snores = "-"; // int heartrate = -1; // final ValueNotifier progressNotifier = ValueNotifier(0.0); // final ValueNotifier failureNotifier = ValueNotifier(false); // Timer? _checkStatusTimer; // 添加状态查询定时器 // bool _isInitialized = false; // 添加初始化标志 // @override // void initState() { // WidgetsBinding.instance.addObserver(this); // 添加生命周期观察者 // try { // deviceTypeController // .checkReportStatus(widget.personInfo['mac']) // .then((_) { // setState(() { // _isInitialized = true; // }); // // 如果当前状态是体验中,启动定时器 // if (deviceTypeController.experience_status.value == 200 && // deviceTypeController.own.value) { // _startCheckStatusTimer(); // } // }); // } catch (e) { // ef.log("快检初始化数据失败"); // } // _initWebSocket(); // super.initState(); // } // Future _initWebSocket() async { // // 发送WebSocket请求 // try { // Future.delayed(Duration(seconds: 0), () { // CommonVariables.callMap["/vsbs/web/rt/marttress"] = (data) { // edm.EasyDartModule.logger.info("[websocket]实时体征页面数据-->${data}]"); // ef.log("[websocket]实时体征页面数据-->${data}]"); // if (data['status'] == "离线") { // inBed = "-"; // bodyMotion = -1; // heartrate = -1; // snores = "-"; // breathrate = -1; // breathState = "-"; // onlineState = "离线".tr; // return; // } // inBed = data["inBed"]; // // 心率 呼吸 体动 呼吸暂停 // if ("离床".tr == inBed) { // breathState = "否".tr; // bodyMotion = 0; // breathrate = 0; // heartrate = 0; // snores = "否".tr; // } else { // onlineState = "在线".tr; // 接收到数据,设置为在线 // breathState = // data["breathState"] == null || data["breathState"] == "" // ? "-" // : data["breathState"].toString().tr; // bodyMotion = data['bodyMotion'] == null ? -1 : data['bodyMotion']; // breathrate = data["breathRate"] == null ? -1 : data["breathRate"]; // heartrate = data['heartRate'] == null ? -1 : data['heartRate']; // snores = data['snores'] == null || // data['snores'] == "" || // data['snores'] == "否".tr // ? "否".tr // : "${data['snores']}".tr; // } // if (mounted) { // setState(() { // onlineState = "在线".tr; // 接收到数据,设置为在线 // }); // } // _startOnlineTimer(); // 重置定时器 // }; // }); // } catch (e) { // print(e); // edm.EasyDartModule.logger // .error("[webscoekt]格式化数据错误-->${{"mac": widget.personInfo['mac']}}"); // } // if (widget.personInfo['status'] != null) { // try { // onlineState = // widget.personInfo['status']['status'] == 1 ? "在线".tr : "离线".tr; // if (widget.personInfo['status']['status'] != 0) { // inBed = widget.personInfo['status']['inBed'] == 1 ? "在床".tr : "离床".tr; // } // } catch (e) { // edm.EasyDartModule.logger // .error("[webscoekt]格式化数据错误-->${{"mac": widget.personInfo['mac']}}"); // } // } // edm.EasyDartModule.logger // .info("[webscoekt]发送请求:数据-->${{"mac": widget.personInfo['mac']}}"); // DailyLogUtils.writeLog( // "[webscoekt]发送请求:数据-->${{"mac": widget.personInfo['mac']}}"); // edm.EasyDartModule.websocket.sendData(jsonEncode(WebSocketMessage( // path: "/vsbs/web/rt/marttress", // type: 1, // data: {"mac": widget.personInfo['mac']}))); // await Future.delayed(Duration(seconds: 3)); // edm.EasyDartModule.websocket.sendData(jsonEncode(WebSocketMessage( // path: "/vsbs/web/rt/marttress", // type: 1, // data: {"mac": widget.personInfo['mac']}))); // _startOnlineTimer(); // } // //y // @override // void dispose() { // WidgetsBinding.instance.removeObserver(this); // 移除生命周期观察者 // _onlineTimer?.cancel(); // _checkStatusTimer?.cancel(); // 取消状态查询定时器 // _closeWebSocket(); // CommonVariables.callMap.remove("/vsbs/web/rt/marttress"); // super.dispose(); // } // // 监听应用生命周期变化 // @override // void didChangeAppLifecycleState(AppLifecycleState state) { // if (state == AppLifecycleState.resumed) { // // 应用回到前台时重新连接WebSocket // edm.EasyDartModule.logger.info("app切回页面,重连websocket"); // _initWebSocket(); // _initWebSocket(); // // 重新查询状态,然后根据状态决定是否启动定时器 // deviceTypeController // .checkReportStatus(widget.personInfo['mac']) // .then((_) { // // 如果当前状态是体验中,重新启动定时器 // if (deviceTypeController.experience_status.value != 404 && // deviceTypeController.own.value) { // _startCheckStatusTimer(); // } // }); // } else if (state == AppLifecycleState.paused) { // // 应用进入后台时关闭WebSocket和定时器 // _closeWebSocket(); // _checkStatusTimer?.cancel(); // } // } // void _startOnlineTimer() { // _onlineTimer?.cancel(); // 取消之前的定时器 // _onlineTimer = Timer.periodic(Duration(seconds: 60), (timer) { // if (mounted) { // setState(() { // edm.EasyDartModule.logger.info("60 秒内没有接收到数据,设置为离线"); // onlineState = "离线".tr; // 30 秒内没有接收到数据,设置为离线 // inBed = "-"; // bodyMotion = -1; // heartrate = -1; // snores = "-"; // breathrate = -1; // breathState = "-"; // }); // } // }); // } // @override // Widget build(BuildContext context) { // Map device = widget.personInfo; // return LayoutBuilder( // builder: (context, bodySize) => GestureDetector( // // onTap: () => FocusScope.of(context).unfocus(),, // child: Container( // decoration: BoxDecoration( // image: DecorationImage( // image: AssetImage(getBackgroundImageNoImage()), // fit: BoxFit.fill, // ), // ), // child: Scaffold( // backgroundColor: Colors.transparent, // appBar: AppBar( // systemOverlayStyle: SystemUiOverlayStyle( // statusBarColor: Colors.transparent, // 状态栏背景色 // statusBarIconBrightness: Brightness.light, // 图标颜色(Android) // statusBarBrightness: Brightness.light, // 图标颜色(iOS) // ), // backgroundColor: themeController.currentColor.sc17, // automaticallyImplyLeading: false, // iconTheme: IconThemeData(color: themeController.currentColor.sc3), // titleSpacing: 0.rpx, // title: Container( // width: double.infinity, // height: 180.rpx, // child: Stack( // alignment: Alignment.center, // children: [ // RichText( // text: TextSpan( // style: TextStyle( // fontFamily: 'Readex Pro', // color: themeController.currentColor.sc3, // fontSize: 30.rpx, // letterSpacing: 0.0, // ), // children: [ // TextSpan( // text: '健康快检'.tr, // ), // ], // ), // ), // Positioned( // left: 0.rpx, // child: returnIconButtom, // ), // Obx(() { // return deviceTypeController.experience_status.value != // 200 || // !deviceTypeController.own.value // ? Positioned( // right: 0.rpx, // child: ClickableContainer( // backgroundColor: Colors.transparent, // highlightColor: Colors.transparent, // padding: EdgeInsets.fromLTRB( // 20.rpx, 20.rpx, 20.rpx, 20.rpx), // onTap: () async { // Get.toNamed('/healthExperienceHistory', // arguments: widget.personInfo); // }, // child: SvgPicture.asset( // 'assets/img/icon/history.svg', // width: 35.rpx, // height: 35.rpx, // color: themeController.currentColor.sc3, // ), // ), // ) // : Container(); // }) // ], // ), // ), // actions: [], // centerTitle: false, // ), // body: SafeArea( // top: true, // child: Obx(() { // return Stack( // children: [ // Align( // alignment: Alignment.center, // child: FractionallySizedBox( // heightFactor: 0.5, // widthFactor: 0.5, // child: Opacity( // opacity: 0.7, // child: (onlineState == "离线".tr || inBed == '离床'.tr) // ? Image.asset( // 'assets/img/black_body_still.png', // fit: BoxFit.contain, // ) // : SpeedControlledGif( // 'assets/img/body_black.gif', // speedFactor: // 2, // 2.0 for 2x speed, 0.5 for half speed // fit: BoxFit.contain, // ), // ), // ), // ), // // 其余内容放在上层 // Positioned.fill( // child: Padding( // padding: EdgeInsetsDirectional.fromSTEB( // 0.rpx, 29.rpx, 0.rpx, 0.rpx), // child: Column( // mainAxisSize: MainAxisSize.max, // children: [ // if (deviceTypeController // .experience_status.value != // 200 || // !deviceTypeController.own.value) // Padding( // padding: EdgeInsetsDirectional.fromSTEB( // 30.rpx, 0.rpx, 30.rpx, 100.rpx), // child: ClickableContainer( // backgroundColor: // themeController.currentColor.sc5, // highlightColor: // Colors.transparent, // 点击涟漪颜色 // borderRadius: AppConstants() // .normal_container_radius, // 如果你想加圆角可以设置 eg. 12.rpx // padding: EdgeInsets.zero, // onTap: () { // print('点击了体征卡片'); // }, // child: Column( // children: [ // Container( // padding: EdgeInsets.fromLTRB( // 37.rpx, 37.rpx, 20.rpx, 37.rpx), // child: Row( // mainAxisSize: MainAxisSize.max, // crossAxisAlignment: // CrossAxisAlignment.start, // children: [ // // 左侧列 - 标签和值 // Expanded( // flex: 3, // child: Column( // crossAxisAlignment: // CrossAxisAlignment.start, // children: [ // // 姓名行 // Row( // crossAxisAlignment: // CrossAxisAlignment // .center, // children: [ // // 标签 - 也不能换行,超出显示... // Expanded( // flex: 3, // child: Text( // '实时体征.姓名'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc4, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // SizedBox( // width: 20 // .rpx), // 标签和值之间的间距 // // 值 // Expanded( // flex: 4, // child: Text( // device['person'] != // null && // device['person'][ // 'name'] != // null && // device['person'] // [ // 'name'] // .toString() // .trim() // .isNotEmpty // ? device['person'] // ['name'] // .toString() // : '体征检测设备'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc3, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // ], // ), // SizedBox(height: 36.rpx), // // 性别行 // Row( // crossAxisAlignment: // CrossAxisAlignment // .center, // children: [ // Expanded( // flex: 3, // child: Text( // '性别'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc4, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // SizedBox(width: 20.rpx), // Expanded( // flex: 4, // child: Text( // device['person'] != // null && // device['person'] // [ // 'gender'] != // null && // device['person'] // [ // 'gender'] // .toString() // .trim() // .isNotEmpty // ? getGenderText( // device['person'] // [ // 'gender']) // : '-'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc3, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // ], // ), // SizedBox(height: 36.rpx), // // 身高行 // Row( // crossAxisAlignment: // CrossAxisAlignment // .center, // children: [ // Expanded( // flex: 3, // child: Text( // '身高'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc4, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // SizedBox(width: 20.rpx), // Expanded( // flex: 4, // child: Text( // device['person'] != // null && // device['person'] // [ // 'height'] != // null && // device['person'] // [ // 'height'] // .toString() // .trim() // .isNotEmpty // ? '${device['person']['height']}cm' // : '-'.tr + "cm", // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc3, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // ], // ), // ], // ), // ), // SizedBox( // width: 30.rpx), // 左右两列之间的间距 // // 右侧列 - 标签和值 // Expanded( // flex: 4, // child: Column( // crossAxisAlignment: // CrossAxisAlignment.start, // children: [ // // 设备ID行 // Row( // crossAxisAlignment: // CrossAxisAlignment // .center, // children: [ // Expanded( // flex: 1, // child: Text( // '实时体征.设备ID'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc4, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // SizedBox(width: 20.rpx), // Expanded( // flex: 2, // child: Text( // '${device['code'] ?? '未知数据'.tr}', // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc3, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // ], // ), // SizedBox(height: 36.rpx), // // 年龄行 // Row( // crossAxisAlignment: // CrossAxisAlignment // .center, // children: [ // Expanded( // flex: 1, // child: Text( // '年龄'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc4, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // SizedBox(width: 20.rpx), // Expanded( // flex: 2, // child: Text( // device['person'] != // null && // device['person'] // [ // 'birthday'] != // null && // device['person'] // [ // 'birthday'] // .toString() // .trim() // .isNotEmpty // ? calculateAge(device[ // 'person'] // [ // 'birthday'] // .toString()) // : '-'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc3, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // ], // ), // SizedBox(height: 36.rpx), // // 体重行 // Row( // crossAxisAlignment: // CrossAxisAlignment // .center, // children: [ // Expanded( // flex: 1, // child: Text( // '体重'.tr, // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc4, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // SizedBox(width: 20.rpx), // Expanded( // flex: 2, // child: Text( // device['person'] != // null && // device['person'] // [ // 'weight'] != // null && // device['person'] // [ // 'weight'] // .toString() // .trim() // .isNotEmpty // ? '${device['person']['weight']}kg' // : '-'.tr + "kg", // style: TextStyle( // fontFamily: // 'Inter', // fontSize: 26.rpx, // color: themeController // .currentColor // .sc3, // ), // maxLines: 1, // overflow: // TextOverflow // .ellipsis, // ), // ), // ], // ), // ], // ), // ), // ], // ), // ), // ], // ), // ), // ), // if (deviceTypeController // .experience_status.value == // 200 && // deviceTypeController.own.value) // Padding( // padding: // EdgeInsets.fromLTRB(46.rpx, 0, 46.rpx, 0), // child: Column( // children: [ // SizedBox( // height: 103.rpx, // ), // Text( // "快检中...".tr, // style: TextStyle( // color: // themeController.currentColor.sc1, // fontSize: AppConstants() // .title_text_fontSize, // ), // ), // SizedBox( // height: 30.rpx, // ), // Text( // "MAC号".tr + // ": ${widget.personInfo['mac'] ?? '未知数据'.tr}", // style: TextStyle( // color: // themeController.currentColor.sc4, // fontSize: AppConstants() // .smaller_text_fontSize, // ), // ), // SizedBox( // height: 4.rpx, // ), // Text( // "睡眠报告提示".tr, // style: TextStyle( // color: // themeController.currentColor.sc4, // fontSize: AppConstants() // .smaller_text_fontSize, // ), // ), // SizedBox( // height: 48.rpx, // ), // ], // ), // ), // Expanded( // child: SingleChildScrollView( // child: deviceTypeController // .experience_status.value != // 200 || // !deviceTypeController.own.value // ? Container() // : Column( // children: [ // Padding( // padding: // EdgeInsetsDirectional.fromSTEB( // 30.rpx, 0, 30.rpx, 0), // child: Container( // child: Column( // children: [ // Row( // mainAxisAlignment: // MainAxisAlignment // .spaceBetween, // children: [ // DeviceStatusInfoWidget( // title: "在离床".tr, // iconAsset: // "assets/img/icon/bed_status.svg", // value: inBed, // ), // DeviceStatusInfoWidget( // title: "体动".tr, // iconAsset: // "assets/img/icon/bodymotion.svg", // value: inBed == "离床".tr // ? ("-") // : (bodyMotion == // null || // bodyMotion == // -1) // ? "-" // : "$bodyMotion", // ), // ], // ), // Row( // mainAxisAlignment: // MainAxisAlignment // .spaceBetween, // children: [ // DeviceStatusInfoWidget( // title: "心率".tr, // iconAsset: // "assets/img/icon/heart.svg", // value: inBed == "离床".tr // ? "-" // : ((heartrate == // null || // heartrate == // -1) // ? "-" // : "$heartrate"), // ), // DeviceStatusInfoWidget( // title: "打鼾".tr, // iconAsset: // "assets/img/icon/snore.svg", // value: inBed == "离床".tr // ? "-" // : ('${snores}'.tr), // ), // ], // ), // Row( // mainAxisAlignment: // MainAxisAlignment // .spaceBetween, // children: [ // DeviceStatusInfoWidget( // title: "呼吸".tr, // iconAsset: // "assets/img/icon/breathe.svg", // value: inBed == "离床".tr // ? ("-") // : ((breathrate == // null || // breathrate == // -1) // ? "-" // : "$breathrate"), // ), // DeviceStatusInfoWidget( // title: "呼吸暂停".tr, // iconAsset: // "assets/img/icon/breathe_pause.svg", // value: inBed == "离床".tr // ? "-" // : ('${breathState}'), // ), // ], // ), // ].divide( // SizedBox(height: 49.rpx)), // ), // ), // ), // Padding( // padding: // EdgeInsetsDirectional.fromSTEB( // 0.rpx, // 67.rpx, // 0.rpx, // 0.rpx), // child: Container( // height: 40.rpx, // child: Text( // bodyMotion >= maxBodyMotion // ? '请保持静止'.tr // : "", // style: TextStyle( // fontFamily: 'Inter', // fontSize: 26.rpx, // letterSpacing: 0.0, // color: themeController // .currentColor.sc9, // ), // ), // ), // ), // // SizedBox( // // height: 207.rpx, // // ), // ], // ), // )), // if (deviceTypeController // .experience_status.value != // 200 || // !deviceTypeController.own.value) // ClickableContainer( // backgroundColor: // Colors.transparent, // 可自定义背景色 // highlightColor: Colors.transparent, // 点击涟漪颜色 // borderRadius: 16.rpx, // 圆角大小,可按需调整 // padding: EdgeInsetsDirectional.fromSTEB( // 30.rpx, 0.rpx, 30.rpx, 0.rpx), // onTap: () {}, // child: Container( // padding: EdgeInsetsDirectional.fromSTEB( // 26.rpx, 26.rpx, 26.rpx, 26.rpx), // decoration: BoxDecoration( // // color: FlutterFlowTheme.of(context) // // .primaryBackground // // .withOpacity(0.6), // 半透明背景 // borderRadius: // BorderRadius.circular(16.rpx), // border: Border.all( // color: themeController.currentColor.sc4 // .withOpacity(0.5), // width: 0.5.rpx, // ), // ), // child: Row( // crossAxisAlignment: // CrossAxisAlignment.start, // children: [ // Padding( // padding: // EdgeInsetsDirectional.fromSTEB( // 0, 8.rpx, 0, 0), // child: Container( // width: 23.rpx, // height: 23.rpx, // // width: double.infinity, // decoration: BoxDecoration(), // child: SvgPicture.asset( // 'assets/img/icon/tips.svg', // fit: BoxFit.cover, // color: themeController // .currentColor.sc4, // ), // ), // ), // Expanded( // child: Text( // '使用方式:人员使用健康快检功能时,只需平躺或坐在正常运行中的体征传感器传感器上方,保持静止,然后点击“启动快检”,待进度条完成,即可得出快检报告。' // .tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // color: themeController // .currentColor.sc4, // ), // ), // ), // ].divide(SizedBox(width: 23.rpx)), // ), // ), // ), // SizedBox( // height: 40.rpx, // ), // if (deviceTypeController // .experience_status.value != // 200 || // !deviceTypeController.own.value) // Padding( // padding: EdgeInsets.fromLTRB( // 100.rpx, 0, 100.rpx, 0), // child: Column( // children: [ // CustomCard( // borderRadius: AppConstants() // .button_container_radius, // 圆角半径 // onTap: () async { // // HapticFeedback.lightImpact(); // bool canStart = // await deviceTypeController // .checkReportStatus( // widget.personInfo['mac']); // // if (!canStart) { // // NewTopSlideNotification.show( // // text: "设备正在快检中,请稍后再试!".tr, // // textColor: themeController // // .currentColor.sc9); // // return; // // } // if (!deviceTypeController.own.value && // deviceTypeController // .experience_status // .value == // APPQuickCheckStatus // .inProgress.value) { // NewTopSlideNotification.show( // text: "设备正在快检中,请稍后再试!".tr, // textColor: themeController // .currentColor.sc9); // return; // } // bool opRes = // await deviceTypeController // .qcCheckControl( // widget.personInfo, 1); // if (!opRes) { // return; // } // deviceTypeController // .experience_percent.value = 0; // progressNotifier.value = 0; // deviceTypeController // .experience_status.value = 200; // _startCheckStatusTimer(); // deviceTypeController.updateAll(); // }, // colors: AppConstants() // .thNormalButton, // 渐变色是同一个色,也可以根据需要调整 // child: Container( // width: // // MediaQuery.sizeOf(context).width * 0.66, // bodySize.maxWidth, // height: MediaQuery.sizeOf(context) // .height * // 0.055, // constraints: BoxConstraints( // minWidth: 500.rpx, // minHeight: 90.rpx, // ), // child: Row( // mainAxisSize: MainAxisSize.max, // mainAxisAlignment: // MainAxisAlignment.center, // children: [ // Text( // '开始快检'.tr, // style: TextStyle( // color: themeController // .currentColor.sc3, // fontFamily: 'Inter', // fontSize: AppConstants() // .normal_text_fontSize, // letterSpacing: 0.0, // ), // ), // ].divide(SizedBox( // width: 17.rpx, // )), // ), // ), // ), // ], // ), // ), // if (deviceTypeController // .experience_status.value == // 200 && // deviceTypeController.own.value) // Padding( // padding: EdgeInsetsDirectional.fromSTEB( // 100.rpx, 0.rpx, 100.rpx, 60.rpx), // child: CalibrationProgressWidget( // progressNotifier: progressNotifier, // failureNotifier: failureNotifier, // ), // ), // if (deviceTypeController // .experience_status.value == // 200 && // deviceTypeController.own.value) // Padding( // padding: EdgeInsets.fromLTRB( // 100.rpx, 0, 100.rpx, 0), // child: Column( // children: [ // CustomCard( // borderRadius: AppConstants() // .button_container_radius, // 圆角半径 // onTap: () { // showCancelConfirmDialog( // context, widget.personInfo); // }, // colors: [ // themeController.currentColor.sc9 // ], // 渐变色是同一个色,也可以根据需要调整 // child: Container( // width: // // MediaQuery.sizeOf(context).width * 0.66, // bodySize.maxWidth, // height: MediaQuery.sizeOf(context) // .height * // 0.055, // constraints: BoxConstraints( // minWidth: 500.rpx, // minHeight: 90.rpx, // ), // child: Row( // mainAxisSize: MainAxisSize.max, // mainAxisAlignment: // MainAxisAlignment.center, // children: [ // Text( // '终止'.tr, // style: TextStyle( // color: themeController // .currentColor.sc3, // fontFamily: 'Inter', // fontSize: AppConstants() // .normal_text_fontSize, // letterSpacing: 0.0, // ), // ), // ].divide(SizedBox( // width: 17.rpx, // )), // ), // ), // ), // ], // ), // ), // SizedBox( // height: 40.rpx, // ), // SizedBox( // height: 26.rpx, // ), // ], // ), // ), // ), // ], // ); // })), // ), // ), // ), // ); // } // void _closeWebSocket() { // // 取消WebSocket订阅 // edm.EasyDartModule.websocket.sendData( // jsonEncode(WebSocketMessage(path: "/vsbs/web/rt/marttress", type: 2))); // _onlineTimer?.cancel(); // } // // 开始状态查询定时器 // void _startCheckStatusTimer() { // _checkStatusTimer?.cancel(); // 取消之前的定时器 // _checkStatusTimer = Timer.periodic(Duration(seconds: 3), (timer) { // if (mounted) { // edm.EasyDartModule.logger.info("定时查询快检状态"); // deviceTypeController // .checkReportStatus(widget.personInfo['mac']) // .then((_) async { // // 如果状态变回404(非体验中),停止定时器 // progressNotifier.value = // deviceTypeController.experience_percent.value.toDouble(); // deviceTypeController.updateAll(); // if (deviceTypeController.experience_status.value == // APPQuickCheckStatus.completed.value) { // //体验正常结束 // try { // deviceTypeController.experience_status.value = 404; // deviceTypeController.experience_status.value = 0; // progressNotifier.value = 0; // edm.EasyDartModule.logger.info("快检结束,停止定时查询"); // _checkStatusTimer?.cancel(); // Map data = { // "id": deviceTypeController.experience_id.value, // "mac": widget.personInfo['mac'] // }; // // await deviceTypeController.getCheckHistory( // // id: deviceTypeController.experience_id.value, // // mac: widget.personInfo['mac']); // bool hasVibrator = await Vibration.hasVibrator(); // if (hasVibrator) { // // 震动1000毫秒(1秒) // Vibration.vibrate(duration: 500); // } // Get.toNamed('/healthQuickCheckReportPage', arguments: data); // } catch (e) { // edm.EasyDartModule.logger.error("快检报告页面加载失败---?${e.toString()}"); // } // } // if (deviceTypeController.experience_status.value == // APPQuickCheckStatus.timeout.value || // deviceTypeController.experience_status.value == // APPQuickCheckStatus.calculateError.value || // deviceTypeController.experience_status.value == // APPQuickCheckStatus.insufficientData.value) { // // 根据状态码获取对应的枚举 // APPQuickCheckStatus? status = APPQuickCheckStatusExtension.fromInt( // deviceTypeController.experience_status.value); // // 获取对应的状态描述文字 // String statusMessage = status?.description ?? "体验异常结束".tr; // //体验异常结束 // deviceTypeController.experience_status.value = 404; // deviceTypeController.experience_percent.value = 0; // progressNotifier.value = 0; // edm.EasyDartModule.logger // .info("快检结束,停止定时查询 - 状态: ${status?.description}"); // _checkStatusTimer?.cancel(); // await showTipDialog( // context, // Text( // statusMessage, // style: TextStyle( // color: Colors.white, // ), // ), // ); // } // if (!deviceTypeController.own.value) { // _checkStatusTimer?.cancel(); // } // }); // } // }); // } // } import 'dart:async'; import 'dart:ui' as ui; import 'package:EasyDartModule/EasyDartModule.dart' as edm; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/util/CommonVariables.dart'; import 'package:vbvs_app/common/util/DailyLogUtils.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/component/tool/CustomCard.dart'; import 'package:vbvs_app/component/tool/NewTopSlideNotification.dart'; import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart'; import 'package:vbvs_app/controller/device/device_type_controller.dart'; import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/controller/user_info_controller.dart'; import 'package:vbvs_app/enum/APPQuickCheckStatus.dart'; import 'package:vbvs_app/model/WebSocketMessage.dart'; import 'package:vbvs_app/pages/device/component/DeviceStatusInfoWidget.dart'; import 'package:vbvs_app/pages/device/component/health_experience_tool.dart'; import 'package:vbvs_app/pages/device_bind/componnet/CalibrationProgressWidget.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; import 'package:vibration/vibration.dart'; import 'component/SpeedControlledGif.dart'; class HealthCheckPage extends StatefulWidget { var personInfo; HealthCheckPage({super.key, required this.personInfo}); @override State createState() => _HealthCheckPageState(); } class _HealthCheckPageState extends State with WidgetsBindingObserver, SingleTickerProviderStateMixin { GlobalController globalController = Get.find(); UserInfoController userInfoController = Get.find(); BlueteethBindController blueteethBindController = Get.find(); ThemeController themeController = Get.find(); DeviceTypeController deviceTypeController = Get.find(); int maxBodyMotion = 1; String breathState = "-"; String inBed = "-"; String onlineState = "离线".tr; Timer? _onlineTimer; int bodyMotion = -1; int breathrate = -1; String snores = "-"; int heartrate = -1; final ValueNotifier progressNotifier = ValueNotifier(0.0); final ValueNotifier failureNotifier = ValueNotifier(false); Timer? _checkStatusTimer; bool _isInitialized = false; // 动画控制器 late AnimationController _animationController; // 顶部动画:从上往下滑动 late Animation _topSlideAnimation; // 左侧容器动画:从左向右滑动 late Animation _leftSlideAnimation; // 右侧容器动画:从右向左滑动 late Animation _rightSlideAnimation; @override void initState() { // 初始化动画控制器 _animationController = AnimationController( duration: const Duration(milliseconds: 400), vsync: this, ); // 顶部下滑动画:从顶部滑入 _topSlideAnimation = Tween( begin: const Offset(0, -1), end: Offset.zero, ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeOutCubic, )); // 左侧滑动动画:从左向右 _leftSlideAnimation = Tween( begin: const Offset(-1, 0), end: Offset.zero, ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeOutCubic, )); // 右侧滑动动画:从右向左 _rightSlideAnimation = Tween( begin: const Offset(1, 0), end: Offset.zero, ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeOutCubic, )); WidgetsBinding.instance.addObserver(this); try { deviceTypeController .checkReportStatus(widget.personInfo['mac']) .then((_) { setState(() { _isInitialized = true; }); if (deviceTypeController.experience_status.value == 200 && deviceTypeController.own.value) { _startCheckStatusTimer(); // 如果已经在体验中,直接播放动画 _animationController.forward(); } }); } catch (e) { ef.log("快检初始化数据失败"); } _initWebSocket(); // 监听状态变化,控制动画 ever(deviceTypeController.experience_status, (status) { final isExperiencing = status == 200 && deviceTypeController.own.value; if (isExperiencing) { _animationController.forward(); } else { _animationController.reverse(); } }); ever(deviceTypeController.own, (own) { final isExperiencing = deviceTypeController.experience_status.value == 200 && own; if (isExperiencing) { _animationController.forward(); } else { _animationController.reverse(); } }); super.initState(); } Future _initWebSocket() async { try { Future.delayed(Duration(seconds: 0), () { CommonVariables.callMap["/vsbs/web/rt/marttress"] = (data) { edm.EasyDartModule.logger.info("[websocket]实时体征页面数据-->${data}]"); ef.log("[websocket]实时体征页面数据-->${data}]"); if (data['status'] == "离线") { inBed = "-"; bodyMotion = -1; heartrate = -1; snores = "-"; breathrate = -1; breathState = "-"; onlineState = "离线".tr; return; } inBed = data["inBed"]; if ("离床".tr == inBed) { breathState = "否".tr; bodyMotion = 0; breathrate = 0; heartrate = 0; snores = "否".tr; } else { onlineState = "在线".tr; breathState = data["breathState"] == null || data["breathState"] == "" ? "-" : data["breathState"].toString().tr; bodyMotion = data['bodyMotion'] == null ? -1 : data['bodyMotion']; breathrate = data["breathRate"] == null ? -1 : data["breathRate"]; heartrate = data['heartRate'] == null ? -1 : data['heartRate']; snores = data['snores'] == null || data['snores'] == "" || data['snores'] == "否".tr ? "否".tr : "${data['snores']}".tr; } if (mounted) { setState(() { onlineState = "在线".tr; }); } _startOnlineTimer(); }; }); } catch (e) { print(e); edm.EasyDartModule.logger .error("[webscoekt]格式化数据错误-->${{"mac": widget.personInfo['mac']}}"); } if (widget.personInfo['status'] != null) { try { onlineState = widget.personInfo['status']['status'] == 1 ? "在线".tr : "离线".tr; if (widget.personInfo['status']['status'] != 0) { inBed = widget.personInfo['status']['inBed'] == 1 ? "在床".tr : "离床".tr; } } catch (e) { edm.EasyDartModule.logger .error("[webscoekt]格式化数据错误-->${{"mac": widget.personInfo['mac']}}"); } } edm.EasyDartModule.logger .info("[webscoekt]发送请求:数据-->${{"mac": widget.personInfo['mac']}}"); DailyLogUtils.writeLog( "[webscoekt]发送请求:数据-->${{"mac": widget.personInfo['mac']}}"); edm.EasyDartModule.websocket.sendData(jsonEncode(WebSocketMessage( path: "/vsbs/web/rt/marttress", type: 1, data: {"mac": widget.personInfo['mac']}))); await Future.delayed(Duration(seconds: 3)); edm.EasyDartModule.websocket.sendData(jsonEncode(WebSocketMessage( path: "/vsbs/web/rt/marttress", type: 1, data: {"mac": widget.personInfo['mac']}))); _startOnlineTimer(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); _onlineTimer?.cancel(); _checkStatusTimer?.cancel(); _closeWebSocket(); // _animationController.dispose(); CommonVariables.callMap.remove("/vsbs/web/rt/marttress"); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { edm.EasyDartModule.logger.info("app切回页面,重连websocket"); _initWebSocket(); _initWebSocket(); deviceTypeController .checkReportStatus(widget.personInfo['mac']) .then((_) { if (deviceTypeController.experience_status.value != 404 && deviceTypeController.own.value) { _startCheckStatusTimer(); } }); } else if (state == AppLifecycleState.paused) { _closeWebSocket(); _checkStatusTimer?.cancel(); } } void _startOnlineTimer() { _onlineTimer?.cancel(); _onlineTimer = Timer.periodic(Duration(seconds: 60), (timer) { if (mounted) { setState(() { edm.EasyDartModule.logger.info("60 秒内没有接收到数据,设置为离线"); onlineState = "离线".tr; inBed = "-"; bodyMotion = -1; heartrate = -1; snores = "-"; breathrate = -1; breathState = "-"; }); } }); } void _closeWebSocket() { edm.EasyDartModule.websocket.sendData( jsonEncode(WebSocketMessage(path: "/vsbs/web/rt/marttress", type: 2))); _onlineTimer?.cancel(); } void _startCheckStatusTimer() { _checkStatusTimer?.cancel(); _checkStatusTimer = Timer.periodic(Duration(seconds: 3), (timer) { if (mounted) { edm.EasyDartModule.logger.info("定时查询快检状态"); deviceTypeController .checkReportStatus(widget.personInfo['mac']) .then((_) async { progressNotifier.value = deviceTypeController.experience_percent.value.toDouble(); deviceTypeController.updateAll(); if (deviceTypeController.experience_status.value == APPQuickCheckStatus.completed.value) { try { deviceTypeController.experience_status.value = 404; deviceTypeController.experience_status.value = 0; progressNotifier.value = 0; edm.EasyDartModule.logger.info("快检结束,停止定时查询"); _checkStatusTimer?.cancel(); Map data = { "id": deviceTypeController.experience_id.value, "mac": widget.personInfo['mac'] }; bool hasVibrator = await Vibration.hasVibrator(); if (hasVibrator) { Vibration.vibrate(duration: 500); } Get.toNamed('/healthQuickCheckReportPage', arguments: data); } catch (e) { edm.EasyDartModule.logger.error("快检报告页面加载失败---?${e.toString()}"); } } if (deviceTypeController.experience_status.value == APPQuickCheckStatus.timeout.value || deviceTypeController.experience_status.value == APPQuickCheckStatus.calculateError.value || deviceTypeController.experience_status.value == APPQuickCheckStatus.insufficientData.value) { APPQuickCheckStatus? status = APPQuickCheckStatusExtension.fromInt( deviceTypeController.experience_status.value); String statusMessage = status?.description ?? "体验异常结束".tr; deviceTypeController.experience_status.value = 404; deviceTypeController.experience_percent.value = 0; progressNotifier.value = 0; edm.EasyDartModule.logger .info("快检结束,停止定时查询 - 状态: ${status?.description}"); _checkStatusTimer?.cancel(); bool hasVibrator = await Vibration.hasVibrator(); if (hasVibrator) { Vibration.vibrate(duration: 500); } await showTipDialog( context, Text( statusMessage, style: TextStyle( color: themeController.currentColor.sc9, ), ), ); } if (!deviceTypeController.own.value) { _checkStatusTimer?.cancel(); } }); } }); } @override Widget build(BuildContext context) { Map device = widget.personInfo; return LayoutBuilder( builder: (context, bodySize) => GestureDetector( child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage(getBackgroundImageNoImage()), fit: BoxFit.fill, ), ), child: Scaffold( backgroundColor: Colors.transparent, appBar: AppBar( systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, // 状态栏背景色 statusBarIconBrightness: Brightness.light, // 图标颜色(Android) statusBarBrightness: Brightness.light, // 图标颜色(iOS) ), backgroundColor: themeController.currentColor.sc17, automaticallyImplyLeading: false, iconTheme: IconThemeData(color: themeController.currentColor.sc3), titleSpacing: 0.rpx, title: Container( width: double.infinity, height: 180.rpx, child: Stack( alignment: Alignment.center, children: [ RichText( text: TextSpan( style: TextStyle( fontFamily: 'Readex Pro', color: themeController.currentColor.sc3, fontSize: 30.rpx, letterSpacing: 0.0, ), children: [ TextSpan( text: '健康快检'.tr, ), ], ), ), Positioned( left: 0.rpx, child: returnIconButtom, ), Obx(() { return deviceTypeController.experience_status.value != 200 || !deviceTypeController.own.value ? Positioned( right: 0.rpx, child: ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.transparent, padding: EdgeInsets.fromLTRB( 20.rpx, 20.rpx, 20.rpx, 20.rpx), onTap: () async { Get.toNamed('/healthExperienceHistory', arguments: widget.personInfo); }, child: SvgPicture.asset( 'assets/img/icon/history.svg', width: 35.rpx, height: 35.rpx, color: themeController.currentColor.sc3, ), ), ) : Container(); }) ], ), ), actions: [], centerTitle: false, ), body: SafeArea( top: true, child: Obx(() { final isExperiencing = deviceTypeController.experience_status.value == 200 && deviceTypeController.own.value; return Stack( children: [ Align( alignment: Alignment.center, child: FractionallySizedBox( heightFactor: 0.5, widthFactor: 0.5, child: Opacity( opacity: 0.7, child: (onlineState == "离线".tr || inBed == '离床'.tr) ? Image.asset( 'assets/img/black_body_still.png', fit: BoxFit.contain, ) : SpeedControlledGif( 'assets/img/body_black.gif', speedFactor: 2, fit: BoxFit.contain, ), ), ), ), // 其余内容放在上层 Positioned.fill( child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 29.rpx, 0.rpx, 0.rpx), child: Column( mainAxisSize: MainAxisSize.max, children: [ // 顶部区域 - 未体验显示个人信息,体验中显示快检中信息(带动画) if (!isExperiencing) Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 100.rpx), child: ClickableContainer( backgroundColor: themeController.currentColor.sc5, highlightColor: Colors.transparent, borderRadius: AppConstants().normal_container_radius, padding: EdgeInsets.zero, onTap: () { print('点击了体征卡片'); }, child: Column( children: [ Container( padding: EdgeInsets.fromLTRB( 37.rpx, 37.rpx, 20.rpx, 37.rpx), child: Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.start, children: [ // 左侧列 - 标签和值 Expanded( flex: 3, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 姓名行 Row( crossAxisAlignment: CrossAxisAlignment .center, children: [ Expanded( flex: 3, child: Text( '实时体征.姓名'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc4, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), SizedBox(width: 20.rpx), Expanded( flex: 4, child: Text( device['person'] != null && device['person'][ 'name'] != null && device['person'] [ 'name'] .toString() .trim() .isNotEmpty ? device['person'] ['name'] .toString() : '体征检测设备'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc3, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), ], ), SizedBox(height: 36.rpx), // 性别行 Row( crossAxisAlignment: CrossAxisAlignment .center, children: [ Expanded( flex: 3, child: Text( '性别'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc4, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), SizedBox(width: 20.rpx), Expanded( flex: 4, child: Text( device['person'] != null && device['person'] [ 'gender'] != null && device['person'] [ 'gender'] .toString() .trim() .isNotEmpty ? getGenderText( device['person'] [ 'gender']) : '-'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc3, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), ], ), SizedBox(height: 36.rpx), // 身高行 Row( crossAxisAlignment: CrossAxisAlignment .center, children: [ Expanded( flex: 3, child: Text( '身高'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc4, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), SizedBox(width: 20.rpx), Expanded( flex: 4, child: Text( device['person'] != null && device['person'] [ 'height'] != null && device['person'] [ 'height'] .toString() .trim() .isNotEmpty ? '${device['person']['height']}cm' : '-'.tr + "cm", style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc3, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), ], ), ], ), ), SizedBox(width: 30.rpx), // 右侧列 - 标签和值 Expanded( flex: 4, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 设备ID行 Row( crossAxisAlignment: CrossAxisAlignment .center, children: [ Expanded( flex: 1, child: Text( '实时体征.设备ID'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc4, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), SizedBox(width: 20.rpx), Expanded( flex: 2, child: Text( '${device['code'] ?? '未知数据'.tr}', style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc3, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), ], ), SizedBox(height: 36.rpx), // 年龄行 Row( crossAxisAlignment: CrossAxisAlignment .center, children: [ Expanded( flex: 1, child: Text( '年龄'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc4, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), SizedBox(width: 20.rpx), Expanded( flex: 2, child: Text( device['person'] != null && device['person'] [ 'birthday'] != null && device['person'] [ 'birthday'] .toString() .trim() .isNotEmpty ? calculateAge(device[ 'person'] [ 'birthday'] .toString()) : '-'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc3, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), ], ), SizedBox(height: 36.rpx), // 体重行 Row( crossAxisAlignment: CrossAxisAlignment .center, children: [ Expanded( flex: 1, child: Text( '体重'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc4, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), SizedBox(width: 20.rpx), Expanded( flex: 2, child: Text( device['person'] != null && device['person'] [ 'weight'] != null && device['person'] [ 'weight'] .toString() .trim() .isNotEmpty ? '${device['person']['weight']}kg' : '-'.tr + "kg", style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, color: themeController .currentColor .sc3, ), maxLines: 1, overflow: TextOverflow .ellipsis, ), ), ], ), ], ), ), ], ), ), ], ), ), ) else // 体验中状态 - 快检中信息(带动画) AnimatedBuilder( animation: _animationController, builder: (context, child) { return SlideTransition( position: _topSlideAnimation, child: Padding( padding: EdgeInsets.fromLTRB( 46.rpx, 0, 46.rpx, 0), child: Column( children: [ SizedBox( height: 103.rpx, ), Text( "快检中...".tr, style: TextStyle( color: themeController .currentColor.sc1, fontSize: AppConstants() .bigger_text_fontSize, ), ), SizedBox( height: 30.rpx, ), Text( "MAC号".tr + ": ${widget.personInfo['mac'] ?? '未知数据'.tr}", style: TextStyle( color: themeController .currentColor.sc4, fontSize: AppConstants() .smaller_text_fontSize, ), ), SizedBox( height: 4.rpx, ), Text( "睡眠报告提示".tr, style: TextStyle( color: themeController .currentColor.sc4, fontSize: AppConstants() .smaller_text_fontSize, ), ), SizedBox( height: 48.rpx, ), ], ), ), ); }, ), // 中间区域 - 体征信息(体验中时显示,带动画) if (isExperiencing) Expanded( child: SingleChildScrollView( child: Column( children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0, 30.rpx, 0), child: Row( children: [ // 左侧三个容器(从左向右滑动) Expanded( child: AnimatedBuilder( animation: _animationController, builder: (context, child) { return SlideTransition( position: _leftSlideAnimation, child: Column( children: [ DeviceStatusInfoWidget( title: "在离床".tr, iconAsset: "assets/img/icon/bed_status.svg", value: inBed, ), SizedBox( height: 49.rpx), DeviceStatusInfoWidget( title: "心率".tr, iconAsset: "assets/img/icon/heart.svg", value: inBed == "离床".tr ? "-" : ((heartrate == null || heartrate == -1) ? "-" : "$heartrate"), ), SizedBox( height: 49.rpx), DeviceStatusInfoWidget( title: "呼吸".tr, iconAsset: "assets/img/icon/breathe.svg", value: inBed == "离床".tr ? ("-") : ((breathrate == null || breathrate == -1) ? "-" : "$breathrate"), ), ], ), ); }, ), ), SizedBox(width: 20.rpx), // 右侧三个容器(从右向左滑动) Expanded( child: AnimatedBuilder( animation: _animationController, builder: (context, child) { return SlideTransition( position: _rightSlideAnimation, child: Column( children: [ DeviceStatusInfoWidget( title: "体动".tr, iconAsset: "assets/img/icon/bodymotion.svg", value: inBed == "离床".tr ? ("-") : (bodyMotion == null || bodyMotion == -1) ? "-" : "$bodyMotion", ), SizedBox( height: 49.rpx), DeviceStatusInfoWidget( title: "打鼾".tr, iconAsset: "assets/img/icon/snore.svg", value: inBed == "离床".tr ? "-" : ('${snores}' .tr), ), SizedBox( height: 49.rpx), DeviceStatusInfoWidget( title: "呼吸暂停".tr, iconAsset: "assets/img/icon/breathe_pause.svg", value: inBed == "离床".tr ? "-" : ('${breathState}'), ), ], ), ); }, ), ), ], ), ), Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 67.rpx, 0.rpx, 0.rpx), child: Container( height: 40.rpx, child: Text( bodyMotion >= maxBodyMotion ? '请保持静止'.tr : "", style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc9, ), ), ), ), ], ), ), ) else // 未体验状态 - 占位空白 Expanded(child: Container()), // 底部区域 - 未体验显示说明和开始按钮,体验中显示进度条和终止按钮(无动画) if (!isExperiencing) Column( children: [ ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.transparent, borderRadius: 16.rpx, padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 0.rpx), onTap: () {}, child: Container( padding: EdgeInsetsDirectional.fromSTEB( 26.rpx, 26.rpx, 26.rpx, 26.rpx), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16.rpx), border: Border.all( color: themeController .currentColor.sc4 .withOpacity(0.5), width: 0.5.rpx, ), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsetsDirectional .fromSTEB(0, 8.rpx, 0, 0), child: Container( width: 23.rpx, height: 23.rpx, decoration: BoxDecoration(), child: SvgPicture.asset( 'assets/img/icon/tips.svg', fit: BoxFit.cover, color: themeController .currentColor.sc4, ), ), ), Expanded( child: Text( '使用方式:人员使用健康快检功能时,只需平躺或坐在正常运行中的体征传感器传感器上方,保持静止,然后点击“启动快检”,待进度条完成,即可得出快检报告。' .tr, style: TextStyle( fontFamily: 'Inter', letterSpacing: 0.0, color: themeController .currentColor.sc4, ), ), ), ].divide(SizedBox(width: 23.rpx)), ), ), ), SizedBox(height: 40.rpx), Padding( padding: EdgeInsets.fromLTRB( 100.rpx, 0, 100.rpx, 0), child: Column( children: [ CustomCard( borderRadius: AppConstants() .button_container_radius, onTap: () async { bool opRes = await deviceTypeController .qcCheckControl( widget.personInfo, 1); if (!opRes) { return; } deviceTypeController .experience_percent.value = 0; progressNotifier.value = 0; deviceTypeController .experience_status .value = 200; _startCheckStatusTimer(); deviceTypeController.updateAll(); }, colors: AppConstants().thNormalButton, child: Container( width: bodySize.maxWidth, height: MediaQuery.sizeOf(context) .height * 0.055, constraints: BoxConstraints( minWidth: 500.rpx, minHeight: 90.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '开始快检'.tr, style: TextStyle( color: themeController .currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants() .normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide( SizedBox(width: 17.rpx)), ), ), ), ], ), ), SizedBox(height: 40.rpx), SizedBox(height: 26.rpx), ], ) else Column( children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB( 100.rpx, 0.rpx, 100.rpx, 60.rpx), child: CalibrationProgressWidget( progressNotifier: progressNotifier, failureNotifier: failureNotifier, ), ), Padding( padding: EdgeInsets.fromLTRB( 100.rpx, 0, 100.rpx, 0), child: Column( children: [ CustomCard( borderRadius: AppConstants() .button_container_radius, onTap: () { showCancelConfirmDialog( context, widget.personInfo); }, colors: [ themeController.currentColor.sc9 ], child: Container( width: bodySize.maxWidth, height: MediaQuery.sizeOf(context) .height * 0.055, constraints: BoxConstraints( minWidth: 500.rpx, minHeight: 90.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '终止'.tr, style: TextStyle( color: themeController .currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants() .normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide( SizedBox(width: 17.rpx)), ), ), ), ], ), ), SizedBox(height: 40.rpx), SizedBox(height: 26.rpx), ], ), ], ), ), ), ], ); })), ), ), ), ); } }