This commit is contained in:
czz
2025-07-19 17:53:41 +08:00
12 changed files with 356 additions and 164 deletions

Binary file not shown.

View File

@@ -12,8 +12,13 @@ import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
class SleepDataModuleWidget extends StatefulWidget { class SleepDataModuleWidget extends StatefulWidget {
final Map<String, dynamic> data; final Map<String, dynamic> data;
final dynamic sleepReportData; // 可选参数,类型为 var/dynamic
const SleepDataModuleWidget({super.key, required this.data}); const SleepDataModuleWidget({
super.key,
required this.data,
this.sleepReportData, // 标记为可选参数
});
@override @override
State<SleepDataModuleWidget> createState() => _SleepDataModuleWidgetState(); State<SleepDataModuleWidget> createState() => _SleepDataModuleWidgetState();
@@ -47,17 +52,18 @@ class _SleepDataModuleWidgetState extends State<SleepDataModuleWidget> {
if (widget.data['showTip'] != null && widget.data['showTip'] == true) { if (widget.data['showTip'] != null && widget.data['showTip'] == true) {
final String itemLevel = widget.data['code'] ?? ''; final String itemLevel = widget.data['code'] ?? '';
SleepReportController sleepReportController = Get.find(); SleepReportController sleepReportController = Get.find();
var report = sleepReportController.sleepReport; var report = sleepReportController.sleepReport;
List<Map<String, dynamic>> levelGroups = []; List<Map<String, dynamic>> levelGroups = [];
if (widget.sleepReportData != null) {
report = widget.sleepReportData;
}
if (report != null) { if (report != null) {
var colorMap = var colorMap =
Map<String, dynamic>.from(report.value['info']['color']); Map<String, dynamic>.from(report.value['info']['color']);
var levelMap = var levelMap =
Map<String, dynamic>.from(report.value['info']['level']); Map<String, dynamic>.from(report.value['info']['level']);
//修改渲染
for (var prefix in ['G', 'R', 'Y']) { for (var prefix in ['G', 'Y', 'R']) {
List<String> keys = List<String> keys =
colorMap.keys.where((k) => k.startsWith(prefix)).toList(); colorMap.keys.where((k) => k.startsWith(prefix)).toList();
keys.sort(); // G1, G2, G3 keys.sort(); // G1, G2, G3

View File

@@ -241,8 +241,8 @@ class _BluetoothPageState extends State<BluetoothPage> {
context, '体征传感器', "/vitalSignsSensorPage", context, '体征传感器', "/vitalSignsSensorPage",
arguments: obsData), arguments: obsData),
_buildMenuButton(context, 'WIFI配置', ""), _buildMenuButton(context, 'WIFI配置', ""),
_buildMenuButton( // _buildMenuButton(
context, '睡眠习惯', "/sleepHabitPage"), // context, '睡眠习惯', "/sleepHabitPage"),
_buildMenuButton( _buildMenuButton(
context, '分享设备', "/deviceSharePage", context, '分享设备', "/deviceSharePage",
arguments: obsData), arguments: obsData),
@@ -406,6 +406,11 @@ class _BluetoothPageState extends State<BluetoothPage> {
if (onTap != null) { if (onTap != null) {
onTap(); // 自定义点击逻辑优先执行 onTap(); // 自定义点击逻辑优先执行
} else if (path?.isNotEmpty == true) { } else if (path?.isNotEmpty == true) {
if (path == "/sleepHabitPage") {
WebviewTestController webviewTestController = Get.find();
webviewTestController.web.jsbridge?.dart.toSleepHabit();
return;
}
final result = await Get.toNamed(path!, arguments: arguments); final result = await Get.toNamed(path!, arguments: arguments);
if (result != null && onResult != null) { if (result != null && onResult != null) {
onResult(result); // ✅ 有回调就处理返回值 onResult(result); // ✅ 有回调就处理返回值

View File

@@ -541,7 +541,8 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
DailyLogUtils.printLog("蓝牙获取MAC失败$e"); DailyLogUtils.printLog("蓝牙获取MAC失败$e");
TopSlideNotification.show( TopSlideNotification.show(
context, context,
text: "设备连接失败,请重试".tr, // text: e.message ?? "设备连接失败,请重试".tr,
text: "获取不到传感器mac,请重试".tr,
textColor: themeController.currentColor.sc9, textColor: themeController.currentColor.sc9,
); );
rethrow; rethrow;
@@ -632,6 +633,12 @@ class _DeviceComponentWidgetState extends State<DeviceComponentWidget> {
try { try {
final mac = await completer.future.timeout(timeout); final mac = await completer.future.timeout(timeout);
if (mac == null || mac.isEmpty) {
throw Exception("获取MAC失败");
}
if (mac == "000000000000") {
throw Exception("获取MAC失败");
}
await subscription.cancel(); await subscription.cancel();
return mac; return mac;
} catch (_) { } catch (_) {

View File

@@ -241,6 +241,7 @@ class MHTBlueToothController extends GetControllerEx<MHTBlueToothModel> {
if (currentFullDevice != null) { if (currentFullDevice != null) {
currentFullDevice!.macAID = res.data['macA']; currentFullDevice!.macAID = res.data['macA'];
currentFullDevice!.macBID = res.data['macB']; currentFullDevice!.macBID = res.data['macB'];
currentFullDevice!.deviceID = res.data['id'];
} }
} }
return res; return res;

View File

@@ -195,7 +195,12 @@ class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
TopSlideNotification.show(context, text: "保存成功"); TopSlideNotification.show(context, text: "保存成功");
MHTHomeController mhtHomeController = Get.find(); MHTHomeController mhtHomeController = Get.find();
mhtHomeController.getPersonList(); mhtHomeController.getPersonList();
Get.offNamed("/bindDeviceSuccess"); // Get.offNamed("/bindDeviceSuccess");
Map data = {};
final device = bluetoothController.currentFullDevice;
data['_id'] = device!.deviceID;
data['isNextStep'] = true;
Get.toNamed("/editBedPage", arguments: data);
}, },
colors: const [ colors: const [
Color(0xFFFCFCFC), Color(0xFFFCFCFC),

View File

@@ -10,7 +10,8 @@ class BlueToothDataModel {
int type; int type;
String? macAID; String? macAID;
String? macBID; String? macBID;
DateTime lastSeen; // 添加的最后可见时间字段 DateTime lastSeen; // 最后可见时间
String? deviceID; // 设备ID
BlueToothDataModel({ BlueToothDataModel({
this.name = '', this.name = '',
@@ -20,12 +21,18 @@ class BlueToothDataModel {
required this.type, required this.type,
this.macA = '', this.macA = '',
this.macB = '', this.macB = '',
required this.lastSeen, // 添加到构造函数参数 required this.lastSeen,
this.deviceID, // ✅ 加入构造函数参数
}); });
factory BlueToothDataModel.fromScanResult(ScanResult result, int type, factory BlueToothDataModel.fromScanResult(
{bool bind = false, String name = '', String mac = ''}) { ScanResult result,
// 如果外部没有传入 name则取 localName int type, {
bool bind = false,
String name = '',
String mac = '',
String? deviceID, // ✅ 工厂方法接收 deviceID
}) {
String finalName = String finalName =
name.isNotEmpty ? name : (result.advertisementData.localName ?? ''); name.isNotEmpty ? name : (result.advertisementData.localName ?? '');
@@ -35,9 +42,10 @@ class BlueToothDataModel {
mac: mac, mac: mac,
scanResult: result, scanResult: result,
type: type, type: type,
macA: '', // 保持原有默认值 macA: '',
macB: '', // 保持原有默认值 macB: '',
lastSeen: DateTime.now(), // 设置为当前时间 lastSeen: DateTime.now(),
deviceID: deviceID, // ✅ 赋值
); );
} }
} }

View File

@@ -9,11 +9,17 @@ import 'package:vbvs_app/component/tool/CustomCard.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/controller/mh_controller/device_list_controller.dart'; import 'package:vbvs_app/controller/mh_controller/device_list_controller.dart';
import 'package:vbvs_app/pages/mh_page/bluetooth.dart'; import 'package:vbvs_app/pages/mh_page/bluetooth.dart';
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart'; import 'package:vbvs_app/pages/mh_page/test/WebviewTestModel.dart';
class EditBedPage extends StatefulWidget { class EditBedPage extends StatefulWidget {
final Map data; final Map data;
EditBedPage({Key? key, required this.data});
EditBedPage({
Key? key,
required this.data,
}) : super(key: key);
@override @override
_EditBedPageState createState() => _EditBedPageState(); _EditBedPageState createState() => _EditBedPageState();
} }
@@ -79,6 +85,70 @@ class _EditBedPageState extends State<EditBedPage> {
left: 0.rpx, left: 0.rpx,
child: returnIconButtomNew, child: returnIconButtomNew,
), ),
if (widget.data != null &&
(widget.data['isNextStep'] != null &&
widget.data['isNextStep'] == true))
Positioned(
right: 30.rpx,
child: CustomCard(
borderRadius: 16.rpx,
gradientDirection: GradientDirection.vertical,
onTap: () async {
String serviceAddress =
ServiceConstant.service_address;
String serviceName = ServiceConstant.server_service;
String serviceApi = ServiceConstant.device_show;
String queryUrl =
"$serviceAddress$serviceName$serviceApi";
await requestWithLog(
logTitle: "更新设备信息",
method: MyHttpMethod.put,
queryUrl: queryUrl,
data: {
"id": editedData["_id"],
"name": editedData["name"],
},
onSuccess: (res) {
TopSlideNotification.show(context,
text: "修改名称成功".tr);
deviceListController.getDeviceList();
Map data = {};
final MHTBlueToothController
bluetoothController = Get.find();
final device =
bluetoothController.currentFullDevice;
data['_id'] = device!.deviceID;
data['isNextStep'] = true;
Get.toNamed("/roomPickerPage",
arguments: data);
},
);
},
colors: const [
Color(0xFFFCFCFC),
Color(0xFFF8FAF9),
Color(0XFFECF6F3),
Color(0XFFD9F0E9),
Color(0xFFCEECE3)
],
child: Container(
width: 120.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text(
"下一步",
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0XFF011D33),
letterSpacing: 0,
fontSize: 30.rpx,
),
),
),
),
)
], ],
), ),
), ),
@@ -186,64 +256,67 @@ class _EditBedPageState extends State<EditBedPage> {
], ],
), ),
), ),
Padding( if (widget.data['isNextStep'] == null ||
padding: EdgeInsets.only( widget.data['isNextStep'] == false)
left: 30.rpx, right: 30.rpx, bottom: 85.rpx), Padding(
child: CustomCard( padding: EdgeInsets.only(
borderRadius: 16.rpx, left: 30.rpx, right: 30.rpx, bottom: 85.rpx),
gradientDirection: GradientDirection.vertical, child: CustomCard(
onTap: () async { borderRadius: 16.rpx,
String serviceAddress = gradientDirection: GradientDirection.vertical,
ServiceConstant.service_address; onTap: () async {
String serviceName = String serviceAddress =
ServiceConstant.server_service; ServiceConstant.service_address;
String serviceApi = ServiceConstant.device_show; String serviceName =
String queryUrl = ServiceConstant.server_service;
"$serviceAddress$serviceName$serviceApi"; String serviceApi =
await requestWithLog( ServiceConstant.device_show;
logTitle: "更新设备信息", String queryUrl =
method: MyHttpMethod.put, "$serviceAddress$serviceName$serviceApi";
queryUrl: queryUrl, await requestWithLog(
data: { logTitle: "更新设备信息",
"id": editedData["_id"], method: MyHttpMethod.put,
"name": editedData["name"], queryUrl: queryUrl,
}, data: {
onSuccess: (res) { "id": editedData["_id"],
TopSlideNotification.show(context, "name": editedData["name"],
text: "修改名称成功".tr); },
deviceListController.getDeviceList(); onSuccess: (res) {
try { TopSlideNotification.show(context,
WebviewTestController text: "修改名称成功".tr);
webviewTestController = Get.find(); deviceListController.getDeviceList();
webviewTestController.web.jsbridge?.dart try {
.alterDevice(); WebviewTestController
} catch (e) { webviewTestController = Get.find();
ef.log("[h5]通知列表更新错误:$e"); webviewTestController.web.jsbridge?.dart
} .alterDevice();
Get.back(result: editedData); } catch (e) {
}, ef.log("[h5]通知列表更新错误:$e");
); }
}, Get.back(result: editedData);
colors: const [ },
Color(0xFFFCFCFC), );
Color(0xFFF8FAF9), },
Color(0XFFECF6F3), colors: const [
Color(0XFFD9F0E9), Color(0xFFFCFCFC),
Color(0xFFCEECE3) Color(0xFFF8FAF9),
], Color(0XFFECF6F3),
child: Container( Color(0XFFD9F0E9),
width: double.infinity, Color(0xFFCEECE3)
height: 90.rpx, ],
alignment: Alignment.center, child: Container(
decoration: BoxDecoration( width: double.infinity,
borderRadius: BorderRadius.circular(6), height: 90.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
),
child: Text("完成".tr,
style: TextStyle(
color: const Color(0xFF003058),
fontSize: 26.rpx)),
), ),
child: Text("完成".tr, ))
style: TextStyle(
color: const Color(0xFF003058),
fontSize: 26.rpx)),
),
))
], ],
))), ))),
), ),

