From e46c976c1f29bedc5aa97fcedcb664fed990f789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=8C=AF=E5=8D=87?= <359059686@qq.com> Date: Wed, 5 Nov 2025 17:13:44 +0800 Subject: [PATCH] =?UTF-8?q?fix=20:=20=E8=8E=B7=E5=8F=96=E8=BF=9C=E7=A8=8B?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../problem_remote_data_source.dart | 2 +- .../repositories/problem_repository_impl.dart | 7 + .../repositories/problem_repository.dart | 2 + .../usecases/resolve_conflict_usecase.dart | 12 ++ .../bindings/problem_list_binding.dart | 14 +- .../controllers/problem_list_controller.dart | 181 +++++++++--------- .../presentation/pages/problem_list_page.dart | 2 +- 7 files changed, 130 insertions(+), 90 deletions(-) create mode 100644 lib/app/features/problem/domain/usecases/resolve_conflict_usecase.dart diff --git a/lib/app/features/problem/data/datasources/problem_remote_data_source.dart b/lib/app/features/problem/data/datasources/problem_remote_data_source.dart index d369028..62f8e9d 100644 --- a/lib/app/features/problem/data/datasources/problem_remote_data_source.dart +++ b/lib/app/features/problem/data/datasources/problem_remote_data_source.dart @@ -61,7 +61,7 @@ class ProblemRemoteDataSourceImpl implements ProblemRemoteDataSource { queryParameters: filter.toJson(), ); // 假设服务器返回的数据在 'data' 字段中,且是一个列表 - final List problemListJson = response.data['data']; + final List problemListJson = response.data['items']; return problemListJson.map((json) => ProblemDto.fromJson(json)).toList(); } on DioException catch (e) { // 在这里处理网络错误,可以抛出一个自定义的异常 diff --git a/lib/app/features/problem/data/repositories/problem_repository_impl.dart b/lib/app/features/problem/data/repositories/problem_repository_impl.dart index 8923dbe..e939c7b 100644 --- a/lib/app/features/problem/data/repositories/problem_repository_impl.dart +++ b/lib/app/features/problem/data/repositories/problem_repository_impl.dart @@ -235,4 +235,11 @@ class ProblemRepositoryImpl implements ProblemRepository { conflicts: conflicts, ); } + + @override + Future resolveConflictAndUpdate(ProblemEntity chosenProblem) { + // 将实体转换为模型,然后更新到数据库 + final problemMap = ProblemModel.fromEntity(chosenProblem).toMap(); + return localDataSource.updateProblem(problemMap); + } } diff --git a/lib/app/features/problem/domain/repositories/problem_repository.dart b/lib/app/features/problem/domain/repositories/problem_repository.dart index 9932e50..a6838e4 100644 --- a/lib/app/features/problem/domain/repositories/problem_repository.dart +++ b/lib/app/features/problem/domain/repositories/problem_repository.dart @@ -21,4 +21,6 @@ abstract class ProblemRepository { Future syncProblemToServer(ProblemEntity problem); Future syncWithServer(); + // 解决冲突 + Future resolveConflictAndUpdate(ProblemEntity chosenProblem) async {} } diff --git a/lib/app/features/problem/domain/usecases/resolve_conflict_usecase.dart b/lib/app/features/problem/domain/usecases/resolve_conflict_usecase.dart new file mode 100644 index 0000000..077c5c4 --- /dev/null +++ b/lib/app/features/problem/domain/usecases/resolve_conflict_usecase.dart @@ -0,0 +1,12 @@ +import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart'; +import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart'; + +class ProblemResolveConflictUsecase { + final ProblemRepository repository; + + ProblemResolveConflictUsecase({required this.repository}); + + Future call(ProblemEntity chosenProblem) async { + return repository.resolveConflictAndUpdate(chosenProblem); + } +} diff --git a/lib/app/features/problem/presentation/bindings/problem_list_binding.dart b/lib/app/features/problem/presentation/bindings/problem_list_binding.dart index 6c26562..2c177ac 100644 --- a/lib/app/features/problem/presentation/bindings/problem_list_binding.dart +++ b/lib/app/features/problem/presentation/bindings/problem_list_binding.dart @@ -6,6 +6,8 @@ import 'package:problem_check_system/app/features/problem/data/datasources/probl import 'package:problem_check_system/app/features/problem/data/repositories/problem_repository_impl.dart'; import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart'; import 'package:problem_check_system/app/features/problem/domain/usecases/get_all_problems_usecase.dart'; +import 'package:problem_check_system/app/features/problem/domain/usecases/resolve_conflict_usecase.dart'; +import 'package:problem_check_system/app/features/problem/domain/usecases/sync_problems_usecase.dart'; import 'package:problem_check_system/app/features/problem/presentation/controllers/problem_list_controller.dart'; class ProblemListBinding extends BaseBindings { @@ -40,12 +42,22 @@ class ProblemListBinding extends BaseBindings { Get.lazyPut( () => GetAllProblemsUsecase(problemRepository: Get.find()), ); + Get.lazyPut( + () => SyncProblemsUsecase(repository: Get.find()), + ); + Get.lazyPut( + () => ProblemResolveConflictUsecase(repository: Get.find()), + ); } @override void register5Controllers() { Get.lazyPut( - () => ProblemListController(getAllProblemsUsecase: Get.find()), + () => ProblemListController( + getAllProblemsUsecase: Get.find(), + syncProblemsUsecase: Get.find(), + problemResolveConflictUsecase: Get.find(), + ), ); } } diff --git a/lib/app/features/problem/presentation/controllers/problem_list_controller.dart b/lib/app/features/problem/presentation/controllers/problem_list_controller.dart index cc6aace..592df08 100644 --- a/lib/app/features/problem/presentation/controllers/problem_list_controller.dart +++ b/lib/app/features/problem/presentation/controllers/problem_list_controller.dart @@ -1,20 +1,24 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:problem_check_system/app/core/extensions/datetime_extension.dart'; import 'package:problem_check_system/app/core/models/form_mode.dart'; import 'package:problem_check_system/app/core/routes/app_routes.dart'; import 'package:problem_check_system/app/features/problem/domain/entities/problem_entity.dart'; import 'package:problem_check_system/app/features/problem/domain/entities/problem_list_item_entity.dart'; +import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart'; import 'package:problem_check_system/app/features/problem/domain/usecases/get_all_problems_usecase.dart'; +import 'package:problem_check_system/app/features/problem/domain/usecases/resolve_conflict_usecase.dart'; +import 'package:problem_check_system/app/features/problem/domain/usecases/sync_problems_usecase.dart'; class ProblemListController extends GetxController { final GetAllProblemsUsecase getAllProblemsUsecase; - // final SyncEnterprisesUsecase syncEnterprisesUsecase; - // final ResolveConflictUsecase resolveConflictUsecase; + final SyncProblemsUsecase syncProblemsUsecase; + final ProblemResolveConflictUsecase problemResolveConflictUsecase; ProblemListController({ required this.getAllProblemsUsecase, - // required this.syncEnterprisesUsecase, - // required this.resolveConflictUsecase, + required this.syncProblemsUsecase, + required this.problemResolveConflictUsecase, }); final problemList = [].obs; @@ -45,31 +49,32 @@ class ProblemListController extends GetxController { // --- 实现基类中定义的方法 --- // 核心流程方法 - Future loadAndSyncEnterprises() async { + Future loadAndSyncProblems() async { try { isLoading(true); isSyncing(true); - // // 步骤 1: 执行同步 - // final syncResult = await syncEnterprisesUsecase(); - - // // 步骤 2: 处理冲突 - // if (syncResult.hasConflicts) { - // // 如果有冲突,则逐个弹窗让用户选择 - // for (final conflict in syncResult.conflicts) { - // final chosenVersion = await _showConflictDialog(conflict); - // if (chosenVersion != null) { - // // 用户做出了选择,更新本地数据 - // await resolveConflictUsecase(chosenVersion); - // } - // } - // } + // 步骤 1: 执行同步 + final syncResult = await syncProblemsUsecase(); + + // 步骤 2: 处理冲突 + if (syncResult.hasConflicts) { + // 如果有冲突,则逐个弹窗让用户选择 + for (final conflict in syncResult.conflicts) { + final chosenVersion = await _showConflictDialog(conflict); + if (chosenVersion != null) { + // 用户做出了选择,更新本地数据 + await problemResolveConflictUsecase(chosenVersion); + } + } + } isSyncing(false); // 步骤 3: 所有同步和冲突解决完毕后,从本地加载最终数据 await loadProblemItems(); } catch (e) { + Get.log('操作失败: $e'); Get.snackbar('错误', '操作失败: $e'); } finally { isLoading(false); @@ -77,74 +82,76 @@ class ProblemListController extends GetxController { } } - // // [修改后] 弹出冲突选择对话框的辅助方法 - // Future _showConflictDialog(EnterpriseConflict conflict) { - // return Get.dialog( - // AlertDialog( - // title: Text('数据冲突'), - // content: Column( - // mainAxisSize: MainAxisSize.min, - // crossAxisAlignment: CrossAxisAlignment.stretch, - // children: [ - // Text('${conflict.localVersion.name} 服务器上的数据与本地数据不一致,请选择要保留的版本。'), - // const SizedBox(height: 24), - - // // --- 本地版本选择区 --- - // Row( - // children: [ - // // 使用 Expanded 让主按钮填充可用空间 - // Expanded( - // child: ElevatedButton( - // child: Text( - // '使用客户端版本\n(修改于: ${conflict.localVersion.lastModifiedTime.toLocal().toDateTimeString2()})', - // textAlign: TextAlign.center, - // ), - // onPressed: () => Get.back(result: conflict.localVersion), - // ), - // ), - // const SizedBox(width: 8), // 按钮间的间距 - // // 查看详情按钮 - // IconButton( - // icon: const Icon(Icons.info_outline), - // tooltip: '查看客户端版本详情', - // onPressed: () => navigateToDetailsView(conflict.localVersion), - // ), - // ], - // ), - // const SizedBox(height: 8), - - // // --- 服务器版本选择区 --- - // Row( - // children: [ - // Expanded( - // child: ElevatedButton( - // style: ElevatedButton.styleFrom( - // backgroundColor: Get.theme.colorScheme.primary, - // foregroundColor: Get.theme.colorScheme.onPrimary, - // ), - // child: Text( - // '使用服务器版本\n(修改于: ${conflict.serverVersion.lastModifiedTime.toLocal().toDateTimeString2()})', - // textAlign: TextAlign.center, - // ), - // onPressed: () => Get.back(result: conflict.serverVersion), - // ), - // ), - // const SizedBox(width: 8), - // IconButton( - // icon: const Icon(Icons.info_outline), - // tooltip: '查看服务器版本详情', - // onPressed: () => - // navigateToDetailsView(conflict.serverVersion), - // ), - // ], - // ), - // ], - // ), - // ), - // // 设置为 false,防止用户点击对话框外部意外关闭它 - // barrierDismissible: false, - // ); - // } + // [修改后] 弹出冲突选择对话框的辅助方法 + Future _showConflictDialog(ProblemConflict conflict) { + return Get.dialog( + AlertDialog( + title: Text('数据冲突'), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + '${conflict.localVersion.description} 服务器上的数据与本地数据不一致,请选择要保留的版本。', + ), + const SizedBox(height: 24), + + // --- 本地版本选择区 --- + Row( + children: [ + // 使用 Expanded 让主按钮填充可用空间 + Expanded( + child: ElevatedButton( + child: Text( + '使用客户端版本\n(修改于: ${conflict.localVersion.lastModifiedTime.toLocal().toDateTimeString2()})', + textAlign: TextAlign.center, + ), + onPressed: () => Get.back(result: conflict.localVersion), + ), + ), + const SizedBox(width: 8), // 按钮间的间距 + // 查看详情按钮 + IconButton( + icon: const Icon(Icons.info_outline), + tooltip: '查看客户端版本详情', + onPressed: () => navigateToDetailsView(conflict.localVersion), + ), + ], + ), + const SizedBox(height: 8), + + // --- 服务器版本选择区 --- + Row( + children: [ + Expanded( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Get.theme.colorScheme.primary, + foregroundColor: Get.theme.colorScheme.onPrimary, + ), + child: Text( + '使用服务器版本\n(修改于: ${conflict.serverVersion.lastModifiedTime.toLocal().toDateTimeString2()})', + textAlign: TextAlign.center, + ), + onPressed: () => Get.back(result: conflict.serverVersion), + ), + ), + const SizedBox(width: 8), + IconButton( + icon: const Icon(Icons.info_outline), + tooltip: '查看服务器版本详情', + onPressed: () => + navigateToDetailsView(conflict.serverVersion), + ), + ], + ), + ], + ), + ), + // 设置为 false,防止用户点击对话框外部意外关闭它 + barrierDismissible: false, + ); + } void search() { loadProblemItems(); diff --git a/lib/app/features/problem/presentation/pages/problem_list_page.dart b/lib/app/features/problem/presentation/pages/problem_list_page.dart index ee664e0..43595a3 100644 --- a/lib/app/features/problem/presentation/pages/problem_list_page.dart +++ b/lib/app/features/problem/presentation/pages/problem_list_page.dart @@ -208,7 +208,7 @@ class ProblemListPage extends GetView { // 使用下拉刷新包裹列表 return RefreshIndicator( - onRefresh: () async => controller.loadAndSyncEnterprises(), + onRefresh: () async => controller.loadAndSyncProblems(), child: ListView.builder( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), itemCount: controller.problemList.length,