import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:get_it/get_it.dart'; import '../../../../core/app/app_user_cubit.dart'; import '../../../../core/logging/i_logger_service.dart'; import '../../../../core/network/error_handler.dart'; import '../../../../features/v2/site/presentation/cubit/site_cubit.dart'; import '../../domain/entities/device_task_entity.dart'; // 🔥 新增 import '../../domain/usecases/cancel_task_usecase.dart'; import '../../domain/usecases/get_device_task_pool_usecase.dart'; import '../../domain/usecases/pause_task_usecase.dart'; import '../../domain/usecases/recovery_task_usecase.dart'; import 'device_task_state.dart'; class DeviceTaskCubit extends Cubit { final GetDeviceTaskPoolUseCase _getDeviceTaskPoolUseCase; final CancelTaskUseCase _cancelTaskUseCase; final PauseTaskUseCase _pauseTaskUseCase; final RecoveryTaskUseCase _recoveryTaskUseCase; final ILoggerService _logger = GetIt.I(); DeviceTaskCubit( this._getDeviceTaskPoolUseCase, this._cancelTaskUseCase, this._pauseTaskUseCase, this._recoveryTaskUseCase, ) : super(const DeviceTaskState()); /// 获取任务池并过滤出当前设备的任务 Future fetchAndFilterTask(String deviceId) async { emit(state.copyWith(isLoading: true, errorMessage: null)); try { // 获取用户信息 final userCubit = GetIt.I(); final user = userCubit.state.user; if (user == null) { emit(state.copyWith(isLoading: false, errorMessage: '用户未登录')); return; } // 获取场站信息(siteId 和 orgId 都从当前场站取) final siteCubit = GetIt.I(); final selectedSite = siteCubit.state.selectedSite; final siteId = selectedSite?.id; final orgId = selectedSite?.orgId ?? 0; if (siteId == null) { emit(state.copyWith(isLoading: false, errorMessage: '未选择场站')); return; } // 调用接口获取任务池 final result = await _getDeviceTaskPoolUseCase.call( GetDeviceTaskPoolParams( userId: user.userId ?? '', siteId: siteId, orgId: orgId, ), ); result.fold( (failure) { _logger.logWithLevel('❌ 获取任务池失败: ${failure.message}'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(failure.message), shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); }, (taskList) { // 🔥 过滤出当前设备 + 活跃状态的任务(NEW, EXECUTING, PAUSE, CANCELING, FAILED) final activeTasks = taskList.where((task) { // 1. 设备号匹配 if (task.deviceId != deviceId) return false; // 2. 状态过滤:保留新建、执行中、暂停中、取消中、执行失败的任务 final status = task.taskStatus; return status == 'NEW' || // 新建 status == 'EXECUTING' || // 执行中 status == 'PAUSE' || // 暂停中 status == 'CANCELING' || // 取消中(用户可处理) status == 'FAILED'; // 执行失败(用户可恢复或取消) }).toList(); _logger.logWithLevel( '✅ [fetchAndFilterTask] deviceId=$deviceId, 任务池总数=${taskList.length}, 过滤后活跃任务数=${activeTasks.length}', ); for (final t in taskList) { _logger.logWithLevel( ' - taskId=${t.id}, deviceId=${t.deviceId}, status=${t.taskStatus}', ); } // 🔥 如果有多个任务,保存所有选项供用户选择 // 如果只有1个,直接选中 final currentTask = activeTasks.isNotEmpty ? activeTasks.first : null; emit( state.copyWith( isLoading: false, taskPool: taskList, currentTask: currentTask, currentTaskId: currentTask?.id, activeTasks: activeTasks, ), ); }, ); } catch (e) { _logger.logWithLevel('❌ 获取任务池异常: $e'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(e), shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); } } /// 取消任务 Future cancelTask(String deviceId, {bool forceCancel = true}) async { final taskId = state.currentTaskId; if (taskId == null) { emit(state.copyWith(errorMessage: '无可用任务')); return; } emit( state.copyWith( isLoading: true, operationType: DeviceTaskOperationType.cancel, ), ); try { final userCubit = GetIt.I(); final user = userCubit.state.user; final siteCubit = GetIt.I(); final selectedSite = siteCubit.state.selectedSite; final siteId = selectedSite?.id; final orgId = selectedSite?.orgId ?? 0; if (user == null || siteId == null) { emit( state.copyWith( isLoading: false, errorMessage: '参数不完整', operationType: DeviceTaskOperationType.none, ), ); return; } final params = CancelTaskParams( deviceId: deviceId, taskId: taskId, orgId: orgId, siteId: siteId, forceCancel: forceCancel, ); _logger.logWithLevel('[取消任务] 请求: POST /iot/deviceTask/cancelTask'); _logger.logWithLevel( '[取消任务] 参数: deviceId=$deviceId, taskId=$taskId, orgId=$orgId, siteId=$siteId, forceCancel=$forceCancel', ); final result = await _cancelTaskUseCase.call(params); result.fold( (failure) { _logger.logWithLevel('[取消任务] 响应失败: ${failure.message}'); _logger.logWithLevel('❌ 取消任务失败: ${failure.message}'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(failure.message), operationType: DeviceTaskOperationType.none, shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); }, (success) { _logger.logWithLevel('[取消任务] 响应成功: $success'); _logger.logWithLevel('✅ 取消任务成功'); emit( state.copyWith( isLoading: false, operationType: DeviceTaskOperationType.none, ), ); }, ); } catch (e) { _logger.logWithLevel('❌ 取消任务异常: $e'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(e), operationType: DeviceTaskOperationType.none, shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); } } /// 暂停任务 Future pauseTask(String deviceId) async { final taskId = state.currentTaskId; if (taskId == null) { emit(state.copyWith(errorMessage: '无可用任务')); return; } emit( state.copyWith( isLoading: true, operationType: DeviceTaskOperationType.pause, ), ); try { final userCubit = GetIt.I(); final user = userCubit.state.user; final siteCubit = GetIt.I(); final selectedSite = siteCubit.state.selectedSite; final siteId = selectedSite?.id; final orgId = selectedSite?.orgId ?? 0; if (user == null || siteId == null) { emit( state.copyWith( isLoading: false, errorMessage: '参数不完整', operationType: DeviceTaskOperationType.none, ), ); return; } final params2 = PauseTaskParams( deviceId: deviceId, taskId: taskId, orgId: orgId, siteId: siteId, ); _logger.logWithLevel('[暂停任务] 请求: POST /iot/deviceTask/pauseTask'); _logger.logWithLevel( '[暂停任务] 参数: deviceId=$deviceId, taskId=$taskId, orgId=$orgId, siteId=$siteId', ); final result = await _pauseTaskUseCase.call(params2); result.fold( (failure) { _logger.logWithLevel('[暂停任务] 响应失败: ${failure.message}'); _logger.logWithLevel('❌ 暂停任务失败: ${failure.message}'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(failure.message), operationType: DeviceTaskOperationType.none, shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); }, (success) { _logger.logWithLevel('[暂停任务] 响应成功: $success'); _logger.logWithLevel('✅ 暂停任务成功'); emit( state.copyWith( isLoading: false, operationType: DeviceTaskOperationType.none, ), ); }, ); } catch (e) { _logger.logWithLevel('❌ 暂停任务异常: $e'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(e), operationType: DeviceTaskOperationType.none, shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); } } /// 恢复任务 Future recoveryTask(String deviceId) async { final taskId = state.currentTaskId; if (taskId == null) { emit(state.copyWith(errorMessage: '无可用任务')); return; } emit( state.copyWith( isLoading: true, operationType: DeviceTaskOperationType.recovery, ), ); try { final userCubit = GetIt.I(); final user = userCubit.state.user; final siteCubit = GetIt.I(); final selectedSite = siteCubit.state.selectedSite; final siteId = selectedSite?.id; final orgId = selectedSite?.orgId ?? 0; if (user == null || siteId == null) { emit( state.copyWith( isLoading: false, errorMessage: '参数不完整', operationType: DeviceTaskOperationType.none, ), ); return; } final params3 = RecoveryTaskParams( deviceId: deviceId, taskId: taskId, orgId: orgId, siteId: siteId, ); _logger.logWithLevel('[恢复任务] 请求: POST /iot/deviceTask/recoveryTask'); _logger.logWithLevel( '[恢复任务] 参数: deviceId=$deviceId, taskId=$taskId, orgId=$orgId, siteId=$siteId', ); final result = await _recoveryTaskUseCase.call(params3); result.fold( (failure) { _logger.logWithLevel('[恢复任务] 响应失败: ${failure.message}'); _logger.logWithLevel('❌ 恢复任务失败: ${failure.message}'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(failure.message), operationType: DeviceTaskOperationType.none, shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); }, (data) { _logger.logWithLevel('[恢复任务] 响应成功: $data'); _logger.logWithLevel('✅ 恢复任务成功: $data'); emit( state.copyWith( isLoading: false, operationType: DeviceTaskOperationType.none, ), ); }, ); } catch (e) { _logger.logWithLevel('❌ 恢复任务异常: $e'); emit( state.copyWith( isLoading: false, errorMessage: ErrorHandler.getErrorMessage(e), operationType: DeviceTaskOperationType.none, shouldShowError: true, // 🔥 标记需要显示错误弹窗 ), ); } } /// 更新当前任务ID(当选择新航线时调用) void updateCurrentTaskId(int taskId) { // 🔥 只有 activeTasks 非空时才设置 currentTask,避免信息栏一直显示 DeviceTaskEntity? taskEntity; if (state.activeTasks.isNotEmpty) { taskEntity = state.activeTasks.firstWhere( (t) => t.id == taskId, orElse: () => DeviceTaskEntity( id: taskId, deviceId: '', taskStatus: 'EXECUTING', taskStatusTranslate: '执行中', ), ); } emit(state.copyWith(currentTaskId: taskId, currentTask: taskEntity)); _logger.logWithLevel( '🔄 更新当前任务ID: $taskId, activeTasks: ${state.activeTasks.length}, currentTask: ${taskEntity?.taskStatus ?? "null"}', ); } /// 🔥 手动选择任务(用户从弹窗中选择) void selectTask(DeviceTaskEntity task) { _logger.logWithLevel('✅ 用户选择任务ID: ${task.id}, 状态: ${task.taskStatus}'); emit(state.copyWith(currentTask: task, currentTaskId: task.id)); } /// 清除当前任务 void clearCurrentTask() { emit(state.copyWith(currentTask: null, currentTaskId: null)); _logger.logWithLevel('🧹 清除当前任务'); } /// 🔥 退出登录时清空所有状态 void clearAll() { if (!isClosed) { emit(const DeviceTaskState()); } _logger.logWithLevel('🧹 [DeviceTaskCubit] clearAll - 所有状态已重置'); } }