Browse Source

feat : 删除问题

dev
徐振升 2 months ago
parent
commit
da29a0d2c0
  1. 10
      lib/app/features/problem/domain/usecases/delete_problem.dart
  2. 29
      lib/app/features/problem/domain/usecases/delete_problem_usecase.dart
  3. 8
      lib/app/features/problem/presentation/bindings/problem_list_binding.dart
  4. 66
      lib/app/features/problem/presentation/controllers/problem_list_controller.dart
  5. 191
      lib/app/features/problem/presentation/pages/problem_list_page.dart

10
lib/app/features/problem/domain/usecases/delete_problem.dart

@ -1,10 +0,0 @@
import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart';
class DeleteProblem {
final ProblemRepository problemRepository;
DeleteProblem({required this.problemRepository});
Future<void> call(String id) async {
await problemRepository.deleteProblem(id);
}
}

29
lib/app/features/problem/domain/usecases/delete_problem_usecase.dart

@ -0,0 +1,29 @@
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/problem/domain/entities/problem_entity.dart';
import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart';
class DeleteProblemUsecase {
final ProblemRepository problemRepository;
final AuthRepository authRepository;
DeleteProblemUsecase({
required this.problemRepository,
required this.authRepository,
});
Future<void> call(ProblemEntity problemEntity) async {
final nowUtc = DateTime.now().toUtc();
final userId = authRepository.getUserId();
if (problemEntity.syncStatus == SyncStatus.pendingCreate) {
await problemRepository.deleteProblem(problemEntity.id);
} else {
final newProblem = problemEntity.copyWith(
lastModifiedTime: nowUtc,
lastModifierId: userId,
syncStatus: SyncStatus.pendingDelete,
);
await problemRepository.updateProblem(newProblem);
}
}
}

8
lib/app/features/problem/presentation/bindings/problem_list_binding.dart

@ -8,6 +8,7 @@ import 'package:problem_check_system/app/features/problem/data/datasources/probl
import 'package:problem_check_system/app/features/problem/data/datasources/problem_remote_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/repositories/problem_repository_impl.dart'; 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/repositories/problem_repository.dart';
import 'package:problem_check_system/app/features/problem/domain/usecases/delete_problem_usecase.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/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/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/domain/usecases/sync_problems_usecase.dart';
@ -58,6 +59,12 @@ class ProblemListBinding extends BaseBindings {
Get.lazyPut<ProblemResolveConflictUsecase>( Get.lazyPut<ProblemResolveConflictUsecase>(
() => ProblemResolveConflictUsecase(repository: Get.find()), () => ProblemResolveConflictUsecase(repository: Get.find()),
); );
Get.lazyPut<DeleteProblemUsecase>(
() => DeleteProblemUsecase(
problemRepository: Get.find(),
authRepository: Get.find(),
),
);
} }
@override @override
@ -68,6 +75,7 @@ class ProblemListBinding extends BaseBindings {
syncProblemsUsecase: Get.find(), syncProblemsUsecase: Get.find(),
problemResolveConflictUsecase: Get.find(), problemResolveConflictUsecase: Get.find(),
getEnterprisesUsecase: Get.find(), getEnterprisesUsecase: Get.find(),
deleteProblemUsecase: Get.find(),
), ),
); );
} }

66
lib/app/features/problem/presentation/controllers/problem_list_controller.dart

