删除撤回逻辑优化完善
This commit is contained in:
@@ -352,34 +352,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
),
|
||||
'planModel': _currentWorkMode == WorkMode.bow ? 0 : 2, // 作业模式值
|
||||
};
|
||||
// 2. 解析并打印 Path
|
||||
try {
|
||||
final List<dynamic> pathData = jsonDecode(savePath['path'] as String);
|
||||
print('\n🗺️ 路径数据 (共 ${pathData.length} 个点):');
|
||||
// 格式化打印前 3 个点,避免数据过多刷屏
|
||||
for (int i = 0; i < math.min(3, pathData.length); i++) {
|
||||
final point = pathData[i] as Map<String, dynamic>;
|
||||
print(' 点 $i: lat=${point['lat']}, lon=${point['lon']}');
|
||||
}
|
||||
if (pathData.length > 3) {
|
||||
print(' ... 还有 ${pathData.length - 3} 个点');
|
||||
}
|
||||
} catch (e) {
|
||||
print('❌ 解析 path 失败: $e');
|
||||
}
|
||||
|
||||
// 3. 解析并打印 Outer
|
||||
try {
|
||||
final List<dynamic> outerData = jsonDecode(savePath['outer'] as String);
|
||||
print('\n📏 外边界数据 (共 ${outerData.length} 个点):');
|
||||
// 格式化打印所有外边界点(通常数量少)
|
||||
for (int i = 0; i < outerData.length; i++) {
|
||||
final point = outerData[i] as Map<String, dynamic>;
|
||||
print(' 点 $i: lat=${point['lat']}, lon=${point['lon']}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('❌ 解析 outer 失败: $e');
|
||||
}
|
||||
|
||||
// 3. 构造 workRecord (包裹一层)
|
||||
final Map<String, dynamic> workRecord = {
|
||||
@@ -425,6 +397,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
debugPrint('保存地块响应体: $responseBody');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('地块「$plotName」保存成功!'), backgroundColor: Colors.green));
|
||||
// 保存成功
|
||||
setState(() {
|
||||
_markedPoints.clear(); // 清空打点
|
||||
@@ -434,8 +407,6 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
_isPanelOpen = false; // 关闭操作面板
|
||||
_isWorkAreaCompleted = false; // 重置作业区域完成状态
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('地块「$plotName」保存成功!'), backgroundColor: Colors.green));
|
||||
} else {
|
||||
throw Exception('服务器错误: ${response.statusCode}, $responseBody');
|
||||
}
|
||||
@@ -453,34 +424,125 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
return polygonPoints;
|
||||
}
|
||||
|
||||
void _undoLastPoint() {
|
||||
if (_markedPoints.isNotEmpty) {
|
||||
setState(() {
|
||||
_markedPoints.removeLast(); // 删除最后一个打点
|
||||
});
|
||||
debugPrint('撤回成功,剩余打点数量:${_markedPoints.length}');
|
||||
} else {
|
||||
debugPrint('无打点可撤回');
|
||||
// 可选:提示用户
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无打点可撤回')));
|
||||
}
|
||||
//void _undoLastPoint() {
|
||||
// if (_markedPoints.isNotEmpty) {
|
||||
// setState(() {
|
||||
// _markedPoints.removeLast(); // 删除最后一个打点
|
||||
// });
|
||||
// debugPrint('撤回成功,剩余打点数量:${_markedPoints.length}');
|
||||
// } else {
|
||||
// debugPrint('无打点可撤回');
|
||||
// // 可选:提示用户
|
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无打点可撤回')));
|
||||
// }
|
||||
//}
|
||||
|
||||
// ========== 统一撤回方法(适配完成后状态) ==========
|
||||
void _undoAction() {
|
||||
setState(() {
|
||||
// 1. 作业区域模式
|
||||
if (_currentAreaMode == AreaMode.work) {
|
||||
if (_markedPoints.isNotEmpty) {
|
||||
_markedPoints.removeLast();
|
||||
// 作业点撤回后,若路径已生成,重新生成路径(保持同步)
|
||||
if (_isWorkAreaCompleted && _markedPoints.length >= 3) {
|
||||
_generatePath(showTips: false);
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已撤回作业区域最后一个点,剩余${_markedPoints.length}个点')));
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无作业区域点可撤回')));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 空洞模式(完成后优先撤回已完成的空洞)
|
||||
if (_currentAreaMode == AreaMode.obstacle) {
|
||||
if (_currentObstaclePoints.isNotEmpty) {
|
||||
_currentObstaclePoints.removeLast();
|
||||
// 如果当前空洞的点撤空了,退出编辑状态
|
||||
if (_currentObstaclePoints.isEmpty) {
|
||||
_isObstacleEditing = false;
|
||||
}
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已撤回当前空洞最后1个点,剩余${_currentObstaclePoints.length}个点')));
|
||||
return; // 撤完点就结束,不执行后面的逻辑
|
||||
}
|
||||
|
||||
// 第二步:当前空洞无点可撤 → 再撤回「上一个完整空洞」
|
||||
if (_obstacleHoles.isNotEmpty) {
|
||||
_obstacleHoles.removeLast();
|
||||
// 撤完空洞后重新生成路径(排除该空洞)
|
||||
if (_isWorkAreaCompleted) {
|
||||
_generatePath(showTips: false);
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已撤回上一个完整空洞,剩余${_obstacleHoles.length}个空洞')));
|
||||
return;
|
||||
}
|
||||
|
||||
// 第三步:无任何可撤内容
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无空洞可撤回')));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ========== 核心:清空所有打点和轨迹 ==========
|
||||
void _deleteAllPoints() {
|
||||
if (_markedPoints.isNotEmpty) {
|
||||
setState(() {
|
||||
_markedPoints.clear(); // 清空所有打点
|
||||
});
|
||||
debugPrint('删除成功,已清空所有打点和轨迹');
|
||||
// 可选:提示用户
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有打点和轨迹')));
|
||||
} else {
|
||||
debugPrint('无打点可删除');
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无打点可删除')));
|
||||
}
|
||||
// 兼容原有调用(可保留,也可直接用上面的_unifiedUndo)
|
||||
void _undoLastPoint() => _undoAction();
|
||||
void _undoObstaclePoint() => _undoAction();
|
||||
|
||||
// ========== 统一删除方法(适配完成后状态) ==========
|
||||
void _deleteAllAction() {
|
||||
setState(() {
|
||||
// 1. 作业区域模式:清空作业点 + 重置路径
|
||||
if (_currentAreaMode == AreaMode.work) {
|
||||
if (_markedPoints.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无作业区域点可删除')));
|
||||
return;
|
||||
}
|
||||
_markedPoints.clear();
|
||||
gcjPathPoints.clear();
|
||||
gcjOuterPoints.clear();
|
||||
_isWorkAreaCompleted = false;
|
||||
_saveBoxOpen = false;
|
||||
typedPathList.clear();
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有作业区域点和路径')));
|
||||
}
|
||||
// 2. 空洞模式:清空所有空洞 + 恢复UI + 重新生成路径
|
||||
else if (_currentAreaMode == AreaMode.obstacle) {
|
||||
if (_obstacleHoles.isEmpty && _currentObstaclePoints.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无空洞可删除')));
|
||||
return;
|
||||
}
|
||||
_obstacleHoles.clear();
|
||||
_currentObstaclePoints.clear();
|
||||
_isObstacleEditing = false;
|
||||
// 清空后重新生成路径(无空洞)
|
||||
if (_isWorkAreaCompleted) {
|
||||
_generatePath(showTips: false);
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有空洞')));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 兼容原有调用
|
||||
void _deleteAllPoints() => _deleteAllAction();
|
||||
void _clearAllObstacles() => _deleteAllAction();
|
||||
|
||||
// ========== 核心:清空所有打点和轨迹 ==========
|
||||
//void _deleteAllPoints() {
|
||||
// if (_markedPoints.isNotEmpty) {
|
||||
// setState(() {
|
||||
// _markedPoints.clear(); // 清空所有打点
|
||||
// });
|
||||
// debugPrint('删除成功,已清空所有打点和轨迹');
|
||||
// // 可选:提示用户
|
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有打点和轨迹')));
|
||||
// } else {
|
||||
// debugPrint('无打点可删除');
|
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无打点可删除')));
|
||||
// }
|
||||
//}
|
||||
|
||||
/// ===============================
|
||||
/// 企业级定位初始化(已修复坐标系)
|
||||
/// ===============================
|
||||
@@ -634,32 +696,36 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已添加第${_obstacleHoles.length}个障碍物区域'), backgroundColor: Colors.green));
|
||||
}
|
||||
|
||||
void _undoObstaclePoint() {
|
||||
if (_currentObstaclePoints.isNotEmpty) {
|
||||
setState(() => _currentObstaclePoints.removeLast());
|
||||
debugPrint('撤回障碍物打点,剩余:${_currentObstaclePoints.length}个');
|
||||
} else if (_obstacleHoles.isNotEmpty) {
|
||||
// 无当前绘制点时,删除最后一组障碍物
|
||||
setState(() => _obstacleHoles.removeLast());
|
||||
debugPrint('删除最后一组障碍物,剩余组数:${_obstacleHoles.length}');
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无障碍物打点可撤回')));
|
||||
}
|
||||
}
|
||||
//void _undoObstaclePoint() {
|
||||
// if (_currentObstaclePoints.isNotEmpty) {
|
||||
// setState(() => _currentObstaclePoints.removeLast());
|
||||
// debugPrint('撤回障碍物打点,剩余:${_currentObstaclePoints.length}个');
|
||||
// } else if (_obstacleHoles.isNotEmpty) {
|
||||
// // 无当前绘制点时,删除最后一组障碍物
|
||||
// setState(() => _obstacleHoles.removeLast());
|
||||
// debugPrint('删除最后一组障碍物,剩余组数:${_obstacleHoles.length}');
|
||||
// } else {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无障碍物打点可撤回')));
|
||||
// }
|
||||
//}
|
||||
|
||||
// ========== 障碍物模式:清空所有障碍物 ==========
|
||||
void _clearAllObstacles() {
|
||||
setState(() {
|
||||
_obstacleHoles.clear();
|
||||
_currentObstaclePoints.clear();
|
||||
_isObstacleEditing = false;
|
||||
});
|
||||
debugPrint('已清空所有障碍物区域');
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有障碍物区域'), backgroundColor: Colors.amber));
|
||||
}
|
||||
//// ========== 障碍物模式:清空所有障碍物 ==========
|
||||
//void _clearAllObstacles() {
|
||||
// setState(() {
|
||||
// _obstacleHoles.clear();
|
||||
// _currentObstaclePoints.clear();
|
||||
// _isObstacleEditing = false;
|
||||
// });
|
||||
// debugPrint('已清空所有障碍物区域');
|
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有障碍物区域'), backgroundColor: Colors.amber));
|
||||
//}
|
||||
|
||||
// ========== 核心方法:打点逻辑 ==========
|
||||
void _addMarkedPoint() {
|
||||
if (_currentAreaMode == AreaMode.work && _isWorkAreaCompleted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业区域已完成,无法继续添加打点!'), backgroundColor: Colors.red));
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
if (_currentAreaMode == AreaMode.work) {
|
||||
_markedPoints.add(_mapCenter);
|
||||
@@ -1827,6 +1893,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
initialRobotMode: RobotMode.point,
|
||||
initialAreaMode: AreaMode.work,
|
||||
initialWorkMode: _currentWorkMode!,
|
||||
canUndo: _isWorkAreaCompleted && _currentAreaMode == AreaMode.work ? false : true,
|
||||
onComplete: () async {
|
||||
debugPrint(
|
||||
'操作完成回调:当前机器人模式=$_currentRobotMode,当前区域模式=$_currentAreaMode,当前作业模式:$_currentWorkMode,作业区域点:$_markedPoints,作业行距=$_workDistance,航线方向角=$_angle',
|
||||
@@ -1846,19 +1913,22 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
},
|
||||
onUndoTap: () {
|
||||
// 区分模式:作业区域撤回/障碍物撤回
|
||||
if (_currentAreaMode == AreaMode.work) {
|
||||
_undoLastPoint();
|
||||
} else {
|
||||
_undoObstaclePoint();
|
||||
}
|
||||
//if (_currentAreaMode == AreaMode.work) {
|
||||
// _undoLastPoint();
|
||||
//} else {
|
||||
// _undoObstaclePoint();
|
||||
//}
|
||||
_undoAction();
|
||||
},
|
||||
onDeleteTap: () {
|
||||
_deleteAllAction();
|
||||
|
||||
// 区分模式:作业区域清空/障碍物清空
|
||||
if (_currentAreaMode == AreaMode.work) {
|
||||
_deleteAllPoints();
|
||||
} else {
|
||||
_clearAllObstacles();
|
||||
}
|
||||
//if (_currentAreaMode == AreaMode.work) {
|
||||
// _deleteAllPoints();
|
||||
//} else {
|
||||
// _clearAllObstacles();
|
||||
//}
|
||||
},
|
||||
onRobotModeChanged: (mode) {
|
||||
setState(() => _currentRobotMode = mode);
|
||||
|
||||
@@ -10,6 +10,7 @@ class BottomOperationPanel extends StatefulWidget {
|
||||
// 新增:外部控制初始选中的标签(默认地块)
|
||||
final String initialSelectedTab;
|
||||
final WorkMode initialWorkMode;
|
||||
final bool? canUndo; // 是否可以撤回(控制撤回按钮状态)
|
||||
// 回调函数:向外部传递事件
|
||||
final VoidCallback onComplete; // 完成按钮点击回调
|
||||
final ValueChanged<RobotMode>? onRobotModeChanged; // 机器人模式变更回调
|
||||
@@ -41,6 +42,7 @@ class BottomOperationPanel extends StatefulWidget {
|
||||
this.onDistanceTap,
|
||||
this.onDeleteTap,
|
||||
this.onUndoTap,
|
||||
this.canUndo, // 接收撤回按钮状态
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -52,6 +54,7 @@ class _BottomOperationPanelState extends State<BottomOperationPanel> {
|
||||
late AreaMode _areaMode;
|
||||
// 新增:当前选中的标签(地块/航线)- 核心状态
|
||||
late String _currentTab;
|
||||
late bool canUndo;
|
||||
// 新增:航线模式下的作业行距(默认0.5米)
|
||||
double _operationDistance = 0.5;
|
||||
|
||||
@@ -62,6 +65,7 @@ class _BottomOperationPanelState extends State<BottomOperationPanel> {
|
||||
_robotMode = widget.initialRobotMode;
|
||||
_areaMode = widget.initialAreaMode;
|
||||
// 初始化选中的标签
|
||||
canUndo = widget.canUndo ?? true;
|
||||
_currentTab = widget.initialSelectedTab;
|
||||
}
|
||||
|
||||
@@ -194,7 +198,7 @@ class _BottomOperationPanelState extends State<BottomOperationPanel> {
|
||||
debugPrint('点击了删除按钮,清空所有打点');
|
||||
widget.onDeleteTap?.call();
|
||||
}),
|
||||
_buildActionButton(Icons.undo_outlined, '撤回', true, () {
|
||||
_buildActionButton(Icons.undo_outlined, '撤回', widget.canUndo ?? true, () {
|
||||
debugPrint('点击了撤回按钮,删除最后一个打点');
|
||||
widget.onUndoTap?.call();
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user