|
|
@ -1,27 +1,34 @@ |
|
|
|
|
|
|
|
// modules/problem/controllers/problem_controller.dart |
|
|
|
import 'package:dio/dio.dart'; |
|
|
|
import 'package:dio/dio.dart'; |
|
|
|
import 'package:get/get.dart' hide MultipartFile, FormData; |
|
|
|
import 'package:get/get.dart' hide MultipartFile, FormData; |
|
|
|
import 'dart:io'; |
|
|
|
import 'dart:io'; |
|
|
|
import 'package:path/path.dart' as path; |
|
|
|
import 'package:path/path.dart' as path; |
|
|
|
import '../../../data/models/problem_model.dart'; |
|
|
|
import '../../../data/models/problem_model.dart'; |
|
|
|
import '../../../data/providers/local_database.dart'; |
|
|
|
import '../../../data/providers/local_database.dart'; |
|
|
|
|
|
|
|
import '../../../data/providers/connectivity_provider.dart'; // 更新路径 |
|
|
|
|
|
|
|
|
|
|
|
class ProblemController extends GetxController { |
|
|
|
class ProblemController extends GetxController { |
|
|
|
final LocalDatabase _localDatabase; |
|
|
|
final LocalDatabase _localDatabase; |
|
|
|
final RxList<Problem> problems = <Problem>[].obs; |
|
|
|
final RxList<Problem> problems = <Problem>[].obs; |
|
|
|
final RxBool isLoading = false.obs; |
|
|
|
final RxBool isLoading = false.obs; |
|
|
|
final Dio _dio; |
|
|
|
final Dio _dio; |
|
|
|
|
|
|
|
final ConnectivityProvider _connectivityProvider; |
|
|
|
|
|
|
|
|
|
|
|
// 依赖注入,由 bindings 传入所有依赖 |
|
|
|
ProblemController({ |
|
|
|
ProblemController({required LocalDatabase localDatabase, required Dio dio}) |
|
|
|
required LocalDatabase localDatabase, |
|
|
|
: _localDatabase = localDatabase, |
|
|
|
required Dio dio, |
|
|
|
_dio = dio; |
|
|
|
required ConnectivityProvider connectivityProvider, |
|
|
|
|
|
|
|
}) : _localDatabase = localDatabase, |
|
|
|
|
|
|
|
_dio = dio, |
|
|
|
|
|
|
|
_connectivityProvider = connectivityProvider; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 provider 中的 isOnline |
|
|
|
|
|
|
|
RxBool get isOnline => _connectivityProvider.isOnline; |
|
|
|
|
|
|
|
|
|
|
|
// 获取所有已选中的问题对象 |
|
|
|
|
|
|
|
List<Problem> get selectedProblems { |
|
|
|
List<Problem> get selectedProblems { |
|
|
|
return problems.where((p) => p.isChecked.value).toList(); |
|
|
|
return problems.where((p) => p.isChecked.value).toList(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 获取未上传的问题 |
|
|
|
|
|
|
|
List<Problem> get unuploadedProblems { |
|
|
|
List<Problem> get unuploadedProblems { |
|
|
|
return problems.where((p) => !p.isUploaded).toList(); |
|
|
|
return problems.where((p) => !p.isUploaded).toList(); |
|
|
|
} |
|
|
|
} |
|
|
@ -44,16 +51,13 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 在本地数据库和GetX列表中添加一个新问题 |
|
|
|
|
|
|
|
Future<void> addProblem(Problem problem) async { |
|
|
|
Future<void> addProblem(Problem problem) async { |
|
|
|
try { |
|
|
|
try { |
|
|
|
// 确保问题有ID |
|
|
|
|
|
|
|
if (problem.id == null) { |
|
|
|
if (problem.id == null) { |
|
|
|
problem = problem.copyWith( |
|
|
|
problem = problem.copyWith( |
|
|
|
id: DateTime.now().millisecondsSinceEpoch.toString(), |
|
|
|
id: DateTime.now().millisecondsSinceEpoch.toString(), |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
await _localDatabase.insertProblem(problem); |
|
|
|
await _localDatabase.insertProblem(problem); |
|
|
|
problems.add(problem); |
|
|
|
problems.add(problem); |
|
|
|
} catch (e) { |
|
|
|
} catch (e) { |
|
|
@ -62,7 +66,6 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 在本地数据库和GetX列表中更新一个现有问题 |
|
|
|
|
|
|
|
Future<void> updateProblem(Problem problem) async { |
|
|
|
Future<void> updateProblem(Problem problem) async { |
|
|
|
try { |
|
|
|
try { |
|
|
|
await _localDatabase.updateProblem(problem); |
|
|
|
await _localDatabase.updateProblem(problem); |
|
|
@ -76,16 +79,11 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 删除单个问题 |
|
|
|
|
|
|
|
Future<void> deleteProblem(Problem problem) async { |
|
|
|
Future<void> deleteProblem(Problem problem) async { |
|
|
|
try { |
|
|
|
try { |
|
|
|
if (problem.id != null) { |
|
|
|
if (problem.id != null) { |
|
|
|
await _localDatabase.deleteProblem(problem.id!); |
|
|
|
await _localDatabase.deleteProblem(problem.id!); |
|
|
|
|
|
|
|
|
|
|
|
// 从本地列表中移除 |
|
|
|
|
|
|
|
problems.remove(problem); |
|
|
|
problems.remove(problem); |
|
|
|
|
|
|
|
|
|
|
|
// 删除关联的图片文件 |
|
|
|
|
|
|
|
await _deleteProblemImages(problem); |
|
|
|
await _deleteProblemImages(problem); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
} catch (e) { |
|
|
@ -94,14 +92,12 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 批量删除选中的问题 |
|
|
|
|
|
|
|
Future<void> deleteSelectedProblems() async { |
|
|
|
Future<void> deleteSelectedProblems() async { |
|
|
|
final problemsToDelete = selectedProblems; |
|
|
|
final problemsToDelete = selectedProblems; |
|
|
|
if (problemsToDelete.isEmpty) { |
|
|
|
if (problemsToDelete.isEmpty) { |
|
|
|
Get.snackbar('提示', '请至少选择一个问题进行删除'); |
|
|
|
Get.snackbar('提示', '请至少选择一个问题进行删除'); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
for (var problem in problemsToDelete) { |
|
|
|
for (var problem in problemsToDelete) { |
|
|
|
await deleteProblem(problem); |
|
|
|
await deleteProblem(problem); |
|
|
@ -112,7 +108,6 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 删除问题关联的图片文件 |
|
|
|
|
|
|
|
Future<void> _deleteProblemImages(Problem problem) async { |
|
|
|
Future<void> _deleteProblemImages(Problem problem) async { |
|
|
|
for (var imagePath in problem.imagePaths) { |
|
|
|
for (var imagePath in problem.imagePaths) { |
|
|
|
try { |
|
|
|
try { |
|
|
@ -126,7 +121,6 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 上传单个问题到服务器 |
|
|
|
|
|
|
|
Future<bool> uploadProblem(Problem problem) async { |
|
|
|
Future<bool> uploadProblem(Problem problem) async { |
|
|
|
try { |
|
|
|
try { |
|
|
|
final formData = FormData.fromMap({ |
|
|
|
final formData = FormData.fromMap({ |
|
|
@ -136,7 +130,6 @@ class ProblemController extends GetxController { |
|
|
|
'boundInfo': problem.boundInfo ?? '', |
|
|
|
'boundInfo': problem.boundInfo ?? '', |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 添加图片文件 |
|
|
|
|
|
|
|
for (var imagePath in problem.imagePaths) { |
|
|
|
for (var imagePath in problem.imagePaths) { |
|
|
|
final file = File(imagePath); |
|
|
|
final file = File(imagePath); |
|
|
|
if (await file.exists()) { |
|
|
|
if (await file.exists()) { |
|
|
@ -162,7 +155,6 @@ class ProblemController extends GetxController { |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (response.statusCode == 200) { |
|
|
|
if (response.statusCode == 200) { |
|
|
|
// 标记为已上传 |
|
|
|
|
|
|
|
final updatedProblem = problem.copyWith(isUploaded: true); |
|
|
|
final updatedProblem = problem.copyWith(isUploaded: true); |
|
|
|
await updateProblem(updatedProblem); |
|
|
|
await updateProblem(updatedProblem); |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -183,8 +175,12 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 批量上传所有未上传的问题 |
|
|
|
|
|
|
|
Future<void> uploadAllUnuploaded() async { |
|
|
|
Future<void> uploadAllUnuploaded() async { |
|
|
|
|
|
|
|
if (!isOnline.value) { |
|
|
|
|
|
|
|
Get.snackbar('提示', '当前无网络,无法上传'); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final unuploaded = unuploadedProblems; |
|
|
|
final unuploaded = unuploadedProblems; |
|
|
|
if (unuploaded.isEmpty) { |
|
|
|
if (unuploaded.isEmpty) { |
|
|
|
Get.snackbar('提示', '没有需要上传的问题'); |
|
|
|
Get.snackbar('提示', '没有需要上传的问题'); |
|
|
@ -199,7 +195,6 @@ class ProblemController extends GetxController { |
|
|
|
if (success) { |
|
|
|
if (success) { |
|
|
|
successCount++; |
|
|
|
successCount++; |
|
|
|
} |
|
|
|
} |
|
|
|
// 添加短暂延迟,避免服务器压力过大 |
|
|
|
|
|
|
|
await Future.delayed(const Duration(milliseconds: 500)); |
|
|
|
await Future.delayed(const Duration(milliseconds: 500)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -214,7 +209,6 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 绑定信息到问题 |
|
|
|
|
|
|
|
Future<void> bindInfoToProblem(String id, String info) async { |
|
|
|
Future<void> bindInfoToProblem(String id, String info) async { |
|
|
|
try { |
|
|
|
try { |
|
|
|
final problem = problems.firstWhere((p) => p.id == id); |
|
|
|
final problem = problems.firstWhere((p) => p.id == id); |
|
|
@ -226,7 +220,6 @@ class ProblemController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 清除所有选中的状态 |
|
|
|
|
|
|
|
void clearSelections() { |
|
|
|
void clearSelections() { |
|
|
|
for (var problem in problems) { |
|
|
|
for (var problem in problems) { |
|
|
|
problem.isChecked.value = false; |
|
|
|
problem.isChecked.value = false; |
|
|
|