@ -11,6 +11,7 @@ import 'package:problem_check_system/app/features/problem/domain/entities/proble
import 'package:problem_check_system/app/features/problem/domain/entities/problem_list_item_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/entities/problem_upload_status.dart'; import 'package:problem_check_system/app/features/problem/domain/entities/problem_upload_status.dart';
import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart'; import 'package:problem_check_system/app/features/problem/domain/repositories/problem_repository.dart';
import 'package:problem_check_system/app/features/problem/domain/usecases/delete_problem_usecase.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/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/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/domain/usecases/sync_problems_usecase.dart';
@ -20,12 +21,14 @@ class ProblemListController extends GetxController {
final GetEnterprisesUsecase getEnterprisesUsecase; final GetEnterprisesUsecase getEnterprisesUsecase;
final SyncProblemsUsecase syncProblemsUsecase; final SyncProblemsUsecase syncProblemsUsecase;
final ProblemResolveConflictUsecase problemResolveConflictUsecase; final ProblemResolveConflictUsecase problemResolveConflictUsecase;
final DeleteProblemUsecase deleteProblemUsecase;
ProblemListController({ ProblemListController({
required this.getAllProblemsUsecase, required this.getAllProblemsUsecase,
required this.syncProblemsUsecase, required this.syncProblemsUsecase,
required this.problemResolveConflictUsecase, required this.problemResolveConflictUsecase,
required this.getEnterprisesUsecase, required this.getEnterprisesUsecase,
required this.deleteProblemUsecase,
}); });
final problemList = <ProblemListItemEntity>[].obs; final problemList = <ProblemListItemEntity>[].obs;
@ -218,6 +221,69 @@ class ProblemListController extends GetxController {
} }
} }
///
Future<bool?> confirmDeleteProblem(ProblemEntity problem) async {
// 使 Get.dialog
return await Get.dialog<bool>(
AlertDialog(
title: const Text('确认删除'),
content: Text('您确定要删除问题 "${problem.description}" 吗?此操作不可恢复。'),
actions: <Widget>[
TextButton(
child: const Text('取消'),
onPressed: () {
// false
Get.back(result: false);
},
),
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.red, //
),
child: const Text('删除'),
onPressed: () {
// true
Get.back(result: true);
},
),
],
),
);
}
///
Future<void> deleteProblem(ProblemEntity problem) async {
// 使 try-catch
try {
// deleteProblemUsecase
await deleteProblemUsecase(problem);
// [!!!] UI列表中移除该项
// problemList .obsUI会自动更新
problemList.removeWhere((item) => item.problemEntity.id == problem.id);
//
Get.snackbar(
'删除成功',
'"${problem.description}" 已被删除。',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
colorText: Colors.white,
);
} catch (e) {
//
Get.snackbar(
'删除失败',
'无法删除该问题: $e',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red,
colorText: Colors.white,
);
// UI状态
// loadAndSyncProblems();
}
}
// //
void setFilters(Enterprise enterprise) { void setFilters(Enterprise enterprise) {
showAppBar.value = false; showAppBar.value = false;

191
lib/app/features/problem/presentation/pages/problem_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/pages/widgets/custom_app_bar.dart'; import 'package:problem_check_system/app/core/pages/widgets/custom_app_bar.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';
@ -339,82 +340,142 @@ class ProblemListPage extends GetView<ProblemListController> {
itemCount: controller.problemList.length, itemCount: controller.problemList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = controller.problemList[index]; final item = controller.problemList[index];
final enterprise = item.problemEntity; final problemEntity = item.problemEntity;
// : base controller // : base controller
final isSelected = controller.selectedProblems.contains(enterprise); final isSelected = controller.selectedProblems.contains(
problemEntity,
);
//
final bool isPendingDelete =
problemEntity.syncStatus == SyncStatus.pendingDelete;
// 1.使 Dismissible
return Dismissible(
// 2. Dismissible Key
// Flutter
// 使ID
key: Key(problemEntity.id),
// 3.
// isPendingDelete true none
// endToStart
direction: isPendingDelete
? DismissDirection.none
: DismissDirection.endToStart,
return Padding( // 4.
padding: EdgeInsets.only(bottom: 12.h), //
child: ProblemCard( background: Container(
problemListItem: item, color: Colors.red, //
isSelected: isSelected, padding: EdgeInsets.symmetric(horizontal: 20.w),
onTap: () => alignment: Alignment.centerRight, //
controller.navigateToDetailsView(item.problemEntity), child: Row(
actions: Row( mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
// Text(
ElevatedButton( '删除',
onPressed: () => style: TextStyle(
controller.navigateToEditForm(item.problemEntity), color: Colors.white,
style: ElevatedButton.styleFrom( fontWeight: FontWeight.bold,
backgroundColor: const Color(0xFF42A5F5), fontSize: 16.sp,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(
horizontal: 20.w,
vertical: 8.h,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
// [!!!]
elevation: 0,
// [!!!]
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.r),
bottomRight: Radius.circular(12.r),
),
),
),
child: Text(
"修改",
style: TextStyle(
fontSize: 13.sp,
fontWeight: FontWeight.bold,
),
), ),
), ),
SizedBox(width: 8.w), SizedBox(width: 8.w),
// () const Icon(Icons.delete, color: Colors.white),
ElevatedButton( ],
onPressed: () => ),
controller.navigateToDetailsView(item.problemEntity), ),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF42A5F5), // 5.
foregroundColor: Colors.white, //
padding: EdgeInsets.symmetric( confirmDismiss: (direction) async {
horizontal: 20.w, //
vertical: 8.h, return await controller.confirmDeleteProblem(problemEntity);
},
// 6. true
//
// confirmDismiss true onDismissed
onDismissed: (direction) {
//
controller.deleteProblem(problemEntity);
},
// 7. child Dismissible
child: Padding(
padding: EdgeInsets.only(bottom: 12.h),
child: ProblemCard(
problemListItem: item,
isSelected: isSelected,
onTap: () =>
controller.navigateToDetailsView(item.problemEntity),
actions: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
//
if (isPendingDelete == false)
ElevatedButton(
onPressed: () =>
controller.navigateToEditForm(item.problemEntity),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF42A5F5),
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(
horizontal: 20.w,
vertical: 8.h,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
// [!!!]
elevation: 0,
// [!!!]
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.r),
bottomRight: Radius.circular(12.r),
),
),
),
child: Text(
"修改",
style: TextStyle(
fontSize: 13.sp,
fontWeight: FontWeight.bold,
),
),
), ),
tapTargetSize: MaterialTapTargetSize.shrinkWrap, SizedBox(width: 8.w),
// [!!!] // ()
elevation: 0, ElevatedButton(
// [!!!] onPressed: () => controller.navigateToDetailsView(
shape: RoundedRectangleBorder( item.problemEntity,
borderRadius: BorderRadius.only( ),
topLeft: Radius.circular(12.r), style: ElevatedButton.styleFrom(
bottomRight: Radius.circular(12.r), backgroundColor: const Color(0xFF42A5F5),
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(
horizontal: 20.w,
vertical: 8.h,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
// [!!!]
elevation: 0,
// [!!!]
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12.r),
bottomRight: Radius.circular(12.r),
),
), ),
), ),
), child: Text(
child: Text( "查看",
"查看", style: TextStyle(
style: TextStyle( fontSize: 13.sp,
fontSize: 13.sp, fontWeight: FontWeight.bold,
fontWeight: FontWeight.bold, ),
), ),
), ),
), ],
], ),
), ),
), ),
); );

Loading…
Cancel
Save