Browse Source

抽取相同的代码到BasePhotoController

云天逵 1 năm trước cách đây
mục cha
commit
449c1cfb44

+ 199 - 0
lib/base/base_photo_controller.dart

@@ -0,0 +1,199 @@
+import 'package:clean/base/base_controller.dart';
+import 'package:get/get.dart';
+import 'package:wechat_assets_picker/wechat_assets_picker.dart';
+import 'package:clean/module/image_picker/image_picker_util.dart';
+import 'package:clean/module/people_photo/photo_group.dart';
+import 'package:clean/utils/toast_util.dart';
+import 'package:clean/data/bean/photos_type.dart';
+import 'package:clean/module/photo_preview/photo_preview_view.dart';
+
+abstract class BasePhotoController extends BaseController {
+  final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
+  final RxDouble selectedFilesSize = 0.0.obs;
+  RxInt selectedFileCount = 0.obs;
+  final RxSet<String> selectedPhotosIds = <String>{}.obs;
+  bool isDeleteFinish = false;
+
+  // 将selectedFilesSize转成String类型,然后单位转换,如果超过1MB,则转成MB,超过1GB,则转成GB,否则KB
+  String get selectedFilesSizeString {
+    if (selectedFilesSize.value > 1024) {
+      return "${(selectedFilesSize.value  / 1024).toStringAsFixed(2)}MB";
+    } else if (selectedFilesSize.value > 1024 *  1024) {
+      return "${(selectedFilesSize.value / 1024 /  1024).toStringAsFixed(2)}GB";
+    } else {
+      return "${(selectedFilesSize.value).toStringAsFixed(2)}KB";
+    }
+  }
+
+
+  // 获取选中的文件大小
+  Future<void> getSelectedFilesSize() async {
+    double totalSize = 0;
+    for (var group in photoGroups) {
+      for (int i = 0; i < group.images.length; i++) {
+        if (group.selectedImages[i]) {
+          final file = await group.images[i].file;
+          if (file != null) {
+            totalSize += file.lengthSync();
+          }
+        }
+      }
+    }
+    selectedFilesSize.value = totalSize / 1024; // Convert to KB
+  }
+
+  // 切换图片选中状态
+  void toggleImageSelection(List<AssetEntity> groupTitle, int imageIndex) {
+    print("BasePhotoController toggleImageSelection");
+    final group = getGroupByImages(groupTitle);
+    final image = group.images[imageIndex];
+    final selected = !group.selectedImages[imageIndex];
+
+    group.selectedImages[imageIndex] = selected;
+    updateSelectedPhotosIds(image.id, selected);
+
+    group.isSelected.value = group.selectedImages.every((selected) => selected);
+
+    selectedFileCount.value = selectedPhotosIds.length;
+    getSelectedFilesSize();
+  }
+
+  void clickImage(List<AssetEntity> images, int imageIndex, PhotosType type) {
+    print("BasePhotoController clickImage");
+    final group = getGroupByImages(images);
+    final image = group.images[imageIndex];
+    PhotoPreviewPage.start(type, image.id);
+  }
+
+  // 切换图片组选中状态
+  void toggleGroupSelection(List<AssetEntity> imagesList) {
+    print("BasePhotoController toggleGroupSelection");
+    final group = getGroupByImages(imagesList);
+    final newValue = !group.isSelected.value;
+    group.toggleSelectAll(newValue);
+
+    for (var image in group.images) {
+      updateSelectedPhotosIds(image.id, newValue);
+    }
+    selectedFileCount.value = selectedPhotosIds.length;
+    getSelectedFilesSize();
+  }
+
+
+  PhotoGroup getGroupByImages(List<AssetEntity> images) {
+    final imageIds = images.map((img) => img.id).toSet();
+    return photoGroups.firstWhere(
+        (group) => group.images.every((image) => imageIds.contains(image.id)));
+  }
+
+  void updateSelectedPhotosIds(String photoId, bool isSelected) {
+    if (isSelected) {
+      selectedPhotosIds.add(photoId);
+    } else {
+      selectedPhotosIds.remove(photoId);
+    }
+  }
+
+  // 恢复选中状态
+  void restoreSelections() async {
+    final selectedIds = selectedPhotosIds.toSet();
+    for (var group in photoGroups) {
+      for (int i = 0; i < group.images.length; i++) {
+        group.selectedImages[i] = selectedIds.contains(group.images[i].id);
+      }
+      group.isSelected.value =
+          group.selectedImages.every((selected) => selected);
+    }
+    selectedFileCount.value = selectedIds.length;
+    if (selectedIds.isEmpty) {
+
+      selectedFilesSize.value = 0;
+      return;
+    }
+    await getSelectedFilesSize();
+  }
+
+  @override
+  void onInit() {
+    print("BasePhotoController onInit");
+    super.onInit();
+    loadPhotos();
+    restoreSelections();
+  }
+
+
+
+  void loadPhotos();
+
+  // 点击删除
+  void clickDelete() async {
+
+    if (selectedPhotosIds.isNotEmpty) {
+      final assetsToDelete = photoGroups
+          .expand((group) => group.images
+              .where((asset) => selectedPhotosIds.contains(asset.id)))
+          .toList();
+
+      final List<String> result = await PhotoManager.editor.deleteWithIds(
+        assetsToDelete.map((e) => e.id).toList(),
+      );
+
+      if (result.length == selectedPhotosIds.length) {
+        for (var group in photoGroups) {
+          group.images
+              .removeWhere((element) => selectedPhotosIds.contains(element.id));
+
+
+        }
+        ImagePickerUtil.updatePhotoGroupDate(
+            getPhotosType(), selectedPhotosIds);
+
+        selectedPhotosIds.clear();
+        isDeleteFinish = true;
+        ToastUtil.show("Delete success");
+
+      } else {
+        ToastUtil.show("Delete failed");
+        isDeleteFinish = false;
+      }
+    }
+  }
+
+  void updateSelections(Set<String> selectedIds) {
+
+    print("BasePhotoController updateSelections selectedIds $selectedIds, selectedPhotosIds $selectedPhotosIds getPhotosType() ${getPhotosType()}");
+    // selectedId如果是selectedPhotosIds对象,那么selectedPhotosIds.assignAll(selectedIds)会清空
+    // selectedPhotosIds.assignAll(selectedIds);
+
+    selectedPhotosIds.assignAll(Set.from(selectedIds));
+    print("BasePhotoController updateSelections selectedIds $selectedIds, selectedPhotosIds $selectedPhotosIds getPhotosType() ${getPhotosType()}");
+
+    switch (getPhotosType()) {
+      case PhotosType.peoplePhotos:
+        ImagePickerUtil.selectedPeoplePhotosIds.assignAll(selectedPhotosIds);
+        break;
+      case PhotosType.screenshots:
+        ImagePickerUtil.selectedScreenshotPhotosIds
+            .assignAll(selectedPhotosIds);
+        break;
+      case PhotosType.similarPhotos:
+        ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
+        break;
+      case PhotosType.locationPhotos:
+        ImagePickerUtil.selectedLocationPhotosIds.assignAll(selectedPhotosIds);
+        break;
+      case PhotosType.blurryPhotos:
+        ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
+        break;
+    }
+
+  }
+
+  PhotosType
+      getPhotosType();
+
+  // 将photoGroups中所有的图片返回
+  List<AssetEntity> getAllPhotos() {
+    return photoGroups.expand((group) => group.images).toList();
+  }
+}

+ 3 - 1
lib/dialog/photo_delete_finish_dialog.dart

