diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
index 17f8265..7769da3 100644
Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-ldpi/ic_launcher.png b/android/app/src/main/res/mipmap-ldpi/ic_launcher.png
index e9d9fbc..36ff3e4 100644
Binary files a/android/app/src/main/res/mipmap-ldpi/ic_launcher.png and b/android/app/src/main/res/mipmap-ldpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
index 98c4f5e..ff2ab98 100644
Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 63ce850..6a02963 100644
Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 92662bd..da91305 100644
Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index d31b2cb..3475f3f 100644
Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/assets/img/google.png b/assets/img/google.png
new file mode 100644
index 0000000..eecdf84
Binary files /dev/null and b/assets/img/google.png differ
diff --git a/assets/img/help_op.png b/assets/img/help_op.png
new file mode 100644
index 0000000..0b0317f
Binary files /dev/null and b/assets/img/help_op.png differ
diff --git a/assets/img/icon/add.svg b/assets/img/icon/add.svg
new file mode 100644
index 0000000..3872b5c
--- /dev/null
+++ b/assets/img/icon/add.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/arrow_left.svg b/assets/img/icon/arrow_left.svg
new file mode 100644
index 0000000..0e389d4
--- /dev/null
+++ b/assets/img/icon/arrow_left.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/bluetooth.svg b/assets/img/icon/bluetooth.svg
new file mode 100644
index 0000000..49752b7
--- /dev/null
+++ b/assets/img/icon/bluetooth.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/close.svg b/assets/img/icon/close.svg
new file mode 100644
index 0000000..ee25aa2
--- /dev/null
+++ b/assets/img/icon/close.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/query.svg b/assets/img/icon/query.svg
new file mode 100644
index 0000000..90aa229
--- /dev/null
+++ b/assets/img/icon/query.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/scan.svg b/assets/img/icon/scan.svg
new file mode 100644
index 0000000..6e38491
--- /dev/null
+++ b/assets/img/icon/scan.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/sound.svg b/assets/img/icon/sound.svg
new file mode 100644
index 0000000..fcec23f
--- /dev/null
+++ b/assets/img/icon/sound.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/icon/tick.svg b/assets/img/icon/tick.svg
new file mode 100644
index 0000000..dbd8ee1
--- /dev/null
+++ b/assets/img/icon/tick.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/img/man.png b/assets/img/man.png
new file mode 100644
index 0000000..606e5bb
Binary files /dev/null and b/assets/img/man.png differ
diff --git a/assets/img/mye.png b/assets/img/mye.png
new file mode 100644
index 0000000..8987727
Binary files /dev/null and b/assets/img/mye.png differ
diff --git a/assets/img/netlove.png b/assets/img/netlove.png
new file mode 100644
index 0000000..6d259d1
Binary files /dev/null and b/assets/img/netlove.png differ
diff --git a/assets/img/tel.png b/assets/img/tel.png
new file mode 100644
index 0000000..361e837
Binary files /dev/null and b/assets/img/tel.png differ
diff --git a/assets/img/wechat.png b/assets/img/wechat.png
new file mode 100644
index 0000000..fd454ee
Binary files /dev/null and b/assets/img/wechat.png differ
diff --git a/assets/img/woman.png b/assets/img/woman.png
new file mode 100644
index 0000000..bd7ba9c
Binary files /dev/null and b/assets/img/woman.png differ
diff --git a/assets/langs/zh_CN.json b/assets/langs/zh_CN.json
index 3d00d81..257469f 100644
--- a/assets/langs/zh_CN.json
+++ b/assets/langs/zh_CN.json
@@ -14,7 +14,10 @@
"提示内容3": "3.若使用扫一扫功能,请对摄像头进行授权。",
"扫一扫绑定": "扫一扫添加新设备",
"蓝牙绑定": "蓝牙搜附近的设备",
- "已关联体征监测设备": "已关联体征监测设备"
+ "已关联体征监测设备": "已关联体征监测设备",
+ "我的e护": "我的e护",
+ "云关爱": "云关爱",
+ "报告详情": "报告详情"
},
"我的": {
"个人信息": "个人信息",
@@ -45,7 +48,30 @@
"信号":"最小信号强度",
"搜索提示":"检索设备",
"搜索":"搜索",
- "匹配":"匹配出的外围设备"
+ "匹配":"匹配出的外围设备",
+ "信号强度":"信号强度",
+ "SN":"SN",
+ "蓝牙地址":"蓝牙地址",
+ "mac":"mac",
+ "网络":"网络",
+ "在线":"在线",
+ "离线":"离线",
+ "版本":"版本",
+ "默认设备名称":"未知设备",
+ "传感器":"传感器",
+ "可绑定":"可绑定",
+ "已被绑定":"已被绑定",
+ "双人版绑定标题":"该设备为双人版,请选择",
+ "绑定全部":"绑定全部",
+ "主设备":"主设备:",
+ "从设备":"从设备:",
+ "确定":"确定",
+ "取消":"取消",
+ "无法绑定":"无法绑定!",
+ "无法绑定1":"检测到该设备",
+ "无法绑定2":"已被绑定",
+ "无法绑定3":",绑定前请先进行解绑,有疑问请联系客服",
+ "知道了":"知道了"
},
"登录页":{
"欢迎使用太和e护":"欢迎使用太和e护",
@@ -76,6 +102,29 @@
"分享内容":"设备绑定成功后,如需对朋友或家人共享我的睡眠情况,可以进行立即分享,分享成功后,对方即可享受查看该设备权限,可以收到该设备的睡眠报告。",
"立即分享":"立即分享",
"返回":"返回首页 开启体验"
+ },
+ "日期":{
+ "取消":"取消",
+ "确定":"确定",
+ "年":"年",
+ "月":"月",
+ "日":"日"
+ },
+ "wifi页":{
+ "标题":"WIFI配置",
+ "跳过":"跳过",
+ "WLAN":"WLAN",
+ "未连接":"未连接",
+ "已连接":"已连接",
+ "可用WLAN":"可用WLAN",
+ "刷新":"刷新"
+ },
+ "其他手机登录页":{
+ "输入内容":"输入手机号码/邮箱",
+ "输入验证码":"输入验证码",
+ "获取验证码":"获取验证码",
+ "登录":"登录"
+
}
}
\ No newline at end of file
diff --git a/lib/common/color/appConstants.dart b/lib/common/color/appConstants.dart
index 49142ed..5cd8c8c 100644
--- a/lib/common/color/appConstants.dart
+++ b/lib/common/color/appConstants.dart
@@ -19,6 +19,7 @@ class AppConstants {
double text_padding_up_dowm_p = 5.rpx; //段落文字上下间距
+ double small_text_fontSize = 20.rpx; //普通文字字号
double normal_text_fontSize = 26.rpx; //普通文字字号
double title_text_fontSize = 30.rpx; //标题文字字号
}
diff --git a/lib/common/util/Ble.dart b/lib/common/util/Ble.dart
new file mode 100644
index 0000000..a1c02c4
--- /dev/null
+++ b/lib/common/util/Ble.dart
@@ -0,0 +1,1100 @@
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:ef/ef.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_blue_plus/flutter_blue_plus.dart';
+import 'package:permission_handler/permission_handler.dart';
+import 'package:vbvs_app/common/util/MyUtils.dart';
+import 'package:vbvs_app/pages/common/selectDialog.dart';
+
+String findInput = "";
+double rssichange = -90;
+Function? findCall;
+
+int mcuMax = 500;
+
+String myuuid = "00000001-0000-1000-8000-00805F9B34FB";
+
+int closeTime = 20000;
+
+Map devices = Map();
+
+StreamSubscription? subscription_adapterState;
+
+Map connectList =
+ Map();
+
+bool isBleStart = false;
+
+StreamSubscription>? onScanResultsListen;
+
+StreamSubscription?
+ streamSubscription_onConnectionStateChangedEvent;
+
+Timer? showToastTimer;
+
+List permissionInfo = [
+ ["位置权限说明", "获得位置信息,连接附近的蓝牙设备与推荐附近门店"],
+ ["蓝牙权限说明", "搜索链接附近的蓝牙设备"],
+ ["附近设备权限说明", "搜索链接附近的蓝牙设备"]
+];
+
+bool isQuanShiDevice(name) {
+ return "$name".contains("S4-ZM-M94-4") || "$name".contains("S4-ZM-N94-4") || "$name".contains("MHT-SWES-D");
+}
+
+bool isMHTSWES(name) {
+ return "$name".contains("MHT-SWES-H") || "$name".contains("MHT-SWES-M") || "$name".contains("MHT-SWES-S");
+}
+
+bleParse() {
+ findCall = null;
+ print("bleParse 执行了");
+ showToastTimer?.cancel();
+ if (FlutterBluePlus.isScanningNow) {
+ FlutterBluePlus.stopScan();
+ }
+}
+
+start(Function fun, {Function? bleOnCall}) async {
+ if (isBleStart) {
+ var isOk = await requestBluetoothPermission();
+ if (isOk == true) {
+ findCall = fun;
+ bleOnCall?.call();
+ bleOnCall = null;
+ }
+ print("ble start again");
+ return;
+ }
+ print("ble start");
+ FlutterBluePlus.setLogLevel(LogLevel.info, color: false);
+ streamSubscription_onConnectionStateChangedEvent?.cancel();
+ streamSubscription_onConnectionStateChangedEvent =
+ FlutterBluePlus.events.onConnectionStateChanged.listen((event) {
+ print('${event.device} ${event.connectionState}');
+ });
+ if (await FlutterBluePlus.isSupported == false) {
+ print("Bluetooth not supported by this device");
+ return;
+ }
+
+ // handle bluetooth on & off
+ // note: for iOS the initial state is typically BluetoothAdapterState.unknown
+ // note: if you have permissions issues you will get stuck at BluetoothAdapterState.unauthorized
+ subscription_adapterState?.cancel();
+ int callIndex = 0;
+ subscription_adapterState =
+ FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) async {
+ print(state);
+ print("蓝牙状态 $state");
+ if (state == BluetoothAdapterState.on) {
+ showToastTimer?.cancel();
+ // usually start scanning, connecting, etc
+ findCall = fun;
+ var isOk = await requestBluetoothPermission();
+ if (isOk == true) {
+ bleOnCall?.call();
+ bleOnCall = null;
+ }
+ } else {
+ // show an error to the user, etc
+ if (Platform.isIOS &&
+ callIndex == 0 &&
+ state == BluetoothAdapterState.unknown) {
+ callIndex++;
+ return;
+ }
+ if (Platform.isAndroid) {
+ showToast("请打开蓝牙开关");
+ }
+ if (Platform.isIOS) {
+ showToast("请打开蓝牙开关且开启蓝牙权限");
+ await showCustomConfirmAndCancelDialog(
+ Get.context!, "请在“设置-蓝牙”中打开蓝牙开关或者在“设置-APP”中找到对应APP开启蓝牙权限",
+ confirmName: "去设置")
+ .then((msg) async {
+ if (msg == "confirm") {
+ openAppSettings();
+ }
+ });
+ }
+ isBleStart = false;
+ showToastTimer?.cancel();
+ showToastTimer = Timer.periodic(const Duration(seconds: 5), (t) {
+ if (t.tick > 3) {
+ t.cancel();
+ }
+ if (Platform.isAndroid) {
+ showToast("请打开蓝牙开关");
+ }
+ if (Platform.isIOS) {
+ showToast("请打开蓝牙开关且开启蓝牙权限");
+ }
+ });
+ }
+ callIndex++;
+ });
+
+ // turn on bluetooth ourself if we can
+ // for iOS, the user controls bluetooth enable/disable
+ if (Platform.isAndroid &&
+ FlutterBluePlus.adapterStateNow != BluetoothAdapterState.on) {
+ showPermissionInfoDialog(Get.context!, permissionInfo);
+ FlutterBluePlus.turnOn().then((e) {
+ Get.back();
+ }).catchError((e) {
+ Get.back();
+ });
+ }
+
+ var timer = null;
+ onScanResultsListen?.cancel();
+ onScanResultsListen = FlutterBluePlus.onScanResults.listen(
+ (List results) {
+ // print(results.length);
+ for (ScanResult result in results) {
+ // if (result.device.id.toString().contains("A3:76")) {
+ // print("$result");
+ // }
+ Map d = {
+ "updateTime": DateTime.now().millisecondsSinceEpoch,
+ "name": result.device.advName,
+ "id": result.device.remoteId.str,
+ "rssi": result.rssi,
+ "device": result.device,
+ "connectable": result.advertisementData.connectable
+ };
+ Map> m_d = result.advertisementData.manufacturerData;
+ m_d.keys.toList().forEach((v) {
+ if (v == 65517 && m_d[65517]?.length != 0) {
+ List a = [0, 0, ...?m_d[65517]];
+ advertisDataFormatter(a, d);
+ } else if (v == 11125 && m_d[11125]?.length == 8) {
+ List a = [...?m_d[11125]];
+ d['adData'] = {'deviceId': ab2str(a.sublist(2, 8)).toUpperCase()};
+ } else if (m_d[v]?.length == 8 && isQuanShiDevice(d["name"])) {
+ List a = [...?m_d[v]];
+ d['adData'] = {'deviceId': ab2str(a.sublist(2, 8)).toUpperCase()};
+ } else if (m_d[v]?.length == 4 && isMHTSWES(d["name"])) {
+ ByteData bd = ByteData(2);
+ bd.setUint16(0, v, Endian.little);
+ List a = [bd.getUint8(0), bd.getUint8(1), ...?m_d[v]];
+ d['adData'] = {'deviceId': ab2str(a).toUpperCase()};
+ } else if (m_d[v]?.length == 6 && isMHTSWES(d["name"])) {
+ List a = [...?m_d[v]];
+ d['adData'] = {'deviceId': ab2str(a).toUpperCase()};
+ }
+ });
+ devices[d['id']] = d;
+ // print('Device found: ${result.device.name}, ${result.device.id}');
+ if (timer == null) {
+ timer = 1;
+ timer = Future.delayed(const Duration(microseconds: 300), () {
+ timer = null;
+ find();
+ });
+ }
+ }
+ },
+ onError: (e) => print(e),
+ );
+}
+
+// Future locationCheck({bool isGetLocation = true}) async {
+// // 先查看定位服务是否开启
+// bool b = await Geolocator.isLocationServiceEnabled();
+// if (b == false) {
+// if (Platform.isAndroid) {
+// showToast("请开启系统位置开关", closeTime: 5);
+// await showCustomConfirmAndCancelDialog(Get.context!, "请开启系统位置开关",
+// confirmName: "去设置")
+// .then((msg) async {
+// if (msg == "confirm") {
+// // await Geolocator.openLocationSettings();
+// await openGeolocatorLocationSettingsAndWait();
+// b = await Geolocator.isLocationServiceEnabled();
+// }
+// });
+// }
+// if (Platform.isIOS) {
+// showToast("请开启系统定位服务与定位权限", closeTime: 5);
+// await showCustomConfirmAndCancelDialog(Get.context!,
+// "请在“设置-隐私与安全性-定位服务”中开启定位服务开关或者在“设置-APP”中找到对应APP开启定位服务权限",
+// confirmName: "去设置")
+// .then((msg) async {
+// if (msg == "confirm") {
+// // await Geolocator.openAppSettings();
+// await openGeolocatorAppSettingsAndWait();
+// b = await Geolocator.isLocationServiceEnabled();
+// }
+// });
+// }
+// }
+
+// var permission = await Geolocator.checkPermission();
+// if (permission == LocationPermission.denied ||
+// permission == LocationPermission.deniedForever) {
+// showPermissionInfoDialog(Get.context!, [permissionInfo[0]]);
+// permission = await Geolocator.requestPermission().catchError((e) {
+// Get.back();
+// });
+// Get.back();
+// if (permission == LocationPermission.deniedForever) {
+// if (Platform.isAndroid) {
+// await showCustomConfirmAndCancelDialog(Get.context!, "请开启位置权限(打开精确位置)",
+// confirmName: "去设置")
+// .then((msg) async {
+// if (msg == "confirm") {
+// // await Geolocator.openAppSettings();
+// await openGeolocatorAppSettingsAndWait();
+// }
+// });
+// }
+// if (Platform.isIOS) {
+// await showCustomConfirmAndCancelDialog(Get.context!,
+// "请在“设置-隐私与安全性-定位服务”中开启定位服务开关或者在“设置-APP”中找到对应APP开启定位服务权限",
+// confirmName: "去设置")
+// .then((msg) async {
+// if (msg == "confirm") {
+// // await Geolocator.openAppSettings();
+// await openGeolocatorAppSettingsAndWait();
+// }
+// });
+// }
+// }
+// }
+
+// Position? position;
+// if (isGetLocation) {
+// if (b &&
+// permission != LocationPermission.denied &&
+// permission != LocationPermission.deniedForever) {
+// try {
+// position = await Geolocator.getCurrentPosition(
+// locationSettings:
+// const LocationSettings(timeLimit: Duration(seconds: 5)));
+// print("$position");
+// } catch (e) {
+// print("error $e");
+// }
+// }
+// }
+// return position;
+// }
+
+/// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态,
+/// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回
+/// ------开始-----
+Future openGeolocatorAppSettingsAndWait() async {
+ final geolocatorAppSettingsLifecycleState =
+ GeolocatorAppSettingsLifecycleEventHandler();
+
+ WidgetsBinding.instance.addObserver(geolocatorAppSettingsLifecycleState);
+
+ // await Geolocator.openAppSettings();
+
+ await geolocatorAppSettingsLifecycleState.waitForResume();
+
+ WidgetsBinding.instance.removeObserver(geolocatorAppSettingsLifecycleState);
+
+ print('AppSettings have been opened and user has returned');
+}
+
+class GeolocatorAppSettingsLifecycleEventHandler
+ extends WidgetsBindingObserver {
+ final Completer _completer = Completer();
+
+ @override
+ void didChangeAppLifecycleState(AppLifecycleState state) {
+ if (state == AppLifecycleState.resumed && !_completer.isCompleted) {
+ _completer.complete();
+ }
+ }
+
+ Future waitForResume() => _completer.future;
+}
+
+/// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态,
+/// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回
+/// ------结束-----
+
+/// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态,
+/// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回
+/// ------开始-----
+Future openGeolocatorLocationSettingsAndWait() async {
+ final geolocatorLocationSettingsLifecycleState =
+ GeolocatorLocationSettingsLifecycleEventHandler();
+
+ WidgetsBinding.instance.addObserver(geolocatorLocationSettingsLifecycleState);
+
+ // await Geolocator.openLocationSettings();
+
+ await geolocatorLocationSettingsLifecycleState.waitForResume();
+
+ WidgetsBinding.instance
+ .removeObserver(geolocatorLocationSettingsLifecycleState);
+
+ print('LocationSettings have been opened and user has returned');
+}
+
+class GeolocatorLocationSettingsLifecycleEventHandler
+ extends WidgetsBindingObserver {
+ final Completer _completer = Completer();
+
+ @override
+ void didChangeAppLifecycleState(AppLifecycleState state) {
+ if (state == AppLifecycleState.resumed && !_completer.isCompleted) {
+ _completer.complete();
+ }
+ }
+
+ Future waitForResume() => _completer.future;
+}
+
+/// 使用 Completer 来等待用户返回应用,自定义的 LifecycleEventHandler 类将监视应用程序的生命周期状态,
+/// 并在应用程序恢复时完成,有效地等待用户从设置屏幕返回
+/// ------结束-----
+
+Future requestBluetoothPermission() async {
+ if (Platform.isIOS) {
+ PermissionStatus isBleGranted = await Permission.bluetooth.request();
+ print('checkBlePermissions-ios, isBleGranted=$isBleGranted');
+ if (isBleGranted.isGranted) {
+ startBluetoothScanning();
+ return true;
+ } else {
+ showToast("蓝牙开关或蓝牙权限未开启,请开启蓝牙开关与蓝牙权限", closeTime: 7);
+ await showCustomConfirmAndCancelDialog(
+ Get.context!, "请“设置-蓝牙”中打开蓝牙开关或者在“设置-APP”中找到对应APP开启蓝牙权限",
+ confirmName: "去设置")
+ .then((msg) async {
+ if (msg == "confirm") {
+ openAppSettings();
+ }
+ });
+ return false;
+ }
+ } else if (Platform.isAndroid) {
+ // 检查蓝牙扫描权限
+ String error = "";
+ bool isShowDialog = false;
+ if (!await Permission.bluetoothScan.isGranted) {
+ if (!isShowDialog) {
+ isShowDialog = true;
+ showPermissionInfoDialog(Get.context!, permissionInfo);
+ }
+ PermissionStatus status = await Permission.bluetoothScan.request();
+ if (!status.isGranted) {
+ error += "蓝牙扫描权限未开启,请开启附近设备权限";
+ }
+ print("蓝牙扫描 $status");
+ }
+
+ // 检查蓝牙连接权限
+ if (!await Permission.bluetoothConnect.isGranted) {
+ if (!isShowDialog) {
+ isShowDialog = true;
+ showPermissionInfoDialog(Get.context!, permissionInfo);
+ }
+ PermissionStatus status = await Permission.bluetoothConnect.request();
+ if (!status.isGranted) {
+ if (error.isNotEmpty) {
+ error += "\n";
+ }
+ error += "蓝牙连接权限未开启,请开启蓝牙权限";
+ }
+ print("蓝牙连接 $status");
+ }
+
+ // 检查位置权限
+ if (!await Permission.location.isGranted) {
+ if (!isShowDialog) {
+ isShowDialog = true;
+ showPermissionInfoDialog(Get.context!, permissionInfo);
+ }
+ //检查
+ PermissionStatus status = await Permission.location.request();
+ print("位置权限 $status");
+ if (!status.isGranted) {
+ await showCustomConfirmAndCancelDialog(Get.context!, "请开启位置权限(打开精确位置)",
+ confirmName: "去设置")
+ .then((msg) async {
+ if (msg == "confirm") {
+ await openGeolocatorAppSettingsAndWait();
+ // await Future.delayed(const Duration(seconds: 2));
+ print('Proceeding with other operations');
+ status = await Permission.location.request();
+ }
+ });
+ }
+ if (!status.isGranted) {
+ if (error.isNotEmpty) {
+ error += "\n";
+ }
+ error += "位置权限未开启,请开启位置权限";
+ }
+ }
+
+ if (isShowDialog) {
+ Get.back();
+ }
+
+ if (await Permission.bluetoothScan.isGranted &&
+ await Permission.bluetoothConnect.isGranted &&
+ await Permission.location.isGranted) {
+ // bool b = await Geolocator.isLocationServiceEnabled();
+ bool b =false;
+ if (b == false) {
+ await showCustomConfirmAndCancelDialog(Get.context!, "请开启系统位置开关",
+ confirmName: "去设置")
+ .then((msg) async {
+ if (msg == "confirm") {
+ // bool isOpen = await Geolocator.openLocationSettings();
+ await openGeolocatorLocationSettingsAndWait();
+ // await Future.delayed(const Duration(seconds: 2));
+ print('Proceeding with other operations');
+ // b = await Geolocator.isLocationServiceEnabled();
+ }
+ });
+ }
+ if (b) {
+ isBleStart = true;
+ startBluetoothScanning();
+ return true;
+ } else {
+ showToast("系统位置开关未开启,请开启系统位置开关", closeTime: 7);
+ return false;
+ }
+ } else {
+ Timer(Duration.zero, () async {
+ showToast(error, closeTime: 7);
+ });
+ return false;
+ }
+ } else {
+ showToast("当前系统不支持蓝牙,无法使用此功能", closeTime: 7);
+ return false;
+ }
+}
+
+void find() {
+ int len = devices.length;
+ String reg = findInput.toLowerCase().replaceAll(RegExp("[::]"), "");
+ List list = devices.values.toList();
+ for (int i = 0; i < len; i++) {
+ Map d = list[i];
+ bool flag = d['rssi'] >= rssichange;
+ if (flag) {
+ bool a = d['name'].toString().toLowerCase().contains(reg);
+ a = a ||
+ d['id']
+ .toString()
+ .toLowerCase()
+ .replaceAll(RegExp("[::]"), "")
+ .contains(reg);
+ // if(d.adData && d.adData.deviceId) {
+ // a = a || d.adData.deviceId.toLowerCase().replace(/[::]/g, "").indexOf(reg) > -1
+ // }
+ // if(d.adData && d.adData.version && reg) {
+ // a = a || (d.adData.version + "").indexOf(reg) > -1
+ // }
+ flag = flag && a;
+ }
+ if (flag) {
+ flag = flag &&
+ DateTime.now().millisecondsSinceEpoch - d['updateTime'] < closeTime;
+ }
+ if (!flag) {
+ d['isClose'] = true;
+ } else {
+ d['isClose'] = false;
+ }
+ }
+ var result = list.where((item) => item['isClose'] == false).toList();
+ if (result == null) {
+ findCall?.call([]);
+ } else {
+ // print(result);
+ result.sort((a, b) {
+ // print("${a['rssi']},${b['rssi']}");
+ return b['rssi'] - a['rssi'];
+ });
+ if (result.length > 0) {
+ findCall?.call(result.where((d) => d?['adData'] != null).toList());
+ } else {
+ findCall?.call(result);
+ }
+ }
+}
+
+String ab2str(List buffer) {
+ return buffer.map((x) => x.toRadixString(16).padLeft(2, '0')).join('');
+}
+
+void advertisDataFormatter(var a, item) {
+ Map obj = {};
+ try {
+ if (a[2] == 1) {
+ obj['sn'] = a[3];
+ obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase();
+ obj['b'] = a[10];
+ obj['h'] = a[11];
+ obj['t'] = a[12];
+ item['adData'] = obj;
+ } else if (a[2] == 2) {
+ obj['sn'] = a[3];
+ obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase();
+ obj['b'] = a[10];
+ obj['h'] = a[11];
+ obj['t'] = a[12];
+ obj['net'] = (a[13] & 1) == 1 ? '在线' : '离线';
+ obj['flag'] = (a[13] & 2) == 2 ? '异常' : '正常';
+ ByteData byteData = ByteData.sublistView(
+ Uint8List.fromList(a.sublist(14, 18).reversed.toList()));
+ obj['version'] = byteData.getUint32(0);
+ item['adData'] = obj;
+ } else if (a[2] == 3) {
+ List otherstr = [];
+ obj['sn'] = a[3];
+ obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase();
+ obj['b'] = a[10];
+ obj['h'] = a[11];
+ obj['t'] = a[12];
+ obj['net'] = (a[13] & 1) == 1 ? '在线' : '离线';
+ obj['flag'] = (a[13] & 2) == 2 ? '异常' : '正常';
+
+ if ((a[13] & 4) == 4) {
+ otherstr.add('呼吸暂停');
+ }
+
+ if ((a[13] & 8) == 8 && (a[13] & 1) == 1) {
+ obj['isbed'] = '在床';
+ } else {
+ obj['isbed'] = '离床';
+ }
+
+ if ((a[13] & 16) == 16) {
+ otherstr.add('授权过期');
+ }
+
+ if ((a[13] & 64) == 64) {
+ otherstr.add('设备休眠');
+ }
+
+ obj['other'] = otherstr.join('、');
+
+ ByteData byteData = ByteData.sublistView(
+ Uint8List.fromList(a.sublist(14, 18).reversed.toList()));
+ obj['version'] = byteData.getUint32(0);
+
+ ByteData qsnData =
+ ByteData.sublistView(Uint8List.fromList(a.sublist(17, 19)));
+ obj['qsn'] = qsnData.getUint16(0) * 256 + obj['sn'];
+
+ item['adData'] = obj;
+ } else if (a.length > 17) {
+ obj['sn'] = a[3];
+ obj['deviceId'] = ab2str(a.sublist(4, 10)).toUpperCase();
+ obj['b'] = a[10];
+ obj['h'] = a[11];
+ obj['t'] = a[12];
+ obj['net'] = (a[13] & 1) == 1 ? '在线' : '离线';
+ obj['flag'] = (a[13] & 2) == 2 ? '异常' : '正常';
+
+ ByteData byteData = ByteData.sublistView(
+ Uint8List.fromList(a.sublist(14, 18).reversed.toList()));
+ obj['version'] = byteData.getUint32(0);
+
+ item['adData'] = obj;
+ }
+ } catch (e) {
+ print(e);
+ }
+}
+
+void startBluetoothScanning() async {
+ // 开始扫描附近的蓝牙设备
+ if (FlutterBluePlus.isScanningNow) {
+ await FlutterBluePlus.stopScan();
+ }
+ FlutterBluePlus.startScan(timeout: const Duration(seconds: 15));
+}
+
+getOneConnectedDeviceProp(id) {
+ return connectList[id];
+}
+
+void setOther(device, connectedDeviceProp, fun) async {
+ try {
+ List services = await device.discoverServices();
+ print(services);
+ bool isNotify = false;
+ bool isWrite = false;
+ for (var service in services) {
+ if (connectedDeviceProp.connectedDevicePropType ==
+ ConnectedDevicePropType.JunHe) {
+ if (service.uuid.str128.toUpperCase() != myuuid) {
+ continue;
+ }
+ }
+ // print("serviece $service");
+ for (BluetoothCharacteristic element in service.characteristics) {
+ if (isNotify == false && element.properties.notify) {
+ await element.setNotifyValue(true);
+ print("setNotifyValue 完成");
+ connectedDeviceProp.createLisetenReceive(element);
+ isNotify = true;
+ if (connectedDeviceProp.connectedDevicePropType ==
+ ConnectedDevicePropType.JunHe) {
+ continue;
+ }
+ if (connectedDeviceProp.connectedDevicePropType ==
+ ConnectedDevicePropType.MHT) {
+ continue;
+ }
+ }
+ if (isWrite == false && element.properties.write) {
+ connectedDeviceProp?.writeCharacteristic = element;
+ isWrite = true;
+ print("$element");
+ }
+ }
+ }
+ if (!isWrite || !isNotify) {
+ if (connectedDeviceProp != null) {
+ disconnect(connectedDeviceProp!);
+ }
+ print("service 订阅失败 isWrite $isWrite isNotify $isNotify");
+ fun['fail']?.call("service 订阅失败 isWrite $isWrite isNotify $isNotify");
+ return;
+ }
+ print("service 注册完成");
+ connectList[connectedDeviceProp.id] = connectedDeviceProp;
+ connectedDeviceProp.createListenState();
+ if (connectedDeviceProp.connectedDevicePropType ==
+ ConnectedDevicePropType.JunHe) {
+ connectedDeviceProp.heartbeat();
+ }
+ print("回调成功");
+ fun['success']?.call(connectedDeviceProp);
+ } catch (e) {
+ print("连接失败 执行失败回调 错误: $e");
+ if (connectedDeviceProp != null) {
+ disconnect(connectedDeviceProp!);
+ }
+ print("连接失败 执行失败回调");
+ fun['fail']?.call(e);
+ }
+}
+
+// 连接设备
+void connectToDevice(fun) async {
+ BluetoothDevice device = fun['device'];
+ ConnectedDeviceProp? connectedDeviceProp =
+ getOneConnectedDeviceProp(device.remoteId.str);
+ if (connectedDeviceProp != null) {
+ disconnect(connectedDeviceProp);
+ Future.delayed(const Duration(seconds: 1), () {
+ connectToDevice(fun);
+ });
+ return;
+ }
+ try {
+ print("connecting");
+ await device.connect(timeout: const Duration(seconds: 8));
+ print("device.connect success");
+ ConnectedDevicePropType connectedDevicePropType =
+ ConnectedDevicePropType.JunHe;
+ if (isQuanShiDevice(device.advName)) {
+ connectedDevicePropType = ConnectedDevicePropType.QuanShi;
+ } else if (isMHTSWES(device.advName)) {
+ connectedDevicePropType = ConnectedDevicePropType.MHT;
+ }
+ connectedDeviceProp = ConnectedDeviceProp(
+ connectDevice: device,
+ fun: fun,
+ connectedDevicePropType: connectedDevicePropType);
+ if (Platform.isAndroid) {
+ await device.requestMtu(mcuMax);
+ }
+ Timer(const Duration(milliseconds: 1000), () {
+ setOther(device, connectedDeviceProp, fun);
+ });
+ } catch (e) {
+ print("连接失败 执行失败回调 错误: $e");
+ if (connectedDeviceProp != null) {
+ disconnect(connectedDeviceProp!);
+ }
+ print("连接失败 执行失败回调");
+ fun['fail']?.call(e);
+ }
+}
+
+void disconnect(ConnectedDeviceProp connectedDeviceProp) {
+ connectedDeviceProp.closeHeartBeat();
+ connectList.remove(connectedDeviceProp.id);
+ connectedDeviceProp.closeConnectedDeviceProp();
+}
+
+void closeAll() {
+ findCall = null;
+ connectList.values.toList().forEach((element) {
+ disconnect(element);
+ });
+}
+
+enum ConnectedDevicePropType { JunHe, QuanShi, MHT }
+
+class ConnectedDeviceProp {
+ ConnectedDevicePropType connectedDevicePropType;
+ Timer? heartbeatTimer = null;
+ int _seq = 0;
+ var connectDevice;
+ var writeCharacteristic;
+ var listenState;
+ StreamSubscription>? lisetenReceive;
+ Map fun;
+ List receiveMethods = [];
+ List logList = [];
+ Function? logChange;
+ ConnectedDeviceProp(
+ {required this.connectDevice,
+ required Map this.fun,
+ this.connectedDevicePropType = ConnectedDevicePropType.JunHe});
+ List receiveLogArr = [];
+ int deviceType = 2;
+ int encodeType = 2;
+ List sendArr = [];
+ double sendExecAverage = 100;
+ bool isClose = false;
+
+ String get id {
+ return connectDevice.remoteId.str;
+ }
+
+ int sum_ab(dv) {
+ ByteData sum = ByteData(1);
+ for (int i = 0; i < dv.buffer.lengthInBytes; i++) {
+ sum.setUint8(0, dv.getUint8(i) + sum.getUint8(0));
+ }
+ return sum.getUint8(0);
+ }
+
+ void heartbeat() {
+ closeHeartBeat();
+ heartbeatTimer = Timer.periodic(const Duration(seconds: 8), (timer) {
+ ByteData dv = ByteData(4);
+ dv.setUint8(0, 4);
+ dv.setUint8(2, seq);
+ dv.setUint8(3, 5);
+ dv.setUint8(1, sum_ab(dv));
+ writeBle(dv);
+ });
+ }
+
+ closeHeartBeat() {
+ if (heartbeatTimer != null) {
+ heartbeatTimer!.cancel();
+ heartbeatTimer = null;
+ }
+ }
+
+ ByteData str2ab_oneByte(String str, {int startLength = 0}) {
+ Uint8List utf8str = utf8.encode(str);
+ int len = utf8str.length + startLength;
+ ByteData buf2 = ByteData.sublistView(utf8str);
+ ByteData buf = ByteData(len);
+ for (int i = startLength; i < len; i++) {
+ buf.setUint8(i, buf2.getUint8(i - startLength));
+ }
+ return buf;
+ }
+
+ void write3OfString(sendDate, {Function? success, Function? fail}) {
+ ByteData dv = str2ab_oneByte(sendDate, startLength: 4);
+ int len = dv.buffer.lengthInBytes;
+ dv.setUint8(0, len);
+ dv.setUint8(2, seq);
+ dv.setUint8(3, 8 * 16 + 3);
+ dv.setUint8(1, sum_ab(dv));
+ writeBle(dv, success: success, fail: fail);
+ }
+
+ void writeBle(ByteData d, {Function? success, Function? fail}) {
+ Uint8List d_ = Uint8List.view(d.buffer);
+ if (sendArr.length == 0) {
+ write(d_, success, fail);
+ }
+ sendArr.insert(0, {"d": d_, "success": success, "fail": fail});
+ }
+
+ void write(Uint8List d, Function? success, Function? fail, {int exec = 100}) {
+ if (writeCharacteristic != null) {
+ // try {
+ // if (d[3] == 8 * 16 + 3) {
+ // print(
+ // "blewrite s = $sendExecAverage d = ${utf8.decode(d.sublist(4))}");
+ // } else {
+ // print("ble last write d = ${d[3]}");
+ // }
+ // } catch (e) {
+ // print("write logprint error $e");
+ // }
+ writeCharacteristic.write(d, withoutResponse: true).then((e) {
+ // print("write success $e");
+ if (connectedDevicePropType != ConnectedDevicePropType.JunHe) {
+ print("发送 $d");
+ }
+ if (exec > 95) {
+ sendExecAverage = sendExecAverage + 0.5;
+ }
+ if (sendExecAverage > 99) {
+ sendExecAverage = 99;
+ }
+ if (sendArr.length > 0) {
+ sendArr.removeLast();
+ Map last = sendArr.last;
+ write(last["d"], last["success"], last["fail"]);
+ }
+ success?.call();
+ }).catchError((e) {
+ // print("exec = $exec , $e");
+ if (exec < 0) {
+ print("$e");
+ fail?.call();
+ }
+ if (exec > -1 && isClose == false) {
+ int time = ((100.0 - sendExecAverage) * 5.0).toInt();
+ if (exec < 80) {
+ time = (100 - exec) * 5;
+ sendExecAverage = exec * 1.0;
+ } else {
+ sendExecAverage = sendExecAverage - (100 - exec) * 0.1;
+ }
+ Timer(Duration(milliseconds: time), () {
+ write(d, success, fail, exec: exec - 1);
+ });
+ }
+ });
+ }
+ }
+
+ void read6() {
+ ByteData dv = ByteData(4);
+ dv.setUint8(0, 4);
+ dv.setUint8(2, seq);
+ dv.setUint8(3, 6);
+ dv.setUint8(1, sum_ab(dv));
+ writeBle(dv);
+ }
+
+ addLog(String log) {
+ if (logList.length > 500) {
+ logList.removeRange(0, 50);
+ }
+ DateTime date = DateTime.now();
+ String h = date.hour > 10 ? "${date.hour}" : "0${date.hour}";
+ String m = date.minute > 10 ? "${date.minute}" : "0${date.minute}";
+ String s = date.second > 10 ? "${date.second}" : "0${date.second}";
+ logList.add({"time": "$h:$m:$s", "value": log});
+ print("ble $id log: $log");
+ if (logChange != null) {
+ logChange?.call(logList, log);
+ }
+ }
+
+ createListenState() {
+ listenState = connectDevice.connectionState.listen((state) {
+ print('ble Device state $id $state');
+ if (state == BluetoothConnectionState.disconnected) {
+ print('ble Device state $id disconnected');
+ isClose = true;
+ disconnect(this);
+ fun['stateChange']?.call(state, this);
+ }
+ });
+ }
+
+ createLisetenReceive(BluetoothCharacteristic element) {
+ lisetenReceive = element.onValueReceived.listen((List value) {
+ if (connectedDevicePropType == ConnectedDevicePropType.JunHe) {
+ if (value.isEmpty) {
+ return;
+ }
+ bool isOk = sumCheck(value);
+ if (isOk) {
+ receiveMethods.forEach((m) {
+ m?.call();
+ });
+ yewuSwitch(value[3], value.sublist(4));
+ }
+ } else {
+ print("onValueReceived $value");
+ receiveLogArr.forEach((m) {
+ m(value);
+ });
+ }
+ });
+ }
+
+ closeConnectedDeviceProp() {
+ isClose = true;
+ if (listenState != null) {
+ listenState?.cancel();
+ }
+ if (lisetenReceive != null) {
+ lisetenReceive?.cancel();
+ }
+ connectDevice?.disconnect();
+ }
+
+ int get seq {
+ int r = _seq % 256;
+ _seq++;
+ return r;
+ }
+
+ bool sumCheck(List ab) {
+ ByteData dv = ByteData.sublistView(Uint8List.fromList(ab));
+
+ if (dv.getUint8(0) != ab.length) {
+ print("和校验失败:长度不对");
+ return false;
+ } //和校验失败
+
+ if (sumList(ab) != dv.getUint8(1)) {
+ print("和校验失败: 校验失败");
+ return false;
+ }
+
+ return true;
+ }
+
+ int sumList(List ab) {
+ ByteData dv = ByteData.sublistView(Uint8List.fromList(ab));
+ ByteData sum = ByteData.sublistView(Uint8List(1));
+
+ sum.setUint8(0, dv.getUint8(0));
+
+ for (int i = 2; i < ab.length; i++) {
+ sum.setUint8(0, dv.getUint8(i) + sum.getUint8(0));
+ }
+
+ return sum.getUint8(0);
+ }
+
+ List endLogValue = [];
+ Timer? endLogTimer;
+
+ void yewuSwitch(int yewu, List abData) {
+ switch (yewu) {
+ case 7:
+ String error = ab2StrByType(abData);
+ print(error);
+ break;
+
+ case 131:
+ List? logData;
+ if (abData.last != 10) {
+ int index = abData.lastIndexOf(10);
+ if (index == -1) {
+ index = abData.length;
+ endLogValue = [...endLogValue, ...abData.sublist(0, index)];
+ } else {
+ logData = [...endLogValue, ...abData.sublist(0, index)];
+ endLogValue = abData.sublist(index);
+ }
+ // if (index == -1) {
+ // index = abData.length;
+ // }
+ // if(endLogValue.isNotEmpty) {
+ // logData = [...endLogValue, ...abData.sublist(0, index)];
+ // endLogValue = [];
+ // } else {
+ // logData = [...abData.sublist(0, index)];
+ // }
+ // if(index != abData.length) {
+ // endLogValue = abData.sublist(index);
+ // }
+ } else {
+ int index = abData.length;
+
+ if (endLogValue.isNotEmpty) {
+ logData = [...endLogValue, ...abData];
+ } else {
+ logData = abData;
+ }
+
+ endLogValue = [];
+ }
+
+ if (endLogTimer != null) {
+ endLogTimer!.cancel();
+ endLogTimer = null;
+ }
+
+ if (endLogValue != null && endLogValue!.isNotEmpty) {
+ endLogTimer = Timer(Duration(milliseconds: 400), () {
+ String log = ab2StrByType(endLogValue!);
+ endLogValue = [];
+ addLog(log);
+ try {
+ receiveLogArr.forEach((m) {
+ m(log);
+ });
+ } catch (e) {
+ print(e);
+ }
+ });
+ }
+
+ if (logData != null && logData.isNotEmpty) {
+ if (logData.length != 1 || logData[0] != 13) {
+ String log = ab2StrByType(logData!);
+ addLog(log);
+ try {
+ receiveLogArr.forEach((m) {
+ m(log);
+ });
+ } catch (e) {
+ print(e);
+ }
+ }
+ }
+ // 处理逻辑
+ break;
+
+ case 132:
+ ByteData dv = ByteData.sublistView(Uint8List.fromList(abData));
+
+ for (int i = 0; i < abData.length;) {
+ int len = dv.getUint8(i);
+ yewuSwitch(dv.getUint8(i + 1), abData.sublist(i + 2, i + 1 + len));
+ i = i + 1 + len;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ String ab2StrByType(List abData) {
+ // Implement your logic for converting abData to String
+ String str = "";
+ if (abData.isNotEmpty) {
+ try {
+ str = utf8.decode(abData);
+ } catch (e) {
+ str = "解析错误";
+ }
+ }
+ return str;
+ }
+}
diff --git a/lib/component/home_page/SleepDataModuleWidget.dart b/lib/component/home_page/SleepDataModuleWidget.dart
new file mode 100644
index 0000000..abaee63
--- /dev/null
+++ b/lib/component/home_page/SleepDataModuleWidget.dart
@@ -0,0 +1,145 @@
+import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart';
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutterflow_ui/flutterflow_ui.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/controller/theme_controller/ThemeController.dart';
+
+class SleepDataModuleWidget extends StatefulWidget {
+ const SleepDataModuleWidget({super.key});
+
+ @override
+ State createState() => _SleepDataModuleWidgetState();
+}
+
+class _SleepDataModuleWidgetState extends State {
+ @override
+ void setState(VoidCallback callback) {
+ super.setState(callback);
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ ThemeController themeController = Get.find();
+ return Container(
+ width: MediaQuery.sizeOf(context).width * 0.27,
+ constraints: BoxConstraints(
+ minWidth: 200.rpx,
+ ),
+ decoration: BoxDecoration(
+ color: stringToColor("#313541"),
+ borderRadius: BorderRadius.circular(20.rpx),
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(18.rpx, 18.rpx, 18.rpx, 22.rpx),
+ child: Container(
+ decoration: BoxDecoration(),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ '离床次数',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ // SizedBox(
+ // height: 21.rpx,
+ // ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Text(
+ '4',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: 40.rpx,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0.rpx, 0, 0.rpx, 10.rpx),
+ child: Text(
+ '次',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants().small_text_fontSize,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ),
+ ],
+ ),
+ Container(
+ width: MediaQuery.sizeOf(context).width * 0.07,
+ height: MediaQuery.sizeOf(context).height * 0.014,
+ constraints: BoxConstraints(
+ minWidth: 43.rpx,
+ minHeight: 36.rpx,
+ ),
+ decoration: BoxDecoration(),
+ child: FFButtonWidget(
+ onPressed: () {
+ print('Button pressed ...');
+ },
+ text: '异常',
+ options: FFButtonOptions(
+ height: 40.rpx,
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0.rpx, 0, 0.rpx, 0),
+ color: stringToColor("#FF7159"),
+ textStyle:
+ FlutterFlowTheme.of(context).titleSmall.override(
+ fontFamily: 'Inter Tight',
+ color: themeController.currentColor.sc3,
+ letterSpacing: 0.0,
+ fontSize: 15.rpx,
+ ),
+ elevation: 0,
+ borderRadius: BorderRadius.circular(8.rpx),
+ ),
+ ),
+ ),
+ ],
+ ),
+ Text(
+ '正常值:0~2',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants().small_text_fontSize,
+ letterSpacing: 0.0,
+ color: Colors.grey),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/component/home_page/SleepDateWidget.dart b/lib/component/home_page/SleepDateWidget.dart
new file mode 100644
index 0000000..38e2e14
--- /dev/null
+++ b/lib/component/home_page/SleepDateWidget.dart
@@ -0,0 +1,136 @@
+import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart';
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutterflow_ui/flutterflow_ui.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/controller/theme_controller/ThemeController.dart';
+
+class SleepDateWidget extends StatefulWidget {
+ const SleepDateWidget({super.key});
+
+ @override
+ State createState() => _SleepDateWidgetState();
+}
+
+class _SleepDateWidgetState extends State {
+ @override
+ Widget build(BuildContext context) {
+ ThemeController themeController = Get.find();
+ return ClickableContainer(
+ backgroundColor: Colors.transparent, // 原 BoxDecoration 为空
+ highlightColor:
+ themeController.currentColor.sc3.withOpacity(0.1), // 自定义点击波纹颜色
+ borderRadius: AppConstants().normal_container_radius, // 原来没设置圆角
+ padding: EdgeInsets.zero,
+ onTap: () {
+ print("今日评分卡片点击");
+ },
+ child: Container(
+ width: MediaQuery.sizeOf(context).width * 0.19,
+ constraints: BoxConstraints(
+ minWidth: 143.rpx,
+ ),
+ child: Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(10.rpx, 25.rpx, 10.rpx, 22.rpx),
+ child: Container(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 14.rpx),
+ child: Text(
+ '今日',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants().title_text_fontSize,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 33.rpx),
+ child: Text(
+ '07/15',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: 20.rpx,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 16.rpx),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ '70',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: 48.rpx,
+ letterSpacing: 0.0,
+ color: stringToColor("#00C1AA")),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 16.rpx, 0, 0.rpx),
+ child: Text(
+ '分',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants().small_text_fontSize,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ Container(
+ width: 0.2.rpx,
+ height: 2.4.rpx,
+ constraints: BoxConstraints(
+ minWidth: 123.rpx,
+ minHeight: 47.rpx,
+ ),
+ child: FFButtonWidget(
+ onPressed: () {
+ print('合格按钮点击');
+ },
+ text: '合格',
+ options: FFButtonOptions(
+ height: 40.rpx,
+ padding:
+ EdgeInsetsDirectional.fromSTEB(16.rpx, 0, 16.rpx, 0),
+ iconPadding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
+ color: stringToColor("#00C1AA"),
+ textStyle:
+ FlutterFlowTheme.of(context).titleSmall.override(
+ fontFamily: 'Inter Tight',
+ color: Colors.white,
+ letterSpacing: 0.0,
+ ),
+ elevation: 0,
+ borderRadius: BorderRadius.circular(50.rpx),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/component/tool/ClickableContainer.dart b/lib/component/tool/ClickableContainer.dart
new file mode 100644
index 0000000..ac5f1f4
--- /dev/null
+++ b/lib/component/tool/ClickableContainer.dart
@@ -0,0 +1,45 @@
+import 'package:flutter/material.dart';
+
+class ClickableContainer extends StatelessWidget {
+ final Color backgroundColor; // 容器背景色
+ final Color highlightColor; // 点击时背景色
+ final EdgeInsetsGeometry padding; // 内部间距
+ final VoidCallback onTap; // 点击回调
+ final Widget child; // 子组件
+ final double borderRadius; // 容器圆角(可选,默认为0)
+
+ const ClickableContainer({
+ Key? key,
+ required this.backgroundColor,
+ required this.highlightColor,
+ required this.padding,
+ required this.onTap,
+ required this.child,
+ this.borderRadius = 0, // 默认无圆角
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: onTap,
+ child: Material(
+ color: Colors.transparent,
+ child: Ink(
+ decoration: BoxDecoration(
+ color: backgroundColor,
+ borderRadius: BorderRadius.circular(borderRadius),
+ ),
+ child: InkWell(
+ borderRadius: BorderRadius.circular(borderRadius),
+ onTap: onTap,
+ splashColor: highlightColor.withOpacity(0.3), // 点击时的波纹效果
+ child: Padding(
+ padding: padding,
+ child: child, // 内容自适应
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/component/tool/CustomCard.dart b/lib/component/tool/CustomCard.dart
index a5b4118..1c6975d 100644
--- a/lib/component/tool/CustomCard.dart
+++ b/lib/component/tool/CustomCard.dart
@@ -5,7 +5,6 @@ class CustomCard extends StatefulWidget {
final VoidCallback onTap; // 点击回调
final List colors; // 背景颜色列表
final Widget child; // 子组件
- final String title; // 标题
final bool enableAnimation; // 是否启用动画效果
final bool enableGradient; // 是否启用渐变
@@ -15,7 +14,6 @@ class CustomCard extends StatefulWidget {
required this.onTap,
required this.colors,
required this.child,
- required this.title,
this.enableAnimation = true, // 默认启用动画效果
this.enableGradient = true, // 默认启用渐变效果
}) : super(key: key);
diff --git a/lib/component/tool/FrostedDialog.dart b/lib/component/tool/FrostedDialog.dart
new file mode 100644
index 0000000..d77971b
--- /dev/null
+++ b/lib/component/tool/FrostedDialog.dart
@@ -0,0 +1,37 @@
+import 'dart:ui';
+import 'package:flutter/material.dart';
+
+class FrostedDialog extends StatelessWidget {
+ final Widget child;
+ final double blurSigma;
+ final Color barrierColor;
+
+ const FrostedDialog({
+ super.key,
+ required this.child,
+ this.blurSigma = 5.0,
+ this.barrierColor = const Color.fromRGBO(0, 0, 0, 0.5),
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Stack(
+ children: [
+ // 毛玻璃背景
+ BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: blurSigma, sigmaY: blurSigma),
+ child: Container(
+ color: Colors.transparent,
+ ),
+ ),
+ Dialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20.0),
+ ),
+ backgroundColor: Colors.transparent, // 背景透明,由 child 自己决定
+ child: child,
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/controller/device/blueteeth_bind_controller.dart b/lib/controller/device/blueteeth_bind_controller.dart
index adf8380..573fdce 100644
--- a/lib/controller/device/blueteeth_bind_controller.dart
+++ b/lib/controller/device/blueteeth_bind_controller.dart
@@ -5,7 +5,24 @@ part 'blueteeth_bind_controller.g.dart'; // 由json_serializable自动生成的
@JsonSerializable()
class BlueteethBindModel {
- int read = 1;//是否不再提示教程 0 不再提示 1 需要提示
+ int? read = 1; //是否不再提示教程 0 不再提示 1 需要提示
+ double? singal = -70; //扫描信号强度
+
+ List? devicelist = []; //蓝牙扫描到的设备数据列表
+ List? blelist = []; //蓝牙扫描到的设备数据列表
+ List? wifiList = [];
+
+ List bindArr = ["", "", ""];
+
+ String connectedWifiName = "";
+
+ int connectedRssi = 0;
+
+ String deviceName = "";
+
+ bool? deviceIndex0 = true;
+ bool? deviceIndex1 = false;
+ bool? deviceIndex2 = false;
BlueteethBindModel();
@@ -27,5 +44,23 @@ class BlueteethBindModel {
class BlueteethBindController extends GetControllerEx {
BlueteethBindController() {
attr = GetModel(BlueteethBindModel()).obs;
- }
-}
\ No newline at end of file
+ }
+
+ void updateDeviceStatus() {
+ // try {
+
+ // } catch (e) {
+ // print(e);
+ // EasyDartModule.logger.info("向后端请求设备绑定状态报错了:$e");
+ // } finally {
+ // EasyDartModule.logger.info("向后端请求设备绑定状态");
+ // }
+ }
+
+ Future bindDevice(d) async {
+ print("绑定参数:$d");
+ await Future.delayed(Duration(seconds: 1));
+ // return ApiService.request
+ // .post("/api/device/info/bind", data: formdata.FormData.fromMap(d));
+ }
+}
diff --git a/lib/controller/login/login_controller.dart b/lib/controller/login/login_controller.dart
new file mode 100644
index 0000000..410168d
--- /dev/null
+++ b/lib/controller/login/login_controller.dart
@@ -0,0 +1,175 @@
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutterflow_ui/flutterflow_ui.dart';
+
+import 'package:json_annotation/json_annotation.dart';
+import 'package:vbvs_app/common/util/MyUtils.dart';
+part 'login_controller.g.dart';
+
+@JsonSerializable()
+class LoginModel {
+ //版本id
+ int? loginStyle = 1; //1.密码登录 2.短信登录
+ String? account = '17649984946'; //账户
+ String? password = 'wyf123,.'; //密码
+
+ String? phone; //手机号
+ String? code; //验证码
+
+ String? register_code;
+
+ bool? showPd = true;
+
+ int? forceLogin = 0;
+
+ bool? isIos; //是否为ios设备
+
+ bool? isWeChatNotInstalled; //是否安装微信
+
+ bool? register_agree = false; //是否同意协议
+
+ LoginModel();
+
+ static LoginModel fromJson(Map json) =>
+ _$LoginModelFromJson(json);
+ Map toJson() => _$LoginModelToJson(this);
+}
+
+class LoginController extends GetControllerEx {
+ // 初始化实例
+ // final Fluwx fluwx = Fluwx();
+ // 微信监听返回值
+ // FluwxCancelable? fluwxCancelable;
+
+ // final UserRepository repository = UserRepository();
+ LoginController() {
+ attr = GetModel(LoginModel()).obs;
+ }
+
+ //登录
+ Future login(BuildContext context) async {
+ // return '';
+ String message = '';
+ String account = '';
+ String password = '';
+ // if (model.loginStyle == 1) {
+ // //账号登录
+ // if (model.account == null || model.account!.isEmpty) {
+ // message = '账户不能为空';
+ // showToast(message);
+ // return message;
+ // }
+ // if (model.password == null || model.password!.isEmpty) {
+ // message = '密码不能为空';
+ // showToast(message);
+ // return message;
+ // }
+ // account = model.account!;
+ // password = model.password!;
+ // }
+ // if (model.loginStyle == 2) {
+ // //账号登录
+ // if (model.phone == null || model.phone!.isEmpty) {
+ // message = '手机号不能为空';
+
+ // showToast(message);
+ // return message;
+ // }
+ // if (!MyUtils.isValidPhoneNumber(model.phone!)) {
+ // message = '请输入正确的手机号';
+
+ // showToast(message);
+ // return message;
+ // }
+ // if (model.code == null || model.code!.isEmpty) {
+ // message = '验证码不能为空';
+
+ // showToast(message);
+ // return message;
+ // }
+ // account = model.phone!;
+ // password = model.code!;
+ // }
+ // RegisterController registerController = Get.find();
+ // if (registerController.model.register_agree == null ||
+ // registerController.model.register_agree != true) {
+ // message = "需要同意协议";
+ // showToast(message);
+ // return message;
+ // }
+ // message = await repository.login(
+ // model.loginStyle!, account, password, model.forceLogin);
+ // model.forceLogin = 0;
+
+ return message;
+ }
+
+ Future getCode(BuildContext context) async {
+ String message = "";
+ if (model.register_agree == null || model.register_agree != true) {
+ // message = "需要同意协议";
+ // showToast(message);
+ return message;
+ }
+ if (model.phone == null || model.phone!.isEmpty) {
+ message = "请输入手机号";
+ // showToast(message);
+ return message;
+ }
+ if (!MyUtils.isValidPhoneNumber(model.phone!)) {
+ message = '请输入正确的手机号';
+ showToast(message);
+ return message;
+ }
+ // message = await repository.sendRegisterCode(model.phone!);
+ if (message.isNotEmpty) {
+ showToast(message ?? "发送失败,请稍后再试!");
+ return "发送失败,请稍后再试!";
+ } else {
+ showToast("发送验证码成功!", color: color_success);
+ }
+ return '';
+ }
+
+ //微信登录
+ // Future wxLoginSendAuth() async {
+ // /*
+ // 1、目前移动应用上微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用。
+ // 2、对于Android应用,建议总是显示微信登录按钮,当用户手机没有安装微信客户端时,请引导用户下载安装微信客户端。
+ // 3、对于iOS应用,考虑到iOS应用商店审核指南中的相关规定,建议开发者接入微信登录时,先检测用户手机是否已安装微信客户端
+ // (使用sdk中isWXAppInstalled函数 ),对未安装的用户隐藏微信登录按钮,只提供其他登录方式(比如手机号注册登录、游客登录等)
+ // */
+ // if (isAndroid) {
+ // bool isWeChatInstalled = await fluwx.isWeChatInstalled;
+ // debugPrint('is wechat installed: $isWeChatInstalled');
+ // if (!isWeChatInstalled) {
+ // showToast("请先安装微信APP,再使用微信登录");
+ // return;
+ // }
+ // }
+ // fluwx
+ // .authBy(
+ // which: NormalAuth(
+ // scope: 'snsapi_userinfo',
+ // state: 'wechat_sdk_zhmht_wxlogin',
+ // ))
+ // .then((data) {
+ // //返回true表示成功或者false表示失败,这边没有意义从login_controller页面构造函数监听中去处理
+ // debugPrint('msg:$data');
+ // });
+ // }
+
+ //退出登录
+ // Future logout() async {
+ // await repository.logout();
+ // }
+
+ // loginByWechatCode(String code) async {
+ // return await repository.loginByWechatCode(code);
+ // }
+
+ //注销账号
+ // deletedAccount() async {
+ // return await repository.deletedAccount();
+ // }
+}
diff --git a/lib/controller/login/login_controller.g.dart b/lib/controller/login/login_controller.g.dart
new file mode 100644
index 0000000..05c1dc7
--- /dev/null
+++ b/lib/controller/login/login_controller.g.dart
@@ -0,0 +1,33 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'login_controller.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+LoginModel _$LoginModelFromJson(Map json) => LoginModel()
+ ..loginStyle = (json['loginStyle'] as num?)?.toInt()
+ ..account = json['account'] as String?
+ ..password = json['password'] as String?
+ ..phone = json['phone'] as String?
+ ..code = json['code'] as String?
+ ..register_code = json['register_code'] as String?
+ ..showPd = json['showPd'] as bool?
+ ..forceLogin = (json['forceLogin'] as num?)?.toInt()
+ ..isIos = json['isIos'] as bool?
+ ..isWeChatNotInstalled = json['isWeChatNotInstalled'] as bool?;
+
+Map _$LoginModelToJson(LoginModel instance) =>
+ {
+ 'loginStyle': instance.loginStyle,
+ 'account': instance.account,
+ 'password': instance.password,
+ 'phone': instance.phone,
+ 'code': instance.code,
+ 'register_code': instance.register_code,
+ 'showPd': instance.showPd,
+ 'forceLogin': instance.forceLogin,
+ 'isIos': instance.isIos,
+ 'isWeChatNotInstalled': instance.isWeChatNotInstalled,
+ };
diff --git a/lib/controller/main_bottom/global_controller.dart b/lib/controller/main_bottom/global_controller.dart
index 8772ee5..6373562 100644
--- a/lib/controller/main_bottom/global_controller.dart
+++ b/lib/controller/main_bottom/global_controller.dart
@@ -1,8 +1,10 @@
import 'dart:async';
+import 'package:EasyDartModule/EasyDartModule.dart';
import 'package:ef/ef.dart';
import 'package:vbvs_app/controller/main_bottom/main_page_controller.dart';
import 'package:vbvs_app/controller/user_info_controller.dart';
+import 'package:vbvs_app/pages/common/selectDialog.dart';
class GlobalModel {
List deviceList = [];
@@ -138,16 +140,11 @@ class GlobalController extends GetControllerEx {
deviceUpdateTimerCreated() {
if (getDeviceListTimer == null) {
getDeviceListTimer = Timer.periodic(const Duration(seconds: 10), (t) {
- if (userInfoController.model.token != null) {
-
- }
+ if (userInfoController.model.token != null) {}
});
}
}
-
-
-
getDeviceGroupName(device) {
return "${device['roomName']}/${device["deviceType"]?["name"]}/${device["name"]}";
}
@@ -169,4 +166,49 @@ class GlobalController extends GetControllerEx {
model.deviceType = rs.where((d) => d["page"] != null).toList();
updateAll();
}
+
+ getDeviceList({int time = 1}) async {
+ await EasyDartModule.dio.get("/api/device/info/list").then((d) {
+ Map d_ = {};
+ d.data?["data"]?.forEach((item) {
+ if (d_[item["roomName"]] == null) {
+ d_[item["roomName"]] = [];
+ }
+ d_[item["roomName"]].add(item);
+ });
+ List res_ = [];
+ d_.keys.forEach((key) {
+ res_.addAll(d_[key]);
+ });
+ model.deviceList = res_;
+ if (model.deviceMain != null && model.deviceMain["mac"] != null) {
+ bool isClose = false;
+ model.deviceList.forEach((item) {
+ if (item["mac"] == model.deviceMain["mac"]) {
+ model.deviceMain = item;
+ isClose = true;
+ updateAll();
+ }
+ });
+ if (!isClose) {
+ model.deviceMain = {};
+ updateAll();
+ showCustomConfirmAndCancelDialog(Get.context!, "设备已经被解绑,是否回到主界面?")
+ .then((e) {
+ if (e == "confirm") {
+ Get.find().model.currentIndex = 0;
+ Get.offAllNamed("/mianPageBottomChange");
+ }
+ });
+ }
+ } else {
+ updateAll();
+ }
+ }).catchError((e) {
+ print("$e");
+ if (time > 0) {
+ getDeviceList(time: time - 1);
+ }
+ });
+ }
}
diff --git a/lib/controller/person/person_controller.dart b/lib/controller/person/person_controller.dart
new file mode 100644
index 0000000..e7c93e7
--- /dev/null
+++ b/lib/controller/person/person_controller.dart
@@ -0,0 +1,33 @@
+import 'package:ef/ef.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part 'person_controller.g.dart'; // 由json_serializable自动生成的部分
+
+@JsonSerializable()
+class PersonModel {
+ int read = 1;
+
+ DateTime? birthday;//是否不再提示教程 0 不再提示 1 需要提示
+
+ PersonModel();
+
+ // 从JSON反序列化时的异常处理
+
+ factory PersonModel.fromJson(Map json) {
+ try {
+ return _$PersonModelFromJson(json);
+ } catch (e) {
+ // 在实际应用中,应该有更细致的异常处理策略和错误日志
+ return PersonModel(); // 或者返回一个带有错误信息的特定DeviceInfoModel实例
+ }
+ }
+
+ // 序列化为JSON时的异常处理
+ Map toJson() => _$PersonModelToJson(this);
+}
+
+class PersonController extends GetControllerEx {
+ PersonController() {
+ attr = GetModel(PersonModel()).obs;
+ }
+}
\ No newline at end of file
diff --git a/lib/controller/person/person_controller.g.dart b/lib/controller/person/person_controller.g.dart
new file mode 100644
index 0000000..004da7e
--- /dev/null
+++ b/lib/controller/person/person_controller.g.dart
@@ -0,0 +1,19 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'person_controller.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+PersonModel _$PersonModelFromJson(Map json) => PersonModel()
+ ..read = (json['read'] as num).toInt()
+ ..birthday = json['birthday'] == null
+ ? null
+ : DateTime.parse(json['birthday'] as String);
+
+Map _$PersonModelToJson(PersonModel instance) =>
+ {
+ 'read': instance.read,
+ 'birthday': instance.birthday?.toIso8601String(),
+ };
diff --git a/lib/controller/time/countdown_controller.dart b/lib/controller/time/countdown_controller.dart
new file mode 100644
index 0000000..7840138
--- /dev/null
+++ b/lib/controller/time/countdown_controller.dart
@@ -0,0 +1,33 @@
+import 'dart:async';
+import 'package:get/get.dart';
+
+class CountdownController extends GetxController {
+ var countdown = 0.obs;
+ Timer? timer;
+
+ @override
+ void onInit() {
+ super.onInit();
+ }
+
+ void startCountdown(int seconds) {
+ timer?.cancel(); // 取消之前的定时器
+ countdown.value = seconds;
+ timer = Timer.periodic(Duration(seconds: 1), (timer) {
+ int elapsed = timer.tick;
+ int remaining = seconds - elapsed;
+ if (remaining > 0) {
+ countdown.value = remaining;
+ } else {
+ countdown.value = 0;
+ timer.cancel();
+ }
+ });
+ }
+
+ @override
+ void onClose() {
+ timer?.cancel();
+ super.onClose();
+ }
+}
diff --git a/lib/controller/user_info_controller.dart b/lib/controller/user_info_controller.dart
index 38d05f3..6c4e7e5 100644
--- a/lib/controller/user_info_controller.dart
+++ b/lib/controller/user_info_controller.dart
@@ -1,19 +1,7 @@
-import 'dart:io';
-
import 'package:ef/ef.dart';
-
-import 'package:get_storage/get_storage.dart';
import 'package:json_annotation/json_annotation.dart';
-import 'package:path/path.dart' as p;
-import 'package:uuid/uuid.dart';
-import 'package:vbvs_app/common/color/app_uri_status.dart';
-import 'package:vbvs_app/common/util/CommonVariables.dart';
-
-import 'package:vbvs_app/common/util/MyUtils.dart';
-import 'package:vbvs_app/model/api_response.dart';
import 'package:vbvs_app/model/user_data.dart';
-
part 'user_info_controller.g.dart';
@JsonSerializable()
@@ -34,9 +22,13 @@ class UserInfoModel {
User? superbase_user;
String? img_bucket = 'user';
- int? login = 0;
+ int? login = 1; //0未登录 1 登录
- bool? register_agree = false; //注册协议
+
+
+ int? deviceBindNum = 0; //绑定设备数量
+
+ int? loginPhone = 0;//0 本机号码 1其他手机号
UserInfoModel();
static UserInfoModel fromJson(Map json) =>
diff --git a/lib/controller/user_info_controller.g.dart b/lib/controller/user_info_controller.g.dart
index f8dc0b9..2243d6a 100644
--- a/lib/controller/user_info_controller.g.dart
+++ b/lib/controller/user_info_controller.g.dart
@@ -19,8 +19,7 @@ UserInfoModel _$UserInfoModelFromJson(Map json) =>
..deviceModel = json['deviceModel'] as String?
..appVersion = json['appVersion'] as String?
..img_bucket = json['img_bucket'] as String?
- ..login = (json['login'] as num?)?.toInt()
- ..register_agree = json['register_agree'] as bool?;
+ ..login = (json['login'] as num?)?.toInt();
Map _$UserInfoModelToJson(UserInfoModel instance) =>
{
@@ -34,5 +33,4 @@ Map _$UserInfoModelToJson(UserInfoModel instance) =>
'appVersion': instance.appVersion,
'img_bucket': instance.img_bucket,
'login': instance.login,
- 'register_agree': instance.register_agree,
};
diff --git a/lib/main.dart b/lib/main.dart
index f3e0f22..5e83c29 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -4,9 +4,12 @@ import 'package:flutter/services.dart';
import 'package:get_storage/get_storage.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
+import 'package:vbvs_app/controller/login/login_controller.dart';
import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
import 'package:vbvs_app/controller/main_bottom/main_page_controller.dart';
+import 'package:vbvs_app/controller/person/person_controller.dart';
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
+import 'package:vbvs_app/controller/time/countdown_controller.dart';
import 'package:vbvs_app/language/AppLanguage.dart';
import 'package:vbvs_app/model/CustomThemeColor.dart';
import 'package:vbvs_app/model/user_data.dart';
@@ -25,6 +28,7 @@ Future main() async {
// await GetStorage.init();
// 初始化登录
await initLogin();
+ await initLog();
// 检查网络
// Checknetwork.checkNetwork();
// 微信开放平台注册
@@ -41,6 +45,10 @@ Future main() async {
// runApp(const MyApp());
}
+initLog() {
+
+}
+
Future initLogin() async {
// 初始化控制器
Get.put(UserInfoController());
@@ -155,6 +163,9 @@ class MyApp extends StatelessWidget {
Get.put(GlobalController()),
Get.lazyPut(() => MainPageController()),
Get.lazyPut(() => BlueteethBindController()),
+ Get.lazyPut(() => PersonController()),
+ Get.lazyPut(() => CountdownController()),
+ Get.lazyPut(() => LoginController()),
]));
});
}
diff --git a/lib/model/BleDeviceData.dart b/lib/model/BleDeviceData.dart
new file mode 100644
index 0000000..b4ad163
--- /dev/null
+++ b/lib/model/BleDeviceData.dart
@@ -0,0 +1,35 @@
+class BleDeviceData {
+ final int type; // 协议版本
+ final int sn; // 广播包序号低8位
+ final String deviceId; // 设备唯一地址(6字节)
+ final int bre; // 呼吸
+ final int ht; // 心率
+ final int active; // 体动等级
+ final int flag; // 设备属性
+ final int version; // 软件版本
+ final int qsn; // 广播帧序列号高16位
+ int? status; // 设备状态
+ String? name;//设备名称
+ int? rssi;
+ String? mac;//mac地址
+
+ BleDeviceData({
+ required this.type,
+ required this.sn,
+ required this.deviceId,
+ required this.bre,
+ required this.ht,
+ required this.active,
+ required this.flag,
+ required this.version,
+ required this.qsn,
+ });
+
+ int get fullSeq => qsn * 256 + sn;
+
+ bool get isOnline => (flag & 0x01) != 0;
+ bool get sensorError => (flag & 0x02) != 0;
+ bool get apnea => (flag & 0x04) != 0;
+ bool get inBed => (flag & 0x08) != 0;
+ bool get expired => (flag & 0x10) != 0;
+}
diff --git a/lib/pages/common/selectDialog.dart b/lib/pages/common/selectDialog.dart
new file mode 100644
index 0000000..c5e0411
--- /dev/null
+++ b/lib/pages/common/selectDialog.dart
@@ -0,0 +1,773 @@
+import 'package:ef/ef.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:vbvs_app/common/util/FitTool.dart';
+import 'package:vbvs_app/common/util/MyUtils.dart';
+
+
+getOnePicker(context, List arr, int checkIndex, Function onSelectedItemChanged,
+ {bool looping = false}) {
+ return CupertinoPicker(
+ key: UniqueKey(),
+ useMagnifier: false,
+ itemExtent: 80.rpx,
+ magnification: 1,
+ diameterRatio: 3,
+ squeeze: 1,
+ looping: looping,
+ scrollController: FixedExtentScrollController(initialItem: checkIndex),
+ selectionOverlay: Container(),
+ onSelectedItemChanged: (int value) {
+ // print("$value");
+ onSelectedItemChanged.call(value);
+ },
+ children: [
+ ...List.generate(arr.length, (index) {
+ return Container(
+ alignment: Alignment.center,
+ width: 400.rpx,
+ decoration: BoxDecoration(
+ border: Border(
+ bottom: index != arr.length
+ ? BorderSide(
+ color: stringToColor("#8D95B0"),
+ )
+ : BorderSide.none,
+ ),
+ ),
+ child: Text("${arr[index]}",
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx)),
+ );
+ })
+ ],
+ );
+}
+
+Future showDateSelectionDialog(BuildContext context,
+ {required DateTime checkDate,
+ Function? checkChange,
+ String title = "选择生日"}) {
+ Color checkColor = stringToColor("#D3B684");
+ List years = [], months = [], days = [];
+ var days_select = [].obs;
+ int day_len = 31;
+ int year = DateTime.now().year;
+ for (var i = 0; i < 100; i++) {
+ years.insert(0, year - i);
+ }
+ for (var i = 1; i < 13; i++) {
+ months.add(i);
+ }
+ for (var i = 1; i < 32; i++) {
+ days.add(i);
+ }
+ int yearIndex = years.lastIndexOf(checkDate.year);
+ int monthIndex = months.lastIndexOf(checkDate.month);
+ day_len = DateTime.fromMillisecondsSinceEpoch(
+ DateTime(years[yearIndex], months[monthIndex] + 1)
+ .millisecondsSinceEpoch -
+ 1000)
+ .day;
+ days_select.value = days.sublist(0, day_len);
+ int dayIndex = days.lastIndexOf(checkDate.day);
+ return showDialog(
+ // barrierColor: stringToColor("#000320"),
+ context: context,
+ barrierDismissible: true, // 点击对话框外部可关闭
+ builder: (BuildContext context) {
+ return Stack(
+ children: [
+ Positioned(
+ bottom: 0, // 控制弹窗距离顶部的位置
+ left: 0,
+ right: 0,
+ child: Material(
+ color: Colors.transparent,
+ child: Dialog(
+ backgroundColor: stringToColor("#182B7C"),
+ insetPadding: EdgeInsets.zero,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+ child: Container(
+ width: double.infinity,
+ padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Container(
+ alignment: Alignment.centerLeft,
+ height: 60.rpx,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Text(
+ "$title",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ closeIconWhite
+ ],
+ ),
+ ),
+ Container(
+ height: 240.rpx,
+ margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
+ padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
+ child: Row(
+ children: [
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 40.rpx, right: 30.rpx),
+ child: getOnePicker(context, years, yearIndex,
+ (d) {
+ yearIndex = d;
+ dayIndex = 0;
+ day_len = DateTime.fromMillisecondsSinceEpoch(
+ DateTime(years[yearIndex],
+ months[monthIndex] + 1)
+ .millisecondsSinceEpoch -
+ 1000)
+ .day;
+ days_select.value = days.sublist(0, day_len);
+ }),
+ ),
+ ),
+ Container(
+ child: Text(
+ "年",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 30.rpx, right: 30.rpx),
+ child: getOnePicker(context, months, monthIndex,
+ (d) {
+ monthIndex = d;
+ dayIndex = 0;
+ day_len = DateTime.fromMillisecondsSinceEpoch(
+ DateTime(years[yearIndex],
+ months[monthIndex] + 1)
+ .millisecondsSinceEpoch -
+ 1000)
+ .day;
+ days_select.value = days.sublist(0, day_len);
+ }),
+ ),
+ ),
+ Container(
+ child: Text(
+ "月",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 30.rpx, right: 40.rpx),
+ child: Obx(
+ () {
+ // print("${dayIndex} ${day_len}");
+ return getOnePicker(
+ context,
+ days_select,
+ dayIndex,
+ (d) {
+ dayIndex = d;
+ },
+ );
+ },
+ ),
+ ),
+ ),
+ Container(
+ child: Text(
+ "日",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ ],
+ ),
+ ),
+ InkWell(
+ onTap: () {
+ checkChange?.call(DateTime(years[yearIndex],
+ months[monthIndex], days[dayIndex]));
+ Get.back();
+ },
+ child: Container(
+ height: 68.rpx,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ color: stringToColor("#D3B684"),
+ borderRadius: BorderRadius.circular(10.rpx),
+ ),
+ child: Text(
+ "确定",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+}
+
+Future showDayTimeSelectionDialog(BuildContext context,
+ {required List dayTimeArr, Function? checkChange, String title = ""}) {
+ Color checkColor = stringToColor("#D3B684");
+ List hours = [], minutes = [];
+ for (var i = 0; i < 24; i++) {
+ hours.add(i);
+ }
+ for (var i = 0; i < 60; i++) {
+ minutes.add(i);
+ }
+ int hoursIndex = hours.lastIndexOf(dayTimeArr[0]);
+ int minutesIndex = minutes.lastIndexOf(dayTimeArr[1]);
+ return showDialog(
+ // barrierColor: stringToColor("#000320"),
+ context: context,
+ barrierDismissible: true, // 点击对话框外部可关闭
+ builder: (BuildContext context) {
+ return Stack(
+ children: [
+ Positioned(
+ bottom: 0, // 控制弹窗距离顶部的位置
+ left: 0,
+ right: 0,
+ child: Material(
+ color: Colors.transparent,
+ child: Dialog(
+ backgroundColor: stringToColor("#182B7C"),
+ insetPadding: EdgeInsets.zero,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+ child: Container(
+ width: double.infinity,
+ padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Container(
+ alignment: Alignment.centerLeft,
+ height: 60.rpx,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Text(
+ "$title",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ closeIconWhite
+ ],
+ ),
+ ),
+ Container(
+ height: 240.rpx,
+ margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
+ padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
+ child: Row(
+ children: [
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 40.rpx, right: 30.rpx),
+ child: getOnePicker(context, hours, hoursIndex,
+ (d) {
+ hoursIndex = d;
+ }),
+ ),
+ ),
+ Container(
+ child: Text(
+ "时",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 30.rpx, right: 30.rpx),
+ child: getOnePicker(
+ context, minutes, minutesIndex, (d) {
+ minutesIndex = d;
+ }),
+ ),
+ ),
+ Container(
+ child: Text(
+ "分",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ ],
+ ),
+ ),
+ InkWell(
+ onTap: () {
+ checkChange?.call(
+ [hours[hoursIndex], minutes[minutesIndex]]);
+ Get.back();
+ },
+ child: Container(
+ height: 68.rpx,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ color: stringToColor("#D3B684"),
+ borderRadius: BorderRadius.circular(10.rpx),
+ ),
+ child: Text(
+ "确定",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+}
+
+Future showOneSelectionDialog(BuildContext context,
+ {required List arr,
+ int checkIndex = 0,
+ Function? checkChange,
+ String title = "选择性别"}) {
+ Color checkColor = stringToColor("#D3B684");
+ return showDialog(
+ // barrierColor: stringToColor("#000320"),
+ context: context,
+ barrierDismissible: true, // 点击对话框外部可关闭
+ builder: (BuildContext context) {
+ return Stack(
+ children: [
+ Positioned(
+ bottom: 0, // 控制弹窗距离顶部的位置
+ left: 0,
+ right: 0,
+ child: Material(
+ color: Colors.transparent,
+ child: Dialog(
+ backgroundColor: stringToColor("#182B7C"),
+ insetPadding: EdgeInsets.zero,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+ child: Container(
+ width: double.infinity,
+ padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Container(
+ alignment: Alignment.centerLeft,
+ height: 60.rpx,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Text(
+ "$title",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ closeIconWhite
+ ],
+ ),
+ ),
+ Container(
+ height: 240.rpx,
+ alignment: Alignment.center,
+ margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
+ padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
+ child: Container(
+ width: 400.rpx,
+ child:
+ getOnePicker(context, arr, checkIndex, (index) {
+ checkIndex = index;
+ }),
+ )),
+ InkWell(
+ onTap: () {
+ checkChange?.call(checkIndex);
+ Get.back();
+ },
+ child: Container(
+ height: 68.rpx,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ color: stringToColor("#D3B684"),
+ borderRadius: BorderRadius.circular(10.rpx),
+ ),
+ child: Text(
+ "确定",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+}
+
+enum ConfirmDialogIcon {
+ none,
+ danger,
+ success,
+ warn;
+
+ get uname {
+ String v = "";
+ switch (this) {
+ case ConfirmDialogIcon.danger:
+ v = "danger";
+ break;
+ case ConfirmDialogIcon.success:
+ v = "success";
+ break;
+ case ConfirmDialogIcon.warn:
+ v = "warn";
+ break;
+ case ConfirmDialogIcon.none:
+ v = "";
+ break;
+ }
+ return v;
+ }
+}
+
+Future showCustomConfirmDialog(BuildContext context, String name,
+ {String btnName = "确定",
+ ConfirmDialogIcon icon = ConfirmDialogIcon.warn}) async {
+ return showDialog(
+ context: context,
+ barrierDismissible: true,
+ builder: (BuildContext context) {
+ return Dialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(10.0),
+ ),
+ child: Container(
+ width: 660.rpx,
+ padding: EdgeInsets.fromLTRB(16, 0, 16, 16),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ alignment: Alignment.centerRight,
+ child: closeIcon,
+ ),
+ SizedBox(height: 60.rpx),
+ if ("${icon.uname}".isNotEmpty)
+ Center(
+ child: Container(
+ margin: EdgeInsets.only(bottom: 39.rpx),
+ width: 50.rpx,
+ height: 50.rpx,
+ child: Image.asset("assets/images/toast/${icon.uname}.png"),
+ ),
+ ),
+ Center(
+ child: Text(
+ '${name}',
+ style: TextStyle(fontSize: 16),
+ ),
+ ),
+ SizedBox(height: 20.rpx),
+ Container(
+ margin: EdgeInsets.only(top: 50.rpx, bottom: 40.rpx),
+ alignment: Alignment.center,
+ child: InkWell(
+ onTap: () {
+ Get.back(result: "confirm");
+ },
+ child: Container(
+ width: 260.rpx,
+ height: 60.rpx,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(6),
+ color: stringToColor("#D3B684")),
+ child: Text(
+ '$btnName',
+ style: TextStyle(color: Colors.white, fontSize: 30.rpx),
+ ),
+ ),
+ ),
+ )
+ ],
+ ),
+ ),
+ );
+ },
+ );
+}
+
+
+Future showCustomConfirmAndCancelDialog(BuildContext context, String name,
+ {String confirmName = "确定",
+ String cancelName = "取消",
+ ConfirmDialogIcon icon = ConfirmDialogIcon.warn}) async {
+ return showDialog(
+ context: context,
+ barrierDismissible: true,
+ builder: (BuildContext context) {
+ return Dialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(10.0),
+ ),
+ child: Container(
+ width: 660.rpx,
+ padding: EdgeInsets.fromLTRB(16, 0, 16, 16),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ alignment: Alignment.centerRight,
+ child: closeIcon,
+ ),
+ SizedBox(height: 40.rpx),
+ if ("${icon.uname}".isNotEmpty)
+ Center(
+ child: Container(
+ margin: EdgeInsets.only(bottom: 39.rpx),
+ width: 50.rpx,
+ height: 50.rpx,
+ child: Image.asset("assets/images/toast/${icon.uname}.png"),
+ ),
+ ),
+ Center(
+ child: Text(
+ '${name}',
+ style: TextStyle(fontSize: 16),
+ ),
+ ),
+ SizedBox(height: 20.rpx),
+ Container(
+ margin: EdgeInsets.only(top: 50.rpx, bottom: 40.rpx),
+ alignment: Alignment.center,
+ child: InkWell(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ InkWell(
+ onTap: () {
+ Get.back(result: "cancel");
+ },
+ child: Container(
+ width: 200.rpx,
+ height: 60.rpx,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(6),
+ border: Border.all(color: Colors.black12)),
+ child: Text(
+ '$cancelName',
+ style:
+ TextStyle(color: Colors.black, fontSize: 30.rpx),
+ ),
+ ),
+ ),
+ SizedBox(
+ width: 80.rpx,
+ ),
+ InkWell(
+ onTap: () {
+ Get.back(result: "confirm");
+ },
+ child: Container(
+ width: 200.rpx,
+ height: 60.rpx,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(6),
+ color: stringToColor("#D3B684")),
+ child: Text(
+ '$confirmName',
+ style:
+ TextStyle(color: Colors.white, fontSize: 30.rpx),
+ ),
+ ),
+ )
+ ],
+ )),
+ )
+ ],
+ ),
+ ),
+ );
+ },
+ );
+}
+
+//权限说明弹窗
+void showPermissionInfoDialog(BuildContext context, List data) {
+ showDialog(
+ context: context,
+ barrierDismissible: false, // 点击对话框外部可关闭
+ builder: (BuildContext context) {
+ return Stack(
+ children: [
+ Positioned(
+ top: 30.rpx, // 控制弹窗距离顶部的位置
+ left: 0,
+ right: 0,
+ child: Material(
+ color: Colors.transparent,
+ child: Dialog(
+ backgroundColor: Colors.white,
+ insetPadding: EdgeInsets.fromLTRB(0, 0, 0, 0),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(10.0),
+ ),
+ child: Container(
+ constraints: BoxConstraints(maxHeight: 500.rpx),
+ padding: EdgeInsets.all(16),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(10),
+ ),
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ...List.generate(data.length, (index) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "${data[index][0]}",
+ style: TextStyle(
+ fontSize: 30.rpx,
+ color: stringToColor("#333333"),
+ ),
+ ),
+ SizedBox(
+ height: 4.rpx,
+ ),
+ Text(
+ "${data[index][1]}",
+ style: TextStyle(
+ fontSize: 26.rpx,
+ color: stringToColor("#A4AABC"),
+ ),
+ ),
+ if (index != data.length - 1)
+ SizedBox(
+ height: 18.rpx,
+ ),
+ ],
+ );
+ }),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+}
diff --git a/lib/pages/device_bind/bind_device_success.dart b/lib/pages/device_bind/bind_device_success.dart
new file mode 100644
index 0000000..626e40d
--- /dev/null
+++ b/lib/pages/device_bind/bind_device_success.dart
@@ -0,0 +1,320 @@
+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/appConstants.dart';
+import 'package:vbvs_app/common/util/FitTool.dart';
+import 'package:vbvs_app/common/util/MyUtils.dart';
+import 'package:vbvs_app/component/tool/CustomCard.dart';
+import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
+import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
+import 'package:vbvs_app/controller/user_info_controller.dart';
+
+class BindDeviceSuccess extends StatefulWidget {
+ const BindDeviceSuccess({super.key});
+
+ @override
+ State createState() => _EPageState();
+}
+
+class _EPageState extends State {
+ GlobalController globalController = Get.find();
+ UserInfoController userInfoController = Get.find();
+ BlueteethBindController blueteethBindController = Get.find();
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return LayoutBuilder(
+ builder: (context, bodySize) => GestureDetector(
+ onTap: () => FocusScope.of(context).unfocus(),
+ child: Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: AssetImage('assets/img/bgNoImg.png'), // 本地图片
+ fit: BoxFit.fill, // 填满整个 Container
+ ),
+ ),
+ child: Scaffold(
+ backgroundColor: Colors.transparent, // 加上这一行
+ appBar: AppBar(
+ backgroundColor: stringToColor("#242835"),
+ // backgroundColor: Colors.transparent,
+ automaticallyImplyLeading: false,
+ iconTheme: IconThemeData(color: Colors.white),
+ titleSpacing: 0,
+ // leading: returnIconButtom,
+ title: Container(
+ // color: Colors.grey,
+ width: double.infinity,
+ height: 180.rpx,
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ /// 居中标题
+ Text(
+ '绑定成功.标题'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx,
+ ),
+ ),
+
+ /// 左边返回按钮
+ Positioned(
+ left: 0,
+ child: returnIconButtom,
+ ),
+ ],
+ ),
+ ),
+
+ actions: [],
+ centerTitle: false,
+ ),
+
+ body: SafeArea(
+ top: true,
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(113.rpx, 0, 113.rpx, 0),
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 74.rpx, 0, 0),
+ child: Container(
+ width: 124.rpx,
+ height: 124.rpx,
+ // width: double.infinity,
+ decoration: BoxDecoration(),
+ child: SvgPicture.asset(
+ 'assets/img/icon/tick.svg',
+ fit: BoxFit.cover,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 42.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Text(
+ '绑定成功.绑定成功'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 48.rpx,
+ letterSpacing: 0.0,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 265.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Text(
+ '绑定成功.分享标题'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 48.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: Text(
+ '绑定成功.分享内容'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: Colors.white,
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 110.rpx, 0, 0),
+ child: CustomCard(
+ borderRadius:
+ AppConstants().button_container_radius, // 圆角半径
+ onTap: () {
+ print('Button pressed ...');
+ Get.toNamed("/deviceType");
+ },
+ colors: [
+ // 渐变色
+ stringToColor("45D989"), // 左侧渐变色
+ stringToColor("00C1AA"), // 右侧渐变色
+ ],
+ child: Container(
+ width: MediaQuery.sizeOf(context).width * 0.66,
+ height: MediaQuery.sizeOf(context).height * 0.055,
+ constraints: BoxConstraints(
+ minWidth: 500.rpx,
+ minHeight: 90.rpx,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ SvgPicture.asset(
+ 'assets/img/icon/share.svg',
+ width: 25.rpx,
+ height: 25.rpx, // 如果 SVG 中没有固定颜色,可以这样设置
+ color: Colors.white, // 设置图标颜色为白色
+ ),
+ Text(
+ '绑定成功.立即分享'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ color: Colors.white, // 文字颜色
+ fontFamily: 'Inter',
+ fontSize: AppConstants()
+ .normal_text_fontSize, // 自定义字体大小
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(width: 17.rpx)),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 18.rpx, 0, 0),
+ child: CustomCard(
+ borderRadius:
+ AppConstants().button_container_radius, // 圆角半径
+ onTap: () {
+ Get.offAllNamed("/mianPageBottomChange");
+ },
+ colors: [
+ // 渐变色
+ stringToColor("45D989"), // 左侧渐变色
+ stringToColor("00C1AA"), // 右侧渐变色
+ ],
+
+ child: Container(
+ width: MediaQuery.sizeOf(context).width * 0.66,
+ 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: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ color: Colors.white, // 文字颜色
+ fontFamily: 'Inter',
+ fontSize: AppConstants()
+ .normal_text_fontSize, // 自定义字体大小
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(width: 17.rpx)),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ Widget _buildDeviceCard(BuildContext context,
+ {required String title, required String imageUrl, required String type}) {
+ return CustomCard(
+ borderRadius: 20.rpx, // 圆角大小
+ onTap: () {
+ if (type != null) {
+ if (type == '1') {
+ Get.toNamed("/blueteethDevice");
+ }
+ }
+ },
+ // colors: [Colors.white.withOpacity(0.06)], // 背景色
+ colors: [stringToColor("#242835")], // 背景色
+ child: Container(
+ width: double.infinity,
+ height: MediaQuery.sizeOf(context).height * 0.135,
+ constraints: BoxConstraints(
+ minHeight: 220.rpx,
+ ),
+ padding: EdgeInsetsDirectional.fromSTEB(77.rpx, 0, 21.rpx, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ title,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFC2CED7),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ClipRRect(
+ borderRadius: BorderRadius.circular(8.rpx),
+ child: Image.asset(
+ imageUrl,
+ width: 212.rpx,
+ height: 168.rpx,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/device_bind/blueteeth_device_page.dart b/lib/pages/device_bind/blueteeth_device_page.dart
new file mode 100644
index 0000000..d653d24
--- /dev/null
+++ b/lib/pages/device_bind/blueteeth_device_page.dart
@@ -0,0 +1,1059 @@
+import 'dart:async';
+
+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:permission_handler/permission_handler.dart'; // 引入permission_handler
+import 'package:vbvs_app/common/util/FitTool.dart';
+import 'package:vbvs_app/common/util/MyUtils.dart';
+import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
+import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
+import 'package:vbvs_app/controller/user_info_controller.dart';
+import 'package:vbvs_app/model/BleDeviceData.dart';
+import 'package:vbvs_app/pages/common/selectDialog.dart';
+import 'package:vbvs_app/pages/device_bind/componnet/SingleBlueteethDeviceCompoentWidget.dart';
+import 'package:vbvs_app/common/util/Ble.dart' as ble;
+
+class BlueteethDevicePage extends StatefulWidget {
+ int tid = -1;
+ BlueteethDevicePage({super.key, this.tid = -1});
+
+ @override
+ State createState() => _EPageState();
+}
+
+class _EPageState extends State {
+ GlobalController globalController = Get.find();
+ UserInfoController userInfoController = Get.find();
+ BlueteethBindController blueteethBindController = Get.find();
+ late FlutterBluePlus flutterBlue; // 声明 flutterBlue 实例
+ List scanResults = []; // 存储扫描到的设备
+ bool isScanning = false; // 扫描状态控制
+ Timer? _timer; // 定时器,用于重复扫描
+ bool _isDialogShowing = false;
+
+ var currentConnectedDeviceProp;
+ var connectDeviceCurrent = null;
+ List bleDevice = [];
+ String currentMsg = "寻找设备中...";
+ Timer? connectTimer;
+ bool isFind = false;
+ List bindArrBackup = [];
+ List bindArr = ["", "", ""];
+
+ @override
+ void initState() {
+ super.initState();
+ flutterBlue = FlutterBluePlus(); // 初始化flutterBlue实例
+ _checkBluetoothPermission(); // 检查蓝牙权限
+ }
+
+ // 检查蓝牙权限
+ Future _checkBluetoothPermission() async {
+ PermissionStatus bluetoothStatus = await Permission.bluetooth.status;
+ PermissionStatus locationStatus = await Permission.location.status;
+
+ if (bluetoothStatus.isGranted && locationStatus.isGranted) {
+ // 权限已授予,开始扫描
+ _startScanning();
+ _startPeriodicScan(); // 开始定时扫描
+ } else {
+ // 权限未授予,请求权限
+ _requestBluetoothPermission();
+ }
+ }
+
+ Future _requestBluetoothPermission() async {
+ // Android 13+ 使用新的蓝牙权限
+ Map statuses = await [
+ Permission.bluetoothScan,
+ Permission.bluetoothConnect,
+ Permission.location, // Android 12 及以下仍需要位置权限来进行扫描
+ ].request();
+
+ bool allGranted = statuses[Permission.bluetoothScan]?.isGranted == true &&
+ statuses[Permission.bluetoothConnect]?.isGranted == true &&
+ statuses[Permission.location]?.isGranted == true;
+
+ if (allGranted) {
+ // 用户授予了权限,开始扫描
+ _startScanning();
+ _startPeriodicScan();
+ } else {
+ // 权限被拒绝,提示用户
+ _showPermissionDeniedDialog();
+ }
+ }
+
+ // 显示权限被拒绝的提示
+ void _showPermissionDeniedDialog() {
+ showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ title: Text("权限提示"),
+ content: Text("应用需要蓝牙和位置权限才能扫描设备。请授予权限。"),
+ actions: [
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ child: Text("确定"),
+ ),
+ ],
+ );
+ },
+ );
+ }
+
+ // 开始扫描蓝牙设备
+ void _startScanning() async {
+ var bluetoothState = await FlutterBluePlus.isOn;
+ if (!bluetoothState && !_isDialogShowing) {
+ _isDialogShowing = true;
+ await _showBluetoothNotEnabledDialog();
+ _isDialogShowing = false;
+ return;
+ }
+
+ if (!isScanning) {
+ setState(() {
+ isScanning = true;
+ });
+
+ await FlutterBluePlus.startScan(timeout: Duration(seconds: 10));
+
+ // FlutterBluePlus.scanResults.listen((results) {
+ // // 使用 controller 中设定的最小信号强度过滤
+ // final signalThreshold = blueteethBindController.model.singal!;
+ // final filteredResults = results
+ // .where((r) =>
+ // r.rssi > signalThreshold &&
+ // r.advertisementData.localName == "AITH-V2")
+ // .toList();
+ // setState(() {
+ // scanResults = filteredResults;
+ // print("过滤后设备数量:${filteredResults.length}");
+ // blueteethBindController.model.devicelist = filteredResults;
+ // blueteethBindController.updateAll();
+ // if (filteredResults.isNotEmpty) {
+ // for (var r in filteredResults) {
+ // print("设备名: ${r.device.name}, RSSI: ${r.rssi}");
+ // }
+ // } else {
+ // print("没有找到符合条件的设备");
+ // }
+ // });
+ // });
+
+ FlutterBluePlus.scanResults.listen((results) {
+ final signalThreshold = blueteethBindController.model.singal!;
+ final filteredResults = results
+ .where((r) =>
+ r.rssi > signalThreshold &&
+ r.advertisementData.localName == "AITH-V2" &&
+ r.advertisementData.manufacturerData.containsKey(0xFFED))
+ .toList();
+
+ // 解析数据
+ final parsedDeviceList = [];
+
+ for (var r in filteredResults) {
+ try {
+ List rawData = r.advertisementData.manufacturerData[0xFFED]!;
+ BleDeviceData deviceData = parseBleData(rawData);
+ deviceData.name = r.advertisementData.advName;
+ deviceData.rssi = r.rssi;
+ deviceData.mac = deviceData.deviceId.replaceAll(':', '');
+ parsedDeviceList.add(deviceData);
+ } catch (e) {
+ print("设备数据解析失败: $e");
+ }
+ }
+
+ setState(() {
+ scanResults = filteredResults;
+
+ // 存入 controller 中
+ blueteethBindController.model.blelist = filteredResults;
+ blueteethBindController.model.devicelist = parsedDeviceList;
+ blueteethBindController.updateDeviceStatus();
+ blueteethBindController.updateAll();
+
+ // print("过滤并解析后设备数量:${parsedDeviceList.length}");
+ // for (var device in parsedDeviceList) {
+ // print(
+ // "设备: ${device.deviceId}, HR: ${device.ht}, BRE: ${device.bre}, Seq: ${device.fullSeq}");
+ // }
+
+ // if (parsedDeviceList.isEmpty) {
+ // print("没有符合条件的 BLE 广播数据");
+ // }
+ });
+ });
+
+ // 等待扫描完成
+ await Future.delayed(Duration(seconds: 10));
+ await FlutterBluePlus.stopScan();
+
+ setState(() {
+ isScanning = false;
+ });
+
+ print("扫描完成");
+ }
+ }
+
+ // 定时每10秒进行一次扫描
+ void _startPeriodicScan() {
+ _timer = Timer.periodic(Duration(seconds: 10), (timer) {
+ if (!isScanning) {
+ _startScanning(); // 调用扫描函数
+ }
+ });
+ }
+
+ // 停止扫描
+ void _stopScanning() {
+ if (isScanning) {
+ FlutterBluePlus.stopScan(); // 停止扫描
+ setState(() {
+ isScanning = false; // 更新扫描状态
+ });
+ }
+ }
+
+ // 停止定时扫描
+ void _stopPeriodicScan() {
+ _timer?.cancel();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ _stopPeriodicScan(); // 停止定时扫描
+ _stopScanning(); // 确保离开页面时停止扫描
+ }
+
+ connectToDevice(device, {int time = 5}) {
+ ble.connectToDevice(
+ {
+ "device": device,
+ 'success': (ble.ConnectedDeviceProp deviceProp) {
+ if (deviceProp.connectedDevicePropType ==
+ ble.ConnectedDevicePropType.JunHe) {
+ currentConnectedDeviceProp = deviceProp;
+ deviceProp.write3OfString("blog enable");
+ deviceProp.write3OfString("blog rlmax=128");
+ Timer(const Duration(microseconds: 100), () async {
+ String log = "";
+ Function logAdd = (l) {
+ log += l;
+ };
+ deviceProp.receiveLogArr.add(logAdd);
+ deviceProp.encodeType = 1;
+ deviceProp.deviceType = 1;
+ Timer.periodic(const Duration(milliseconds: 300), (timer) async {
+ if (timer.tick > 20) {
+ ble.disconnect(currentConnectedDeviceProp);
+ failSelectDialog();
+ timer.cancel();
+ }
+ if (log.contains("GB2312") || log.contains("UTF-8")) {
+ timer.cancel();
+ if (log.contains('CHARSET:UTF-8')) {
+ deviceProp.encodeType = 2;
+ }
+ if (log.contains('TARGET:ESPXX')) {
+ deviceProp.deviceType = 2;
+ }
+ log = "";
+ bool isSuccess = false;
+ for (var i = 0; i < 4; i++) {
+ deviceProp.write3OfString("at+system info");
+ await Future.delayed(const Duration(milliseconds: 400));
+ RegExp regExp = RegExp(r"Target Mac:(\S*)");
+ RegExpMatch? regExpMatch = regExp.firstMatch(log);
+ if (regExpMatch != null && regExpMatch.group(1) != null) {
+ String? mac = regExpMatch.group(1);
+ if (mac?.length == 12 && mac != "000000000000") {
+ bindArr[2] = "$mac".toUpperCase();
+ }
+ isSuccess = true;
+ break;
+ }
+ }
+ deviceProp.receiveLogArr.remove(logAdd);
+ print("$bindArr");
+ RegExp regExp = RegExp(
+ r"WIFI CONNECTED INFO:SSID=([^\t\n]*)\s*,RSSI=(\S*)\s*,");
+ RegExpMatch? regExpMatch = regExp.firstMatch(log);
+ if (regExpMatch != null && log.contains("Status=connect")) {
+ blueteethBindController.model.connectedWifiName =
+ regExpMatch.group(1) ?? "";
+ if (int.tryParse("${regExpMatch.group(2)}") != null) {
+ blueteethBindController.model.connectedRssi =
+ int.parse("${regExpMatch.group(2)}");
+ }
+ blueteethBindController.updateAll();
+ }
+ ble.bleParse();
+ if (bindArr[0] != null &&
+ bindArr[0] != "" &&
+ bindArr[1] != "") {
+ setState(() {
+ currentMsg = "绑定中...";
+ });
+ blueteethBindController.bindDevice({
+ "tid": widget.tid,
+ "name": blueteethBindController.model.deviceName,
+ "mac": bindArr[0],
+ "macA": bindArr[1],
+ "macB": bindArr[2]
+ }).then((d) {
+ blueteethBindController.model.bindArr = bindArr;
+ globalController.getDeviceList();
+ LoadingDialog.hide();
+ showCustomConfirmDialog(context, "设备添加成功!",
+ btnName: "打开WIFI配置",
+ icon: ConfirmDialogIcon.success)
+ .then((d) {
+ if (d == "confirm") {
+ Get.offAndToNamed("/wifi", arguments: deviceProp);
+ }
+ });
+ }).catchError((d) {
+ print("$d");
+ currentMsg = "绑定失败: ${d.message}";
+ ble.disconnect(currentConnectedDeviceProp);
+ failSelectDialog(title: "${d.message}");
+ });
+ } else {
+ LoadingDialog.hide();
+ Get.offAndToNamed("/wifi", arguments: deviceProp);
+ }
+ } else {
+ deviceProp.read6();
+ }
+ });
+ });
+ } else if (deviceProp.connectedDevicePropType ==
+ ble.ConnectedDevicePropType.QuanShi) {
+ List receive = [];
+ Function fun = (d) {
+ receive.add(d);
+ };
+ deviceProp.receiveLogArr.add(fun);
+ List head = [
+ 255,
+ 255,
+ 255,
+ 255,
+ 1,
+ 0,
+ 12,
+ 17,
+ ];
+ Timer.periodic(const Duration(seconds: 1), (timer) {
+ if (timer.tick > 20) {
+ timer.cancel();
+ currentMsg = "错误:未能获取到MAC";
+ failSelectDialog();
+ }
+ deviceProp.write(
+ Uint8List.fromList([
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0xFF,
+ 0x01,
+ 0x00,
+ 0x0C,
+ 0x0B,
+ 0x0F,
+ 0x23,
+ 0x04
+ ]),
+ null,
+ null);
+ if (receive.length > 0) {
+ receive.forEach((data) {
+ if (data.length != 17) {
+ return;
+ }
+ bool r = true;
+ for (var i = 0; i < head.length; i++) {
+ if (head[i] != data[i]) {
+ r = false;
+ }
+ }
+ if (r == false) {
+ return;
+ }
+ bindArr[1] = ble.ab2str(data.sublist(9, 15)).toUpperCase();
+ timer.cancel();
+ deviceProp.receiveLogArr.remove(fun);
+ blueteethBindController.model.deviceName =
+ deviceProp.connectDevice?.advName;
+ ble.disconnect(deviceProp);
+ toFindJunhe();
+ });
+ }
+ });
+ } else {
+ List receive = [];
+ Function fun = (d) {
+ receive.add(d);
+ };
+ deviceProp.receiveLogArr.add(fun);
+ List head = [255, 255, 255, 255, 0x00, 0x08, 0x40, 0x01];
+ Timer.periodic(const Duration(seconds: 1), (timer) {
+ if (timer.tick > 20) {
+ timer.cancel();
+ currentMsg = "错误:未能获取到MAC";
+ failSelectDialog();
+ }
+ deviceProp.write(
+ Uint8List.fromList([
+ 255,
+ 255,
+ 255,
+ 255,
+ 0x00,
+ 0x03,
+ 0x40,
+ 0x01,
+ 0x01,
+ 0x00,
+ 0x45,
+ 0xfd
+ ]),
+ null,
+ null);
+ if (receive.length > 0) {
+ receive.forEach((data) {
+ if (data.length != 17) {
+ return;
+ }
+ bool r = true;
+ for (var i = 0; i < head.length; i++) {
+ if (head[i] != data[i]) {
+ r = false;
+ }
+ }
+ if (r == false) {
+ return;
+ }
+
+ bindArr[1] = ble.ab2str(data.sublist(8, 14)).toUpperCase();
+ print("$bindArr");
+ timer.cancel();
+ deviceProp.receiveLogArr.remove(fun);
+ blueteethBindController.model.deviceName =
+ deviceProp.connectDevice?.advName;
+ ble.disconnect(deviceProp);
+ toFindJunhe();
+ });
+ }
+ });
+ }
+ },
+ 'fail': (e) {
+ print(e);
+ if (time > 0) {
+ connectToDevice(device, time: time - 1);
+ } else {
+ currentMsg = "蓝牙无法连接上设备";
+ failSelectDialog(title: currentMsg);
+ }
+ }
+ },
+ );
+ }
+
+ isBind() {
+ return !(blueteethBindController.model.bindArr[1]?.length == 12);
+ }
+
+ failSelectDialog({String title = ""}) {
+ LoadingDialog.hide();
+ setState(() {});
+ showCustomConfirmAndCancelDialog(
+ context, title == "" ? (isBind() ? "绑定失败" : "连接失败") : title,
+ confirmName: "重试", cancelName: "返回")
+ .then((d) {
+ if (d == "confirm") {
+ if (connectDeviceCurrent != null) {
+ ble.bleParse();
+ ble.start((List d) {
+ setState(() {
+ bleDevice = d;
+ });
+ }, bleOnCall: () {
+ LoadingDialog.show("连接中...\n靠近设备2米内",
+ icon:
+ isBind() ? LoadingDialogIcon.ble : LoadingDialogIcon.wifi);
+ setState(() {
+ currentMsg = "连接设备中...";
+ });
+ connectToDevice(connectDeviceCurrent);
+ });
+ } else {
+ bleExec();
+ }
+ } else if (d == "cancel") {
+ Get.back();
+ }
+ });
+ }
+
+ bleExec() {
+ ble.bleParse();
+ connectTimer?.cancel();
+ int index = 0;
+ bool isCloseLoadingDialog = false;
+ isFind = false;
+ blueteethBindController.model.bindArr = bindArrBackup;
+ bindArr = ["", "", ""];
+ ble.start((List d) {
+ setState(() {
+ bleDevice = d;
+ });
+ if (isBind()) {
+ if (isCloseLoadingDialog == false &&
+ bleDevice.indexWhere((item) {
+ if (widget.tid == 1) {
+ return ble.isQuanShiDevice(item["name"]);
+ } else {
+ return ble.isMHTSWES(item["name"]);
+ }
+ }) !=
+ -1) {
+ isCloseLoadingDialog = true;
+ LoadingDialog.hide();
+ }
+ }
+ }, bleOnCall: () {
+ if (isBind()) {
+ LoadingDialog.show("搜索蓝牙设备中...\n请打开蓝牙开关、定位开关\n与设备距离在2米内",
+ icon: isBind() ? LoadingDialogIcon.ble : LoadingDialogIcon.wifi);
+ Timer.periodic(const Duration(seconds: 1), (t) {
+ if (t.tick > 15) {
+ t.cancel();
+ isCloseLoadingDialog = true;
+ LoadingDialog.hide();
+ showCustomConfirmAndCancelDialog(context, "未发现设备",
+ confirmName: "重试", cancelName: "返回")
+ .then((d) {
+ if (d == "confirm") {
+ bleExec();
+ } else if (d == "cancel") {
+ Get.back();
+ }
+ });
+ } else {
+ if (isCloseLoadingDialog == true) {
+ t.cancel();
+ }
+ }
+ });
+ return;
+ }
+ LoadingDialog.show(
+ "${isBind() ? "绑定中...\n与设备距离在2米内" : "连接中...\n请打开蓝牙开关、定位开关\n与设备距离在2米内"}",
+ icon: isBind() ? LoadingDialogIcon.ble : LoadingDialogIcon.wifi);
+ connectTimer = Timer.periodic(const Duration(seconds: 1), (t) {
+ index++;
+ if (index > 15) {
+ connectTimer = null;
+ t.cancel();
+ failSelectDialog();
+ }
+ var d = bleDevice;
+ if (d != null && d.length > 0) {
+ if (isBind()) {
+ var deviceble = d.firstWhere((item) {
+ bool isFF = false;
+ if (widget.tid == 1) {
+ isFF = ble.isQuanShiDevice(item["name"]);
+ } else {
+ isFF = ble.isMHTSWES(item["name"]);
+ }
+ if (isFF) {
+ isFF = globalController.model.deviceList.indexWhere(
+ (d) => d["mac"] == item["adData"]["deviceId"]) ==
+ -1
+ ? true
+ : false;
+ }
+ return isFF;
+ }, orElse: () => null);
+ if (!isFind && deviceble != null) {
+ print("quanshidevice");
+ isFind = true;
+ setState(() {
+ currentMsg = "连接设备中...";
+ });
+ t.cancel();
+ connectToDevice(deviceble["device"]);
+ bindArr[0] = deviceble["adData"]["deviceId"];
+ }
+ } else {
+ var deviceble = d.firstWhere(
+ (item) =>
+ item["adData"]["deviceId"] ==
+ blueteethBindController.model.bindArr[1],
+ orElse: () => null);
+ if (!isFind && deviceble != null) {
+ print("junhedevice");
+ isFind = true;
+ t.cancel();
+ setState(() {
+ currentMsg = "连接设备中...";
+ });
+ connectToDevice(deviceble["device"]);
+ bindArr[1] = deviceble["adData"]["deviceId"];
+ }
+ }
+ }
+ });
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return LayoutBuilder(
+ builder: (context, boxConstraints) => GestureDetector(
+ onTap: () => FocusScope.of(context).unfocus(),
+ child: Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: AssetImage('assets/img/bgNoImg.png'), // 本地图片
+ fit: BoxFit.fill, // 填满整个 Container
+ ),
+ ),
+ child: Scaffold(
+ backgroundColor: Colors.transparent, // 加上这一行
+ appBar: AppBar(
+ iconTheme: IconThemeData(color: Colors.white),
+ backgroundColor: stringToColor("#242835"),
+ automaticallyImplyLeading: false,
+ titleSpacing: 0,
+ title: Container(
+ width: double.infinity,
+ height: 180.rpx,
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ Text(
+ '蓝牙绑定.标题'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx,
+ ),
+ ),
+ Positioned(
+ left: 0,
+ child: returnIconButtom,
+ ),
+ ],
+ ),
+ ),
+ actions: [],
+ centerTitle: false,
+ ),
+ body: SafeArea(
+ top: true,
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 30.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Color(0xFF242835),
+ borderRadius: BorderRadius.circular(20.rpx),
+ ),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 30.rpx, 0, 30.rpx),
+ child: Text(
+ '蓝牙绑定.扫描蓝牙设备中…'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Color(0xFFE8EEF3),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Color(0xFF242835),
+ borderRadius: BorderRadius.circular(20.rpx),
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 21.rpx, 5.rpx, 21.rpx, 5.rpx),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '最小信号强度',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEEF2F5),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Expanded(
+ child: Obx(() {
+ return Slider(
+ activeColor: Color(0xFF1FCC9B),
+ inactiveColor:
+ FlutterFlowTheme.of(context).alternate,
+ min: -100,
+ max: 50,
+ value: blueteethBindController.model.singal!,
+ onChanged: (newValue) {
+ newValue = double.parse(
+ newValue.toStringAsFixed(0));
+ blueteethBindController.model.singal =
+ newValue;
+ blueteethBindController.updateAll();
+ },
+ );
+ }),
+ ),
+ Obx(() {
+ return Text(
+ '${blueteethBindController.model.singal!.toInt()}',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Color(0xFFE4E8EB),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ );
+ }),
+ ].divide(SizedBox(width: 30.rpx)),
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(20.rpx),
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 35.rpx, 0, 35.rpx, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 0.rpx, 0, 0),
+ child: Container(
+ width: 25.rpx,
+ height: 25.rpx,
+ // width: double.infinity,
+ decoration: BoxDecoration(),
+ child: SvgPicture.asset(
+ 'assets/img/icon/query.svg',
+ fit: BoxFit.cover,
+ color: Colors.black,
+ ),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ width: 100.rpx,
+ height: 100.rpx,
+ decoration: BoxDecoration(
+ color: FlutterFlowTheme.of(context)
+ .secondaryBackground,
+ ),
+ child: Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: TextFormField(
+ autofocus: false,
+ obscureText: false,
+ decoration: InputDecoration(
+ isDense: true,
+ labelStyle:
+ FlutterFlowTheme.of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ hintText: '蓝牙绑定.搜索提示'.tr,
+ hintStyle:
+ FlutterFlowTheme.of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ 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),
+ ),
+ errorBorder: OutlineInputBorder(
+ borderSide: BorderSide(
+ color:
+ FlutterFlowTheme.of(context)
+ .error,
+ width: 1.rpx,
+ ),
+ borderRadius:
+ BorderRadius.circular(8.rpx),
+ ),
+ focusedErrorBorder:
+ OutlineInputBorder(
+ borderSide: BorderSide(
+ color:
+ FlutterFlowTheme.of(context)
+ .error,
+ width: 1.rpx,
+ ),
+ borderRadius:
+ BorderRadius.circular(8.rpx),
+ ),
+ filled: true,
+ fillColor:
+ FlutterFlowTheme.of(context)
+ .secondaryBackground,
+ ),
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ cursorColor:
+ FlutterFlowTheme.of(context)
+ .primaryText,
+ // validator: _model
+ // .textControllerValidator
+ // .asValidator(context),
+ ),
+ ),
+ ),
+ ),
+ ].divide(SizedBox(width: 6.rpx)),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 26.rpx, 0, 0, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ SizedBox(
+ height: 50.rpx,
+ child: VerticalDivider(
+ thickness: 2.rpx,
+ color: FlutterFlowTheme.of(context)
+ .alternate,
+ ),
+ ),
+ Text(
+ '搜索',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(width: 26.rpx)),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 60.rpx, 0, 32.rpx),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(19.rpx, 0, 0, 0),
+ child: Text(
+ '匹配出的外围设备(${blueteethBindController.model.devicelist!.length})',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: Colors.white),
+ ),
+ ),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ width: double.infinity,
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ ...blueteethBindController.model.blelist!
+ .map((device) =>
+ SingleBlueteethDeviceCompoentWidget(
+ // device: device,
+ bleDevice: device,
+ ))
+ .toList()
+ .divide(SizedBox(height: 30.rpx))
+ .addToEnd(SizedBox(height: 30.rpx)),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ].divide(SizedBox(height: 30.rpx)),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ _showBluetoothNotEnabledDialog() async {
+ await showDialog(
+ context: context,
+ builder: (_) => AlertDialog(
+ title: Text("蓝牙未开启"),
+ content: Text("请先打开蓝牙再进行设备扫描"),
+ actions: [
+ TextButton(
+ onPressed: () => Navigator.of(context).pop(),
+ child: Text("知道了"),
+ ),
+ ],
+ ),
+ );
+ }
+
+ toFindJunhe() {
+ bool isSuccess = false;
+ int i = 0;
+ Timer.periodic(const Duration(seconds: 1), (t) async {
+ i++;
+ if (isSuccess) {
+ return;
+ }
+ if (i > 8) {
+ if (!isSuccess) {
+ currentMsg = "错误:未找到关联设备";
+ failSelectDialog(title: "绑定失败:未找到关联设备");
+ }
+ t.cancel();
+ return;
+ }
+ bleDevice.forEach((item) {
+ if (isSuccess) {
+ return;
+ }
+ if (item['adData']['deviceId'] == bindArr[1]) {
+ isSuccess = true;
+ t.cancel();
+ setState(() {
+ currentMsg = "寻找关联设备中...";
+ });
+ connectToDevice(item["device"]);
+ }
+ });
+ });
+ }
+}
+
+BleDeviceData parseBleData(List data) {
+ if (data.length < 18) {
+ throw Exception('BLE广播数据长度不足18字节');
+ }
+
+ int type = data[0];
+ int sn = data[1];
+
+ // 设备唯一ID (6字节),格式化为 MAC 地址样式
+ String deviceId =
+ List.generate(6, (i) => data[2 + i].toRadixString(16).padLeft(2, '0'))
+ .join(":")
+ .toUpperCase();
+
+ int bre = data[8];
+ int ht = data[9];
+ int active = data[10];
+ int flag = data[11];
+
+ // version 是4字节 uint,大端字节序
+ int version =
+ (data[12] << 24) | (data[13] << 16) | (data[14] << 8) | data[15];
+
+ // qsn 是2字节 ushort,大端字节序
+ int qsn = (data[16] << 8) | data[17];
+
+ return BleDeviceData(
+ type: type,
+ sn: sn,
+ deviceId: deviceId,
+ bre: bre,
+ ht: ht,
+ active: active,
+ flag: flag,
+ version: version,
+ qsn: qsn,
+ );
+}
diff --git a/lib/pages/device_bind/componnet/DoubleBlueteethDeviceCompoentWidget.dart b/lib/pages/device_bind/componnet/DoubleBlueteethDeviceCompoentWidget.dart
new file mode 100644
index 0000000..4664d0c
--- /dev/null
+++ b/lib/pages/device_bind/componnet/DoubleBlueteethDeviceCompoentWidget.dart
@@ -0,0 +1,294 @@
+import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart';
+import 'package:flutter/material.dart';
+import 'package:flutterflow_ui/flutterflow_ui.dart';
+import 'package:vbvs_app/common/util/FitTool.dart';
+
+class DoubleBlueteethDeviceCompoentWidget extends StatefulWidget {
+ const DoubleBlueteethDeviceCompoentWidget({super.key});
+
+ @override
+ State createState() =>
+ _DoubleBlueteethDeviceCompoentWidgetState();
+}
+
+class _DoubleBlueteethDeviceCompoentWidgetState
+ extends State {
+ @override
+ void setState(VoidCallback callback) {
+ super.setState(callback);
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Color(0xFF242835),
+ borderRadius: BorderRadius.circular(20.rpx),
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 36.rpx, 0, 52.rpx),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ 'AITH-V3',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '信号强度:-36dBm',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Text(
+ 'SN:12',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF5F9FD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(width: 40.rpx)),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ '蓝牙地址:48:CA:43:B1:B3:B2',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ 'mac:48CA43B1B3B0',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '网络:在线',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '传感器:',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Text(
+ '可绑定',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFF1AD2B5),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ],
+ ),
+ ].divide(SizedBox(width: 145.rpx)),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ '版本:02409.0301',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Divider(
+ thickness: 2.rpx,
+ color: FlutterFlowTheme.of(context).alternate,
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ 'AITH-V3',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '信号强度:-36dBm',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Text(
+ 'SN:12',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF5F9FD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(width: 40.rpx)),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ '蓝牙地址:48:CA:43:B1:B3:B2',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ 'mac:48CA43B1B3B0',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '网络:在线',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '传感器:',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Text(
+ '可绑定',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFF1AD2B5),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ],
+ ),
+ ].divide(SizedBox(width: 145.rpx)),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Text(
+ '版本:02409.0301',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ ].divide(SizedBox(height: 37.rpx)),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/device_bind/componnet/FancyCircleCheckbox.dart b/lib/pages/device_bind/componnet/FancyCircleCheckbox.dart
new file mode 100644
index 0000000..fec9480
--- /dev/null
+++ b/lib/pages/device_bind/componnet/FancyCircleCheckbox.dart
@@ -0,0 +1,86 @@
+import 'package:flutter/material.dart';
+
+class FancyCircleCheckbox extends StatefulWidget {
+ final bool value;
+ final ValueChanged onChanged;
+ final Color borderColor;
+ final Color fillColor;
+
+ const FancyCircleCheckbox({
+ Key? key,
+ required this.value,
+ required this.onChanged,
+ this.borderColor = Colors.white,
+ this.fillColor = Colors.blue,
+ }) : super(key: key);
+
+ @override
+ State createState() => _FancyCircleCheckboxState();
+}
+
+class _FancyCircleCheckboxState extends State
+ with SingleTickerProviderStateMixin {
+ late AnimationController _controller;
+ late Animation _scaleAnimation;
+
+ @override
+ void initState() {
+ super.initState();
+ _controller = AnimationController(
+ duration: Duration(milliseconds: 200),
+ vsync: this,
+ );
+ _scaleAnimation = CurvedAnimation(
+ parent: _controller,
+ curve: Curves.easeInOut,
+ );
+
+ if (widget.value) {
+ _controller.forward();
+ }
+ }
+
+ @override
+ void didUpdateWidget(covariant FancyCircleCheckbox oldWidget) {
+ super.didUpdateWidget(oldWidget);
+ if (widget.value != oldWidget.value) {
+ widget.value ? _controller.forward() : _controller.reverse();
+ }
+ }
+
+ @override
+ void dispose() {
+ _controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: () => widget.onChanged(!widget.value),
+ child: Container(
+ width: 24,
+ height: 24,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ border: Border.all(
+ color: widget.value
+ ? widget.borderColor
+ : widget.borderColor.withOpacity(0.5),
+ width: 1,
+ ),
+ ),
+ child: ScaleTransition(
+ scale: _scaleAnimation,
+ child: Container(
+ margin: EdgeInsets.all(5),
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: widget.fillColor,
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/device_bind/componnet/SingleBlueteethDeviceCompoentWidget.dart b/lib/pages/device_bind/componnet/SingleBlueteethDeviceCompoentWidget.dart
new file mode 100644
index 0000000..84dab75
--- /dev/null
+++ b/lib/pages/device_bind/componnet/SingleBlueteethDeviceCompoentWidget.dart
@@ -0,0 +1,184 @@
+import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart';
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_blue_plus/flutter_blue_plus.dart';
+import 'package:flutterflow_ui/flutterflow_ui.dart';
+import 'package:vbvs_app/common/util/FitTool.dart';
+import 'package:vbvs_app/component/tool/ClickableContainer.dart';
+import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
+import 'package:vbvs_app/model/BleDeviceData.dart';
+import 'package:vbvs_app/pages/device_bind/blueteeth_device_page.dart';
+import 'package:vbvs_app/pages/device_bind/componnet/bind_dialog.dart';
+
+class SingleBlueteethDeviceCompoentWidget extends StatefulWidget {
+ // final BleDeviceData device;
+ final bleDevice;
+
+ const SingleBlueteethDeviceCompoentWidget({
+ super.key,
+ // required this.device,
+ required this.bleDevice,
+ });
+
+ @override
+ State createState() =>
+ _SingleBlueteethDeviceCompoentWidgetState();
+}
+
+class _SingleBlueteethDeviceCompoentWidgetState
+ extends State {
+ @override
+ Widget build(BuildContext context) {
+ var bleDevice = widget.bleDevice;
+ List rawData =
+ widget.bleDevice.advertisementData.manufacturerData[0xFFED]!;
+ BleDeviceData deviceData = parseBleData(rawData);
+ deviceData.name = widget.bleDevice.advertisementData.advName;
+ deviceData.rssi = widget.bleDevice.rssi;
+ deviceData.mac = deviceData.deviceId.replaceAll(':', '');
+ BleDeviceData device = deviceData;
+
+ ThemeController themeController = Get.find();
+ return ClickableContainer(
+ backgroundColor: themeController.currentColor.sc5,
+ highlightColor: Colors.white,
+ borderRadius: 20.rpx,
+ padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 36.rpx, 0, 52.rpx),
+ onTap: () async {
+ //todo 请求绑定
+ print(device.mac);
+ // try {
+ // await bleDevice.device.connect(autoConnect: false);
+ // List services =
+ // await bleDevice.device.discoverServices();
+ // BluetoothCharacteristic? wifiListChar;
+ // BluetoothCharacteristic? wifiSsidChar;
+ // BluetoothCharacteristic? wifiPasswordChar;
+ // BluetoothCharacteristic? startProvisionChar;
+
+ // for (BluetoothService service in services) {
+ // for (BluetoothCharacteristic c in service.characteristics) {
+ // if (c.uuid.toString() == 'YOUR_WIFI_LIST_UUID') {
+ // wifiListChar = c;
+ // } else if (c.uuid.toString() == 'YOUR_WIFI_SSID_UUID') {
+ // wifiSsidChar = c;
+ // } else if (c.uuid.toString() == 'YOUR_WIFI_PWD_UUID') {
+ // wifiPasswordChar = c;
+ // } else if (c.uuid.toString() == 'YOUR_WIFI_START_UUID') {
+ // startProvisionChar = c;
+ // }
+ // }
+ // }
+ // } catch (e) {
+ // print("蓝牙连接失败");
+ // }
+ //
+ // Get.toNamed('/wifiPage', arguments: bleDevice.device);
+ showBindDoubleDialog(context,[]);
+ // showHaveBindDialog(context);
+ },
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ device.name ?? '蓝牙绑定.默认设备名称'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFF6FAFD),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Row(
+ children: [
+ Text(
+ "蓝牙绑定.信号强度".tr + ':${device.rssi ?? '-'}dBm',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ SizedBox(width: 40.rpx),
+ Text(
+ "蓝牙绑定.SN".tr + ':${device.sn ?? '-'}',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFF5F9FD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ],
+ ),
+ Text(
+ "蓝牙绑定.蓝牙地址".tr + ':${device.deviceId ?? '-'}',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Text(
+ "蓝牙绑定.mac".tr + ':${device.mac ?? '-'}',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Row(
+ children: [
+ Text(
+ "蓝牙绑定.网络".tr +
+ ':${device.isOnline == true ? '蓝牙绑定.在线'.tr : '蓝牙绑定.离线'.tr}',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ SizedBox(width: 145.rpx),
+ Row(
+ children: [
+ Text(
+ "蓝牙绑定.传感器".tr + ":",
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFEBF2F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ Text(
+ device.status == 1 ? '蓝牙绑定.可绑定'.tr : '蓝牙绑定.已被绑定'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFF1AD2B5),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ Text(
+ '版本:${device.version ?? '-'}',
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFF6FAFD),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(height: 37.rpx)),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/device_bind/componnet/bind_dialog.dart b/lib/pages/device_bind/componnet/bind_dialog.dart
new file mode 100644
index 0000000..3db176f
--- /dev/null
+++ b/lib/pages/device_bind/componnet/bind_dialog.dart
@@ -0,0 +1,324 @@
+import 'dart:ui';
+
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutterflow_ui/flutterflow_ui.dart';
+import 'package:vbvs_app/common/color/appConstants.dart';
+import 'package:vbvs_app/common/util/FitTool.dart';
+import 'package:vbvs_app/component/tool/CustomCard.dart';
+import 'package:vbvs_app/component/tool/FrostedDialog.dart';
+import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
+import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
+import 'package:vbvs_app/model/BleDeviceData.dart';
+import 'package:vbvs_app/pages/device_bind/componnet/FancyCircleCheckbox.dart';
+
+void showBindDoubleDialog(BuildContext context, List devices) {
+ ThemeController themeController = Get.find();
+ BlueteethBindController blueteethBindController = Get.find();
+
+ blueteethBindController.model.deviceIndex0 = true;
+ blueteethBindController.model.deviceIndex1 = false;
+ blueteethBindController.model.deviceIndex2 = false;
+
+ showDialog(
+ context: context,
+ barrierDismissible: true,
+ barrierColor: Colors.black.withOpacity(0.5), // 建议加个背景模糊色
+ builder: (BuildContext context) {
+ return FrostedDialog(
+ blurSigma: 3.0,
+ child: Container(
+ decoration: BoxDecoration(
+ color: themeController.currentColor.sc17,
+ borderRadius: BorderRadius.circular(20.0),
+ ),
+ padding: EdgeInsetsDirectional.fromSTEB(60.rpx, 0, 60.rpx, 0),
+ child: Container(
+ width: double.infinity,
+ constraints: BoxConstraints(
+ maxHeight: MediaQuery.sizeOf(context).height * 0.656,
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ // 标题
+ Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0.rpx, 93.rpx, 0, 0),
+ child: Text(
+ '蓝牙绑定.双人版绑定标题'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ),
+ ),
+ // 全选
+ _buildCheckboxRow(
+ context,
+ title: '蓝牙绑定.绑定全部'.tr,
+ value: () => blueteethBindController.model.deviceIndex0!,
+ onChanged: (v) {
+ if (!blueteethBindController.model.deviceIndex0!) {
+ blueteethBindController.model.deviceIndex0 = v;
+ blueteethBindController.model.deviceIndex1 = !v;
+ blueteethBindController.model.deviceIndex2 = !v;
+ blueteethBindController.updateAll();
+ }
+ },
+ ),
+ // 主设备
+ _buildCheckboxRow(
+ context,
+ title: '蓝牙绑定.主设备'.tr,
+ value: () => blueteethBindController.model.deviceIndex1!,
+ onChanged: (v) {
+ if (!blueteethBindController.model.deviceIndex1!) {
+ blueteethBindController.model.deviceIndex1 = v;
+ blueteethBindController.model.deviceIndex0 = !v;
+ blueteethBindController.model.deviceIndex2 = !v;
+ blueteethBindController.updateAll();
+ }
+ },
+ ),
+ // 从设备
+ _buildCheckboxRow(
+ context,
+ title: '蓝牙绑定.从设备'.tr,
+ value: () => blueteethBindController.model.deviceIndex2!,
+ onChanged: (v) {
+ if (!blueteethBindController.model.deviceIndex2!) {
+ blueteethBindController.model.deviceIndex2 = v;
+ blueteethBindController.model.deviceIndex0 = !v;
+ blueteethBindController.model.deviceIndex1 = !v;
+ blueteethBindController.updateAll();
+ }
+ },
+ ),
+ // 确定按钮
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 100.rpx, 0, 0),
+ child: _buildActionButton(
+ context,
+ text: '蓝牙绑定.确定'.tr,
+ onTap: () {
+ Get.back();
+ },
+ ),
+ ),
+ // 取消按钮
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 19.rpx, 0, 60.rpx),
+ child: _buildActionButton(
+ context,
+ text: '蓝牙绑定.取消'.tr,
+ onTap: () {
+ Get.back();
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ );
+}
+
+
+
+void showHaveBindDialog(BuildContext context) {
+ ThemeController themeController = Get.find();
+
+ showDialog(
+ context: context,
+ barrierDismissible: true,
+ barrierColor: Colors.black.withOpacity(0.5),
+ builder: (BuildContext context) {
+ return FrostedDialog(
+ blurSigma: 3.0,
+ child: Container(
+ decoration: BoxDecoration(
+ color: themeController.currentColor.sc17,
+ borderRadius: BorderRadius.circular(20.0),
+ ),
+ padding: EdgeInsetsDirectional.fromSTEB(60.rpx, 0, 60.rpx, 0),
+ child: Container(
+ width: double.infinity,
+ constraints: BoxConstraints(
+ maxHeight: MediaQuery.sizeOf(context).height * 0.656,
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0.rpx, 93.rpx, 0.rpx, 0.rpx),
+ child: Text(
+ '蓝牙绑定.无法绑定'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0.rpx, 70.rpx, 0.rpx, 56.rpx),
+ child: RichText(
+ text: TextSpan(children: [
+ TextSpan(
+ text: "蓝牙绑定.无法绑定1".tr,
+ style: TextStyle(
+ color: themeController.currentColor.sc3,
+ fontSize: AppConstants().normal_text_fontSize,
+ ),
+ ),
+ TextSpan(
+ text: "蓝牙绑定.无法绑定2".tr,
+ style: TextStyle(
+ color: themeController.currentColor.sc10,
+ fontSize: AppConstants().normal_text_fontSize,
+ ),
+ ),
+ TextSpan(
+ text: "蓝牙绑定.无法绑定3".tr,
+ style: TextStyle(
+ color: themeController.currentColor.sc3,
+ fontSize: AppConstants().normal_text_fontSize,
+ ),
+ ),
+ ]),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(0, 19.rpx, 0, 60.rpx),
+ child: CustomCard(
+ borderRadius: AppConstants().button_container_radius,
+ onTap: () {
+ Get.back();
+ },
+ colors: [
+ themeController.currentColor.sc1,
+ themeController.currentColor.sc2,
+ ],
+ child: Container(
+ width: MediaQuery.sizeOf(context).width,
+ 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: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ color: Colors.white,
+ fontFamily: 'Inter',
+ fontSize:
+ AppConstants().normal_text_fontSize,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(
+ width: 17.rpx,
+ )),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ );
+}
+
+
+Widget _buildCheckboxRow(
+ BuildContext context, {
+ required String title,
+ required bool Function() value,
+ required void Function(bool) onChanged,
+}) {
+ ThemeController themeController = Get.find();
+ return Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(60.rpx, 64.rpx, 0.rpx, 0.rpx),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Obx(() => FancyCircleCheckbox(
+ borderColor: themeController.currentColor.sc3,
+ fillColor: themeController.currentColor.sc2,
+ value: value(),
+ onChanged: onChanged,
+ )),
+ Text(
+ title,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: AppConstants().normal_text_fontSize,
+ color: themeController.currentColor.sc3,
+ ),
+ ),
+ ].divide(SizedBox(width: 21.rpx)),
+ ),
+ );
+}
+
+Widget _buildActionButton(
+ BuildContext context, {
+ required String text,
+ required VoidCallback onTap,
+}) {
+ ThemeController themeController = Get.find();
+ return CustomCard(
+ borderRadius: AppConstants().button_container_radius,
+ onTap: onTap,
+ colors: [
+ themeController.currentColor.sc1,
+ themeController.currentColor.sc2,
+ ],
+ child: Container(
+ width: MediaQuery.sizeOf(context).width,
+ 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(
+ text,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ color: Colors.white,
+ fontFamily: 'Inter',
+ fontSize: AppConstants().normal_text_fontSize,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(width: 17.rpx)),
+ ),
+ ),
+ );
+}
diff --git a/lib/pages/device_bind/device_type.dart b/lib/pages/device_bind/device_type.dart
index 48a52e1..b13fd5f 100644
--- a/lib/pages/device_bind/device_type.dart
+++ b/lib/pages/device_bind/device_type.dart
@@ -1,12 +1,15 @@
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/appConstants.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/component/tool/CustomCard.dart';
+import 'package:vbvs_app/component/tool/FrostedDialog.dart';
import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
+import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
import 'package:vbvs_app/controller/user_info_controller.dart';
class DeviceTypePage extends StatefulWidget {
@@ -20,6 +23,7 @@ class _EPageState extends State {
GlobalController globalController = Get.find();
UserInfoController userInfoController = Get.find();
BlueteethBindController blueteethBindController = Get.find();
+ ThemeController themeController = Get.find();
@override
void initState() {
@@ -31,79 +35,84 @@ class _EPageState extends State {
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
- return Dialog(
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(20.0),
- ),
- backgroundColor: Colors.transparent,
+ return FrostedDialog(
child: Padding(
- padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
- child: Container(
- width: double.infinity,
- constraints: BoxConstraints(
- maxHeight: MediaQuery.sizeOf(context).height * 0.656,
- ),
- child: Column(
- mainAxisSize: MainAxisSize.max,
- children: [
- Expanded(
- child: Container(
- width: double.infinity,
- child: SingleChildScrollView(
- child: Column(
- mainAxisSize: MainAxisSize.max,
- children: [
- Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
+ child: Container(
+ width: double.infinity,
+ constraints: BoxConstraints(
+ maxHeight: MediaQuery.sizeOf(context).height * 0.656,
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Expanded(
+ child: Container(
+ width: double.infinity,
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 26.rpx, 0, 0),
+ child: Container(
+ width: MediaQuery.sizeOf(context).width,
+ decoration: BoxDecoration(
+ color: Color(0xFFFBF5D5),
+ borderRadius: BorderRadius.circular(
+ AppConstants()
+ .normal_container_radius), // 圆角半径
+ ),
+ child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
- 0, 26.rpx, 0, 0),
- child: Container(
- width: MediaQuery.sizeOf(context).width,
- decoration: BoxDecoration(
- color: Color(0xFFFBF5D5),
- borderRadius: BorderRadius.circular(
- AppConstants()
- .normal_container_radius), // 圆角半径
- ),
- child: Padding(
- padding: EdgeInsetsDirectional.fromSTEB(
- 25.rpx, 25.rpx, 25.rpx, 25.rpx),
- child: Row(
- mainAxisSize: MainAxisSize.max,
- crossAxisAlignment:
- CrossAxisAlignment.start,
- children: [
- Icon(
- Icons.volume_mute,
- color:
- FlutterFlowTheme.of(context)
- .primaryText,
- size: 30.rpx,
+ 25.rpx, 25.rpx, 25.rpx, 25.rpx),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(
+ 0, 8.rpx, 0, 0),
+ child: Container(
+ width: 25.rpx,
+ height: 25.rpx,
+ // width: double.infinity,
+ decoration: BoxDecoration(),
+ child: SvgPicture.asset(
+ 'assets/img/icon/sound.svg',
+ fit: BoxFit.fill,
+ color: themeController
+ .currentColor.sc8,
),
- Expanded(
- child: Column(
- mainAxisSize: MainAxisSize.max,
- crossAxisAlignment:
- CrossAxisAlignment.start,
- children: [
- Text(
- '绑定引导.说明标题'.tr,
- style: FlutterFlowTheme.of(
- context)
- .bodyMedium
- .override(
- fontFamily: 'Inter',
- fontSize: AppConstants()
- .normal_text_fontSize,
- letterSpacing: 0.0,
- fontWeight:
- FontWeight.w500,
- color:
- Colors.orange),
- ),
- Text(
- '绑定引导.说明正文'.tr,
- style: FlutterFlowTheme.of(
- context)
+ ),
+ ),
+ Expanded(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Text(
+ '绑定引导.说明标题'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants()
+ .normal_text_fontSize,
+ letterSpacing: 0.0,
+ fontWeight:
+ FontWeight.w500,
+ color: Colors.orange),
+ ),
+ Text(
+ '绑定引导.说明正文'.tr,
+ style:
+ FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Inter',
@@ -111,162 +120,161 @@ class _EPageState extends State {
.normal_text_fontSize,
letterSpacing: 0.0,
),
- ),
- ].divide(SizedBox(
- height: AppConstants()
- .text_padding_up_dowm_p)),
),
- ),
- ].divide(SizedBox(width: 20.rpx)),
+ ].divide(SizedBox(
+ height: AppConstants()
+ .text_padding_up_dowm_p)),
+ ),
),
- ),
+ ].divide(SizedBox(width: 20.rpx)),
),
),
- Container(
- width: double.infinity,
- height: (MediaQuery.sizeOf(context).width) *
- 0.13,
- constraints: BoxConstraints(
- minHeight: 200.rpx,
- ),
- child: ClipRRect(
- borderRadius:
- BorderRadius.circular(20.rpx),
- // child: Image.network(
- // 'https://picsum.photos/seed/861/600',
- // fit: BoxFit.cover,
- // ),
- child: Image.asset(
- "assets/img/help_op.png",
- fit: BoxFit.cover,
- ),
- ),
- ),
- ].divide(SizedBox(height: 25.rpx)),
+ ),
),
- ),
+ Container(
+ width: double.infinity,
+ height:
+ (MediaQuery.sizeOf(context).width) * 0.13,
+ constraints: BoxConstraints(
+ minHeight: 200.rpx,
+ ),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20.rpx),
+ // child: Image.network(
+ // 'https://picsum.photos/seed/861/600',
+ // fit: BoxFit.cover,
+ // ),
+ child: Image.asset(
+ "assets/img/help_op.png",
+ fit: BoxFit.cover,
+ ),
+ ),
+ ),
+ ].divide(SizedBox(height: 25.rpx)),
),
),
- Flexible(
- child: Padding(
- padding: EdgeInsetsDirectional.fromSTEB(
- 0, 210.rpx, 0, 0),
- child: Container(
- width: double.infinity,
- child: Column(
- mainAxisSize: MainAxisSize.max,
- children: [
- Container(
- width: double.infinity,
- child: Row(
- mainAxisSize: MainAxisSize.max,
- mainAxisAlignment:
- MainAxisAlignment.center,
- children: [
- Theme(
- data: ThemeData(
- checkboxTheme: CheckboxThemeData(
- visualDensity:
- VisualDensity.compact,
- materialTapTargetSize:
- MaterialTapTargetSize
- .shrinkWrap,
- shape: RoundedRectangleBorder(
- borderRadius:
- BorderRadius.circular(64),
- ),
- ),
- unselectedWidgetColor:
- Color(0xFFD3D3D3),
+ ),
+ ),
+ Flexible(
+ child: Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 210.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Container(
+ width: double.infinity,
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Theme(
+ data: ThemeData(
+ checkboxTheme: CheckboxThemeData(
+ visualDensity:
+ VisualDensity.compact,
+ materialTapTargetSize:
+ MaterialTapTargetSize
+ .shrinkWrap,
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.circular(64),
),
- child: Obx(
- () => Checkbox(
- value: userInfoController
- .model.register_agree ??
- false,
- onChanged: (newValue) async {
- userInfoController.model
- .register_agree =
- newValue;
- userInfoController
- .updateAll();
- // 获取设备信息,需要用户点击确认隐私协议与用户协议选择框时才能获取
- // if (newValue == true) {
- // Deviceconfig
- // .initPlatformState();
- // }
- },
- side: BorderSide(
- width: 1.5,
- color: FlutterFlowTheme.of(
- context)
- .secondaryText,
- ),
- activeColor:
- stringToColor("#16C89F"),
- checkColor:
- FlutterFlowTheme.of(context)
- .info,
- ),
- )),
- Text(
- '绑定引导.不再提示'.tr,
- style: FlutterFlowTheme.of(context)
- .bodyMedium
- .override(
- fontFamily: 'Inter',
- fontSize: 26.rpx,
- letterSpacing: 0.0,
- color: Colors.white),
+ ),
+ unselectedWidgetColor:
+ Color(0xFFD3D3D3),
),
- ].divide(SizedBox(width: 22.rpx)),
- ),
- ),
- CustomCard(
- borderRadius: 50.rpx,
- onTap: () async {
- await Future.delayed(
- Duration(milliseconds: 500));
- Get.back(); // 关闭当前弹窗或页面
- },
- colors: [
- //todo 颜色
- stringToColor("45D989"),
- stringToColor("00C1AA")
- ], // 单色背景也用渐变写法
- title: '',
- child: Container(
- width: MediaQuery.sizeOf(context).width *
- 0.66,
- height:
- MediaQuery.sizeOf(context).height *
- 0.055,
- constraints: BoxConstraints(
- minWidth: 500.rpx,
- minHeight: 90.rpx,
- ),
- alignment: Alignment.center, // 居中对齐
- child: Text(
- '绑定引导.跳过'.tr,
- style: FlutterFlowTheme.of(context)
- .bodyMedium
- .override(
+ child: Obx(
+ () => Checkbox(
+ value: blueteethBindController
+ .model.read ==
+ 1
+ ? false
+ : true,
+ onChanged: (newValue) async {
+ blueteethBindController
+ .model.read =
+ newValue == true ? 0 : 1;
+ blueteethBindController
+ .updateAll();
+ // 获取设备信息,需要用户点击确认隐私协议与用户协议选择框时才能获取
+ // if (newValue == true) {
+ // Deviceconfig
+ // .initPlatformState();
+ // }
+ },
+ side: BorderSide(
+ width: 1.5,
+ color:
+ FlutterFlowTheme.of(context)
+ .secondaryText,
+ ),
+ activeColor:
+ stringToColor("#16C89F"),
+ checkColor:
+ FlutterFlowTheme.of(context)
+ .info,
+ ),
+ )),
+ Text(
+ '绑定引导.不再提示'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
fontFamily: 'Inter',
fontSize: 26.rpx,
letterSpacing: 0.0,
- ),
- ),
+ color: Colors.white),
),
- )
- ].divide(SizedBox(height: 42.rpx)),
+ ].divide(SizedBox(width: 22.rpx)),
+ ),
),
- ),
+ CustomCard(
+ borderRadius: 50.rpx,
+ onTap: () async {
+ await Future.delayed(
+ Duration(milliseconds: 500));
+ Get.back(); // 关闭当前弹窗或页面
+ },
+ colors: [
+ //todo 颜色
+ stringToColor("45D989"),
+ stringToColor("00C1AA")
+ ], // 单色背景也用渐变写法
+
+ child: Container(
+ width:
+ MediaQuery.sizeOf(context).width * 0.66,
+ height:
+ MediaQuery.sizeOf(context).height * 0.055,
+ constraints: BoxConstraints(
+ minWidth: 500.rpx,
+ minHeight: 90.rpx,
+ ),
+ alignment: Alignment.center, // 居中对齐
+ child: Text(
+ '绑定引导.跳过'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ )
+ ].divide(SizedBox(height: 42.rpx)),
),
),
- ],
+ ),
),
- ),
- ));
+ ],
+ ),
+ ),
+ ));
},
);
}
@@ -275,7 +283,7 @@ class _EPageState extends State {
@override
Widget build(BuildContext context) {
- int read = blueteethBindController.model.read;
+ int read = blueteethBindController.model.read!;
if (blueteethBindController.model.read == 1) {
//需要弹窗显示教程
}
@@ -378,11 +386,12 @@ class _EPageState extends State {
if (type == '1') {
Get.toNamed("/blueteethDevice");
}
+ if (type == '2') {
+ Get.toNamed("/wifiPage");
+ }
}
},
- // colors: [Colors.white.withOpacity(0.06)], // 背景色
colors: [stringToColor("#242835")], // 背景色
- title: title,
child: Container(
width: double.infinity,
height: MediaQuery.sizeOf(context).height * 0.135,
diff --git a/lib/pages/device_bind/wifi_page.dart b/lib/pages/device_bind/wifi_page.dart
new file mode 100644
index 0000000..fe7801b
--- /dev/null
+++ b/lib/pages/device_bind/wifi_page.dart
@@ -0,0 +1,502 @@
+import 'dart:async';
+
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_blue_plus/flutter_blue_plus.dart';
+import 'package:flutterflow_ui/flutterflow_ui.dart';
+import 'package:vbvs_app/common/color/appConstants.dart';
+import 'package:vbvs_app/common/util/Ble.dart';
+import 'package:vbvs_app/common/util/FitTool.dart';
+import 'package:vbvs_app/common/util/MyUtils.dart';
+import 'package:vbvs_app/component/tool/CustomCard.dart';
+import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
+import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
+import 'package:vbvs_app/controller/person/person_controller.dart';
+import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
+import 'package:vbvs_app/controller/user_info_controller.dart';
+import 'package:vbvs_app/common/util/Ble.dart' as ble;
+import 'package:vbvs_app/pages/common/selectDialog.dart';
+
+class WifiPage extends StatefulWidget {
+ // ble.ConnectedDeviceProp connectedDeviceProp;
+ BluetoothDevice bluetoothDevice;
+ // WifiPage({super.key, required this.connectedDeviceProp});
+ WifiPage({super.key, required this.bluetoothDevice});
+
+ @override
+ State createState() => _WifiPageState();
+}
+
+class _WifiPageState extends State {
+ GlobalController globalController = Get.find();
+ UserInfoController userInfoController = Get.find();
+ BlueteethBindController blueteethBindController = Get.find();
+ PersonController personController = Get.find();
+ ThemeController themeController = Get.find();
+ late ble.ConnectedDeviceProp connectedDeviceProp;
+
+ @override
+ void initState() {
+ super.initState();
+ connectToDevice(widget.bluetoothDevice);
+ // connectedDeviceProp = widget.connectedDeviceProp;
+ Timer(const Duration(microseconds: 100), () {
+ getWifiList();
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return LayoutBuilder(
+ builder: (context, bodySize) => GestureDetector(
+ onTap: () => FocusScope.of(context).unfocus(),
+ child: Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: AssetImage('assets/img/bgNoImg.png'), // 本地图片
+ fit: BoxFit.fill, // 填满整个 Container
+ ),
+ ),
+ child: Scaffold(
+ backgroundColor: Colors.transparent, // 加上这一行
+ appBar: AppBar(
+ backgroundColor: stringToColor("#242835"),
+ // backgroundColor: Colors.transparent,
+ automaticallyImplyLeading: false,
+ iconTheme: IconThemeData(color: Colors.white),
+ titleSpacing: 0,
+ // leading: returnIconButtom,
+ title: Container(
+ // color: Colors.grey,
+ width: double.infinity,
+ height: 180.rpx,
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ /// 居中标题
+ Text(
+ 'wifi页.标题'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx,
+ ),
+ ),
+
+ /// 左边返回按钮
+ Positioned(
+ left: 0,
+ child: returnIconButtom,
+ ),
+ Positioned(
+ right: 20.rpx,
+ child: CustomCard(
+ borderRadius: 20.rpx,
+ onTap: () async {
+ Get.offAllNamed("/bindDeviceSuccess");
+ },
+ colors: [
+ stringToColor("#45D989"),
+ stringToColor("#00C1AA"),
+ ],
+ child: Container(
+ width: 100.rpx,
+ height: 60.rpx,
+ alignment: Alignment.center,
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 16.rpx, 0, 16.rpx, 0),
+ child: Text(
+ 'wifi页.跳过'.tr,
+ style: FlutterFlowTheme.of(context)
+ .titleSmall
+ .override(
+ fontFamily: 'Inter Tight',
+ color: Colors.white,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+
+ actions: [],
+ centerTitle: false,
+ ),
+
+ body: SafeArea(
+ top: true,
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 30.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Color(0xFF242835),
+ borderRadius: BorderRadius.circular(20.rpx),
+ ),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 30.rpx, 30.rpx, 30.rpx, 30.rpx),
+ child: Row(
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ "wifi页.WLAN".tr,
+ style: TextStyle(
+ color: themeController.currentColor.sc3,
+ fontSize:
+ AppConstants().title_text_fontSize,
+ ),
+ ),
+ Text(
+ "wifi页.未连接".tr,
+ style: TextStyle(
+ color: themeController.currentColor.sc3,
+ fontSize:
+ AppConstants().normal_text_fontSize,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0.rpx, 25.rpx, 0.rpx, 0.rpx),
+ child: 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,
+ decoration: BoxDecoration(),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '可用WLAN',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ ],
+ ),
+ Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ '6503',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Icon(
+ Icons.wifi_outlined,
+ size: 30.rpx,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ '6503',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Icon(
+ Icons.wifi_outlined,
+ size: 30.rpx,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ '6503',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Icon(
+ Icons.wifi_outlined,
+ size: 30.rpx,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ '6503',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Icon(
+ Icons.wifi_outlined,
+ size: 30.rpx,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ],
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ '6503',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Icon(
+ Icons.wifi_outlined,
+ size: 30.rpx,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ],
+ ),
+ ].divide(SizedBox(height: 67.rpx)),
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(
+ Icons.arrow_back,
+ color: themeController.currentColor.sc3,
+ size: 30.rpx,
+ ),
+ Text(
+ '刷新',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3),
+ ),
+ ].divide(SizedBox(width: 26.rpx)),
+ ),
+ ].divide(SizedBox(height: 65.rpx)),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ Widget _buildDeviceCard(BuildContext context,
+ {required String title, required String imageUrl, required String type}) {
+ return CustomCard(
+ borderRadius: 20.rpx, // 圆角大小
+ onTap: () {
+ if (type != null) {
+ if (type == '1') {
+ Get.toNamed("/blueteethDevice");
+ }
+ }
+ },
+ // colors: [Colors.white.withOpacity(0.06)], // 背景色
+ colors: [stringToColor("#242835")], // 背景色
+
+ child: Container(
+ width: double.infinity,
+ height: MediaQuery.sizeOf(context).height * 0.135,
+ constraints: BoxConstraints(
+ minHeight: 220.rpx,
+ ),
+ padding: EdgeInsetsDirectional.fromSTEB(77.rpx, 0, 21.rpx, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ title,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFC2CED7),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ClipRRect(
+ borderRadius: BorderRadius.circular(8.rpx),
+ child: Image.asset(
+ imageUrl,
+ width: 212.rpx,
+ height: 168.rpx,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ getWifiList({int time = 3}) {
+ // LoadingDialog.show("扫描WIFI列表中...", icon: LoadingDialogIcon.wifi);
+ try {
+ var device = widget.bluetoothDevice;
+ String log = "";
+ Function logAdd = (l) {
+ log += l;
+ };
+ connectedDeviceProp.receiveLogArr.add(logAdd);
+ connectedDeviceProp.write3OfString("wscan scan", success: () {
+ Timer.periodic(const Duration(milliseconds: 1000), (timer) async {
+ if (timer.tick > 8) {
+ timer.cancel();
+ connectedDeviceProp.receiveLogArr.remove(logAdd);
+ LoadingDialog.hide();
+ if (time > 0) {
+ getWifiList(time: time - 1);
+ }
+ }
+ Iterable a = RegExp(
+ r'ITEM:SSID=([^\t]*)\s*RSSI=(\S*)\s*(,\s*auth\s*=\s*(\S*))?')
+ .allMatches(log);
+ if (a.isEmpty == false) {
+ await Future.delayed(const Duration(milliseconds: 500));
+ a = RegExp(
+ r'ITEM:SSID=([^\t]*)\s*RSSI=(\S*)\s*(,\s*auth\s*=\s*(\S*))?')
+ .allMatches(log);
+ List arr = [];
+ for (RegExpMatch one in a) {
+ arr.add({"name": one[1], "num": one[2], "auth": one[4]});
+ }
+ LoadingDialog.hide();
+ blueteethBindController.model.wifiList = arr;
+ blueteethBindController.updateAll();
+ connectedDeviceProp.receiveLogArr.remove(logAdd);
+ timer.cancel();
+ checkIsCalibration();
+ }
+ });
+ }, fail: () {
+ connectedDeviceProp.receiveLogArr.remove(logAdd);
+ LoadingDialog.hide();
+ });
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ checkIsCalibration() {
+ // if (controller.model.bindArr[0] == "" ||
+ // controller.model.bindArr[0] == null) {
+ // return;
+ // }
+ // if (controller.model.bindArr[2] == "" ||
+ // controller.model.bindArr[2] == null) {
+ // return;
+ // }
+ // if (controller.model.connectedWifiName == "" ||
+ // controller.model.connectedWifiName == null) {
+ // return;
+ // }
+ showCustomConfirmAndCancelDialog(context, "是否进行设备校准?", confirmName: "去校准")
+ .then((d) async {
+ // if (d == "confirm") {
+ // await Get.offAndToNamed("/calibration", arguments: [
+ // controller.model.bindArr[1],
+ // controller.model.bindArr[2]
+ // ]);
+ // Get.find().getDeviceList();
+ // }
+ });
+ }
+}
diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart
index c27e3d1..923d8e1 100644
--- a/lib/pages/login/login.dart
+++ b/lib/pages/login/login.dart
@@ -7,6 +7,7 @@ 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/controller/login/login_controller.dart';
import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
import 'package:vbvs_app/controller/user_info_controller.dart';
@@ -20,6 +21,7 @@ class LoginPage extends StatefulWidget {
class _EPageState extends State {
GlobalController globalController = Get.find();
UserInfoController userInfoController = Get.find();
+ LoginController loginController = Get.find();
@override
Widget build(BuildContext context) {
@@ -75,36 +77,6 @@ class _EPageState extends State {
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
- // ClickableContainer(
- // backgroundColor: Colors.transparent, // 容器背景色为透明
- // highlightColor: Colors.pink, // 点击时背景色也为透明
- // padding: EdgeInsets.all(0), // 没有额外的内边距
- // onTap: () {
- // // 你可以在这里定义点击事件的回调,比如关闭页面等
- // print('关闭按钮被点击');
- // },
- // borderRadius: 0, // 没有圆角
- // child: Container(
- // // color: Colors.red,
- // // width: double.infinity, // 使容器宽度充满父容器
- // child: Align(
- // alignment:
- // AlignmentDirectional(-1, 0), // 左对齐
- // child: Padding(
- // padding: EdgeInsetsDirectional.fromSTEB(
- // 0, 66.rpx, 0, 0),
- // child: SvgPicture.asset(
- // 'assets/img/icon/close.svg',
- // width: 25.rpx,
- // height: 25
- // .rpx, // 如果 SVG 中没有固定颜色,使用 color 设置
- // color: Colors.white, // 这里设置了颜色
- // ),
- // ),
- // ),
- // ),
- // ),
-
Align(
alignment: AlignmentDirectional(-1, 0),
child: Padding(
@@ -190,16 +162,20 @@ class _EPageState extends State {
borderRadius: AppConstants()
.button_container_radius, // 圆角半径
onTap: () {
- print('Button pressed ...');
- // Get.toNamed("/deviceType");
+ bool agree = loginController
+ .model.register_agree!;
+ if (!agree) {
+ print('未授权 ...');
+ } else {
+ print('已授权 ...');
+ }
},
colors: [
//todo 颜色
stringToColor("45D989"),
stringToColor("00C1AA")
], // 渐变色是同一个色,也可以根据需要调整
- title:
- '首页.蓝牙绑定'.tr, // 可选,虽然这个 title 没用,但可以作为调试用
+
child: Container(
width:
// MediaQuery.sizeOf(context).width * 0.66,
@@ -215,13 +191,6 @@ class _EPageState extends State {
mainAxisAlignment:
MainAxisAlignment.center,
children: [
- // Icon(
- // Icons.arrow_back,
- // color: FlutterFlowTheme.of(context)
- // .primaryText,
- // size: 28.rpx,
- // ),
-
Text(
'登录页.本机号码一键登录/注册'.tr,
style: FlutterFlowTheme.of(context)
@@ -242,39 +211,6 @@ class _EPageState extends State {
),
),
),
- // ClickableContainer(
- // backgroundColor: Colors.transparent, // 背景色(透明)
- // highlightColor: stringToColor(
- // "#FF6347"), // 点击时的背景色,可以根据需求设置颜色
- // padding: EdgeInsetsDirectional.fromSTEB(
- // 0, 32.rpx, 0, 32.rpx), // 内部间距
- // onTap: () {
- // print('点击了“其他手机号码”'); // 点击后的回调事件
- // // 这里可以放置点击后的逻辑,比如导航等
- // },
- // borderRadius: 0.rpx, // 可选的圆角参数,默认是 20.rpx
- // child: Align(
- // alignment: AlignmentDirectional(-1, 0),
- // child: Container(
- // width: double.infinity,
- // decoration: BoxDecoration(),
- // child: Align(
- // alignment: AlignmentDirectional(0, 0),
- // child: Text(
- // '登录页.其他手机号码'.tr,
- // style: FlutterFlowTheme.of(context)
- // .bodyMedium
- // .override(
- // fontFamily: 'Inter',
- // fontSize: 26.rpx,
- // letterSpacing: 0.0,
- // color: stringToColor("#FFFFFF"),
- // ),
- // ),
- // ),
- // ),
- // ),
- // ),
SizedBox(
height: 20.rpx,
),
@@ -285,6 +221,7 @@ class _EPageState extends State {
16.rpx, 10.rpx, 16.rpx, 10.rpx),
onTap: () {
print('点击了容器');
+ Get.toNamed("/otherLoginPage");
},
child: Text(
'登录页.其他手机号码'.tr, // 子组件内容
@@ -306,14 +243,6 @@ class _EPageState extends State {
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
- // SvgPicture.asset(
- // 'assets/img/icon/tick.svg',
- // width: 30.rpx,
- // height: 30.rpx, // 如果 SVG 中没有固定颜色,可以这样设置
- // //todo 颜色
- // // color: Colors.white,
- // color: Colors.white,
- // ),
Theme(
data: ThemeData(
checkboxTheme: CheckboxThemeData(
@@ -332,13 +261,13 @@ class _EPageState extends State {
),
child: Obx(
() => Checkbox(
- value: userInfoController
+ value: loginController
.model.register_agree ??
false,
onChanged: (newValue) async {
- userInfoController.model
+ loginController.model
.register_agree = newValue;
- userInfoController.updateAll();
+ loginController.updateAll();
// 获取设备信息,需要用户点击确认隐私协议与用户协议选择框时才能获取
// if (newValue == true) {
// Deviceconfig
@@ -358,7 +287,6 @@ class _EPageState extends State {
.info,
),
)),
-
Expanded(
child: Padding(
padding:
diff --git a/lib/pages/login/other_login.dart b/lib/pages/login/other_login.dart
new file mode 100644
index 0000000..0a98278
--- /dev/null
+++ b/lib/pages/login/other_login.dart
@@ -0,0 +1,801 @@
+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/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/CustomCard.dart';
+import 'package:vbvs_app/controller/login/login_controller.dart';
+import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
+import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
+import 'package:vbvs_app/controller/time/countdown_controller.dart';
+import 'package:vbvs_app/controller/user_info_controller.dart';
+
+class OtherLoginPage extends StatefulWidget {
+ const OtherLoginPage({super.key});
+
+ @override
+ State createState() => _OtherLoginPageState();
+}
+
+class _OtherLoginPageState extends State {
+ GlobalController globalController = Get.find();
+ UserInfoController userInfoController = Get.find();
+ ThemeController themeController = Get.find();
+ CountdownController countdownController = Get.find();
+ LoginController loginController = Get.find();
+
+ @override
+ Widget build(BuildContext context) {
+ return LayoutBuilder(
+ builder: (context, bodysize) => GestureDetector(
+ onTap: () => FocusScope.of(context).unfocus(),
+ child: Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: AssetImage('assets/img/bgImage.png'), // 本地图片
+ fit: BoxFit.fill, // 填满整个 Container
+ ),
+ ),
+ child: Scaffold(
+ backgroundColor: Colors.transparent,
+ body: SafeArea(
+ top: true,
+ child: Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(75.rpx, 0.rpx, 75.rpx, 0),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Column(
+ children: [
+ SizedBox(
+ height: 66.rpx,
+ ),
+ ClickableContainer(
+ backgroundColor: Colors.transparent, // 容器背景色
+ highlightColor: Colors.green, // 点击时的背景色
+ padding:
+ EdgeInsets.zero, // 这里去掉外部的 padding,避免影响点击范围
+ onTap: () {
+ Get.back();
+ },
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 16.rpx, 10.rpx, 16.rpx, 10.rpx),
+ child: SvgPicture.asset(
+ 'assets/img/icon/arrow_left.svg',
+ width: 25.rpx,
+ height: 25.rpx, // 如果 SVG 中没有固定颜色,使用 color 设置
+ color: Colors.white, // 这里设置了颜色
+ ),
+ ),
+ ),
+ ],
+ ),
+ Expanded(
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 141.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Text(
+ '登录页.欢迎使用太和e护'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 48.rpx,
+ letterSpacing: 0.0,
+ //todo 颜色
+ color: stringToColor("#FFFFFF"),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 15.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Text(
+ '登录页.科技睡眠 洞悉万千'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ //todo 颜色
+ color: stringToColor("#FFFFFF"),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 95.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ height: bodysize.maxHeight * 0.056,
+ decoration: BoxDecoration(
+ color: Colors.transparent,
+ borderRadius: BorderRadius.circular(
+ AppConstants()
+ .button_container_radius),
+ border: Border.all(
+ color: Colors.white,
+ width: 1.rpx,
+ ),
+ ),
+ constraints: BoxConstraints(
+ minHeight: 90.rpx,
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 35.rpx, 0, 35.rpx, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: Container(
+ child: Align(
+ alignment:
+ AlignmentDirectional(-1, 0),
+ child: TextFormField(
+ autofocus: false,
+ obscureText: false,
+ decoration: InputDecoration(
+ isDense: true,
+ labelStyle: FlutterFlowTheme
+ .of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ 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),
+ ),
+ errorBorder:
+ OutlineInputBorder(
+ borderSide: BorderSide(
+ color:
+ FlutterFlowTheme.of(
+ context)
+ .error,
+ width: 1.rpx,
+ ),
+ borderRadius:
+ BorderRadius.circular(
+ 8.rpx),
+ ),
+ focusedErrorBorder:
+ OutlineInputBorder(
+ borderSide: BorderSide(
+ color:
+ FlutterFlowTheme.of(
+ context)
+ .error,
+ width: 1.rpx,
+ ),
+ borderRadius:
+ BorderRadius.circular(
+ 8.rpx),
+ ),
+ filled: false,
+ fillColor: FlutterFlowTheme
+ .of(context)
+ .secondaryBackground,
+ ),
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ cursorColor:
+ FlutterFlowTheme.of(
+ context)
+ .primaryText,
+ // validator: _model
+ // .textControllerValidator
+ // .asValidator(context),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 19.rpx, 0, 0),
+ child: Container(
+ height: bodysize.maxHeight * 0.056,
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: Colors.transparent,
+ borderRadius: BorderRadius.circular(
+ AppConstants()
+ .button_container_radius),
+ border: Border.all(
+ color: Colors.white,
+ width: 1.rpx,
+ ),
+ ),
+ constraints: BoxConstraints(
+ minHeight: 90.rpx,
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 35.rpx, 0, 35.rpx, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: Container(
+ child: Align(
+ alignment:
+ AlignmentDirectional(-1, 0),
+ child: TextFormField(
+ autofocus: false,
+ obscureText: false,
+ decoration: InputDecoration(
+ isDense: true,
+ labelStyle: FlutterFlowTheme
+ .of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ 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),
+ ),
+ errorBorder:
+ OutlineInputBorder(
+ borderSide: BorderSide(
+ color:
+ FlutterFlowTheme.of(
+ context)
+ .error,
+ width: 1.rpx,
+ ),
+ borderRadius:
+ BorderRadius.circular(
+ 8.rpx),
+ ),
+ focusedErrorBorder:
+ OutlineInputBorder(
+ borderSide: BorderSide(
+ color:
+ FlutterFlowTheme.of(
+ context)
+ .error,
+ width: 1.rpx,
+ ),
+ borderRadius:
+ BorderRadius.circular(
+ 8.rpx),
+ ),
+ filled: true,
+ fillColor:
+ Colors.transparent,
+ ),
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ cursorColor:
+ FlutterFlowTheme.of(
+ context)
+ .primaryText,
+ // validator: _model
+ // .textControllerValidator
+ // .asValidator(context),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(
+ 26.rpx, 0, 0, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ SizedBox(
+ height: 50.rpx,
+ child: VerticalDivider(
+ thickness: 2.rpx,
+ color: themeController
+ .currentColor.sc7,
+ ),
+ ),
+ // Text(
+ // countdownController.countdown
+ // .value ==
+ // 0
+ // ? '其他手机登录页.获取验证码'.tr
+ // : '${countdownController.countdown.value}秒',
+ // style: TextStyle(
+ // fontFamily: 'Readex Pro',
+ // color: themeController
+ // .currentColor.sc7,
+ // fontSize: AppConstants()
+ // .title_text_fontSize,
+ // letterSpacing: 0,
+ // ),
+ // ),
+ Obx(() {
+ final CountdownController
+ countdownController =
+ Get.find<
+ CountdownController>();
+ return InkWell(
+ onTap: () async {
+ if (countdownController
+ .countdown
+ .value !=
+ 0) {
+ return;
+ }
+
+ String msg =
+ await loginController
+ .getCode(context);
+ if (msg.isNotEmpty) {
+ return;
+ }
+ countdownController
+ .countdown
+ .value ==
+ 0
+ ? countdownController
+ .startCountdown(
+ AppConstants
+ .code_time)
+ : null;
+ },
+ child: Container(
+ alignment:
+ Alignment.center,
+ constraints:
+ BoxConstraints(
+ minWidth: 150.rpx,
+ ),
+ child: Text(
+ countdownController
+ .countdown
+ .value ==
+ 0
+ ? '获取验证码'
+ : '${countdownController.countdown.value}秒',
+ style: TextStyle(
+ fontFamily:
+ 'Readex Pro',
+ color:
+ Color(0xFF333333),
+ fontSize: AppConstants()
+ .title_text_fontSize,
+ letterSpacing: 0,
+ ),
+ ),
+ ),
+ );
+ }),
+ ].divide(SizedBox(width: 26.rpx)),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 35.rpx, 0, 0),
+ child: CustomCard(
+ borderRadius: AppConstants()
+ .button_container_radius, // 圆角半径
+ onTap: () {
+ bool agree =
+ loginController.model.register_agree!;
+ if (!agree) {
+ print('未授权 ...');
+ } else {
+ print('已授权 ...');
+ }
+ },
+ colors: [
+ //todo 颜色
+ stringToColor("45D989"),
+ stringToColor("00C1AA")
+ ], // 渐变色是同一个色,也可以根据需要调整
+
+ child: Container(
+ width:
+ // MediaQuery.sizeOf(context).width * 0.66,
+ 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: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ //todo 颜色
+ color: Colors.white,
+ fontFamily: 'Inter',
+ fontSize: AppConstants()
+ .normal_text_fontSize,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(
+ width: 17.rpx,
+ )),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 25.rpx, 83.rpx, 25.rpx, 50.rpx),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Theme(
+ data: ThemeData(
+ checkboxTheme: CheckboxThemeData(
+ visualDensity:
+ VisualDensity.compact,
+ materialTapTargetSize:
+ MaterialTapTargetSize
+ .shrinkWrap,
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.circular(64),
+ ),
+ ),
+ unselectedWidgetColor:
+ Color(0xFFD3D3D3),
+ ),
+ child: Obx(
+ () => Checkbox(
+ value: loginController
+ .model.register_agree ??
+ false,
+ onChanged: (newValue) async {
+ loginController.model
+ .register_agree = newValue;
+ loginController.updateAll();
+ // 获取设备信息,需要用户点击确认隐私协议与用户协议选择框时才能获取
+ // if (newValue == true) {
+ // Deviceconfig
+ // .initPlatformState();
+ // }
+ },
+ side: BorderSide(
+ width: 1.5,
+ color:
+ FlutterFlowTheme.of(context)
+ .secondaryText,
+ ),
+ activeColor:
+ stringToColor("#FF9F66"),
+ checkColor:
+ FlutterFlowTheme.of(context)
+ .info,
+ ),
+ )),
+ Expanded(
+ child: Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(
+ 0.rpx, 10.rpx, 0.rpx, 0.rpx),
+ child: Container(
+ width: bodysize.maxWidth,
+ constraints: BoxConstraints(
+ minWidth: 500.rpx,
+ minHeight: 90.rpx,
+ ),
+ child: RichText(
+ text: TextSpan(
+ children: [
+ TextSpan(
+ text: '登录页.协议1'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: 26.rpx,
+ color: Colors
+ .white, // 可以调整为你想要的颜色
+ ),
+ ),
+ TextSpan(
+ text: '登录页.协议2'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: 26.rpx,
+ color: stringToColor(
+ "#FF9F66"),
+ ),
+ ),
+ TextSpan(
+ text: '登录页.协议3'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: 26.rpx,
+ color: Colors
+ .white, // 可以调整为你想要的颜色
+ ),
+ ),
+ TextSpan(
+ text: '登录页.协议4'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: 26.rpx,
+ color: stringToColor(
+ "#FF9F66"),
+ ),
+ ),
+ TextSpan(
+ text: '登录页.协议5'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: 26.rpx,
+ color: Colors
+ .white, // 可以调整为你想要的颜色
+ ),
+ ),
+ TextSpan(
+ text: '登录页.协议6'.tr,
+ style: FlutterFlowTheme.of(
+ context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ fontSize: 26.rpx,
+ color: stringToColor(
+ "#FF9F66"),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ].divide(SizedBox(width: 18.rpx)),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ height: MediaQuery.sizeOf(context).height * 0.136,
+ constraints: BoxConstraints(
+ minHeight: 220.rpx,
+ ),
+ decoration: BoxDecoration(),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 0, 0, 36.rpx),
+ child: Text(
+ '登录页.其他登录方式'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ //todo 颜色
+ color: stringToColor("#FFFFFF"),
+ ),
+ ),
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Container(
+ width: 91.rpx,
+ height: 91.rpx,
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ ),
+ child: Image.asset(
+ "assets/img/wechat.png",
+ width: 30.rpx,
+ height: 30.rpx,
+ ),
+ ),
+ Container(
+ width: 91.rpx,
+ height: 91.rpx,
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ ),
+ child: Image.asset(
+ "assets/img/tel.png",
+ width: 30.rpx,
+ height: 30.rpx,
+ ),
+ ),
+ Container(
+ width: 91.rpx,
+ height: 91.rpx,
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ ),
+ child: Image.asset(
+ "assets/img/google.png",
+ width: 30.rpx,
+ height: 30.rpx,
+ ),
+ ),
+ ].divide(SizedBox(width: 35.rpx)),
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ )),
+ );
+ }
+}
diff --git a/lib/pages/main_bottom/home_page.dart b/lib/pages/main_bottom/home_page.dart
index 577d3d1..8ac38df 100644
--- a/lib/pages/main_bottom/home_page.dart
+++ b/lib/pages/main_bottom/home_page.dart
@@ -5,6 +5,8 @@ import 'package:flutterflow_ui/flutterflow_ui.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/home_page/SleepDataModuleWidget.dart';
+import 'package:vbvs_app/component/home_page/SleepDateWidget.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/component/tool/CustomCard.dart';
import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
@@ -53,6 +55,7 @@ class _HomePageState extends State {
mainAxisSize: MainAxisSize.max,
children: [
Padding(
+ //用户信息
padding: EdgeInsetsDirectional.fromSTEB(
AppConstants().content_left_right_padding,
0,
@@ -64,36 +67,60 @@ class _HomePageState extends State {
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- CustomCard(
- borderRadius: 20.rpx,
- onTap: () async {
- Get.toNamed("/loginPage");
- },
- title: '首页.登录'
- .tr, // 虽然 title 传入了,但当前组件里没用它(可忽略或用于调试)
- colors: [
- themeController.currentColor.sc1,
- themeController.currentColor.sc2,
- ],
- child: Container(
- width: 100.rpx,
- height: 60.rpx,
- alignment: Alignment.center,
- padding: EdgeInsetsDirectional.fromSTEB(
- 16.rpx, 0, 16.rpx, 0),
- child: Text(
- '首页.登录'.tr,
- style: FlutterFlowTheme.of(context)
- .titleSmall
- .override(
- fontFamily: 'Inter Tight',
- color: themeController
- .currentColor.sc19,
- letterSpacing: 0.0,
- ),
+ Obx(() {
+ return Visibility(
+ visible:
+ userInfoController.model.login == 0,
+ child: CustomCard(
+ borderRadius: 20.rpx,
+ onTap: () async {
+ Get.toNamed("/loginPage");
+ },
+ colors: [
+ themeController.currentColor.sc1,
+ themeController.currentColor.sc2,
+ ],
+ child: Container(
+ width: 100.rpx,
+ height: 60.rpx,
+ alignment: Alignment.center,
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 16.rpx, 0, 16.rpx, 0),
+ child: Text(
+ '首页.登录'.tr,
+ style: FlutterFlowTheme.of(context)
+ .titleSmall
+ .override(
+ fontFamily: 'Inter Tight',
+ color: themeController
+ .currentColor.sc19,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
),
- ),
- ),
+ );
+ }),
+ Obx(() {
+ return Visibility(
+ visible:
+ userInfoController.model.login == 1,
+ child: Column(
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Text(
+ "飞行的鱼",
+ style: TextStyle(color: Colors.white),
+ ),
+ Text(
+ "嘉兴 晴",
+ style: TextStyle(color: Colors.white),
+ ),
+ ],
+ ),
+ );
+ }),
SvgPicture.asset(
'assets/img/icon/add.svg',
width: 39.rpx,
@@ -106,6 +133,7 @@ class _HomePageState extends State {
),
),
Padding(
+ //绑定数量
padding: EdgeInsetsDirectional.fromSTEB(
19.rpx, 34.rpx, 0, 21.rpx),
child: ClickableContainer(
@@ -116,42 +144,67 @@ class _HomePageState extends State {
},
padding: EdgeInsetsDirectional.fromSTEB(
0.rpx, 10.rpx, 0, 10.rpx),
- child: Container(
- child: Row(
- mainAxisSize: MainAxisSize.min,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- Text(
- '首页.已关联体征监测设备'.tr,
- style: FlutterFlowTheme.of(context)
- .bodyMedium
- .override(
- fontFamily: 'Inter',
- fontSize:
- AppConstants().title_text_fontSize,
- letterSpacing: 0.0,
- //todo 颜色
- color: themeController.currentColor.sc3,
+ Container(
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Text(
+ '首页.已关联体征监测设备'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants()
+ .title_text_fontSize,
+ letterSpacing: 0.0,
+ //todo 颜色
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Text(
+ '0',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: AppConstants()
+ .title_text_fontSize,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc8,
+ ),
+ ),
+ ].divide(SizedBox(
+ width: 6.rpx,
+ )),
+ )),
+ Obx(() {
+ return Visibility(
+ visible: userInfoController
+ .model.deviceBindNum! >
+ 0,
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 0.rpx, 8.rpx, 0.rpx),
+ child: SvgPicture.asset(
+ 'assets/img/icon/arrow_right.svg',
+ width: 14.rpx,
+ height: 14.rpx, // 如果 SVG 中没有固定颜色,可以这样设置
+ color: Colors.white,
),
- ),
- Text(
- '0',
- style: FlutterFlowTheme.of(context)
- .bodyMedium
- .override(
- fontFamily: 'Inter',
- fontSize:
- AppConstants().title_text_fontSize,
- letterSpacing: 0.0,
- color: themeController.currentColor.sc8,
- ),
- ),
- ].divide(SizedBox(
- width: 6.rpx,
- )),
- )),
+ ),
+ );
+ }),
+ ],
+ ),
),
),
Container(
+ //未绑定布局
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height * 0.277,
constraints: BoxConstraints(
@@ -178,8 +231,7 @@ class _HomePageState extends State {
themeController.currentColor.sc1,
themeController.currentColor.sc2,
],
- title:
- '首页.蓝牙绑定'.tr, // 可选,虽然这个 title 没用,但可以作为调试用
+
child: Container(
width:
MediaQuery.sizeOf(context).width * 0.66,
@@ -229,8 +281,7 @@ class _HomePageState extends State {
themeController.currentColor.sc1,
themeController.currentColor.sc2,
], // 渐变色是同一个色,也可以根据需要调整
- title:
- '首页.蓝牙绑定'.tr, // 可选,虽然这个 title 没用,但可以作为调试用
+
child: Container(
width:
MediaQuery.sizeOf(context).width * 0.66,
@@ -278,6 +329,7 @@ class _HomePageState extends State {
),
),
Padding(
+ //未绑定标语
padding:
EdgeInsetsDirectional.fromSTEB(0, 26.rpx, 0, 0),
child: Container(
@@ -374,6 +426,213 @@ class _HomePageState extends State {
),
),
),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 26.rpx, 0, 0),
+ child: Container(
+ // color: Colors.red,
+ width: bodySize.maxWidth,
+ height: bodySize.maxHeight * 0.107,
+ constraints: BoxConstraints(
+ minHeight: 240.rpx,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ ClickableContainer(
+ backgroundColor:
+ themeController.currentColor.sc5,
+ highlightColor:
+ themeController.currentColor.sc3,
+ borderRadius:
+ AppConstants().normal_container_radius,
+ padding:
+ EdgeInsets.zero, // 原始Container没有padding
+ onTap: () {
+ // 点击逻辑放这里
+ },
+ child: Container(
+ width: bodySize.maxWidth * 0.445,
+ child: Column(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ SizedBox(height: 32.rpx),
+ Container(
+ width: 120.rpx,
+ height: 120.rpx,
+ child: Image.asset(
+ "assets/img/netlove.png",
+ fit: BoxFit.cover,
+ ),
+ ),
+ Text(
+ "首页.我的e护".tr,
+ style: TextStyle(
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ SizedBox(height: 32.rpx),
+ ],
+ ),
+ ),
+ ),
+ ClickableContainer(
+ backgroundColor:
+ themeController.currentColor.sc5,
+ highlightColor:
+ themeController.currentColor.sc3,
+ borderRadius:
+ AppConstants().normal_container_radius,
+ padding: EdgeInsets
+ .zero, // 原本的Container没有 padding,这里设置为 zero
+ onTap: () {
+ // TODO: 替换为你需要的点击事件逻辑
+ print("云关爱 被点击");
+ },
+ child: SizedBox(
+ width: bodySize.maxWidth * 0.445,
+ child: Column(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ Container(
+ width: 120.rpx,
+ height: 120.rpx,
+ child: Image.asset(
+ "assets/img/mye.png",
+ fit: BoxFit.cover,
+ ),
+ ),
+ Text(
+ "首页.云关爱".tr,
+ style: TextStyle(
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ ]
+ .addToStart(SizedBox(height: 32.rpx))
+ .addToEnd(SizedBox(height: 32.rpx)),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ // Generated code for this Container Widget...
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 25.rpx, 0, 25.rpx),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ color: themeController.currentColor.sc5,
+ borderRadius: BorderRadius.circular(
+ AppConstants().normal_container_radius),
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 30.rpx, 30.rpx, 30.rpx, 30.rpx),
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Container(
+ width: double.infinity,
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ '次卧/1201/李小北',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Text(
+ '首页.报告详情'.tr,
+ style:
+ FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ color: themeController
+ .currentColor.sc3,
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional
+ .fromSTEB(0, 6.rpx, 0, 0.rpx),
+ child: SvgPicture.asset(
+ 'assets/img/icon/arrow_right.svg',
+ width: 14.rpx,
+ height: 14
+ .rpx, // 如果 SVG 中没有固定颜色,可以这样设置
+ color: Colors.white,
+ ),
+ ),
+ ].divide(SizedBox(width: 22.rpx)),
+ ),
+ ],
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ SleepDateWidget(),
+ SleepDateWidget(),
+ SleepDateWidget(),
+ SleepDateWidget(),
+ SleepDateWidget(),
+ SleepDateWidget(),
+ ].divide(SizedBox(
+ width: 20.rpx,
+ )),
+ ),
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ SleepDataModuleWidget(),
+ SleepDataModuleWidget(),
+ SleepDataModuleWidget(),
+ SleepDataModuleWidget(),
+ SleepDataModuleWidget(),
+ ].divide(SizedBox(
+ width: 14.rpx)), // ✅ 这里加了 .rpx
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ )
],
),
),
diff --git a/lib/pages/main_bottom/main_page_bottom_change.dart b/lib/pages/main_bottom/main_page_bottom_change.dart
index e1dc519..de47fd5 100644
--- a/lib/pages/main_bottom/main_page_bottom_change.dart
+++ b/lib/pages/main_bottom/main_page_bottom_change.dart
@@ -90,47 +90,56 @@ class MainPageBottomChange extends GetView {
floatingActionButton: Container(),
);
} else {
- return Scaffold(
- backgroundColor: Colors.transparent,
- body: arr[controller.model.currentIndex],
- floatingActionButtonAnimator:
- FloatingActionButtonAnimator.noAnimation,
- floatingActionButtonLocation:
- FloatingActionButtonLocation.centerDocked,
- bottomNavigationBar: Theme(
- data: ThemeData(
- splashFactory: NoSplash.splashFactory,
- highlightColor: Colors.transparent),
- child: BottomNavigationBar(
- unselectedItemColor: themeController.currentColor.sc4,
- selectedItemColor: themeController.currentColor.sc1,
- backgroundColor: themeController.currentColor.sc5,
- selectedFontSize: 26.rpx,
- unselectedFontSize: 26.rpx,
- type: BottomNavigationBarType.fixed,
- currentIndex: controller.model.currentIndex,
- onTap: (index) {
- Future.delayed(const Duration(milliseconds: 500), () {
- if (controller.model.currentIndex != 1) {
- globalController.model.hideBottomNavigationBar = false;
- globalController.updateAll();
- }
- });
- controller.model.currentIndex = index;
- controller.updateAll();
- },
- items: [
- getBottomNavigationBarItem("assets/img/menu/home.svg",
- "assets/img/menu/n_home.svg", "菜单.首页".tr),
- // getBottomNavigationBarItem("assets/img/menu/report.svg",
- // "assets/img/menu/n_report.svg", "菜单.报告".tr),
- getBottomNavigationBarItem("assets/img/menu/e.svg",
- "assets/img/menu/n_e.svg", "菜单.小e".tr),
- getBottomNavigationBarItem("assets/img/menu/message.svg",
- "assets/img/menu/n_message.svg", "菜单.消息".tr),
- getBottomNavigationBarItem("assets/img/menu/mine.svg",
- "assets/img/menu/n_mine.svg", "菜单.我的".tr),
- ],
+ return Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: AssetImage('assets/img/bgImage.png'), // 本地图片
+ fit: BoxFit.fill, // 填满整个 Container
+ ),
+ ),
+ child: Scaffold(
+ backgroundColor: Colors.transparent,
+ body: arr[controller.model.currentIndex],
+ floatingActionButtonAnimator:
+ FloatingActionButtonAnimator.noAnimation,
+ floatingActionButtonLocation:
+ FloatingActionButtonLocation.centerDocked,
+ bottomNavigationBar: Theme(
+ data: ThemeData(
+ splashFactory: NoSplash.splashFactory,
+ highlightColor: Colors.transparent),
+ child: BottomNavigationBar(
+ unselectedItemColor: themeController.currentColor.sc4,
+ selectedItemColor: themeController.currentColor.sc1,
+ backgroundColor: themeController.currentColor.sc5,
+ selectedFontSize: 26.rpx,
+ unselectedFontSize: 26.rpx,
+ type: BottomNavigationBarType.fixed,
+ currentIndex: controller.model.currentIndex,
+ onTap: (index) {
+ Future.delayed(const Duration(milliseconds: 500), () {
+ if (controller.model.currentIndex != 1) {
+ globalController.model.hideBottomNavigationBar =
+ false;
+ globalController.updateAll();
+ }
+ });
+ controller.model.currentIndex = index;
+ controller.updateAll();
+ },
+ items: [
+ getBottomNavigationBarItem("assets/img/menu/home.svg",
+ "assets/img/menu/n_home.svg", "菜单.首页".tr),
+ // getBottomNavigationBarItem("assets/img/menu/report.svg",
+ // "assets/img/menu/n_report.svg", "菜单.报告".tr),
+ getBottomNavigationBarItem("assets/img/menu/e.svg",
+ "assets/img/menu/n_e.svg", "菜单.小e".tr),
+ getBottomNavigationBarItem("assets/img/menu/message.svg",
+ "assets/img/menu/n_message.svg", "菜单.消息".tr),
+ getBottomNavigationBarItem("assets/img/menu/mine.svg",
+ "assets/img/menu/n_mine.svg", "菜单.我的".tr),
+ ],
+ ),
),
),
);
diff --git a/lib/pages/person/person_page.dart b/lib/pages/person/person_page.dart
new file mode 100644
index 0000000..e29fa35
--- /dev/null
+++ b/lib/pages/person/person_page.dart
@@ -0,0 +1,619 @@
+import 'package:ef/ef.dart';
+import 'package:flutter/material.dart';
+import 'package:flutterflow_ui/flutterflow_ui.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/CustomCard.dart';
+import 'package:vbvs_app/controller/device/blueteeth_bind_controller.dart';
+import 'package:vbvs_app/controller/main_bottom/global_controller.dart';
+import 'package:vbvs_app/controller/person/person_controller.dart';
+import 'package:vbvs_app/controller/user_info_controller.dart';
+import 'package:vbvs_app/pages/person/select_time.dart';
+
+class PersonPage extends StatefulWidget {
+ const PersonPage({super.key});
+
+ @override
+ State createState() => _EPageState();
+}
+
+class _EPageState extends State {
+ GlobalController globalController = Get.find();
+ UserInfoController userInfoController = Get.find();
+ BlueteethBindController blueteethBindController = Get.find();
+ PersonController personController = Get.find();
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return LayoutBuilder(
+ builder: (context, bodySize) => GestureDetector(
+ onTap: () => FocusScope.of(context).unfocus(),
+ child: Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: AssetImage('assets/img/bgNoImg.png'), // 本地图片
+ fit: BoxFit.fill, // 填满整个 Container
+ ),
+ ),
+ child: Scaffold(
+ backgroundColor: Colors.transparent, // 加上这一行
+ appBar: AppBar(
+ backgroundColor: stringToColor("#242835"),
+ // backgroundColor: Colors.transparent,
+ automaticallyImplyLeading: false,
+ iconTheme: IconThemeData(color: Colors.white),
+ titleSpacing: 0,
+ // leading: returnIconButtom,
+ title: Container(
+ // color: Colors.grey,
+ width: double.infinity,
+ height: 180.rpx,
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ /// 居中标题
+ Text(
+ '人员资料.标题'.tr,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx,
+ ),
+ ),
+
+ /// 左边返回按钮
+ Positioned(
+ left: 0,
+ child: returnIconButtom,
+ ),
+ Positioned(
+ right: 20.rpx,
+ child: CustomCard(
+ borderRadius: 20.rpx,
+ onTap: () async {
+ Get.offAllNamed("/bindDeviceSuccess");
+ },
+
+ colors: [
+ stringToColor("#45D989"),
+ stringToColor("#00C1AA"),
+ ],
+ child: Container(
+ width: 100.rpx,
+ height: 60.rpx,
+ alignment: Alignment.center,
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 16.rpx, 0, 16.rpx, 0),
+ child: Text(
+ '人员资料.保存'.tr,
+ style: FlutterFlowTheme.of(context)
+ .titleSmall
+ .override(
+ fontFamily: 'Inter Tight',
+ color: Colors.white,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+
+ actions: [],
+ centerTitle: false,
+ ),
+
+ body: SafeArea(
+ top: true,
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
+ child: SingleChildScrollView(
+ child: Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 70.rpx, 141.rpx, 70.rpx, 0),
+ child: Container(
+ width: double.infinity,
+ height: 100.rpx,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(50.rpx),
+ border: Border.all(
+ color: Color(0xFFF3EDED),
+ ),
+ ),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: TextFormField(
+ // controller: _model.textController1,
+ // focusNode: _model.textFieldFocusNode1,
+ autofocus: false,
+ obscureText: false,
+ decoration: InputDecoration(
+ fillColor: Colors.transparent,
+ isDense: true,
+ labelStyle: FlutterFlowTheme.of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ color: Colors.white),
+ hintText: '人员资料.名字输入提示'.tr,
+ hintStyle: FlutterFlowTheme.of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ 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),
+ ),
+ errorBorder: OutlineInputBorder(
+ borderSide: BorderSide(
+ color: FlutterFlowTheme.of(context).error,
+ width: 1.rpx,
+ ),
+ borderRadius: BorderRadius.circular(8.rpx),
+ ),
+ focusedErrorBorder: OutlineInputBorder(
+ borderSide: BorderSide(
+ color: FlutterFlowTheme.of(context).error,
+ width: 1.rpx,
+ ),
+ borderRadius: BorderRadius.circular(8.rpx),
+ ),
+ filled: true,
+ ),
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ color: Colors.white),
+ textAlign: TextAlign.center,
+ cursorColor:
+ FlutterFlowTheme.of(context).primaryText,
+ // validator: _model.textController1Validator
+ // .asValidator(context),
+ ),
+ ),
+ ),
+ ),
+ Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 90.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(-1, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Container(
+ width: 90.rpx,
+ height: 90.rpx,
+ decoration: BoxDecoration(),
+ child: Container(
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ ),
+ child: Image.asset(
+ "assets/img/man.png",
+ fit: BoxFit.cover,
+ ),
+ ),
+ ),
+ Text(
+ '男',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Colors.white,
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(height: 14.rpx)),
+ ),
+ Column(
+ mainAxisSize: MainAxisSize.max,
+ children: [
+ Container(
+ width: 90.rpx,
+ height: 90.rpx,
+ decoration: BoxDecoration(),
+ child: Container(
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ ),
+ child: Image.asset(
+ "assets/img/woman.png",
+ fit: BoxFit.cover,
+ ),
+ ),
+ ),
+ Text(
+ '女',
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Colors.white,
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ].divide(SizedBox(height: 14.rpx)),
+ ),
+ ].divide(SizedBox(width: 170.rpx)),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 70.rpx, 50.rpx, 70.rpx, 0),
+ // child: Container(
+ // width: double.infinity,
+ // height: 100.rpx,
+ // decoration: BoxDecoration(
+ // borderRadius: BorderRadius.circular(50.rpx),
+ // border: Border.all(
+ // color: Color(0xFFF3EDED),
+ // ),
+ // ),
+ // child: Align(
+ // alignment: AlignmentDirectional(0, 0),
+ // child: Obx(
+ // () => Container(
+ // width: double.infinity,
+ // height:
+ // MediaQuery.sizeOf(context).height * 0.064,
+ // decoration: BoxDecoration(),
+ // child: InkWell(
+ // onTap: () {
+ // // 触摸收起键盘
+ // FocusScope.of(context)
+ // .requestFocus(FocusNode());
+ // Future.delayed(
+ // const Duration(milliseconds: 250), () {
+ // // 延迟执行的代码
+ // showDateSelectionDialog(context,
+ // checkDate:
+ // personController.model.birthday ??
+ // DateTime.now(),
+ // checkChange: (DateTime d) {
+ // personController.model.birthday = d;
+ // personController.updateAll();
+ // print("$d");
+ // }).then((d) {
+ // // Timer(Duration.zero, () {
+ // // FocusScope.of(context).unfocus();
+ // // });
+ // });
+ // });
+ // },
+ // child: Container(
+ // constraints:
+ // BoxConstraints(minWidth: 200.rpx),
+ // child: Text(
+ // personController.model.birthday != null
+ // ? DateFormat("yyyy年MM月dd日").format(
+ // personController.model.birthday!)
+ // : '人员资料.生日输入提示'.tr,
+ // textAlign: TextAlign.right,
+ // style: FlutterFlowTheme.of(context)
+ // .bodyMedium
+ // .override(
+ // fontFamily: 'Readex Pro',
+ // color: Colors.white,
+ // fontSize: 30.rpx,
+ // letterSpacing: 0,
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+ // ),
+
+ child: Container(
+ height: 100.rpx,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(50.rpx),
+ border: Border.all(color: Color(0xFFF3EDED)),
+ ),
+ child: InkWell(
+ onTap: () {
+ FocusScope.of(context).requestFocus(FocusNode());
+ Future.delayed(Duration(milliseconds: 250), () {
+ showDateSelectionDialog(
+ context,
+ checkDate: personController.model.birthday ??
+ DateTime.now(),
+ checkChange: (DateTime d) {
+ personController.model.birthday = d;
+ personController.updateAll();
+ },
+ );
+ });
+ },
+ child: Center(
+ child: Text(
+ personController.model.birthday != null
+ ? DateFormat("yyyy年MM月dd日").format(
+ personController.model.birthday!)
+ : '人员资料.生日输入提示'.tr,
+ textAlign: TextAlign.right,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: personController.model.birthday !=
+ null
+ ? Colors.white
+ : Colors.grey,
+ fontSize:
+ AppConstants().normal_text_fontSize,
+ letterSpacing: 0,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 70.rpx, 18.rpx, 70.rpx, 0),
+ child: Container(
+ width: double.infinity,
+ height: 100.rpx,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(50.rpx),
+ border: Border.all(
+ color: Color(0xFFF3EDED),
+ ),
+ ),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: TextFormField(
+ // controller: _model.textController3,
+ // focusNode: _model.textFieldFocusNode3,
+ autofocus: false,
+ obscureText: false,
+ decoration: InputDecoration(
+ fillColor: Colors.transparent,
+ isDense: true,
+ labelStyle: FlutterFlowTheme.of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ ),
+ hintText: '人员资料.体重输入提示'.tr,
+ hintStyle: FlutterFlowTheme.of(context)
+ .labelMedium
+ .override(
+ fontFamily: 'Inter',
+ color: personController.model.birthday !=
+ null
+ ? Colors.white
+ : Colors.grey,
+ fontSize:
+ AppConstants().normal_text_fontSize,
+ letterSpacing: 0.0,
+ ),
+ 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),
+ ),
+ errorBorder: OutlineInputBorder(
+ borderSide: BorderSide(
+ color: FlutterFlowTheme.of(context).error,
+ width: 1.rpx,
+ ),
+ borderRadius: BorderRadius.circular(8.rpx),
+ ),
+ focusedErrorBorder: OutlineInputBorder(
+ borderSide: BorderSide(
+ color: FlutterFlowTheme.of(context).error,
+ width: 1.rpx,
+ ),
+ borderRadius: BorderRadius.circular(8.rpx),
+ ),
+ filled: true,
+ ),
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ letterSpacing: 0.0,
+ color: Colors.white,
+ ),
+ textAlign: TextAlign.center,
+ cursorColor:
+ FlutterFlowTheme.of(context).primaryText,
+ // validator: _model.textController3Validator
+ // .asValidator(context),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 117.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ child: Align(
+ alignment: AlignmentDirectional(0, 0),
+ child: Text(
+ '人员资料.疾病标题'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Color(0xFFF3F4F5),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 70.rpx, 70.rpx, 70.rpx, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(),
+ ),
+ ),
+ Padding(
+ padding:
+ EdgeInsetsDirectional.fromSTEB(0, 152.rpx, 0, 0),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(20.rpx),
+ border: Border.all(
+ color: Color(0xFFE9E3E3),
+ ),
+ ),
+ child: Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 30.rpx, 30.rpx, 30.rpx, 30.rpx),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: EdgeInsetsDirectional.fromSTEB(
+ 0, 8.rpx, 0, 0),
+ child: Icon(
+ Icons.arrow_back,
+ color: Color(0xFFE4EBF0),
+ size: 24.rpx,
+ ),
+ ),
+ Expanded(
+ child: Text(
+ '人员资料.提示'.tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Inter',
+ color: Color(0xFFEEF3F8),
+ fontSize: 26.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ),
+ ].divide(SizedBox(width: 23.rpx)),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ Widget _buildDeviceCard(BuildContext context,
+ {required String title, required String imageUrl, required String type}) {
+ return CustomCard(
+ borderRadius: 20.rpx, // 圆角大小
+ onTap: () {
+ if (type != null) {
+ if (type == '1') {
+ Get.toNamed("/blueteethDevice");
+ }
+ }
+ },
+ // colors: [Colors.white.withOpacity(0.06)], // 背景色
+ colors: [stringToColor("#242835")], // 背景色
+
+ child: Container(
+ width: double.infinity,
+ height: MediaQuery.sizeOf(context).height * 0.135,
+ constraints: BoxConstraints(
+ minHeight: 220.rpx,
+ ),
+ padding: EdgeInsetsDirectional.fromSTEB(77.rpx, 0, 21.rpx, 0),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ title,
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Inter',
+ color: const Color(0xFFC2CED7),
+ fontSize: 30.rpx,
+ letterSpacing: 0.0,
+ ),
+ ),
+ ClipRRect(
+ borderRadius: BorderRadius.circular(8.rpx),
+ child: Image.asset(
+ imageUrl,
+ width: 212.rpx,
+ height: 168.rpx,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/person/select_time.dart b/lib/pages/person/select_time.dart
new file mode 100644
index 0000000..073374f
--- /dev/null
+++ b/lib/pages/person/select_time.dart
@@ -0,0 +1,290 @@
+import 'package:ef/ef.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.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/controller/theme_controller/ThemeController.dart';
+
+Future showDateSelectionDialog(BuildContext context,
+ {required DateTime checkDate, Function? checkChange, String title = "生日"}) {
+ Color checkColor = stringToColor("#D3B684");
+ List years = [], months = [], days = [];
+ var days_select = [].obs;
+ int day_len = 31;
+ int year = DateTime.now().year;
+ for (var i = 0; i < 100; i++) {
+ years.insert(0, year - i);
+ }
+ for (var i = 1; i < 13; i++) {
+ months.add(i);
+ }
+ for (var i = 1; i < 32; i++) {
+ days.add(i);
+ }
+ int yearIndex = years.lastIndexOf(checkDate.year);
+ int monthIndex = months.lastIndexOf(checkDate.month);
+ day_len = DateTime.fromMillisecondsSinceEpoch(
+ DateTime(years[yearIndex], months[monthIndex] + 1)
+ .millisecondsSinceEpoch -
+ 1000)
+ .day;
+ days_select.value = days.sublist(0, day_len);
+ int dayIndex = days.lastIndexOf(checkDate.day);
+ ThemeController themeController = Get.find();
+ return showDialog(
+ // barrierColor: stringToColor("#000320"),
+ context: context,
+ barrierDismissible: true, // 点击对话框外部可关闭
+ builder: (BuildContext context) {
+ return Stack(
+ children: [
+ Positioned(
+ bottom: 0, // 控制弹窗距离顶部的位置
+ left: 0,
+ right: 0,
+ child: Material(
+ color: Colors.transparent,
+ child: Dialog(
+ backgroundColor: stringToColor("#242835"),
+ // backgroundColor: Colors.transparent,
+ insetPadding: EdgeInsets.zero,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+ child: Container(
+ width: double.infinity,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(
+ AppConstants().normal_container_radius),
+ topRight: Radius.circular(
+ AppConstants().normal_container_radius),
+ bottomLeft: Radius.circular(0.rpx),
+ bottomRight: Radius.circular(0.rpx),
+ ),
+ ),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Container(
+ color: themeController.currentColor.sc5,
+ alignment: Alignment.centerLeft,
+ height: 80.rpx,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ InkWell(
+ child: Text(
+ "日期.取消".tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: AppConstants()
+ .normal_text_fontSize),
+ ),
+ onTap: () {
+ Get.back();
+ },
+ ),
+ Text(
+ "$title",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize:
+ AppConstants().title_text_fontSize),
+ ),
+ // closeIconWhite,
+ InkWell(
+ child: Text(
+ "日期.确定".tr,
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: AppConstants()
+ .normal_text_fontSize),
+ ),
+ onTap: () {
+ checkChange?.call(DateTime(years[yearIndex],
+ months[monthIndex], days[dayIndex]));
+ Get.back();
+ },
+ )
+ ],
+ ),
+ ),
+ Container(
+ height: 240.rpx,
+ margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
+ padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
+ child: Container(
+ child: Row(
+ children: [
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 40.rpx, right: 30.rpx),
+ child: getOnePicker(context, years, yearIndex,
+ (d) {
+ yearIndex = d;
+ dayIndex = 0;
+ day_len =
+ DateTime.fromMillisecondsSinceEpoch(
+ DateTime(
+ years[yearIndex],
+ months[monthIndex] +
+ 1)
+ .millisecondsSinceEpoch -
+ 1000)
+ .day;
+ days_select.value =
+ days.sublist(0, day_len);
+ }),
+ ),
+ ),
+ Container(
+ child: Text(
+ "年",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 30.rpx, right: 30.rpx),
+ child: getOnePicker(
+ context, months, monthIndex, (d) {
+ monthIndex = d;
+ dayIndex = 0;
+ day_len =
+ DateTime.fromMillisecondsSinceEpoch(
+ DateTime(
+ years[yearIndex],
+ months[monthIndex] +
+ 1)
+ .millisecondsSinceEpoch -
+ 1000)
+ .day;
+ days_select.value =
+ days.sublist(0, day_len);
+ }),
+ ),
+ ),
+ Container(
+ child: Text(
+ "月",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ Expanded(
+ child: Container(
+ padding: EdgeInsets.only(
+ left: 30.rpx, right: 40.rpx),
+ child: Obx(
+ () {
+ // print("${dayIndex} ${day_len}");
+ return getOnePicker(
+ context,
+ days_select,
+ dayIndex,
+ (d) {
+ dayIndex = d;
+ },
+ );
+ },
+ ),
+ ),
+ ),
+ Container(
+ child: Text(
+ "日",
+ style: FlutterFlowTheme.of(context)
+ .bodyMedium
+ .override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+}
+
+getOnePicker(context, List arr, int checkIndex, Function onSelectedItemChanged,
+ {bool looping = false}) {
+ return CupertinoPicker(
+ key: UniqueKey(),
+ useMagnifier: false,
+ itemExtent: 80.rpx,
+ magnification: 1,
+ diameterRatio: 3,
+ squeeze: 1,
+ looping: looping,
+ scrollController: FixedExtentScrollController(initialItem: checkIndex),
+ selectionOverlay: Container(),
+ onSelectedItemChanged: (int value) {
+ // print("$value");
+ onSelectedItemChanged.call(value);
+ },
+ children: [
+ ...List.generate(arr.length, (index) {
+ return Container(
+ alignment: Alignment.center,
+ width: 400.rpx,
+ decoration: BoxDecoration(
+ // border: Border(
+ // bottom: index != arr.length
+ // ? BorderSide(
+ // color: stringToColor("#8D95B0"),
+ // )
+ // : BorderSide.none,
+ // ),
+ ),
+ child: Text("${arr[index]}",
+ style: FlutterFlowTheme.of(context).bodyMedium.override(
+ fontFamily: 'Readex Pro',
+ color: Colors.white,
+ letterSpacing: 0,
+ fontSize: 30.rpx)),
+ );
+ })
+ ],
+ );
+}
diff --git a/lib/routers/routers.dart b/lib/routers/routers.dart
index 55b7209..30b63f8 100644
--- a/lib/routers/routers.dart
+++ b/lib/routers/routers.dart
@@ -2,7 +2,9 @@ import 'package:flutter/cupertino.dart';
import 'package:vbvs_app/pages/device_bind/bind_device_success.dart';
import 'package:vbvs_app/pages/device_bind/blueteeth_device_page.dart';
import 'package:vbvs_app/pages/device_bind/device_type.dart';
+import 'package:vbvs_app/pages/device_bind/wifi_page.dart';
import 'package:vbvs_app/pages/login/login.dart';
+import 'package:vbvs_app/pages/login/other_login.dart';
import 'package:vbvs_app/pages/main_bottom/e_page.dart';
import 'package:vbvs_app/pages/main_bottom/home_page.dart';
import 'package:vbvs_app/pages/main_bottom/main_page_bottom_change.dart';
@@ -26,6 +28,9 @@ var routes = {
"/blueteethDevice": (contxt) => BlueteethDevicePage(),
"/personPage": (contxt) => PersonPage(),
"/bindDeviceSuccess": (contxt) => BindDeviceSuccess(),
+ // "/wifiPage": (contxt, {arguments}) => WifiPage(connectedDeviceProp: arguments),
+ "/wifiPage": (contxt, {arguments}) => WifiPage(bluetoothDevice: arguments),
+ "/otherLoginPage": (contxt) => OtherLoginPage(),
};
//2、配置onGenerateRoute 固定写法 这个方法也相当于一个中间件,这里可以做权限判断
diff --git a/pubspec.yaml b/pubspec.yaml
index 0d85cb2..5e7383d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -31,6 +31,7 @@ dependencies:
lottie: ^3.2.0
flutter_blue_plus: ^1.35.3
permission_handler: ^12.0.0+1
+ # geolocator: ^13.0.4
dev_dependencies: