集成接口 开始执行任务的领域层和数据层和UI层的开发啊(待测试)

集成功能 暂停 取消功能 恢复功能的接口的领域层和数据层的开发 下一步待集成到页面上
优化功能,优化了接口异常和未知异常对页面渲染的影响对用户的体验的不好情况。具体通过弹窗友好提示!
优化更新了tcp指示灯点击出现机器状态中添加选中设备的编号 方便用户使用的明白明了!。
优化更新关闭了tcp重连操作内链条中的获取用户设备和切换设备操作项。
调整了获取无人机状态信息的更新频率 为14秒一次
This commit is contained in:
2026-06-16 17:34:00 +08:00
parent 52fe17c0d5
commit 71aea48d9f
61 changed files with 2896 additions and 1648 deletions

View File

@@ -16,6 +16,7 @@ import 'package:latlong2/latlong.dart';
import 'package:maibu_satabot_v2/components/confrim_dialog.dart';
import 'package:maibu_satabot_v2/components/toast.dart';
import 'package:maibu_satabot_v2/core/app/app_user_cubit.dart';
import 'package:maibu_satabot_v2/features/remote_control/presentation/bloc/remote_control_cubit.dart';
import 'package:maibu_satabot_v2/core/consts/tcp_consts.dart';
import 'package:maibu_satabot_v2/core/di/injection.dart';
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
@@ -28,6 +29,7 @@ import 'package:maibu_satabot_v2/features/devices/data/models/device_work_area_p
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';
import 'package:maibu_satabot_v2/features/devices/domain/usecases/create_device_task_usecase.dart';
import 'package:maibu_satabot_v2/features/devices/domain/usecases/select_work_record_usecase.dart';
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/device_status_bloc.dart';
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/device_status_event.dart';
@@ -782,15 +784,10 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
Future<void> _savePlotData(String plotName, String? imgBase64) async {
final loc = AppLocalizations.of(context);
// 1. 获取用户ID
final userId = context.read<AppUserCubit>().state.user?.userId ?? "";
if (userId.isEmpty) {
_showPageToast(
message: loc.translate('route_planning.user_id_empty'),
type: ToastType.error,
);
//ToastUtils.showError(context, '用户ID为空,无法保存!');
// 🔥 V2 适配:使用 SiteCubit 获取站点ID(从 v2 首页场站选择获取,有默认值)
final siteId = sl<SiteCubit>().state.selectedSite?.id;
if (siteId == null) {
_showPageToast(message: '请先在场站列表中选择一个场站!', type: ToastType.error);
return;
}
for (var i = 0; i < typedPathList.length; i++) {
@@ -834,7 +831,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
// 3. 构造 workRecord (包裹一层)
final Map<String, dynamic> workRecord = {
'workName': plotName,
'userId': userId,
'siteId': siteId, // 修改:使用 siteId 代替 userId
'jsonData': jsonEncode(savePath), // 将 savePath 转为 JSON 字符串
};
final String workRecordJson = jsonEncode(workRecord);
@@ -1372,6 +1369,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
return GestureDetector(
// 核心:点击列表项触发选中逻辑
onTap: () async {
// 🔥 添加日志:打印选中的路线任务详情
debugPrint('📋 [路径规划] 选中路线任务:');
debugPrint(' ├─ 地块名称: ${plot.plotName}');
debugPrint(' └─ 数据ID: ${plot.id}');
// 【优化1】第一步就UI响应,不卡手
setState(() {
_isListBoxOpen = false;
@@ -1969,13 +1971,96 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
/// 开始作业
void _startWork() async {
// 🔥 V2 适配:使用接口方式执行作业,不再使用 TCP
// 1. 校验选中的路线
if (_selectedPlot == null) {
_showPageToast(message: "请先选择一个路线任务", type: ToastType.info);
return;
}
// 2. 获取设备ID(从 RemoteControlCubit 的 targetDevice)
final targetDevice = context.read<RemoteControlCubit>().state.targetDevice;
final deviceId = targetDevice?.deviceName;
if (deviceId == null || deviceId.isEmpty) {
_showPageToast(message: "请先选择一个设备", type: ToastType.info);
return;
}
// 3. 获取路线ID(从选中的路线任务)
final routeId = int.tryParse(_selectedPlot!.id);
if (routeId == null) {
_showPageToast(message: "路线ID无效", type: ToastType.error);
return;
}
// 4. 获取场站ID(从 SiteCubit 的 selectedSite)
final siteId = sl<SiteCubit>().state.selectedSite?.id;
if (siteId == null) {
_showPageToast(message: "请先选择一个场站", type: ToastType.info);
return;
}
// 5. 打印请求参数日志
debugPrint('🚀 [开始作业] 请求参数:');
debugPrint(' ├─ deviceId: $deviceId');
debugPrint(' ├─ routeId: $routeId');
debugPrint(' └─ siteId: $siteId');
// 6. 更新UI状态
setState(() {
isStopWork = false;
isStartWork = true;
_workStatus = WorkStatus.working;
_traceManager.reset();
tracePoint?.clear();
gctracePoint?.clear();
});
// 7. 更新应用状态
context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
try {
// 8. 调用接口创建设备任务
final result = await sl<CreateDeviceTaskUseCase>().execute(
deviceId: deviceId,
routeId: routeId,
siteId: siteId,
);
result.fold(
(failure) {
// 失败
debugPrint('❌ [开始作业] 创建设备任务失败: $failure');
_showPageToast(message: "作业启动失败", type: ToastType.error);
setState(() {
isStartWork = false;
_workStatus = WorkStatus.idle;
});
},
(_) {
// 成功
debugPrint('✅ [开始作业] 创建设备任务成功');
_showPageToast(message: "作业已开始", type: ToastType.success);
_saveDataToLocal();
},
);
} catch (e) {
debugPrint('❌ [开始作业] 异常: $e');
_showPageToast(message: "作业启动异常: $e", type: ToastType.error);
setState(() {
isStartWork = false;
_workStatus = WorkStatus.idle;
});
}
// ============ 以下是原有的 TCP 方式代码,已注释 ============
/*
if (startWorkList.isEmpty) {
_showPageToast(message: "作业列表为空,请重新选择路径", type: ToastType.info);
//ToastUtils.showInfo(context, '作业列表为空,请重新选择路径');
return;
}
_traceManager.setMode(TPMode.LOCATION);
//_traceManager.reset();
tracePoint = _traceManager.getTracePoint();
gctracePoint = batchWgs84ToGcj02(tracePoint!);
_logger.log("[当前轨迹模式][转换后gctracePoint]开始作业: $tracePoint");
@@ -1984,18 +2069,14 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
setState(() {
isStopWork = false;
isStartWork = true; // 🔥 关键:停止作业标志
isStartWork = true;
_workStatus = WorkStatus.working;
_traceManager.reset();
tracePoint?.clear();
gctracePoint?.clear();
//_traceManager.setMode(TPMode.NAVIGATION);
});
// 🔥 核心修复:先更新 AppState 为 routePlanning
context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
// 🔥 延迟一下,确保状态已更新
await Future.delayed(const Duration(milliseconds: 100));
debugPrint('⚙️ 开始类型转换...');
@@ -2007,19 +2088,12 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
);
}).toList();
final Queue<work_area_model.DeviceAddPathPointModel> pathQueue = Queue.from(
typedList,
);
// 步骤 3:调用 Cubit 方法(类型匹配)
final Queue<work_area_model.DeviceAddPathPointModel> pathQueue = Queue.from(typedList);
await context.read<DevicesCubit>().startRoutePlanning(pathQueue);
///context.read<DevicesCubit>().updateAppState(AppState.routePlanning);
// 可选:显示作业提示
_showPageToast(message: "作业已开始", type: ToastType.success);
//ToastUtils.showSuccess(context, '作业已开始');
_saveDataToLocal();
//ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('作业已开始'), backgroundColor: Colors.green));
*/
}
/// 暂停作业
@@ -2303,7 +2377,8 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
headingStatus == 0
? null
: () {
_startWork();
//@开始作业通过后端接口
// _startWork();
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF00C853),
@@ -2344,6 +2419,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
height: 50,
child: ElevatedButton(
onPressed: () =>
//@暂停工作通过接口、恢复(继续)工作通过接口
_workStatus == WorkStatus.working
? _pauseWork()
: _resumeWork(),
@@ -2487,7 +2563,7 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
}).toList();
}
// ========== 抽象:生成路径的核心函数 ==========
// ========== 抽象:生成路径的核心函数(打点函数) ==========
Future<void> _generatePath({bool showTips = true}) async {
if (_currentWorkMode == WorkMode.custom) {
setState(() {
@@ -2742,10 +2818,11 @@ class _MapPageEnterpriseState extends State<MapPageEnterprise> {
final menuHeight = 16 * 6; // 假设 VerticalFloatMenu 有 6 个选项,每个高度为 56
final maxTop = screenHeight - menuHeight;
final userState = context.watch<AppUserCubit>().state;
// 🔥 V2 适配:使用 RemoteControlCubit 的 targetDevice 保持一致性
final deviceId = context
.watch<DevicesCubit>()
.watch<RemoteControlCubit>()
.state
.selectedDevice
.targetDevice
?.deviceName;
if (deviceId != null &&