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'; import 'package:flutter/services.dart'; class DeviceUpgrade extends StatefulWidget { DeviceUpgrade({super.key}); @override State createState() => _DeviceUpgradeState(); } class _DeviceUpgradeState extends State { MHTBlueToothController mhtBlueToothController = Get.find(); GlobalController globalController = Get.find(); UserInfoController userInfoController = Get.find(); ThemeController themeController = Get.find(); late FlutterBluePlus 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; StreamSubscription>? _scanSubscription; var formFieldController = FormFieldController(null); MHTDeviceUpgradeController mhtDeviceUpgradeController = Get.find(); final BatchUpgradeManager _batchManager = BatchUpgradeManager(); bool _isPopupOpen = false; // 新增状态:控制展开/收起 bool _isExpanded = false; bool _showFilterPanel = false; // 开始批量升级 Future _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 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 { Map 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 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> m_d = r.advertisementData.manufacturerData; String? deviceId; m_d.forEach((key, value) { if (value == null || value.isEmpty) return; if (key == 65517) { List 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 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 = []; // 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 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( systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, // 状态栏背景色 statusBarIconBrightness: Brightness.light, // 图标颜色(Android) statusBarBrightness: Brightness.light, // 图标颜色(iOS) ), 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( controller: formFieldController, options: mhtDeviceUpgradeController .firmwareList! .map((d) => "${d.version}") .toList(), optionLabels: mhtDeviceUpgradeController .firmwareList! .map((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 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 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, ), ), ), ], ), ), ), ), ), ], ), ), ), ), ); } }