点击完成生成路径 完成
This commit is contained in:
@@ -4,13 +4,15 @@ class DeviceAddPathPointModel {
|
||||
|
||||
DeviceAddPathPointModel({required this.latitude, required this.longitude});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'latitude': latitude,
|
||||
'longitude': longitude,
|
||||
};
|
||||
Map<String, dynamic> toJson() => {'lat': latitude.toString(), 'lon': longitude.toString()};
|
||||
|
||||
factory DeviceAddPathPointModel.fromJson(Map<String, dynamic> json) => DeviceAddPathPointModel(
|
||||
latitude: json['latitude'],
|
||||
longitude: json['longitude'],
|
||||
);
|
||||
factory DeviceAddPathPointModel.fromJson(Map<String, dynamic> json) {
|
||||
return DeviceAddPathPointModel(
|
||||
latitude: double.parse((json['lat'] ?? json['latitude']).toString()),
|
||||
longitude: double.parse((json['lon'] ?? json['longitude']).toString()),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => '{lat: ${latitude.toString()}, lon: ${longitude.toString()}}';
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import '../models/device_add_path_point_model.dart';
|
||||
import '../models/device_work_area_param_model.dart';
|
||||
|
||||
class PathRepositoryImpl implements PathRepository {
|
||||
/* final String baseUrl = 'https://serviceri.satabot.com'; // 后端接口地址*/
|
||||
/* final UserStorage localTokenStorage;
|
||||
/* final String baseUrl = 'https://serviceri.satabot.com'; // 后端接口地址*/
|
||||
/* final UserStorage localTokenStorage;
|
||||
PathRepositoryImpl({
|
||||
required this.localTokenStorage, // 👈 关键:注入依赖
|
||||
});*/
|
||||
@@ -23,7 +23,6 @@ class PathRepositoryImpl implements PathRepository {
|
||||
required OuterBoundary outer,
|
||||
required List<HoleBoundary> holes,
|
||||
required int workType,
|
||||
|
||||
}) async {
|
||||
final url = Uri.parse('https://servicepathplan.satabot.com/api/path');
|
||||
// ✅ 直接从 GetIt 获取 UserStorage(无需构造函数传参)
|
||||
@@ -33,10 +32,7 @@ class PathRepositoryImpl implements PathRepository {
|
||||
if (token == null) throw Exception('请先登录');
|
||||
|
||||
// ✅ 设置带 token 的 headers
|
||||
final headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': token,
|
||||
};
|
||||
final headers = {'Content-Type': 'application/json', 'Authorization': token};
|
||||
|
||||
final body = jsonEncode({
|
||||
'reference': reference.toJson(),
|
||||
@@ -51,8 +47,10 @@ class PathRepositoryImpl implements PathRepository {
|
||||
final response = await http.post(url, headers: headers, body: body);
|
||||
print('响应体: ${response.body}');
|
||||
final decoded = jsonDecode(response.body) as Map<String, dynamic>;
|
||||
if (decoded['code'] == 200) {
|
||||
final pathJson = decoded['path'];
|
||||
print('解码后的响应: $decoded'); // 调试输出解码后的响应
|
||||
if (decoded['success'] == true) {
|
||||
final pathJson = decoded['data']?['path'];
|
||||
print('路径数据: $pathJson'); // 调试输出路径数据
|
||||
if (pathJson == null) {
|
||||
throw Exception('API returned null for "path"');
|
||||
}
|
||||
@@ -60,6 +58,8 @@ class PathRepositoryImpl implements PathRepository {
|
||||
throw Exception('Expected "path" to be a List, but got ${pathJson.runtimeType}');
|
||||
}
|
||||
final List<dynamic> jsonData = pathJson;
|
||||
print('路径数据1111: $jsonData'); // 调试输出路径数据
|
||||
print('路径数据11112222: ${jsonData.map((item) => DeviceAddPathPointModel.fromJson(item)).toList()}');
|
||||
return jsonData.map((item) => DeviceAddPathPointModel.fromJson(item)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to load path: ${response.statusCode}');
|
||||
@@ -71,18 +71,10 @@ class PathRepositoryImpl implements PathRepository {
|
||||
|
||||
// 保存工作记录
|
||||
@override
|
||||
Future<Map<String, dynamic>> saveWorkRecord({
|
||||
required String workName,
|
||||
required String userId,
|
||||
required String jsonData,
|
||||
}) async {
|
||||
Future<Map<String, dynamic>> saveWorkRecord({required String workName, required String userId, required String jsonData}) async {
|
||||
final url = Uri.parse('https://serviceri.satabot.com/iot/workRecord/add');
|
||||
final headers = {'Content-Type': 'application/json'};
|
||||
final body = jsonEncode({
|
||||
'workName': workName,
|
||||
'userId': userId,
|
||||
'jsonData': jsonData,
|
||||
});
|
||||
final body = jsonEncode({'workName': workName, 'userId': userId, 'jsonData': jsonData});
|
||||
|
||||
try {
|
||||
final response = await http.post(url, headers: headers, body: body);
|
||||
@@ -98,9 +90,7 @@ class PathRepositoryImpl implements PathRepository {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> getWorkRecord({
|
||||
required String userId,
|
||||
}) async {
|
||||
Future<List<Map<String, dynamic>>> getWorkRecord({required String userId}) async {
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
final url = Uri.parse(
|
||||
'https://serviceri.satabot.com/iot/workRecord/selectByUserId',
|
||||
@@ -116,9 +106,7 @@ class PathRepositoryImpl implements PathRepository {
|
||||
throw Exception('API error: ${data['msg'] ?? 'Unknown'}');
|
||||
}
|
||||
} else {
|
||||
throw Exception(
|
||||
'HTTP ${response.statusCode}: ${response.reasonPhrase}',
|
||||
);
|
||||
throw Exception('HTTP ${response.statusCode}: ${response.reasonPhrase}');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Network error in getWorkRecord: $e');
|
||||
@@ -126,16 +114,11 @@ class PathRepositoryImpl implements PathRepository {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> deleteWorkRecord({
|
||||
required String workName,
|
||||
}) async {
|
||||
Future<Map<String, dynamic>> deleteWorkRecord({required String workName}) async {
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
final url =
|
||||
Uri.parse(
|
||||
'https://serviceri.satabot.com/iot/workRecord/deleteByWorkName',
|
||||
).replace(
|
||||
queryParameters: {'workName': workName, '_t': timestamp.toString()},
|
||||
);
|
||||
final url = Uri.parse(
|
||||
'https://serviceri.satabot.com/iot/workRecord/deleteByWorkName',
|
||||
).replace(queryParameters: {'workName': workName, '_t': timestamp.toString()});
|
||||
|
||||
try {
|
||||
final response = await http.get(url);
|
||||
@@ -144,9 +127,7 @@ class PathRepositoryImpl implements PathRepository {
|
||||
if (response.statusCode == 200 && data['code'] == 200) {
|
||||
return data; // 返回 {"code": 200, "msg": "删除成功"}
|
||||
} else {
|
||||
throw Exception(
|
||||
'Delete failed: ${data['msg'] ?? response.reasonPhrase}',
|
||||
);
|
||||
throw Exception('Delete failed: ${data['msg'] ?? response.reasonPhrase}');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Network error in deleteWorkRecord: $e');
|
||||
@@ -155,16 +136,11 @@ class PathRepositoryImpl implements PathRepository {
|
||||
|
||||
/// 选择工作记录
|
||||
@override
|
||||
Future<List<Map<String, dynamic>>> selectWorkRecordByName({
|
||||
required String workName,
|
||||
}) async {
|
||||
Future<List<Map<String, dynamic>>> selectWorkRecordByName({required String workName}) async {
|
||||
final timestamp = DateTime.now().millisecondsSinceEpoch;
|
||||
final url =
|
||||
Uri.parse(
|
||||
'https://serviceri.satabot.com/iot/workRecord/selectByWorkName',
|
||||
).replace(
|
||||
queryParameters: {'workName': workName, '_t': timestamp.toString()},
|
||||
);
|
||||
final url = Uri.parse(
|
||||
'https://serviceri.satabot.com/iot/workRecord/selectByWorkName',
|
||||
).replace(queryParameters: {'workName': workName, '_t': timestamp.toString()});
|
||||
|
||||
try {
|
||||
final response = await http.get(url);
|
||||
@@ -188,9 +164,7 @@ class PathRepositoryImpl implements PathRepository {
|
||||
} else if (rawData is Map) {
|
||||
records = [Map<String, dynamic>.from(rawData)];
|
||||
} else {
|
||||
throw Exception(
|
||||
'Unexpected data type for "data": ${rawData.runtimeType}',
|
||||
);
|
||||
throw Exception('Unexpected data type for "data": ${rawData.runtimeType}');
|
||||
}
|
||||
|
||||
return records;
|
||||
@@ -198,9 +172,7 @@ class PathRepositoryImpl implements PathRepository {
|
||||
throw Exception('API error: ${data['msg'] ?? 'Unknown'}');
|
||||
}
|
||||
} else {
|
||||
throw Exception(
|
||||
'HTTP ${response.statusCode}: ${response.reasonPhrase}',
|
||||
);
|
||||
throw Exception('HTTP ${response.statusCode}: ${response.reasonPhrase}');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Network error in selectWorkRecordByName: $e');
|
||||
|
||||
@@ -59,6 +59,7 @@ class DevicesState extends Equatable {
|
||||
pathData: pathData ?? this.pathData,
|
||||
workRecords: workRecords ?? this.workRecords,
|
||||
operationType: operationType ?? this.operationType, // 更新操作类型
|
||||
generatedPath: generatedPath ?? this.generatedPath, // 更新生成的路径数据
|
||||
);
|
||||
}
|
||||
|
||||
@@ -69,5 +70,7 @@ class DevicesState extends Equatable {
|
||||
deviceLongitude,
|
||||
workRecords,
|
||||
pathData,
|
||||
operationType,
|
||||
generatedPath,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -11,6 +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/network/net_message_dispatcher.dart';
|
||||
import 'package:maibu_satabot_v2/core/network/protocol_decoder.dart';
|
||||
import 'package:maibu_satabot_v2/features/devices/data/models/device_add_path_point_model.dart' as work_area_model;
|
||||
import 'package:maibu_satabot_v2/features/devices/data/models/device_work_area_param_model.dart' 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/domain/usecases/get_work_record_usecase.dart';
|
||||
@@ -1091,6 +1092,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
|
||||
// 4. 获取生成结果并处理
|
||||
final cubitState = context.read<DevicesCubit>().state;
|
||||
print('${cubitState.generatedPath},路径生成结果');
|
||||
if (cubitState.errorMessage != null) {
|
||||
// 生成失败
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('路径生成失败:${cubitState.errorMessage}'), backgroundColor: Colors.red));
|
||||
@@ -1100,21 +1102,22 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
|
||||
debugPrint('生成的路径数据:${cubitState.generatedPath}');
|
||||
|
||||
// 可选:将生成的路径转换为地图可显示的坐标(WGS84 → GCJ02)
|
||||
if (cubitState.generatedPath is List) {
|
||||
if (cubitState.generatedPath is List) {
|
||||
setState(() {
|
||||
// 关键:生成的路径是 WGS84,需转回 GCJ02 才能在高德地图正确显示
|
||||
gcjPathPoints = (cubitState.generatedPath as List).map((point) {
|
||||
// 先取 WGS84 坐标
|
||||
double wgs84Lat = safeToDouble(point['lat']) ?? 0.0;
|
||||
double wgs84Lon = safeToDouble(point['lon']) ?? 0.0;
|
||||
// 转换为 GCJ02
|
||||
// 先将 List<dynamic> 转换为 List<DeviceAddPathPointModel>
|
||||
final pathList = cubitState.generatedPath as List;
|
||||
final typedPathList = pathList.whereType<work_area_model.DeviceAddPathPointModel>().toList();
|
||||
|
||||
// 然后使用 .lat 和 .lon 属性访问
|
||||
gcjPathPoints = typedPathList.map((point) {
|
||||
double wgs84Lat = point.latitude;
|
||||
double wgs84Lon = point.longitude;
|
||||
final gcjPoint = wgs84ToGcj02(wgs84Lat, wgs84Lon);
|
||||
return LatLng(gcjPoint.latitude, gcjPoint.longitude);
|
||||
}).toList();
|
||||
// 外边界也转回 GCJ02 显示(可选,保持和地图坐标系一致)
|
||||
|
||||
gcjOuterPoints = _markedPoints;
|
||||
});
|
||||
// 移动地图到生成的路径中心
|
||||
moveMapToPointsCenter(gcjPathPoints);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user