Files
tuiche/lib/pages/device/component/DeviceDataComponentWidget.dart
2025-05-15 13:57:42 +08:00

1310 lines
51 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:easydevice/easydevice.dart';
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.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/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/controller/theme_controller/ThemeController.dart';
import 'package:vbvs_app/enum/BindType.dart';
import 'package:vbvs_app/model/BleDeviceData.dart';
import 'package:vbvs_app/model/api_response.dart';
import 'package:vbvs_app/pages/device_bind/blueteeth_device_page.dart';
import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
import 'dart:math' as math;
import 'dart:ui' as ui;
class DeviceDataComponentWidget extends StatefulWidget {
final Map<String, dynamic> device;
const DeviceDataComponentWidget({super.key, required this.device});
@override
State<DeviceDataComponentWidget> createState() =>
_DeviceDataComponentWidgetState();
}
class _DeviceDataComponentWidgetState extends State<DeviceDataComponentWidget> {
final GlobalKey _arrowKey = GlobalKey();
OverlayEntry? _popupEntry;
BodyDeviceController bodyDeviceController = Get.find();
PersonController personController = Get.find();
@override
void dispose() {
_popupEntry?.remove();
super.dispose();
}
void _showPopup() {
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, // 你也可以传 sc2
);
final allTexts = [
"体征检测设备.首页展示".tr,
"体征检测设备.设备详情".tr,
"WIFI配置".tr,
"设备校准".tr,
"分享设备".tr,
"消息设置".tr,
"体征检测设备.重命名".tr,
"体征检测设备.删除".tr,
];
final menuWidth = _calculateMaxMenuItemWidth(allTexts, textStyle);
popupWidth = menuWidth;
// 计算弹窗需要的实际高度(估算)
final estimatedItemHeight = 60.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;
}
_popupEntry?.remove();
_popupEntry = OverlayEntry(
builder: (context) => GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_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(),
),
);
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 content;
}
// 构建菜单项列表
List<Widget> _buildMenuItems() {
final items = <Widget>[
_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 {
_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: () {
_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: () {
// _popupEntry?.remove();
// _popupEntry = null;
// // Get.toNamed("/deviceDetail", arguments: widget.device);
// dealWifi(widget.device['mac']);
// },
// ),
_buildMenuItem(
text: "WIFI配置".tr,
onTap: () {
_popupEntry?.remove();
_popupEntry = null;
dealWifi(widget.device['mac']);
},
),
_buildMenuItem(
text: "设备校准".tr,
onTap: () {
_popupEntry?.remove();
_popupEntry = null;
BlueteethBindController blueteethBindController = Get.find();
blueteethBindController.currentDeviceMac = widget.device['mac'];
Get.toNamed("/calibrationPage", arguments: 2);
},
),
_buildMenuItem(
text: "分享设备".tr,
onTap: () {
_popupEntry?.remove();
_popupEntry = null;
Get.toNamed("/deviceSharePage", arguments: widget.device);
},
),
_buildMenuItem(
text: "消息设置".tr,
onTap: () {
_popupEntry?.remove();
_popupEntry = null;
// Get.toNamed("/deviceDetail", arguments: widget.device);
TopSlideNotification.show(context, text: "待开发功能".tr);
},
),
]);
}
items.addAll([
_buildMenuItem(
text: "体征检测设备.重命名".tr,
onTap: () {
_popupEntry?.remove();
_popupEntry = null;
_showRenameDialog();
},
),
_buildMenuItem(
text: "体征检测设备.删除".tr,
onTap: () {
_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 = "";
showConfirmDialog(
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('用户点击了取消');
},
);
}
// 显示解绑确认对话框
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,
),
),
),
],
),
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(
'张三',
style:
FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
color: themeController.currentColor.sc4,
),
),
].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)
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: SvgPicture.asset(
'assets/img/icon/signal${widget.device['status']['wifi']}.svg',
width: 25.rpx,
height: 25.rpx,
fit: BoxFit.fill,
),
),
if (widget.device['status']['inBed'] != null)
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)
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)
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)
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',
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: [
CustomCard(
borderRadius: AppConstants().button_container_radius,
onTap: () async {
// personController.currentPersonId = widget.device
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'] ?? 0;
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(
width: MediaQuery.sizeOf(context).width * 0.19,
height: MediaQuery.sizeOf(context).height * 0.0037,
constraints: BoxConstraints(
minWidth: 143.rpx,
minHeight: 61.rpx,
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.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)),
),
),
),
),
CustomCard(
borderRadius: AppConstants().button_container_radius,
onTap: () {
Get.toNamed("/instantBodyPage", arguments: widget.device);
},
colors: [
themeController.currentColor.sc1,
themeController.currentColor.sc2,
],
child: Container(
width: MediaQuery.sizeOf(context).width * 0.19,
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)),
),
),
),
CustomCard(
borderRadius: AppConstants().button_container_radius,
onTap: () {
TopSlideNotification.show(context, text: "待开发功能".tr);
},
colors: [
themeController.currentColor.sc1,
themeController.currentColor.sc2,
],
child: Container(
width: MediaQuery.sizeOf(context).width * 0.19,
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)),
),
),
),
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: Container(
width: MediaQuery.sizeOf(context).width * 0.19,
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<void> dealWifi(String mac) async {
final blueteethBindController = Get.find<BlueteethBindController>();
final themeController = Get.find<ThemeController>();
// 显示加载对话框
showLoadingDialog(Get.context!, title: "连接中...".tr);
// 设置超时定时器
Timer? timeoutTimer;
bool isConnected = false;
try {
// 开始扫描蓝牙设备
await FlutterBluePlus.startScan(timeout: Duration(seconds: 20));
// 设置超时20秒
timeoutTimer = Timer(Duration(seconds: 20), () {
if (!isConnected) {
Navigator.of(Get.context!).pop(); // 关闭加载对话框
TopSlideNotification.show(
Get.context!,
text: "设备连接超时,请重试".tr,
textColor: themeController.currentColor.sc9,
);
FlutterBluePlus.stopScan();
}
});
// 监听扫描结果
StreamSubscription<List<ScanResult>>? scanSubscription;
scanSubscription = FlutterBluePlus.scanResults.listen((results) async {
// 过滤出符合条件的设备
final targetDevice = results.firstWhere(
(r) {
try {
if (r.advertisementData.manufacturerData.containsKey(0xFFED)) {
List<int> rawData =
r.advertisementData.manufacturerData[0xFFED]!;
BleDeviceData deviceData = parseBleData(rawData);
String deviceMac =
deviceData.deviceId.replaceAll(':', '').toLowerCase();
return deviceMac == mac.toLowerCase();
}
return false;
} catch (e) {
return false;
}
},
);
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;
// Get.toNamed("/wifiPage", arguments: {bledevice});
Get.toNamed("/wifiPage", arguments: 1);
} 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<String> 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;
}
}
_showBluetoothNotEnabledDialog() async {
await showDialog(
context: Get.context!,
builder: (_) => AlertDialog(
title: Text("蓝牙未开启"),
content: Text("请先打开蓝牙再进行WIFI配置"),
actions: [
TextButton(
onPressed: () => Navigator.of(Get.context!).pop(),
child: Text("知道了"),
),
],
),
);
}