优化显示完成点和 显示作业路径代码
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
- get_it: true
|
||||
- get_it: true
|
||||
- provider: true
|
||||
@@ -95,10 +95,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
bool isStopWork = false; //是否点击过停止
|
||||
bool isreceiveFirstCompletePoint = false;
|
||||
Offset _videoPopupPos = const Offset(0, 100); // 弹窗初始位置
|
||||
// 🔥 关键修复:添加截图全局Key
|
||||
final GlobalKey _mapRepaintKey = GlobalKey();
|
||||
// 4. 标记点集合(flutter_map需要Set类型)
|
||||
Set<Marker> _markers = {};
|
||||
|
||||
final MapController _mapController = MapController();
|
||||
// 初始化轨迹管理器(泛型指定为LatLng)
|
||||
@@ -119,7 +116,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
bool _showControlModeWarn = false; // 远程模式提示
|
||||
// 新增:存储选中的地块(null表示未选中)
|
||||
PlotData? _selectedPlot;
|
||||
PlotDataPath? _selectedPlotPath; // 存储选中地块的路径数据(可选)
|
||||
// 新增:控制底部作业面板显示
|
||||
bool _isWorkPanelOpen = false;
|
||||
bool _isWorkAreaCompleted = false;
|
||||
@@ -296,9 +292,13 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
_isWorkAreaCompleted = prefs.getBool(kSavedIsWorkAreaCompleted) ?? false;
|
||||
_saveBoxOpen = _isWorkAreaCompleted;
|
||||
|
||||
// ====================== 🔥 新增恢复逻辑 ======================
|
||||
// 1. 恢复作业面板状态
|
||||
_isWorkPanelOpen = prefs.getBool(kSavedIsWorkPanelOpen) ?? false;
|
||||
if (isStartWork && !isStopWork) {
|
||||
_isWorkPanelOpen = true;
|
||||
} else {
|
||||
_isWorkPanelOpen = false;
|
||||
}
|
||||
|
||||
// 2. 恢复作业模式
|
||||
workMode = prefs.getString(kSavedWorkMode) ?? "弓字模式";
|
||||
@@ -478,19 +478,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
//} else {
|
||||
// ObsToastWidget.dismiss();
|
||||
//}
|
||||
|
||||
final wgsPoint = LatLng(lat, lng);
|
||||
|
||||
// 2. 转换为高德GCJ02坐标系
|
||||
|
||||
// 可选:更新航向角(如果有角度数据)
|
||||
// _headingAngle = updatedState.status.heading ?? 0.0;
|
||||
// 可选:插入队列
|
||||
_traceManager.upsert(wgsPoint, TPAction.UPDATE);
|
||||
tracePoint = _traceManager.getTracePoint();
|
||||
gctracePoint = batchWgs84ToGcj02(tracePoint!);
|
||||
|
||||
debugPrint("$gctracePoint gctracePoint");
|
||||
} catch (e) {
|
||||
debugPrint('处理经纬度数据失败:$e');
|
||||
}
|
||||
@@ -864,7 +851,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
// 6. 重置选中状态
|
||||
_selectedPlot = null;
|
||||
_selectedPlotPath = null;
|
||||
|
||||
// 7. 重置作业模式
|
||||
_currentRobotMode = RobotMode.robot;
|
||||
@@ -1046,134 +1032,128 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
return GestureDetector(
|
||||
// 核心:点击列表项触发选中逻辑
|
||||
onTap: () async {
|
||||
// 1. 清空之前的轨迹数据
|
||||
// 【优化1】第一步就UI响应,不卡手
|
||||
setState(() {
|
||||
_isListBoxOpen = false;
|
||||
gcjPathPoints = [];
|
||||
gcjOuterPoints = [];
|
||||
_selectedPlot = plot;
|
||||
});
|
||||
|
||||
await context.read<DevicesCubit>().loadSelectedPath(plot.plotName);
|
||||
final cubitState = context.read<DevicesCubit>().state;
|
||||
final _loadedPlot = cubitState.pathData;
|
||||
print('加载地块「${plot.plotName}」的路径数据: $_loadedPlot');
|
||||
if (_loadedPlot is List) {
|
||||
final List<dynamic> rawList = _loadedPlot as List<dynamic>;
|
||||
final pathRecords = rawList.where((item) => item is Map<String, dynamic>).cast<Map<String, dynamic>>().toList();
|
||||
if (pathRecords.isNotEmpty) {
|
||||
final selectedPlotPath = PlotDataPath(jsonData: pathRecords.first);
|
||||
try {
|
||||
final dynamic nestedJsonRaw = selectedPlotPath.jsonData['jsonData'];
|
||||
if (nestedJsonRaw != null && nestedJsonRaw is String) {
|
||||
final String nestedJsonStr = nestedJsonRaw;
|
||||
final dynamic parsedJson = jsonDecode(nestedJsonStr);
|
||||
workMode = parsedJson['planModel'] == WorkMode.bow.value ? "弓字模式" : "自定义模式";
|
||||
debugPrint('解析出的作业模式: ${parsedJson['planModel']},WorkMode.bow.value=${WorkMode.bow.value}, 解析结果: $workMode');
|
||||
if (parsedJson is Map<String, dynamic>) {
|
||||
final Map<String, dynamic> nestedJson = parsedJson;
|
||||
// 替换你原来的 rawPath/rawOuter 解析部分
|
||||
final dynamic rawPath = nestedJson['path'];
|
||||
final dynamic rawOuter = nestedJson['outer'];
|
||||
try {
|
||||
_traceManager.reset();
|
||||
await context.read<DevicesCubit>().loadSelectedPath(plot.plotName);
|
||||
final cubitState = context.read<DevicesCubit>().state;
|
||||
final _loadedPlot = cubitState.pathData;
|
||||
|
||||
debugPrint('解析后的路径数据11: pathList=$rawPath,');
|
||||
debugPrint('解析后的外边界数据22: outerList=$rawOuter,');
|
||||
|
||||
// ========== 修复核心:先解码字符串,再处理类型 ==========
|
||||
List<dynamic> pathList = [];
|
||||
if (rawPath is String) {
|
||||
try {
|
||||
pathList = jsonDecode(rawPath) as List<dynamic>;
|
||||
} catch (e) {
|
||||
debugPrint('path 字符串解码失败: $e, rawPath=$rawPath');
|
||||
pathList = [];
|
||||
}
|
||||
} else if (rawPath is List) {
|
||||
pathList = rawPath;
|
||||
} else {
|
||||
pathList = [];
|
||||
}
|
||||
|
||||
List<dynamic> outerList = [];
|
||||
if (rawOuter is String) {
|
||||
try {
|
||||
outerList = jsonDecode(rawOuter) as List<dynamic>;
|
||||
} catch (e) {
|
||||
debugPrint('outer 字符串解码失败: $e, rawOuter=$rawOuter');
|
||||
outerList = [];
|
||||
}
|
||||
} else if (rawOuter is List) {
|
||||
outerList = rawOuter;
|
||||
} else {
|
||||
outerList = [];
|
||||
}
|
||||
if (workMode == "弓字模式") {
|
||||
startWorkList = pathList;
|
||||
} else {
|
||||
startWorkList = outerList;
|
||||
}
|
||||
|
||||
List<LatLng> newPathPoints = [];
|
||||
List<LatLng> newOuterPoints = [];
|
||||
for (var item in pathList) {
|
||||
double? lat = safeToDouble(item['lat']);
|
||||
double? lon = safeToDouble(item['lon']);
|
||||
if (lat != null && lon != null) {
|
||||
newPathPoints.add(convertWGS84ToGCJ02(lat, lon));
|
||||
}
|
||||
}
|
||||
for (var item in outerList) {
|
||||
double? lng = safeToDouble(item['lng']);
|
||||
double? lat = safeToDouble(item['lat']);
|
||||
if (lng != null && lat != null) {
|
||||
newOuterPoints.add(convertWGS84ToGCJ02(lat, lng));
|
||||
}
|
||||
}
|
||||
// 在这里更新状态(安全,因为在事件回调中)
|
||||
setState(() {
|
||||
gcjPathPoints = newPathPoints;
|
||||
gcjOuterPoints = newOuterPoints;
|
||||
if (_currentWorkMode == WorkMode.custom) gcjPathPoints = newOuterPoints; // 自定义模式不显示路径
|
||||
_selectedPlot = plot;
|
||||
_isListBoxOpen = false;
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false; // 关闭操作面板,专注作业界面
|
||||
});
|
||||
// 移动地图到中心
|
||||
List<LatLng> allPoints = [];
|
||||
allPoints.addAll(gcjPathPoints);
|
||||
allPoints.addAll(gcjOuterPoints);
|
||||
if (allPoints.isNotEmpty) {
|
||||
moveMapToPointsCenter(allPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('解析/转换坐标失败:$e');
|
||||
setState(() {
|
||||
gcjPathPoints = [];
|
||||
gcjOuterPoints = [];
|
||||
_selectedPlot = plot;
|
||||
_isListBoxOpen = false;
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false; // 关闭操作面板,专注作业界面
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 【优化2】提前快速判断,不进无用逻辑
|
||||
if (_loadedPlot is! List || _loadedPlot!.isEmpty) {
|
||||
setState(() {
|
||||
gcjPathPoints = [];
|
||||
gcjOuterPoints = [];
|
||||
_selectedPlot = plot;
|
||||
_isListBoxOpen = false;
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false; // 关闭操作面板,专注作业界面
|
||||
_isPanelOpen = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
final pathRecords = _loadedPlot.where((item) => item is Map<String, dynamic>).cast<Map<String, dynamic>>().toList();
|
||||
if (pathRecords.isEmpty) {
|
||||
setState(() {
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final selectedPlotPath = PlotDataPath(jsonData: pathRecords.first);
|
||||
final nestedJsonRaw = selectedPlotPath.jsonData['jsonData'];
|
||||
|
||||
if (nestedJsonRaw is! String) {
|
||||
setState(() {
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 【优化3】只解码一次核心JSON,最耗时操作只跑一遍
|
||||
final parsedJson = jsonDecode(nestedJsonRaw);
|
||||
if (parsedJson is! Map<String, dynamic>) {
|
||||
setState(() {
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
workMode = parsedJson['planModel'] == WorkMode.bow.value ? "弓字模式" : "自定义模式";
|
||||
|
||||
// 【优化4】统一 path/outer 解析逻辑,不重复代码
|
||||
List<dynamic> pathList = [];
|
||||
final rawPath = parsedJson['path'];
|
||||
if (rawPath is String) {
|
||||
try {
|
||||
pathList = jsonDecode(rawPath) as List;
|
||||
} catch (_) {}
|
||||
} else if (rawPath is List) {
|
||||
pathList = rawPath;
|
||||
}
|
||||
|
||||
List<dynamic> outerList = [];
|
||||
final rawOuter = parsedJson['outer'];
|
||||
if (rawOuter is String) {
|
||||
try {
|
||||
outerList = jsonDecode(rawOuter) as List;
|
||||
} catch (_) {}
|
||||
} else if (rawOuter is List) {
|
||||
outerList = rawOuter;
|
||||
}
|
||||
|
||||
if (workMode == "弓字模式") {
|
||||
startWorkList = pathList;
|
||||
} else {
|
||||
startWorkList = outerList;
|
||||
}
|
||||
|
||||
// 【优化5】一次性生成坐标,不反复操作数组
|
||||
List<LatLng> newPathPoints = [];
|
||||
List<LatLng> newOuterPoints = [];
|
||||
for (var item in pathList) {
|
||||
double? lat = safeToDouble(item['lat']);
|
||||
double? lon = safeToDouble(item['lon']);
|
||||
if (lat != null && lon != null) {
|
||||
newPathPoints.add(convertWGS84ToGCJ02(lat, lon));
|
||||
}
|
||||
}
|
||||
for (var item in outerList) {
|
||||
double? lng = safeToDouble(item['lng']);
|
||||
double? lat = safeToDouble(item['lat']);
|
||||
if (lng != null && lat != null) {
|
||||
newOuterPoints.add(convertWGS84ToGCJ02(lat, lng));
|
||||
}
|
||||
}
|
||||
|
||||
// 【优化6】整个方法只调用一次 setState,性能暴涨
|
||||
setState(() {
|
||||
gcjPathPoints = _currentWorkMode == WorkMode.custom ? [] : newPathPoints;
|
||||
gcjOuterPoints = newOuterPoints;
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false;
|
||||
});
|
||||
|
||||
// 最后移动地图
|
||||
List<LatLng> allPoints = [];
|
||||
allPoints.addAll(gcjPathPoints);
|
||||
allPoints.addAll(gcjOuterPoints);
|
||||
if (allPoints.isNotEmpty) {
|
||||
moveMapToPointsCenter(allPoints);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('解析失败:$e');
|
||||
setState(() {
|
||||
gcjPathPoints = [];
|
||||
gcjOuterPoints = [];
|
||||
_selectedPlot = plot;
|
||||
_isListBoxOpen = false;
|
||||
_isWorkPanelOpen = true;
|
||||
_isPanelOpen = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -1237,6 +1217,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
Widget _buildMap(double lat, double lng, bool obfFlag, int headingStatus, String controlMode) {
|
||||
_onDeviceData(lng, lat, obfFlag, headingStatus, controlMode);
|
||||
|
||||
final gcjPoint = wgs84ToGcj02(lat, lng);
|
||||
|
||||
//final initCenter = bd09ToGcj02(
|
||||
@@ -1248,6 +1229,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
final initCenter = _getDefaultValidCenter();
|
||||
_currentWgsLatLng = LatLng(lat, lng);
|
||||
|
||||
_traceManager.upsert(_currentWgsLatLng as PlotPoint, TPAction.UPDATE);
|
||||
tracePoint = _traceManager.getTracePoint();
|
||||
gctracePoint = batchWgs84ToGcj02(tracePoint!);
|
||||
|
||||
debugPrint("$gctracePoint gctracePoint");
|
||||
|
||||
//_currentLatLng = gcjPoint; // ✅ 状态变量在setState内更新
|
||||
if (_isValidLatLng(gcjPoint.latitude, gcjPoint.longitude)) {
|
||||
_currentLatLng = gcjPoint;
|
||||
@@ -1368,21 +1355,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
],
|
||||
),
|
||||
|
||||
/// 当前定位 Marker
|
||||
if (_currentLatLng != null && __isValidLatLng(_currentLatLng))
|
||||
MarkerLayer(
|
||||
markers: [
|
||||
Marker(
|
||||
point: _currentLatLng!,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: CustomPaint(
|
||||
size: const Size(40, 40),
|
||||
painter: HeadingMarkerPainter(headingAngle: _headingAngle),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_currentWorkMode == WorkMode.bow && _markedPoints.isNotEmpty && !_isWorkAreaCompleted && _currentRobotMode == RobotMode.point)
|
||||
PolygonLayer(
|
||||
polygons: [
|
||||
@@ -1421,8 +1393,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
strokeWidth: 1.5,
|
||||
isDotted: true, // 虚线区分作业区域
|
||||
),
|
||||
// 最后一个点到地图中心的连线
|
||||
Polyline(points: [_mapCenter, _currentObstaclePoints.last], color: Colors.red.withOpacity(0.5), strokeWidth: 1.5, isDotted: true),
|
||||
if (_currentRobotMode == RobotMode.point)
|
||||
// 最后一个点到地图中心的连线
|
||||
Polyline(points: [_mapCenter, _currentObstaclePoints.last], color: Colors.red.withOpacity(0.5), strokeWidth: 1.5, isDotted: true),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1525,16 +1498,24 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
if (gctracePoint!.isNotEmpty && isStartWork)
|
||||
if (gctracePoint!.isNotEmpty)
|
||||
PolylineLayer(
|
||||
polylines: [
|
||||
for (int i = 0; i < gctracePoint!.length - 1; i++)
|
||||
Polyline(
|
||||
points: [gctracePoint![i], gctracePoint![i + 1]],
|
||||
color: Color(0xFF00C853),
|
||||
strokeWidth: 3,
|
||||
isDotted: false, // 虚线区分作业区域
|
||||
polylines: [Polyline(points: gctracePoint!, color: Color(0xFF00C853), strokeWidth: 3, isDotted: false)],
|
||||
),
|
||||
|
||||
/// 当前定位 Marker
|
||||
if (_currentLatLng != null && __isValidLatLng(_currentLatLng))
|
||||
MarkerLayer(
|
||||
markers: [
|
||||
Marker(
|
||||
point: _currentLatLng!,
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: CustomPaint(
|
||||
size: const Size(40, 40),
|
||||
painter: HeadingMarkerPainter(headingAngle: _headingAngle),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -1544,15 +1525,16 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
/// 开始作业
|
||||
void _startWork() async {
|
||||
_traceManager.reset();
|
||||
isStopWork = false;
|
||||
_saveDataToLocal();
|
||||
|
||||
if (startWorkList.isEmpty) {
|
||||
ToastUtils.showInfo(context, '作业列表为空,请重新选择路径');
|
||||
return;
|
||||
}
|
||||
_traceManager.setMode(TPMode.LOCATION);
|
||||
_traceManager.setMode(TPMode.NAVIGATION);
|
||||
|
||||
setState(() {
|
||||
isStopWork = false;
|
||||
|
||||
isStartWork = true; // 🔥 关键:停止作业标志
|
||||
_workStatus = WorkStatus.working;
|
||||
});
|
||||
@@ -1562,15 +1544,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
// 🔥 延迟一下,确保状态已更新
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
//// 步骤1:将 List<LatLng> 转换为 List<DeviceAddPathPointModel>
|
||||
//final List<work_area_model.DeviceAddPathPointModel> pathModels = gcjPathPoints.map((latLng) {
|
||||
// return work_area_model.DeviceAddPathPointModel(
|
||||
// latitude: latLng.latitude, // 纬度
|
||||
// longitude: latLng.longitude, // 经度
|
||||
// );
|
||||
//}).toList();
|
||||
|
||||
// 步骤2:将 List 转换为 Queue(队列)
|
||||
debugPrint('⚙️ 开始类型转换...');
|
||||
final List<work_area_model.DeviceAddPathPointModel> typedList = startWorkList.whereType<Map<String, dynamic>>().map((item) {
|
||||
return work_area_model.DeviceAddPathPointModel(latitude: (item['lat'] as num).toDouble(), longitude: (item['lon'] ?? item["lng"] as num).toDouble());
|
||||
@@ -1587,6 +1560,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
///context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
|
||||
// 可选:显示作业提示
|
||||
ToastUtils.showSuccess(context, '作业已开始');
|
||||
_saveDataToLocal();
|
||||
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业已开始'), backgroundColor: Colors.green));
|
||||
}
|
||||
|
||||
@@ -1597,7 +1571,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
_workStatus = WorkStatus.paused;
|
||||
});
|
||||
_saveDataToLocal(); // 🔥 保存暂停状态
|
||||
context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||
//context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||
await context.read<DevicesCubit>().pauseRoutePlanning();
|
||||
}
|
||||
|
||||
@@ -1610,10 +1584,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
isStopWork = true; //已经点击过停止
|
||||
isreceiveFirstCompletePoint = false;
|
||||
});
|
||||
|
||||
//context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||
await context.read<DevicesCubit>().stopRoutePlanning();
|
||||
_traceManager.reset();
|
||||
_saveDataToLocal(); // 🔥 保存暂停状态
|
||||
context.read<DevicesCubit>().updateAppState(AppState.none);
|
||||
await context.read<DevicesCubit>().stopRoutePlanning();
|
||||
|
||||
ToastUtils.showError(context, '作业已停止');
|
||||
}
|
||||
@@ -1952,6 +1927,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
// ========== 抽象:生成路径的核心函数 ==========
|
||||
Future<void> _generatePath({bool showTips = true}) async {
|
||||
debugPrint("机器打点孔洞_obstacleHoles$_obstacleHoles");
|
||||
debugPrint("机器打点孔洞_robotModeObsWgsPoints$_robotModeObsWgsPoints");
|
||||
|
||||
if (_currentWorkMode == WorkMode.custom) {
|
||||
setState(() {
|
||||
_saveBoxOpen = true; // 显示保存按钮
|
||||
@@ -2087,7 +2065,14 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
holes = {'tempKey': holeBoundary}; // 键名任意,仅为满足类型要求
|
||||
}
|
||||
final workType = _currentWorkMode == WorkMode.bow ? 0 : 2;
|
||||
|
||||
print('==================================================');
|
||||
print('✅ generatePath 完整参数结构:');
|
||||
print('reference: ${formatPrettyJson(referencePoint)}');
|
||||
print('heading: $heading');
|
||||
print('outer: ${formatPrettyJson(outerBoundary)}');
|
||||
print('holes: ${formatPrettyJson(holes)}');
|
||||
print('workType: $workType');
|
||||
print('==================================================');
|
||||
// 3. 调用 Cubit 的 generatePath 方法(传入holes参数)
|
||||
await context.read<DevicesCubit>().generatePath(
|
||||
reference: referencePoint,
|
||||
@@ -2152,7 +2137,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
return BlocBuilder<DeviceStatusBloc, DeviceStatusState>(
|
||||
builder: (context, state) {
|
||||
final devicesState = context.watch<DevicesCubit>().state;
|
||||
// 2. 读取 isFinishWork 数据(修正拼写,设置默认值)
|
||||
bool isFinishWork = devicesState.isFinshWork ?? false;
|
||||
double? arriLatitude = devicesState.arriLatitude;
|
||||
double? arriLongitude = devicesState.arriLongitude;
|
||||
@@ -2160,11 +2144,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
if (arriLatitude != null && arriLongitude != null) {
|
||||
targetLatLng = LatLng(arriLatitude, arriLongitude);
|
||||
if (__isValidLatLng(targetLatLng)) {
|
||||
debugPrint("${targetLatLng}收到完成点gctracePoint");
|
||||
//if (!isreceiveFirstCompletePoint) {
|
||||
_traceManager.setMode(TPMode.NAVIGATION);
|
||||
// isreceiveFirstCompletePoint = true;
|
||||
//}
|
||||
debugPrint("${targetLatLng}收到完成点arriLatitude");
|
||||
if (!isreceiveFirstCompletePoint) {
|
||||
_traceManager.setMode(TPMode.NAVIGATION);
|
||||
isreceiveFirstCompletePoint = true;
|
||||
}
|
||||
|
||||
_traceManager.upsert(targetLatLng, TPAction.ADD);
|
||||
}
|
||||
@@ -2180,7 +2164,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
if (isFinishWork) {
|
||||
_workStatus = WorkStatus.idle;
|
||||
ToastUtils.showError(context, '作业已停止');
|
||||
_traceManager.reset();
|
||||
// 👇 延迟 1 秒钟再执行 reset(不会阻塞UI,安全)
|
||||
Future.delayed(const Duration(seconds: 1), () {
|
||||
if (mounted) {
|
||||
_traceManager.reset();
|
||||
}
|
||||
});
|
||||
isStopWork = true;
|
||||
isreceiveFirstCompletePoint = false;
|
||||
}
|
||||
@@ -2312,6 +2301,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
onPressed: _moveToCurrentLocation,
|
||||
child: VerticalFloatMenu(
|
||||
onEditTap: (bool isOpen) {
|
||||
_traceManager.reset();
|
||||
setState(() {
|
||||
_isPanelOpen = isOpen;
|
||||
});
|
||||
@@ -2741,3 +2731,28 @@ LatLng _getMiddleLatLng(LatLng point1, LatLng point2) {
|
||||
double middleLng = (point1.longitude + point2.longitude) / 2;
|
||||
return LatLng(middleLat, middleLng);
|
||||
}
|
||||
|
||||
// 🔥 万能格式化打印:输出完整结构(层级+字段名+值)
|
||||
String formatPrettyJson(dynamic obj) {
|
||||
try {
|
||||
if (obj == null) return 'null';
|
||||
if (obj is List) {
|
||||
return obj.map((e) => formatPrettyJson(e)).toList().toString();
|
||||
}
|
||||
if (obj is Map) {
|
||||
Map<String, dynamic> map = {};
|
||||
obj.forEach((k, v) {
|
||||
map[k.toString()] = formatPrettyJson(v);
|
||||
});
|
||||
return map.toString();
|
||||
}
|
||||
// 自定义模型:转 Map
|
||||
try {
|
||||
return obj.toJson().toString();
|
||||
} catch (e) {
|
||||
return obj.toString();
|
||||
}
|
||||
} catch (e) {
|
||||
return obj.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user