保存按钮显示逻辑 自定义模式 十字准星的打点 、保存和 点击后的显示

This commit is contained in:
mmc
2026-03-02 15:32:17 +08:00
parent fe9b763783
commit a29b81be20
2 changed files with 72 additions and 36 deletions

View File

@@ -78,14 +78,14 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
bool _hasMovedOnce = false;
bool _isPanelOpen = false; // 控制面板显示/隐藏
bool _directionBoxOpen = false; //航线面板显示/隐藏
final bool _saveBoxOpen = true; //保存按钮显示/隐藏
bool _saveBoxOpen = false; //保存按钮显示/隐藏
bool _isListBoxOpen = false; //列表面板显示/隐藏
// 新增:存储选中的地块(null表示未选中)
PlotData? _selectedPlot;
PlotDataPath? _selectedPlotPath; // 存储选中地块的路径数据(可选)
// 新增:控制底部作业面板显示
bool _isWorkPanelOpen = false;
bool _isWorkAreaCompleted = false;
RobotMode _currentRobotMode = RobotMode.point; //打点模式
AreaMode _currentAreaMode = AreaMode.work; //作业区域还是障碍物区域
WorkMode? _currentWorkMode = WorkMode.bow; // 当前作业模式
@@ -333,18 +333,19 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
final Map<String, dynamic> savePath = {
//'img': imgBase64 ?? '', // 截图的 Base64 字符串
'name': plotName, // 地块名称
'path': jsonEncode(
typedPathList
.map(
(point) => {
// 路径点数组
'lon': point.longitude,
'lat': point.latitude,
},
)
.toList(),
),
'path': _currentWorkMode == WorkMode.custom
? jsonEncode([]) // 自定义模式 path 为空数组
: jsonEncode(
typedPathList
.map(
(point) => {
// 路径点数组
'lon': point.longitude,
'lat': point.latitude,
},
)
.toList(),
),
'outer': jsonEncode(
gcjOuterPoints.map((point) {
final wgs84 = gcj02ToWgs84(point.latitude, point.longitude);
@@ -433,6 +434,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
gcjOuterPoints.clear(); // 清空外边界
_isPanelOpen = false; // 关闭操作面板
_isWorkAreaCompleted = false; // 重置作业区域完成状态
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('地块「$plotName」保存成功!'), backgroundColor: Colors.green));
@@ -530,6 +532,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
gcjPathPoints.clear();
gcjOuterPoints.clear();
_currentTracePoints = null;
_isWorkAreaCompleted = false;
_saveBoxOpen = false;
// 重置面板状态
_isPanelOpen = false;
@@ -878,6 +882,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
setState(() {
gcjPathPoints = newPathPoints;
gcjOuterPoints = newOuterPoints;
if (_currentWorkMode == WorkMode.custom) gcjPathPoints = newOuterPoints; // 自定义模式不显示路径
_selectedPlot = plot;
_isListBoxOpen = false;
_isWorkPanelOpen = true;
@@ -1297,6 +1302,17 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// ========== 抽象:生成路径的核心函数 ==========
Future<void> _generatePath({bool showTips = true}) async {
if (_currentWorkMode == WorkMode.custom) {
setState(() {
_saveBoxOpen = true; // 显示保存按钮
_isWorkAreaCompleted = true; // 标记为完成,允许保存
gcjPathPoints = List.from(_markedPoints); // outer直接使用打点坐标
gcjOuterPoints = List.from(_markedPoints);
typedPathList = []; // 路径列表置空
});
return;
}
// 1. 校验必要条件
if (_currentAreaMode == AreaMode.work && _markedPoints.isEmpty) {
if (showTips) {
@@ -1391,6 +1407,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
if (cubitState.generatedPath is List) {
setState(() {
_isWorkAreaCompleted = true;
_saveBoxOpen = true;
final pathList = cubitState.generatedPath as List;
typedPathList = pathList.whereType<work_area_model.DeviceAddPathPointModel>().toList();
debugPrint('✅ 过滤并转换后的路径点列表:typedPathList 长度=${typedPathList.length}');
@@ -1462,7 +1480,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
),
// 绘制outer边框(Polygon模式)
if (gcjOuterPoints.isNotEmpty)
if (gcjOuterPoints.isNotEmpty && _currentWorkMode == WorkMode.bow)
PolygonLayer(
polygons: [
Polygon(
@@ -1474,15 +1492,29 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
),
],
),
if (gcjPathPoints.isNotEmpty && _currentWorkMode == WorkMode.custom)
PolylineLayer(
polylines: [
Polyline(
points: gcjPathPoints, // 转换后的GCJ02坐标
color: Colors.green, // 内部填充色(透明)
strokeWidth: 3.0, // 折线宽度
isDotted: false, // 非虚线(Line模式)
borderColor: Colors.white, // 可选:添加白色描边,提升辨识度
borderStrokeWidth: 0.5,
),
],
),
/// 中心标与历史打点的虚线连线
PolylineLayer(
polylines: [
for (int i = 0; i < _markedPoints.length - 1; i++)
Polyline(points: [_markedPoints[i], _markedPoints[i + 1]], color: Colors.orange.withOpacity(0.5), strokeWidth: 1.5),
],
),
if (_markedPoints.isNotEmpty)
if (!_isWorkAreaCompleted)
PolylineLayer(
polylines: [
for (int i = 0; i < _markedPoints.length - 1; i++)
Polyline(points: [_markedPoints[i], _markedPoints[i + 1]], color: Colors.orange.withOpacity(0.5), strokeWidth: 1.5),
],
),
if (_markedPoints.isNotEmpty && !_isWorkAreaCompleted)
PolylineLayer(
polylines: [
Polyline(points: [_mapCenter, _markedPoints.last], color: Colors.blue.withOpacity(0.5), strokeWidth: 1.5),
@@ -1504,7 +1536,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
),
],
),
if (_currentWorkMode == WorkMode.bow && _markedPoints.isNotEmpty)
if (_currentWorkMode == WorkMode.bow && _markedPoints.isNotEmpty && !_isWorkAreaCompleted)
PolygonLayer(
polygons: [
Polygon(
@@ -1784,6 +1816,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
child: BottomOperationPanel(
initialRobotMode: RobotMode.point,
initialAreaMode: AreaMode.work,
initialWorkMode: _currentWorkMode!,
onComplete: () async {
debugPrint(
'操作完成回调:当前机器人模式=$_currentRobotMode,当前区域模式=$_currentAreaMode,当前作业模式:$_currentWorkMode,作业区域点:$_markedPoints,作业行距=$_workDistance,航线方向角=$_angle',

View File

@@ -9,6 +9,7 @@ class BottomOperationPanel extends StatefulWidget {
final AreaMode initialAreaMode;
// 新增:外部控制初始选中的标签(默认地块)
final String initialSelectedTab;
final WorkMode initialWorkMode;
// 回调函数:向外部传递事件
final VoidCallback onComplete; // 完成按钮点击回调
final ValueChanged<RobotMode>? onRobotModeChanged; // 机器人模式变更回调
@@ -29,6 +30,7 @@ class BottomOperationPanel extends StatefulWidget {
this.initialRobotMode = RobotMode.point,
this.initialAreaMode = AreaMode.work,
this.initialSelectedTab = '地块', // 默认选中地块
this.initialWorkMode = WorkMode.bow,
required this.onComplete, // 完成按钮必须传
this.onRobotModeChanged,
this.onAreaModeChanged,
@@ -166,19 +168,20 @@ class _BottomOperationPanelState extends State<BottomOperationPanel> {
child: const Icon(Icons.add, color: Colors.white, size: 32),
),
),
DropdownButton<AreaMode>(
value: _areaMode,
items: const [
DropdownMenuItem(value: AreaMode.work, child: Text("作业区域")),
DropdownMenuItem(value: AreaMode.obstacle, child: Text("障碍区域")),
],
onChanged: (v) {
if (v != null) {
setState(() => _areaMode = v);
widget.onAreaModeChanged?.call(v);
}
},
),
if (widget.initialWorkMode == WorkMode.bow)
DropdownButton<AreaMode>(
value: _areaMode,
items: const [
DropdownMenuItem(value: AreaMode.work, child: Text("作业区域")),
DropdownMenuItem(value: AreaMode.obstacle, child: Text("障碍区域")),
],
onChanged: (v) {
if (v != null) {
setState(() => _areaMode = v);
widget.onAreaModeChanged?.call(v);
}
},
),
],
),
const SizedBox(height: 16),