Files
flutterApp/lib/features/home/presentation/widgets/startpoint_area.dart
2026-03-09 11:06:43 +08:00

317 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/enum.dart';
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/testmap_pages.dart';
/// 底部操作面板独立组件
class BottomOperationPanel extends StatefulWidget {
// 外部传入的初始值
final RobotMode initialRobotMode;
final AreaMode initialAreaMode;
// 新增:外部控制初始选中的标签(默认地块)
final String initialSelectedTab;
final WorkMode initialWorkMode;
final bool? canUndo; // 是否可以撤回(控制撤回按钮状态)
// 回调函数:向外部传递事件
final VoidCallback onComplete; // 完成按钮点击回调
final ValueChanged<RobotMode>? onRobotModeChanged; // 机器人模式变更回调
final ValueChanged<AreaMode>? onAreaModeChanged; // 作业区域模式变更回调
final VoidCallback? onAddTap; // 加号按钮点击回调
final VoidCallback? onLandTap; // 地块标签点击回调
final VoidCallback? onRouteTap; // 航线标签点击回调
final VoidCallback? onSettingTap;
final ValueChanged<double>? onDistanceTap;
final VoidCallback? onDeleteTap;
final VoidCallback? onUndoTap; // 设置标签点击回调
const BottomOperationPanel({
super.key,
this.initialRobotMode = RobotMode.robot,
this.initialAreaMode = AreaMode.work,
this.initialSelectedTab = '地块', // 默认选中地块
this.initialWorkMode = WorkMode.bow,
required this.onComplete, // 完成按钮必须传
this.onRobotModeChanged,
this.onAreaModeChanged,
this.onAddTap,
this.onLandTap,
this.onRouteTap,
this.onSettingTap,
this.onDistanceTap,
this.onDeleteTap,
this.onUndoTap,
this.canUndo, // 接收撤回按钮状态
});
@override
State<BottomOperationPanel> createState() => _BottomOperationPanelState();
}
class _BottomOperationPanelState extends State<BottomOperationPanel> {
late RobotMode _robotMode;
late AreaMode _areaMode;
// 新增:当前选中的标签(地块/航线)- 核心状态
late String _currentTab;
late bool canUndo;
// 新增:航线模式下的作业行距(默认0.5米)
double _operationDistance = 0.5;
@override
void initState() {
super.initState();
// 初始化外部传入的默认值
_robotMode = widget.initialRobotMode;
_areaMode = widget.initialAreaMode;
// 初始化选中的标签
canUndo = widget.canUndo ?? true;
_currentTab = widget.initialSelectedTab;
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 8)],
),
padding: const EdgeInsets.all(16),
//constraints: const BoxConstraints(minHeight: 260),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildTabContent(),
// 底部标签页切换(修复背景色切换+状态更新)
Container(
decoration: BoxDecoration(color: Colors.grey[200], borderRadius: BorderRadius.circular(8)),
child: Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_currentTab = '地块'; // 更新选中状态
});
debugPrint('切换到地块标签');
widget.onLandTap?.call();
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
// 选中地块时背景为白色,否则透明
decoration: BoxDecoration(color: _currentTab == '地块' ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(8)),
child: const Center(
child: Text('地块', style: TextStyle(color: Colors.black87, fontSize: 16)),
),
),
),
),
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_currentTab = '航线'; // 更新选中状态
});
debugPrint('切换到航线标签');
widget.onRouteTap?.call();
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
// 选中航线时背景为白色,否则透明
decoration: BoxDecoration(color: _currentTab == '航线' ? Colors.white : Colors.transparent, borderRadius: BorderRadius.circular(8)),
child: const Center(
child: Text('航线', style: TextStyle(color: Colors.black87, fontSize: 16)),
),
),
),
),
],
),
),
const SizedBox(height: 5),
],
),
),
);
}
// 地块模式内容构建方法
Widget _buildLandContent() {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// 面板核心内容
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
DropdownButton<RobotMode>(
value: _robotMode,
items: const [
DropdownMenuItem(value: RobotMode.point, child: Text("十字准星")),
DropdownMenuItem(value: RobotMode.robot, child: Text("机器人模式")),
],
onChanged: (v) {
if (v != null) {
setState(() => _robotMode = v);
widget.onRobotModeChanged?.call(v);
}
},
),
GestureDetector(
onTap: () {
debugPrint('点击了添加按钮');
widget.onAddTap?.call();
},
child: Container(
width: 40,
height: 40,
decoration: const BoxDecoration(color: Color(0xFF00C853), shape: BoxShape.circle),
child: const Icon(Icons.add, color: Colors.white, size: 32),
),
),
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),
// 操作按钮行
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildActionButton(Icons.delete_outline, '删除', true, () {
debugPrint('点击了删除按钮,清空所有打点');
widget.onDeleteTap?.call();
}),
_buildActionButton(Icons.undo_outlined, '撤回', widget.canUndo ?? true, () {
debugPrint('点击了撤回按钮,删除最后一个打点');
widget.onUndoTap?.call();
}),
_buildActionButton(Icons.check_outlined, '完成', true, () {
widget.onComplete.call();
}),
],
),
const SizedBox(height: 16),
],
);
}
// 标签内容切换方法(地块/航线)
Widget _buildTabContent() {
if (_currentTab == '地块') {
// 地块模式:显示机器人/区域选择+操作按钮
return _buildLandContent();
} else {
// 航线模式:显示作业行距+航线方向设置
return Column(
children: [
// 作业行距配置行
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('作业行距(米)', style: TextStyle(fontSize: 16, color: Colors.black87)),
Row(
children: [
// 减号按钮
GestureDetector(
onTap: () {
setState(() {
if (_operationDistance > 0.1) {
_operationDistance -= 0.1;
}
});
widget.onDistanceTap?.call(_operationDistance);
},
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(color: Colors.grey[200], shape: BoxShape.circle),
child: const Icon(Icons.remove, size: 16, color: Colors.black87),
),
),
const SizedBox(width: 10),
// 行距数值
Text('${_operationDistance.toStringAsFixed(1)}', style: const TextStyle(fontSize: 16, color: Colors.black87)),
const SizedBox(width: 10),
// 加号按钮
GestureDetector(
onTap: () {
setState(() {
_operationDistance += 0.1;
});
widget.onDistanceTap?.call(_operationDistance);
},
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(color: Colors.grey[200], shape: BoxShape.circle),
child: const Icon(Icons.add, size: 16, color: Colors.black87),
),
),
],
),
],
),
const SizedBox(height: 16),
// 航线方向配置行
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('航线方向', style: TextStyle(fontSize: 16, color: Colors.black87)),
// 设置按钮
ElevatedButton(
onPressed: () {
widget.onSettingTap?.call();
debugPrint('点击了航线方向设置按钮');
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF00C853),
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
),
child: const Text('设置'),
),
],
),
],
);
}
}
// 构建操作按钮
Widget _buildActionButton(IconData icon, String label, bool isEnabled, VoidCallback onTap) {
return GestureDetector(
onTap: isEnabled ? onTap : null,
child: Column(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(color: isEnabled ? Colors.blue : Colors.grey[300], shape: BoxShape.circle),
child: Icon(icon, color: Colors.white),
),
const SizedBox(height: 6),
Text(label, style: TextStyle(color: isEnabled ? Colors.black : Colors.grey)),
],
),
);
}
}