import 'dart:async'; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:vbvs_app/common/color/ServiceConstant.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/common/util/requestWithLog.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/CustomCard.dart'; import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart'; import 'package:vbvs_app/controller/device/device_calibration_controller.dart'; import 'package:vbvs_app/pages/device_bind/componnet/CalibrationProgressWidget.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; class CalibrationPersonPage extends StatefulWidget { int? type; //1.绑定时 2.绑定后 CalibrationPersonPage({super.key, required this.type}); @override State createState() => _CalibrationPersonPageState(); } class _CalibrationPersonPageState extends State { DeviceCalibrationController deviceCalibrationController = Get.find(); BlueteethBindController blueteethBindController = Get.find(); final ValueNotifier progressNotifier = ValueNotifier(0.0); final ValueNotifier failureNotifier = ValueNotifier(false); Timer? _pollingTimer; bool exit = false; @override void initState() { super.initState(); deviceCalibrationController.process.value = 0; deviceCalibrationController.cd.value = 10000; deviceCalibrationController.flag.value = 0; deviceCalibrationController.bed_calibration.value = 0; deviceCalibrationController.position_calibration.value = 0; blueteethBindController.cid!.value = ""; deviceCalibrationController.motionTips.value = 0; deviceCalibrationController.inBedTips.value = 0; deviceCalibrationController.statusContext.value = ""; } @override void dispose() { _pollingTimer?.cancel(); blueteethBindController.cid!.value = ""; super.dispose(); } @override Widget build(BuildContext context) { return WillPopScope( child: LayoutBuilder( builder: (context, bodySize) => GestureDetector( // onTap: () => FocusScope.of(context).unfocus(),, child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('assets/img/bgNoImg.png'), fit: BoxFit.fill, ), ), child: Scaffold( backgroundColor: Colors.transparent, appBar: AppBar( backgroundColor: themeController.currentColor.sc17, automaticallyImplyLeading: false, iconTheme: IconThemeData(color: themeController.currentColor.sc3), titleSpacing: 0, title: Container( width: double.infinity, height: 180.rpx, child: Stack( alignment: Alignment.center, children: [ Text( '设备校准'.tr, style: TextStyle( fontFamily: 'Readex Pro', color: themeController.currentColor.sc3, letterSpacing: 0, fontSize: 30.rpx, ), ), Positioned( left: 0, child: returnIconButtomAddCallback(() { if (deviceCalibrationController.flag.value != 2) { try { showConfirmDialog( context, Container(), "校准未完成提示".tr, onConfirm: () async { exit = true; if (widget.type == 2) { Get.back(); return; } await Get.toNamed("/personPage"); print("object"); deviceCalibrationController.process.value = 0; deviceCalibrationController .bed_calibration.value = 0; deviceCalibrationController .position_calibration.value = 0; blueteethBindController.cid!.value = ""; }, onCancel: () { exit = false; }); } catch (e) { print(e); } } else { exit = true; } if (exit) { Get.back(); } }, enableBack: exit), ), Positioned( right: 20.rpx, child: CustomCard( borderRadius: 20.rpx, onTap: () async { if (deviceCalibrationController.flag.value != 2) { showConfirmDialog( context, Container(), "校准未完成提示".tr, onConfirm: () async { Get.back(); print("object"); deviceCalibrationController.process.value = 0; deviceCalibrationController .bed_calibration.value = 0; deviceCalibrationController .position_calibration.value = 0; blueteethBindController.cid!.value = ""; }, onCancel: () {}); } else { Get.back(); deviceCalibrationController.process.value = 0; deviceCalibrationController .bed_calibration.value = 0; deviceCalibrationController .position_calibration.value = 0; blueteethBindController.cid!.value = ""; } }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], child: Container( width: 130.rpx, height: 60.rpx, alignment: Alignment.center, padding: EdgeInsetsDirectional.fromSTEB( 16.rpx, 0, 16.rpx, 0), child: Text( '完成'.tr, style: TextStyle( fontFamily: 'Inter Tight', color: themeController.currentColor.sc3, letterSpacing: 0.0, ), ), ), ), ), ], ), ), actions: [], centerTitle: false, ), body: SafeArea( top: true, // child: Container(), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 30.rpx, 0.rpx, 30.rpx, 0.rpx), child: Column( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 30.rpx, 0, 0), child: Container( width: double.infinity, decoration: BoxDecoration( color: themeController.currentColor.sc5, borderRadius: BorderRadius.circular(16.rpx), ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 10.rpx, 20.rpx, 34.rpx, 20.rpx), child: Column( mainAxisSize: MainAxisSize.max, children: [ ClickableContainer( backgroundColor: Colors.transparent, highlightColor: themeController.currentColor.sc21, borderRadius: 0, // 可按需设置圆角 padding: EdgeInsets.symmetric( vertical: 10.rpx), // 可自定义内边距 onTap: () { // deviceCalibrationController.process.value = 0; // deviceCalibrationController.updateAll(); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Obx(() { return Visibility( maintainState: true, maintainAnimation: true, maintainSize: true, visible: deviceCalibrationController .process.value == 0, child: SvgPicture.asset( 'assets/img/icon/select_arrow.svg', width: 17.rpx, height: 17.rpx, color: themeController .currentColor.sc9, ), ); }), SizedBox(width: 8.rpx), Text( '离床校准'.tr, style: TextStyle( fontSize: 30.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc3, ), ), ], ), Obx(() { return Text( deviceCalibrationController .bed_calibration .value == 0 ? '未完成'.tr : "已完成".tr, style: TextStyle( fontSize: 26.rpx, letterSpacing: 0.0, color: deviceCalibrationController .bed_calibration .value == 0 ? themeController .currentColor.sc3 : themeController .currentColor.sc1, ), ); }), ], ), ), SizedBox(height: 41.rpx), ClickableContainer( backgroundColor: Colors.transparent, highlightColor: themeController.currentColor.sc21, borderRadius: 0, // 可根据需要设为圆角 padding: EdgeInsets.symmetric( vertical: 10.rpx), // 可根据需要调整上下内边距 onTap: () { // deviceCalibrationController.process.value = 1; // deviceCalibrationController.updateAll(); }, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Obx(() { return Visibility( maintainState: true, maintainAnimation: true, maintainSize: true, visible: deviceCalibrationController .process.value == 1, child: SvgPicture.asset( 'assets/img/icon/select_arrow.svg', width: 17.rpx, height: 17.rpx, color: themeController .currentColor.sc9, ), ); }), SizedBox(width: 8.rpx), Text( '位置校准'.tr, style: TextStyle( fontSize: 30.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc3, ), ), ], ), Obx(() { return Text( deviceCalibrationController .position_calibration .value == 0 ? '未完成'.tr : "已完成".tr, style: TextStyle( fontSize: 26.rpx, letterSpacing: 0.0, color: deviceCalibrationController .position_calibration .value == 0 ? themeController .currentColor.sc3 : themeController .currentColor.sc1, ), ); }), ], ), ), ], ), ), ), ), Obx(() { return Expanded( child: SizedBox( width: double.infinity, child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 100.rpx, 55.rpx, 100.rpx, 0), child: Stack( clipBehavior: Clip.none, children: [ Container( width: MediaQuery.sizeOf(context).width * 0.65, height: MediaQuery.sizeOf(context).height * 0.3, child: Stack( children: [ Image.asset( deviceCalibrationController .process.value == 1 && deviceCalibrationController .position_calibration .value == 1 ? (deviceCalibrationController .bed_type.value == 0 ? "assets/img/single_person.png" : "assets/img/double_person.png") : (deviceCalibrationController .bed_type.value == 0 ? "assets/img/single_pillow.png" : "assets/img/double_pillow.png"), width: double.infinity, height: double.infinity, fit: BoxFit.contain, ), // 床头文字 Positioned( top: 23.rpx, left: (MediaQuery.sizeOf(context) .width * 0.65) / 2 - 26.rpx, child: Text( '床头'.tr, style: TextStyle( fontSize: 26.rpx, color: themeController .currentColor.sc4, ), ), ), ], ), ), Obx(() { final double centerLeft = (bodySize.maxWidth * 0.56) / 2; if (deviceCalibrationController .bed_type.value == 0 && deviceCalibrationController .process.value == 1) { //单人床位置校准 return Positioned( top: -40.rpx, left: centerLeft - 0.rpx, child: Container( width: bodySize.maxWidth * 0.087, height: bodySize.maxHeight * 0.06, constraints: BoxConstraints( minWidth: 65.rpx, minHeight: 76.rpx, ), decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/img/tip_arrow.gif'), fit: BoxFit.cover, ), ), ), ); } if (deviceCalibrationController .bed_type.value == 1 && deviceCalibrationController .process.value == 1) { //双人人床位置校准 return Positioned( top: -40.rpx, left: (MediaQuery.sizeOf(context) .width * 0.65) * 0.22 - 0.rpx, child: Container( width: bodySize.maxWidth * 0.087, height: bodySize.maxHeight * 0.06, constraints: BoxConstraints( minWidth: 65.rpx, minHeight: 76.rpx, ), decoration: BoxDecoration( image: DecorationImage( image: AssetImage( 'assets/img/tip_arrow.gif'), fit: BoxFit.cover, ), ), ), ); } return Container(); }), Positioned( top: MediaQuery.sizeOf(context).height * 0.3 + 82.rpx, left: 0, right: 0, child: Obx(() { return Column( children: [ getBodyMontion(), SizedBox( height: 10.rpx, ), getInBedMontion(), SizedBox( height: 10.rpx, ), Text( (deviceCalibrationController .cd.value == 10000) ? ((deviceCalibrationController .process .value == 0 && deviceCalibrationController .bed_calibration .value == 1) || (deviceCalibrationController .process .value == 1 && deviceCalibrationController .position_calibration .value == 1) ? (deviceCalibrationController .flag.value == 2 ? '校准完成'.tr : "校准失败".tr) : deviceCalibrationController .statusContext .value .isEmpty == true ? (deviceCalibrationController .process .value == 0 ? '离床校准提示'.tr : '位置校准提示'.tr) : deviceCalibrationController .statusContext .value) : "${deviceCalibrationController.cd.value}" + "s后超时".tr, style: TextStyle( fontSize: 38.rpx, letterSpacing: 0.0, color: ((deviceCalibrationController .process .value == 0 && deviceCalibrationController .bed_calibration .value == 1) || (deviceCalibrationController .process .value == 1 && deviceCalibrationController .position_calibration .value == 1)) && (deviceCalibrationController .flag.value == 2) ? themeController .currentColor.sc1 : themeController .currentColor.sc9, ), ), ], ); }), ), ], ), ), ), ); }), Obx(() { if (deviceCalibrationController.flag.value == 1) { return Padding( padding: EdgeInsetsDirectional.fromSTEB( 100.rpx, 0.rpx, 100.rpx, 60.rpx), child: CalibrationProgressWidget( progressNotifier: progressNotifier, failureNotifier: failureNotifier, ), ); } return Container(); }), Obx(() { if (deviceCalibrationController.flag.value != 1) { return Padding( padding: EdgeInsetsDirectional.fromSTEB( 100.rpx, 0.rpx, 100.rpx, 60.rpx), child: CustomCard( borderRadius: AppConstants() .button_container_radius, // 圆角半径 onTap: () async { if (deviceCalibrationController.flag.value == 2) { deviceCalibrationController .statusContext.value = ""; deviceCalibrationController.flag.value = 1; progressNotifier.value = 0; failureNotifier.value = false; deviceCalibrationController.process.value = 0; deviceCalibrationController .bed_calibration.value = 0; deviceCalibrationController .position_calibration.value = 0; BlueteethBindController blueteethBindController = Get.find(); blueteethBindController.cid!.value = ""; deviceCalibrationController.process.value = 0; deviceCalibrationController .bed_calibration.value = 0; deviceCalibrationController .position_calibration.value = 0; blueteethBindController.cid!.value = ""; String serviceAddress = "https://caibration.he-info.cn"; String calibrationApi = ServiceConstant.start_calibration; String progressApi = ServiceConstant.calibration_process; String queryUrl = "$serviceAddress$calibrationApi"; Timer? pollingTimer; Map data = { "macA": blueteethBindController .currentDeviceMac!.value, }; // 是否是二次点击(有cid表示进行第二阶段) bool isSecondStep = blueteethBindController .cid?.value.isNotEmpty ?? false; if (isSecondStep) { data["id"] = blueteethBindController.cid!.value; } // 发起校准请求 requestWithLog( logTitle: "设备校准", method: MyHttpMethod.post, queryUrl: queryUrl, data: data, onSuccess: (res) { if (!isSecondStep) { // 保存第一次获取的 cid String cid = res.rawResponse.data['cid']; blueteethBindController.cid!.value = cid; } _startPollingProgress(serviceAddress, progressApi, isSecondStep); }, onFailure: (res) { deviceCalibrationController.flag.value = 0; blueteethBindController.cid!.value = ""; blueteethBindController.updateAll(); failureNotifier.value = true; TopSlideNotification.show( context, text: res.msg ?? "服务器.失败".tr, textColor: themeController.currentColor.sc9, ); }, ); } else { deviceCalibrationController.flag.value = 1; progressNotifier.value = 0; failureNotifier.value = false; _pollingTimer?.cancel(); BlueteethBindController blueteethBindController = Get.find(); String serviceAddress = "https://caibration.he-info.cn"; String calibrationApi = ServiceConstant.start_calibration; String progressApi = ServiceConstant.calibration_process; String queryUrl = "$serviceAddress$calibrationApi"; Map data = { "macA": blueteethBindController .currentDeviceMac!.value, }; // 是否是二次点击(有cid表示进行第二阶段) bool isSecondStep = blueteethBindController .cid?.value.isNotEmpty ?? false; if (isSecondStep) { data["id"] = blueteethBindController.cid!.value; } else { data["cancel"] = true; } // 发起校准请求 requestWithLog( logTitle: "设备校准", method: MyHttpMethod.post, queryUrl: queryUrl, data: data, onSuccess: (res) { if (!isSecondStep) { // 保存第一次获取的 cid String cid = res.rawResponse.data['cid']; blueteethBindController.cid!.value = cid; } _startPollingProgress(serviceAddress, progressApi, isSecondStep); }, onFailure: (res) { deviceCalibrationController.flag.value = 0; blueteethBindController.cid!.value = ""; blueteethBindController.updateAll(); _pollingTimer?.cancel(); failureNotifier.value = true; TopSlideNotification.show( context, text: res.msg ?? "服务器.失败".tr, textColor: themeController.currentColor.sc9, ); }, ); } }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], 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: [ Obx(() { if (deviceCalibrationController .flag.value == 0) { return Text( '开始校准'.tr, style: TextStyle( color: themeController .currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants() .normal_text_fontSize, letterSpacing: 0.0, ), ); } if (deviceCalibrationController .flag.value == 1) { deviceCalibrationController .statusContext.value = ""; return Text( '开始校准'.tr, style: TextStyle( color: themeController .currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants() .normal_text_fontSize, letterSpacing: 0.0, ), ); } if (deviceCalibrationController .flag.value == 2) { return Text( '重新校准'.tr, style: TextStyle( color: themeController .currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants() .normal_text_fontSize, letterSpacing: 0.0, ), ); } return Container(); }), ].divide(SizedBox( width: 17.rpx, )), ), ), ), ); } return Container(); }), ], ), ), ), ), ), ), ), onWillPop: () async { bool exit = false; if (deviceCalibrationController.flag.value != 2) { showConfirmDialog(context, Container(), "校准未完成提示".tr, onConfirm: () async { exit = true; // await Get.toNamed("/personPage"); // print("object"); deviceCalibrationController.process.value = 0; deviceCalibrationController.bed_calibration.value = 0; deviceCalibrationController.position_calibration.value = 0; blueteethBindController.cid!.value = ""; }, onCancel: () { exit = false; }); } else { exit = true; } return exit; }); } void _startPollingProgress( String serviceAddress, String progressApi, bool isSecondStep) { // 立即请求一次 _requestProgress(serviceAddress, progressApi, isSecondStep); // 设置定时器每2秒请求一次 _pollingTimer = Timer.periodic(Duration(seconds: 1), (_) { _requestProgress(serviceAddress, progressApi, isSecondStep); }); } void _requestProgress( String serviceAddress, String progressApi, bool isSecondStep) { String cid = blueteethBindController.cid!.value; String progressUrl = "$serviceAddress$progressApi?id=$cid"; requestWithLog( logTitle: "设备校准进度", method: MyHttpMethod.get, queryUrl: progressUrl, onSuccess: (res) { final data = res.data; double per = (data['per'] ?? 0).toDouble(); int currStep = data['currStep'] ?? -1; String tips = data['statusText'] ?? ''; try { if (data['mattress'] != null) { deviceCalibrationController.inBedTips.value = data['mattress']['inBed']; deviceCalibrationController.motionTips.value = data['mattress']['bm']; } } catch (e) { print(e); } if (data['status'] == null) { //当前进程执行中,执行倒计时 if (data['cd'] != null) { int cd = data['cd'] ?? 0; deviceCalibrationController.cd.value = cd; deviceCalibrationController.statusContext.value = ""; } } else { if (data['status'] == true) { //当前步骤执行成功 deviceCalibrationController.tips.value = ""; deviceCalibrationController.cd.value = 10000; if (isSecondStep) { deviceCalibrationController.statusContext.value = data['statusText']; deviceCalibrationController.updateAll(); } } else { deviceCalibrationController.statusContext.value = ""; //当前步骤执行失败 deviceCalibrationController.bed_calibration.value == 0; _pollingTimer?.cancel(); blueteethBindController.cid?.value = ""; deviceCalibrationController.process.value = 0; deviceCalibrationController.flag.value = 0; deviceCalibrationController.tips.value = ""; deviceCalibrationController.cd.value = 10000; deviceCalibrationController.updateAll(); TopSlideNotification.show( context, text: tips, textColor: themeController.currentColor.sc9, ); return; } } bool status = data['status'] ?? false; // 更新进度 progressNotifier.value = per; if (per != 100 && per != 20) { deviceCalibrationController.tips.value = tips; } else { deviceCalibrationController.tips.value = ""; } deviceCalibrationController.updateAll(); if (!isSecondStep && per >= 20) { // 第一步完成 _pollingTimer?.cancel(); progressNotifier.value = 100; TopSlideNotification.show(context, text: tips); deviceCalibrationController.process.value = 1; deviceCalibrationController.bed_calibration.value = 1; deviceCalibrationController.flag.value = 0; // 重置标志允许再次点击 } else if (isSecondStep && per >= 100 && currStep == 5 && status) { // 第二步完成 updateDeviceBindStatus( blueteethBindController.currentDeviceMac!.value); _pollingTimer?.cancel(); TopSlideNotification.show(context, text: "设备校准完成".tr); deviceCalibrationController.bed_calibration.value = 1; deviceCalibrationController.position_calibration.value = 1; deviceCalibrationController.process.value = 1; deviceCalibrationController.flag.value = 2; progressNotifier.value = 0; // 重置进度条 failureNotifier.value = false; // 重置失败状态 } }, onFailure: (res) { deviceCalibrationController.flag.value = 0; _pollingTimer?.cancel(); blueteethBindController.cid!.value = ""; failureNotifier.value = true; deviceCalibrationController.flag.value = 0; deviceCalibrationController.cd.value = 10000; TopSlideNotification.show( context, text: res.msg ?? "服务器.失败".tr, textColor: themeController.currentColor.sc9, ); }, ); } getInBedMontion() { if (deviceCalibrationController.cd.value == 10000) { return Container(); } if (deviceCalibrationController.process.value == 1) { if (deviceCalibrationController.inBedTips.value == 0) { return Text( "请校准人员保持在床状态".tr, style: TextStyle( fontSize: AppConstants().normal_text_fontSize, color: themeController.currentColor.sc9), ); } } else { if (deviceCalibrationController.inBedTips.value != 0) { return Text( "请校准人员暂时离开床铺".tr, style: TextStyle( fontSize: AppConstants().normal_text_fontSize, color: themeController.currentColor.sc9), ); } } return Container(); } getBodyMontion() { if (deviceCalibrationController.cd.value == 10000) { return Container(); } if (deviceCalibrationController.process.value == 1) { if (deviceCalibrationController.motionTips.value != 0) { return Text( "请保持身体静止".tr, style: TextStyle( fontSize: AppConstants().normal_text_fontSize, color: themeController.currentColor.sc9), ); } } return Container(); } void updateDeviceBindStatus(String mac) { String serviceAddress = ServiceConstant.service_address; String serviceName = ServiceConstant.server_service; String serviceApi = ServiceConstant.user_setting; String type = "device_bind_status_$mac"; String queryUrl = "${serviceAddress}${serviceName}${serviceApi}?type=${type}"; requestWithLog( logTitle: "查询绑定流程", method: MyHttpMethod.get, queryUrl: queryUrl, onSuccess: (res) { print(res); Map data = { "type": type, "mac": mac, "wifi": res.data['wifi'], "celibration": true, "person_info": res.data['person_info'], "time": DateTime.now().millisecondsSinceEpoch, }; requestWithLog( logTitle: "更新绑定流程", method: MyHttpMethod.put, queryUrl: queryUrl, data: data, onSuccess: (res) {}, onFailure: (res) {}, ); }, onFailure: (res) {}, ); } }