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/common/selectDialog.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; class CalibrationPage extends StatefulWidget { int? type; //1.绑定时 2.绑定后 CalibrationPage({super.key, required this.type}); @override State createState() => _CalibrationPageState(); } class _CalibrationPageState extends State { DeviceCalibrationController deviceCalibrationController = Get.find(); BlueteethBindController blueteethBindController = Get.find(); bool exit = false; @override void initState() { super.initState(); deviceCalibrationController.process.value = 0; deviceCalibrationController.bed_calibration.value = 0; deviceCalibrationController.position_calibration.value = 0; blueteethBindController.cid!.value = ""; } @override void dispose() { 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(getBackgroundImageNoImage()), fit: BoxFit.fill, ), ), child: Scaffold( backgroundColor: Colors.transparent, appBar: AppBar( backgroundColor: themeController.currentColor.sc5, 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 { await Get.toNamed("/personPage"); print("object"); deviceCalibrationController.process.value = 0; deviceCalibrationController .bed_calibration.value = 0; deviceCalibrationController .position_calibration.value = 0; blueteethBindController.cid!.value = ""; }, onCancel: () {}); } else { await Get.toNamed("/personPage"); 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: 140.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 // .bed_type.value == // 0 // ? "assets/img/single_pillow.png" // : "assets/img/double_pillow.png", // width: double.infinity, // height: double.infinity, // fit: BoxFit.contain, // ), 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: [ Text( (deviceCalibrationController .process .value == 0 && deviceCalibrationController .bed_calibration .value == 1) || (deviceCalibrationController .process .value == 1 && deviceCalibrationController .position_calibration .value == 1) ? '校准完成'.tr : deviceCalibrationController .process.value == 0 ? '离床校准提示'.tr : '位置校准提示'.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)) ? themeController .currentColor.sc1 : themeController .currentColor.sc9, ), ), ], ); }), ), ], ), ), ), ); }), 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) { showConfirmDialog( context, Container(), "校准已经完成,是否重新开始校准?", onConfirm: () { deviceCalibrationController.flag.value = 1; BlueteethBindController blueteethBindController = Get.find(); 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"; final ValueNotifier progressNotifier = ValueNotifier(0.0); final ValueNotifier failureNotifier = ValueNotifier(false); 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; } void requestCalibrationProgress() { 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; bool status = data['status'] ?? false; String tips = data['statusText'] ?? ''; deviceCalibrationController .tips.value = tips; progressNotifier.value = per; if (!isSecondStep && per >= 20) { progressNotifier.value = 100; // 第一步完成:仅 per >= 100 pollingTimer?.cancel(); TopSlideNotification.show(context, text: tips); deviceCalibrationController .process.value = 1; deviceCalibrationController .bed_calibration.value = 1; deviceCalibrationController .updateAll(); } if (isSecondStep && per >= 100 && currStep == 5 && status == true) { // 第二步完成:per >= 100 && currStep == 5 && status == true deviceCalibrationController .flag.value = 2; pollingTimer?.cancel(); TopSlideNotification.show(context, text: "设备校准完成".tr); // 可在这里执行校准完成后的业务逻辑更新 deviceCalibrationController .bed_calibration.value = 1; deviceCalibrationController .position_calibration .value = 1; deviceCalibrationController .process.value = 1; deviceCalibrationController .updateAll(); } }, onFailure: (res) { pollingTimer?.cancel(); failureNotifier.value = true; TopSlideNotification.show( context, text: res.msg ?? "失败".tr, textColor: themeController .currentColor.sc9, ); }, ); } // 初始调用一次 requestCalibrationProgress(); // 开始轮询 pollingTimer = Timer.periodic( Duration(seconds: 2), (_) { requestCalibrationProgress(); }); // 显示进度弹窗 showProgressDialog(context, progressNotifier, failureNotifier); }, onFailure: (res) { TopSlideNotification.show( context, text: res.msg ?? "失败".tr, textColor: themeController.currentColor.sc9, ); }, ); }, onCancel: () { return; }); } else { deviceCalibrationController.flag.value = 1; 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"; final ValueNotifier progressNotifier = ValueNotifier(0.0); final ValueNotifier failureNotifier = ValueNotifier(false); 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; } void requestCalibrationProgress() { 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; bool status = data['status'] ?? false; String tips = data['statusText'] ?? ''; deviceCalibrationController .tips.value = tips; progressNotifier.value = per; if (!isSecondStep && per >= 20) { progressNotifier.value = 100; // 第一步完成:仅 per >= 100 pollingTimer?.cancel(); TopSlideNotification.show(context, text: tips); deviceCalibrationController .process.value = 1; deviceCalibrationController .bed_calibration.value = 1; deviceCalibrationController .updateAll(); } if (isSecondStep && per >= 100 && currStep == 5 && status == true) { // 第二步完成:per >= 100 && currStep == 5 && status == true 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; deviceCalibrationController .updateAll(); } }, onFailure: (res) { pollingTimer?.cancel(); failureNotifier.value = true; TopSlideNotification.show( context, text: res.msg ?? "失败".tr, textColor: themeController .currentColor.sc9, ); }, ); } // 初始调用一次 requestCalibrationProgress(); // 开始轮询 pollingTimer = Timer.periodic( Duration(seconds: 2), (_) { requestCalibrationProgress(); }); // 显示进度弹窗 showProgressDialog(context, progressNotifier, failureNotifier); }, onFailure: (res) { 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: [ Text( '开始校准'.tr, style: TextStyle( //todo 颜色 color: themeController.currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants().normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide(SizedBox( width: 17.rpx, )), ), ), ), ), ], ), ), ), ), ), ), ), 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; }); } }