344 lines
11 KiB
Dart
344 lines
11 KiB
Dart
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<DeviceTaskState> {
|
||
final GetDeviceTaskPoolUseCase _getDeviceTaskPoolUseCase;
|
||
final CancelTaskUseCase _cancelTaskUseCase;
|
||
final PauseTaskUseCase _pauseTaskUseCase;
|
||
final RecoveryTaskUseCase _recoveryTaskUseCase;
|
||
final ILoggerService _logger = GetIt.I<ILoggerService>();
|
||
|
||
DeviceTaskCubit(
|
||
this._getDeviceTaskPoolUseCase,
|
||
this._cancelTaskUseCase,
|
||
this._pauseTaskUseCase,
|
||
this._recoveryTaskUseCase,
|
||
) : super(const DeviceTaskState());
|
||
|
||
/// 获取任务池并过滤出当前设备的任务
|
||
Future<void> fetchAndFilterTask(String deviceId) async {
|
||
emit(state.copyWith(isLoading: true, errorMessage: null));
|
||
|
||
try {
|
||
// 获取用户信息
|
||
final userCubit = GetIt.I<AppUserCubit>();
|
||
final user = userCubit.state.user;
|
||
if (user == null) {
|
||
emit(state.copyWith(
|
||
isLoading: false,
|
||
errorMessage: '用户未登录',
|
||
));
|
||
return;
|
||
}
|
||
|
||
// 获取场站ID
|
||
final siteCubit = GetIt.I<SiteCubit>();
|
||
final siteId = siteCubit.state.selectedSite?.id;
|
||
if (siteId == null) {
|
||
emit(state.copyWith(
|
||
isLoading: false,
|
||
errorMessage: '未选择场站',
|
||
));
|
||
return;
|
||
}
|
||
|
||
// 调用接口获取任务池
|
||
final result = await _getDeviceTaskPoolUseCase.call(
|
||
GetDeviceTaskPoolParams(
|
||
userId: user.userId ?? '',
|
||
siteId: siteId,
|
||
orgId: user.orgId ?? 0,
|
||
),
|
||
);
|
||
|
||
result.fold(
|
||
(failure) {
|
||
_logger.logWithLevel('❌ 获取任务池失败: ${failure.message}');
|
||
emit(state.copyWith(
|
||
isLoading: false,
|
||
errorMessage: ErrorHandler.getErrorMessage(failure.message),
|
||
shouldShowError: true, // 🔥 标记需要显示错误弹窗
|
||
));
|
||
},
|
||
(taskList) {
|
||
// 🔥 过滤出当前设备 + 活跃状态的任务(NEW, EXECUTING, PAUSE)
|
||
final activeTasks = taskList.where((task) {
|
||
// 1. 设备号匹配
|
||
if (task.deviceId != deviceId) return false;
|
||
|
||
// 2. 状态过滤:只保留新建、执行中、暂停中的任务
|
||
final status = task.taskStatus;
|
||
return status == 'NEW' || // 新建
|
||
status == 'EXECUTING' || // 执行中
|
||
status == 'PAUSE'; // 暂停中
|
||
}).toList();
|
||
|
||
_logger.logWithLevel(
|
||
'✅ 找到 ${activeTasks.length} 个活跃任务',
|
||
);
|
||
|
||
// 🔥 如果有多个任务,保存所有选项供用户选择
|
||
// 如果只有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<void> cancelTask(String deviceId) 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<AppUserCubit>();
|
||
final user = userCubit.state.user;
|
||
final siteCubit = GetIt.I<SiteCubit>();
|
||
final siteId = siteCubit.state.selectedSite?.id;
|
||
|
||
if (user == null || siteId == null) {
|
||
emit(state.copyWith(
|
||
isLoading: false,
|
||
errorMessage: '参数不完整',
|
||
operationType: DeviceTaskOperationType.none,
|
||
));
|
||
return;
|
||
}
|
||
|
||
final params = CancelTaskParams(
|
||
deviceId: deviceId,
|
||
taskId: taskId,
|
||
orgId: user.orgId ?? 0,
|
||
siteId: siteId,
|
||
);
|
||
_logger.logWithLevel('[取消任务] 请求: POST /iot/deviceTask/cancelTask');
|
||
_logger.logWithLevel('[取消任务] 参数: deviceId=$deviceId, taskId=$taskId, orgId=${user.orgId ?? 0}, siteId=$siteId');
|
||
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<void> 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<AppUserCubit>();
|
||
final user = userCubit.state.user;
|
||
final siteCubit = GetIt.I<SiteCubit>();
|
||
final siteId = siteCubit.state.selectedSite?.id;
|
||
|
||
if (user == null || siteId == null) {
|
||
emit(state.copyWith(
|
||
isLoading: false,
|
||
errorMessage: '参数不完整',
|
||
operationType: DeviceTaskOperationType.none,
|
||
));
|
||
return;
|
||
}
|
||
|
||
final params2 = PauseTaskParams(
|
||
deviceId: deviceId,
|
||
taskId: taskId,
|
||
orgId: user.orgId ?? 0,
|
||
siteId: siteId,
|
||
);
|
||
_logger.logWithLevel('[暂停任务] 请求: POST /iot/deviceTask/pauseTask');
|
||
_logger.logWithLevel('[暂停任务] 参数: deviceId=$deviceId, taskId=$taskId, orgId=${user.orgId ?? 0}, 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<void> 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<AppUserCubit>();
|
||
final user = userCubit.state.user;
|
||
final siteCubit = GetIt.I<SiteCubit>();
|
||
final siteId = siteCubit.state.selectedSite?.id;
|
||
|
||
if (user == null || siteId == null) {
|
||
emit(state.copyWith(
|
||
isLoading: false,
|
||
errorMessage: '参数不完整',
|
||
operationType: DeviceTaskOperationType.none,
|
||
));
|
||
return;
|
||
}
|
||
|
||
final params3 = RecoveryTaskParams(
|
||
deviceId: deviceId,
|
||
taskId: taskId,
|
||
orgId: user.orgId ?? 0,
|
||
siteId: siteId,
|
||
);
|
||
_logger.logWithLevel('[恢复任务] 请求: POST /iot/deviceTask/recoveryTask');
|
||
_logger.logWithLevel('[恢复任务] 参数: deviceId=$deviceId, taskId=$taskId, orgId=${user.orgId ?? 0}, 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) {
|
||
emit(state.copyWith(currentTaskId: taskId));
|
||
_logger.logWithLevel('🔄 更新当前任务ID: $taskId');
|
||
}
|
||
|
||
/// 🔥 手动选择任务(用户从弹窗中选择)
|
||
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('🧹 清除当前任务');
|
||
}
|
||
}
|