优化
This commit is contained in:
@@ -141,14 +141,12 @@ class PathRepositoryImpl implements PathRepository {
|
|||||||
).replace(
|
).replace(
|
||||||
queryParameters: {'workName': workName, '_t': timestamp.toString()},
|
queryParameters: {'workName': workName, '_t': timestamp.toString()},
|
||||||
);
|
);
|
||||||
print('请求URL: $url');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await http.get(url);
|
final response = await http.get(url);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final data = jsonDecode(response.body) as Map<String, dynamic>;
|
final data = jsonDecode(response.body) as Map<String, dynamic>;
|
||||||
print('响应数据: $data');
|
|
||||||
|
|
||||||
if (data['code'] == 200 && data.containsKey('data')) {
|
if (data['code'] == 200 && data.containsKey('data')) {
|
||||||
final dynamic rawData = data['data'];
|
final dynamic rawData = data['data'];
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ class DevicesCubit extends Cubit<DevicesState> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(deviceList) {
|
(deviceList) {
|
||||||
print("设备列表:$deviceList"); // 调试输出
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
devices: deviceList,
|
devices: deviceList,
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart';
|
|||||||
import 'package:maibu_satabot_v2/core/di/injection.dart';
|
import 'package:maibu_satabot_v2/core/di/injection.dart';
|
||||||
import 'package:maibu_satabot_v2/core/network/net_message_dispatcher.dart';
|
import 'package:maibu_satabot_v2/core/network/net_message_dispatcher.dart';
|
||||||
import 'package:maibu_satabot_v2/core/network/protocol_decoder.dart';
|
import 'package:maibu_satabot_v2/core/network/protocol_decoder.dart';
|
||||||
import 'package:maibu_satabot_v2/features/devices/data/models/device_work_area_param_model.dart'
|
import 'package:maibu_satabot_v2/features/devices/data/models/device_work_area_param_model.dart' as work_area_model;
|
||||||
as work_area_model;
|
|
||||||
import 'package:maibu_satabot_v2/features/devices/data/repositories/generate_path_repository_Impl.dart';
|
import 'package:maibu_satabot_v2/features/devices/data/repositories/generate_path_repository_Impl.dart';
|
||||||
import 'package:maibu_satabot_v2/features/devices/domain/usecases/get_work_record_usecase.dart';
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/get_work_record_usecase.dart';
|
||||||
import 'package:maibu_satabot_v2/features/devices/domain/usecases/select_work_record_usecase.dart';
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/select_work_record_usecase.dart';
|
||||||
@@ -20,7 +19,7 @@ import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubi
|
|||||||
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_state.dart';
|
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_state.dart';
|
||||||
import 'package:maibu_satabot_v2/features/home/presentation/widgets/BottomDirectionLine.dart';
|
import 'package:maibu_satabot_v2/features/home/presentation/widgets/BottomDirectionLine.dart';
|
||||||
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/enum.dart';
|
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/enum.dart';
|
||||||
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/input_confirm_dialog.dart';
|
import 'package:maibu_satabot_v2/components/input_confirm_dialog.dart';
|
||||||
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/tracepoint.dart';
|
import 'package:maibu_satabot_v2/features/home/presentation/widgets/common/tracepoint.dart';
|
||||||
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/CenterLocation.dart';
|
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/CenterLocation.dart';
|
||||||
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/HeadingPointer.dart';
|
import 'package:maibu_satabot_v2/features/home/presentation/widgets/map/HeadingPointer.dart';
|
||||||
@@ -38,12 +37,7 @@ class PlotData {
|
|||||||
final String imageUrl; // 图片URL(本地/assets/网络都可)
|
final String imageUrl; // 图片URL(本地/assets/网络都可)
|
||||||
final String? jsonData; // 原始数据的JSON字符串(可选,便于调试或后续使用)
|
final String? jsonData; // 原始数据的JSON字符串(可选,便于调试或后续使用)
|
||||||
|
|
||||||
PlotData({
|
PlotData({required this.id, required this.plotName, required this.imageUrl, this.jsonData});
|
||||||
required this.id,
|
|
||||||
required this.plotName,
|
|
||||||
required this.imageUrl,
|
|
||||||
this.jsonData,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlotDataPath {
|
class PlotDataPath {
|
||||||
@@ -135,9 +129,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 可选:打印验证精度(保留15位小数)
|
// 可选:打印验证精度(保留15位小数)
|
||||||
debugPrint(
|
debugPrint('地图中心更新(高精度):纬度=${_mapCenter.latitude.toStringAsFixed(15)}, 经度=${_mapCenter.longitude.toStringAsFixed(15)}');
|
||||||
'地图中心更新(高精度):纬度=${_mapCenter.latitude.toStringAsFixed(15)}, 经度=${_mapCenter.longitude.toStringAsFixed(15)}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -236,12 +228,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
onConfirm: (plotName) {
|
onConfirm: (plotName) {
|
||||||
_savePlotData(plotName);
|
_savePlotData(plotName);
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('地块「$plotName」保存成功!'), backgroundColor: Colors.green));
|
||||||
SnackBar(
|
|
||||||
content: Text('地块「$plotName」保存成功!'),
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -274,9 +261,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
} else {
|
} else {
|
||||||
debugPrint('无打点可撤回');
|
debugPrint('无打点可撤回');
|
||||||
// 可选:提示用户
|
// 可选:提示用户
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无打点可撤回')));
|
||||||
context,
|
|
||||||
).showSnackBar(const SnackBar(content: Text('暂无打点可撤回')));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,14 +273,10 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
});
|
});
|
||||||
debugPrint('删除成功,已清空所有打点和轨迹');
|
debugPrint('删除成功,已清空所有打点和轨迹');
|
||||||
// 可选:提示用户
|
// 可选:提示用户
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已清空所有打点和轨迹')));
|
||||||
context,
|
|
||||||
).showSnackBar(const SnackBar(content: Text('已清空所有打点和轨迹')));
|
|
||||||
} else {
|
} else {
|
||||||
debugPrint('无打点可删除');
|
debugPrint('无打点可删除');
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('暂无打点可删除')));
|
||||||
context,
|
|
||||||
).showSnackBar(const SnackBar(content: Text('暂无打点可删除')));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,27 +291,19 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
if (permission == LocationPermission.denied) {
|
if (permission == LocationPermission.denied) {
|
||||||
permission = await Geolocator.requestPermission();
|
permission = await Geolocator.requestPermission();
|
||||||
}
|
}
|
||||||
if (permission != LocationPermission.whileInUse &&
|
if (permission != LocationPermission.whileInUse && permission != LocationPermission.always) {
|
||||||
permission != LocationPermission.always) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1️⃣ 首次强制获取定位
|
// 1️⃣ 首次强制获取定位
|
||||||
final position = await Geolocator.getCurrentPosition(
|
final position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.bestForNavigation);
|
||||||
desiredAccuracy: LocationAccuracy.bestForNavigation,
|
|
||||||
);
|
|
||||||
|
|
||||||
final gcj = wgs84ToGcj02(position.latitude, position.longitude);
|
final gcj = wgs84ToGcj02(position.latitude, position.longitude);
|
||||||
_updateLocation(gcj, moveMap: true);
|
_updateLocation(gcj, moveMap: true);
|
||||||
|
|
||||||
// 2️⃣ 实时监听(不再强制移动地图)
|
// 2️⃣ 实时监听(不再强制移动地图)
|
||||||
_positionSub =
|
_positionSub = Geolocator.getPositionStream(locationSettings: const LocationSettings(accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 2))
|
||||||
Geolocator.getPositionStream(
|
.listen((pos) {
|
||||||
locationSettings: const LocationSettings(
|
|
||||||
accuracy: LocationAccuracy.bestForNavigation,
|
|
||||||
distanceFilter: 2,
|
|
||||||
),
|
|
||||||
).listen((pos) {
|
|
||||||
final gcj = wgs84ToGcj02(pos.latitude, pos.longitude);
|
final gcj = wgs84ToGcj02(pos.latitude, pos.longitude);
|
||||||
_updateLocation(gcj, moveMap: false);
|
_updateLocation(gcj, moveMap: false);
|
||||||
});
|
});
|
||||||
@@ -397,25 +370,15 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
|
|
||||||
// 刷新成功提示
|
// 刷新成功提示
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('页面已刷新完成'), backgroundColor: Colors.green, duration: Duration(seconds: 2)));
|
||||||
const SnackBar(
|
|
||||||
content: Text('页面已刷新完成'),
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
duration: Duration(seconds: 2),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 错误处理
|
// 错误处理
|
||||||
debugPrint('刷新失败:$e');
|
debugPrint('刷新失败:$e');
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text('刷新失败:${e.toString().substring(0, 50)}'),
|
).showSnackBar(SnackBar(content: Text('刷新失败:${e.toString().substring(0, 50)}'), backgroundColor: Colors.red, duration: Duration(seconds: 3)));
|
||||||
backgroundColor: Colors.red,
|
|
||||||
duration: Duration(seconds: 3),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// 标记刷新结束
|
// 标记刷新结束
|
||||||
@@ -452,9 +415,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_markedPoints.add(_mapCenter); // 在地图中心打点
|
_markedPoints.add(_mapCenter); // 在地图中心打点
|
||||||
});
|
});
|
||||||
debugPrint(
|
debugPrint('$_markedPoints,新增打点:第${_markedPoints.length}个点,经纬度:${_mapCenter.latitude.toStringAsFixed(20)}, ${_mapCenter.longitude.toStringAsFixed(20)}');
|
||||||
'$_markedPoints,新增打点:第${_markedPoints.length}个点,经纬度:${_mapCenter.latitude.toStringAsFixed(20)}, ${_mapCenter.longitude.toStringAsFixed(20)}',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 新增:返回上一级页面的方法 ==========
|
// ========== 新增:返回上一级页面的方法 ==========
|
||||||
@@ -474,19 +435,13 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
|
|
||||||
// 模拟添加完成点
|
// 模拟添加完成点
|
||||||
void _addCompletePoint() {
|
void _addCompletePoint() {
|
||||||
final newPoint = LatLng(
|
final newPoint = LatLng(39.9042 + (DateTime.now().millisecond / 10000), 116.4074 + (DateTime.now().millisecond / 10000));
|
||||||
39.9042 + (DateTime.now().millisecond / 10000),
|
|
||||||
116.4074 + (DateTime.now().millisecond / 10000),
|
|
||||||
);
|
|
||||||
_traceManager.upsert(newPoint, TPAction.ADD);
|
_traceManager.upsert(newPoint, TPAction.ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模拟更新当前点
|
// 模拟更新当前点
|
||||||
void _updateCurrentPoint() {
|
void _updateCurrentPoint() {
|
||||||
final newPoint = LatLng(
|
final newPoint = LatLng(39.9042 + (DateTime.now().millisecond / 10000), 116.4074 + (DateTime.now().millisecond / 10000));
|
||||||
39.9042 + (DateTime.now().millisecond / 10000),
|
|
||||||
116.4074 + (DateTime.now().millisecond / 10000),
|
|
||||||
);
|
|
||||||
_traceManager.upsert(newPoint);
|
_traceManager.upsert(newPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,23 +465,17 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
// 2. 立即解析并更新状态(在事件回调中,不在 build 中)
|
// 2. 立即解析并更新状态(在事件回调中,不在 build 中)
|
||||||
if (_loadedPlot is List) {
|
if (_loadedPlot is List) {
|
||||||
final List<dynamic> rawList = _loadedPlot as List<dynamic>;
|
final List<dynamic> rawList = _loadedPlot as List<dynamic>;
|
||||||
final pathRecords = rawList
|
final pathRecords = rawList.where((item) => item is Map<String, dynamic>).cast<Map<String, dynamic>>().toList();
|
||||||
.where((item) => item is Map<String, dynamic>)
|
|
||||||
.cast<Map<String, dynamic>>()
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (pathRecords.isNotEmpty) {
|
if (pathRecords.isNotEmpty) {
|
||||||
final selectedPlotPath = PlotDataPath(jsonData: pathRecords.first);
|
final selectedPlotPath = PlotDataPath(jsonData: pathRecords.first);
|
||||||
try {
|
try {
|
||||||
final dynamic nestedJsonRaw =
|
final dynamic nestedJsonRaw = selectedPlotPath.jsonData['jsonData'];
|
||||||
selectedPlotPath.jsonData['jsonData'];
|
|
||||||
|
|
||||||
if (nestedJsonRaw != null && nestedJsonRaw is String) {
|
if (nestedJsonRaw != null && nestedJsonRaw is String) {
|
||||||
final String nestedJsonStr = nestedJsonRaw;
|
final String nestedJsonStr = nestedJsonRaw;
|
||||||
final dynamic parsedJson = jsonDecode(nestedJsonStr);
|
final dynamic parsedJson = jsonDecode(nestedJsonStr);
|
||||||
workMode = parsedJson['planModel'] == WorkMode.bow.value
|
workMode = parsedJson['planModel'] == WorkMode.bow.value ? "弓字模式" : "自定义模式";
|
||||||
? "弓字模式"
|
|
||||||
: "自定义模式";
|
|
||||||
if (parsedJson is Map<String, dynamic>) {
|
if (parsedJson is Map<String, dynamic>) {
|
||||||
final Map<String, dynamic> nestedJson = parsedJson;
|
final Map<String, dynamic> nestedJson = parsedJson;
|
||||||
final dynamic rawPath = nestedJson['path'];
|
final dynamic rawPath = nestedJson['path'];
|
||||||
@@ -606,9 +555,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: _selectedPlot?.id == plot.id
|
color: _selectedPlot?.id == plot.id ? Colors.blue : Colors.grey[100]!,
|
||||||
? Colors.blue
|
|
||||||
: Colors.grey[100]!,
|
|
||||||
width: _selectedPlot?.id == plot.id ? 2 : 1, // 选中项高亮边框
|
width: _selectedPlot?.id == plot.id ? 2 : 1, // 选中项高亮边框
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -645,11 +592,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => _showDeleteConfirmDialog(plot, onDelete),
|
onPressed: () => _showDeleteConfirmDialog(plot, onDelete),
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.delete_outline, color: Colors.redAccent, size: 20),
|
||||||
Icons.delete_outline,
|
|
||||||
color: Colors.redAccent,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
constraints: const BoxConstraints(),
|
constraints: const BoxConstraints(),
|
||||||
),
|
),
|
||||||
@@ -669,9 +612,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
onDelete(plot);
|
onDelete(plot);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已删除地块「${plot.plotName}」')));
|
||||||
context,
|
|
||||||
).showSnackBar(SnackBar(content: Text('已删除地块「${plot.plotName}」')));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -694,13 +635,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||||
boxShadow: [
|
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, -2))],
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black12,
|
|
||||||
blurRadius: 10,
|
|
||||||
offset: Offset(0, -2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -721,11 +656,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
width: 80,
|
width: 80,
|
||||||
height: 80,
|
height: 80,
|
||||||
color: Colors.grey[200],
|
color: Colors.grey[200],
|
||||||
child: const Icon(
|
child: const Icon(Icons.image_outlined, color: Colors.grey, size: 32),
|
||||||
Icons.image_outlined,
|
|
||||||
color: Colors.grey,
|
|
||||||
size: 32,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -737,22 +668,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
_selectedPlot!.plotName,
|
_selectedPlot!.plotName,
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87),
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.black87,
|
|
||||||
),
|
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text('作业模式:$workMode', style: const TextStyle(fontSize: 14, color: Colors.grey)),
|
||||||
'作业模式:$workMode',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -765,16 +686,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
gcjOuterPoints = [];
|
gcjOuterPoints = [];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.close, color: Colors.grey, size: 20),
|
||||||
Icons.close,
|
|
||||||
color: Colors.grey,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(minWidth: 24, minHeight: 24),
|
||||||
minWidth: 24,
|
|
||||||
minHeight: 24,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -784,10 +698,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
// 2. 错误提示(如果加载失败)
|
// 2. 错误提示(如果加载失败)
|
||||||
if (state.errorMessage != null)
|
if (state.errorMessage != null)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
horizontal: 12,
|
|
||||||
vertical: 8,
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.red[50],
|
color: Colors.red[50],
|
||||||
@@ -796,19 +707,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(
|
const Icon(Icons.error_outline, color: Colors.redAccent, size: 16),
|
||||||
Icons.error_outline,
|
|
||||||
color: Colors.redAccent,
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
state.errorMessage!,
|
state.errorMessage!,
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontSize: 14, color: Colors.redAccent),
|
||||||
fontSize: 14,
|
|
||||||
color: Colors.redAccent,
|
|
||||||
),
|
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
@@ -826,36 +730,19 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
// 作业逻辑:使用加载的pathData
|
// 作业逻辑:使用加载的pathData
|
||||||
debugPrint(
|
debugPrint('开始作业:${_selectedPlot!.plotName},路径数据:$gcjPathPoints');
|
||||||
'开始作业:${_selectedPlot!.plotName},路径数据:$gcjPathPoints',
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xFF00C853),
|
backgroundColor: const Color(0xFF00C853),
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
disabledBackgroundColor: Colors.grey[300],
|
disabledBackgroundColor: Colors.grey[300],
|
||||||
disabledForegroundColor: Colors.grey[600],
|
disabledForegroundColor: Colors.grey[600],
|
||||||
),
|
),
|
||||||
child: state.isLoading
|
child: state.isLoading
|
||||||
? const SizedBox(
|
? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white))
|
||||||
width: 20,
|
: const Text('开始作业', style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
|
||||||
height: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const Text(
|
|
||||||
'开始作业',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -867,14 +754,10 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 🔥 改动4:新增方法 - 将Bloc的workRecords转换为PlotData列表
|
// 🔥 改动4:新增方法 - 将Bloc的workRecords转换为PlotData列表
|
||||||
List<PlotData> _convertWorkRecordsToPlotData(
|
List<PlotData> _convertWorkRecordsToPlotData(List<Map<String, dynamic>> records) {
|
||||||
List<Map<String, dynamic>> records,
|
|
||||||
) {
|
|
||||||
return records.map((record) {
|
return records.map((record) {
|
||||||
return PlotData(
|
return PlotData(
|
||||||
id:
|
id: record['id']?.toString() ?? DateTime.now().microsecondsSinceEpoch.toString(), // 唯一ID
|
||||||
record['id']?.toString() ??
|
|
||||||
DateTime.now().microsecondsSinceEpoch.toString(), // 唯一ID
|
|
||||||
plotName: record['workName'] ?? '未命名地块', // 地块名称(从接口字段取)
|
plotName: record['workName'] ?? '未命名地块', // 地块名称(从接口字段取)
|
||||||
imageUrl: record['imgUrl'] ?? '', // 图片URL(从接口字段取,无则为空)
|
imageUrl: record['imgUrl'] ?? '', // 图片URL(从接口字段取,无则为空)
|
||||||
jsonData: record['jsonData'], // 原始数据的JSON字符串(可选,便于调试或后续使用)
|
jsonData: record['jsonData'], // 原始数据的JSON字符串(可选,便于调试或后续使用)
|
||||||
@@ -896,8 +779,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
FlutterMap(
|
FlutterMap(
|
||||||
mapController: _mapController,
|
mapController: _mapController,
|
||||||
options: MapOptions(
|
options: MapOptions(
|
||||||
initialCenter:
|
initialCenter: _currentLatLng ?? const LatLng(39.9042, 116.4074),
|
||||||
_currentLatLng ?? const LatLng(39.9042, 116.4074),
|
|
||||||
initialZoom: 20,
|
initialZoom: 20,
|
||||||
maxZoom: 22,
|
maxZoom: 22,
|
||||||
// 禁止地图点击事件(避免和中心标冲突)
|
// 禁止地图点击事件(避免和中心标冲突)
|
||||||
@@ -944,21 +826,13 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
PolylineLayer(
|
PolylineLayer(
|
||||||
polylines: [
|
polylines: [
|
||||||
for (int i = 0; i < _markedPoints.length - 1; i++)
|
for (int i = 0; i < _markedPoints.length - 1; i++)
|
||||||
Polyline(
|
Polyline(points: [_markedPoints[i], _markedPoints[i + 1]], color: Colors.orange.withOpacity(0.5), strokeWidth: 1.5),
|
||||||
points: [_markedPoints[i], _markedPoints[i + 1]],
|
|
||||||
color: Colors.orange.withOpacity(0.5),
|
|
||||||
strokeWidth: 1.5,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (_markedPoints.isNotEmpty)
|
if (_markedPoints.isNotEmpty)
|
||||||
PolylineLayer(
|
PolylineLayer(
|
||||||
polylines: [
|
polylines: [
|
||||||
Polyline(
|
Polyline(points: [_mapCenter, _markedPoints.last], color: Colors.blue.withOpacity(0.5), strokeWidth: 1.5),
|
||||||
points: [_mapCenter, _markedPoints.last],
|
|
||||||
color: Colors.blue.withOpacity(0.5),
|
|
||||||
strokeWidth: 1.5,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -972,15 +846,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: CustomPaint(
|
child: CustomPaint(
|
||||||
size: const Size(40, 40),
|
size: const Size(40, 40),
|
||||||
painter: HeadingMarkerPainter(
|
painter: HeadingMarkerPainter(headingAngle: _headingAngle),
|
||||||
headingAngle: _headingAngle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (_currentWorkMode == WorkMode.bow &&
|
if (_currentWorkMode == WorkMode.bow && _markedPoints.isNotEmpty)
|
||||||
_markedPoints.isNotEmpty)
|
|
||||||
PolygonLayer(
|
PolygonLayer(
|
||||||
polygons: [
|
polygons: [
|
||||||
Polygon(
|
Polygon(
|
||||||
@@ -1014,18 +885,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Color(0xFF00C853), // 绿色主题色
|
color: Color(0xFF00C853), // 绿色主题色
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
boxShadow: [
|
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 2)],
|
||||||
BoxShadow(color: Colors.black12, blurRadius: 2),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'$index',
|
'$index',
|
||||||
style: const TextStyle(
|
style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold),
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 10,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1044,12 +909,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
child: const Center(
|
child: const Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [CircularProgressIndicator(color: Colors.white, strokeWidth: 3)],
|
||||||
CircularProgressIndicator(
|
|
||||||
color: Colors.white,
|
|
||||||
strokeWidth: 3,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1069,13 +929,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withOpacity(0.8),
|
color: Colors.white.withOpacity(0.8),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [
|
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 3, offset: const Offset(0, 2))],
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black12,
|
|
||||||
blurRadius: 3,
|
|
||||||
offset: const Offset(0, 2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
// 核心:用 Stack 实现点击高亮层 + 图标层
|
// 核心:用 Stack 实现点击高亮层 + 图标层
|
||||||
child: Stack(
|
child: Stack(
|
||||||
@@ -1091,11 +945,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
// 2. 图标层(绝对居中)
|
// 2. 图标层(绝对居中)
|
||||||
const Icon(
|
const Icon(Icons.arrow_back_ios, color: Colors.black87, size: 20),
|
||||||
Icons.arrow_back_ios,
|
|
||||||
color: Colors.black87,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1131,13 +981,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF00C853),
|
color: const Color(0xFF00C853),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
boxShadow: [
|
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 4, offset: const Offset(0, 2))],
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black12,
|
|
||||||
blurRadius: 4,
|
|
||||||
offset: const Offset(0, 2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -1165,8 +1009,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
},
|
},
|
||||||
onListBox: (bool isOpen) {
|
onListBox: (bool isOpen) {
|
||||||
// 🔥 改动5:加载作业记录(原有逻辑保留)
|
// 🔥 改动5:加载作业记录(原有逻辑保留)
|
||||||
final userId =
|
final userId = context.read<AppUserCubit>().state.user?.userId ?? "";
|
||||||
context.read<AppUserCubit>().state.user?.userId ?? "";
|
|
||||||
print('加载作业记录,当前用户ID:$userId');
|
print('加载作业记录,当前用户ID:$userId');
|
||||||
context.read<DevicesCubit>().loadWorkRecords(userId);
|
context.read<DevicesCubit>().loadWorkRecords(userId);
|
||||||
|
|
||||||
@@ -1200,30 +1043,15 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
|
|
||||||
// 1. 校验必要条件(至少需要3个打点才能形成闭合区域)
|
// 1. 校验必要条件(至少需要3个打点才能形成闭合区域)
|
||||||
if (_markedPoints.isEmpty) {
|
if (_markedPoints.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请先添加作业区域打点!'), backgroundColor: Colors.red));
|
||||||
const SnackBar(
|
|
||||||
content: Text('请先添加作业区域打点!'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_markedPoints.length < 3) {
|
if (_markedPoints.length < 3) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业区域至少需要3个打点才能生成路径!'), backgroundColor: Colors.red));
|
||||||
const SnackBar(
|
|
||||||
content: Text('作业区域至少需要3个打点才能生成路径!'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_currentWorkMode == null) {
|
if (_currentWorkMode == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请先选择作业模式!'), backgroundColor: Colors.red));
|
||||||
const SnackBar(
|
|
||||||
content: Text('请先选择作业模式!'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1231,14 +1059,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
// 2. 转换页面数据为 generatePath 所需的参数格式
|
// 2. 转换页面数据为 generatePath 所需的参数格式
|
||||||
// 2.1 参考点(取第一个打点,转换为 WGS84)
|
// 2.1 参考点(取第一个打点,转换为 WGS84)
|
||||||
final firstPoint = _markedPoints.first;
|
final firstPoint = _markedPoints.first;
|
||||||
final wgs84FirstPoint = gcj02ToWgs84(
|
final wgs84FirstPoint = gcj02ToWgs84(firstPoint.latitude, firstPoint.longitude);
|
||||||
firstPoint.latitude,
|
final referencePoint = work_area_model.ReferencePoint(lat: wgs84FirstPoint.latitude, lon: wgs84FirstPoint.longitude);
|
||||||
firstPoint.longitude,
|
|
||||||
);
|
|
||||||
final referencePoint = work_area_model.ReferencePoint(
|
|
||||||
lat: wgs84FirstPoint.latitude,
|
|
||||||
lon: wgs84FirstPoint.longitude,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2.2 航向角(转换为整型,-1表示最优航向则取-1)
|
// 2.2 航向角(转换为整型,-1表示最优航向则取-1)
|
||||||
final heading = _angle == -1 ? -1 : _angle.toInt();
|
final heading = _angle == -1 ? -1 : _angle.toInt();
|
||||||
@@ -1248,23 +1070,15 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
// 将 LatLng 打点转换为 Position 列表(先转 WGS84)
|
// 将 LatLng 打点转换为 Position 列表(先转 WGS84)
|
||||||
position: _markedPoints.map((latLng) {
|
position: _markedPoints.map((latLng) {
|
||||||
// 关键:每个点都转换为 WGS84 坐标系
|
// 关键:每个点都转换为 WGS84 坐标系
|
||||||
final wgs84Point = gcj02ToWgs84(
|
final wgs84Point = gcj02ToWgs84(latLng.latitude, latLng.longitude);
|
||||||
latLng.latitude,
|
return work_area_model.Position(lat: wgs84Point.latitude, lon: wgs84Point.longitude);
|
||||||
latLng.longitude,
|
|
||||||
);
|
|
||||||
return work_area_model.Position(
|
|
||||||
lat: wgs84Point.latitude,
|
|
||||||
lon: wgs84Point.longitude,
|
|
||||||
);
|
|
||||||
}).toList(),
|
}).toList(),
|
||||||
sideWidth: _workDistance,
|
sideWidth: _workDistance,
|
||||||
);
|
);
|
||||||
|
|
||||||
final holes = <work_area_model.HoleBoundary>[];
|
final holes = <work_area_model.HoleBoundary>[];
|
||||||
|
|
||||||
final workType = _currentWorkMode == WorkMode.bow
|
final workType = _currentWorkMode == WorkMode.bow ? 0 : 2; // 注意:这里弓字模式是0,自定义是2(确认和后端一致)
|
||||||
? 0
|
|
||||||
: 2; // 注意:这里弓字模式是0,自定义是2(确认和后端一致)
|
|
||||||
|
|
||||||
// 3. 调用 Cubit 的 generatePath 方法生成路径
|
// 3. 调用 Cubit 的 generatePath 方法生成路径
|
||||||
await context.read<DevicesCubit>().generatePath(
|
await context.read<DevicesCubit>().generatePath(
|
||||||
@@ -1279,44 +1093,24 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
final cubitState = context.read<DevicesCubit>().state;
|
final cubitState = context.read<DevicesCubit>().state;
|
||||||
if (cubitState.errorMessage != null) {
|
if (cubitState.errorMessage != null) {
|
||||||
// 生成失败
|
// 生成失败
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('路径生成失败:${cubitState.errorMessage}'), backgroundColor: Colors.red));
|
||||||
SnackBar(
|
|
||||||
content: Text('路径生成失败:${cubitState.errorMessage}'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else if (cubitState.generatedPath != null) {
|
} else if (cubitState.generatedPath != null) {
|
||||||
// 生成成功
|
// 生成成功
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('路径生成成功!'), backgroundColor: Colors.green));
|
||||||
const SnackBar(
|
|
||||||
content: Text('路径生成成功!'),
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
debugPrint('生成的路径数据:${cubitState.generatedPath}');
|
debugPrint('生成的路径数据:${cubitState.generatedPath}');
|
||||||
|
|
||||||
// 可选:将生成的路径转换为地图可显示的坐标(WGS84 → GCJ02)
|
// 可选:将生成的路径转换为地图可显示的坐标(WGS84 → GCJ02)
|
||||||
if (cubitState.generatedPath is List) {
|
if (cubitState.generatedPath is List) {
|
||||||
setState(() {
|
setState(() {
|
||||||
// 关键:生成的路径是 WGS84,需转回 GCJ02 才能在高德地图正确显示
|
// 关键:生成的路径是 WGS84,需转回 GCJ02 才能在高德地图正确显示
|
||||||
gcjPathPoints = (cubitState.generatedPath as List)
|
gcjPathPoints = (cubitState.generatedPath as List).map((point) {
|
||||||
.map((point) {
|
// 先取 WGS84 坐标
|
||||||
// 先取 WGS84 坐标
|
double wgs84Lat = safeToDouble(point['lat']) ?? 0.0;
|
||||||
double wgs84Lat =
|
double wgs84Lon = safeToDouble(point['lon']) ?? 0.0;
|
||||||
safeToDouble(point['lat']) ?? 0.0;
|
// 转换为 GCJ02
|
||||||
double wgs84Lon =
|
final gcjPoint = wgs84ToGcj02(wgs84Lat, wgs84Lon);
|
||||||
safeToDouble(point['lon']) ?? 0.0;
|
return LatLng(gcjPoint.latitude, gcjPoint.longitude);
|
||||||
// 转换为 GCJ02
|
}).toList();
|
||||||
final gcjPoint = wgs84ToGcj02(
|
|
||||||
wgs84Lat,
|
|
||||||
wgs84Lon,
|
|
||||||
);
|
|
||||||
return LatLng(
|
|
||||||
gcjPoint.latitude,
|
|
||||||
gcjPoint.longitude,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.toList();
|
|
||||||
// 外边界也转回 GCJ02 显示(可选,保持和地图坐标系一致)
|
// 外边界也转回 GCJ02 显示(可选,保持和地图坐标系一致)
|
||||||
gcjOuterPoints = _markedPoints;
|
gcjOuterPoints = _markedPoints;
|
||||||
});
|
});
|
||||||
@@ -1327,14 +1121,9 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 异常处理
|
// 异常处理
|
||||||
debugPrint('路径生成异常:$e');
|
debugPrint('路径生成异常:$e');
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
SnackBar(
|
context,
|
||||||
content: Text(
|
).showSnackBar(SnackBar(content: Text('路径生成异常:${e.toString().substring(0, 50)}'), backgroundColor: Colors.red));
|
||||||
'路径生成异常:${e.toString().substring(0, 50)}',
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 关闭操作面板
|
// 5. 关闭操作面板
|
||||||
@@ -1356,9 +1145,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
},
|
},
|
||||||
onDistanceTap: (distance) {
|
onDistanceTap: (distance) {
|
||||||
_workDistance = distance;
|
_workDistance = distance;
|
||||||
debugPrint(
|
debugPrint('外部处理作业行距距离设置,当前距离:${distance.toStringAsFixed(1)}米');
|
||||||
'外部处理作业行距距离设置,当前距离:${distance.toStringAsFixed(1)}米',
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
onSettingTap: () {
|
onSettingTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -1385,12 +1172,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
initialOptimalHeading: true,
|
initialOptimalHeading: true,
|
||||||
initialDirection: 0.0,
|
initialDirection: 0.0,
|
||||||
onConfirm: (result) {
|
onConfirm: (result) {
|
||||||
debugPrint(
|
debugPrint('最优航向:${result['optimalHeading']},角度:${result['direction']}');
|
||||||
'最优航向:${result['optimalHeading']},角度:${result['direction']}',
|
_angle = result['optimalHeading'] == true ? -1 : result['direction'];
|
||||||
);
|
|
||||||
_angle = result['optimalHeading'] == true
|
|
||||||
? -1
|
|
||||||
: result['direction'];
|
|
||||||
debugPrint('外部处理航线方向设置,当前角度:${_angle}');
|
debugPrint('外部处理航线方向设置,当前角度:${_angle}');
|
||||||
setState(() => _directionBoxOpen = false);
|
setState(() => _directionBoxOpen = false);
|
||||||
},
|
},
|
||||||
@@ -1404,9 +1187,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
if (_isListBoxOpen)
|
if (_isListBoxOpen)
|
||||||
BlocBuilder<DevicesCubit, DevicesState>(
|
BlocBuilder<DevicesCubit, DevicesState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final plotList = _convertWorkRecordsToPlotData(
|
final plotList = _convertWorkRecordsToPlotData(state.workRecords ?? []);
|
||||||
state.workRecords ?? [],
|
|
||||||
);
|
|
||||||
|
|
||||||
return Positioned.fill(
|
return Positioned.fill(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -1419,48 +1200,27 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
_isListBoxOpen = false;
|
_isListBoxOpen = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(color: Colors.black.withOpacity(0.3)),
|
||||||
color: Colors.black.withOpacity(0.3),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.vertical(
|
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||||
top: Radius.circular(16),
|
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10, offset: Offset(0, -2))],
|
||||||
),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black12,
|
|
||||||
blurRadius: 10,
|
|
||||||
offset: Offset(0, -2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
constraints: const BoxConstraints(
|
|
||||||
maxHeight: 600,
|
|
||||||
minHeight: 200,
|
|
||||||
),
|
),
|
||||||
|
constraints: const BoxConstraints(maxHeight: 600, minHeight: 200),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
horizontal: 16,
|
|
||||||
vertical: 12,
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'地块列表(共${plotList.length}条)',
|
'地块列表(共${plotList.length}条)',
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87),
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.black87,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -1468,11 +1228,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
_isListBoxOpen = false;
|
_isListBoxOpen = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: const Icon(
|
icon: const Icon(Icons.close, color: Colors.grey, size: 20),
|
||||||
Icons.close,
|
|
||||||
color: Colors.grey,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -1482,51 +1238,24 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
|||||||
child: plotList.isEmpty
|
child: plotList.isEmpty
|
||||||
? const Center(
|
? const Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(Icons.inbox_outlined, color: Colors.grey, size: 48),
|
||||||
Icons.inbox_outlined,
|
|
||||||
color: Colors.grey,
|
|
||||||
size: 48,
|
|
||||||
),
|
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Text(
|
Text('暂无地块数据', style: TextStyle(color: Colors.grey, fontSize: 16)),
|
||||||
'暂无地块数据',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.grey,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
vertical: 8,
|
|
||||||
),
|
|
||||||
itemCount: plotList.length,
|
itemCount: plotList.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final plot = plotList[index];
|
final plot = plotList[index];
|
||||||
// 传入删除回调(调用Bloc的删除方法)
|
// 传入删除回调(调用Bloc的删除方法)
|
||||||
return _buildPlotListItem(plot, (
|
return _buildPlotListItem(plot, (deletedPlot) async {
|
||||||
deletedPlot,
|
await context.read<DevicesCubit>().deleteWorkRecord(deletedPlot.plotName);
|
||||||
) async {
|
final userId = context.read<AppUserCubit>().state.user?.userId ?? "";
|
||||||
await context
|
await context.read<DevicesCubit>().loadWorkRecords(userId);
|
||||||
.read<DevicesCubit>()
|
|
||||||
.deleteWorkRecord(
|
|
||||||
deletedPlot.plotName,
|
|
||||||
);
|
|
||||||
final userId =
|
|
||||||
context
|
|
||||||
.read<AppUserCubit>()
|
|
||||||
.state
|
|
||||||
.user
|
|
||||||
?.userId ??
|
|
||||||
"";
|
|
||||||
await context
|
|
||||||
.read<DevicesCubit>()
|
|
||||||
.loadWorkRecords(userId);
|
|
||||||
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
@@ -1602,13 +1331,7 @@ bool _outOfChina(double lat, double lon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double _transformLat(double x, double y) {
|
double _transformLat(double x, double y) {
|
||||||
double ret =
|
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(x.abs());
|
||||||
-100.0 +
|
|
||||||
2.0 * x +
|
|
||||||
3.0 * y +
|
|
||||||
0.2 * y * y +
|
|
||||||
0.1 * x * y +
|
|
||||||
0.2 * sqrt(x.abs());
|
|
||||||
ret += (20.0 * sin(6.0 * x * _pi) + 20.0 * sin(2.0 * x * _pi)) * 2.0 / 3.0;
|
ret += (20.0 * sin(6.0 * x * _pi) + 20.0 * sin(2.0 * x * _pi)) * 2.0 / 3.0;
|
||||||
ret += (20.0 * sin(y * _pi) + 40.0 * sin(y / 3.0 * _pi)) * 2.0 / 3.0;
|
ret += (20.0 * sin(y * _pi) + 40.0 * sin(y / 3.0 * _pi)) * 2.0 / 3.0;
|
||||||
ret += (160.0 * sin(y / 12.0 * _pi) + 320 * sin(y * _pi / 30.0)) * 2.0 / 3.0;
|
ret += (160.0 * sin(y / 12.0 * _pi) + 320 * sin(y * _pi / 30.0)) * 2.0 / 3.0;
|
||||||
@@ -1616,11 +1339,9 @@ double _transformLat(double x, double y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double _transformLon(double x, double y) {
|
double _transformLon(double x, double y) {
|
||||||
double ret =
|
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(x.abs());
|
||||||
300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(x.abs());
|
|
||||||
ret += (20.0 * sin(6.0 * x * _pi) + 20.0 * sin(2.0 * x * _pi)) * 2.0 / 3.0;
|
ret += (20.0 * sin(6.0 * x * _pi) + 20.0 * sin(2.0 * x * _pi)) * 2.0 / 3.0;
|
||||||
ret += (20.0 * sin(x * _pi) + 40.0 * sin(x / 3.0 * _pi)) * 2.0 / 3.0;
|
ret += (20.0 * sin(x * _pi) + 40.0 * sin(x / 3.0 * _pi)) * 2.0 / 3.0;
|
||||||
ret +=
|
ret += (150.0 * sin(x / 12.0 * _pi) + 300.0 * sin(x / 30.0 * _pi)) * 2.0 / 3.0;
|
||||||
(150.0 * sin(x / 12.0 * _pi) + 300.0 * sin(x / 30.0 * _pi)) * 2.0 / 3.0;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,6 @@ include: package:flutter_lints/flutter.yaml
|
|||||||
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
|
||||||
|
formatter:
|
||||||
|
line-length: 120
|
||||||
|
|||||||
Reference in New Issue
Block a user