|
|
|
|
@ -1,8 +1,10 @@
|
|
|
|
|
import 'dart:convert'; |
|
|
|
|
import 'package:problem_check_system/app/core/domain/entities/sync_status.dart'; |
|
|
|
|
import 'package:problem_check_system/app/core/services/network_status_service.dart'; |
|
|
|
|
import 'package:problem_check_system/app/features/problem/data/datasources/problem_local_data_source.dart'; |
|
|
|
|
import 'package:problem_check_system/app/features/problem/data/datasources/problem_remote_data_source.dart'; |
|
|
|
|
import 'package:problem_check_system/app/features/problem/data/model/problem_dto.dart'; |
|
|
|
|
import 'package:problem_check_system/app/features/problem/data/model/problem_filter_dto.dart'; |
|
|
|
|
import 'package:problem_check_system/app/features/problem/data/model/problem_model.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_filter_params.dart'; |
|
|
|
|
@ -15,10 +17,12 @@ import 'package:problem_check_system/app/features/problem/domain/repositories/pr
|
|
|
|
|
class ProblemRepositoryImpl implements ProblemRepository { |
|
|
|
|
final ProblemLocalDataSource localDataSource; |
|
|
|
|
final ProblemRemoteDataSource remoteDataSource; |
|
|
|
|
final NetworkStatusService networkStatusService; |
|
|
|
|
|
|
|
|
|
ProblemRepositoryImpl({ |
|
|
|
|
required this.localDataSource, |
|
|
|
|
required this.remoteDataSource, |
|
|
|
|
required this.networkStatusService, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
@ -161,4 +165,74 @@ class ProblemRepositoryImpl implements ProblemRepository {
|
|
|
|
|
// 返回最终从服务器同步回来的、纯净的 Entity |
|
|
|
|
return syncedEntity; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// 同步服务器数据 |
|
|
|
|
@override |
|
|
|
|
Future<ProblemSyncResult> syncWithServer() async { |
|
|
|
|
if (!networkStatusService.isOnline.value) { |
|
|
|
|
// 如果离线,直接返回一个空的同步结果 |
|
|
|
|
return const ProblemSyncResult(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 从远程和本地获取所有数据 |
|
|
|
|
final remoteProblemsDto = await remoteDataSource.getProblems( |
|
|
|
|
ProblemFilterDto(), |
|
|
|
|
); |
|
|
|
|
final localProblemsModel = await localDataSource.getAllProblems( |
|
|
|
|
ProblemFilterParams(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
final remoteProblems = remoteProblemsDto |
|
|
|
|
.map((dto) => dto.toEntity()) |
|
|
|
|
.toList(); |
|
|
|
|
final localProblems = localProblemsModel.map( |
|
|
|
|
(map) => ProblemModel.fromMap(map), |
|
|
|
|
); |
|
|
|
|
// 2. 使用 Map 进行高效查找 |
|
|
|
|
final localProblemMap = {for (var e in localProblems) e.id: e.toEntity()}; |
|
|
|
|
|
|
|
|
|
final List<ProblemEntity> newProblems = []; |
|
|
|
|
final List<ProblemConflict> conflicts = []; |
|
|
|
|
|
|
|
|
|
// 3. 遍历远程数据,进行比较 |
|
|
|
|
for (final remoteProblem in remoteProblems) { |
|
|
|
|
final localProblem = localProblemMap[remoteProblem.id]; |
|
|
|
|
|
|
|
|
|
if (localProblem == null) { |
|
|
|
|
// 本地没有,是新数据 |
|
|
|
|
|
|
|
|
|
newProblems.add(remoteProblem); |
|
|
|
|
} else { |
|
|
|
|
// 将两个时间都转换为毫秒时间戳进行比较,以忽略微秒级别的精度差异。 |
|
|
|
|
final remoteMillis = |
|
|
|
|
remoteProblem.lastModifiedTime.millisecondsSinceEpoch; |
|
|
|
|
final localMillis = |
|
|
|
|
localProblem.lastModifiedTime.millisecondsSinceEpoch; |
|
|
|
|
if (remoteMillis != localMillis) { |
|
|
|
|
//产生冲突 |
|
|
|
|
conflicts.add( |
|
|
|
|
ProblemConflict( |
|
|
|
|
localVersion: localProblem, |
|
|
|
|
serverVersion: remoteProblem, |
|
|
|
|
), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
// 如果时间一致或本地更新(我们以服务器为准),则跳过 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4. 将无冲突的新数据直接写入本地数据库 |
|
|
|
|
if (newProblems.isNotEmpty) { |
|
|
|
|
List<Map<String, dynamic>> problemMaps = newProblems |
|
|
|
|
.map((entity) => ProblemModel.fromEntity(entity).toMap()) |
|
|
|
|
.toList(); |
|
|
|
|
await localDataSource.cacheProblems(problemMaps); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 5. 返回同步结果,让上层处理冲突 |
|
|
|
|
return ProblemSyncResult( |
|
|
|
|
newItemsFromServer: newProblems.length, |
|
|
|
|
conflicts: conflicts, |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|