import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as ui; 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/color/app_uri_status.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/ToggleColorContainer.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/body_device_controller.dart'; import 'package:vbvs_app/controller/person/person_controller.dart'; import 'package:vbvs_app/enum/BindType.dart'; import 'package:vbvs_app/model/api_response.dart'; import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart'; class DeviceDataComponentWidget extends StatefulWidget { final Map device; const DeviceDataComponentWidget({super.key, required this.device}); @override State createState() => _DeviceDataComponentWidgetState(); } class _DeviceDataComponentWidgetState extends State { final GlobalKey _arrowKey = GlobalKey(); OverlayEntry? _popupEntry; BodyDeviceController bodyDeviceController = Get.find(); PersonController personController = Get.find(); bool _isPopupOpen = false; var lisObj; @override void dispose() { _popupEntry?.remove(); super.dispose(); } @override void initState() { super.initState(); } void _showPopup() { setState(() { _isPopupOpen = true; }); final RenderBox? renderBox = _arrowKey.currentContext?.findRenderObject() as RenderBox?; if (renderBox == null) return; final position = renderBox.localToGlobal(Offset.zero); final size = renderBox.size; final screenSize = MediaQuery.of(context).size; final screenHeight = screenSize.height; final screenWidth = screenSize.width; // final popupWidth = 190.rpx; var popupWidth = 190.rpx; final paddingOffset = 10.rpx; // 构建弹窗内容 final popupContent = _buildPopupContent(); final textStyle = TextStyle( fontSize: AppConstants().normal_text_fontSize, color: themeController.currentColor.sc3, ); final allTexts = [ "体征检测设备.首页展示".tr, "体征检测设备.设备详情".tr, "WIFI配置".tr, "设备校准".tr, "分享设备".tr, "消息设置".tr, "体征检测设备.重命名".tr, "体征检测设备.删除".tr, ]; final menuWidth = _calculateMaxMenuItemWidth(allTexts, textStyle); popupWidth = menuWidth; // 计算弹窗需要的实际高度(估算) final estimatedItemHeight = 66.rpx; // 每个菜单项的估算高度 //todo 更新菜单项,需要在此添加数量 final itemCount = widget.device['bind_type'] == BindType.active.code ? 9 : 5; final estimatedPopupHeight = (itemCount * estimatedItemHeight) + 40.rpx; // 加上padding // 计算可用空间 final availableSpaceBelow = screenHeight - position.dy - size.height - paddingOffset; final availableSpaceAbove = position.dy - paddingOffset; // 决定显示位置和实际高度 bool showAbove; double popupTop; double actualPopupHeight; if (availableSpaceBelow >= estimatedPopupHeight || (availableSpaceBelow < estimatedPopupHeight && availableSpaceAbove > availableSpaceBelow)) { // 显示在下方的条件:下方空间足够,或者下方空间比上方大 showAbove = false; popupTop = position.dy + size.height + paddingOffset; actualPopupHeight = math.min(estimatedPopupHeight, availableSpaceBelow); } else { // 显示在上方 showAbove = true; actualPopupHeight = math.min(estimatedPopupHeight, availableSpaceAbove); popupTop = position.dy - actualPopupHeight - paddingOffset; } // 确保弹窗不会超出屏幕边界 popupTop = math.max(paddingOffset, popupTop); actualPopupHeight = math.min(actualPopupHeight, screenHeight * 0.7); // 限制最大高度为屏幕的70% // 计算左侧位置,确保不会超出屏幕右侧 double popupLeft = position.dx + size.width - popupWidth; if (popupLeft + popupWidth > screenWidth) { popupLeft = screenWidth - popupWidth - paddingOffset; } // setState(() { // _isPopupOpen = false; // }); _popupEntry?.remove(); _popupEntry = OverlayEntry( builder: (context) => GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; }, child: Stack( children: [ Positioned( top: popupTop, left: popupLeft, child: Material( color: Colors.transparent, child: Container( constraints: BoxConstraints( // maxWidth: popupWidth, maxWidth: screenWidth, maxHeight: actualPopupHeight, ), decoration: BoxDecoration( color: themeController.currentColor.sc17, borderRadius: BorderRadius.circular(12.rpx), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 12.rpx, spreadRadius: 1.rpx, offset: Offset(0, 6.rpx), ), ], ), child: SingleChildScrollView( child: popupContent, ), ), ), ), ], ), ), ); Overlay.of(context)?.insert(_popupEntry!); } // 构建弹窗内容 Widget _buildPopupContent() { final content = Container( padding: EdgeInsets.all(20.rpx), // decoration: BoxDecoration( // color: themeController.currentColor.sc17, // borderRadius: BorderRadius.circular(12.rpx), // boxShadow: [ // BoxShadow( // color: Colors.black.withOpacity(0.2), // blurRadius: 12.rpx, // spreadRadius: 1.rpx, // offset: Offset(0, 6.rpx), // ), // ], // ), child: Column( mainAxisSize: MainAxisSize.min, children: _buildMenuItems().divide(SizedBox( height: 6.rpx, )), ), ); return widget.device['bind_type'] == BindType.active.code ? _buildActiveDeviceContent(content) : _buildSharedDeviceContent(content); } // 构建主动绑定设备的菜单项 Widget _buildActiveDeviceContent(Widget content) { return IntrinsicWidth( child: content, ); } // 构建共享设备的菜单项 Widget _buildSharedDeviceContent(Widget content) { return IntrinsicWidth( child: content, ); } // 构建菜单项列表 List _buildMenuItems() { final items = [ _buildMenuItem( icon: widget.device['show'] != null && widget.device['show'] == true ? Icon(Icons.check, size: 24.rpx, color: themeController.currentColor.sc2) : null, text: "体征检测设备.首页展示".tr, onTap: () async { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; ApiResponse apiResponse = await bodyDeviceController.updateDeviceShow(widget.device); if (apiResponse.code == HttpStatusCodes.ok) { bodyDeviceController.getDeviceList(); bodyDeviceController.updateAll(); } else { TopSlideNotification.show( context, text: apiResponse.msg!, textColor: themeController.currentColor.sc9, ); } }, textColor: (widget.device['show'] != null && widget.device['show'] == true) ? themeController.currentColor.sc2 : themeController.currentColor.sc3, ), _buildMenuItem( text: "体征检测设备.设备详情".tr, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; Get.toNamed("/deviceDetail", arguments: widget.device); }, ), ]; if (widget.device['bind_type'] == BindType.active.code) { items.addAll([ _buildMenuItem( text: "WIFI配置".tr, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; dealWifi(widget.device); }, ), _buildMenuItem( text: "设备校准".tr, onTap: () async { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; BlueteethBindController blueteethBindController = Get.find(); blueteethBindController.currentDeviceMac?.value = widget.device['mac']; await Get.toNamed("/calibrationPage", arguments: 2); }, ), _buildMenuItem( text: "分享设备".tr, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; Get.toNamed("/deviceSharePage", arguments: widget.device); }, ), _buildMenuItem( text: "消息设置".tr, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; // Get.toNamed("/deviceDetail", arguments: widget.device); Get.toNamed("/messageSettingPage", arguments: widget.device); // TopSlideNotification.show(context, text: "待开发功能".tr); }, ), ]); } items.addAll([ _buildMenuItem( text: "体征检测设备.重命名".tr, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; _showRenameDialog(); }, ), _buildMenuItem( text: widget.device['bind_type'] == BindType.active.code ? "解绑".tr : "删除".tr, onTap: () { setState(() { _isPopupOpen = false; }); _popupEntry?.remove(); _popupEntry = null; _showUnbindConfirmDialog(); }, ), ]); return items; } // 构建单个菜单项 Widget _buildMenuItem({ Widget? icon, required String text, required VoidCallback onTap, Color? textColor, }) { return ClickableContainer( padding: EdgeInsets.symmetric(vertical: 16.rpx), backgroundColor: Colors.transparent, highlightColor: themeController.currentColor.sc16.withOpacity(0.1), borderRadius: 8.rpx, onTap: onTap, child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ icon ?? SizedBox(width: 24.rpx, height: 24.rpx), SizedBox(width: 10.rpx), Expanded( child: Text( text, style: TextStyle( fontSize: AppConstants().normal_text_fontSize, color: textColor ?? themeController.currentColor.sc3, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ); } // 显示重命名对话框 void _showRenameDialog() { personController.currentPersonId.value = widget.device['_id']; personController.name.value = ""; String text = "确定".tr; showSingleConfirmDialog( context, Padding( padding: EdgeInsetsDirectional.fromSTEB(0.rpx, 41.rpx, 0.rpx, 0), child: Container( height: 80.rpx, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12.rpx), ), child: Align( alignment: AlignmentDirectional(-1, 0), child: TextFormField( onChanged: (value) { personController.name.value = value; }, autofocus: false, decoration: InputDecoration( isDense: true, hintText: '请输入人员名称'.tr, hintStyle: FlutterFlowTheme.of(context).labelMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc4, ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Color(0x00000000), width: 1.rpx, ), borderRadius: BorderRadius.circular(8.rpx), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Color(0x00000000), width: 1.rpx, ), borderRadius: BorderRadius.circular(8.rpx), ), ), style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: Colors.black, ), cursorColor: FlutterFlowTheme.of(context).primaryText, ), ), ), ), '修改人员名称'.tr, onConfirm: () async { ApiResponse response = await personController.updatePersonName( widget.device['person'], widget.device['_id'], ); if (response.code == HttpStatusCodes.ok) { await bodyDeviceController.getDeviceList(); bodyDeviceController.updateAll(); } else { TopSlideNotification.show( context, text: response.msg!, textColor: themeController.currentColor.sc9, ); } }, onCancel: () { print('用户点击了取消'); }, confirmText: text, ); } // 显示解绑确认对话框 void _showUnbindConfirmDialog() { showConfirmDialog( context, Container(), "是否确认解绑".tr, onConfirm: () async { ApiResponse apiResponse = await bodyDeviceController.deleteDevice(widget.device); if (apiResponse.code == HttpStatusCodes.ok) { bodyDeviceController.getDeviceList(); TopSlideNotification.show( context, text: apiResponse.msg!, ); } else { TopSlideNotification.show( context, text: apiResponse.msg!, textColor: themeController.currentColor.sc9, ); } }, onCancel: () {}, ); } @override Widget build(BuildContext context) { return Container( width: double.infinity, decoration: BoxDecoration( color: themeController.currentColor.sc5, borderRadius: BorderRadius.circular(20.rpx), ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 30.rpx, 30.rpx, 30.rpx), child: Container( width: double.infinity, child: Column( mainAxisSize: MainAxisSize.max, children: [ Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( // 'TH689564522DL', '${widget.device['person']?['name'] ?? '未命名'.tr}', style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 30.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), // ClickableContainer( // key: _arrowKey, // padding: EdgeInsetsDirectional.fromSTEB( // 16.rpx, 16.rpx, 14.rpx, 16.rpx), // backgroundColor: Colors.transparent, // highlightColor: Colors.black.withOpacity(0.1), // borderRadius: 8.rpx, // onTap: _showPopup, // child: Container( // width: 15.rpx, // height: 8.rpx, // child: SvgPicture.asset( // 'assets/img/icon/arrow_down.svg', // fit: BoxFit.cover, // color: Colors.white, // ), // ), // ), ToggleColorContainer( key: _arrowKey, padding: EdgeInsetsDirectional.fromSTEB( 16.rpx, 16.rpx, 14.rpx, 16.rpx, ), initialColor: Colors.transparent, toggledColor: Colors.black.withOpacity(0.5), borderRadius: 8.rpx, onToggle: _showPopup, toggled: _isPopupOpen, child: Container( width: 15.rpx, height: 8.rpx, child: SvgPicture.asset( 'assets/img/icon/arrow_down.svg', fit: BoxFit.cover, color: Colors.white, ), ), ), ], ), SizedBox(height: 40.rpx), Row( mainAxisSize: MainAxisSize.max, children: [ Container( width: 100.rpx, constraints: BoxConstraints( minWidth: 105.rpx, ), decoration: BoxDecoration(), child: Text( '设备ID'.tr, style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc4, ), ), ), Text( '${widget.device['code'] ?? '未知数据'.tr}', style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ].divide(SizedBox(width: 34.rpx)), ), SizedBox(height: 40.rpx), Row( mainAxisSize: MainAxisSize.max, children: [ Container( width: 100.rpx, constraints: BoxConstraints( minWidth: 105.rpx, ), decoration: BoxDecoration(), child: Text( '更新时间'.tr, style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc4, ), ), ), Text( '${widget.device['status']['updateTime'] != null ? MyUtils.timestampToDateString(widget.device['status']['updateTime']) : '未知时间'.tr}', style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ].divide(SizedBox(width: 34.rpx)), ), SizedBox(height: 40.rpx), if (widget.device['bind_type'] == BindType.active.code) Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisSize: MainAxisSize.max, children: [ Container( width: 100.rpx, constraints: BoxConstraints( minWidth: 105.rpx, ), decoration: BoxDecoration(), child: Text( '已分享'.tr, style: FlutterFlowTheme.of(context) .bodyMedium .override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc4, ), ), ), Text( '${widget.device['shareNum']}' + "人".tr, style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ].divide(SizedBox(width: 34.rpx)), ), // Icon( // Icons.arrow_back, // color: FlutterFlowTheme.of(context).primaryText, // size: 24.rpx, // ), // Padding( // padding: // EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 14.rpx, 0), // child: Container( // width: 28.rpx, // height: 28.rpx, // // width: double.infinity, // decoration: BoxDecoration(), // child: SvgPicture.asset( // 'assets/img/icon/group.svg', // fit: BoxFit.cover, // // color: stringToColor("#333333"), //固定 // color: Colors.white, // ), // ), // ), ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.white, // 或设置为你需要的水波纹颜色 padding: EdgeInsetsDirectional.fromSTEB( 14.rpx, 0.rpx, 14.rpx, 0), // borderRadius: 0.rpx, // 圆形点击区域 onTap: () { // 你的点击逻辑 Get.toNamed("/deviceShareListPage", arguments: widget.device['mac']); }, child: Container( padding: EdgeInsetsDirectional.fromSTEB( 0, 0.rpx, 0.rpx, 0), // 外部 padding 移到内部 width: 28.rpx, height: 28.rpx, child: SvgPicture.asset( 'assets/img/icon/group.svg', fit: BoxFit.cover, color: Colors.white, ), ), ) ].divide(SizedBox(width: 34.rpx)), ), if (widget.device['bind_type'] == BindType.share.code) Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( mainAxisSize: MainAxisSize.max, children: [ Container( width: 100.rpx, constraints: BoxConstraints( minWidth: 105.rpx, ), decoration: BoxDecoration(), child: Text( '设备来源'.tr, style: FlutterFlowTheme.of(context) .bodyMedium .override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc4, ), ), ), Text( (widget.device['source']?.toString().isEmpty ?? true) ? '未知数据'.tr : widget.device['source'].toString(), style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ].divide(SizedBox(width: 34.rpx)), ), Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 14.rpx, 0), child: Container( decoration: BoxDecoration(), child: Text( "云关爱".tr, style: TextStyle( color: themeController.currentColor.sc4, fontSize: AppConstants().normal_text_fontSize, ), ), ), ), ].divide(SizedBox(width: 34.rpx)), ), SizedBox(height: 40.rpx), Row( mainAxisSize: MainAxisSize.max, children: [ Container( width: 100.rpx, constraints: BoxConstraints( minWidth: 105.rpx, ), decoration: BoxDecoration(), child: Text( '体征检测设备.设备状态'.tr, style: FlutterFlowTheme.of(context).bodyMedium.override( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc4, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), Row( mainAxisSize: MainAxisSize.max, children: [ if (widget.device['status']['signal'] != null && widget.device['status']['signal'] != -1 && widget.device['status']['status'] != null && widget.device['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 或根据你主题定制颜色 padding: EdgeInsets.zero, borderRadius: 0, onTap: () { // 点击事件 showTipDialog( context, Container( child: RichText( text: TextSpan( text: "信号强度".tr, // 文本前缀部分 style: TextStyle( color: themeController.currentColor.sc3, fontSize: AppConstants().title_text_fontSize, ), children: [ TextSpan( text: getBedSignal( widget.device['status'] ['signal']), // 状态部分 style: TextStyle( color: themeController.currentColor .sc2, // 同样颜色,也可改成其他颜色 fontSize: AppConstants() .title_text_fontSize, ), ), ], ), ), ), ); }, child: Container( width: 30.rpx, height: 24.rpx, child: Image.asset( 'assets/img/signal${_getSignalLevel(widget.device['status']['signal'])}.png'), ), ), if (widget.device['status']['inBed'] != null && widget.device['status']['status'] != null && widget.device['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { showTipDialog( context, Container( child: RichText( text: TextSpan( text: "是否在床".tr, // 文本前缀部分 style: TextStyle( color: themeController.currentColor.sc3, fontSize: AppConstants().title_text_fontSize, ), children: [ TextSpan( text: getBedStatus(widget .device['status']['inBed']), // 状态部分 style: TextStyle( color: themeController.currentColor .sc2, // 同样颜色,也可改成其他颜色 fontSize: AppConstants() .title_text_fontSize, ), ), ], ), ), ), ); }, child: SizedBox( width: 16.rpx, height: 36.rpx, child: SvgPicture.asset( widget.device['status']['inBed'] == 0 ? 'assets/img/icon/not_bed.svg' : 'assets/img/icon/in_bed.svg', fit: BoxFit.fill, ), ), ), if (widget.device['status']['failure'] != 0 && widget.device['status']['status'] != null && widget.device['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 可自定义点击水波纹颜色 padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { showTipDialog( context, Container( child: RichText( text: TextSpan( text: "设备故障".tr, // 文本前缀部分 style: TextStyle( color: themeController.currentColor.sc9, fontSize: AppConstants().title_text_fontSize, ), children: [ // TextSpan( // text:widget // .device['status']['status'] == 1?"在线".tr:"离线".tr, // 状态部分 // style: TextStyle( // color: themeController.currentColor // .sc2, // 同样颜色,也可改成其他颜色 // fontSize: AppConstants() // .title_text_fontSize, // ), // ), ], ), ), ), ); }, child: SizedBox( width: 27.rpx, height: 27.rpx, child: SvgPicture.asset( 'assets/img/icon/device_issue.svg', fit: BoxFit.cover, ), ), ), if (widget.device['status']['upgrade'] != 0 && widget.device['status']['status'] != null && widget.device['status']['status'] == 1) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 可自定义点击效果颜色 padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { //todo 升级 }, child: SizedBox( width: 34.rpx, height: 24.rpx, child: SvgPicture.asset( 'assets/img/icon/upgrade.svg', fit: BoxFit.cover, // color: themeController.currentColor.sc3, // 若你想加颜色控制可取消注释 ), ), ), if (widget.device['status']['status'] != null && widget.device['status']['status'] == 0) ClickableContainer( backgroundColor: Colors.transparent, highlightColor: Colors.grey, // 可替换为点击高亮色 padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), borderRadius: 0, onTap: () { showTipDialog( context, Container( child: RichText( text: TextSpan( text: "网络状态".tr, // 文本前缀部分 style: TextStyle( color: themeController.currentColor.sc3, fontSize: AppConstants().title_text_fontSize, ), children: [ TextSpan( text: widget.device['status'] ['status'] == 1 ? "在线".tr : "离线".tr, // 状态部分 style: TextStyle( color: themeController.currentColor .sc2, // 同样颜色,也可改成其他颜色 fontSize: AppConstants() .title_text_fontSize, ), ), ], ), ), ), ); }, child: SizedBox( width: 27.rpx, height: 27.rpx, child: SvgPicture.asset( // widget.device['status']['status'] == 1 // ? 'assets/img/icon/device_online.svg' // : 'assets/img/icon/device_offline.svg', 'assets/img/icon/device_issue.svg', fit: BoxFit.cover, ), ), ), ].divide(SizedBox(width: 50.rpx)), ), ].divide(SizedBox(width: 34.rpx)), ), SizedBox(height: 20.rpx), Divider( thickness: 0.5, color: themeController.currentColor.sc4, ), SizedBox(height: 5.rpx), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Expanded( child: CustomCard( borderRadius: AppConstants().button_container_radius, onTap: () async { if (widget.device['person'] != null) { personController.currentPersonId.value = widget.device['_id']; personController.name.value = widget.device['person']['name']; personController.gender.value = widget.device['person']['gender'] ?? 1; personController.weight?.value = widget.device['person']['weight'] == null ? '' : widget.device['person']['weight'] .toString(); personController.height.value = widget.device['person']['height'] == null ? '' : widget.device['person']['height'] .toString(); personController.selectedDiseaseIds.value = widget.device['person']['disease'] ?? []; personController.birthday.value = widget.device['person']['birthday'] ?? ''; personController.dateTime = MyUtils.formatBirthdayTime( widget.device['person']['birthday']); } else { personController.currentPersonId.value = widget.device['_id']; } await Get.toNamed("/updatePersonPage", arguments: widget.device['bind_type']); bodyDeviceController.getDeviceList(); }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 0.rpx, 0.rpx, 0.rpx), child: Container( alignment: Alignment.center, height: MediaQuery.sizeOf(context).height * 0.0037, constraints: BoxConstraints( minWidth: 143.rpx, minHeight: 61.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "体征检测设备.人员资料".tr, style: FlutterFlowTheme.of(context) .bodyMedium .override( color: themeController.currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants().normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide(SizedBox(width: 17.rpx)), ), ), ), ), ), SizedBox( width: 20.rpx, ), Expanded( // 使用 Expanded 来占据屏幕宽度 child: CustomCard( borderRadius: AppConstants().button_container_radius, onTap: () { Get.toNamed("/instantBodyPage", arguments: widget.device); }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], child: Container( alignment: Alignment.center, height: MediaQuery.sizeOf(context).height * 0.0037, constraints: BoxConstraints( minWidth: 143.rpx, minHeight: 61.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "体征检测设备.实时体征".tr, style: FlutterFlowTheme.of(context) .bodyMedium .override( color: themeController.currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants().normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide(SizedBox(width: 17.rpx)), ), ), ), ), ], ), SizedBox( height: 20.rpx, ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Expanded( // 使用 Expanded 来占据屏幕宽度的一半 child: CustomCard( borderRadius: AppConstants().button_container_radius, onTap: () { // TopSlideNotification.show(context, text: "待开发功能".tr); Get.toNamed("/messageReviewPage", arguments: widget.device); }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 0.rpx, 0.rpx, 0.rpx), child: Container( alignment: Alignment.center, height: MediaQuery.sizeOf(context).height * 0.0037, constraints: BoxConstraints( minWidth: 143.rpx, minHeight: 61.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "体征检测设备.消息回看".tr, style: FlutterFlowTheme.of(context) .bodyMedium .override( color: themeController.currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants().normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide(SizedBox(width: 17.rpx)), ), ), ), ), ), SizedBox( width: 20.rpx, ), Expanded( // 使用 Expanded 来占据屏幕宽度的一半 child: CustomCard( borderRadius: AppConstants().button_container_radius, onTap: () { String mac = widget.device['mac']; String sleepReportUrl = "${ServiceConstant.sleep_report_url}?mac=${mac}&token=${ServiceConstant.sleep_token}"; Get.toNamed("/sleepReportPage", arguments: sleepReportUrl); }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 0.rpx, 0.rpx, 0.rpx), child: Container( alignment: Alignment.center, height: MediaQuery.sizeOf(context).height * 0.0037, constraints: BoxConstraints( minWidth: 143.rpx, minHeight: 61.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "体征检测设备.健康报告".tr, style: FlutterFlowTheme.of(context) .bodyMedium .override( color: themeController.currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants().normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide(SizedBox(width: 17.rpx)), ), ), ), ), ), ], ), ].divide(SizedBox(height: 0.rpx)), ), ), ), ); } String getBedStatus(int status) { if (status == 0) { return "离床".tr; } else if (status == 1) { return "在床".tr; } return ""; } getBedSignal(signal) { if (signal <= 1) { return "较弱".tr; } if (signal > 1 && signal <= 2) { return "弱".tr; } if (signal > 2 && signal <= 3) { return "一般".tr; } if (signal > 3) { return "强".tr; } return "未知数据".tr; } Future dealWifi(device) async { bodyDeviceController.wifiMac = device['mac']; Get.toNamed("/wifiPage", arguments: device); return; // final blueteethBindController = Get.find(); // final themeController = Get.find(); // // 显示加载对话框 // showLoadingDialog(Get.context!, title: "连接中...".tr); // // 设置超时定时器 // Timer? timeoutTimer; // bool isConnected = false; // try { // // 开始扫描蓝牙设备 // await FlutterBluePlus.startScan(timeout: Duration(seconds: 10)); // // 设置超时(20秒) // timeoutTimer = Timer(Duration(seconds: 20), () { // try { // if (!isConnected) { // Navigator.of(context).pop(); // 先关闭 dialog // WidgetsBinding.instance.addPostFrameCallback((_) { // TopSlideNotification.show( // context, // text: "设备连接超时,请重试".tr, // textColor: themeController.currentColor.sc9, // ); // }); // FlutterBluePlus.stopScan(); // } // } catch (e) { // print(e); // } // }); // // 监听扫描结果 // StreamSubscription>? scanSubscription; // scanSubscription = FlutterBluePlus.scanResults.listen((results) async { // // 过滤出符合条件的设备 // ScanResult? targetDevice; // for (var r in results) { // if (r.advertisementData.manufacturerData.containsKey(0xFFED)) { // List rawData = r.advertisementData.manufacturerData[0xFFED]!; // BleDeviceData deviceData = parseBleData(rawData); // String deviceMac = // deviceData.deviceId.replaceAll(':', '').toLowerCase(); // if (deviceMac == mac.toLowerCase()) { // targetDevice = r; // break; // } // } // } // if (targetDevice != null && !isConnected) { // isConnected = true; // FlutterBluePlus.stopScan(); // scanSubscription?.cancel(); // timeoutTimer?.cancel(); // try { // // 连接设备 // // await targetDevice.device.connect(); // THapp bledevice = THapp(device: targetDevice.device); // await bledevice.device.connect(); // var res2 = bledevice.isConnected; // if (res2) { // Navigator.pop(context); // TopSlideNotification.show( // context, // text: "蓝牙绑定.连接成功".tr, // textColor: themeController.currentColor.sc2, // ); // blueteethBindController.currentDevice = bledevice; // if (lisObj != null) { // lisObj!.cancel(); // } // var aa; // lisObj = blueteethBindController.currentDevice!.statusStream // .listen((onData) async { // if (onData.status == BleEventType.recvLineLog) { // final line = onData.val; // print("[bleee]:" + line); // } // if (onData.status == BleEventType.ready) { // aa = await getDeviceNetVersion( // blueteethBindController.currentDevice!, 1); // if (aa == "4g") { // // TopSlideNotification.show( // // Get.context!, // // text: "4g设备配置wifi提示".tr, // // textColor: themeController.currentColor.sc9, // // ); // WidgetsBinding.instance.addPostFrameCallback((_) { // TopSlideNotification.show( // context, // text: "4g设备配置wifi提示".tr, // textColor: themeController.currentColor.sc9, // ); // }); // return; // } else { // Get.toNamed("/wifiPage", arguments: 2); // } // } // }); // // Get.toNamed("/wifiPage", arguments: {bledevice}); // } else { // Navigator.pop(context); // TopSlideNotification.show( // context, // text: "蓝牙绑定.连接失败".tr, // textColor: themeController.currentColor.sc9, // ); // } // } catch (e) { // Navigator.of(Get.context!).pop(); // 关闭加载对话框 // TopSlideNotification.show( // Get.context!, // text: "设备连接失败".tr, // textColor: themeController.currentColor.sc9, // ); // } // } // }); // // 等待扫描完成 // await Future.delayed(Duration(seconds: 20)); // } catch (e) { // timeoutTimer?.cancel(); // Navigator.of(Get.context!).pop(); // 关闭加载对话框 // TopSlideNotification.show( // Get.context!, // text: "扫描过程中发生错误".tr, // textColor: themeController.currentColor.sc9, // ); // } finally { // timeoutTimer?.cancel(); // await FlutterBluePlus.stopScan(); // } } double _calculateMaxMenuItemWidth(List texts, TextStyle style) { double maxTextWidth = 0; for (final text in texts) { final painter = TextPainter( text: TextSpan(text: text, style: style), maxLines: 1, textDirection: ui.TextDirection.ltr, )..layout(); if (painter.width > maxTextWidth) { maxTextWidth = painter.width; } } final iconWidth = 24.rpx; final spacing = 10.rpx; final horizontalPadding = 40.rpx; return iconWidth + spacing + maxTextWidth + horizontalPadding; } int _getSignalLevel(int signal) { if (signal <= 25) { return 1; } else if (signal <= 50) { return 2; } else if (signal <= 75) { return 3; } else { return 4; } } }