View File

@@ -85,6 +85,75 @@ class _RoomPickerPageState extends State<RoomPickerPage> {
left: 0.rpx, left: 0.rpx,
child: returnIconButtomNew, child: returnIconButtomNew,
), ),
if (widget.data != null &&
(widget.data['isNextStep'] != null &&
widget.data['isNextStep'] == true))
Positioned(
right: 30.rpx,
child: CustomCard(
borderRadius: 16.rpx,
gradientDirection: GradientDirection.vertical,
onTap: () async {
// Get.toNamed("/applyRepairPage");
try {
String serviceAddress =
ServiceConstant.service_address;
String serviceName =
ServiceConstant.server_service;
String serviceApi =
ServiceConstant.device_show;
String queryUrl =
"$serviceAddress$serviceName$serviceApi";
await requestWithLog(
logTitle: "更新设备信息",
method: MyHttpMethod.put,
queryUrl: queryUrl,
data: {
"id": editedData["_id"],
"roomId": rooms[selectedIndex]['_id'],
},
onSuccess: (res) {
editedData['roomName'] =
rooms[selectedIndex]['name'];
TopSlideNotification.show(context,
text: "更新成功".tr,
textColor: Color(0XFF00C1AA));
deviceListController.getDeviceList();
Get.offNamed("/bindDeviceSuccess");
},
onFailure: (res) {
TopSlideNotification.show(context,
text: "更新失败".tr,
textColor: Color(0xFFFF7159));
},
);
} catch (e) {
print(e);
}
},
colors: const [
Color(0xFFFCFCFC),
Color(0xFFF8FAF9),
Color(0XFFECF6F3),
Color(0XFFD9F0E9),
Color(0xFFCEECE3)
],
child: Container(
width: 120.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text(
"下一步",
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0XFF011D33),
letterSpacing: 0,
fontSize: 30.rpx,
),
),
),
),
)
], ],
), ),
), ),
@@ -157,86 +226,90 @@ class _RoomPickerPageState extends State<RoomPickerPage> {
), ),
const Spacer(), const Spacer(),
// 完成按钮 // 完成按钮
Padding( if (widget.data['isNextStep'] == null ||
padding: EdgeInsets.only( widget.data['isNextStep'] == false)
left: 30.rpx, Padding(
right: 30.rpx, padding: EdgeInsets.only(
bottom: 83.rpx, left: 30.rpx,
), right: 30.rpx,
child: SizedBox( bottom: 83.rpx,
width: double.infinity, ),
height: 50, child: SizedBox(
child: CustomCard( width: double.infinity,
borderRadius: 16.rpx, height: 50,
gradientDirection: GradientDirection.vertical, child: CustomCard(
onTap: () async { borderRadius: 16.rpx,
// Get.toNamed("/applyRepairPage"); gradientDirection: GradientDirection.vertical,
try { onTap: () async {
String serviceAddress = // Get.toNamed("/applyRepairPage");
ServiceConstant.service_address; try {
String serviceName = String serviceAddress =
ServiceConstant.server_service; ServiceConstant.service_address;
String serviceApi = String serviceName =
ServiceConstant.device_show; ServiceConstant.server_service;
String queryUrl = String serviceApi =
"$serviceAddress$serviceName$serviceApi"; ServiceConstant.device_show;
await requestWithLog( String queryUrl =
logTitle: "更新设备信息", "$serviceAddress$serviceName$serviceApi";
method: MyHttpMethod.put, await requestWithLog(
queryUrl: queryUrl, logTitle: "更新设备信息",
data: { method: MyHttpMethod.put,
"id": editedData["_id"], queryUrl: queryUrl,
"roomId": rooms[selectedIndex]['_id'], data: {
}, "id": editedData["_id"],
onSuccess: (res) { "roomId": rooms[selectedIndex]['_id'],
editedData['roomName'] = },
rooms[selectedIndex]['name']; onSuccess: (res) {
TopSlideNotification.show(context, editedData['roomName'] =
text: "更新成功".tr, rooms[selectedIndex]['name'];
textColor: Color(0XFF00C1AA)); TopSlideNotification.show(context,
deviceListController.getDeviceList(); text: "更新成功".tr,
try { textColor: Color(0XFF00C1AA));
WebviewTestController deviceListController.getDeviceList();
webviewTestController = Get.find(); try {
webviewTestController.web.jsbridge?.dart WebviewTestController
.alterDevice(); webviewTestController =
} catch (e) { Get.find();
ef.log("[h5]通知列表更新错误:$e"); webviewTestController
} .web.jsbridge?.dart
Get.back(result: editedData); .alterDevice();
}, } catch (e) {
onFailure: (res) { ef.log("[h5]通知列表更新错误:$e");
TopSlideNotification.show(context, }
text: "更新失败".tr, Get.back(result: editedData);
textColor: Color(0xFFFF7159)); },
}, onFailure: (res) {
); TopSlideNotification.show(context,
} catch (e) { text: "更新失败".tr,
print(e); textColor: Color(0xFFFF7159));
} },
}, );
colors: const [ } catch (e) {
Color(0xFFFCFCFC), print(e);
Color(0xFFF8FAF9), }
Color(0XFFECF6F3), },
Color(0XFFD9F0E9), colors: const [
Color(0xFFCEECE3) Color(0xFFFCFCFC),
], Color(0xFFF8FAF9),
child: Container( Color(0XFFECF6F3),
width: double.infinity, Color(0XFFD9F0E9),
height: 90.rpx, Color(0xFFCEECE3)
alignment: Alignment.center, ],
decoration: BoxDecoration( child: Container(
borderRadius: BorderRadius.circular(6), width: double.infinity,
height: 90.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
),
child: Text("完成".tr,
style: TextStyle(
color: const Color(0xFF003058),
fontSize: 30.rpx,
)),
), ),
child: Text("完成".tr, )),
style: TextStyle( ),
color: const Color(0xFF003058),
fontSize: 30.rpx,
)),
),
)),
),
], ],
), ),
), ),

