You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

228 lines
6.4 KiB

// modules/problem/controllers/problem_controller.dart
import 'package:dio/dio.dart';
import 'package:get/get.dart' hide MultipartFile, FormData;
import 'dart:io';
import 'package:path/path.dart' as path;
import '../../../data/models/problem_model.dart';
import '../../../data/providers/local_database.dart';
import '../../../data/providers/connectivity_provider.dart'; // 更新路径
class ProblemController extends GetxController {
final LocalDatabase _localDatabase;
final RxList<Problem> problems = <Problem>[].obs;
final RxBool isLoading = false.obs;
final Dio _dio;
final ConnectivityProvider _connectivityProvider;
ProblemController({
required LocalDatabase localDatabase,
required Dio dio,
required ConnectivityProvider connectivityProvider,
}) : _localDatabase = localDatabase,
_dio = dio,
_connectivityProvider = connectivityProvider;
// 使用 provider 中的 isOnline
RxBool get isOnline => _connectivityProvider.isOnline;
List<Problem> get selectedProblems {
return problems.where((p) => p.isChecked.value).toList();
}
List<Problem> get unuploadedProblems {
return problems.where((p) => !p.isUploaded).toList();
}
@override
void onInit() {
super.onInit();
loadProblems();
}
Future<void> loadProblems() async {
isLoading.value = true;
try {
problems.value = await _localDatabase.getProblems();
} catch (e) {
Get.snackbar('错误', '加载问题失败: $e');
rethrow;
} finally {
isLoading.value = false;
}
}
Future<void> addProblem(Problem problem) async {
try {
if (problem.id == null) {
problem = problem.copyWith(
id: DateTime.now().millisecondsSinceEpoch.toString(),
);
}
await _localDatabase.insertProblem(problem);
problems.add(problem);
} catch (e) {
Get.snackbar('错误', '保存问题失败: $e');
rethrow;
}
}
Future<void> updateProblem(Problem problem) async {
try {
await _localDatabase.updateProblem(problem);
final index = problems.indexWhere((p) => p.id == problem.id);
if (index != -1) {
problems[index] = problem;
}
} catch (e) {
Get.snackbar('错误', '更新问题失败: $e');
rethrow;
}
}
Future<void> deleteProblem(Problem problem) async {
try {
if (problem.id != null) {
await _localDatabase.deleteProblem(problem.id!);
problems.remove(problem);
await _deleteProblemImages(problem);
}
} catch (e) {
Get.snackbar('错误', '删除问题失败: $e');
rethrow;
}
}
Future<void> deleteSelectedProblems() async {
final problemsToDelete = selectedProblems;
if (problemsToDelete.isEmpty) {
Get.snackbar('提示', '请至少选择一个问题进行删除');
return;
}
try {
for (var problem in problemsToDelete) {
await deleteProblem(problem);
}
Get.snackbar('成功', '已删除${problemsToDelete.length}个问题');
} catch (e) {
Get.snackbar('错误', '删除问题失败: $e');
}
}
Future<void> _deleteProblemImages(Problem problem) async {
for (var imagePath in problem.imagePaths) {
try {
final file = File(imagePath);
if (await file.exists()) {
await file.delete();
}
} catch (e) {
print('删除图片失败: $imagePath, 错误: $e');
}
}
}
Future<bool> uploadProblem(Problem problem) async {
try {
final formData = FormData.fromMap({
'description': problem.description,
'location': problem.location,
'createdAt': problem.createdAt.toIso8601String(),
'boundInfo': problem.boundInfo ?? '',
});
for (var imagePath in problem.imagePaths) {
final file = File(imagePath);
if (await file.exists()) {
formData.files.add(
MapEntry(
'images',
await MultipartFile.fromFile(
imagePath,
filename: path.basename(imagePath),
),
),
);
}
}
final response = await _dio.post(
'https://your-server.com/api/problems',
data: formData,
options: Options(
sendTimeout: const Duration(seconds: 30),
receiveTimeout: const Duration(seconds: 30),
),
);
if (response.statusCode == 200) {
final updatedProblem = problem.copyWith(isUploaded: true);
await updateProblem(updatedProblem);
return true;
} else {
throw Exception('服务器返回错误状态码: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.type == DioExceptionType.connectionTimeout ||
e.type == DioExceptionType.receiveTimeout) {
Get.snackbar('网络超时', '请检查网络连接后重试');
} else {
Get.snackbar('网络错误', '上传问题失败: ${e.message}');
}
return false;
} catch (e) {
Get.snackbar('错误', '上传问题失败: $e');
return false;
}
}
Future<void> uploadAllUnuploaded() async {
if (!isOnline.value) {
Get.snackbar('提示', '当前无网络,无法上传');
return;
}
final unuploaded = unuploadedProblems;
if (unuploaded.isEmpty) {
Get.snackbar('提示', '没有需要上传的问题');
return;
}
isLoading.value = true;
int successCount = 0;
for (var problem in unuploaded) {
final success = await uploadProblem(problem);
if (success) {
successCount++;
}
await Future.delayed(const Duration(milliseconds: 500));
}
isLoading.value = false;
if (successCount > 0) {
Get.snackbar('成功', '已成功上传$successCount个问题');
}
if (successCount < unuploaded.length) {
Get.snackbar('部分成功', '${unuploaded.length - successCount}个问题上传失败');
}
}
Future<void> bindInfoToProblem(String id, String info) async {
try {
final problem = problems.firstWhere((p) => p.id == id);
final updatedProblem = problem.copyWith(boundInfo: info);
await updateProblem(updatedProblem);
Get.snackbar('成功', '信息已绑定');
} catch (e) {
Get.snackbar('错误', '未找到问题或绑定失败: $e');
}
}
void clearSelections() {
for (var problem in problems) {
problem.isChecked.value = false;
}
}
}