Files
tuiche/lib/pages/mh_page/bluetooth.dart
2026-04-07 14:49:31 +08:00

503 lines
25 KiB
Dart
Raw Permalink 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 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/svg.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/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/controller/mh_controller/device_list_controller.dart';
import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
import 'package:vbvs_app/pages/mh_page/device/device.dart';
import 'package:vbvs_app/pages/mh_page/homepage/controller/mht_home_controller.dart';
import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart';
class BluetoothPage extends StatefulWidget {
final Map data;
BluetoothPage({Key? key, required this.data});
@override
_BluetoothPageState createState() => _BluetoothPageState();
}
class _BluetoothPageState extends State<BluetoothPage> {
late RxMap<String, dynamic> obsData;
double _textHalfWidth = 0;
@override
void initState() {
super.initState();
obsData = Map<String, dynamic>.from(widget.data).obs; // 复制成 obs
}
BoxConstraints? bodysize;
DeviceListController deviceListController = Get.find();
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, cc) {
bodysize = cc;
final isBind = obsData['bind_type'] == 1;
return GestureDetector(
// onTap: () => FocusScope.of(context).unfocus(),,
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/new_background.png'), // 本地图片
fit: BoxFit.fill, // 填满整个 Container
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent, // 状态栏背景色
statusBarIconBrightness: Brightness.light, // 图标颜色Android
statusBarBrightness: Brightness.light, // 图标颜色iOS
),
backgroundColor: Colors.transparent,
iconTheme: const IconThemeData(color: Colors.white),
automaticallyImplyLeading: false,
titleSpacing: 0,
title: SizedBox(
width: double.infinity,
height: 180.rpx,
child: Stack(
alignment: Alignment.center,
children: [
// 中间居中的标题
Text(
'设置'.tr,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 30.rpx,
),
),
// 左侧图标
Positioned(
left: 0.rpx,
child: returnIconButtomNew(),
),
],
),
),
centerTitle: false,
),
body: SafeArea(
top: true,
child: Padding(
padding: EdgeInsets.fromLTRB(0.rpx, 115.rpx, 0.rpx, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Column(
children: [
Padding(
padding:
EdgeInsets.symmetric(horizontal: 30.rpx),
child: Container(
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
_limitText(
obsData['name']?.toString() ??
getNameByType(obsData.value),
AppConstants().text_length),
style: TextStyle(
color: Colors.white,
fontSize: 40.rpx,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
textAlign: TextAlign.center,
),
),
SizedBox(width: 10.rpx),
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: const Color(0xFF055466),
padding: EdgeInsets.zero,
onTap: () async {
var x = await Get.toNamed(
"/editBedPage",
arguments: obsData);
if (x != null) {
setState(() {
obsData.addAll(x);
});
}
},
child: SizedBox(
width: 42.rpx,
height: 42.rpx,
child: SvgPicture.asset(
"assets/img/icon/bluetooth_edit.svg",
color: Colors.white,
),
),
),
],
),
// Stack(
// alignment: Alignment.center,
// children: [
// Text(
// obsData['name']?.toString() ??
// getNameByType(obsData.value),
// style: TextStyle(
// color: Colors.white,
// fontSize: 40.rpx,
// ),
// overflow:
// TextOverflow.ellipsis, // 超出部分显示省略号
// maxLines: 1, // 限制为单行
// ),
// Positioned(
// left: MediaQuery.of(context)
// .size
// .width /
// 2 +
// _calculateTextHalfWidth(
// obsData['name']?.toString() ??
// getNameByType(
// obsData.value)) +
// 22.rpx,
// top: 5.rpx,
// child: ClickableContainer(
// backgroundColor:
// Colors.transparent,
// highlightColor:
// const Color(0xFF055466),
// padding: EdgeInsets.only(left: 0),
// onTap: () async {
// var x = await Get.toNamed(
// "/editBedPage",
// arguments: obsData);
// if (x != null) {
// setState(() {
// obsData.addAll(
// x); // 值更新后主动刷新页面
// });
// }
// },
// child: Container(
// width: 42.rpx,
// height: 42.rpx,
// child: SvgPicture.asset(
// "assets/img/icon/bluetooth_edit.svg",
// color: Colors.white,
// ))))
// ],
// ),
),
),
const SizedBox(height: 4),
Text(obsData['mac'.tr]?.toString() ?? '未命名'.tr,
style: TextStyle(
color: Colors.white70, fontSize: 26.rpx)),
const SizedBox(height: 16),
// 蓝牙连接状态
Column(
children: [
obsData['blueToothStatus'] == 2
? SvgPicture.asset(
'assets/img/icon/blue_success.svg',
width: 68.rpx,
height: 68.rpx,
)
: SvgPicture.asset(
'assets/img/icon/blue_fail.svg',
width: 68.rpx,
height: 68.rpx,
),
SizedBox(height: 4),
//下面文字和颜色也根据上面变化
Text(
obsData['blueToothStatus'] == 2
? '已连接'.tr
: '未连接'.tr,
style: TextStyle(
color: obsData['blueToothStatus'] == 2
? Color(0xFF6BFDAC)
: Color(0xFFFF7159),
fontSize: 26.rpx)),
],
),
],
),
const SizedBox(height: 24),
Expanded(
child: ListView(
padding: EdgeInsets.only(
left: 30.rpx, right: 30.rpx, bottom: 60.rpx),
reverse: !isBind,
children: [
if (isBind) ...[
_buildMenuButton(
context, '详情'.tr, "/devicePeopleInfo",
arguments: obsData),
_buildMenuButton(
context,
'人员资料'.tr,
"/peopleInfoPage",
arguments: obsData,
),
_buildMenuButton(
context, '房间选择'.tr, "/roomPickerPage",
arguments: obsData, onResult: (result) {
if (result != null && result is Map) {
final Map<String, dynamic> safeMap =
result.map(
(key, value) =>
MapEntry(key.toString(), value),
);
setState(() {
obsData.addAll(safeMap);
});
}
}),
_buildMenuButton(
context,
'设备校准'.tr,
"/mhtCalibrationAfterPage",
arguments: obsData,
),
_buildMenuButton(context, '体征传感器'.tr,
"/vitalSignsSensorPage",
arguments: obsData),
_buildMenuButton(
context,
'WIFI配置'.tr,
"/mhtWifiAfterPage",
arguments: obsData,
),
_buildMenuButton(
context, '睡眠习惯'.tr, "/sleepHabitPage"),
_buildMenuButton(
context, '分享设备'.tr, "/deviceSharePage",
arguments: obsData),
],
if (!isBind) ...[
_buildMenuButton(
context,
obsData['bind_type'] == 1
? '解绑'.tr
: '删除'.tr,
"",
onTap: () async {
if (obsData['bind_type'] == 1) {
// 解绑弹窗
showUnbindConfirmDialog(
context: context,
title: "是否进行解绑?".tr,
onConfirm: () async {
await deviceListController
.unbindDevice(obsData);
await deviceListController
.getDeviceList();
MHTHomeController homeController =
Get.find();
homeController.selectDevcie.value =
"";
await homeController
.getPersonList();
try {
WebviewTestController
webviewTestController =
Get.find();
webviewTestController
.web.jsbridge?.dart
.unBindDevice();
} catch (e) {
ef.log("[h5]通知列表更新报错:$e");
}
Get.toNamed(
"/mianPageBottomChange");
// 执行解绑逻辑
},
onCancel: () {
// 点击取消后的逻辑
},
);
} else if (obsData['bind_type'] == 2) {
// 删除弹窗
showDeleteDeviceConfirmDialog(
context: context,
title: "是否进行删除?".tr,
onConfirm: () async {
await deviceListController
.unbindDevice(
obsData,
);
await deviceListController
.getDeviceList();
Get.toNamed(
"/mianPageBottomChange");
},
onCancel: () {
// 点击取消后的逻辑
},
);
}
},
),
_buildMenuButton(
context, '详情'.tr, "/devicePeopleInfo",
arguments: obsData),
],
if (isBind) ...[
_buildMenuButton(
context,
obsData['bind_type'] == 1
? '解绑'.tr
: '删除'.tr,
"",
onTap: () {
if (obsData['bind_type'] == 1) {
// 解绑弹窗
showUnbindConfirmDialog(
context: context,
title: "是否进行解绑?".tr,
onConfirm: () async {
await deviceListController
.unbindDevice(obsData);
await deviceListController
.getDeviceList();
MHTHomeController homeController =
Get.find();
homeController.selectDevcie.value =
"";
try {
WebviewTestController
webviewTestController =
Get.find();
webviewTestController
.web.jsbridge?.dart
.unBindDevice();
} catch (e) {
ef.log("[h5]通知列表更新报错:$e");
}
Get.toNamed(
"/mianPageBottomChange");
// 执行解绑逻辑
},
onCancel: () {
// 点击取消后的逻辑
},
);
} else if (obsData['bind_type'] == 2) {
// 删除弹窗
showDeleteDeviceConfirmDialog(
context: context,
title: "是否进行删除?".tr,
onConfirm: () async {
await deviceListController
.unbindDevice(
obsData,
);
await deviceListController
.getDeviceList();
Get.toNamed(
"/mianPageBottomChange");
},
onCancel: () {
// 点击取消后的逻辑
},
);
}
},
),
],
],
),
),
],
),
)),
)));
});
}
Widget _buildMenuButton(
BuildContext context,
String title,
String? path, {
Map<dynamic, dynamic>? arguments,
VoidCallback? onTap,
ValueChanged<dynamic>? onResult, // ✅ 可选返回值处理器
}) {
return Padding(
padding: EdgeInsets.only(bottom: 19.rpx),
child: ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: const Color(0XFF055466),
borderRadius: 16.rpx,
padding: EdgeInsets.only(left: 0),
onTap: () async {
if (onTap != null) {
onTap(); // 自定义点击逻辑优先执行
} else if (path?.isNotEmpty == true) {
if (path == "/sleepHabitPage") {
Get.back();
WebviewTestController webviewTestController = Get.find();
webviewTestController.web.jsbridge?.dart.toSleepHabit();
return;
}
final result = await Get.toNamed(path!, arguments: arguments);
if (result != null && onResult != null) {
onResult(result); // ✅ 有回调就处理返回值
}
} else {
TopSlideNotification.show(context, text: "功能开发中...");
}
},
child: Container(
height: MediaQuery.sizeOf(context).height * 0.0566,
decoration: BoxDecoration(
color: const Color(0xFF003058),
borderRadius: BorderRadius.circular(16.rpx),
),
child: Center(
child: Text(
title,
style: const TextStyle(color: Colors.white, fontSize: 16),
),
),
),
),
);
}
String _limitText(String? text, int maxLength) {
if (text == null || text.length <= maxLength) return text ?? '';
return text.substring(0, maxLength) + '...';
}
}
// double _calculateTextHalfWidth(String text) {
// final textPainter = TextPainter(
// text: TextSpan(
// text: text,
// style: TextStyle(
// fontSize: 40.rpx,
// height: 1,
// ),
// ),
// textDirection: ui.TextDirection.ltr,
// );
// textPainter.layout();
// return textPainter.width / 2;
// }