View File

@@ -31,6 +31,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
var bluetooth = 0; var bluetooth = 0;
List personList = []; List personList = [];
List instantData = []; List instantData = [];
RxBool initFlag = false.obs;
WebviewTestController() : super(WebviewTestModel()) { WebviewTestController() : super(WebviewTestModel()) {
web = WebviewHelper( web = WebviewHelper(
@@ -44,9 +45,9 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
params: PlatformHeadlessInAppWebViewCreationParams( params: PlatformHeadlessInAppWebViewCreationParams(
onLoadStop: (controller, url) { onLoadStop: (controller, url) {
setState(() => ready.value = true); setState(() => ready.value = true);
MHTHomeController deviceController = Get.find(); // MHTHomeController deviceController = Get.find();
web.jsbridge!.dart // web.jsbridge!.dart
.updateDeviceList(deviceController.deviceList.values); // .updateDeviceList(deviceController.deviceList.values);
}, },
), ),
); );
@@ -129,6 +130,7 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
return true; return true;
}); });
bridge.sdk.restoreTimer((args) async { bridge.sdk.restoreTimer((args) async {
ef.log('更新定时: $args[0]');
ef.log('queryInstantData: $args'); ef.log('queryInstantData: $args');
MHTHomeController homeController = Get.find(); MHTHomeController homeController = Get.find();
var data = await homeController.restoreTimer(args); var data = await homeController.restoreTimer(args);
@@ -160,6 +162,16 @@ class WebviewTestController extends GetControllerEx<WebviewTestModel> {
} }
return true; return true;
}); });
bridge.sdk.webPageBuild((args) async {
ef.log('网页加载完成: $args[0]');
try {
initFlag.value = true;
return true;
} catch (e) {
ef.log("[网页加载失败]:$e");
}
return true;
});
}); });
} catch (e, s) { } catch (e, s) {
ef.log('$e,$s'); ef.log('$e,$s');
@@ -391,11 +403,11 @@ class WebviewTestView extends GetComponent<WebviewTestController> {
child: Expanded( child: Expanded(
child: Align( child: Align(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
child: Obx( child: Obx(() {
() => controller.ready.value return controller.ready.value
? controller.web.build() ? controller.web.build()
: Container(), : Container();
), }),
), ),
)); ));
}), }),

View File

@@ -1272,6 +1272,8 @@ class MHTLoginPage extends GetView<MHTLoginController> {
.model.register_agree = false; .model.register_agree = false;
Get.offAndToNamed( Get.offAndToNamed(
"/mianPageBottomChange"); "/mianPageBottomChange");
//登陆成功
//
} }
}, },
colors: [ colors: [

View File

@@ -124,7 +124,7 @@ class _SleepCardState extends State<SleepCard> with TickerProviderStateMixin {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
) )
: null, : null,
child: SleepDataModuleWidget(data: item), child: SleepDataModuleWidget(data: item,sleepReportData: widget.sleepReport,),
); );
}, },
), ),
@@ -134,7 +134,7 @@ class _SleepCardState extends State<SleepCard> with TickerProviderStateMixin {
), ),
); );
} catch (e) { } catch (e) {
es.EasyDartModule.logger.error("打鼾监测绘制异常${e}"); es.EasyDartModule.logger.error("数据卡片渲染异常${e}");
return Container(); return Container();
} }
} }