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