Browse Source

fix : 同步企业上传修改时间到本地数据库

dev
徐振升 1 week ago
parent
commit
d459d905ff
  1. 19
      lib/app/features/enterprise/data/datasources/enterprise_remote_data_source.dart
  2. 15
      lib/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart
  3. 2
      lib/app/features/enterprise/domain/repositories/enterprise_repository.dart
  4. 11
      lib/app/features/enterprise/domain/usecases/upload_enterprises_usecase.dart
  5. 116
      lib/app/features/enterprise/presentation/controllers/enterprise_list_controller.dart
  6. 2
      lib/app/features/enterprise/presentation/pages/enterprise_form_page.dart

19
lib/app/features/enterprise/data/datasources/enterprise_remote_data_source.dart

@ -7,10 +7,10 @@ import 'package:problem_check_system/app/features/enterprise/data/model/enterpri
/// API
abstract class EnterpriseRemoteDataSource {
///
Future<void> createEnterprise(EnterpriseModel enterprise);
Future<EnterpriseDto> createEnterprise(EnterpriseModel enterprise);
///
Future<void> updateEnterprise(EnterpriseModel enterprise);
Future<EnterpriseDto> updateEnterprise(EnterpriseModel enterprise);
///
Future<void> deleteEnterprise(String enterpriseId);
@ -25,14 +25,15 @@ class EnterpriseRemoteDataSourceImpl implements EnterpriseRemoteDataSource {
static const String enterprisesEndpoint = '/api/Companies';
@override
Future<void> createEnterprise(EnterpriseModel enterprise) async {
Future<EnterpriseDto> createEnterprise(EnterpriseModel enterprise) async {
try {
final enterpriseDto = EnterpriseDto.fromModel(enterprise);
final data = enterpriseDto.toJson();
await http.post(
final response = await http.post(
'$enterprisesEndpoint/CreateWithId?Id=${enterprise.id}',
data: data,
);
return EnterpriseDto.fromJson(response.data);
} catch (e) {
rethrow;
}
@ -48,12 +49,16 @@ class EnterpriseRemoteDataSourceImpl implements EnterpriseRemoteDataSource {
}
@override
Future<void> updateEnterprise(EnterpriseModel enterprise) async {
Future<EnterpriseDto> updateEnterprise(EnterpriseModel enterprise) async {
try {
final enterpriseDto = EnterpriseDto.fromModel(enterprise);
final data = enterpriseDto.toJson();
// ID
await http.patch('$enterprisesEndpoint/${enterprise.id}', data: data);
final response = await http.patch(
'$enterprisesEndpoint/${enterprise.id}',
data: data,
);
return EnterpriseDto.fromJson(response.data);
} catch (e) {
rethrow;
}
@ -62,7 +67,7 @@ class EnterpriseRemoteDataSourceImpl implements EnterpriseRemoteDataSource {
@override
Future<List<EnterpriseDto>> getEnterprises() async {
try {
final response = await http.get(enterprisesEndpoint);
final response = await http.get("$enterprisesEndpoint?PageSize=999");
final Map<String, dynamic> data = response.data;
final List<dynamic> enterprises = data['items'];
return enterprises.map((json) => EnterpriseDto.fromJson(json)).toList();

15
lib/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart

@ -2,6 +2,7 @@ import 'package:problem_check_system/app/core/models/sync_status.dart';
import 'package:problem_check_system/app/core/services/network_status_service.dart';
import 'package:problem_check_system/app/features/enterprise/data/datasources/enterprise_local_data_source.dart';
import 'package:problem_check_system/app/features/enterprise/data/datasources/enterprise_remote_data_source.dart';
import 'package:problem_check_system/app/features/enterprise/data/model/enterprise_dto.dart';
import 'package:problem_check_system/app/features/enterprise/data/model/enterprise_model.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise_conflict.dart';
@ -83,29 +84,31 @@ class EnterpriseRepositoryImpl implements EnterpriseRepository {
}
@override
Future<void> syncEnterpriseToServer(Enterprise enterprise) async {
Future<Enterprise> syncEnterpriseToServer(Enterprise enterprise) async {
// Domain Data Model
final enterpriseModel = EnterpriseModel.fromEntity(enterprise);
EnterpriseDto syncedDto;
// ****
// Repository DataSource
switch (enterprise.syncStatus) {
case SyncStatus.pendingCreate:
await remoteDataSource.createEnterprise(enterpriseModel);
syncedDto = await remoteDataSource.createEnterprise(enterpriseModel);
break;
case SyncStatus.pendingUpdate:
await remoteDataSource.updateEnterprise(enterpriseModel);
syncedDto = await remoteDataSource.updateEnterprise(enterpriseModel);
break;
case SyncStatus.pendingDelete:
await remoteDataSource.deleteEnterprise(enterprise.id);
break;
return enterprise;
//
case SyncStatus.synced:
case SyncStatus.untracked:
break;
return enterprise;
}
return syncedDto.toModel().toEntity();
}
// todo **************************************************************************
@override
Future<void> updateEnterpriseSyncStatus(
String enterpriseId,

2
lib/app/features/enterprise/domain/repositories/enterprise_repository.dart

@ -21,7 +21,7 @@ abstract class EnterpriseRepository implements SyncableRepository<Enterprise> {
bool? isUploaded,
});
Future<void> syncEnterpriseToServer(Enterprise enterprise) async {}
Future<Enterprise> syncEnterpriseToServer(Enterprise enterprise);
Future<void> updateEnterpriseSyncStatus(String id, SyncStatus synced) async {}

11
lib/app/features/enterprise/domain/usecases/upload_enterprises_usecase.dart

@ -58,15 +58,14 @@ class UploadEnterprisesUseCase {
final enterprise = enterprisesToUpload[i].enterprise;
try {
// 1.
await repository.syncEnterpriseToServer(enterprise);
final syncedEnterprise = await repository.syncEnterpriseToServer(
enterprise,
);
// 2.
if (enterprise.syncStatus == SyncStatus.pendingDelete) {
// repository.deleteLocalEnterprise(enterprise.id); //
// repository.deleteLocalEnterprise(enterprise.id);
} else {
await repository.updateEnterpriseSyncStatus(
enterprise.id,
SyncStatus.synced,
);
await repository.updateEnterprise(syncedEnterprise);
}
successCount++;
} catch (e) {

116
lib/app/features/enterprise/presentation/controllers/enterprise_list_controller.dart

@ -51,7 +51,8 @@ class EnterpriseListController extends GetxController {
@override
void onInit() {
// -
loadAndSyncEnterprises();
// loadAndSyncEnterprises();
search();
super.onInit();
}
@ -96,51 +97,119 @@ class EnterpriseListController extends GetxController {
}
}
//
// []
Future<Enterprise?> _showConflictDialog(EnterpriseConflict conflict) {
return Get.dialog<Enterprise>(
AlertDialog(
title: Text('数据冲突: ${conflict.localVersion.name}'),
// [ 1] content
title: Text('数据冲突'),
content: Column(
// mainAxisSize.min Column
mainAxisSize: MainAxisSize.min,
// crossAxisAlignment.stretch
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text('服务器上的数据与本地数据不一致,请选择要保留的版本。'),
const SizedBox(height: 24), //
//
ElevatedButton(
Text('${conflict.localVersion.name} 服务器上的数据与本地数据不一致,请选择要保留的版本。'),
const SizedBox(height: 24),
// --- ---
Row(
children: [
// 使 Expanded
Expanded(
child: ElevatedButton(
child: Text(
'使用客户端版本\n(修改于: ${conflict.localVersion.lastModifiedTime.toUtc().toDateTimeString2()})',
'使用客户端版本\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),
//
ElevatedButton(
// --- ---
Row(
children: [
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Get.theme.colorScheme.primary,
foregroundColor: Get.theme.colorScheme.onPrimary,
),
child: Text(
'使用服务器版本\n(修改于: ${conflict.serverVersion.lastModifiedTime.toUtc().toDateTimeString2()})',
'使用服务器版本\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),
),
],
),
],
),
// [ 2] actions
// actions: [ ... ],
),
// false
barrierDismissible: false,
);
}
// //
// Future<Enterprise?> _showConflictDialog(EnterpriseConflict conflict) {
// return Get.dialog<Enterprise>(
// AlertDialog(
// title: Text('数据冲突: ${conflict.localVersion.name}'),
// // [ 1] content
// content: Column(
// // mainAxisSize.min Column
// mainAxisSize: MainAxisSize.min,
// // crossAxisAlignment.stretch
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: [
// const Text('服务器上的数据与本地数据不一致,请选择要保留的版本。'),
// const SizedBox(height: 24), //
// //
// ElevatedButton(
// child: Text(
// '使用客户端版本\n(修改于: ${conflict.localVersion.lastModifiedTime.toUtc().toDateTimeString2()})',
// textAlign: TextAlign.center,
// ),
// onPressed: () => Get.back(result: conflict.localVersion),
// ),
// const SizedBox(height: 8),
// //
// ElevatedButton(
// style: ElevatedButton.styleFrom(
// backgroundColor: Get.theme.colorScheme.primary,
// foregroundColor: Get.theme.colorScheme.onPrimary,
// ),
// child: Text(
// '使用服务器版本\n(修改于: ${conflict.serverVersion.lastModifiedTime.toUtc().toDateTimeString2()})',
// textAlign: TextAlign.center,
// ),
// onPressed: () => Get.back(result: conflict.serverVersion),
// ),
// ],
// ),
// // [ 2] actions
// // actions: [ ... ],
// ),
// );
// }
void search() {
loadEnterprises();
@ -191,6 +260,17 @@ class EnterpriseListController extends GetxController {
}
}
// []
void navigateToDetailsView(Enterprise enterprise) {
Get.toNamed(
AppRoutes.enterpriseForm,
arguments: {
'data': enterprise,
'mode': FormMode.view, //
},
);
}
///
Future<void> navigateToAddForm() async {
final result = await Get.toNamed(

2
lib/app/features/enterprise/presentation/pages/enterprise_form_page.dart

@ -22,7 +22,7 @@ class EnterpriseFormPage extends GetView<EnterpriseFormController> {
child: Column(
children: [
Expanded(child: EnterpriseFormView()),
_buildBottomButtons(),
if (!controller.isReadOnly) _buildBottomButtons(),
],
),
),

Loading…
Cancel
Save