AIR版的功能添加
This commit is contained in:
@@ -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<BleDeviceDetailPage> createState() => _BleDeviceDetailPageState();
|
||||
@@ -515,7 +524,9 @@ class _BleDeviceDetailPageState extends State<BleDeviceDetailPage> {
|
||||
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<BleDeviceDetailPage> {
|
||||
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<BleDeviceDetailPage> {
|
||||
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<BleDeviceDetailPage> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'设备配置 (0x05)',
|
||||
'设备配置',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
||||
@@ -74,6 +74,10 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
/// 当前缓存的 siteId,用于判断是否真的发生了变化
|
||||
int? _currentSiteId;
|
||||
|
||||
/// 🔥 下拉刷新计数器:变更时联动重建"全部"标签下的机器人/无人机场内嵌列表,
|
||||
/// 使其与统计卡片(DeviceStatusBloc)同步刷新,避免统计数字与实际卡片对不上
|
||||
int _refreshTick = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -616,9 +620,16 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
// 🔥 同步刷新:统计卡片(DeviceStatusBloc) + 下方机器人列表(RobotListBloc)
|
||||
// + 无人机场列表(DroneStationBloc)。三者数据源相互独立,只刷统计会导致
|
||||
// 数字与实际卡片对不上,故用 _refreshTick 变更内嵌列表的 ValueKey 强制
|
||||
// 重建对应 BlocProvider,使其重新拉取数据。
|
||||
context.read<DeviceListBloc.DeviceStatusBloc>().add(
|
||||
const DeviceListEvent.DeviceStatusRefresh(),
|
||||
);
|
||||
if (state.selectedType == 'all') {
|
||||
setState(() => _refreshTick++);
|
||||
}
|
||||
},
|
||||
color: context.appColors.primary,
|
||||
child: ListView(
|
||||
@@ -639,7 +650,7 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
_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<DeviceStatusView> {
|
||||
|
||||
return BlocProvider(
|
||||
// 🔥 电站切换时通过 key 变化强制重建 BlocProvider,重新用新 siteId 加载
|
||||
key: ValueKey('embedded_robot_$siteId'),
|
||||
key: ValueKey('embedded_robot_${siteId}_$_refreshTick'),
|
||||
create: (_) =>
|
||||
sl<RobotListBloc>()..add(RobotListLoadData(siteId: siteId)),
|
||||
child: BlocConsumer<RobotListBloc, RobotListState>(
|
||||
@@ -757,7 +768,7 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
debugPrint('❌ [全部-EmbeddedRobotList] 未提取到时间戳');
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('设备名称格式错误,无法提取时间戳'),
|
||||
content: Text('设备名称异常,暂时无法连接'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
@@ -967,12 +978,12 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
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<DeviceStatusView> {
|
||||
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<DeviceStatusView> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BleDeviceDetailPage(device: connectedDevice),
|
||||
builder: (_) => BleDeviceDetailPage(
|
||||
device: connectedDevice,
|
||||
displayName: deviceName,
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -1418,7 +1423,10 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BleDeviceDetailPage(device: device),
|
||||
builder: (_) => BleDeviceDetailPage(
|
||||
device: device,
|
||||
displayName: deviceName,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -1449,7 +1457,7 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
dialogShown = true;
|
||||
return AlertDialog(
|
||||
title: const Text('未找到设备'),
|
||||
content: const Text('请确认机器已上线并打开蓝牙了'),
|
||||
content: const Text('暂未匹配到该设备,稍后重试'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -1495,7 +1503,10 @@ class _DeviceStatusViewState extends State<DeviceStatusView> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BleDeviceDetailPage(device: result.device),
|
||||
builder: (_) => BleDeviceDetailPage(
|
||||
device: result.device,
|
||||
displayName: deviceName,
|
||||
),
|
||||
),
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -669,7 +669,7 @@ class _RobotListViewState extends State<RobotListView> {
|
||||
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<RobotListView> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BleDeviceDetailPage(device: connectedDevice),
|
||||
builder: (_) => BleDeviceDetailPage(
|
||||
device: connectedDevice,
|
||||
displayName: deviceName,
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -848,7 +851,10 @@ class _RobotListViewState extends State<RobotListView> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BleDeviceDetailPage(device: device),
|
||||
builder: (_) => BleDeviceDetailPage(
|
||||
device: device,
|
||||
displayName: deviceName,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -881,7 +887,7 @@ class _RobotListViewState extends State<RobotListView> {
|
||||
dialogShown = true;
|
||||
return AlertDialog(
|
||||
title: const Text('未找到设备'),
|
||||
content: const Text('请确认机器已上线并打开蓝牙了'),
|
||||
content: const Text('暂未匹配到该设备,稍后重试'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -933,7 +939,10 @@ class _RobotListViewState extends State<RobotListView> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BleDeviceDetailPage(device: dev!),
|
||||
builder: (_) => BleDeviceDetailPage(
|
||||
device: dev!,
|
||||
displayName: deviceName,
|
||||
),
|
||||
),
|
||||
);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user