Browse Source

feat : 删除企业

dev
徐振升 2 months ago
parent
commit
3879d0f9f6
  1. 6
      lib/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart
  2. 2
      lib/app/features/enterprise/domain/repositories/enterprise_repository.dart
  3. 31
      lib/app/features/enterprise/domain/usecases/delete_enterprise_usecase.dart
  4. 8
      lib/app/features/enterprise/presentation/bindings/enterprise_list_binding.dart
  5. 50
      lib/app/features/enterprise/presentation/controllers/enterprise_list_controller.dart
  6. 167
      lib/app/features/enterprise/presentation/pages/enterprise_list_page.dart
  7. 44
      lib/app/features/enterprise/presentation/pages/widgets/unified_enterprise_card.dart

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

@ -213,4 +213,10 @@ class EnterpriseRepositoryImpl implements EnterpriseRepository {
// 3. DTO // 3. DTO
return EnterpriseModel.fromMap(problemMap).toEntity(); return EnterpriseModel.fromMap(problemMap).toEntity();
} }
@override
Future<void> deleteEnterprise(String id) async {
// ID
await localDataSource.deleteEnterprise(id);
}
} }

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

@ -36,4 +36,6 @@ abstract class EnterpriseRepository implements SyncableRepository<Enterprise> {
Future<List<Enterprise>> getAllEnterprises(); Future<List<Enterprise>> getAllEnterprises();
// ID获取企业信息 // ID获取企业信息
Future<Enterprise?> getEnterpriseById(String enterpriseId); Future<Enterprise?> getEnterpriseById(String enterpriseId);
//
Future<void> deleteEnterprise(String id);
} }

31
lib/app/features/enterprise/domain/usecases/delete_enterprise_usecase.dart

@ -0,0 +1,31 @@
import 'package:problem_check_system/app/core/domain/entities/sync_status.dart';
import 'package:problem_check_system/app/core/repositories/auth_repository.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart';
class DeleteEnterpriseUsecase {
final EnterpriseRepository repository;
final AuthRepository authRepository;
DeleteEnterpriseUsecase({
required this.repository,
required this.authRepository,
});
Future<void> call(Enterprise enterprise) async {
final nowUtc = DateTime.now().toUtc();
final userId = authRepository.getUserId();
//
if (enterprise.syncStatus == SyncStatus.pendingCreate) {
await repository.deleteEnterprise(enterprise.id);
} else {
//
final enterpriseToDelete = enterprise.copyWith(
lastModifiedTime: nowUtc,
lastModifierId: userId,
syncStatus: SyncStatus.pendingDelete,
);
await repository.updateEnterprise(enterpriseToDelete);
}
}
}

8
lib/app/features/enterprise/presentation/bindings/enterprise_list_binding.dart

@ -5,6 +5,7 @@ import 'package:problem_check_system/app/features/enterprise/data/datasources/en
import 'package:problem_check_system/app/features/enterprise/data/datasources/enterprise_remote_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/repositories_impl/enterprise_repository_impl.dart'; import 'package:problem_check_system/app/features/enterprise/data/repositories_impl/enterprise_repository_impl.dart';
import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart'; import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/delete_enterprise_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprise_list_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprise_list_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/resolve_conflict_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/resolve_conflict_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/sync_enterprises_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/sync_enterprises_usecase.dart';
@ -38,12 +39,19 @@ class EnterpriseListBinding extends Bindings {
Get.put<GetEnterpriseListUsecase>( Get.put<GetEnterpriseListUsecase>(
GetEnterpriseListUsecase(repository: Get.find<EnterpriseRepository>()), GetEnterpriseListUsecase(repository: Get.find<EnterpriseRepository>()),
); );
Get.put<DeleteEnterpriseUsecase>(
DeleteEnterpriseUsecase(
repository: Get.find<EnterpriseRepository>(),
authRepository: Get.find(),
),
);
Get.lazyPut<EnterpriseListController>( Get.lazyPut<EnterpriseListController>(
() => EnterpriseListController( () => EnterpriseListController(
getEnterpriseListUsecase: Get.find<GetEnterpriseListUsecase>(), getEnterpriseListUsecase: Get.find<GetEnterpriseListUsecase>(),
syncEnterprisesUsecase: Get.find<SyncEnterprisesUsecase>(), syncEnterprisesUsecase: Get.find<SyncEnterprisesUsecase>(),
resolveConflictUsecase: Get.find<ResolveConflictUsecase>(), resolveConflictUsecase: Get.find<ResolveConflictUsecase>(),
deleteEnterpriseUsecase: Get.find<DeleteEnterpriseUsecase>(),
), ),
); );
} }

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

