Files
tuiche/lib/pages/mh_page/device/upgrade/device_upgrade.dart
2025-11-13 09:56:02 +08:00

1166 lines
57 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'dart:io';
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';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/util/BluetoothHelper.dart';
import 'package:vbvs_app/common/util/CommonVariables.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/component/tool/CustomCard.dart';
import 'package:vbvs_app/component/tool/NewTopSlideNotification.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.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';
import 'package:vbvs_app/enum/APPDeviceUpgrade.dart';
import 'package:vbvs_app/pages/common/selectDialog.dart';
import 'package:vbvs_app/pages/mh_page/device/component/UpgradeDevice.dart';
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
import 'package:vbvs_app/pages/mh_page/device/mht_blueteeth_device_page.dart';
import 'package:vbvs_app/pages/mh_page/device/model/BlueToothDataModel.dart';
import 'package:vbvs_app/pages/mh_page/device/upgrade/BatchUpgradeManager.dart';
import 'package:vbvs_app/pages/mh_page/device/upgrade/device_upgrade_controller.dart';
import 'package:vbvs_app/pages/mh_page/device/upgrade/tool/device_upgrade_tool.dart';
class DeviceUpgrade extends StatefulWidget {
DeviceUpgrade({super.key});
@override
State<DeviceUpgrade> createState() => _DeviceUpgradeState();
}
class _DeviceUpgradeState extends State<DeviceUpgrade> {
MHTBlueToothController mhtBlueToothController = Get.find();
GlobalController globalController = Get.find();
UserInfoController userInfoController = Get.find();
ThemeController themeController = Get.find();
late FlutterBluePlus flutterBlue;
List<ScanResult> scanResults = [];
bool isScanning = false;
Timer? _timer;
bool _isDialogShowing = false;
var currentConnectedDeviceProp;
var connectDeviceCurrent = null;
List bleDevice = [];
String currentMsg = "寻找设备中...";
Timer? connectTimer;
bool isFind = false;
StreamSubscription<List<ScanResult>>? _scanSubscription;
var formFieldController = FormFieldController<String>(null);
MHTDeviceUpgradeController mhtDeviceUpgradeController = Get.find();
final BatchUpgradeManager _batchManager = BatchUpgradeManager();
bool _isPopupOpen = false;
// 新增状态:控制展开/收起
bool _isExpanded = false;
bool _showFilterPanel = false;
// 开始批量升级
Future<void> _startBatchUpgrade() async {
final selectedDevices = mhtDeviceUpgradeController.model.blueRawData!
.where((device) => device.selected == true)
.toList();
if (selectedDevices.isEmpty) {
TopSlideNotification.show(context,
text: "请选择要升级的设备".tr, textColor: Colors.red);
return;
}
try {
await _batchManager.startBatchUpgrade(selectedDevices);
} catch (e) {
TopSlideNotification.show(context,
text: "批量升级启动失败: $e".tr, textColor: Colors.red);
}
}
@override
void initState() {
super.initState();
mhtBlueToothController.allSelect.value = false;
flutterBlue = FlutterBluePlus();
checkBluetoothPermission();
mhtBlueToothController.search.value = "";
mhtBlueToothController.currentDeviceMac?.value = "";
BluetoothHelper.listenBluetoothState((isOn) {
mhtBlueToothController.model.bluetooth = isOn;
mhtBlueToothController.updateAll();
if (!isOn && !_isDialogShowing) {
_isDialogShowing = true;
mhtDeviceUpgradeController.model.blueRawData = [];
mhtBlueToothController.model.deviceDataStatus = [];
mhtBlueToothController.updateAll();
showBluetoothNotEnabledDialog(context).then((_) {
_isDialogShowing = false;
});
}
});
initFirmwareVersions(formFieldController);
initDeviceUpgradeType();
}
//扫描设备
Future<void> checkBluetoothPermission() async {
PermissionStatus bluetoothStatus = await Permission.bluetooth.status;
PermissionStatus locationStatus = await Permission.location.status;
if (bluetoothStatus.isGranted && locationStatus.isGranted) {
_startScanning();
_startPeriodicScan();
} else {
_requestBluetoothPermission();
}
}
Future<void> _requestBluetoothPermission() async {
Map<Permission, PermissionStatus> statuses = {};
bool dialogShown = false; // 标记是否弹过权限提示弹窗
if (Platform.isIOS) {
PermissionStatus isBleGranted = await Permission.bluetooth.request();
print('checkBlePermissions-ios, isBleGranted=$isBleGranted');
if (isBleGranted.isGranted) {
// startBluetoothScanning();
_startScanning();
_startPeriodicScan();
} else {
try {
_startScanning();
_startPeriodicScan();
} catch (e) {
TopSlideNotification.show(context,
text: "蓝牙权限未开启,请在设置中开启蓝牙权限".tr,
textColor: themeController.currentColor.sc9);
}
}
} else if (Platform.isAndroid) {
try {
// 检查是否已授权
bool alreadyGranted = await Permission.bluetoothScan.isGranted &&
await Permission.bluetoothConnect.isGranted &&
await Permission.location.isGranted;
if (!alreadyGranted) {
// 弹出自定义提示
showPermissionInfoDialog(
Get.context!, CommonVariables().bluetoothpermissionInfo);
dialogShown = true;
await Future.delayed(const Duration(milliseconds: 300));
// 请求权限
statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.location,
].request();
ef.log("权限状态: $statuses");
} else {
statuses = {
Permission.bluetoothScan: PermissionStatus.granted,
Permission.bluetoothConnect: PermissionStatus.granted,
Permission.location: PermissionStatus.granted,
};
}
} catch (e) {
ef.log("申请权限出错: $e");
} finally {
// 只有真的弹过提示才关闭
if (dialogShown && Get.context != null) {
Navigator.of(Get.context!, rootNavigator: true).pop();
}
}
bool allGranted = statuses[Permission.bluetoothScan]?.isGranted == true &&
statuses[Permission.bluetoothConnect]?.isGranted == true &&
statuses[Permission.location]?.isGranted == true;
if (allGranted) {
_startScanning();
_startPeriodicScan();
} else {
_showPermissionDeniedDialog(context);
}
} else {
TopSlideNotification.show(context,
text: "当前系统不支持蓝牙,无法使用此功能".tr,
textColor: themeController.currentColor.sc9);
}
}
void _showPermissionDeniedDialog(BuildContext context) {
TopSlideNotification.show(context,
text: "应用需要蓝牙和位置权限才能扫描设备。请授予权限。".tr,
textColor: themeController.currentColor.sc9);
}
void _startScanning() async {
try {
if (!mounted || isScanning || !mhtBlueToothController.shouldScan.value)
return;
_scanSubscription?.cancel();
mhtBlueToothController.updateAll();
if (!mhtBlueToothController.model.bluetooth!) return;
if (!isScanning) {
setState(() {
isScanning = true;
});
await FlutterBluePlus.startScan(timeout: Duration(seconds: 10));
_scanSubscription = FlutterBluePlus.scanResults.listen((results) {
if (!mounted) return;
final signalThreshold = mhtBlueToothController.model.singal!;
final searchKey =
mhtBlueToothController.search.value.trim().toLowerCase();
final filteredResults = results.map((r) {
Map<String, dynamic> d = {
"updateTime": DateTime.now().millisecondsSinceEpoch,
"name": r.advertisementData.localName?.trim() ??
r.advertisementData.advName?.trim() ??
r.device.name ??
"",
"rssi": r.rssi,
"device": r.device,
"connectable": r.advertisementData.connectable
};
// 从 manufacturerData 解析设备唯一 ID
Map<int, List<int>> m_d = r.advertisementData.manufacturerData;
String? deviceId;
m_d.forEach((key, value) {
if (value == null || value.isEmpty) return;
if (key == 65517) {
List<int> a = [0, 0, ...value];
advertisDataFormatter(a, d); // 你原来的处理
if (d['adData']?['deviceId'] != null)
deviceId = d['adData']['deviceId'];
} else if (key == 11125 && value.length == 8) {
deviceId = ab2str(value.sublist(2, 8)).toUpperCase();
}
});
d['id'] = deviceId ?? r.device.remoteId.str; // fallback UUID
return BlueToothDataModel.fromScanResult(
r,
1,
bind: false,
name: d['name'],
mac: d['id'],
version: d['adData']?['version'],
rssi: d['rssi'],
selected: mhtBlueToothController.allSelect.value,
);
}).where((d) {
// 信号强度过滤(用 d.scanResult.rssi 或 d.rssi 都可以)
if (d.scanResult.rssi <= signalThreshold) return false;
// 搜索关键字过滤
if (searchKey.isNotEmpty) {
String name = d.name.toLowerCase();
String mac = d.mac.toLowerCase();
if (!name.contains(searchKey) && !mac.contains(searchKey))
return false;
}
// 名称过滤规则,必须包含 deviceType['reg'] 列表中的某个字符串
List<String> regList = [];
if (regList.isNotEmpty) {
String lowerName = d.name.toLowerCase();
bool match =
regList.any((reg) => lowerName.contains(reg.toLowerCase()));
if (!match) return false;
}
// 修正:不要使用外部的 r改从 d.scanResult 读取广告数据
final adv = d.scanResult.advertisementData;
final isTarget = (d.rssi ?? d.scanResult.rssi) > signalThreshold &&
(adv.localName == "AITH-V2" || adv.localName == "SLAVE") &&
adv.manufacturerData.containsKey(0xFFED);
if (!isTarget) return false;
return true;
}).toList();
final currentDevices =
mhtDeviceUpgradeController.model.blueRawData ?? [];
final newDevices = <BlueToothDataModel>[];
// for (var newDevice in filteredResults) {
// final existingIndex =
// currentDevices.indexWhere((d) => d.mac == newDevice.mac);
// if (existingIndex >= 0) {
// currentDevices[existingIndex] = newDevice;
// } else {
// newDevices.add(newDevice);
// }
// }
for (var newDevice in filteredResults) {
final existingIndex =
currentDevices.indexWhere((d) => d.mac == newDevice.mac);
if (existingIndex >= 0) {
// 如果设备已存在更新信号强度rssi
currentDevices[existingIndex].rssi = newDevice.rssi;
} else {
// 如果设备不存在,添加到新设备列表
newDevice.upgradeStatus = APPDeviceUpgrade.nothing.value;
newDevices.add(newDevice);
}
}
setState(() {
mhtDeviceUpgradeController.model.blueRawData = [
...currentDevices,
...newDevices
];
mhtBlueToothController.updateAll();
});
});
await Future.delayed(Duration(seconds: 10));
await FlutterBluePlus.stopScan();
if (mounted) {
setState(() {
isScanning = false;
});
}
}
} catch (e) {
ef.log("$e");
} finally {
setState(() {
isScanning = false;
});
}
}
void _startPeriodicScan() {
_timer = Timer.periodic(Duration(seconds: 3), (timer) {
if (mhtBlueToothController.shouldScan.value && !isScanning) {
removeOldDevices(); // 先清理老旧设备
_startScanning();
}
});
}
void _stopScanning() {
if (isScanning) {
FlutterBluePlus.stopScan();
_scanSubscription?.cancel();
if (mounted) {
setState(() {
isScanning = false;
});
}
}
}
void _stopPeriodicScan() {
_timer?.cancel();
}
@override
void dispose() {
_stopPeriodicScan();
_stopScanning();
_scanSubscription?.cancel();
connectTimer?.cancel();
mhtBlueToothController.stopStatusPolling();
mhtDeviceUpgradeController.model.blueRawData = [];
mhtBlueToothController.model.deviceDataStatus = [];
BluetoothHelper.cancelListener();
super.dispose();
}
bool isTargetDevice(String? name, List<String> keywords) {
if (name == null) return false;
return keywords.any((k) => name.contains(k));
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, boxConstraints) => GestureDetector(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/new_background.png'),
fit: BoxFit.fill,
),
),
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
appBar: AppBar(
iconTheme: IconThemeData(color: themeController.currentColor.sc3),
backgroundColor: Colors.transparent,
automaticallyImplyLeading: false,
titleSpacing: 0,
title: Container(
width: double.infinity,
height: 180.rpx,
child: Stack(
alignment: Alignment.center,
children: [
Text(
'批量升级'.tr,
style: TextStyle(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx,
),
),
Positioned(
left: 0,
child: returnIconButtom,
),
Positioned(
right: 0.rpx,
child: ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding:
EdgeInsets.fromLTRB(30.rpx, 30.rpx, 50.rpx, 30.rpx),
onTap: () {
// 切换筛选条件显示状态
setState(() {
_showFilterPanel = !_showFilterPanel;
});
},
child: Stack(
children: [
SizedBox(
width: 34.rpx,
height: 24.rpx,
child: SvgPicture.asset(
'assets/img/icon/upgrade.svg',
fit: BoxFit.cover,
color: Colors.white,
),
),
// 使用 Obx 监听升级设备数量
Obx(() {
final upgradingCount = mhtDeviceUpgradeController
.model.upgradingDevices?.length ??
0;
return upgradingCount > 0
? Positioned(
right: 0,
top: -2.rpx,
child: Container(
padding: EdgeInsets.all(4.rpx),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text(
upgradingCount.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 12.rpx,
fontWeight: FontWeight.bold,
),
),
),
)
: SizedBox.shrink();
}),
],
),
),
),
],
),
),
actions: [],
centerTitle: false,
),
body: Stack(
children: [
// 主内容区域
SafeArea(
top: true,
child: Padding(
padding:
EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Column(
children: [
Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.transparent,
Colors.transparent,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
borderRadius: BorderRadius.circular(20.rpx),
),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
21.rpx, 5.rpx, 21.rpx, 0.rpx),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Text(
'最小信号强度'.tr,
style: TextStyle(
fontFamily: 'Inter',
color: stringToColor("#FFFFFF"),
fontSize: 26.rpx,
letterSpacing: 0.0,
),
),
Expanded(
child: Obx(() {
return Slider(
activeColor: Color(0xFF1FCC9B),
inactiveColor: Colors.white,
thumbColor: Colors.white,
min: -100,
max: 50,
value: mhtBlueToothController
.model.singal!,
onChanged: (newValue) {
newValue = double.parse(
newValue.toStringAsFixed(0));
mhtBlueToothController
.model.singal = newValue;
mhtDeviceUpgradeController
.model.blueRawData =
mhtDeviceUpgradeController
.model.blueRawData!
?.where((device) =>
device.rssi != null &&
device.rssi! >=
mhtBlueToothController
.model
.singal!)
.toList();
mhtBlueToothController
.updateAll();
},
);
}),
),
Obx(() {
return Text(
'${mhtBlueToothController.model.singal!.toInt()}',
style: TextStyle(
fontFamily: 'Inter',
color: stringToColor("#FFFFFF"),
fontSize: 26.rpx,
letterSpacing: 0.0,
),
);
}),
].divide(SizedBox(width: 30.rpx)),
),
),
),
Container(
width: double.infinity,
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
21.rpx, 0.rpx, 0.rpx, 5.rpx),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
Theme(
data: Theme.of(context).copyWith(
splashColor:
stringToColor("#011D33"),
highlightColor:
stringToColor("#011D33"),
),
child: ScrollbarTheme(
data: ScrollbarThemeData(
thumbColor:
MaterialStateProperty.all(
Colors.transparent),
trackColor:
MaterialStateProperty.all(
Colors.transparent),
trackBorderColor:
MaterialStateProperty.all(
Colors.transparent),
),
child: ValueListenableBuilder(
valueListenable:
formFieldController,
builder: (c, a, s) =>
FlutterFlowDropDown<String>(
controller:
formFieldController,
options:
mhtDeviceUpgradeController
.firmwareList!
.map<String>((d) =>
"${d.version}")
.toList(),
optionLabels:
mhtDeviceUpgradeController
.firmwareList!
.map<String>((d) =>
"${d.version}")
.toList(),
onChanged: (val) {
var selectedVersion =
mhtDeviceUpgradeController
.firmwareList!
.firstWhere(
(d) => d.version == val,
);
if (selectedVersion !=
null) {
mhtDeviceUpgradeController
.selectVerison =
selectedVersion;
final MHTBlueToothController
_btController =
Get.find();
_btController
.currentUpgradeVersion =
mhtDeviceUpgradeController
.selectVerison!
.version!;
_btController
.currentUpgradeName =
mhtDeviceUpgradeController
.selectVerison!
.fileName!;
_btController
.currentUpgradeUrl =
mhtDeviceUpgradeController
.selectVerison!
.downloadUrl!;
}
},
width: 300.rpx,
height: 81.rpx,
maxHeight: 300.rpx,
textStyle: TextStyle(
fontSize: 28.rpx,
overflow:
TextOverflow.ellipsis,
color: Colors.black,
),
hintText: '选择固件版本'.tr,
icon: Icon(
Icons
.keyboard_arrow_down_rounded,
color: Color(0xFF929699),
size: 30.rpx,
),
fillColor: Colors.white,
elevation: 2,
borderColor:
Colors.transparent,
borderWidth: 2,
borderRadius: AppConstants()
.normal_container_radius,
margin: EdgeInsetsDirectional
.fromSTEB(32.rpx, 8.rpx,
22.rpx, 8.rpx),
hidesUnderline: true,
isOverButton: false,
isSearchable: false,
isMultiSelect: false,
),
),
),
),
ClickableContainer(
backgroundColor:
Colors.transparent,
highlightColor:
Colors.transparent,
padding: EdgeInsets.all(0),
onTap: () {
mhtBlueToothController
.autoUpgrade.value =
!mhtBlueToothController
.autoUpgrade.value;
mhtBlueToothController
.updateAll();
},
child: Obx(() {
double h = 33.rpx;
bool check =
mhtBlueToothController
.autoUpgrade.value;
return Container(
height: 33.rpx,
child: Row(
children: [
AspectRatio(
aspectRatio: 1,
child: Center(
child: Container(
height: h,
width: h,
decoration:
BoxDecoration(
borderRadius:
BorderRadius
.circular(
h / 2),
border:
Border.all(
width: check
? 1
: 0.5,
color: Color(
0xFFC8CBD2),
),
),
child: check
? Center(
child:
ClipOval(
child:
Container(
width:
h * 0.6,
height:
h * 0.6,
color:
const Color(0xFF6BFDAC),
),
),
)
: null,
),
),
),
Text(
"自动升级".tr,
style: TextStyle(
fontFamily: 'Inter',
color:
stringToColor(
"#FFFFFF"),
fontSize: 26.rpx,
letterSpacing: 0.0,
),
),
].divide(SizedBox(
width: 10.rpx)),
));
})),
].divide(SizedBox(width: 30.rpx)),
),
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.fromLTRB(
0.rpx, 0.rpx, 20.rpx, 0.rpx),
onTap: () {
//刷新信号强度以及重置设备录入强度排行
},
child: SizedBox(
width: 28.rpx,
height: 28.rpx,
child: SvgPicture.asset(
'assets/img/icon/refresh.svg',
fit: BoxFit.cover,
color: Colors.white,
),
),
),
],
),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 0.rpx, 0, 0.rpx),
child: Container(
width: double.infinity,
decoration: BoxDecoration(),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(
19.rpx, 0, 0, 0),
child: Obx(() {
return Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'匹配出的外围设备'.tr +
"${getRemainingDeviceCount()}",
style: TextStyle(
fontFamily: 'Inter',
fontSize: 30.rpx,
letterSpacing: 0.0,
color: themeController
.currentColor.sc3,
),
),
Row(
children: [
ClickableContainer(
backgroundColor:
Colors.transparent,
highlightColor:
Colors.transparent,
padding: EdgeInsets.all(0),
onTap: () {
mhtBlueToothController
.allSelect.value =
!mhtBlueToothController
.allSelect.value;
if (mhtBlueToothController
.allSelect.value) {
for (var device
in mhtDeviceUpgradeController
.model
.blueRawData!) {
device.selected = true;
}
} else {
for (var device
in mhtDeviceUpgradeController
.model
.blueRawData!) {
device.selected = false;
}
}
mhtBlueToothController
.updateAll();
},
child: Obx(() {
double h = 33.rpx;
bool check =
mhtBlueToothController
.allSelect.value;
return Container(
height: 33.rpx,
child: Row(
children: [
Text(
mhtBlueToothController
.allSelect
.value ==
false
? "全选".tr
: "取消全选".tr,
style: TextStyle(
fontFamily:
'Inter',
color:
stringToColor(
"#85F5FF"),
fontSize: 26.rpx,
letterSpacing:
0.0,
),
),
].divide(SizedBox(
width: 10.rpx)),
));
}),
),
],
)
],
);
}),
),
),
),
//设备列表
// Obx(() {
// if (mhtDeviceUpgradeController
// .model.blueRawData!.isNotEmpty) {
// final allDevices = mhtDeviceUpgradeController
// .model.blueRawData!;
// final upgradingDevices =
// mhtDeviceUpgradeController
// .model.upgradingDevices ??
// [];
// final upgradingDevicesMacs = upgradingDevices
// .map((device) => device.mac)
// .toList();
// // 当前选择的升级版本
// final selectedVersion =
// mhtDeviceUpgradeController.selectVerison;
// // 过滤条件:
// // 1. 不在正在升级列表中
// // 2. 且版本号不等于当前选择的版本(同版本不需要升级)
// var filteredDevices =
// allDevices.where((device) {
// // bool notUpgrading = !upgradingDevicesMacs
// // .contains(device.mac);
// bool notUpgrading = true;
// //todo wyf 恢复
// // bool needUpgrade =
// // device.version.toString() !=
// // selectedVersion!.version;
// bool needUpgrade = true;
// return notUpgrading && needUpgrade;
// }).toList();
// // 若需要过滤设备类型,可继续使用你的方法
// var deviceList =
// filterDeviceType(filteredDevices);
// // 按信号强度排序
// final sortedList = deviceList
// ..sort(
// (a, b) => b.rssi!.compareTo(a.rssi!));
// return Expanded(
// child: Container(
// width: double.infinity,
// child: SingleChildScrollView(
// child: Column(
// mainAxisSize: MainAxisSize.max,
// children: [
// ...sortedList
// .map((device) {
// return UpgradeDevice(
// bleDevice: device,
// deviceType: 1,
// );
// })
// .toList()
// .divide(
// SizedBox(height: 30.rpx))
// .addToEnd(
// SizedBox(height: 30.rpx)),
// ],
// ),
// ),
// ),
// );
// }
// return Container();
// })
Obx(() {
final allDevices = mhtDeviceUpgradeController
.model.blueRawData ??
[];
final upgradingDevices =
mhtDeviceUpgradeController
.model.upgradingDevices ??
[];
// 合并列表显示
// List<BlueToothDataModel> displayDevices = [
// ...allDevices.map((d) {
// final upgrading =
// upgradingDevices.firstWhereOrNull(
// (u) => u.mac == d.mac);
// return upgrading ?? d;
// }),
// // 如果有升级设备不在 rawData 中,也加上
// ...upgradingDevices
// .where((u) => !allDevices
// .any((d) => d.mac == u.mac))
// .toList(),
// ];
List<BlueToothDataModel> displayDevices = [
// 用 upgrading 覆盖 raw 中的相同 mac
...allDevices.map((d) {
final u = upgradingDevices.firstWhereOrNull(
(x) => x.mac == d.mac);
return u ?? d;
}),
// 加入那些只在 upgradingDevices 中但不在 raw 的
...upgradingDevices.where((u) =>
!allDevices.any((d) => d.mac == u.mac)),
];
// 可以按信号强度排序
displayDevices.sort((a, b) =>
(b.rssi ?? 0).compareTo(a.rssi ?? 0));
return Expanded(
child: Container(
width: double.infinity,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
...displayDevices
.map((device) {
return UpgradeDevice(
bleDevice: device,
deviceType: 1,
);
})
.toList()
.divide(SizedBox(height: 30.rpx))
.addToEnd(
SizedBox(height: 30.rpx)),
],
),
),
),
);
}),
].divide(SizedBox(height: 30.rpx)),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 0.rpx, 0, 30.rpx),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.rpx),
border: Border.all(
color: themeController.currentColor.sc4
.withOpacity(0.5),
width: AppConstants().border_width,
),
),
child: Padding(
padding: EdgeInsets.only(bottom: 0.rpx),
child: CustomCard(
borderRadius: 16.rpx,
gradientDirection: GradientDirection.vertical,
onTap: () {
String deviceCountFlag =
judgeUpgradeDeviceCount();
if (deviceCountFlag != null &&
deviceCountFlag != "") {
NewTopSlideNotification.show(
text: deviceCountFlag,
textColor:
themeController.currentColor.sc9);
return;
}
mhtDeviceUpgradeController.startUpgrade();
},
colors: const [
Color(0xFFFCFCFC),
Color(0xFFF8FAF9),
Color(0XFFECF6F3),
Color(0XFFD9F0E9),
Color(0xFFCEECE3)
],
child: Container(
width: double.infinity,
height: 90.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
),
child: Text("升级".tr,
style: TextStyle(
color: const Color(0xFF003058),
fontSize: 26.rpx)),
),
)),
),
),
].divide(SizedBox(height: 30.rpx)),
),
),
),
// 筛选条件面板 - 从AppBar下方开始显示遮住主内容
if (_showFilterPanel)
Positioned.fill(
top: 0.rpx, // 从AppBar下方开始
child: Container(
color: Colors.black.withOpacity(0.5), // 半透明遮罩
child: GestureDetector(
onTap: () {
// 点击遮罩区域关闭筛选面板
setState(() {
_showFilterPanel = false;
});
},
child: Container(
color: Colors.transparent,
child: Column(
children: [
// 筛选条件内容
Container(
width: double.infinity,
margin:
EdgeInsets.symmetric(horizontal: 30.rpx),
decoration: BoxDecoration(
color: stringToColor("#003058"),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(12.rpx),
bottomRight: Radius.circular(12.rpx),
topLeft: Radius.circular(12.rpx),
topRight: Radius.circular(12.rpx),
),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 8.rpx,
offset: Offset(0, 4.rpx),
),
],
),
child: getQueryList(), // 使用原来的筛选条件内容
),
// 剩余空间可以点击关闭
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_showFilterPanel = false;
});
},
child: Container(
color: Colors.transparent,
),
),
),
],
),
),
),
),
),
],
),
),
),
),
);
}
}