From 04e54871c93e5d833d8fa1743ba81b95c6d1ec03 Mon Sep 17 00:00:00 2001 From: mmc <1556375442@qq.com> Date: Sat, 7 Mar 2026 20:03:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=BA=E5=99=A8=E7=8A=B6=E6=80=81=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E5=A2=9E=E5=8A=A0=E5=AE=9A=E6=97=B6=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/path_http_datasource_impl.dart | 1 - .../pages/running_status_page.dart | 88 +++++++++++++++++-- .../widgets/map/testmap_pages.dart | 75 ++++++++++++---- 3 files changed, 140 insertions(+), 24 deletions(-) diff --git a/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart b/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart index 3f1c9bee..96064cd0 100644 --- a/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart +++ b/lib/features/devices/data/datasources/impl/path_http_datasource_impl.dart @@ -22,7 +22,6 @@ class PathHttpDatasourceImpl implements PathHttpDatasource { // 2. 格式化打印JSON(带缩进,清晰展示嵌套结构) final jsonString = const JsonEncoder.withIndent(' ').convert(body); - print('完整JSON请求体:\n$jsonString'); final _jsonString = jsonEncode(body); print('完整JSON请求体:\n$jsonString'); diff --git a/lib/features/home/presentation/pages/running_status_page.dart b/lib/features/home/presentation/pages/running_status_page.dart index a6bbc82a..1247df5f 100644 --- a/lib/features/home/presentation/pages/running_status_page.dart +++ b/lib/features/home/presentation/pages/running_status_page.dart @@ -18,6 +18,9 @@ import '../../../devices/presentation/bloc/devices_cubit.dart'; import '../../../devices/presentation/bloc/device_status_bloc.dart'; import '../../../devices/presentation/bloc/device_status_state.dart'; +// 配置:数据超时时间(5秒) +const int DATA_TIMEOUT_SECONDS = 5; + class RunningStatusPage extends StatefulWidget { const RunningStatusPage({super.key}); @@ -48,6 +51,41 @@ class _RunningStatusPageState extends State { double _timeIndex = 0; + // 新增:超时检测相关变量 + Timer? _dataTimeoutTimer; + bool _isDataTimeout = false; // 标记是否数据超时 + + @override + void initState() { + super.initState(); + // 初始化超时计时器 + _startDataTimeoutTimer(); + } + + @override + void dispose() { + // 销毁计时器,防止内存泄漏 + _dataTimeoutTimer?.cancel(); + super.dispose(); + } + + // 启动/重置数据超时计时器 + void _startDataTimeoutTimer() { + // 先取消现有计时器 + _dataTimeoutTimer?.cancel(); + + // 启动新计时器:超过指定时间未收到数据则标记为超时 + _dataTimeoutTimer = Timer(Duration(seconds: DATA_TIMEOUT_SECONDS), () { + if (mounted) { + setState(() { + _isDataTimeout = true; + // 超时后清空历史图表数据(可选) + _resetChartData(); + }); + } + }); + } + // 核心修复:数据点X轴坐标强制映射为0-5(对应6个标签),保证一一对应 List _getMappedSpots(List data) { final List mapped = []; @@ -74,6 +112,11 @@ class _RunningStatusPageState extends State { if (currentDevice != null) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("数据刷新成功!"), duration: Duration(seconds: 1))); + // 刷新后重置超时状态 + if (_isDataTimeout) { + setState(() => _isDataTimeout = false); + } + _startDataTimeoutTimer(); } else { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("暂无设备,无法刷新"), duration: Duration(seconds: 1))); } @@ -375,6 +418,11 @@ class _RunningStatusPageState extends State { // ====================== 图表视图 ====================== Widget _buildChartContentView(DeviceStatusState state) { + // 新增:如果数据超时,直接显示loading + if (_isDataTimeout) { + return const Center(child: CircularProgressIndicator(color: Color(0xFF1677FF), strokeWidth: 4)); + } + if (state is! DeviceStatusUpdated) { return const Center( child: CircularProgressIndicator( @@ -602,6 +650,11 @@ class _RunningStatusPageState extends State { // ====================== 卡片视图 ====================== Widget _buildCardContentView(DeviceStatusState state) { + // 新增:如果数据超时,直接显示loading + if (_isDataTimeout) { + return const Center(child: CircularProgressIndicator(color: Color(0xFF1677FF), strokeWidth: 4)); + } + if (state is DeviceStatusUpdated) { return SingleChildScrollView( padding: const EdgeInsets.all(16), @@ -766,11 +819,12 @@ class _RunningStatusPageState extends State { BlocBuilder( builder: (context, state) { - String qual = '--'; - String satelliteCnt = '--'; - String headingStatus = "--"; + // 新增:超时状态下显示-- + String qual = _isDataTimeout ? '--' : '--'; + String satelliteCnt = _isDataTimeout ? '--' : '--'; + String headingStatus = _isDataTimeout ? "--" : "--"; - if (state is DeviceStatusUpdated) { + if (!_isDataTimeout && state is DeviceStatusUpdated) { headingStatus = state.status.headingStatus == 0 ? '未初始化' : '已初始化'; int qualValue = 0; try { @@ -780,7 +834,13 @@ class _RunningStatusPageState extends State { } qual = LocationUtils.parseLocationQuality(qualValue); satelliteCnt = state.status.satelliteCnt.toString(); - } else if (state is DeviceStatusError) { + + // 收到新数据,重置超时计时器和状态 + _startDataTimeoutTimer(); + if (_isDataTimeout) { + setState(() => _isDataTimeout = false); + } + } else if (!_isDataTimeout && state is DeviceStatusError) { qual = '-'; satelliteCnt = '-'; headingStatus = '-'; @@ -873,7 +933,7 @@ class _RunningStatusPageState extends State { }); } - if (state is DeviceStatusUpdated) { + if (!_isDataTimeout && state is DeviceStatusUpdated) { debugPrint('📈 [UI] 检测到 Updated 状态,准备追加图表数据'); _appendChartData(state); } @@ -886,7 +946,21 @@ class _RunningStatusPageState extends State { ); } - void _resetChartData() {} + // 新增:清空图表历史数据 + void _resetChartData() { + _leftMeasureHistory.clear(); + _rightMeasureHistory.clear(); + _leftTargetHistory.clear(); + _rightTargetHistory.clear(); + _leftCurrentHistory.clear(); + _rightCurrentHistory.clear(); + _leftTempHistory.clear(); + _rightTempHistory.clear(); + _knifeHistory.clear(); + _chipTempHistory.clear(); + _voltageHistory.clear(); + _timeIndex = 0; + } } // ====================== 带动画的圆形仪表盘 Widget ====================== diff --git a/lib/features/home/presentation/widgets/map/testmap_pages.dart b/lib/features/home/presentation/widgets/map/testmap_pages.dart index b744638c..c7fbecb7 100644 --- a/lib/features/home/presentation/widgets/map/testmap_pages.dart +++ b/lib/features/home/presentation/widgets/map/testmap_pages.dart @@ -70,7 +70,6 @@ class MapPageEnterprise extends StatefulWidget { class _MapPageEnterpriseState extends State { final _dispatcher = sl(); - late StreamSubscription _sub; bool _isRefreshing = false; // 新增:页面刷新状态标志 bool _isVideoDialogOpen = false; // 控制视频弹窗显示 String _videoStreamUrl = ""; @@ -180,14 +179,21 @@ class _MapPageEnterpriseState extends State { // 计算边界 final bounds = calculateBounds(points); if (bounds == null) return; + final currentZoom = _mapController.camera?.zoom ?? 18.0; // 移动地图到边界中心(自动适配缩放级别) - _mapController.fitBounds( - bounds, - options: FitBoundsOptions( - padding: const EdgeInsets.all(50), // 边缘留白(避免内容贴边) - //maxZoom: 18, // 最大缩放级别(防止过度放大) - ), + //_mapController.fitBounds( + // bounds, + + // options: FitBoundsOptions( + // padding: const EdgeInsets.all(50), // 边缘留白(避免内容贴边) + // //maxZoom: 18, // 最大缩放级别(防止过度放大) + // ), + //); + + _mapController.move( + bounds.center, // 边界中心点 + currentZoom, // 保留当前缩放比例 ); print('地图已移动到绘制内容中心,边界范围:$bounds'); @@ -204,6 +210,17 @@ class _MapPageEnterpriseState extends State { return null; } + bool __isValidLatLng(LatLng? latLng) { + if (latLng == null) return false; + // 排除赤道0,0坐标,同时校验经纬度范围(避免非法值) + return latLng.latitude != 0.0 && + latLng.longitude != 0.0 && + latLng.latitude >= -90 && + latLng.latitude <= 90 && + latLng.longitude >= -180 && + latLng.longitude <= 180; + } + bool _isValidLatLng(double lat, double lng) { return lat != 0 && lng != 0 && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180; } @@ -820,7 +837,6 @@ class _MapPageEnterpriseState extends State { _positionSub?.cancel(); _traceManager.reset(); _mapController.dispose(); - _sub.cancel(); super.dispose(); } @@ -1160,20 +1176,20 @@ class _MapPageEnterpriseState extends State { } final gcjPoint = wgs84ToGcj02(lat, lng); - // 关键:判断Widget是否还挂载,避免空指针 + final initCenter = bd09ToGcj02( + '120.81992468426961', // 经度 + '32.04532826114155', + ); + _currentLatLng = gcjPoint; // ✅ 状态变量在setState内更新 return FlutterMap( mapController: _mapController, options: MapOptions( - initialCenter: _currentLatLng ?? const LatLng(39.9042, 116.4074), + initialCenter: __isValidLatLng(_currentLatLng) ? _currentLatLng! : initCenter, initialZoom: 18, - // 1. 调整最大缩放级别(匹配高德实际支持的上限) maxZoom: 18, - // 2. 增加最小缩放级别(可选,提升体验) minZoom: 3, - // 3. 启用连续缩放(支持滚轮精细缩放) enableScrollWheel: true, - // 禁止地图点击事件(避免和中心标冲突) onTap: (_, __) {}, // 空实现,禁用地图点击响应 ), children: [ @@ -1283,10 +1299,10 @@ class _MapPageEnterpriseState extends State { ); }).toList(), ), - if (gctracePoint!.isNotEmpty) + //开始作业之后 + if (gctracePoint!.isNotEmpty && isStartWork) PolylineLayer( polylines: [ - // 已绘制的障碍物点连线 for (int i = 0; i < gctracePoint!.length - 1; i++) Polyline( points: [gctracePoint![i], gctracePoint![i + 1]], @@ -2309,6 +2325,33 @@ List batchWgs84ToGcj02(List wgs84Points) { }).toList(); } +LatLng bd09ToGcj02(dynamic bdLng, dynamic bdLat) { + // 1. 先将字符串转为double(兼容你的初始值格式) + double lng = _safeToDouble(bdLng); + double lat = _safeToDouble(bdLat); + + // 2. BD09转GCJ02核心公式 + double x = lng - 0.0065; + double y = lat - 0.006; + double z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * _pi); + double theta = math.atan2(y, x) - 0.000003 * math.cos(x * _pi); + double gcjLng = z * math.cos(theta); + double gcjLat = z * math.sin(theta); + + return LatLng(gcjLat, gcjLng); +} + +double _safeToDouble(dynamic value) { + if (value == null) return 0.0; + if (value is double) return value; + if (value is int) return value.toDouble(); + if (value is String) { + // 字符串转数字,失败返回0.0 + return double.tryParse(value) ?? 0.0; + } + return 0.0; +} + LatLng gcj02ToWgs84(double lat, double lon) { if (_outOfChina(lat, lon)) { return LatLng(lat, lon);