@ -9,6 +9,7 @@ import 'package:problem_check_system/app/core/routes/app_routes.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart'; import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise_list_item.dart'; import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise_list_item.dart';
import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart'; import 'package:problem_check_system/app/features/enterprise/domain/repositories/enterprise_repository.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/delete_enterprise_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprise_list_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/get_enterprise_list_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/resolve_conflict_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/resolve_conflict_usecase.dart';
import 'package:problem_check_system/app/features/enterprise/domain/usecases/sync_enterprises_usecase.dart'; import 'package:problem_check_system/app/features/enterprise/domain/usecases/sync_enterprises_usecase.dart';
@ -29,11 +30,14 @@ class EnterpriseListController extends GetxController {
final GetEnterpriseListUsecase getEnterpriseListUsecase; final GetEnterpriseListUsecase getEnterpriseListUsecase;
final SyncEnterprisesUsecase syncEnterprisesUsecase; // final SyncEnterprisesUsecase syncEnterprisesUsecase; //
final ResolveConflictUsecase resolveConflictUsecase; // final ResolveConflictUsecase resolveConflictUsecase; //
final DeleteEnterpriseUsecase
deleteEnterpriseUsecase; // 1. UseCase
EnterpriseListController({ EnterpriseListController({
required this.getEnterpriseListUsecase, required this.getEnterpriseListUsecase,
required this.syncEnterprisesUsecase, required this.syncEnterprisesUsecase,
required this.resolveConflictUsecase, required this.resolveConflictUsecase,
required this.deleteEnterpriseUsecase, // 2. UseCase
}); });
// --- --- // --- ---
@ -215,6 +219,52 @@ class EnterpriseListController extends GetxController {
loadEnterprises(); loadEnterprises();
} }
// 3.
Future<bool?> confirmDeleteEnterprise(Enterprise enterprise) async {
return await Get.dialog<bool>(
AlertDialog(
title: const Text('确认删除'),
content: Text('您确定要删除企业 "${enterprise.name}" 吗?该企业下的所有问题也将无法查看。'),
actions: <Widget>[
TextButton(
child: const Text('取消'),
onPressed: () => Get.back(result: false),
),
TextButton(
style: TextButton.styleFrom(foregroundColor: Colors.red),
child: const Text('删除'),
onPressed: () => Get.back(result: true),
),
],
),
);
}
// 4.
void deleteEnterprise(Enterprise enterprise) async {
try {
// UseCase
await deleteEnterpriseUsecase(enterprise);
// UI列表中移除该项
enterpriseList.removeWhere((item) => item.enterprise.id == enterprise.id);
Get.snackbar(
'删除成功',
'"${enterprise.name}" 已被标记为删除。',
snackPosition: SnackPosition.BOTTOM,
);
} catch (e) {
Get.snackbar(
'删除失败',
'无法删除该企业: $e',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
}
}
Future<void> loadEnterprises() async { Future<void> loadEnterprises() async {
expansibleController.collapse(); expansibleController.collapse();
isLoading.value = true; isLoading.value = true;

167
lib/app/features/enterprise/presentation/pages/enterprise_list_page.dart

@ -2,6 +2,7 @@ import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:problem_check_system/app/core/domain/entities/sync_status.dart';
import 'package:problem_check_system/app/core/extensions/datetime_extension.dart'; import 'package:problem_check_system/app/core/extensions/datetime_extension.dart';
import 'package:problem_check_system/app/core/models/company_enum.dart'; import 'package:problem_check_system/app/core/models/company_enum.dart';
import 'package:problem_check_system/app/core/pages/widgets/custom_app_bar.dart'; import 'package:problem_check_system/app/core/pages/widgets/custom_app_bar.dart';
@ -251,77 +252,121 @@ class EnterpriseListPage extends GetView<EnterpriseListController> {
enterprise, enterprise,
); );
return Padding( // 1.
padding: EdgeInsets.only(bottom: 12.h), final bool isPendingDelete =
child: UnifiedEnterpriseCard( enterprise.syncStatus == SyncStatus.pendingDelete;
enterpriseListItem: item,
isSelected: isSelected, // 2. 使 Dismissible
// itemMode mode return Dismissible(
// --- [] controller --- key: Key(enterprise.id), // 使ID作为唯一Key
onTap: () => // 3.
controller.navigateToEnterpriseInfoPage(item.enterprise), direction: isPendingDelete
// [] actions ? DismissDirection.none
actions: Row( : DismissDirection.endToStart,
// 4.
background: Container(
color: Colors.red,
padding: EdgeInsets.symmetric(horizontal: 20.w),
alignment: Alignment.centerRight,
child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
//
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
// Text(
TextButton.icon( '删除',
onPressed: () => style: TextStyle(
controller.navigateToEditForm(item.enterprise), color: Colors.white,
icon: Icon( fontWeight: FontWeight.bold,
Icons.edit_outlined, fontSize: 16.sp,
size: 16.sp,
color: Colors.grey.shade700,
),
label: Text(
'修改信息',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey.shade700,
),
),
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(
horizontal: 12.w,
vertical: 12.h,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
), ),
), ),
SizedBox(width: 8.w),
const Icon(Icons.delete, color: Colors.white),
],
),
),
// () // 5.
ElevatedButton( confirmDismiss: (direction) async {
onPressed: () => controller.navigateToEnterpriseInfoPage( return await controller.confirmDeleteEnterprise(enterprise);
item.enterprise, },
),
style: ElevatedButton.styleFrom( // 6.
backgroundColor: const Color(0xFF42A5F5), onDismissed: (direction) {
foregroundColor: Colors.white, controller.deleteEnterprise(enterprise);
padding: EdgeInsets.symmetric( },
horizontal: 20.w, child: Padding(
vertical: 12.h, padding: EdgeInsets.only(bottom: 12.h),
child: UnifiedEnterpriseCard(
enterpriseListItem: item,
isSelected: isSelected,
// itemMode mode
// --- [] controller ---
onTap: () =>
controller.navigateToEnterpriseInfoPage(item.enterprise),
// [] actions
actions: Row(
mainAxisSize: MainAxisSize.min,
//
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//
if (!isPendingDelete)
TextButton.icon(
onPressed: () =>
controller.navigateToEditForm(item.enterprise),
icon: Icon(
Icons.edit_outlined,
size: 16.sp,
color: Colors.grey.shade700,
),
label: Text(
'修改信息',
style: TextStyle(
fontSize: 12.sp,
color: Colors.grey.shade700,
),
),
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(
horizontal: 12.w,
vertical: 12.h,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
), ),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
// [!!!] // ()
elevation: 0, ElevatedButton(
// [!!!] onPressed: () => controller
shape: RoundedRectangleBorder( .navigateToEnterpriseInfoPage(item.enterprise),
borderRadius: BorderRadius.only( style: ElevatedButton.styleFrom(
topLeft: Radius.circular(12.r), backgroundColor: const Color(0xFF42A5F5),
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(
horizontal: 20.w,
vertical: 12.h,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
// [!!!]
elevation: 0,
// [!!!]
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.r),
),
), ),
), ),
), child: Text(
child: Text( "查看问题",
"查看问题", style: TextStyle(
style: TextStyle( fontSize: 13.sp,
fontSize: 13.sp, fontWeight: FontWeight.bold,
fontWeight: FontWeight.bold, ),
), ),
), ),
), ],
], ),
), ),
), ),
); );

