diff --git a/lib/features/v2/device_list/presentation/pages/ble_device_detail_page.dart b/lib/features/v2/device_list/presentation/pages/ble_device_detail_page.dart index bf941a81..2abf64c1 100644 --- a/lib/features/v2/device_list/presentation/pages/ble_device_detail_page.dart +++ b/lib/features/v2/device_list/presentation/pages/ble_device_detail_page.dart @@ -20,7 +20,16 @@ class BleDeviceDetailPage extends StatefulWidget { final BluetoothDevice device; final ScanResult? scanResult; - const BleDeviceDetailPage({super.key, required this.device, this.scanResult}); + /// 后端设备长名称(如 MC700PLUS-CN-JS-1760408682847-0000002A-A9), + /// 由列表页跳转时传入;为空时回退到蓝牙广播名 + final String? displayName; + + const BleDeviceDetailPage({ + super.key, + required this.device, + this.scanResult, + this.displayName, + }); @override State createState() => _BleDeviceDetailPageState(); @@ -515,7 +524,9 @@ class _BleDeviceDetailPageState extends State { final advData = widget.scanResult?.advertisementData; // 优先使用广告数据中的名称(含扫描响应),手机蓝牙列表也是这样显示的 final name = - _resolvedName ?? + (widget.displayName?.isNotEmpty == true + ? widget.displayName! + : _resolvedName) ?? (advData?.advName.isNotEmpty == true ? advData!.advName : (device.platformName.isNotEmpty @@ -603,14 +614,6 @@ class _BleDeviceDetailPageState extends State { color: context.appColors.textPrimary, ), ), - const SizedBox(height: 4), - Text( - '${widget.device.remoteId}', - style: TextStyle( - fontSize: 12, - color: context.appColors.textTertiary, - ), - ), ], ), ), @@ -621,7 +624,6 @@ class _BleDeviceDetailPageState extends State { Divider(height: 1, color: context.appColors.divider), const SizedBox(height: 12), _buildInfoRow('设备名称', name), - _buildInfoRow('设备ID', '${widget.device.remoteId}'), if (scanResult != null) ...[ _buildInfoRow('信号强度', '${scanResult.rssi} dBm'), _buildInfoRow( @@ -1237,7 +1239,7 @@ class _BleDeviceDetailPageState extends State { children: [ Expanded( child: Text( - '设备配置 (0x05)', + '设备配置', style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, diff --git a/lib/features/v2/device_list/presentation/pages/device_status_page.dart b/lib/features/v2/device_list/presentation/pages/device_status_page.dart index c116c29f..ad56e4cd 100644 --- a/lib/features/v2/device_list/presentation/pages/device_status_page.dart +++ b/lib/features/v2/device_list/presentation/pages/device_status_page.dart @@ -74,6 +74,10 @@ class _DeviceStatusViewState extends State { /// 当前缓存的 siteId,用于判断是否真的发生了变化 int? _currentSiteId; + /// 🔥 下拉刷新计数器:变更时联动重建"全部"标签下的机器人/无人机场内嵌列表, + /// 使其与统计卡片(DeviceStatusBloc)同步刷新,避免统计数字与实际卡片对不上 + int _refreshTick = 0; + @override void initState() { super.initState(); @@ -616,9 +620,16 @@ class _DeviceStatusViewState extends State { return RefreshIndicator( onRefresh: () async { + // 🔥 同步刷新:统计卡片(DeviceStatusBloc) + 下方机器人列表(RobotListBloc) + // + 无人机场列表(DroneStationBloc)。三者数据源相互独立,只刷统计会导致 + // 数字与实际卡片对不上,故用 _refreshTick 变更内嵌列表的 ValueKey 强制 + // 重建对应 BlocProvider,使其重新拉取数据。 context.read().add( const DeviceListEvent.DeviceStatusRefresh(), ); + if (state.selectedType == 'all') { + setState(() => _refreshTick++); + } }, color: context.appColors.primary, child: ListView( @@ -639,7 +650,7 @@ class _DeviceStatusViewState extends State { _buildDroneStationList( context, embedded: true, - key: ValueKey('embedded_drone_station_$_currentSiteId'), + key: ValueKey('embedded_drone_station_${_currentSiteId}_$_refreshTick'), ), // 🔥 普通设备列表(仅类型 tab 生效,"全部"模式下 filteredByType 为空) ...filteredDevices @@ -674,7 +685,7 @@ class _DeviceStatusViewState extends State { return BlocProvider( // 🔥 电站切换时通过 key 变化强制重建 BlocProvider,重新用新 siteId 加载 - key: ValueKey('embedded_robot_$siteId'), + key: ValueKey('embedded_robot_${siteId}_$_refreshTick'), create: (_) => sl()..add(RobotListLoadData(siteId: siteId)), child: BlocConsumer( @@ -757,7 +768,7 @@ class _DeviceStatusViewState extends State { debugPrint('❌ [全部-EmbeddedRobotList] 未提取到时间戳'); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: Text('设备名称格式错误,无法提取时间戳'), + content: Text('设备名称异常,暂时无法连接'), duration: Duration(seconds: 2), ), ); @@ -967,12 +978,12 @@ class _DeviceStatusViewState extends State { BuildContext context, DeviceListState.DeviceStatusLoaded state, ) { - // 从实际设备列表计算统计数据(不再使用硬编码的假数据) + // 从实际设备列表计算统计数据(设备状态仅有"在线/离线"两种,接口不会返回"异常", + // 故不再统计恒为 0 的"告警"项) final devices = state.devices; final totalCount = devices.length; final onlineCount = devices.where((d) => d.status == '在线').length; - final exceptionCount = devices.where((d) => d.status == '异常').length; - final offlineCount = totalCount - onlineCount - exceptionCount; + final offlineCount = totalCount - onlineCount; return Container( margin: const EdgeInsets.symmetric(horizontal: 16.0), @@ -1008,15 +1019,6 @@ class _DeviceStatusViewState extends State { textColor: context.appColors.success, ), Container(width: 1, height: 40, color: context.appColors.divider), - _buildStatItem( - value: exceptionCount.toString(), - label: AppLocalizations.of( - context, - ).translate('device_list_v2.alarm'), - dotColor: context.appColors.warning, - textColor: context.appColors.warning, - ), - Container(width: 1, height: 40, color: context.appColors.divider), _buildStatItem( value: offlineCount.toString(), label: AppLocalizations.of( @@ -1356,7 +1358,10 @@ class _DeviceStatusViewState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => BleDeviceDetailPage(device: connectedDevice), + builder: (_) => BleDeviceDetailPage( + device: connectedDevice, + displayName: deviceName, + ), ), ); return; @@ -1418,7 +1423,10 @@ class _DeviceStatusViewState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => BleDeviceDetailPage(device: device), + builder: (_) => BleDeviceDetailPage( + device: device, + displayName: deviceName, + ), ), ); } else { @@ -1449,7 +1457,7 @@ class _DeviceStatusViewState extends State { dialogShown = true; return AlertDialog( title: const Text('未找到设备'), - content: const Text('请确认机器已上线并打开蓝牙了'), + content: const Text('暂未匹配到该设备,稍后重试'), actions: [ TextButton( onPressed: () { @@ -1495,7 +1503,10 @@ class _DeviceStatusViewState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => BleDeviceDetailPage(device: result.device), + builder: (_) => BleDeviceDetailPage( + device: result.device, + displayName: deviceName, + ), ), ); break; diff --git a/lib/features/v2/device_list/presentation/pages/robot_list_page.dart b/lib/features/v2/device_list/presentation/pages/robot_list_page.dart index 41a6f954..34475753 100644 --- a/lib/features/v2/device_list/presentation/pages/robot_list_page.dart +++ b/lib/features/v2/device_list/presentation/pages/robot_list_page.dart @@ -669,7 +669,7 @@ class _RobotListViewState extends State { debugPrint('❌ [RobotListPage] 无法从设备名中提取时间戳: ${robot.name}'); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('设备名格式异常,无法进行蓝牙连接'), + content: Text('设备名称异常,暂时无法连接'), backgroundColor: context.appColors.warning, ), ); @@ -767,7 +767,10 @@ class _RobotListViewState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => BleDeviceDetailPage(device: connectedDevice), + builder: (_) => BleDeviceDetailPage( + device: connectedDevice, + displayName: deviceName, + ), ), ); return; @@ -848,7 +851,10 @@ class _RobotListViewState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => BleDeviceDetailPage(device: device), + builder: (_) => BleDeviceDetailPage( + device: device, + displayName: deviceName, + ), ), ); } else { @@ -881,7 +887,7 @@ class _RobotListViewState extends State { dialogShown = true; return AlertDialog( title: const Text('未找到设备'), - content: const Text('请确认机器已上线并打开蓝牙了'), + content: const Text('暂未匹配到该设备,稍后重试'), actions: [ TextButton( onPressed: () { @@ -933,7 +939,10 @@ class _RobotListViewState extends State { Navigator.push( context, MaterialPageRoute( - builder: (_) => BleDeviceDetailPage(device: dev!), + builder: (_) => BleDeviceDetailPage( + device: dev!, + displayName: deviceName, + ), ), ); break;