333 lines
12 KiB
Dart
333 lines
12 KiB
Dart
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: Material(
|
||
color: Colors.transparent,
|
||
shape: const CircleBorder(),
|
||
child: InkWell(
|
||
customBorder: const CircleBorder(),
|
||
splashColor: Colors.white24,
|
||
highlightColor: Colors.white10,
|
||
child: Ink(
|
||
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 Column(
|
||
children: [
|
||
Material(
|
||
color: Colors.transparent,
|
||
shape: const CircleBorder(),
|
||
child: InkWell(
|
||
onTap: isEnabled ? onTap : null, // 关键
|
||
customBorder: const CircleBorder(),
|
||
splashColor: isEnabled ? null : Colors.transparent,
|
||
highlightColor: Colors.transparent,
|
||
child: Ink(
|
||
width: 40,
|
||
height: 40,
|
||
decoration: BoxDecoration(color: isEnabled ? Colors.blue : Colors.grey[300], shape: BoxShape.circle),
|
||
child: Icon(icon, color: isEnabled ? Colors.white : Colors.grey),
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(height: 6),
|
||
Text(label, style: TextStyle(color: isEnabled ? Colors.black : Colors.grey)),
|
||
],
|
||
);
|
||
}
|
||
}
|