44
lib/app/features/enterprise/presentation/pages/widgets/unified_enterprise_card.dart

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:problem_check_system/app/core/domain/entities/sync_status.dart';
import 'package:problem_check_system/app/core/extensions/datetime_extension.dart'; import 'package:problem_check_system/app/core/extensions/datetime_extension.dart';
import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise_list_item.dart'; import 'package:problem_check_system/app/features/enterprise/domain/entities/enterprise_list_item.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart';
@ -22,6 +23,8 @@ class UnifiedEnterpriseCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bool isDeleted =
enterpriseListItem.enterprise.syncStatus == SyncStatus.pendingDelete;
return Card( return Card(
elevation: isSelected ? 4.0 : .2, elevation: isSelected ? 4.0 : .2,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
@ -33,6 +36,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
// [ 1] // [ 1]
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
color: isDeleted ? Colors.grey[200] : Theme.of(context).cardColor,
child: InkWell( child: InkWell(
onTap: onTap, onTap: onTap,
// [ 2] 使 Column // [ 2] 使 Column
@ -48,9 +52,9 @@ class UnifiedEnterpriseCard extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildTopSection(), _buildTopSection(isDeleted),
SizedBox(height: 12.h), SizedBox(height: 12.h),
_buildMiddleSection(), _buildMiddleSection(isDeleted),
], ],
), ),
), ),
@ -60,7 +64,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
// --- 2: --- // --- 2: ---
// [ 3] // [ 3]
if (actions != null) _buildBottomActionRow(), if (actions != null) _buildBottomActionRow(isDeleted),
], ],
), ),
), ),
@ -68,7 +72,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
} }
/// ///
Widget _buildTopSection() { Widget _buildTopSection(bool isDeleted) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -90,7 +94,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.5.sp, fontSize: 12.5.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.black87, color: isDeleted ? Colors.grey : Colors.black87,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -113,7 +117,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.5.sp, fontSize: 12.5.sp,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.black87, color: isDeleted ? Colors.grey : Colors.black87,
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -145,7 +149,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
} }
/// ///
Widget _buildMiddleSection() { Widget _buildMiddleSection(bool isDeleted) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -162,8 +166,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
enterpriseListItem.totalProblems.toString(), enterpriseListItem.totalProblems.toString(),
style: TextStyle( style: TextStyle(
fontSize: 12.5.sp, fontSize: 12.5.sp,
color: Colors.black87, color: isDeleted ? Colors.grey : Colors.black87,
fontWeight: FontWeight.w500,
), ),
), ),
], ],
@ -173,9 +176,16 @@ class UnifiedEnterpriseCard extends StatelessWidget {
children: [ children: [
Icon(Icons.access_time, color: Colors.grey, size: 16.sp), Icon(Icons.access_time, color: Colors.grey, size: 16.sp),
Text( Text(
'创建时间: ${enterpriseListItem.enterprise.creationTime.toDateTimeString()}', '创建时间:',
style: TextStyle(fontSize: 12.sp, color: Colors.grey), style: TextStyle(fontSize: 12.sp, color: Colors.grey),
), ),
Text(
enterpriseListItem.enterprise.creationTime.toDateTimeString(),
style: TextStyle(
fontSize: 12.sp,
color: isDeleted ? Colors.grey : Colors.black87,
),
),
], ],
), ),
], ],
@ -183,7 +193,7 @@ class UnifiedEnterpriseCard extends StatelessWidget {
} }
/// + /// +
Widget _buildBottomActionRow() { Widget _buildBottomActionRow(bool isDeleted) {
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
@ -194,14 +204,18 @@ class UnifiedEnterpriseCard extends StatelessWidget {
children: [ children: [
TDTag( TDTag(
'已上传 ${enterpriseListItem.uploadedProblems}', '已上传 ${enterpriseListItem.uploadedProblems}',
textColor: Colors.blue, textColor: isDeleted ? Colors.grey : Colors.blue,
backgroundColor: Colors.blue.withAlpha(20), backgroundColor: isDeleted
? Colors.grey.withAlpha(20)
: Colors.blue.withAlpha(20),
), ),
SizedBox(width: 8.w), SizedBox(width: 8.w),
TDTag( TDTag(
'未上传 ${enterpriseListItem.pendingProblems}', '未上传 ${enterpriseListItem.pendingProblems}',
textColor: Colors.red, textColor: isDeleted ? Colors.grey : Colors.red,
backgroundColor: Colors.red.withAlpha(20), backgroundColor: isDeleted
? Colors.grey.withAlpha(20)
: Colors.red.withAlpha(20),
), ),
], ],
), ),

Loading…
Cancel
Save