2026-01-18 20:21:14 +08:00
|
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
|
|
import 'package:maibu_satabot_v2/features/devices/domain/entities/device_entity.dart';
|
|
|
|
|
|
import 'package:maibu_satabot_v2/features/devices/domain/repositories/device_repository.dart';
|
|
|
|
|
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/get_user_device_usecase.dart';
|
2026-02-27 13:17:09 +08:00
|
|
|
|
import 'package:maibu_satabot_v2/features/devices/domain/usecases/unbind_device_usecase.dart';
|
2026-01-18 20:21:14 +08:00
|
|
|
|
|
2026-02-26 16:20:02 +08:00
|
|
|
|
import '../../domain/usecases/delete_work_record_usecase.dart';
|
2026-02-26 08:45:37 +08:00
|
|
|
|
import '../../domain/usecases/get_device_location_usecase.dart';
|
2026-02-26 16:20:02 +08:00
|
|
|
|
import '../../domain/usecases/get_work_record_usecase.dart';
|
2026-01-18 20:21:14 +08:00
|
|
|
|
import 'devices_state.dart';
|
|
|
|
|
|
|
|
|
|
|
|
class DevicesCubit extends Cubit<DevicesState> {
|
|
|
|
|
|
final GetUserDeviceUseCase _getUserDeviceUseCase;
|
2026-02-26 08:45:37 +08:00
|
|
|
|
final GetDeviceLocationUseCase _getDeviceLocationUseCase;
|
2026-01-18 20:21:14 +08:00
|
|
|
|
final DeviceRepository repository;
|
2026-02-26 16:20:02 +08:00
|
|
|
|
final GetWorkRecordUseCase _getWorkRecordUseCase;
|
|
|
|
|
|
final DeleteWorkRecordUseCase _deleteWorkRecordUseCase;
|
2026-02-27 13:17:09 +08:00
|
|
|
|
final UnbindDeviceUseCase _unbindDeviceUseCase;
|
2026-01-18 20:21:14 +08:00
|
|
|
|
|
2026-02-27 13:17:09 +08:00
|
|
|
|
DevicesCubit(
|
|
|
|
|
|
this.repository,
|
|
|
|
|
|
this._getUserDeviceUseCase,
|
|
|
|
|
|
this._getDeviceLocationUseCase,
|
|
|
|
|
|
this._getWorkRecordUseCase,
|
|
|
|
|
|
this._deleteWorkRecordUseCase,
|
|
|
|
|
|
this._unbindDeviceUseCase,
|
|
|
|
|
|
) : super(const DevicesState());
|
2026-02-26 16:20:02 +08:00
|
|
|
|
|
2026-02-27 13:17:09 +08:00
|
|
|
|
Future<void> unbindDevice(String deviceId, String deviceName) async {
|
|
|
|
|
|
emit(state.copyWith(isLoading: true, errorMessage: ''));
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
final params = UnbindDeviceParams(deviceId, deviceName);
|
|
|
|
|
|
final result = await _unbindDeviceUseCase.call(params);
|
|
|
|
|
|
|
|
|
|
|
|
result.fold(
|
|
|
|
|
|
(failure) => emit(
|
|
|
|
|
|
state.copyWith(
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
errorMessage: failure.message ?? '解绑设备失败',
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
(successCode) {
|
2026-02-27 14:16:29 +08:00
|
|
|
|
// 核心修复:int 转 bool 条件判断
|
|
|
|
|
|
final isSuccess = successCode == 1; // 显式转为 bool
|
|
|
|
|
|
if (isSuccess) {
|
|
|
|
|
|
final updatedDevices = state.devices?.where((device) {
|
|
|
|
|
|
return device.deviceName != deviceId;
|
|
|
|
|
|
}).toList();
|
2026-02-27 13:17:09 +08:00
|
|
|
|
|
2026-02-27 14:16:29 +08:00
|
|
|
|
emit(
|
|
|
|
|
|
state.copyWith(
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
devices: updatedDevices,
|
|
|
|
|
|
selectedDevice: state.selectedDevice?.deviceName == deviceId
|
|
|
|
|
|
? null
|
|
|
|
|
|
: state.selectedDevice,
|
|
|
|
|
|
errorMessage: '',
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
emit(
|
|
|
|
|
|
state.copyWith(
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
errorMessage: '解绑失败:状态码 $successCode',
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2026-02-27 13:17:09 +08:00
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
emit(
|
2026-02-27 14:16:29 +08:00
|
|
|
|
state.copyWith(isLoading: false, errorMessage: '解绑异常:${e.toString()}'),
|
2026-02-27 13:17:09 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-18 20:21:14 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取所有设备列表
|
|
|
|
|
|
Future<void> fetchAllDevices(String username) async {
|
|
|
|
|
|
emit(state.copyWith(isLoading: true));
|
|
|
|
|
|
try {
|
2026-02-26 08:45:37 +08:00
|
|
|
|
// 网络请求获取列表
|
2026-01-18 20:21:14 +08:00
|
|
|
|
var resultEither = await _getUserDeviceUseCase.call(
|
|
|
|
|
|
GetUserDeviceParams(username),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
resultEither.fold(
|
|
|
|
|
|
(failure) => emit(
|
|
|
|
|
|
state.copyWith(
|
|
|
|
|
|
isLoading: false,
|
2026-02-26 16:20:02 +08:00
|
|
|
|
errorMessage: failure.message, //
|
2026-01-18 20:21:14 +08:00
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
(deviceList) {
|
2026-02-27 13:17:09 +08:00
|
|
|
|
print("设备列表:$deviceList"); // 调试输出
|
2026-01-18 20:21:14 +08:00
|
|
|
|
emit(
|
|
|
|
|
|
state.copyWith(
|
|
|
|
|
|
devices: deviceList,
|
|
|
|
|
|
selectedDevice: deviceList.isNotEmpty ? deviceList.first : null,
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
emit(state.copyWith(isLoading: false, errorMessage: e.toString()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 切换当前选中的设备
|
|
|
|
|
|
void selectDevice(DeviceEntity device) {
|
|
|
|
|
|
emit(state.copyWith(selectedDevice: device));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新单个设备的状态(例如从 Tcp 收到实时电量更新)
|
|
|
|
|
|
void updateDeviceStatus(DeviceEntity updatedDevice) {
|
|
|
|
|
|
final newList = state.devices.map((d) {
|
|
|
|
|
|
return d.deviceName == updatedDevice.deviceName ? updatedDevice : d;
|
|
|
|
|
|
}).toList();
|
|
|
|
|
|
|
|
|
|
|
|
// 如果更新的是当前选中的设备,也要同步更新 selectedDevice
|
|
|
|
|
|
final newSelected =
|
|
|
|
|
|
state.selectedDevice?.deviceName == updatedDevice.deviceName
|
|
|
|
|
|
? updatedDevice
|
|
|
|
|
|
: state.selectedDevice;
|
|
|
|
|
|
|
|
|
|
|
|
emit(state.copyWith(devices: newList, selectedDevice: newSelected));
|
|
|
|
|
|
}
|
2026-02-27 13:17:09 +08:00
|
|
|
|
|
2026-02-26 16:20:02 +08:00
|
|
|
|
/// 切换设备
|
2026-01-18 20:21:14 +08:00
|
|
|
|
Future<void> switchDevice(DeviceEntity device) async {
|
|
|
|
|
|
// 保持现有列表,只改 loading
|
|
|
|
|
|
emit(state.copyWith(isLoading: true));
|
|
|
|
|
|
|
|
|
|
|
|
final result = await repository.switchDevice("app", device.deviceName);
|
|
|
|
|
|
|
|
|
|
|
|
result.fold((l) {
|
|
|
|
|
|
emit(state.copyWith(isLoading: false, errorMessage: l.message));
|
|
|
|
|
|
selectDevice(device);
|
|
|
|
|
|
}, (r) => emit(state.copyWith(isLoading: false, selectedDevice: device)));
|
|
|
|
|
|
}
|
2026-02-27 13:17:09 +08:00
|
|
|
|
|
2026-02-26 16:20:02 +08:00
|
|
|
|
/// 获取设备位置
|
2026-02-26 08:45:37 +08:00
|
|
|
|
Future<void> getDeviceLocation(DeviceEntity device) async {
|
|
|
|
|
|
emit(state.copyWith(isLoading: true));
|
|
|
|
|
|
final result = await _getDeviceLocationUseCase.call(device.deviceName);
|
|
|
|
|
|
result.fold(
|
2026-02-27 13:17:09 +08:00
|
|
|
|
(failure) =>
|
|
|
|
|
|
emit(state.copyWith(isLoading: false, errorMessage: failure.message)),
|
|
|
|
|
|
(location) => emit(
|
|
|
|
|
|
state.copyWith(
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
deviceLatitude: location.latitude,
|
|
|
|
|
|
deviceLongitude: location.longitude,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
2026-02-26 08:45:37 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
2026-02-27 13:17:09 +08:00
|
|
|
|
|
2026-02-26 16:20:02 +08:00
|
|
|
|
///获取记录
|
|
|
|
|
|
Future<void> loadWorkRecords(String userId) async {
|
|
|
|
|
|
emit(state.copyWith(isLoading: true));
|
|
|
|
|
|
final result = await _getWorkRecordUseCase(userId);
|
|
|
|
|
|
result.fold(
|
2026-02-27 13:17:09 +08:00
|
|
|
|
(failure) =>
|
|
|
|
|
|
emit(state.copyWith(isLoading: false, errorMessage: failure.message)),
|
|
|
|
|
|
(records) => emit(state.copyWith(isLoading: false, workRecords: records)),
|
2026-02-26 16:20:02 +08:00
|
|
|
|
);
|
|
|
|
|
|
}
|
2026-02-27 13:17:09 +08:00
|
|
|
|
|
2026-02-26 16:20:02 +08:00
|
|
|
|
/// 删除工作记录
|
|
|
|
|
|
Future<void> deleteWorkRecord(String workName) async {
|
|
|
|
|
|
emit(state.copyWith(isLoading: true));
|
|
|
|
|
|
final result = await _deleteWorkRecordUseCase(workName);
|
|
|
|
|
|
result.fold(
|
2026-02-27 13:17:09 +08:00
|
|
|
|
(failure) =>
|
|
|
|
|
|
emit(state.copyWith(isLoading: false, errorMessage: failure.message)),
|
|
|
|
|
|
(_) => emit(
|
2026-02-26 16:20:02 +08:00
|
|
|
|
state.copyWith(
|
|
|
|
|
|
isLoading: false,
|
2026-02-27 13:17:09 +08:00
|
|
|
|
workRecords: state.workRecords
|
|
|
|
|
|
?.where((record) => record != workName)
|
|
|
|
|
|
.toList(),
|
2026-02-26 16:20:02 +08:00
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2026-01-18 20:21:14 +08:00
|
|
|
|
}
|