@@ -15,7 +15,9 @@ void photoDeleteFinishDialog() {
   Future.delayed(Duration(milliseconds: 1500), () {
     SmartDialog.dismiss(tag: tag);
     //   回到首页
-   MainTabPage.start();
+    Get.until((route) => Get. currentRoute ==RoutePath.mainTab);
+
+
   });
   SmartDialog.show(
       tag: tag,

+ 10 - 8
lib/module/image_picker/image_picker_util.dart

@@ -59,7 +59,9 @@ class ImagePickerUtil {
     locationPhotos.clear();
     peoplePhotos.clear();
   }
-  static Future<void> updatePhotoGroupDate(PhotosType photosType,Set<String> selectedPhotosIds, ) async {
+
+
+  static Future<void> updatePhotoGroupDate(PhotosType photosType,Set<String> selectedPhotosIds) async {
     // 1. 统一移除相关的照片列表
     screenshotPhotos.removeWhere((element) => selectedPhotosIds.contains(element.id));
     for (var group in similarPhotos) {
@@ -73,6 +75,13 @@ class ImagePickerUtil {
     locationPhotos.removeWhere((key, value) => value.isEmpty);
 
 
+    selectedScreenshotPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+    selectedSimilarPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+    selectedLocationPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+    selectedPeoplePhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+    selectedBlurryPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+
+
 
     // 3. 根据photosType来处理不同的控制器和photoGroups
     switch (photosType) {
@@ -122,13 +131,6 @@ class ImagePickerUtil {
         break;
 
     }
-
-
-
-
-    // 4. 清空已选择的照片ID集合
-    selectedPhotosIds.clear();
-
   }
 
   // 更新照片数据

+ 17 - 7
lib/module/locations_photo/locations_photo_controller.dart

@@ -1,5 +1,6 @@
 import 'dart:io';
 
+import 'package:clean/base/base_controller.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/locations_photo/locations_single_photo_view.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
@@ -8,9 +9,10 @@ import 'package:path_provider/path_provider.dart';
 import 'package:path/path.dart' as p;
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
-class LocationsPhotoController extends GetxController {
+class LocationsPhotoController extends BaseController {
    final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
 
+
   @override
   onInit() {
     super.onInit();
@@ -34,8 +36,16 @@ class LocationsPhotoController extends GetxController {
         ));
       }
     }
+
+
   }
 
+  @override
+  void onReady() {
+    // TODO: implement onReady
+    super.onReady();
+    restoreSelections();
+  }
   void clickPhotoGroup(PhotoGroup photoGroup) {
     print('clickPhotoGroup ${photoGroup.location}');
     LocationsSinglePhotoPage.start(photoGroup: photoGroup);
@@ -46,11 +56,11 @@ class LocationsPhotoController extends GetxController {
   }
 
   void restoreSelections() {
+    for (var group in photoGroups) {
+      for (int i = 0; i < group.images.length; i++) {
+        group.selectedImages[i] = ImagePickerUtil.selectedLocationPhotosIds.contains(group.images[i].id);
+      }
+    }
   }
-// PhotoGroup getGroupByImages(List<AssetEntity> images) {
-//   final imageIds = images.map((img) => img.id).toSet();
-//   return photoGroups.firstWhere((group) =>
-//       group.images.every((image) => imageIds.contains(image.id))
-//   );
-// }
+
 }

+ 27 - 118
lib/module/locations_photo/locations_single_photo_controller.dart

@@ -1,5 +1,6 @@
 
 import 'package:clean/base/base_controller.dart';
+import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/locations_photo/locations_photo_controller.dart';
@@ -8,143 +9,51 @@ import 'package:clean/module/photo_preview/photo_preview_view.dart';
 import 'package:clean/utils/toast_util.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
-class LocationsSinglePhotoController extends BaseController {
 
-  late final PhotoGroup photoGroup;
-  final RxInt selectedFileCount = 0.obs;
+class LocationsSinglePhotoController extends BasePhotoController {
 
 
-  final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
-  final RxDouble selectedFilesSize = 0.0.obs;
+  late PhotoGroup photoGroup;
+
   @override
   void onInit() {
-    // TODO: implement onInit
-    super.onInit();
+    print('LocationsSinglePhotoController onInit');
     _getArgs();
-    loadLocationsSinglePhoto();
-    restoreSelections();
-
-  }
-
-  void clickImage(String location, int imageIndex) {
-    final group = getGroupByLocation(location);
-    final image = group.images[imageIndex];
-
-    PhotoPreviewPage.start(PhotosType.locationPhotos, image.id);
-  }
-
-  void toggleImageSelection(String groupTitle, int imageIndex) {
-    final group = getGroupByLocation(groupTitle);
-    final image = group.images[imageIndex];
-    final selected = !group.selectedImages[imageIndex];
-
-    group.selectedImages[imageIndex] = selected;
-    _updateSelectedScreenshotsPhotosIds(image.id, selected);
-
-    group.isSelected.value = group.selectedImages.every((selected) => selected);
-
-    updateSelectedFilesSize();
-    selectedFileCount.value = ImagePickerUtil.selectedLocationPhotosIds.length;
-  }
-
-  Future<void> updateSelectedFilesSize() async {
-    double totalSize = 0;
-
-    for (var id in ImagePickerUtil.selectedLocationPhotosIds) {
-      final entity = await AssetEntity.fromId(id);
-      if (entity != null) {
-        final file = await entity.file;
-        if (file != null) {
-          totalSize += await file.length();
-        }
-      }
-    }
-
-    selectedFilesSize.value = totalSize / 1024; // Convert to KB
-  }
-
-  void _updateSelectedScreenshotsPhotosIds(String photoId, bool isSelected) {
-    if (isSelected) {
-      ImagePickerUtil.selectedLocationPhotosIds.add(photoId);
-    } else {
-      ImagePickerUtil.selectedLocationPhotosIds.remove(photoId);
-    }
+    super.onInit();
   }
 
-  // 获取参数
+  // 获取传递的参数
   void _getArgs() {
+    final parameters = Get.arguments;
     photoGroup = parameters?['PhotoGroup'] as PhotoGroup;
-
-  }
-  void loadLocationsSinglePhoto() {
-    photoGroups.clear();
-    if (ImagePickerUtil.locationPhotos.isEmpty) {
-      print('locationPhotos.isEmpty');
-      return;
-    }
-    photoGroups.add(photoGroup);
-  }
-
-  void restoreSelections() async {
-    final selectedIds = ImagePickerUtil.selectedLocationPhotosIds.toSet();
-
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        group.selectedImages[i] = selectedIds.contains(group.images[i].id);
-      }
-      group.isSelected.value = group.selectedImages.every((selected) => selected);
-    }
-    await updateSelectedFilesSize();
-    selectedFileCount.value = selectedIds.length;
   }
 
-  void toggleGroupSelection(String location) {
-    final group = getGroupByLocation(location);
-    final newValue = !group.isSelected.value;
-    group.toggleSelectAll(newValue);
+  // // 通过位置获取照片组
+  // PhotoGroup getGroupByLocation(String? location) {
+  //   return photoGroups.firstWhere((group) => group.location == location);
+  // }
 
-    for (var image in group.images) {
-      _updateSelectedScreenshotsPhotosIds(image.id, newValue);
-    }
 
-    updateSelectedFilesSize();
-    selectedFileCount.value =  ImagePickerUtil.selectedLocationPhotosIds.length;
-  }
-
-
-  // 通过位置获取照片组
-  PhotoGroup getGroupByLocation(String? location) {
-    return photoGroups.firstWhere((group) => group.location == location);
+  // 获取对应的 PhotosType
+  @override
+  PhotosType getPhotosType() {
+    return PhotosType.locationPhotos;
   }
 
 
-  clickDelete() async {
-    print('clickDelete');
-
-    if (ImagePickerUtil.selectedLocationPhotosIds.isNotEmpty) {
-      final assetsToDelete = photoGroups.expand((group) =>
-          group.images.where((asset) => ImagePickerUtil.selectedLocationPhotosIds.contains(asset.id))
-      ).toList();
-
-      final List<String> result = await PhotoManager.editor.deleteWithIds(
-        assetsToDelete.map((e) => e.id).toList(),
-      );
-      print('PhotoPreviewController result $result');
 
-      if (result.length == ImagePickerUtil.selectedLocationPhotosIds.length) {
-        if (photoGroup.images.length == ImagePickerUtil.selectedLocationPhotosIds.length) {
-          ImagePickerUtil.locationPhotos.remove(photoGroup.location);
-        } else {
-          photoGroup.images.removeWhere((element) => ImagePickerUtil.selectedLocationPhotosIds.contains(element.id));
-        }
-        ImagePickerUtil.updatePhotoGroupDate(PhotosType.locationPhotos, ImagePickerUtil.selectedLocationPhotosIds);
-        ToastUtil.show("Delete success");
-      } else {
-        // 删除失败
-        ToastUtil.show("Delete failed");
-      }
+  @override
+  void loadPhotos() {
+    photoGroups.clear();
+    if (photoGroup.images.isNotEmpty) {
+      photoGroups.add(photoGroup);
     }
+    selectedPhotosIds.assignAll(ImagePickerUtil.selectedLocationPhotosIds);
   }
 
-
+  void clickBack() {
+    print('LocationsSinglePhotoController clickBack selectedPhotosIds $selectedPhotosIds');
+    updateSelections(selectedPhotosIds); // 恢复选中状态
+    Get.back();
+  }
 }

+ 21 - 10
lib/module/locations_photo/locations_single_photo_view.dart

@@ -1,4 +1,5 @@
 import 'package:clean/base/base_page.dart';
+import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/locations_photo/locations_single_photo_controller.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
 import 'package:clean/resource/assets.gen.dart';
@@ -31,7 +32,15 @@ class LocationsSinglePhotoPage
   @override
   Widget buildBody(BuildContext context) {
     return Stack(children: [
-      Container(
+      PopScope(
+        canPop: false,
+          onPopInvokedWithResult: (didPop, result) {
+            if (didPop) {
+              return;
+            }
+            controller.clickBack();
+          },
+          child: Container(
         child: SafeArea(
           child: Obx(() {
             if (controller.photoGroups.isEmpty) {
@@ -56,7 +65,7 @@ class LocationsSinglePhotoPage
                           ),
                           itemCount: controller.photoGroups.first.images.length,
                           itemBuilder: _buildPhotoItem(
-                              controller.photoGroups.first.location ?? "")),
+                              controller.photoGroups.first.images)),
                     );
                   }),
                 ),
@@ -72,7 +81,7 @@ class LocationsSinglePhotoPage
             );
           }),
         ),
-      ),
+      )),
       IgnorePointer(
         child: Assets.images.bgHome.image(
           width: 360.w,
@@ -93,7 +102,7 @@ class LocationsSinglePhotoPage
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             children: [
               GestureDetector(
-                onTap: () => Get.back(),
+                onTap: controller.clickBack,
                 child: Assets.images.iconBackArrow.image(
                   width: 28.w,
                   height: 28.h,
@@ -115,7 +124,7 @@ class LocationsSinglePhotoPage
                 if (controller.photoGroups.isEmpty) return SizedBox();
                 return GestureDetector(
                   onTap: () => controller.toggleGroupSelection(
-                      controller.photoGroups.first.location ?? ""),
+                      controller.photoGroups.first.images),
                   child: Obx(() => Text(
                         controller.photoGroups.first.isSelected.value
                             ? 'Deselect All'
@@ -159,7 +168,7 @@ class LocationsSinglePhotoPage
             SizedBox(width: 5.w),
             Obx(() {
               return Text(
-                '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
+                '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSizeString})',
                 textAlign: TextAlign.center,
                 style: TextStyle(
                   color: Colors.white,
@@ -174,12 +183,14 @@ class LocationsSinglePhotoPage
     );
   }
 
-  Widget Function(BuildContext, int) _buildPhotoItem(String location) =>
+  Widget Function(BuildContext, int) _buildPhotoItem(
+          List<AssetEntity> images) =>
       (context, index) {
-        final group = controller.getGroupByLocation(location);
+        final group = controller.getGroupByImages(images);
 
         return GestureDetector(
-          onTap: () => controller.clickImage(location, index),
+          onTap: () =>
+              controller.clickImage(images, index, PhotosType.locationPhotos),
           child: Obx(() {
             final isSelected = group.selectedImages[index];
             return Stack(
@@ -207,7 +218,7 @@ class LocationsSinglePhotoPage
                   bottom: 8.h,
                   child: GestureDetector(
                       onTap: () =>
-                          controller.toggleImageSelection(location, index),
+                          controller.toggleImageSelection(images, index),
                       child: Container(
                         child: isSelected
                             ? Center(

+ 17 - 130
lib/module/people_photo/people_photo_controller.dart

@@ -1,4 +1,5 @@
 import 'package:clean/base/base_controller.dart';
+import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
@@ -7,113 +8,11 @@ import 'package:clean/utils/toast_util.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
-class PeoplePhotoController extends BaseController {
-  final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
-  final RxDouble selectedFilesSize = 0.0.obs;
-  final RxInt selectedFileCount = 0.obs;
-
-  @override
-  void onInit() {
-    super.onInit();
-    loadPeoplePhoto();
-    restoreSelections();
-  }
-
+class PeoplePhotoController extends BasePhotoController {
   @override
-  void onReady() {
-    super.onReady();
-  }
-
-  Future<void> updateSelectedFilesSize() async {
-    double totalSize = 0;
-    // 通过selectedPhotosIds获取选中的图片,然后计算大小
-    for (var id in ImagePickerUtil.selectedPeoplePhotosIds) {
-      final entity = await AssetEntity.fromId(id);
-      if (entity != null) {
-        final file = await entity.file;
-        if (file != null) {
-          totalSize += await file.length();
-        }
-      }
-    }
-
-    selectedFilesSize.value = totalSize / 1024; // Convert to KB
-  }
-
-  void toggleImageSelection(
-      List<AssetEntity> groupTitle, int imageIndex) async {
-    final group = getGroupByImages(groupTitle);
-    final image = group.images[imageIndex];
-    final selected = !group.selectedImages[imageIndex];
-
-    group.selectedImages[imageIndex] = selected;
-    _updateSelectedPeoplePhotosIds(image.id, selected);
-
-    group.isSelected.value = group.selectedImages.every((selected) => selected);
-
-    selectedFileCount.value = ImagePickerUtil.selectedPeoplePhotosIds.length;
-    await updateSelectedFilesSize();
-  }
-
-  void clickImage(List<AssetEntity> images, int imageIndex) {
-    final group = getGroupByImages(images);
-    final image = group.images[imageIndex];
-
-    PhotoPreviewPage.start(PhotosType.peoplePhotos, image.id);
-  }
-
-  void toggleGroupSelection(List<AssetEntity> images) async {
-    final group = getGroupByImages(images);
-    final newValue = !group.isSelected.value;
-    group.toggleSelectAll(newValue);
-
-    for (var image in group.images) {
-      _updateSelectedPeoplePhotosIds(image.id, newValue);
-    }
-    selectedFileCount.value = ImagePickerUtil.selectedPeoplePhotosIds.length;
-    updateSelectedFilesSize();
-  }
-
-  PhotoGroup getGroupByImages(List<AssetEntity> images) {
-    final imageIds = images.map((img) => img.id).toSet();
-    return photoGroups.firstWhere(
-        (group) => group.images.every((image) => imageIds.contains(image.id)));
-  }
-
-  void _updateSelectedPeoplePhotosIds(String photoId, bool isSelected) {
-    if (isSelected) {
-      // 检查这个id有没有在这个list里面
-      if (!ImagePickerUtil.selectedPeoplePhotosIds.contains(photoId)) {
-        ImagePickerUtil.selectedPeoplePhotosIds.add(photoId);
-      }
-    } else {
-      ImagePickerUtil.selectedPeoplePhotosIds.remove(photoId);
-    }
-  }
-
-  void restoreSelections() async {
-    print("PeoplePhotoController  restoreSelections");
-
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        if (ImagePickerUtil.selectedPeoplePhotosIds
-            .contains(group.images[i].id)) {
-          group.selectedImages[i] = true;
-        } else {
-          group.selectedImages[i] = false;
-        }
-      }
-      group.isSelected.value =
-          group.selectedImages.every((selected) => selected);
-    }
-    updateSelectedFilesSize();
-    selectedFileCount.value = ImagePickerUtil.selectedPeoplePhotosIds.length;
-  }
-
-  void loadPeoplePhoto() {
-    print("loadPeoplePhoto");
+  void loadPhotos() {
+    // 清空现有数据
     photoGroups.clear();
-
     final photoGroup = ImagePickerUtil.peoplePhotos;
     if (photoGroup.isNotEmpty) {
       photoGroups.add(PhotoGroup(
@@ -121,34 +20,22 @@ class PeoplePhotoController extends BaseController {
         images: photoGroup,
       ));
     }
+    print('PeoplePhotoController loadPhotos ImagePickerUtil.selectedPeoplePhotosIds ${ImagePickerUtil.selectedPeoplePhotosIds}');
+    selectedPhotosIds.assignAll(ImagePickerUtil.selectedPeoplePhotosIds);
   }
 
-  clickDelete() async {
-    print('clickDelete');
-
-    if (ImagePickerUtil.selectedPeoplePhotosIds.isNotEmpty) {
-      // 获取要删除的资产
-      final assetsToDelete = ImagePickerUtil.peoplePhotos
-          .where(
-            (asset) =>
-                ImagePickerUtil.selectedPeoplePhotosIds.contains(asset.id),
-          )
-          .toList();
+  @override
+  PhotosType getPhotosType() => PhotosType.peoplePhotos;
 
-      // 调用方法会返回被删除的资源,如果全部失败会返回空列表。
-      final List<String> result = await PhotoManager.editor.deleteWithIds(
-        assetsToDelete.map((e) => e.id).toList(),
-      );
-      print('PhotoPreviewController result $result');
+  void clickBack() {
+    print('PeoplePhotoController clickBack selectedPhotosIds $selectedPhotosIds');
+    updateSelections(selectedPhotosIds); // 恢复选中状态
 
-      if (result.length == ImagePickerUtil.selectedPeoplePhotosIds.length) {
-        // 删除成功
-        ToastUtil.show("Delete success");
-        ImagePickerUtil.updatePhotoGroupDate(PhotosType.peoplePhotos,ImagePickerUtil.selectedPeoplePhotosIds);
-      } else {
-        // 删除失败
-        ToastUtil.show("Delete failed");
-      }
-    }
+    Get.back();
+  }
+  @override
+  void onReady() {
+    // TODO: implement onReady
+    super.onReady();
   }
 }

+ 14 - 5
lib/module/people_photo/people_photo_view.dart

@@ -1,6 +1,7 @@
 import 'dart:io';
 
 import 'package:clean/base/base_page.dart';
+import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/people_photo/people_photo_controller.dart';
 import 'package:clean/resource/assets.gen.dart';
@@ -33,7 +34,15 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
   @override
   Widget buildBody(BuildContext context) {
     return Stack(children: [
-      Container(
+     PopScope(
+       canPop: false,
+        onPopInvokedWithResult: (didPop, result) {
+          if (didPop) {
+            return;
+          }
+          controller.clickBack();
+        },
+       child:  Container(
         child: SafeArea(
           child: Obx(() {
             if (controller.photoGroups.isEmpty ||
@@ -68,7 +77,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
             );
           }),
         ),
-      ),
+      ),),
       IgnorePointer(
         child: Assets.images.bgHome.image(
           width: 360.w,
@@ -86,7 +95,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
         crossAxisAlignment: CrossAxisAlignment.start,
         children: [
           GestureDetector(
-            onTap: () => Get.back(),
+            onTap:  controller.clickBack,
             child: Assets.images.iconBackArrow.image(
               width: 28.w,
               height: 28.h,
@@ -135,7 +144,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
         children: [
           Obx(() {
             return Text(
-              '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
+              '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSizeString})',
               textAlign: TextAlign.center,
               style: TextStyle(
                 color: Colors.white.withOpacity(0.9),
@@ -274,7 +283,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
 
         return GestureDetector(
           onTap: () {
-            controller.clickImage(images, index);
+            controller.clickImage(images, index, PhotosType.peoplePhotos);
             print("点击图片");
           },
           child: Obx(() {

+ 102 - 56
lib/module/photo_preview/photo_preview_controller.dart

@@ -1,6 +1,7 @@
 import 'dart:async';
 
 import 'package:clean/base/base_controller.dart';
+import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/data/consts/constants.dart';
 import 'package:clean/dialog/photo_delete_finish_dialog.dart';
@@ -22,8 +23,9 @@ import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 class PhotoPreviewController extends BaseController {
   Rx<CardSwiperController> cardSwiperController = CardSwiperController().obs;
-  final RxList<AssetEntity> photoGroups = <AssetEntity>[].obs;
+  final RxList<AssetEntity> listAssetEntity = <AssetEntity>[].obs;
   final RxSet<String> selectedPhotosIds = <String>{}.obs;
+
   final RxBool isSwiperEnd = false.obs;
   RxInt groupIndex = 0.obs;
 
@@ -35,16 +37,16 @@ class PhotoPreviewController extends BaseController {
   @override
   void onInit() {
     super.onInit();
-    isSwiperEnd.value = false;
+
     print('PhotoPreviewController onInit');
     _getArgs(); // 获取传递的参数
     _initData(); // 初始化数据
 
     WidgetsBinding.instance.addPostFrameCallback((_) {
       if (currentImageId != null) {
-        for (int i = 0; i < photoGroups.length; i++) {
-          if (photoGroups[i].id == currentImageId) {
-            print('photoGroups[i].id ${photoGroups[i].id},i $i');
+        for (int i = 0; i < listAssetEntity.length; i++) {
+          if (listAssetEntity[i].id == currentImageId) {
+            print('photoGroups[i].id ${listAssetEntity[i].id},i $i');
             groupIndex.value = i;
             cardSwiperController.value.moveTo(i);
             break;
@@ -58,12 +60,13 @@ class PhotoPreviewController extends BaseController {
   void onReady() {
     // TODO: implement onReady
     super.onReady();
-
+    print('PhotoPreviewController onReady');
     if (isFirstOpenPhotoPreview()) {
       photoPreviewTipDialog(clickCallback: () {
         setFirstOpenPhotoPreview(false);
       });
     }
+
   }
 
   // 获取参数
@@ -73,54 +76,81 @@ class PhotoPreviewController extends BaseController {
   }
 
   void _initData() {
-    photoGroups.clear();
+    listAssetEntity.clear();
     selectedPhotosIds.clear();
 
     switch (photosType) {
       case PhotosType.peoplePhotos:
-        photoGroups.assignAll(ImagePickerUtil.peoplePhotos);
-        selectedPhotosIds.assignAll(ImagePickerUtil.selectedPeoplePhotosIds);
-        selectedFileCount.value =
-            ImagePickerUtil.selectedPeoplePhotosIds.length;
+        final PeoplePhotoController controller =
+            Get.find<PeoplePhotoController>();
+        listAssetEntity.assignAll(controller.getAllPhotos());
+        selectedPhotosIds.assignAll(controller.selectedPhotosIds);
+        selectedFileCount.value = selectedPhotosIds.length;
         break;
       case PhotosType.screenshots:
-        photoGroups.assignAll(ImagePickerUtil.screenshotPhotos);
-        selectedPhotosIds
-            .assignAll(ImagePickerUtil.selectedScreenshotPhotosIds);
-        selectedFileCount.value =
-            ImagePickerUtil.selectedScreenshotPhotosIds.length;
+        final ScreenShotsController controller =
+            Get.find<ScreenShotsController>();
+        listAssetEntity.assignAll(controller.getAllPhotos());
+        selectedPhotosIds.assignAll(controller.selectedPhotosIds);
+        selectedFileCount.value = selectedPhotosIds.length;
         break;
       case PhotosType.similarPhotos:
-        for (var group in ImagePickerUtil.similarPhotos) {
-          photoGroups.addAll(group);
-        }
-        selectedPhotosIds.assignAll(ImagePickerUtil.selectedSimilarPhotosIds);
-        selectedFileCount.value =
-            ImagePickerUtil.selectedSimilarPhotosIds.length;
+        final SimilarPhotoController controller =
+            Get.find<SimilarPhotoController>();
+        listAssetEntity.assignAll(controller.getAllPhotos());
+        selectedPhotosIds.assignAll(controller.selectedPhotosIds);
+        selectedFileCount.value = selectedPhotosIds.length;
         break;
       case PhotosType.locationPhotos:
-        for (var group in ImagePickerUtil.locationPhotos.values) {
-          photoGroups.addAll(group);
-        }
-        selectedPhotosIds.assignAll(ImagePickerUtil.selectedLocationPhotosIds);
-        selectedFileCount.value =
-            ImagePickerUtil.selectedLocationPhotosIds.length;
+        final LocationsSinglePhotoController controller =
+            Get.find<LocationsSinglePhotoController>();
+        listAssetEntity.assignAll(controller.getAllPhotos());
+        selectedPhotosIds.assignAll(controller.selectedPhotosIds);
+        selectedFileCount.value = selectedPhotosIds.length;
         break;
       case PhotosType.blurryPhotos:
-        photoGroups.assignAll(ImagePickerUtil.blurryPhotos);
-        selectedPhotosIds.assignAll(ImagePickerUtil.selectedBlurryPhotosIds);
-        selectedFileCount.value =
-            ImagePickerUtil.selectedBlurryPhotosIds.length;
+        final ScreenShotsController controller =
+            Get.find<ScreenShotsController>();
+        listAssetEntity.assignAll(controller.getAllPhotos());
+        selectedPhotosIds.assignAll(controller.selectedPhotosIds);
+        selectedFileCount.value = selectedPhotosIds.length;
         break;
     }
+
     updateSelectedFilesSize();
   }
 
-  void restoreSelections() async {
-    photoGroups
+  //删除成功清除选中的图片
+  void cleanSelections() async {
+    listAssetEntity
         .removeWhere((element) => selectedPhotosIds.contains(element.id));
     selectedPhotosIds.clear();
-    if (photoGroups.isNotEmpty) {
+    if (listAssetEntity.isEmpty) {
+      return;
+    }
+
+    isSwiperEnd.value = false;
+
+    if (listAssetEntity.isNotEmpty) {
+      WidgetsBinding.instance.addPostFrameCallback((_) {
+        groupIndex.value = 0;
+        cardSwiperController.value.moveTo(0);
+      });
+    }
+    updateSelectedFilesSize();
+    selectedFileCount.value = selectedPhotosIds.length;
+  }
+
+  // 恢复状态
+  void restoreSelections() {
+    if (listAssetEntity.isEmpty) {
+      clickBack();
+      return;
+    }
+
+    isSwiperEnd.value = false;
+
+    if (listAssetEntity.isNotEmpty) {
       WidgetsBinding.instance.addPostFrameCallback((_) {
         groupIndex.value = 0;
         cardSwiperController.value.moveTo(0);
@@ -146,6 +176,13 @@ class PhotoPreviewController extends BaseController {
     selectedFilesSize.value = totalSize / 1024; // Convert to KB
   }
 
+  void updateSelections(Set<String> selectedIds) {
+    print('PhotoPreviewController updateSelections photosType $photosType selectedIds $selectedIds');
+    selectedPhotosIds.assignAll(selectedIds);
+
+    restoreSelections();
+  }
+
   void recoverSelectPhoto() {
     cardSwiperController.value.undo();
   }
@@ -156,7 +193,9 @@ class PhotoPreviewController extends BaseController {
 
   @override
   void onClose() {
+    print('PhotoPreviewController onClose');
     super.onClose();
+    isSwiperEnd.value = false;
 
     // 清理操作,释放资源
     cardSwiperController.value.dispose();
@@ -167,37 +206,34 @@ class PhotoPreviewController extends BaseController {
     Get.back();
   }
 
+
   // // 保存选择的图片ID列表
   void _saveSelectedPhotos(PhotosType type) {
     switch (type) {
       case PhotosType.peoplePhotos:
-        ImagePickerUtil.selectedPeoplePhotosIds.assignAll(selectedPhotosIds);
         PeoplePhotoController controller = Get.find<PeoplePhotoController>();
+        controller.updateSelections(selectedPhotosIds);
         controller.restoreSelections();
         break;
       case PhotosType.screenshots:
-        ImagePickerUtil.selectedScreenshotPhotosIds
-            .assignAll(selectedPhotosIds);
         ScreenShotsController controller = Get.find<ScreenShotsController>();
+        controller.updateSelections(selectedPhotosIds);
         controller.restoreSelections();
         break;
       case PhotosType.similarPhotos:
-        ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
         SimilarPhotoController controller = Get.find<SimilarPhotoController>();
-
+        controller.updateSelections(selectedPhotosIds);
         controller.restoreSelections();
         break;
       case PhotosType.locationPhotos:
-        ImagePickerUtil.selectedLocationPhotosIds.assignAll(selectedPhotosIds);
         LocationsSinglePhotoController controller =
             Get.find<LocationsSinglePhotoController>();
-
+        controller.updateSelections(selectedPhotosIds);
         controller.restoreSelections();
         break;
       case PhotosType.blurryPhotos:
-        ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
         ScreenShotsController controller = Get.find<ScreenShotsController>();
-
+        controller.updateSelections(selectedPhotosIds);
         controller.restoreSelections();
         break;
     }
@@ -222,17 +258,17 @@ class PhotoPreviewController extends BaseController {
     // 如果direction是left,
     if (direction == CardSwiperDirection.left) {
       //   先看看图片id是不是在selectedPhotosIds里面,如果在,不处理,如果不在,添加到selectedPhotosIds里面
-      if (!selectedPhotosIds.contains(photoGroups[previousIndex].id)) {
+      if (!selectedPhotosIds.contains(listAssetEntity[previousIndex].id)) {
         print(
-            'add photoGroups[groupIndex.value].id ${photoGroups[previousIndex].id}');
-        selectedPhotosIds.add(photoGroups[previousIndex].id);
+            'add photoGroups[groupIndex.value].id ${listAssetEntity[previousIndex].id}');
+        selectedPhotosIds.add(listAssetEntity[previousIndex].id);
       }
     } else if (direction == CardSwiperDirection.right) {
       //   先看看图片id是不是在selectedPhotosIds里面,如果在,在selectedPhotosIds移除,不处理,如果不在,不处理
-      if (selectedPhotosIds.contains(photoGroups[previousIndex].id)) {
+      if (selectedPhotosIds.contains(listAssetEntity[previousIndex].id)) {
         print(
-            'remove photoGroups[groupIndex.value].id ${photoGroups[previousIndex].id}');
-        selectedPhotosIds.remove(photoGroups[previousIndex].id);
+            'remove photoGroups[groupIndex.value].id ${listAssetEntity[previousIndex].id}');
+        selectedPhotosIds.remove(listAssetEntity[previousIndex].id);
       }
     }
     selectedFileCount.value = selectedPhotosIds.length;
@@ -252,9 +288,9 @@ class PhotoPreviewController extends BaseController {
     //   撤销之前左滑的操作
     if (direction == CardSwiperDirection.left) {
       print(
-          'photoGroups[groupIndex.value].id ${photoGroups[groupIndex.value].id}');
-      if (selectedPhotosIds.contains(photoGroups[groupIndex.value].id)) {
-        selectedPhotosIds.remove(photoGroups[groupIndex.value].id);
+          'photoGroups[groupIndex.value].id ${listAssetEntity[groupIndex.value].id}');
+      if (selectedPhotosIds.contains(listAssetEntity[groupIndex.value].id)) {
+        selectedPhotosIds.remove(listAssetEntity[groupIndex.value].id);
       }
     }
     selectedFileCount.value = selectedPhotosIds.length;
@@ -292,7 +328,7 @@ class PhotoPreviewController extends BaseController {
     }
     if (selectedPhotosIds.isNotEmpty) {
       // 获取要删除的资产
-      final assetsToDelete = photoGroups
+      final assetsToDelete = listAssetEntity
           .where(
             (asset) => selectedPhotosIds.contains(asset.id),
           )
@@ -335,12 +371,22 @@ class PhotoPreviewController extends BaseController {
             break;
         }
 
-        restoreSelections();
-  
+        cleanSelections();
       } else {
         // 删除失败
         ToastUtil.show("Delete failed");
       }
     }
   }
+
+  // 将selectedFilesSize转成String类型,然后单位转换,如果超过1MB,则转成MB,超过1GB,则转成GB,否则KB
+  String get selectedFilesSizeString {
+    if (selectedFilesSize.value > 1024) {
+      return "${(selectedFilesSize.value  / 1024).toStringAsFixed(2)}MB";
+    } else if (selectedFilesSize.value > 1024 *  1024) {
+      return "${(selectedFilesSize.value / 1024 /  1024).toStringAsFixed(2)}GB";
+    } else {
+      return "${(selectedFilesSize.value).toStringAsFixed(2)}KB";
+    }
+  }
 }

+ 9 - 9
lib/module/photo_preview/photo_preview_view.dart

@@ -49,7 +49,7 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
           child: Container(
             child: Obx(() {
               if (controller.isSwiperEnd.value ||
-                  controller.photoGroups.isEmpty) {
+                  controller.listAssetEntity.isEmpty) {
                 return onSwiperEndCard();
               } else {
                 return Column(
@@ -68,13 +68,13 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
                         isLoop: false,
                         backCardOffset: Offset(0.w, -20.h),
                         controller: controller.cardSwiperController.value,
-                        cardsCount: controller.photoGroups.length,
+                        cardsCount: controller.listAssetEntity.length,
                         onSwipe: controller.onSwipe,
                         onUndo: controller.onSwiperUndo,
                         numberOfCardsDisplayed:
-                            (controller.photoGroups.length == 1)
+                            (controller.listAssetEntity.length == 1)
                                 ? 1
-                                : (controller.photoGroups.length == 2)
+                                : (controller.listAssetEntity.length == 2)
                                     ? 2
                                     : 3,
                         onEnd: controller.onSwiperEnd,
@@ -82,7 +82,7 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
                             index,
                             horizontalOffsetPercentage,
                             verticalOffsetPercentage) {
-                          final assetEntity = controller.photoGroups[index];
+                          final assetEntity = controller.listAssetEntity[index];
                           return AssetEntityImage(
                             assetEntity,
                             width: 314.w,
@@ -103,7 +103,7 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
         ),
       )),
       Obx(() {
-        if (controller.isSwiperEnd.value || controller.photoGroups.isEmpty) {
+        if (controller.isSwiperEnd.value || controller.listAssetEntity.isEmpty) {
           return IgnorePointer(
             child: Assets.images.bgPreviewSwiperEndFirework.image(
               width: 360.w,
@@ -152,7 +152,7 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
                         ),
                       ),
                       Text(
-                        ' / ${controller.photoGroups.length}',
+                        ' / ${controller.listAssetEntity.length}',
                         textAlign: TextAlign.center,
                         style: TextStyle(
                           color: Colors.white.withValues(alpha: 0.6),
@@ -200,7 +200,7 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
           children: [
             Obx(() {
               return Text(
-                '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
+                '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSizeString} )',
                 textAlign: TextAlign.center,
                 style: TextStyle(
                   color: Colors.white.withValues(alpha: 0.9),
@@ -329,7 +329,7 @@ class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
           ),
         ),
         Spacer(flex: 5,),
-        controller.photoGroups.isEmpty ? SizedBox() : _bottomBarCard(),
+        controller.listAssetEntity.isEmpty ? SizedBox() : _bottomBarCard(),
       ],
     );
   }

+ 62 - 167
lib/module/photo_preview/photo_selected_preview_controller.dart

@@ -1,4 +1,5 @@
 import 'package:clean/base/base_controller.dart';
+import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/dialog/photo_delete_finish_dialog.dart';
 import 'package:clean/dialog/photo_deleting_dialog.dart';
@@ -11,228 +12,122 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
-class PhotoSelectedPreviewController extends BaseController {
+class PhotoSelectedPreviewController extends BasePhotoController {
   late PhotosType photosType;
 
-  final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
-  final RxDouble selectedFilesSize = 0.0.obs;
-  RxInt selectedFileCount = 0.obs;
-  RxList<AssetEntity> selectedPhotos = <AssetEntity>[].obs;
-  late final RxSet<String> selectedPhotosIds;
 
+  final RxBool isKeepAll = false.obs;
+  final RxList<AssetEntity> selectedPhotos = <AssetEntity>[].obs;
   PhotoPreviewController photoPreviewController =
       Get.find<PhotoPreviewController>();
 
-
-
-
-
   @override
-  onInit() {
-    super.onInit();
+  void onInit() {
     _getArgs();
-
-    loadPhotoSelectedPreview();
-
-
-
-
+    super.onInit();
   }
 
+  // 从参数中获取照片类型和选中的照片ID集合
   _getArgs() {
+    final parameters = Get.arguments;
     photosType = parameters?['photosType'];
-    selectedPhotosIds = parameters?['selectedIds'];
+    selectedPhotosIds.assignAll(parameters?['selectedIds'] ?? []);
   }
 
-  loadPhotoSelectedPreview() {
+  // 加载选中的照片预览
+  @override
+  void loadPhotos() {
     photoGroups.clear();
-    for (var assetsEntity in photoPreviewController.photoGroups) {
+    for (var assetsEntity in photoPreviewController.listAssetEntity) {
       if (selectedPhotosIds.contains(assetsEntity.id)) {
         selectedPhotos.add(assetsEntity);
       }
     }
+
     if (selectedPhotos.isNotEmpty) {
       photoGroups.add(PhotoGroup(
         isSelected: true,
         images: selectedPhotos,
       ));
     }
+  }
 
-    updateSelectedFilesSize();
+  void clickBack() {
+    print('PhotoSelectedPreviewController clickBack');
+    photoPreviewController.updateSelections(selectedPhotosIds);
 
-    selectedFileCount.value = selectedPhotosIds.length;
-  }
 
-  void restoreSelections() async {
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        if (selectedPhotosIds.contains(group.images[i].id)) {
-          group.selectedImages[i] = true;
-        } else {
-          group.selectedImages[i] = false;
-        }
-      }
-      group.isSelected.value =
-          group.selectedImages.every((selected) => selected);
-    }
-    updateSelectedFilesSize();
-    selectedFileCount.value = selectedPhotosIds.length;
+    Get.back();
   }
 
-  clickDelete() async {
-    print('clickDelete');
-    photoDeletingDialog();
+  @override
+  clickImage(List<AssetEntity> images, int imageIndex, PhotosType type) {
+    print("PhotoSelectedPreviewController clickImage");
+  }
 
-    switch (photosType) {
-      case PhotosType.peoplePhotos:
-        ImagePickerUtil.selectedPeoplePhotosIds.assignAll(selectedPhotosIds);
-        break;
-      case PhotosType.screenshots:
-        ImagePickerUtil.selectedScreenshotPhotosIds
-            .assignAll(selectedPhotosIds);
-        break;
-      case PhotosType.similarPhotos:
-        ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
-        break;
-      case PhotosType.locationPhotos:
-        ImagePickerUtil.selectedLocationPhotosIds.assignAll(selectedPhotosIds);
-        break;
-      case PhotosType.blurryPhotos:
-        ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
-        break;
+  @override
+  void clickDelete() async {
 
-    }
+    photoDeletingDialog();
     if (selectedPhotosIds.isNotEmpty) {
+      print("PhotoSelectedPreviewController clickDelete selectedPhotosIds $selectedPhotosIds");
       final assetsToDelete = photoGroups
           .expand((group) => group.images
-              .where((asset) => selectedPhotosIds.contains(asset.id)))
+          .where((asset) => selectedPhotosIds.contains(asset.id)))
           .toList();
 
       final List<String> result = await PhotoManager.editor.deleteWithIds(
         assetsToDelete.map((e) => e.id).toList(),
       );
 
-      //   比较result和selectedPhotosIds,如果result和selectedPhotosIds相等,说明删除成功,走下面的逻辑
-      // 如果不相等,说明有删除失败的,走else逻辑
       if (result.length == selectedPhotosIds.length) {
-        switch (photosType) {
-          case PhotosType.peoplePhotos:
-            ImagePickerUtil.updatePhotoGroupDate(
-                photosType, ImagePickerUtil.selectedPeoplePhotosIds);
-
-            break;
-          case PhotosType.screenshots:
-            ImagePickerUtil.updatePhotoGroupDate(
-                photosType, ImagePickerUtil.selectedScreenshotPhotosIds);
-
-            break;
-          case PhotosType.similarPhotos:
-            ImagePickerUtil.updatePhotoGroupDate(
-                photosType, ImagePickerUtil.selectedSimilarPhotosIds);
-
-            break;
-          case PhotosType.locationPhotos:
-            ImagePickerUtil.updatePhotoGroupDate(
-                photosType, ImagePickerUtil.selectedLocationPhotosIds);
-
-            break;
-          case PhotosType.blurryPhotos:
-            ImagePickerUtil.updatePhotoGroupDate(
-                photosType, ImagePickerUtil.selectedBlurryPhotosIds);
-
-            break;
-        }
 
-        photoGroups.removeWhere((element) => element.images
-            .any((image) => selectedPhotosIds.contains(image.id)));
-        photoGroups.removeWhere((element) => element.images.isEmpty);
-        selectedPhotosIds.clear();
+        isDeleteFinish = true;
 
-        restoreSelections();
+        for (var group in photoGroups) {
+          group.images
+              .removeWhere((element) => selectedPhotosIds.contains(element.id));
 
-        Future.delayed(Duration(seconds: 3), () {
-          SmartDialog.dismiss(tag: 'photoDeletingDialog');
-          photoDeleteFinishDialog();
-        });
+          // 更新 group 中的 selectedImages 状态
+          group.selectedImages.value = group.images.map((image) {
+            return selectedPhotosIds.contains(image.id);
+          }).toList();
 
+          // 更新 group.isSelected
+          group.isSelected.value = group.selectedImages.every((selected) => selected);
+        }
 
-      } else {
+        photoPreviewController.selectedPhotosIds.assignAll(selectedPhotosIds);
+        photoPreviewController.cleanSelections();
 
-        Future.delayed(Duration(seconds: 3), () {
-          SmartDialog.dismiss(tag: 'photoDeletingDialog');
-        });
+        ImagePickerUtil.updatePhotoGroupDate(
+            getPhotosType(), selectedPhotosIds);
+        selectedPhotosIds.clear();
+        ToastUtil.show("Delete success selectedPhotosIds ");
 
-        ToastUtil.show("Delete failed");
-      }
-    }
-  }
 
-  void toggleGroupSelection(List<AssetEntity> images) {
-    final group = getGroupByImages(images);
-    final newValue = !group.isSelected.value;
-    group.toggleSelectAll(newValue);
 
-    for (var image in group.images) {
-      _updateSelectedPhotosIds(image.id, newValue);
-    }
+        Future.delayed(Duration(seconds: 2), () {
 
-    updateSelectedFilesSize();
-    selectedFileCount.value = selectedPhotosIds.length;
-  }
+          SmartDialog.dismiss(tag: 'photoDeletingDialog');
+          photoDeleteFinishDialog();
+        });
 
-  Future<void> updateSelectedFilesSize() async {
-    double totalSize = 0;
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        if (group.selectedImages[i]) {
-          final file = await group.images[i].file;
-          if (file != null) {
-            totalSize += file.lengthSync();
-          }
-        }
+      } else {
+        ToastUtil.show("Delete failed");
+        isDeleteFinish = false;
       }
+    }else {
+      // ToastUtil.show("Please select the photo to delete");
+      isKeepAll.value = true;
     }
-    selectedFilesSize.value = totalSize / 1024; // Convert to KB
-    //  如果超过1MB转成MB
-    if (selectedFilesSize.value > 1024) {
-      selectedFilesSize.value = selectedFilesSize.value / 1024;
-    }
-    //   如果超过1GB转成GB
-    if (selectedFilesSize.value > 1024 * 1024) {
-      selectedFilesSize.value = selectedFilesSize.value / 1024 / 1024;
-    }
-  }
-
-  void clickImage(List<AssetEntity> images, int imageIndex) {
-    final group = getGroupByImages(images);
-    final image = group.images[imageIndex];
   }
-
-  void toggleImageSelection(List<AssetEntity> images, int imageIndex) {
-    final group = getGroupByImages(images);
-    final image = group.images[imageIndex];
-    final selected = !group.selectedImages[imageIndex];
-
-    group.selectedImages[imageIndex] = selected;
-    _updateSelectedPhotosIds(image.id, selected);
-
-    group.isSelected.value = group.selectedImages.every((selected) => selected);
-
-    updateSelectedFilesSize();
-    selectedFileCount.value = selectedPhotosIds.length;
-  }
-
-  PhotoGroup getGroupByImages(List<AssetEntity> images) {
-    final imageIds = images.map((img) => img.id).toSet();
-    return photoGroups.firstWhere(
-        (group) => group.images.every((image) => imageIds.contains(image.id)));
-  }
-
-  void _updateSelectedPhotosIds(String photoId, bool isSelected) {
-    if (isSelected) {
-      selectedPhotosIds.add(photoId);
-    } else {
-      selectedPhotosIds.remove(photoId);
-    }
+  @override
+  void onClose() {
+    // TODO: implement onClose
+    super.onClose();
+    isKeepAll.value = false;
   }
+  @override
+  PhotosType getPhotosType() => photosType;
 }

+ 84 - 64
lib/module/photo_preview/phtoto_selected_preview_view.dart

@@ -34,52 +34,63 @@ class PhotoSelectedPreviewPage
   @override
   Widget buildBody(BuildContext context) {
     return Stack(children: [
-      Container(
-        child: SafeArea(
-          child: Obx(() {
-            if (controller.photoGroups.isEmpty ||
-                controller.photoGroups[0].images.isEmpty) {
-              return _finishCleanCard();
+      PopScope(
+          canPop: false,
+          onPopInvokedWithResult: (didPop, result) {
+            if (didPop) {
+              return;
             }
-            return Column(
-              children: [
-                _titleCard(),
-                Flexible(
-                  child: Obx(() {
-                    return SizedBox(
-                      child: GridView.builder(
-                          padding: EdgeInsets.symmetric(horizontal: 16.w),
-                          scrollDirection: Axis.vertical,
-                          // 设置为垂直方向滚动
-                          physics: BouncingScrollPhysics(),
-                          gridDelegate:
-                              SliverGridDelegateWithFixedCrossAxisCount(
-                            crossAxisCount: 3, // 每行显示 2 个元素
-                            mainAxisSpacing: 8.w, // 垂直间距
-                            crossAxisSpacing: 8.h, // 水平间距
-                          ),
-                          itemCount: controller.photoGroups[0].images.length,
-                          itemBuilder: _buildPhotoItem(
-                              controller.photoGroups[0].images)),
-                    );
-                  }),
-                ),
-                Obx(() {
-                  if (controller.selectedPhotosIds.isNotEmpty) {
-                    return _bottomBarCard();
-                  } else {
-                    return SizedBox();
-                  }
-                }),
-                SizedBox(height: 8.h),
-              ],
-            );
-          }),
-        ),
-      ),
+            controller.clickBack();
+          },
+          child: Container(
+            child: SafeArea(
+              child: Obx(() {
+                if (controller.photoGroups.isEmpty ||
+                    controller.photoGroups[0].images.isEmpty) {
+                  return _noNoPicturesCard();
+                }else if (controller.isKeepAll.value) {
+                  return _finishCleanCard();
+                }
+                return Column(
+                  children: [
+                    _titleCard(),
+                    Flexible(
+                      child: Obx(() {
+                        return SizedBox(
+                          child: GridView.builder(
+                              padding: EdgeInsets.symmetric(horizontal: 16.w),
+                              scrollDirection: Axis.vertical,
+                              // 设置为垂直方向滚动
+                              physics: BouncingScrollPhysics(),
+                              gridDelegate:
+                                  SliverGridDelegateWithFixedCrossAxisCount(
+                                crossAxisCount: 3, // 每行显示 2 个元素
+                                mainAxisSpacing: 8.w, // 垂直间距
+                                crossAxisSpacing: 8.h, // 水平间距
+                              ),
+                              itemCount:
+                                  controller.photoGroups[0].images.length,
+                              itemBuilder: _buildPhotoItem(
+                                  controller.photoGroups[0].images)),
+                        );
+                      }),
+                    ),
+                    Obx(() {
+                      if (controller.photoGroups.isNotEmpty ||
+                          controller.photoGroups[0].images.isNotEmpty) {
+                        return _bottomBarCard();
+                      } else {
+                        return SizedBox();
+                      }
+                    }),
+                    SizedBox(height: 8.h),
+                  ],
+                );
+              }),
+            ),
+          )),
       Obx(() {
-        if (controller.photoGroups.isEmpty ||
-            controller.photoGroups[0].images.isEmpty) {
+        if (controller.isKeepAll.value) {
           return IgnorePointer(
             child: Assets.images.bgPhotoSelectedPreviewFinish.image(
               width: 360.w,
@@ -111,7 +122,7 @@ class PhotoSelectedPreviewPage
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
               children: [
                 GestureDetector(
-                  onTap: () => Get.back(),
+                  onTap: () => controller.clickBack(),
                   child: Assets.images.iconBackArrow.image(
                     width: 28.w,
                     height: 28.h,
@@ -171,15 +182,27 @@ class PhotoSelectedPreviewPage
               ),
               SizedBox(width: 5.w),
               Obx(() {
-                return Text(
-                  'delete ${controller.selectedFilesSize.value.toStringAsFixed(1)} KB',
-                  textAlign: TextAlign.center,
-                  style: TextStyle(
-                    color: Colors.white,
-                    fontSize: 16.sp,
-                    fontWeight: FontWeight.w500,
-                  ),
-                );
+                if (controller.selectedPhotosIds.isNotEmpty) {
+                  return Text(
+                    'delete ${controller.selectedFilesSizeString}',
+                    textAlign: TextAlign.center,
+                    style: TextStyle(
+                      color: Colors.white,
+                      fontSize: 16.sp,
+                      fontWeight: FontWeight.w500,
+                    ),
+                  );
+                } else {
+                  return Text(
+                    'Keep All',
+                    textAlign: TextAlign.center,
+                    style: TextStyle(
+                      color: Colors.white,
+                      fontSize: 16.sp,
+                      fontWeight: FontWeight.w500,
+                    ),
+                  );
+                }
               }),
             ],
           ),
@@ -193,7 +216,8 @@ class PhotoSelectedPreviewPage
             controller.getGroupByImages(controller.photoGroups[0].images);
 
         return GestureDetector(
-          onTap: () => controller.clickImage(images, index),
+          onTap: () =>
+              controller.clickImage(images, index, controller.photosType),
           child: Obx(() {
             var isSelected = group.selectedImages[index];
             return Stack(
@@ -321,16 +345,12 @@ class PhotoSelectedPreviewPage
           // ),
 
           SizedBox(
-
               child: Lottie.asset(
-                Assets.anim.animPhotoSelectedPreviewFireworks,
-
-                width: 158.w,
-                height: 158.w,
-
-                repeat: false,
-
-              )),
+            Assets.anim.animPhotoSelectedPreviewFireworks,
+            width: 158.w,
+            height: 158.w,
+            repeat: false,
+          )),
 
           Spacer(
             flex: 5,

+ 23 - 155
lib/module/screenshots_blurry/screenshots_controller.dart

@@ -1,4 +1,5 @@
 import 'package:clean/base/base_controller.dart';
+import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
@@ -7,135 +8,36 @@ import 'package:clean/utils/toast_util.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
-class ScreenShotsController extends BaseController {
+class ScreenShotsController extends BasePhotoController {
   late String titleName;
-  final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
-  final RxDouble selectedFilesSize = 0.0.obs;
-  RxInt selectedFileCount = 0.obs;
-  final RxSet<String> selectedPhotosIds = <String>{}.obs;
 
-  Future<void> updateSelectedFilesSize() async {
-    double totalSize = 0;
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        if (group.selectedImages[i]) {
-          final file = await group.images[i].file;
-          if (file != null) {
-            totalSize += file.lengthSync();
-          }
-        }
-      }
-    }
-    selectedFilesSize.value = totalSize / 1024; // Convert to KB
-  }
-
-
-  void toggleImageSelection(List<AssetEntity> images, int imageIndex) {
-    final group = getGroupByImages(images);
-    final image = group.images[imageIndex];
-    final selected = !group.selectedImages[imageIndex];
-
-    group.selectedImages[imageIndex] = selected;
-    _updateSelectedScreenshotsPhotosIds(image.id, selected);
-
-    group.isSelected.value = group.selectedImages.every((selected) => selected);
-
-    updateSelectedFilesSize();
-    selectedFileCount.value = selectedPhotosIds.length;
+  @override
+  void onInit() {
+    print("ScreenShotsController onInit");
+    _getArgs();
+    super.onInit();
   }
 
-  void clickImage(List<AssetEntity> images, int imageIndex) {
-    final group = getGroupByImages(images);
-    final image = group.images[imageIndex];
+  void _getArgs() {
 
 
-    if (titleName == "Screenshots") {
-      ImagePickerUtil.selectedScreenshotPhotosIds.assignAll(selectedPhotosIds);
-      PhotoPreviewPage.start(PhotosType.screenshots, image.id);
-    } else if (titleName == "Blurry") {
-      ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
-      PhotoPreviewPage.start(PhotosType.blurryPhotos, image.id);
+    print("ScreenShotsController _getArgs");
+    final args = Get.arguments;
+    if (args != null) {
+      titleName = args["titleName"];
     }
-
-  }
-
-
-  void toggleGroupSelection(List<AssetEntity> images) {
-    final group = getGroupByImages(images);
-    final newValue = !group.isSelected.value;
-    group.toggleSelectAll(newValue);
-
-    for (var image in group.images) {
-      _updateSelectedScreenshotsPhotosIds(image.id, newValue);
+    if (titleName.isEmpty) {
+      ToastUtil.show("titleName is empty");
+      Get.back();
     }
 
-    updateSelectedFilesSize();
-    selectedFileCount.value = selectedPhotosIds.length;
-  }
-  //
-  // // 通过标题获取照片组
-  // PhotoGroup _getGroupByTitle(String groupTitle) {
-  //   return photoGroups.firstWhere((g) => g.title == groupTitle);
-  // }
-
-  // // 通过photoGroup的images来获取图片组
-
-  PhotoGroup getGroupByImages(List<AssetEntity> images) {
-    final imageIds = images.map((img) => img.id).toSet();
-    return photoGroups.firstWhere((group) =>
-        group.images.every((image) => imageIds.contains(image.id))
-    );
   }
-  void _updateSelectedScreenshotsPhotosIds(String photoId, bool isSelected) {
-    if (isSelected) {
-      selectedPhotosIds.add(photoId);
-    } else {
-      selectedPhotosIds.remove(photoId);
-    }
-  }
-
-  void restoreSelections() {
-    if (titleName == "Screenshots") {
-      selectedPhotosIds.assignAll(ImagePickerUtil.selectedScreenshotPhotosIds);
-
-    } else if (titleName == "Blurry") {
-      selectedPhotosIds.assignAll(ImagePickerUtil.selectedBlurryPhotosIds);
-    }
 
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        if (selectedPhotosIds.contains(group.images[i].id)) {
-          group.selectedImages[i] = true;
-        }else {
-          group.selectedImages[i] = false;
-        }
-      }
-      group.isSelected.value =
-          group.selectedImages.every((selected) => selected);
-    }
-    updateSelectedFilesSize();
-    selectedFileCount.value = selectedPhotosIds.length;
-  }
 
   @override
-  void onInit() async {
-    // TODO: implement onInit
-    super.onInit();
-    _getArgs();
-    loadScreenshots();
-    restoreSelections();
-  }
-
-  void _getArgs() {
-    titleName = parameters?['titleName'];
-  }
-
-  void loadScreenshots() {
-    // 清空现有数据
+  void loadPhotos() {
     photoGroups.clear();
 
-    // 将 ImagePickerUtil 中的相似照片转换为 PhotoGroup
-
     if (titleName == "Screenshots") {
       final photoGroup = ImagePickerUtil.screenshotPhotos;
       if (photoGroup.isNotEmpty) {
@@ -146,7 +48,6 @@ class ScreenShotsController extends BaseController {
       }
       selectedPhotosIds.assignAll(ImagePickerUtil.selectedScreenshotPhotosIds);
     } else if (titleName == "Blurry") {
-
       final photoGroup = ImagePickerUtil.blurryPhotos;
       if (photoGroup.isNotEmpty) {
         photoGroups.add(PhotoGroup(
@@ -158,45 +59,12 @@ class ScreenShotsController extends BaseController {
     }
   }
 
-  @override
-  void onClose() {
-    // TODO: implement onClose
-    super.onClose();
-    if (titleName == "Screenshots") {
-      ImagePickerUtil.selectedScreenshotPhotosIds.assignAll(selectedPhotosIds);
-    } else if (titleName == "Blurry") {
-      ImagePickerUtil.selectedBlurryPhotosIds.assignAll(selectedPhotosIds);
-    }
+  clickBack() {
+    print("ScreenShotsController titleName $titleName clickBack ");
+    updateSelections(selectedPhotosIds);
+    Get.back();
   }
 
-  clickDelete() async {
-    print('clickDelete');
-
-
-    if (selectedPhotosIds.isNotEmpty) {
-
-      final assetsToDelete = photoGroups.expand((group) =>
-          group.images.where((asset) => selectedPhotosIds.contains(asset.id))
-      ).toList();
-
-      final List<String> result = await PhotoManager.editor.deleteWithIds(
-        assetsToDelete.map((e) => e.id).toList(),
-      );
-      print('PhotoPreviewController result $result');
-
-      if (result.length == selectedPhotosIds.length) {
-
-
-        if (titleName == "Screenshots") {
-          ImagePickerUtil.updatePhotoGroupDate(PhotosType.screenshots, selectedPhotosIds);
-        } else if (titleName == "Blurry") {
-          ImagePickerUtil.updatePhotoGroupDate(PhotosType.blurryPhotos, selectedPhotosIds);
-        }
-        ToastUtil.show("Delete success");
-      } else {
-        // 删除失败
-        ToastUtil.show("Delete failed");
-      }
-    }
-  }
-}
+  @override
+  PhotosType getPhotosType() => titleName == "Screenshots" ? PhotosType.screenshots : PhotosType.blurryPhotos;
+}

+ 109 - 93
lib/module/screenshots_blurry/screenshots_view.dart

@@ -29,56 +29,68 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
   @override
   Widget buildBody(BuildContext context) {
     return Stack(children: [
-      Container(
+        PopScope(canPop: false,
+        onPopInvokedWithResult: (didPop, result) {
+          if (didPop) {
+            return;
+          }
+          controller.clickBack();
+        },
+        child:
+        Container(
         child: SafeArea(
-          child: Obx(() {
-            if (controller.photoGroups.isEmpty ||
-                controller.photoGroups[0].images.isEmpty) {
-              return _noNoPicturesCard();
+        child: Obx(()
+    {
+      if (controller.photoGroups.isEmpty ||
+          controller.photoGroups[0].images.isEmpty) {
+        return _noNoPicturesCard();
+      }
+      return Column(
+        children: [
+          _titleCard(),
+          Flexible(
+            child: Obx(() {
+              return SizedBox(
+                child: GridView.builder(
+                    padding: EdgeInsets.symmetric(horizontal: 16.w),
+                    scrollDirection: Axis.vertical,
+                    // 设置为垂直方向滚动
+                    physics: BouncingScrollPhysics(),
+                    gridDelegate:
+                    SliverGridDelegateWithFixedCrossAxisCount(
+                      crossAxisCount: 3, // 每行显示 2 个元素
+                      mainAxisSpacing: 8.w, // 垂直间距
+                      crossAxisSpacing: 8.h, // 水平间距
+                    ),
+                    itemCount: controller.photoGroups[0].images.length,
+                    itemBuilder: _buildPhotoItem(
+                        controller.photoGroups[0].images)),
+              );
+            }),
+          ),
+          Obx(() {
+            if (controller.selectedPhotosIds.isNotEmpty) {
+              return _bottomBarCard();
+            } else {
+              return SizedBox();
             }
-            return Column(
-              children: [
-                _titleCard(),
-                Flexible(
-                  child: Obx(() {
-                    return SizedBox(
-                      child: GridView.builder(
-                          padding: EdgeInsets.symmetric(horizontal: 16.w),
-                          scrollDirection: Axis.vertical,
-                          // 设置为垂直方向滚动
-                          physics: BouncingScrollPhysics(),
-                          gridDelegate:
-                              SliverGridDelegateWithFixedCrossAxisCount(
-                            crossAxisCount: 3, // 每行显示 2 个元素
-                            mainAxisSpacing: 8.w, // 垂直间距
-                            crossAxisSpacing: 8.h, // 水平间距
-                          ),
-                          itemCount: controller.photoGroups[0].images.length,
-                          itemBuilder: _buildPhotoItem(
-                              controller.photoGroups[0].images)),
-                    );
-                  }),
-                ),
-                Obx(() {
-                  if (controller.selectedPhotosIds.isNotEmpty) {
-                    return _bottomBarCard();
-                  } else {
-                    return SizedBox();
-                  }
-                }),
-                SizedBox(height: 8.h),
-              ],
-            );
           }),
-        ),
-      ),
-      IgnorePointer(
-        child: Assets.images.bgHome.image(
-          width: 360.w,
-          height: 234.h,
-        ),
-      ),
-    ]);
+          SizedBox(height: 8.h),
+        ],
+      );
+    }),
+    ),
+    ),),
+    IgnorePointer(
+    child: Assets.images.bgHome.image(
+    width: 360.w,
+    height: 234.h,
+    )
+    ,
+    )
+    ,
+    ]
+    );
   }
 
   Widget _titleCard() {
@@ -93,7 +105,7 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
               mainAxisAlignment: MainAxisAlignment.spaceBetween,
               children: [
                 GestureDetector(
-                  onTap: () => Get.back(),
+                  onTap: controller.clickBack,
                   child: Assets.images.iconBackArrow.image(
                     width: 28.w,
                     height: 28.h,
@@ -101,46 +113,48 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
                 ),
                 // 如果photoGroup数据为空,不显示全选按钮
                 controller.photoGroups.isEmpty ||
-                        controller.photoGroups[0].images.isEmpty
+                    controller.photoGroups[0].images.isEmpty
                     ? Container()
                     : GestureDetector(
-                        onTap: () => controller.toggleGroupSelection(
-                            controller.photoGroups[0].images),
-                        child: Obx(() => Text(
-                              controller
-                                      .getGroupByImages(
-                                          controller.photoGroups[0].images)
-                                      .isSelected
-                                      .value
-                                  ? 'Deselect All'
-                                  : 'Select All',
-                              style: TextStyle(
-                                color: Colors.white.withValues(alpha: 0.7),
-                                fontSize: 14.sp,
-                                fontWeight: FontWeight.w400,
-                              ),
-                            )),
-                      ),
+                  onTap: () =>
+                      controller.toggleGroupSelection(
+                          controller.photoGroups[0].images),
+                  child: Obx(() =>
+                      Text(
+                        controller
+                            .getGroupByImages(
+                            controller.photoGroups[0].images)
+                            .isSelected
+                            .value
+                            ? 'Deselect All'
+                            : 'Select All',
+                        style: TextStyle(
+                          color: Colors.white.withValues(alpha: 0.7),
+                          fontSize: 14.sp,
+                          fontWeight: FontWeight.w400,
+                        ),
+                      )),
+                ),
               ],
             );
           }),
           controller.photoGroups.isEmpty ||
-                  controller.photoGroups[0].images.isEmpty
+              controller.photoGroups[0].images.isEmpty
               ? Container()
               : Column(
-                  children: [
-                    SizedBox(height: 12.h),
-                    Text(
-                      controller.titleName,
-                      style: TextStyle(
-                        color: Colors.white,
-                        fontSize: 24.sp,
-                        fontWeight: FontWeight.w700,
-                      ),
-                    ),
-                    SizedBox(height: 20.h),
-                  ],
+            children: [
+              SizedBox(height: 12.h),
+              Text(
+                controller.titleName,
+                style: TextStyle(
+                  color: Colors.white,
+                  fontSize: 24.sp,
+                  fontWeight: FontWeight.w700,
                 ),
+              ),
+              SizedBox(height: 20.h),
+            ],
+          ),
         ],
       ),
     );
@@ -171,7 +185,8 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
               SizedBox(width: 5.w),
               Obx(() {
                 return Text(
-                  '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
+                  '${controller.selectedFileCount
+                      .value} files selected (${controller.selectedFilesSizeString})',
                   textAlign: TextAlign.center,
                   style: TextStyle(
                     color: Colors.white,
@@ -186,13 +201,14 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
   }
 
   Widget Function(BuildContext, int) _buildPhotoItem(
-          List<AssetEntity> images) =>
-      (context, index) {
+      List<AssetEntity> images) =>
+          (context, index) {
         final group =
-            controller.getGroupByImages(controller.photoGroups[0].images);
+        controller.getGroupByImages(controller.photoGroups[0].images);
 
         return GestureDetector(
-          onTap: () => controller.clickImage(images, index),
+          onTap: () =>
+              controller.clickImage(images, index, controller.getPhotosType()),
           child: Obx(() {
             var isSelected = group.selectedImages[index];
             return Stack(
@@ -224,16 +240,16 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
                       child: Container(
                         child: isSelected
                             ? Center(
-                                child: Assets.images.iconSelected.image(
-                                  width: 20.w,
-                                  height: 20.h,
-                                ),
-                              )
+                          child: Assets.images.iconSelected.image(
+                            width: 20.w,
+                            height: 20.h,
+                          ),
+                        )
                             : Center(
-                                child: Assets.images.iconUnselected.image(
-                                width: 20.w,
-                                height: 20.h,
-                              )),
+                            child: Assets.images.iconUnselected.image(
+                              width: 20.w,
+                              height: 20.h,
+                            )),
                       )),
                 ),
               ],

+ 60 - 119
lib/module/similar_photo/similar_photo_controller.dart

@@ -1,6 +1,7 @@
 import 'dart:io';
 
 import 'package:clean/base/base_controller.dart';
+import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
@@ -10,94 +11,10 @@ import 'package:get/get.dart';
 
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
-class SimilarPhotoController extends BaseController {
-  final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
-  final RxDouble selectedFilesSize = 0.0.obs;
-  RxInt selectedFileCount = 0.obs;
-
-  Future<void> getSelectedFilesSize() async {
-    double totalSize = 0;
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        if (group.selectedImages[i]) {
-          final file = await group.images[i].file;
-          if (file != null) {
-            totalSize += file.lengthSync();
-          }
-        }
-      }
-    }
-    selectedFilesSize.value = totalSize / 1024; // Convert to KB
-  }
-
-  void toggleImageSelection(List<AssetEntity> groupTitle, int imageIndex) {
-    final group = _getGroupByImages(groupTitle);
-    final image = group.images[imageIndex];
-    final selected = !group.selectedImages[imageIndex];
-
-    group.selectedImages[imageIndex] = selected;
-    _updateSelectedSimilarPhotosIds(image.id, selected);
-
-    group.isSelected.value = group.selectedImages.every((selected) => selected);
-
-    selectedFileCount.value = ImagePickerUtil.selectedSimilarPhotosIds.length;
-    getSelectedFilesSize();
-  }
-
-  void clickImage(List<AssetEntity> images, int imageIndex) {
-    final group = _getGroupByImages(images);
-    final image = group.images[imageIndex];
-    PhotoPreviewPage.start(PhotosType.similarPhotos, image.id);
-  }
-
-  void toggleGroupSelection(List<AssetEntity> imagesList) {
-    final group = _getGroupByImages(imagesList);
-    final newValue = !group.isSelected.value;
-    group.toggleSelectAll(newValue);
-
-    for (var image in group.images) {
-      _updateSelectedSimilarPhotosIds(image.id, newValue);
-    }
-    selectedFileCount.value = ImagePickerUtil.selectedSimilarPhotosIds.length;
-    getSelectedFilesSize();
-  }
-
-  PhotoGroup _getGroupByImages(List<AssetEntity> images) {
-    return photoGroups.firstWhere((g) => g.images == images);
-  }
-
-  void _updateSelectedSimilarPhotosIds(String photoId, bool isSelected) {
-    if (isSelected) {
-      ImagePickerUtil.selectedSimilarPhotosIds.add(photoId);
-    } else {
-      ImagePickerUtil.selectedSimilarPhotosIds.remove(photoId);
-    }
-  }
-
-  void restoreSelections() async {
-    final selectedIds = ImagePickerUtil.selectedSimilarPhotosIds.toSet();
-    for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        group.selectedImages[i] = selectedIds.contains(group.images[i].id);
-      }
-      group.isSelected.value =
-          group.selectedImages.every((selected) => selected);
-    }
-    await getSelectedFilesSize();
-    selectedFileCount.value = selectedIds.length;
-  }
-
+class SimilarPhotoController extends BasePhotoController {
   @override
-  void onInit() {
-    super.onInit();
-    loadSimilarPhotos();
-    restoreSelections();
-  }
-
-  void loadSimilarPhotos() {
-    // 清空现有数据
+  void loadPhotos() {
     photoGroups.clear();
-
     photoGroups.addAll(
       ImagePickerUtil.similarPhotos.where((group) => group.isNotEmpty).map(
         (group) {
@@ -108,57 +25,81 @@ class SimilarPhotoController extends BaseController {
         },
       ),
     );
-    // 每组第一张图片不选中,其余选中
     for (var group in photoGroups) {
       for (int i = 0; i < group.images.length; i++) {
         group.selectedImages[i] = i == 0 ? false : true;
-
-        _updateSelectedSimilarPhotosIds(group.images[i].id, i != 0);
+        updateSelectedPhotosIds(group.images[i].id, i != 0);
       }
     }
-
-    selectedFileCount.value = ImagePickerUtil.selectedSimilarPhotosIds.length;
-    getSelectedFilesSize();
+    ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
   }
 
-  clickDelete() async {
-    print('clickDelete');
 
-    if (ImagePickerUtil.selectedSimilarPhotosIds.isNotEmpty) {
-      final assetsToDelete = photoGroups
-          .expand((group) => group.images.where((asset) =>
-              ImagePickerUtil.selectedSimilarPhotosIds.contains(asset.id)))
-          .toList();
 
+  // 点击删除单组选中的图片
+  void clickSingleGroupDelete(List<AssetEntity> images) async {
+    // 获取指定组
+    final group = getGroupByImages(images);
+
+    // 获取该组中所有选中的图片
+    final selectedImages = group.images
+        .where((image) => group.selectedImages[group.images.indexOf(image)])
+        .toList();
+
+    if (selectedImages.isEmpty) {
+      ToastUtil.show('Please select the photo to delete');
+      return;
+    }
+
+    try {
+      // 执行删除操作
       final List<String> result = await PhotoManager.editor.deleteWithIds(
-        assetsToDelete.map((e) => e.id).toList(),
+        selectedImages.map((e) => e.id).toList(),
       );
-      print('PhotoPreviewController result $result');
 
-      if (result.length == ImagePickerUtil.selectedSimilarPhotosIds.length) {
-        for (var group in photoGroups) {
-          group.images.removeWhere((element) =>
-              ImagePickerUtil.selectedSimilarPhotosIds.contains(element.id));
+      // 检查删除成功的图片数量
+      if (result.length == selectedImages.length) {
+        // 先删除该组的图片,再更新selectedImages和selectedPhotosIds
+        List<AssetEntity> imagesToRemove = [];
+        List<int> indexesToRemove = [];
+
+        for (var image in selectedImages) {
+          // 找到图片在该组中的索引
+          int index = group.images.indexOf(image);
+          imagesToRemove.add(image);
+          indexesToRemove.add(index);
+        }
+
+        // 从后往前删除,避免删除后索引错位
+        for (int i = indexesToRemove.length - 1; i >= 0; i--) {
+          int index = indexesToRemove[i];
+          group.images.removeAt(index);
+          group.selectedImages.removeAt(index);
         }
-        ImagePickerUtil.updatePhotoGroupDate(
-            PhotosType.similarPhotos, ImagePickerUtil.selectedSimilarPhotosIds);
+
+        // 如果当前组为空,则删除该组
+        if (group.images.isEmpty) {
+          photoGroups.remove(group);
+        }
+
+        // 更新选中的图片ID
+        for (var image in imagesToRemove) {
+          updateSelectedPhotosIds(image.id, false);
+        }
+
+
+
         ToastUtil.show("Delete success");
       } else {
-        // 删除失败
         ToastUtil.show("Delete failed");
       }
+    } catch (e) {
+      // 异常处理
+      ToastUtil.show("Error occurred during deletion: $e");
     }
   }
 
-  // 修改视图构建方法,使用 AssetEntity 而不是文件路径
-  AssetEntity? getAssetById(String id) {
-    for (var group in ImagePickerUtil.similarPhotos) {
-      for (var asset in group) {
-        if (asset.id == id) {
-          return asset;
-        }
-      }
-    }
-    return null;
-  }
+
+  @override
+  PhotosType getPhotosType() => PhotosType.similarPhotos;
 }

+ 6 - 5
lib/module/similar_photo/similar_photo_view.dart

@@ -1,6 +1,7 @@
 import 'dart:io';
 import 'dart:math';
 import 'package:clean/base/base_page.dart';
+import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/similar_photo/similar_photo_controller.dart';
 import 'package:clean/resource/assets.gen.dart';
 import 'package:clean/router/app_pages.dart';
@@ -122,7 +123,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
         children: [
           Obx(() {
             return Text(
-              '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
+              '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSizeString})',
               textAlign: TextAlign.center,
               style: TextStyle(
                 color: Colors.white.withValues(alpha: 0.9),
@@ -228,7 +229,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                 // 第一张大图
                 if (imageCount > 0)
                   GestureDetector(
-                    onTap: () => controller.clickImage(imagesList, 0),
+                    onTap: () => controller.clickImage(imagesList, 0, PhotosType.similarPhotos),
                     child: SizedBox(
                       width: 148.w,
                       height: 148.h,
@@ -339,13 +340,13 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                             final realIndex = gridIndex * 4 + index + 1;
                             return GestureDetector(
                               onTap: () =>
-                                  controller.clickImage(imagesList, realIndex),
+                                  controller.clickImage(imagesList, realIndex, PhotosType.similarPhotos),
                               child: Obx(() {
                                 final group = controller.photoGroups
                                     .firstWhere((g) => g.images == imagesList);
                                 return Container(
                                   decoration: ShapeDecoration(
-                                    color: Colors.white.withOpacity(0.12),
+                                    color: Colors.white.withValues(alpha: 0.12),
                                     shape: RoundedRectangleBorder(
                                       borderRadius: BorderRadius.circular(8.r),
                                     ),
@@ -407,7 +408,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
             ),
           ),
           GestureDetector(
-            onTap: () => controller.clickDelete(),
+            onTap: () => controller.clickSingleGroupDelete(imagesList),
             child: Container(
               width: 162.w,
               height: 38.h,