Files
feature-next-arch/lib/features/devices/presentation/bloc/device_task_cubit.dart
2026-08-07 08:49:29 +08:00

352 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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('🧹 清除当前任务');
}
/// 🔥 退出登录时清空所有状态
void clearAll() {
if (!isClosed) {
emit(const DeviceTaskState());
}
_logger.logWithLevel('🧹 [DeviceTaskCubit] clearAll - 所有状态已重置');
}
}