Преглед изворни кода

[feat]1.升级flutter版本,
2.去掉PhotoGroup的selectedImages
3.尝试接入photo_classifier插件
4.修改图片保存插件,改成image_gallery_saver_plus

云天逵 пре 1 година
родитељ
комит
38e5e68b61
30 измењених фајлова са 1152 додато и 1316 уклоњено
  1. 5 5
      android/app/build.gradle
  2. 1 1
      android/gradle/wrapper/gradle-wrapper.properties
  3. 1 1
      android/settings.gradle
  4. 18 37
      lib/base/base_photo_controller.dart
  5. 140 0
      lib/base/base_photos_controller.dart
  6. 5 0
      lib/data/repositories/user_repository.dart
  7. 3 2
      lib/dialog/wallpaper_detail_dialog.dart
  8. 194 521
      lib/handler/photo_scan_handler.dart
  9. 0 1
      lib/module/home/home_controller.dart
  10. 107 41
      lib/module/image_picker/image_picker_util.dart
  11. 1 1
      lib/module/locations_photo/locations_photo_controller.dart
  12. 20 0
      lib/module/locations_photo/locations_photo_state.dart
  13. 11 16
      lib/module/locations_photo/locations_photo_view.dart
  14. 5 43
      lib/module/locations_photo/locations_single_photo_controller.dart
  15. 15 16
      lib/module/locations_photo/locations_single_photo_view.dart
  16. 14 21
      lib/module/people_photo/people_photo_controller.dart
  17. 22 0
      lib/module/people_photo/people_photo_state.dart
  18. 42 42
      lib/module/people_photo/people_photo_view.dart
  19. 15 15
      lib/module/people_photo/photo_group.dart
  20. 38 40
      lib/module/photo_preview/photo_preview_controller.dart
  21. 20 19
      lib/module/photo_preview/photo_selected_preview_controller.dart
  22. 1 1
      lib/module/photo_preview/phtoto_selected_preview_view.dart
  23. 32 0
      lib/module/screenshots_blurry/screenshots_blurry_state.dart
  24. 12 36
      lib/module/screenshots_blurry/screenshots_controller.dart
  25. 17 26
      lib/module/screenshots_blurry/screenshots_view.dart
  26. 6 5
      lib/module/similar_photo/similar_photo_controller.dart
  27. 23 35
      lib/module/similar_photo/similar_photo_view.dart
  28. 0 1
      lib/module/splash/intro/intro_view.dart
  29. 374 386
      pubspec.lock
  30. 10 4
      pubspec.yaml

+ 5 - 5
android/app/build.gradle

@@ -8,15 +8,15 @@ plugins {
 android {
 android {
     namespace = "com.example.clean.clean"
     namespace = "com.example.clean.clean"
     compileSdk = flutter.compileSdkVersion
     compileSdk = flutter.compileSdkVersion
-    ndkVersion = flutter.ndkVersion
+    ndkVersion = "27.0.12077973"
 
 
     compileOptions {
     compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_1_8
-        targetCompatibility = JavaVersion.VERSION_1_8
+        sourceCompatibility = JavaVersion.VERSION_11
+        targetCompatibility = JavaVersion.VERSION_11
     }
     }
 
 
     kotlinOptions {
     kotlinOptions {
-        jvmTarget = JavaVersion.VERSION_1_8
+        jvmTarget = JavaVersion.VERSION_11
     }
     }
 
 
     defaultConfig {
     defaultConfig {
@@ -24,7 +24,7 @@ android {
         applicationId = "com.cleanpro.tools"
         applicationId = "com.cleanpro.tools"
         // You can update the following values to match your application needs.
         // You can update the following values to match your application needs.
         // For more information, see: https://flutter.dev/to/review-gradle-config.
         // For more information, see: https://flutter.dev/to/review-gradle-config.
-        minSdk = flutter.minSdkVersion
+        minSdk = 23
         targetSdk = flutter.targetSdkVersion
         targetSdk = flutter.targetSdkVersion
         versionCode = flutter.versionCode
         versionCode = flutter.versionCode
         versionName = flutter.versionName
         versionName = flutter.versionName

+ 1 - 1
android/gradle/wrapper/gradle-wrapper.properties

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip

+ 1 - 1
android/settings.gradle

@@ -18,7 +18,7 @@ pluginManagement {
 
 
 plugins {
 plugins {
     id "dev.flutter.flutter-plugin-loader" version "1.0.0"
     id "dev.flutter.flutter-plugin-loader" version "1.0.0"
-    id "com.android.application" version "8.1.0" apply false
+    id("com.android.application") version "8.7.0" apply false
     id "org.jetbrains.kotlin.android" version "1.8.22" apply false
     id "org.jetbrains.kotlin.android" version "1.8.22" apply false
 }
 }
 
 

+ 18 - 37
lib/base/base_photo_controller.dart

@@ -54,45 +54,18 @@ abstract class BasePhotoController extends BaseController {
         });
         });
   }
   }
 
 
+
   // 切换图片选中状态
   // 切换图片选中状态
   Future<void> toggleImageSelection(
   Future<void> toggleImageSelection(
       List<AssetEntity> groupTitle, int imageIndex) async {
       List<AssetEntity> groupTitle, int imageIndex) async {
     debugPrint("BasePhotoController toggleImageSelection");
     debugPrint("BasePhotoController toggleImageSelection");
     final group = getGroupByImages(groupTitle);
     final group = getGroupByImages(groupTitle);
     final image = group.images[imageIndex];
     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);
+    group.toggleSelectImage(image.id);
 
 
+    updateSelectedPhotosIds(image.id, group.selectedPhotosIds.contains(image.id));
     selectedFileCount.value = selectedPhotosIds.length;
     selectedFileCount.value = selectedPhotosIds.length;
-
-    // 更新文件大小
-    // if (selected) {
-    //   // 如果选中,增加文件大小
-    //   if (FileSizeCalculatorUtil.fileSizeCache.containsKey(image.id)) {
-    //     selectedFilesSize.value +=
-    //         FileSizeCalculatorUtil.fileSizeCache[image.id]!;
-    //   } else {
-    //     final file = await image.file;
-    //     if (file != null) {
-    //       selectedFilesSize.value += (await file.length()) / 1024; // 转换为KB
-    //     }
-    //   }
-    // } else {
-    //   // 如果取消选中,减少文件大小
-    //   if (FileSizeCalculatorUtil.fileSizeCache.containsKey(image.id)) {
-    //     selectedFilesSize.value -=
-    //         FileSizeCalculatorUtil.fileSizeCache[image.id]!;
-    //   } else {
-    //     final file = await image.file;
-    //     if (file != null) {
-    //       selectedFilesSize.value -= (await file.length()) / 1024; // 转换为KB
-    //     }
-    //   }
-    // }
+    group.isSelected.value = group.selectedPhotosIds.length == group.images.length;
 
 
     updateSelectedFilesSize();
     updateSelectedFilesSize();
 
 
@@ -138,14 +111,22 @@ abstract class BasePhotoController extends BaseController {
   void restoreSelections() async {
   void restoreSelections() async {
     final selectedIds = selectedPhotosIds.toSet();
     final selectedIds = selectedPhotosIds.toSet();
     for (var group in photoGroups) {
     for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        group.selectedImages[i] = selectedIds.contains(group.images[i].id);
+      group.selectedPhotosIds.clear();
+
+      for (var image in group.images) {
+        if (selectedIds.contains(image.id)) {
+          group.selectedPhotosIds.add(image.id);
+        }
       }
       }
-      group.isSelected.value =
-          group.selectedImages.every((selected) => selected);
+
+      // 更新 isSelected,只有所有图片都被选中时才设为 true
+      group.isSelected.value = group.selectedPhotosIds.length == group.images.length;
     }
     }
-    selectedFileCount.value = selectedIds.length;
-    if (selectedIds.isEmpty) {
+
+    // 更新全局选中的文件数量
+    selectedFileCount.value = selectedPhotosIds.length;
+
+    if (selectedPhotosIds.isEmpty) {
       selectedFilesSize.value = 0;
       selectedFilesSize.value = 0;
       return;
       return;
     }
     }

+ 140 - 0
lib/base/base_photos_controller.dart

@@ -0,0 +1,140 @@
+import 'package:clean/base/base_controller.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:wechat_assets_picker/wechat_assets_picker.dart';
+
+import '../../dialog/photo_delete_finish_dialog.dart';
+import '../../dialog/photo_deleting_dialog.dart';
+import '../../utils/file_size_calculator_util.dart';
+import '../../utils/toast_util.dart';
+import '../data/repositories/user_repository.dart';
+import '../module/calendar/preview/calendar_preview_view.dart';
+import '../module/image_picker/image_picker_util.dart';
+import '../module/people_photo/photo_group.dart';
+import '../module/store/store_view.dart';
+
+// 单个组
+abstract class BasePhotosController extends BaseController {
+
+
+  final Rx<PhotoGroup> photoGroup = PhotoGroup(isSelected: false, images: []).obs;
+
+  @override
+  void onInit() {
+    super.onInit();
+  }
+
+  void clickBack() {
+    print('BasePhotosController $runtimeType clickBack');
+    Get.back();
+  }
+
+  // 切换图片组选中状态
+  void toggleGroupSelection() {
+    photoGroup.value.toggleSelectAll(!photoGroup.value.isSelected.value);
+    updateSelectedFilesSize();
+  }
+
+  // 删除选中的图片
+  Future<void> clickDelete() async {
+    debugPrint('BasePhotosController $runtimeType clickDelete');
+    if (!userRepository.isVip()) {
+      StorePage.start();
+      return;
+    }
+    if (photoGroup.value.selectedPhotosIds.isNotEmpty) {
+      photoDeletingDialog();
+      final List<String> result = await PhotoManager.editor.deleteWithIds(
+        photoGroup.value.selectedPhotosIds.toList(),
+      );
+
+      if (result.length == photoGroup.value.selectedPhotosIds.length) {
+        debugPrint(
+            "BasePhotosController $runtimeType delete ${photoGroup.value.selectedPhotosIds}");
+        ImagePickerUtil.updatePhotoData(photoGroup.value.selectedPhotosIds);
+        cleanSelections();
+        ToastUtil.show('Delete success');
+        Future.delayed(Duration(seconds: 2), () {
+          SmartDialog.dismiss(tag: 'photoDeletingDialog');
+          photoDeleteFinishDialog();
+        });
+      } else {
+        SmartDialog.dismiss(tag: 'photoDeletingDialog');
+        ToastUtil.show("Delete failed");
+      }
+    }
+  }
+
+// 删除成功后清理选中图片
+  void cleanSelections() {
+    photoGroup.update((group) {
+      group?.images.removeWhere(
+          (element) => group.selectedPhotosIds.contains(element.id));
+      group?.selectedPhotosIds.clear();
+    });
+
+    if (photoGroup.value.images.isNotEmpty) {
+      updateSelectedFilesSize();
+    }
+  }
+
+// 更新选中图片的总大小
+  Future<void> updateSelectedFilesSize() async {
+    if (photoGroup.value.selectedCount == 0) {
+      photoGroup.value.selectedTotalSize.value = 0;
+      return;
+    }
+
+    FileSizeCalculatorUtil.calculateTotalSize(
+      assetIds: photoGroup.value.selectedPhotosIds,
+      updateValue: (double totalSize) {
+        photoGroup.value.selectedTotalSize.value = totalSize;
+      },
+    );
+  }
+
+// 更新选中的照片 ID
+  void updateSelectedPhotosIds(String photoId, bool isSelected) {
+    if (isSelected) {
+      if (!photoGroup.value.selectedPhotosIds.contains(photoId)) {
+        photoGroup.value.selectedPhotosIds.add(photoId);
+      }
+    } else {
+      photoGroup.value.selectedPhotosIds.remove(photoId);
+    }
+    photoGroup.value.isSelected.value =
+        photoGroup.value.selectedPhotosIds.length ==
+            photoGroup.value.images.length;
+  }
+
+// 点击图片
+  void clickImage(int imageIndex) {
+    print("BasePhotosController $runtimeType clickImage");
+    CalendarPreviewPage.start(
+      photoGroup: photoGroup.value,
+      currentImageId: photoGroup.value.images[imageIndex].id,
+    );
+  }
+
+// 选中/取消选中图片
+  Future<void> toggleImageSelection(int imageIndex) async {
+    print("BasePhotosController $runtimeType toggleImageSelection");
+    final image = photoGroup.value.images[imageIndex];
+    photoGroup.value.toggleSelectImage(image.id);
+    updateSelectedFilesSize();
+  }
+
+// 计算已选图片大小(格式化)
+  String get selectedFilesSizeString {
+    final double sizeInKB = photoGroup.value.selectedTotalSize.value;
+
+    if (sizeInKB >= 1024 * 1024) {
+      return "${(sizeInKB / (1024 * 1024)).toStringAsFixed(2)}GB";
+    } else if (sizeInKB >= 1024) {
+      return "${(sizeInKB / 1024).toStringAsFixed(2)}MB";
+    } else {
+      return "${sizeInKB.toStringAsFixed(2)}KB";
+    }
+  }
+}

+ 5 - 0
lib/data/repositories/user_repository.dart

@@ -1,3 +1,5 @@
+import 'dart:io';
+
 import 'package:get/get_rx/src/rx_types/rx_types.dart';
 import 'package:get/get_rx/src/rx_types/rx_types.dart';
 
 
 import '../../base/base_request.dart';
 import '../../base/base_request.dart';
@@ -25,6 +27,9 @@ class UserRepository {
   // 检测是否为会员
   // 检测是否为会员
   bool isVip() {
   bool isVip() {
 
 
+   if (Platform.isAndroid) {
+      return true;
+    }
     // 检查用户信息和会员信息是否存在
     // 检查用户信息和会员信息是否存在
     if (userInfo.value?.memberInfo == null) {
     if (userInfo.value?.memberInfo == null) {
       return false;
       return false;

+ 3 - 2
lib/dialog/wallpaper_detail_dialog.dart

@@ -8,7 +8,8 @@ import 'package:flutter/Material.dart';
 import 'package:flutter_cache_manager/flutter_cache_manager.dart';
 import 'package:flutter_cache_manager/flutter_cache_manager.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
-import 'package:image_gallery_saver/image_gallery_saver.dart';
+import 'package:image_gallery_saver_plus/image_gallery_saver_plus.dart';
+
 
 
 import '../data/consts/event_report_id.dart';
 import '../data/consts/event_report_id.dart';
 
 
@@ -109,7 +110,7 @@ void downloadWallpaper(String? imageUrl) async {
     ToastUtil.show("Downloading...");
     ToastUtil.show("Downloading...");
     final saveFile = await DefaultCacheManager().getSingleFile(imageUrl ?? "");
     final saveFile = await DefaultCacheManager().getSingleFile(imageUrl ?? "");
 
 
-    await ImageGallerySaver.saveFile(saveFile.path);
+    await ImageGallerySaverPlus.saveFile(saveFile.path);
     ToastUtil.show("Download success");
     ToastUtil.show("Download success");
   } catch (e) {
   } catch (e) {
     ToastUtil.show("Download failed");
     ToastUtil.show("Download failed");

+ 194 - 521
lib/handler/photo_scan_handler.dart

@@ -3,17 +3,33 @@ import 'dart:io';
 
 
 import 'package:classify_photo/classify_photo.dart';
 import 'package:classify_photo/classify_photo.dart';
 import 'package:clean/widget/multi_segment_circle_indicator.dart';
 import 'package:clean/widget/multi_segment_circle_indicator.dart';
-import 'package:disk_space/disk_space.dart';
+
+
 import 'package:flutter/Material.dart';
 import 'package:flutter/Material.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
 import 'package:permission_handler/permission_handler.dart';
 import 'package:permission_handler/permission_handler.dart';
+import 'package:photo_classifier/models.dart';
+import 'package:photo_classifier/photo_classifier.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
 import '../../module/image_picker/image_picker_util.dart';
 import '../../module/image_picker/image_picker_util.dart';
-import '../utils/toast_util.dart';
+
 
 
 class PhotoScanHandler {
 class PhotoScanHandler {
-  static final _photoClassify = ClassifyPhoto();
+
+
+  final classifier = PhotoClassifier();
+  var hasPermission = false.obs;
+  var isClassifying = false.obs;
+  var errorMessage = ''.obs;
+
+  static var progress = Rxn<ClassificationProgress>();
+  static var similarResult = <ClassifiedImageGroup>[].obs;
+  static var peopleResult = <ClassifiedImage>[].obs;
+  static var screenshotResult = <ClassifiedImage>[].obs;
+  static var blurryResult = <ClassifiedImage>[].obs;
+
+  StreamSubscription<ClassificationEvent?>? _subscription;
 
 
   static RxBool isSimilarScanned = false.obs;
   static RxBool isSimilarScanned = false.obs;
   static RxBool isPeopleScanned = false.obs;
   static RxBool isPeopleScanned = false.obs;
@@ -35,11 +51,6 @@ class PhotoScanHandler {
   // 相似照片
   // 相似照片
   static RxList<AssetEntity> similarPhotos = <AssetEntity>[].obs;
   static RxList<AssetEntity> similarPhotos = <AssetEntity>[].obs;
 
 
-  // 添加一个标志来跟踪当前扫描状态
-  bool _isScanningCancelled = false;
-
-  List<StreamSubscription> _scanningTasks = [];
-
   static Rx<double> totalSpace = 0.0.obs;
   static Rx<double> totalSpace = 0.0.obs;
   static Rx<double> usedSpace = 0.0.obs;
   static Rx<double> usedSpace = 0.0.obs;
   static Rx<double> photoSpace = 0.0.obs;
   static Rx<double> photoSpace = 0.0.obs;
@@ -51,157 +62,30 @@ class PhotoScanHandler {
   static Rx<String> freeSpaceStr = "0.0 GB".obs;
   static Rx<String> freeSpaceStr = "0.0 GB".obs;
 
 
   // 计算已用存储百分比
   // 计算已用存储百分比
-  static double get usedSpacePercentage => (usedSpace.value / totalSpace.value) * 100;
+  static double get usedSpacePercentage =>
+      (usedSpace.value / totalSpace.value) * 100;
 
 
   // 计算照片占用存储百分比
   // 计算照片占用存储百分比
   static double get photoSpacePercentage =>
   static double get photoSpacePercentage =>
       (photoSpace.value / totalSpace.value) * 100;
       (photoSpace.value / totalSpace.value) * 100;
 
 
   // 计算可用存储百分比
   // 计算可用存储百分比
-  static double get freeSpacePercentage => (freeSpace.value / totalSpace.value) * 100;
+  static double get freeSpacePercentage =>
+      (freeSpace.value / totalSpace.value) * 100;
 
 
   static List<PieData> get pieDataList => [
   static List<PieData> get pieDataList => [
-    PieData("PhotoSpace", photoSpacePercentage, Colors.blue),
-    PieData("OtherUsed", usedSpacePercentage - photoSpacePercentage,
-        Colors.red),
-    PieData("totalSpace", totalSpace.value, Colors.grey.withOpacity(0.1)),
-  ];
+        PieData("PhotoSpace", photoSpacePercentage, Colors.blue),
+        PieData("OtherUsed", usedSpacePercentage - photoSpacePercentage,
+            Colors.red),
+        PieData("totalSpace", totalSpace.value, Colors.grey.withOpacity(0.1)),
+      ];
 
 
   // 存储是否扫描完成
   // 存储是否扫描完成
   static RxBool isStorageScanned = false.obs;
   static RxBool isStorageScanned = false.obs;
 
 
-  // 监听照片库变化
-  void _listenToPhotoLibraryChanges() {
-    PhotoManager.addChangeCallback((change) {
-      print("照片库发生变化: $change");
-
-      // 取消当前正在进行的扫描
-      _cancelCurrentScan();
-
-      // 延迟一小段时间后重新开始扫描
-      Future.delayed(Duration(milliseconds: 500), () {
-        _restartScan();
-      });
-    });
-
-    // 开始监听
-    PhotoManager.startChangeNotify();
-  }
-
-  // 取消当前扫描
-  void _cancelCurrentScan() {
-    _isScanningCancelled = true;
-
-    // 取消所有正在进行的异步任务
-    for (var subscription in _scanningTasks) {
-      subscription.cancel();
-    }
-    _scanningTasks.clear();
-
-    print("已取消当前扫描任务");
-  }
-
-// 重新开始扫描
-  void _restartScan() {
-    _isScanningCancelled = false;
-
-    isSimilarScanned.value = false;
-    isPeopleScanned.value = false;
-    isBlurryScanned.value = false;
-    isScreenShotScanned.value = false;
-
-    // 清除之前的结果
-    similarPhotos.clear();
-    peoplePhotos.clear();
-    locationPhoto.value = null;
-    screenshotPhoto.value = null;
-    blurryPhoto.value = null;
-
-
-    print("开始重新扫描照片");
-
-    // 重新开始扫描流程
-    startScanningProcess();
-  }
-
-  // 开始扫描过程
-  Future<void> startScanningProcess() async {
-    // 确保在开始新扫描前取消标志被重置
-    _isScanningCancelled = false;
-
-    // 清空之前的任务
-    _scanningTasks.clear();
-
-    try {
-      // 按顺序执行扫描任务
-      print('开始顺序扫描照片');
-
-      // 1. 先扫描截图照片
-      if (!_isScanningCancelled) {
-        var screenTask = _handleScreenPhotosWithCancellation();
-        _scanningTasks.add(screenTask);
-        // 等待截图扫描完成
-        await Future.delayed(Duration(milliseconds: 500));
-      }
-
-      // 2. 再扫描模糊照片
-      if (!_isScanningCancelled) {
-        var blurryTask = _handleBlurryPhotosWithCancellation();
-        _scanningTasks.add(blurryTask);
-        // 等待模糊照片扫描完成
-        await Future.delayed(Duration(milliseconds: 500));
-      }
-
-      // 3. 然后扫描人物照片
-      if (!_isScanningCancelled) {
-        var peopleTask = _handlePeoplePhotosWithCancellation();
-        _scanningTasks.add(peopleTask);
-        // 等待人物照片扫描完成
-        await Future.delayed(Duration(milliseconds: 500));
-      }
-
-      // 4. 最后扫描相似照片
-      if (!_isScanningCancelled) {
-        var similarTask = _handleSimilarPhotosWithCancellation();
-        _scanningTasks.add(similarTask);
-      }
-
-      print('所有扫描任务已启动');
-    } catch (e) {
-      print('扫描过程中出错: $e');
-    }
-  }
 
 
   Future<void> getStorageInfo() async {
   Future<void> getStorageInfo() async {
 
 
-    if (Platform.isAndroid) {
-      // 延迟3秒
-      Future.delayed(const Duration(seconds: 3), () {
-        isStorageScanned.value = true;
-        totalSpace.value = 200.0;
-        usedSpace.value = 50.0;
-        photoSpace.value = 30.0;
-        freeSpace.value = 150.0;
-      });
-    }
-
-    final totalSpaceGB = (await DiskSpace.getTotalDiskSpace ?? 0) / 1000;
-    final freeSpaceGB = (await DiskSpace.getFreeDiskSpace ?? 0) / 1024;
-    final usedSpaceGB = ((await DiskSpace.getTotalDiskSpace ?? 0) - (await DiskSpace.getFreeDiskSpace ?? 0)) / 1024;
-
-    totalSpaceStr.value = ImagePickerUtil.formatFileSize(
-        (await DiskSpace.getTotalDiskSpace ?? 0).round(),
-        decimals: 1);
-    freeSpaceStr.value = ImagePickerUtil.formatFileSize(
-        (await DiskSpace.getFreeDiskSpace ?? 0).round(),
-        decimals: 1);
-    usedSpaceStr.value = ImagePickerUtil.formatFileSize(
-        ((await DiskSpace.getTotalDiskSpace ?? 0) - (await DiskSpace.getFreeDiskSpace ?? 0)).round(),
-        decimals: 1);
-
-    totalSpace.value = totalSpaceGB.round().toDouble();
-    freeSpace.value = freeSpaceGB;
-    usedSpace.value = usedSpaceGB;
 
 
     final classifyPhoto = ClassifyPhoto();
     final classifyPhoto = ClassifyPhoto();
 
 
@@ -244,420 +128,209 @@ class PhotoScanHandler {
 
 
   /// 执行所有的照片处理操作
   /// 执行所有的照片处理操作
   Future<void> handleAllPhotos() async {
   Future<void> handleAllPhotos() async {
-    // var request = Platform.isIOS
-    //     ? await Permission.photos.request()
-    //     : await Permission.storage.request();
-    //
-    // if (request.isGranted) {
-    //   PhotoManager.clearFileCache();
-    //   await handleScreenPhotos();
-    //   await handleBlurryPhotos();
-    //   await handlePeoplePhotos();
-    //   await handleSimilarPhotos();
-    //   if (Platform.isAndroid) {
-    //     await handleAndroidPhotos();
-    //   }
-    // } else if (request.isPermanentlyDenied) {
-    //   ToastUtil.show("Please enable the album permission");
-    //   openAppSettings();
-    // } else {
-    //   ToastUtil.show("Please enable the album permission");
-    //
-    //   isSimilarScanned.value = false;
-    //   isPeopleScanned.value = false;
-    //   isBlurryScanned.value = false;
-    //   isScreenShotScanned.value = false;
-  // }
-
-
-      var currentStatus = await Permission.photos.status;
-
-      if (currentStatus.isGranted) {
-        // 已有完全权限,直接扫描
-        PhotoManager.clearFileCache();
-        // _listenToPhotoLibraryChanges(); // 添加监听
-        await handleScreenPhotos();
-        await handleBlurryPhotos();
-        await handlePeoplePhotos();
-        await handleSimilarPhotos();
-      } else if (currentStatus.isLimited) {
-        // 已有有限权限,显示自定义弹窗
+    var currentStatus = await Permission.photos.status;
+    if (Platform.isAndroid) {
+      currentStatus = await Permission.storage.status;
+    }
+    if (currentStatus.isGranted) {
+      if (Platform.isAndroid) {
+        await handleAndroidPhotos();
+      }
+      // 已有完全权限,直接扫描
+      PhotoManager.clearFileCache();
+      startClassification();
+    } else if (currentStatus.isLimited) {
+      // 已有有限权限,显示自定义弹窗
+      PhotoManager.clearFileCache();
+      startClassification();
+
+    } else {
+      // 未授权,请求权限
+      var result = await Permission.photos.request();
+      if (Platform.isAndroid) {
+        result = await Permission.storage.request();
+      }
+      if (result.isGranted || result.isLimited) {
         PhotoManager.clearFileCache();
         PhotoManager.clearFileCache();
-        await handleScreenPhotos();
-        await handleBlurryPhotos();
-        await handlePeoplePhotos();
-        await handleSimilarPhotos();
-      } else {
-        // 未授权,请求权限
-        var result = await Permission.photos.request();
-        if (result.isGranted || result.isLimited) {
-          PhotoManager.clearFileCache();
-          getStorageInfo();
-          await handleScreenPhotos();
-          await handleBlurryPhotos();
-          await handlePeoplePhotos();
-          await handleSimilarPhotos();
-        } else {
-          isSimilarScanned.value = true;
-          isPeopleScanned.value = true;
-          isBlurryScanned.value = true;
-          isScreenShotScanned.value = true;
+        getStorageInfo();
+        startClassification();
+
+        if (Platform.isAndroid) {
+          await handleAndroidPhotos();
         }
         }
+      } else {
+        isSimilarScanned.value = true;
+        isPeopleScanned.value = true;
+        isBlurryScanned.value = true;
+        isScreenShotScanned.value = true;
       }
       }
+    }
   }
   }
 
 
-    // 可取消的截图照片扫描
-    StreamSubscription _handleScreenPhotosWithCancellation() {
-      var controller = StreamController<bool>();
 
 
-      Future<void> task() async {
-        if (_isScanningCancelled) {
-          controller.add(false);
-          return;
-        }
+  /// Android平台处理方式
+  Future<void> handleAndroidPhotos() async {
+    final List<AssetEntity> result = await ImagePickerUtil.loadAssets();
+    ImagePickerUtil.peoplePhotos.value = result ?? [];
+    ImagePickerUtil.locationPhotos['location'] = result ?? [];
+    ImagePickerUtil.screenshotPhotos.value = result ?? [];
+    ImagePickerUtil.similarPhotos.add(result ?? []);
+    ImagePickerUtil.blurryPhotos.value = result ?? [];
 
 
-        try {
-          print('开始获取截图照片');
-          final photoClassify = ClassifyPhoto();
-          final photos = await photoClassify.getScreenshots();
+    // result = await ImagePickerUtil.loadAssetsPaged(page: 1, pageSize: 9);
+    // ImagePickerUtil.similarPhotos.add(result ?? []);
+    // result = await ImagePickerUtil.loadAssetsPaged(page: 2, pageSize: 9);
+    // ImagePickerUtil.similarPhotos.add(result ?? []);
 
 
-          if (_isScanningCancelled) {
-            controller.add(false);
-            return;
-          }
+    print("handleAndroidPhotos $result");
+    print(
+        "ImagePickerUtil.peoplePhotos.value ${ImagePickerUtil.peoplePhotos.length}");
 
 
-          print('获取截图照片完成: ${photos?.length ?? 0} 组照片');
-          isScreenShotScanned.value = true;
+    isSimilarScanned.value = true;
+    isPeopleScanned.value = true;
+    isBlurryScanned.value = true;
+    isScreenShotScanned.value = true;
 
 
-          if (photos != null) {
-            await ImagePickerUtil.updatePhotos(photos);
-            if (ImagePickerUtil.screenshotPhotos.isNotEmpty) {
-              var asset = ImagePickerUtil.screenshotPhotos.first;
-              screenshotPhoto.value = asset;
-            }
+    similarPhotos.clear();
+    if (ImagePickerUtil.similarPhotos.isNotEmpty) {
+      for (var group in ImagePickerUtil.similarPhotos) {
+        print(
+            " ImagePickerUtil.similarPhotos ${ImagePickerUtil.similarPhotos.length}");
+        for (var asset in group) {
+          similarPhotos.add(asset);
+          if (similarPhotos.length == 4) {
+            break;
           }
           }
-
-          controller.add(true);
-        } catch (e) {
-          print('获取截图照片失败: $e');
-          controller.add(false);
         }
         }
       }
       }
-
-      task();
-
-      return controller.stream.listen((success) {
-        controller.close();
-      });
     }
     }
 
 
-// 可取消的模糊照片扫描
-    StreamSubscription _handleBlurryPhotosWithCancellation() {
-      var controller = StreamController<bool>();
-
-      Future<void> task() async {
-        if (_isScanningCancelled) {
-          controller.add(false);
-          return;
-        }
-
-        try {
-          print('开始获取模糊照片');
-          final photoClassify = ClassifyPhoto();
-          final photos = await photoClassify.getBlurryPhotos();
-
-          if (_isScanningCancelled) {
-            controller.add(false);
-            return;
-          }
-
-          print('获取模糊照片完成: ${photos?.length ?? 0} 组照片');
-          isBlurryScanned.value = true;
-
-          if (photos != null) {
-            await ImagePickerUtil.updatePhotos(photos);
-            if (ImagePickerUtil.blurryPhotos.isNotEmpty) {
-              var asset = ImagePickerUtil.blurryPhotos.first;
-              blurryPhoto.value = asset;
-            }
-          }
-
-          controller.add(true);
-        } catch (e) {
-          print('获取模糊照片失败: $e');
-          controller.add(false);
+    peoplePhotos.clear();
+    if (ImagePickerUtil.peoplePhotos.isNotEmpty) {
+      for (var personPhotos in ImagePickerUtil.peoplePhotos) {
+        peoplePhotos.add(personPhotos);
+        if (peoplePhotos.length == 2) {
+          break;
         }
         }
       }
       }
-
-      task();
-
-      return controller.stream.listen((success) {
-        controller.close();
-      });
     }
     }
 
 
-// 可取消的人物照片扫描
-    StreamSubscription _handlePeoplePhotosWithCancellation() {
-      var controller = StreamController<bool>();
-
-      Future<void> task() async {
-        if (_isScanningCancelled) {
-          controller.add(false);
-          return;
-        }
-
-        try {
-          print('开始获取人物照片');
-          final photoClassify = ClassifyPhoto();
-          final photos = await photoClassify.getPeoplePhotos();
-
-          if (_isScanningCancelled) {
-            controller.add(false);
-            return;
-          }
-
-          print('获取人物照片完成: ${photos?.length ?? 0} 组照片');
-          isPeopleScanned.value = true;
-
-          if (photos != null) {
-            await ImagePickerUtil.updatePhotos(photos);
+    if (ImagePickerUtil.blurryPhotos.isNotEmpty) {
+      var asset = ImagePickerUtil.blurryPhotos.first;
+      blurryPhoto.value = asset;
+    }
 
 
-            // 处理人物照片
-            peoplePhotos.clear();
-            if (ImagePickerUtil.peoplePhotos.isNotEmpty) {
-              for (var personPhotos in ImagePickerUtil.peoplePhotos) {
-                if (_isScanningCancelled) break;
+    if (ImagePickerUtil.screenshotPhotos.isNotEmpty) {
+      var asset = ImagePickerUtil.screenshotPhotos.first;
+      screenshotPhoto.value = asset;
+    }
+  }
 
 
-                peoplePhotos.add(personPhotos);
-                if (peoplePhotos.length == 2) {
-                  break;
-                }
-              }
+  Future<void> startClassification() async {
+    isClassifying.value = true;
+    errorMessage.value = '';
+    progress.value = null;
+    similarResult.clear();
+    peopleResult.clear();
+    screenshotResult.clear();
+    blurryResult.clear();
+    try {
+      await classifier.configureClassifier(
+        batchSize: 200,
+        maxConcurrentProcessing: 4,
+        similarityThreshold: 0.75,
+      );
+
+      _subscription = classifier.startClassificationStream().listen(
+        (event) async {
+          if (event == null) return;
+          progress.value = event.progress;
+          final result = event.result;
+          if (result != null) {
+            similarResult.assignAll(result.similarGroups ?? []);
+            for (var group in similarResult) {
+              await ImagePickerUtil.newUpdatePhotos("similar", group.images);
             }
             }
+            peopleResult.assignAll (result.peopleImages ?? []);
+            await ImagePickerUtil.newUpdatePhotos("people", peopleResult);
+            screenshotResult.addAll(result.screenshotImages ?? []);
+            await ImagePickerUtil.newUpdatePhotos(
+                "screenshot", screenshotResult);
+            blurryResult.assignAll(result.blurryImages ?? []);
+            await ImagePickerUtil.newUpdatePhotos("blurry", blurryResult);
           }
           }
-
-          controller.add(true);
-        } catch (e) {
-          print('获取人物照片失败: $e');
-          controller.add(false);
-        }
-      }
-
-      task();
-
-      return controller.stream.listen((success) {
-        controller.close();
-      });
-    }
-
-// 可取消的相似照片扫描
-    StreamSubscription _handleSimilarPhotosWithCancellation() {
-      var controller = StreamController<bool>();
-
-      Future<void> task() async {
-        if (_isScanningCancelled) {
-          controller.add(false);
-          return;
-        }
-
-        try {
-          print('开始获取相似照片');
-          final photoClassify = ClassifyPhoto();
-          final photos = await photoClassify.getSimilarPhotos();
-
-          if (_isScanningCancelled) {
-            controller.add(false);
-            return;
+          if (event.progress?.isCompleted == true) {
+            isClassifying.value = false;
+            _subscription?.cancel();
+            _subscription = null;
+            completeClassification();
           }
           }
-
-          print('获取相似照片完成: ${photos?.length ?? 0} 组照片');
-          isSimilarScanned.value = true;
-
-          if (photos != null) {
-            await ImagePickerUtil.updatePhotos(photos);
-
-            similarPhotos.clear();
-            if (ImagePickerUtil.similarPhotos.isNotEmpty) {
-              for (var group in ImagePickerUtil.similarPhotos) {
-                if (_isScanningCancelled) break;
-
-                for (var asset in group) {
-                  similarPhotos.add(asset);
-                  if (similarPhotos.length == 4) {
-                    break;
-                  }
-                }
-
-                if (similarPhotos.length == 4) {
-                  break;
-                }
-              }
-            }
+        },
+        onError: (error) {
+          errorMessage.value = '分类过程中出错: $error';
+          isClassifying.value = false;
+        },
+        onDone: () {
+          if (progress.value?.isCompleted != true) {
+            errorMessage.value = '分类过程意外结束';
+            isClassifying.value = false;
           }
           }
+        },
+      );
+    } catch (e) {
+      errorMessage.value = '启动分类失败: $e';
+      isClassifying.value = false;
+    }
+  }
 
 
-          controller.add(true);
-        } catch (e) {
-          print('获取相似照片失败: $e');
-          controller.add(false);
-        }
-      }
-
-      task();
+  void cancelClassification() {
+    _subscription?.cancel();
+    _subscription = null;
+    isClassifying.value = false;
+    classifier.resetClassifier();
+  }
 
 
-      return controller.stream.listen((success) {
-        controller.close();
-      });
-    }
+  void resetAll() {
+    progress.value = null;
+    similarResult.clear();
+    peopleResult.clear();
+    screenshotResult.clear();
+    blurryResult.clear();
+    errorMessage.value = '';
+    isClassifying.value = false;
+  }
 
 
-    /// 截图照片
-    Future<bool> handleScreenPhotos() async {
-      try {
-        final photos = await _photoClassify.getScreenshots();
-        print('获取截图照片完成: ${photos?.length ?? 0} 组照片');
-        isScreenShotScanned.value = true;
-        if (photos != null) {
-          await ImagePickerUtil.updatePhotos(photos);
-          if (ImagePickerUtil.screenshotPhotos.isNotEmpty) {
-            var asset = ImagePickerUtil.screenshotPhotos.first;
-            screenshotPhoto.value = asset;
+  void completeClassification() {
+    if (ImagePickerUtil.similarPhotos.isNotEmpty) {
+      for (var group in ImagePickerUtil.similarPhotos) {
+        print(
+            " ImagePickerUtil.similarPhotos ${ImagePickerUtil.similarPhotos.length}");
+        for (var asset in group) {
+          similarPhotos.add(asset);
+          if (similarPhotos.length == 4) {
+            break;
           }
           }
         }
         }
-      } catch (e, stackTrace) {
-        print('获取截图失败: $e\n$stackTrace');
       }
       }
-      isScreenShotScanned.value = true;
-      return true;
     }
     }
-
-    /// 模糊照片
-    Future<bool> handleBlurryPhotos() async {
-      try {
-        final photos = await _photoClassify.getBlurryPhotos();
-        print('获取模糊照片完成: ${photos?.length ?? 0} 组照片');
-        isBlurryScanned.value = true;
-        if (photos != null) {
-          await ImagePickerUtil.updatePhotos(photos);
-          if (ImagePickerUtil.blurryPhotos.isNotEmpty) {
-            var asset = ImagePickerUtil.blurryPhotos.first;
-            blurryPhoto.value = asset;
-          }
-          return true;
+    if (ImagePickerUtil.peoplePhotos.isNotEmpty) {
+      for (var personPhotos in ImagePickerUtil.peoplePhotos) {
+        peoplePhotos.add(personPhotos);
+        if (peoplePhotos.length == 2) {
+          break;
         }
         }
-      } catch (e, stackTrace) {
-        print('获取模糊失败: $e\n$stackTrace');
       }
       }
-      isBlurryScanned.value = true;
-      return true;
     }
     }
-
-    /// 人物照片
-    Future<bool> handlePeoplePhotos() async {
-      try {
-        final photos = await _photoClassify.getPeoplePhotos();
-        print('获取人物照片完成: ${photos?.length ?? 0} 组照片');
-        isPeopleScanned.value = true;
-        if (photos != null) {
-          await ImagePickerUtil.updatePhotos(photos);
-          // 处理人物照片
-          peoplePhotos.clear();
-          if (ImagePickerUtil.peoplePhotos.isNotEmpty) {
-            for (var personPhotos in ImagePickerUtil.peoplePhotos) {
-              peoplePhotos.add(personPhotos);
-              if (peoplePhotos.length == 2) {
-                break;
-              }
-            }
-          }
-          return true;
-        }
-      } catch (e, stackTrace) {
-        print('获取人物失败: $e\n$stackTrace');
-      }
-      isPeopleScanned.value = true;
-      return true;
+    if (ImagePickerUtil.blurryPhotos.isNotEmpty) {
+      var asset = ImagePickerUtil.blurryPhotos.first;
+      blurryPhoto.value = asset;
     }
     }
 
 
-    /// 相似照片
-    Future<bool> handleSimilarPhotos() async {
-      try {
-        print('开始获取相似照片');
-        final photos = await _photoClassify.getSimilarPhotos();
-        print('获取相似照片完成: ${photos?.length ?? 0} 组照片');
-        isSimilarScanned.value = true;
-        if (photos != null) {
-          await ImagePickerUtil.updatePhotos(photos);
-          similarPhotos.clear();
-          if (ImagePickerUtil.similarPhotos.isNotEmpty) {
-            for (var group in ImagePickerUtil.similarPhotos) {
-              for (var asset in group) {
-                similarPhotos.add(asset);
-                if (similarPhotos.length == 4) {
-                  break;
-                }
-              }
-            }
-          }
-          return true;
-        }
-      } catch (e, stackTrace) {
-        print('获取相似失败: $e\n$stackTrace');
-      }
-      isSimilarScanned.value = true;
-      return true;
+    if (ImagePickerUtil.screenshotPhotos.isNotEmpty) {
+      var asset = ImagePickerUtil.screenshotPhotos.first;
+      screenshotPhoto.value = asset;
     }
     }
+  }
 
 
-    /// Android平台处理方式
-    Future<void> handleAndroidPhotos() async {
-      final List<AssetEntity> result = await ImagePickerUtil.loadAssets();
-      ImagePickerUtil.peoplePhotos.value = result ?? [];
-      ImagePickerUtil.locationPhotos['location'] = result ?? [];
-      ImagePickerUtil.screenshotPhotos.value = result ?? [];
-      ImagePickerUtil.similarPhotos.add(result ?? []);
-      ImagePickerUtil.blurryPhotos.value = result ?? [];
-
-      print("handleAndroidPhotos $result");
-      print(
-          "ImagePickerUtil.peoplePhotos.value ${ImagePickerUtil.peoplePhotos
-              .length}");
-
-      isSimilarScanned.value = true;
-      isPeopleScanned.value = true;
-      isBlurryScanned.value = true;
-      isScreenShotScanned.value = true;
-
-      similarPhotos.clear();
-      if (ImagePickerUtil.similarPhotos.isNotEmpty) {
-        for (var group in ImagePickerUtil.similarPhotos) {
-          print(
-              " ImagePickerUtil.similarPhotos ${ImagePickerUtil.similarPhotos
-                  .length}");
-          for (var asset in group) {
-            similarPhotos.add(asset);
-            if (similarPhotos.length == 4) {
-              break;
-            }
-          }
-        }
-      }
-
-      peoplePhotos.clear();
-      if (ImagePickerUtil.peoplePhotos.isNotEmpty) {
-        for (var personPhotos in ImagePickerUtil.peoplePhotos) {
-          peoplePhotos.add(personPhotos);
-          if (peoplePhotos.length == 2) {
-            break;
-          }
-        }
-      }
-
-      if (ImagePickerUtil.blurryPhotos.isNotEmpty) {
-        var asset = ImagePickerUtil.blurryPhotos.first;
-        blurryPhoto.value = asset;
-      }
 
 
-      if (ImagePickerUtil.screenshotPhotos.isNotEmpty) {
-        var asset = ImagePickerUtil.screenshotPhotos.first;
-        screenshotPhoto.value = asset;
-      }
-    }
-  }
+}

+ 0 - 1
lib/module/home/home_controller.dart

@@ -14,7 +14,6 @@ import 'package:clean/module/screenshots_blurry/screenshots_view.dart';
 import 'package:clean/module/similar_photo/similar_photo_view.dart';
 import 'package:clean/module/similar_photo/similar_photo_view.dart';
 import 'package:clean/router/app_pages.dart';
 import 'package:clean/router/app_pages.dart';
 import 'package:clean/utils/toast_util.dart';
 import 'package:clean/utils/toast_util.dart';
-import 'package:disk_space/disk_space.dart';
 import 'package:flutter/Material.dart';
 import 'package:flutter/Material.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';

+ 107 - 41
lib/module/image_picker/image_picker_util.dart

@@ -13,6 +13,7 @@ import 'package:clean/module/screenshots_blurry/screenshots_controller.dart';
 import 'package:clean/module/similar_photo/similar_photo_controller.dart';
 import 'package:clean/module/similar_photo/similar_photo_controller.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter/widgets.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
+import 'package:photo_classifier/models.dart';
 import 'package:photo_manager/photo_manager.dart';
 import 'package:photo_manager/photo_manager.dart';
 
 
 import '../../handler/photo_scan_handler.dart';
 import '../../handler/photo_scan_handler.dart';
@@ -73,67 +74,54 @@ class ImagePickerUtil {
     peoplePhotos.clear();
     peoplePhotos.clear();
   }
   }
 
 
-  static Future<void> updatePhotoGroupDate(
-      PhotosType photosType, Set<String> selectedPhotosIds1) async {
-    // 1. 统一移除相关的照片列表
-    debugPrint(
-        "updatePhotoGroupDate1 ScreenshotsController screenshotController $selectedPhotosIds1");
+
+
+  static Future<void> updatePhotoGroupDate(PhotosType photosType,Set<String> selectedPhotosIds1) async {
+    // // 1. 统一移除相关的照片列表
+    debugPrint("updatePhotoGroupDate1 ScreenshotsController screenshotController $selectedPhotosIds1");
     // 2. 移除控制器中的数据
     // 2. 移除控制器中的数据
     Set<String> selectedPhotosIds = Set.from(selectedPhotosIds1);
     Set<String> selectedPhotosIds = Set.from(selectedPhotosIds1);
     updatePhotoData(selectedPhotosIds);
     updatePhotoData(selectedPhotosIds);
-
-    debugPrint(
-        "updatePhotoGroupDate2 ScreenshotsController screenshotController $selectedPhotosIds");
+    //
+    debugPrint("updatePhotoGroupDate2 ScreenshotsController screenshotController $selectedPhotosIds");
     // 3. 根据photosType来处理不同的控制器和photoGroups
     // 3. 根据photosType来处理不同的控制器和photoGroups
     switch (photosType) {
     switch (photosType) {
       case PhotosType.screenshots:
       case PhotosType.screenshots:
-        ScreenShotsController screenshotController =
-            Get.find<ScreenShotsController>();
-        removeImagesAndEmptyGroups(screenshotController, selectedPhotosIds);
-        selectedScreenshotPhotosIds
-            .removeWhere((element) => selectedPhotosIds.contains(element));
-        screenshotController.restoreSelections();
+        // ScreenShotsController screenshotController = Get.find<ScreenShotsController>();
+        // removeImagesAndEmptyGroups(screenshotController, selectedPhotosIds);
+        // selectedScreenshotPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+        // screenshotController.restoreSelections();
         break;
         break;
 
 
       case PhotosType.similarPhotos:
       case PhotosType.similarPhotos:
-        SimilarPhotoController similarController =
-            Get.find<SimilarPhotoController>();
+        SimilarPhotoController similarController = Get.find<SimilarPhotoController>();
         removeImagesAndEmptyGroups(similarController, selectedPhotosIds);
         removeImagesAndEmptyGroups(similarController, selectedPhotosIds);
-        selectedSimilarPhotosIds
-            .removeWhere((element) => selectedPhotosIds.contains(element));
+        selectedSimilarPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
         similarController.restoreSelections();
         similarController.restoreSelections();
         break;
         break;
 
 
       case PhotosType.locationPhotos:
       case PhotosType.locationPhotos:
-        LocationsSinglePhotoController locationsSingleController =
-            Get.find<LocationsSinglePhotoController>();
-        LocationsPhotoController locationsPhotoController =
-            Get.find<LocationsPhotoController>();
-        removeImagesAndEmptyGroups(
-            locationsSingleController, selectedPhotosIds);
-        removeImagesAndEmptyGroups(locationsPhotoController, selectedPhotosIds);
-        selectedLocationPhotosIds
-            .removeWhere((element) => selectedPhotosIds.contains(element));
-        locationsSingleController.restoreSelections();
-        locationsPhotoController.restoreSelections();
+        // LocationsSinglePhotoController locationsSingleController = Get.find<LocationsSinglePhotoController>();
+        // LocationsPhotoController locationsPhotoController = Get.find<LocationsPhotoController>();
+        // removeImagesAndEmptyGroups(locationsSingleController, selectedPhotosIds);
+        // removeImagesAndEmptyGroups(locationsPhotoController, selectedPhotosIds);
+        // selectedLocationPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+        // locationsSingleController.restoreSelections();
+        // locationsPhotoController.restoreSelections();
         break;
         break;
 
 
       case PhotosType.peoplePhotos:
       case PhotosType.peoplePhotos:
-        PeoplePhotoController peoplePhotoController =
-            Get.find<PeoplePhotoController>();
-        removeImagesAndEmptyGroups(peoplePhotoController, selectedPhotosIds);
-        selectedPeoplePhotosIds
-            .removeWhere((element) => selectedPhotosIds.contains(element));
-        peoplePhotoController.restoreSelections();
+        // PeoplePhotoController peoplePhotoController = Get.find<PeoplePhotoController>();
+        // removeImagesAndEmptyGroups(peoplePhotoController, selectedPhotosIds);
+        // selectedPeoplePhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+        // peoplePhotoController.restoreSelections();
         break;
         break;
 
 
       case PhotosType.blurryPhotos:
       case PhotosType.blurryPhotos:
-        ScreenShotsController blurryController =
-            Get.find<ScreenShotsController>();
-        removeImagesAndEmptyGroups(blurryController, selectedPhotosIds);
-        selectedBlurryPhotosIds
-            .removeWhere((element) => selectedPhotosIds.contains(element));
-        blurryController.restoreSelections();
+        // ScreenShotsController blurryController = Get.find<ScreenShotsController>();
+        // removeImagesAndEmptyGroups(blurryController, selectedPhotosIds);
+        // selectedBlurryPhotosIds.removeWhere((element) => selectedPhotosIds.contains(element));
+        // blurryController.restoreSelections();
         break;
         break;
     }
     }
   }
   }
@@ -282,6 +270,39 @@ class ImagePickerUtil {
     }
     }
   }
   }
 
 
+  static Future<void> newUpdatePhotos( String type,
+      List<ClassifiedImage> photoGroups) async {
+
+      switch (type) {
+        case 'screenshots':
+          screenshotPhotos.clear();
+          screenshotPhotos.value = await _newConvertToAssetEntities(photoGroups);
+          screenshotsSize.value = photoGroups.fold(0, (sum, image) => sum + image.fileSize);
+          break;
+        case 'similar':
+          similarPhotos.add(await _newConvertToAssetEntities(photoGroups));
+          similarPhotosSize.value = photoGroups.fold(0, (sum, image) => sum + image.fileSize);
+          similarPhotoCount.value = photoGroups.length;
+          break;
+        // case 'location':
+        //   String location = group['name'] as String;
+        //   locationPhotos[location] = await _convertToAssetEntities(photos);
+        //   locationsSize.value = totalSize;
+          break;
+        case 'people':
+          peoplePhotos.clear();
+          peoplePhotos.value = await _newConvertToAssetEntities(photoGroups);
+          peopleSize.value = photoGroups.fold(0, (sum, image) => sum + image.fileSize);
+          break;
+        case 'blurry':
+          blurryPhotos.clear();
+          blurryPhotos.value = await _newConvertToAssetEntities(photoGroups);
+          blurrySize.value = photoGroups.fold(0, (sum, image) => sum + image.fileSize);
+          break;
+      }
+
+  }
+
   // 将原始照片数据转换为 AssetEntity 列表
   // 将原始照片数据转换为 AssetEntity 列表
   static Future<List<AssetEntity>> _convertToAssetEntities(
   static Future<List<AssetEntity>> _convertToAssetEntities(
       List<dynamic> photos) async {
       List<dynamic> photos) async {
@@ -295,6 +316,19 @@ class ImagePickerUtil {
     return entities;
     return entities;
   }
   }
 
 
+  // 新版将原始照片数据转换为AssetsEntity列表
+  static Future<List<AssetEntity>> _newConvertToAssetEntities(
+      List<ClassifiedImage> photos) async {
+    List<AssetEntity> entities = [];
+    for (var photo in photos) {
+      final entity = await AssetEntity.fromId(photo.assetsId);
+      if (entity != null) {
+        entities.add(entity);
+      }
+    }
+    return entities;
+  }
+
   //申请权限
   //申请权限
   static Future<bool> requestPermissionExtend() async {
   static Future<bool> requestPermissionExtend() async {
     final PermissionState ps = await PhotoManager.requestPermissionExtend(
     final PermissionState ps = await PhotoManager.requestPermissionExtend(
@@ -383,7 +417,39 @@ class ImagePickerUtil {
       return '${(sizeInGB / 1024).toStringAsFixed(1)} ';
       return '${(sizeInGB / 1024).toStringAsFixed(1)} ';
     }
     }
   }
   }
+  static Future<List<AssetEntity>> loadAssetsPaged({
+    int page = 0,
+    int pageSize = 9,
+    bool sortByDate = true,
+  }) async {
+    final PermissionState result = await PhotoManager.requestPermissionExtend();
+    if (!result.hasAccess) return [];
+
+    // 获取相册列表(这里只取第一个相册)
+    final List<AssetPathEntity> albums = await PhotoManager.getAssetPathList(
+      type: RequestType.common,
+      filterOption: FilterOptionGroup(
+        orders: [
+          OrderOption(
+            type: OrderOptionType.createDate,
+            asc: !sortByDate,
+          ),
+        ],
+      ),
+    );
+
+    if (albums.isEmpty) return [];
+
+    final AssetPathEntity album = albums.first;
 
 
+    // 分页加载当前页的照片
+    final List<AssetEntity> assets = await album.getAssetListPaged(
+      page: page,
+      size: pageSize,
+    );
+
+    return assets;
+  }
   // 加载图片资源
   // 加载图片资源
   static Future<List<AssetEntity>> loadAssets({bool sortByDate = true}) async {
   static Future<List<AssetEntity>> loadAssets({bool sortByDate = true}) async {
     final PermissionState result = await PhotoManager.requestPermissionExtend();
     final PermissionState result = await PhotoManager.requestPermissionExtend();

+ 1 - 1
lib/module/locations_photo/locations_photo_controller.dart

@@ -62,7 +62,7 @@ class LocationsPhotoController extends BaseController {
   void restoreSelections() {
   void restoreSelections() {
     for (var group in photoGroups) {
     for (var group in photoGroups) {
       for (int i = 0; i < group.images.length; i++) {
       for (int i = 0; i < group.images.length; i++) {
-        group.selectedImages[i] = ImagePickerUtil.selectedLocationPhotosIds.contains(group.images[i].id);
+        group.selectedPhotosIds.add(group.images[i].id);
       }
       }
     }
     }
   }
   }

+ 20 - 0
lib/module/locations_photo/locations_photo_state.dart

@@ -0,0 +1,20 @@
+import 'package:clean/module/people_photo/photo_group.dart';
+import 'package:get/get.dart';
+
+import '../image_picker/image_picker_util.dart';
+
+class LocationsPhotoState {
+
+  static final RxList<PhotoGroup> photoGroups = <PhotoGroup>[].obs;
+  static void removePhotosData(Set<String> selectedPhotosIds) {
+    photoGroups.removeWhere((album) {
+      album.images
+          .removeWhere((element) => selectedPhotosIds.contains(element.id));
+      album.selectedPhotosIds
+          .removeWhere((element) => selectedPhotosIds.contains(element));
+
+      // 如果images为空,删除该 album
+      return album.images.isEmpty;
+    });
+  }
+}

+ 11 - 16
lib/module/locations_photo/locations_photo_view.dart

@@ -4,12 +4,14 @@ import 'package:clean/base/base_page.dart';
 import 'package:clean/module/locations_photo/locations_photo_controller.dart';
 import 'package:clean/module/locations_photo/locations_photo_controller.dart';
 import 'package:clean/resource/assets.gen.dart';
 import 'package:clean/resource/assets.gen.dart';
 import 'package:clean/router/app_pages.dart';
 import 'package:clean/router/app_pages.dart';
-import 'package:clean/utils/styles.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:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
+import '../../utils/styles.dart';
+import '../people_photo/photo_group.dart';
+
 class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
 class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
   @override
   @override
   bool statusBarDarkFont() => false;
   bool statusBarDarkFont() => false;
@@ -54,11 +56,7 @@ class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
               children: [
               children: [
                 ...controller.photoGroups.map((group) => Column(
                 ...controller.photoGroups.map((group) => Column(
                       children: [
                       children: [
-                        _buildPhotoGroup(
-                          title: "photo: ${group.images.length}",
-                          location: group.location ?? '',
-                          imageCount: group.images.length,
-                        ),
+                        _buildPhotoGroup(photoGroup: group),
                         SizedBox(height: 15.h),
                         SizedBox(height: 15.h),
                       ],
                       ],
                     ))
                     ))
@@ -106,9 +104,7 @@ class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
   }
   }
 
 
   Widget _buildPhotoGroup({
   Widget _buildPhotoGroup({
-    required String location,
-    required String title,
-    required int imageCount,
+    required PhotoGroup photoGroup,
   }) {
   }) {
     return Container(
     return Container(
       margin: EdgeInsets.only(top: 14.h),
       margin: EdgeInsets.only(top: 14.h),
@@ -128,7 +124,7 @@ class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
             children: [
             children: [
               SizedBox(width: 16.w),
               SizedBox(width: 16.w),
               Text(
               Text(
-                title,
+                photoGroup.location ?? "",
                 textAlign: TextAlign.center,
                 textAlign: TextAlign.center,
                 style: TextStyle(
                 style: TextStyle(
                   color: Colors.white,
                   color: Colors.white,
@@ -140,12 +136,11 @@ class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
           ),
           ),
           SizedBox(
           SizedBox(
             child: GestureDetector(
             child: GestureDetector(
-              onTap: () => controller
-                  .clickPhotoGroup(controller.getGroupByLocation(location)),
+              onTap: () => controller.clickPhotoGroup(photoGroup),
               child: Obx(() {
               child: Obx(() {
-                final group = controller.getGroupByLocation(location);
-                final imagePath =
-                    group.images.isNotEmpty ? group.images.first : null;
+                final imagePath = photoGroup.images.isNotEmpty
+                    ? photoGroup.images.first
+                    : null;
                 return imagePath != null
                 return imagePath != null
                     ? Stack(
                     ? Stack(
                         children: [
                         children: [
@@ -177,7 +172,7 @@ class LocationsPhotoPage extends BasePage<LocationsPhotoController> {
                               right: 1.w,
                               right: 1.w,
                               bottom: 16.sp,
                               bottom: 16.sp,
                               child: Text(
                               child: Text(
-                                location,
+                                photoGroup.location ?? "",
                                 textAlign: TextAlign.center,
                                 textAlign: TextAlign.center,
                                 style: TextStyle(
                                 style: TextStyle(
                                   color: Colors.white,
                                   color: Colors.white,

+ 5 - 43
lib/module/locations_photo/locations_single_photo_controller.dart

@@ -1,59 +1,21 @@
 
 
-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';
+import 'package:clean/base/base_photos_controller.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
-import 'package:clean/module/photo_preview/photo_preview_view.dart';
-import 'package:clean/utils/toast_util.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
-import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
-class LocationsSinglePhotoController extends BasePhotoController {
-
-
-  late PhotoGroup photoGroup;
+class LocationsSinglePhotoController extends BasePhotosController {
 
 
   @override
   @override
   void onInit() {
   void onInit() {
-    print('LocationsSinglePhotoController onInit');
     _getArgs();
     _getArgs();
     super.onInit();
     super.onInit();
+
   }
   }
 
 
-  // 获取传递的参数
   void _getArgs() {
   void _getArgs() {
     final parameters = Get.arguments;
     final parameters = Get.arguments;
-    photoGroup = parameters?['PhotoGroup'] as PhotoGroup;
-  }
-
-  // // 通过位置获取照片组
-  // PhotoGroup getGroupByLocation(String? location) {
-  //   return photoGroups.firstWhere((group) => group.location == location);
-  // }
-
-
-  // 获取对应的 PhotosType
-  @override
-  PhotosType getPhotosType() {
-    return PhotosType.locationPhotos;
+    photoGroup.value =
+        parameters?['photoGroup'] ?? PhotoGroup(isSelected: false, images: []);
   }
   }
 
 
-
-
-  @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();
-  }
 }
 }

+ 15 - 16
lib/module/locations_photo/locations_single_photo_view.dart

@@ -17,7 +17,7 @@ class LocationsSinglePhotoPage
 
 
   static void start({required PhotoGroup photoGroup}) {
   static void start({required PhotoGroup photoGroup}) {
     Get.toNamed(RoutePath.locationsSinglePhoto, arguments: {
     Get.toNamed(RoutePath.locationsSinglePhoto, arguments: {
-      "PhotoGroup": photoGroup,
+      "photoGroup": photoGroup,
     });
     });
   }
   }
 
 
@@ -45,7 +45,7 @@ class LocationsSinglePhotoPage
           child: Container(
           child: Container(
             child: SafeArea(
             child: SafeArea(
               child: Obx(() {
               child: Obx(() {
-                if (controller.photoGroups.isEmpty) {
+                if (controller.photoGroup.value.images.isEmpty) {
                   return _noNoPicturesCard();
                   return _noNoPicturesCard();
                 }
                 }
                 return Column(
                 return Column(
@@ -66,14 +66,14 @@ class LocationsSinglePhotoPage
                                 crossAxisSpacing: 8.h, // 水平间距
                                 crossAxisSpacing: 8.h, // 水平间距
                               ),
                               ),
                               itemCount:
                               itemCount:
-                                  controller.photoGroups.first.images.length,
+                              controller.photoGroup.value.images.length,
                               itemBuilder: _buildPhotoItem(
                               itemBuilder: _buildPhotoItem(
-                                  controller.photoGroups.first.images)),
+                                  controller.photoGroup.value.images)),
                         );
                         );
                       }),
                       }),
                     ),
                     ),
                     Obx(() {
                     Obx(() {
-                      if (controller.selectedFileCount.value == 0) {
+                      if (controller.photoGroup.value.selectedPhotosIds.isEmpty) {
                         return SizedBox();
                         return SizedBox();
                       } else {
                       } else {
                         return _bottomBarCard();
                         return _bottomBarCard();
@@ -111,9 +111,9 @@ class LocationsSinglePhotoPage
                 ),
                 ),
               ),
               ),
               Obx(() {
               Obx(() {
-                if (controller.photoGroups.isEmpty) return SizedBox();
+                if (controller.photoGroup.value.images.isEmpty) return SizedBox();
                 return Text(
                 return Text(
-                  controller.photoGroups.first.location ?? "",
+                  controller.photoGroup.value.location ?? "",
                   textAlign: TextAlign.center,
                   textAlign: TextAlign.center,
                   style: TextStyle(
                   style: TextStyle(
                     color: Colors.white,
                     color: Colors.white,
@@ -123,12 +123,11 @@ class LocationsSinglePhotoPage
                 );
                 );
               }),
               }),
               Obx(() {
               Obx(() {
-                if (controller.photoGroups.isEmpty) return SizedBox();
+                if (controller.photoGroup.value.images.isEmpty) return SizedBox();
                 return GestureDetector(
                 return GestureDetector(
-                  onTap: () => controller.toggleGroupSelection(
-                      controller.photoGroups.first.images),
+                  onTap: () => controller.toggleGroupSelection(),
                   child: Obx(() => Text(
                   child: Obx(() => Text(
-                        controller.photoGroups.first.isSelected.value
+                        controller.photoGroup.value.isSelected.value
                             ? 'Deselect All'
                             ? 'Deselect All'
                             : 'Select All',
                             : 'Select All',
                         style: TextStyle(
                         style: TextStyle(
@@ -170,7 +169,7 @@ class LocationsSinglePhotoPage
             SizedBox(width: 5.w),
             SizedBox(width: 5.w),
             Obx(() {
             Obx(() {
               return Text(
               return Text(
-                'Delete ${controller.selectedFileCount.value} Photos (${controller.selectedFilesSizeString})',
+                'Delete ${controller.photoGroup.value.selectedCount} Photos (${controller.selectedFilesSizeString})',
                 textAlign: TextAlign.center,
                 textAlign: TextAlign.center,
                 style: TextStyle(
                 style: TextStyle(
                   color: Colors.white,
                   color: Colors.white,
@@ -188,13 +187,13 @@ class LocationsSinglePhotoPage
   Widget Function(BuildContext, int) _buildPhotoItem(
   Widget Function(BuildContext, int) _buildPhotoItem(
           List<AssetEntity> images) =>
           List<AssetEntity> images) =>
       (context, index) {
       (context, index) {
-        final group = controller.getGroupByImages(images);
+        final group = controller.photoGroup.value;
 
 
         return GestureDetector(
         return GestureDetector(
           onTap: () =>
           onTap: () =>
-              controller.clickImage(images, index, PhotosType.locationPhotos),
+              controller.clickImage(index),
           child: Obx(() {
           child: Obx(() {
-            final isSelected = group.selectedImages[index];
+            final isSelected = group.isImageSelected(images[index]);
             return Stack(
             return Stack(
               children: [
               children: [
                 Container(
                 Container(
@@ -226,7 +225,7 @@ class LocationsSinglePhotoPage
                   bottom: 8.h,
                   bottom: 8.h,
                   child: GestureDetector(
                   child: GestureDetector(
                       onTap: () =>
                       onTap: () =>
-                          controller.toggleImageSelection(images, index),
+                          controller.toggleImageSelection( index),
                       child: Container(
                       child: Container(
                         child: isSelected
                         child: isSelected
                             ? Center(
                             ? Center(

+ 14 - 21
lib/module/people_photo/people_photo_controller.dart

@@ -2,6 +2,7 @@ import 'package:clean/base/base_controller.dart';
 import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/base/base_photo_controller.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
+import 'package:clean/module/people_photo/people_photo_state.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
 import 'package:clean/module/photo_preview/photo_preview_view.dart';
 import 'package:clean/module/photo_preview/photo_preview_view.dart';
 import 'package:clean/utils/toast_util.dart';
 import 'package:clean/utils/toast_util.dart';
@@ -9,48 +10,40 @@ import 'package:flutter/Material.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
+import '../../base/base_photos_controller.dart';
 import '../../data/consts/event_report_id.dart';
 import '../../data/consts/event_report_id.dart';
 import '../../handler/event_handler.dart';
 import '../../handler/event_handler.dart';
 import '../photo_preview/phtoto_selected_preview_view.dart';
 import '../photo_preview/phtoto_selected_preview_view.dart';
 
 
-class PeoplePhotoController extends BasePhotoController {
+class PeoplePhotoController extends BasePhotosController {
+  late String titleName;
+
   @override
   @override
+  void onInit() {
+    super.onInit();
+    loadPhotos();
+  }
+
   void loadPhotos() {
   void loadPhotos() {
-    // 清空现有数据
-    photoGroups.clear();
-    final photoGroup = ImagePickerUtil.peoplePhotos;
-    if (photoGroup.isNotEmpty) {
-      photoGroups.add(PhotoGroup(
-        isSelected: false,
-        images: photoGroup,
-      ));
-    }
-    print('PeoplePhotoController loadPhotos ImagePickerUtil.selectedPeoplePhotosIds ${ImagePickerUtil.selectedPeoplePhotosIds}');
-    selectedPhotosIds.assignAll(ImagePickerUtil.selectedPeoplePhotosIds);
+    photoGroup.value = PeoplePhotoState.peoplePhotoGroup;
   }
   }
 
 
-  @override
-  PhotosType getPhotosType() => PhotosType.peoplePhotos;
 
 
-  void clickBack() {
-    print('PeoplePhotoController clickBack selectedPhotosIds $selectedPhotosIds');
-    updateSelections(selectedPhotosIds); // 恢复选中状态
 
 
-    Get.back();
-  }
   @override
   @override
   void onReady() {
   void onReady() {
     // TODO: implement onReady
     // TODO: implement onReady
     super.onReady();
     super.onReady();
     EventHandler.report(EventId.event_03006);
     EventHandler.report(EventId.event_03006);
   }
   }
+
   void clickJumpSelect() {
   void clickJumpSelect() {
-    if (selectedPhotosIds.isEmpty) {
+    if (photoGroup.value.selectedPhotosIds.isEmpty) {
       ToastUtil.show('Please select the picture');
       ToastUtil.show('Please select the picture');
       return;
       return;
     }
     }
     debugPrint('PeoplePhotoController clickJumpSelected');
     debugPrint('PeoplePhotoController clickJumpSelected');
     EventHandler.report(EventId.event_04005);
     EventHandler.report(EventId.event_04005);
-    PhotoSelectedPreviewPage.start(PhotosType.peoplePhotos, selectedPhotosIds);
+    PhotoSelectedPreviewPage.start(PhotosType.peoplePhotos, photoGroup.value.selectedPhotosIds);
   }
   }
 }
 }

+ 22 - 0
lib/module/people_photo/people_photo_state.dart

@@ -0,0 +1,22 @@
+import 'package:clean/module/people_photo/photo_group.dart';
+
+import '../image_picker/image_picker_util.dart';
+
+class PeoplePhotoState {
+  static final PhotoGroup peoplePhotoGroup = PhotoGroup(
+    isSelected: false,
+    images: ImagePickerUtil.peoplePhotos,
+  );
+
+  static void removePhotosData(Set<String> selectedPhotosIds) {
+    peoplePhotoGroup.images
+        .removeWhere((element) => selectedPhotosIds.contains(element.id));
+    peoplePhotoGroup.selectedPhotosIds
+        .removeWhere((element) => selectedPhotosIds.contains(element));
+
+    // 如果images为空,删除该 album
+    if (peoplePhotoGroup.images.isEmpty) {
+      return;
+    }
+  }
+}

+ 42 - 42
lib/module/people_photo/people_photo_view.dart

@@ -47,8 +47,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
         child: Container(
         child: Container(
           child: SafeArea(
           child: SafeArea(
             child: Obx(() {
             child: Obx(() {
-              if (controller.photoGroups.isEmpty ||
-                  controller.photoGroups[0].images.isEmpty) {
+              if (controller.photoGroup.value.images.isEmpty) {
                 return _noNoPicturesCard();
                 return _noNoPicturesCard();
               }
               }
               return Column(
               return Column(
@@ -60,16 +59,22 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
                       return ListView(
                       return ListView(
                         padding: EdgeInsets.symmetric(horizontal: 16.w),
                         padding: EdgeInsets.symmetric(horizontal: 16.w),
                         children: [
                         children: [
-                          ...controller.photoGroups.map((group) => Column(
-                                children: [
-                                  _buildPhotoGroup(
-                                    images: group.images,
-                                    title: "photo: ${group.images.length}",
-                                    imageCount: group.images.length,
-                                  ),
-                                  SizedBox(height: 15.h),
-                                ],
-                              ))
+                          Column(
+                            children: [
+                              _buildPhotoGroup(),
+                              SizedBox(height: 15.h),
+                            ],
+                          )
+                          // ...controller.photoGroups.map((group) => Column(
+                          //       children: [
+                          //         _buildPhotoGroup(
+                          //           images: group.images,
+                          //           title: "photo: ${group.images.length}",
+                          //           imageCount: group.images.length,
+                          //         ),
+                          //         SizedBox(height: 15.h),
+                          //       ],
+                          //     ))
                         ],
                         ],
                       );
                       );
                     }),
                     }),
@@ -103,8 +108,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
               height: 28.h,
               height: 28.h,
             ),
             ),
           ),
           ),
-          (controller.photoGroups.isEmpty ||
-                  controller.photoGroups[0].images.isEmpty)
+          (controller.photoGroup.value.images.isEmpty)
               ? SizedBox()
               ? SizedBox()
               : Column(
               : Column(
                   children: [
                   children: [
@@ -150,7 +154,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
             children: [
             children: [
               Obx(() {
               Obx(() {
                 return Text(
                 return Text(
-                  '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSizeString})',
+                  '${controller.photoGroup.value.selectedCount} files selected (${controller.selectedFilesSizeString})',
                   textAlign: TextAlign.center,
                   textAlign: TextAlign.center,
                   style: TextStyle(
                   style: TextStyle(
                     color: Colors.white.withOpacity(0.9),
                     color: Colors.white.withOpacity(0.9),
@@ -197,16 +201,17 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
         ));
         ));
   }
   }
 
 
-  Widget _buildPhotoGroup({
-    required List<AssetEntity> images,
-    required String title,
-    required int imageCount,
-  }) {
+  Widget _buildPhotoGroup(//     {
+      //   required List<AssetEntity> images,
+      //   required String title,
+      //   required int imageCount,
+      // }
+      ) {
     return Container(
     return Container(
       padding: EdgeInsets.symmetric(horizontal: 12.w),
       padding: EdgeInsets.symmetric(horizontal: 12.w),
       margin: EdgeInsets.only(top: 14.h),
       margin: EdgeInsets.only(top: 14.h),
       width: 328.w,
       width: 328.w,
-      height: imageCount < 5 ? 160.h : 230.h,
+      height: controller.photoGroup.value.images.length < 5 ? 160.h : 230.h,
       decoration: ShapeDecoration(
       decoration: ShapeDecoration(
         color: Colors.white.withValues(alpha: 0.12),
         color: Colors.white.withValues(alpha: 0.12),
         shape: RoundedRectangleBorder(
         shape: RoundedRectangleBorder(
@@ -220,7 +225,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             children: [
             children: [
               Text(
               Text(
-                title,
+                'photo: ${controller.photoGroup.value.images.length.toString()}',
                 textAlign: TextAlign.center,
                 textAlign: TextAlign.center,
                 style: TextStyle(
                 style: TextStyle(
                   color: Colors.white,
                   color: Colors.white,
@@ -229,9 +234,9 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
                 ),
                 ),
               ),
               ),
               GestureDetector(
               GestureDetector(
-                onTap: () => controller.toggleGroupSelection(images),
+                onTap: () => controller.toggleGroupSelection(),
                 child: Obx(() => Text(
                 child: Obx(() => Text(
-                      controller.getGroupByImages(images).isSelected.value
+                      controller.photoGroup.value.isSelected.value
                           ? 'Deselect All'
                           ? 'Deselect All'
                           : 'Select All',
                           : 'Select All',
                       style: TextStyle(
                       style: TextStyle(
@@ -244,12 +249,12 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
             ],
             ],
           ),
           ),
           SizedBox(
           SizedBox(
-            height: imageCount < 3
+            height: controller.photoGroup.value.images.length < 3
                 ? 70.h
                 ? 70.h
-                : imageCount <= 8
+                : controller.photoGroup.value.images.length <= 8
                     ? null
                     ? null
                     : 148.h,
                     : 148.h,
-            child: imageCount <= 8
+            child: controller.photoGroup.value.images.length <= 8
                 ? GridView.builder(
                 ? GridView.builder(
                     shrinkWrap: true,
                     shrinkWrap: true,
                     physics: NeverScrollableScrollPhysics(),
                     physics: NeverScrollableScrollPhysics(),
@@ -258,8 +263,8 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
                       mainAxisSpacing: 8.w,
                       mainAxisSpacing: 8.w,
                       crossAxisSpacing: 8.h,
                       crossAxisSpacing: 8.h,
                     ),
                     ),
-                    itemCount: imageCount,
-                    itemBuilder: _buildPhotoItem(images),
+                    itemCount: controller.photoGroup.value.images.length,
+                    itemBuilder: _buildPhotoItem(),
                   )
                   )
                 : GridView.builder(
                 : GridView.builder(
                     scrollDirection: Axis.horizontal,
                     scrollDirection: Axis.horizontal,
@@ -270,8 +275,8 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
                       crossAxisSpacing: 8.h,
                       crossAxisSpacing: 8.h,
                       childAspectRatio: 1,
                       childAspectRatio: 1,
                     ),
                     ),
-                    itemCount: imageCount,
-                    itemBuilder: _buildPhotoItem(images),
+                    itemCount: controller.photoGroup.value.images.length,
+                    itemBuilder: _buildPhotoItem(),
                   ),
                   ),
           ),
           ),
         ],
         ],
@@ -279,20 +284,15 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
     );
     );
   }
   }
 
 
-  Widget Function(BuildContext, int) _buildPhotoItem(
-          List<AssetEntity> images) =>
-      (context, index) {
-        final group = controller.getGroupByImages(images);
-
-        final assetEntity = group.images[index];
-
+  Widget Function(BuildContext, int) _buildPhotoItem() => (context, index) {
         return GestureDetector(
         return GestureDetector(
           onTap: () {
           onTap: () {
-            controller.clickImage(images, index, PhotosType.peoplePhotos);
+            controller.clickImage(index);
             print("点击图片");
             print("点击图片");
           },
           },
           child: Obx(() {
           child: Obx(() {
-            final isSelected = group.selectedImages[index];
+            final isSelected = controller.photoGroup.value
+                .isImageSelected(controller.photoGroup.value.images[index]);
             return Stack(
             return Stack(
               children: [
               children: [
                 Container(
                 Container(
@@ -306,7 +306,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
                   ),
                   ),
                   child: ClipRRect(
                   child: ClipRRect(
                       borderRadius: BorderRadius.circular(9.27.sp),
                       borderRadius: BorderRadius.circular(9.27.sp),
-                      child: AssetEntityImage(assetEntity,
+                      child: AssetEntityImage(controller.photoGroup.value.images[index],
                           thumbnailSize: const ThumbnailSize.square(300),
                           thumbnailSize: const ThumbnailSize.square(300),
                           isOriginal: false,
                           isOriginal: false,
                           fit: BoxFit.cover,
                           fit: BoxFit.cover,
@@ -321,7 +321,7 @@ class PeoplePhotoPage extends BasePage<PeoplePhotoController> {
                     bottom: 6.h,
                     bottom: 6.h,
                     child: GestureDetector(
                     child: GestureDetector(
                       onTap: () {
                       onTap: () {
-                        controller.toggleImageSelection(images, index);
+                        controller.toggleImageSelection(index);
                       },
                       },
                       child: Container(
                       child: Container(
                         child: isSelected
                         child: isSelected

+ 15 - 15
lib/module/people_photo/photo_group.dart

@@ -1,14 +1,7 @@
-import 'dart:io';
-import 'dart:isolate';
-
 import 'package:clean/utils/file_size_calculator_util.dart';
 import 'package:clean/utils/file_size_calculator_util.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:flutter/foundation.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
-import '../image_picker/image_picker_util.dart';
-
 class PhotoGroup {
 class PhotoGroup {
   // 照片组的选择状态
   // 照片组的选择状态
   final RxBool isSelected;
   final RxBool isSelected;
@@ -16,9 +9,6 @@ class PhotoGroup {
   // 照片组中的图片列表
   // 照片组中的图片列表
   final RxList<AssetEntity> images;
   final RxList<AssetEntity> images;
 
 
-  // 每张图片的选择状态
-  final RxList<bool> selectedImages;
-
   // 已选中图片的唯一标识集合
   // 已选中图片的唯一标识集合
   final RxSet<String> selectedPhotosIds = <String>{}.obs;
   final RxSet<String> selectedPhotosIds = <String>{}.obs;
 
 
@@ -44,11 +34,11 @@ class PhotoGroup {
     this.location,
     this.location,
     this.month,
     this.month,
   })  : isSelected = isSelected.obs,
   })  : isSelected = isSelected.obs,
-        images = images.obs,
-        selectedImages = RxList<bool>.filled(images.length, isSelected) {
+        images = images.obs
+  {
     // 初始化已选中图片的唯一标识集合
     // 初始化已选中图片的唯一标识集合
     if (isSelected) {
     if (isSelected) {
-      selectedPhotosIds.addAll(images.map((e) => e.id).toList());
+      selectedPhotosIds.addAll(images.map((e) => e.id));
     }
     }
   }
   }
 
 
@@ -56,7 +46,9 @@ class PhotoGroup {
     await FileSizeCalculatorUtil.calculateTotalSize(
     await FileSizeCalculatorUtil.calculateTotalSize(
          assetIds: images.map((e) => e.id).toSet(), updateValue: (double totalSize) {
          assetIds: images.map((e) => e.id).toSet(), updateValue: (double totalSize) {
 
 
-      this.totalSize.value = totalSize; // 监听并更新 UI
+      if (this.totalSize.value != totalSize) {
+        this.totalSize.value = totalSize; // 监听并更新 UI
+      }
     });
     });
   }
   }
 
 
@@ -64,7 +56,6 @@ class PhotoGroup {
   // 切换选择所有图片的状态
   // 切换选择所有图片的状态
   void toggleSelectAll(bool value) {
   void toggleSelectAll(bool value) {
     isSelected.value = value;
     isSelected.value = value;
-    selectedImages.assignAll(List.filled(images.length, value));
     if (value) {
     if (value) {
       selectedPhotosIds.addAll(images.map((e) => e.id).toList());
       selectedPhotosIds.addAll(images.map((e) => e.id).toList());
     } else {
     } else {
@@ -72,6 +63,15 @@ class PhotoGroup {
     }
     }
   }
   }
 
 
+  // 切换某张图片的选择状态
+  void toggleSelectImage(String id) {
+    if (selectedPhotosIds.contains(id)) {
+      selectedPhotosIds.remove(id);
+    } else {
+      selectedPhotosIds.add(id);
+    }
+
+  }
   /// 判断某张图片是否被选中
   /// 判断某张图片是否被选中
   bool isImageSelected(AssetEntity image) {
   bool isImageSelected(AssetEntity image) {
     return selectedPhotosIds.contains(image.id);
     return selectedPhotosIds.contains(image.id);

+ 38 - 40
lib/module/photo_preview/photo_preview_controller.dart

@@ -26,6 +26,7 @@ import 'package:lottie/lottie.dart';
 
 
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
+import '../../base/base_photos_controller.dart';
 import '../../data/consts/event_report_id.dart';
 import '../../data/consts/event_report_id.dart';
 import '../../dialog/play_video_dialog.dart';
 import '../../dialog/play_video_dialog.dart';
 import '../../handler/event_handler.dart';
 import '../../handler/event_handler.dart';
@@ -40,7 +41,6 @@ class PhotoPreviewController extends BaseController
   final RxBool isSwiperEnd = false.obs;
   final RxBool isSwiperEnd = false.obs;
   RxInt groupIndex = 0.obs;
   RxInt groupIndex = 0.obs;
 
 
-
   late PhotosType photosType;
   late PhotosType photosType;
   late String? currentImageId;
   late String? currentImageId;
   RxDouble selectedFilesSize = 0.0.obs;
   RxDouble selectedFilesSize = 0.0.obs;
@@ -103,7 +103,6 @@ class PhotoPreviewController extends BaseController
     }
     }
   }
   }
 
 
-
   // 获取参数
   // 获取参数
   void _getArgs() {
   void _getArgs() {
     photosType = parameters?['photosType'];
     photosType = parameters?['photosType'];
@@ -116,21 +115,26 @@ class PhotoPreviewController extends BaseController
     selectedFileCount.value = selectedPhotosIds.length;
     selectedFileCount.value = selectedPhotosIds.length;
   }
   }
 
 
+  void _assignPhotosAndSelections1(BasePhotosController controller) {
+    listAssetEntity.assignAll(controller.photoGroup.value.images);
+    selectedPhotosIds.assignAll(controller.photoGroup.value.selectedPhotosIds);
+    selectedFileCount.value = selectedPhotosIds.length;
+  }
+
   void _initData() {
   void _initData() {
     listAssetEntity.clear();
     listAssetEntity.clear();
     selectedPhotosIds.clear();
     selectedPhotosIds.clear();
 
 
     switch (photosType) {
     switch (photosType) {
-
       case PhotosType.peoplePhotos:
       case PhotosType.peoplePhotos:
         final PeoplePhotoController controller =
         final PeoplePhotoController controller =
-        Get.find<PeoplePhotoController>();
-        _assignPhotosAndSelections(controller);
+            Get.find<PeoplePhotoController>();
+        _assignPhotosAndSelections1(controller);
         break;
         break;
       case PhotosType.screenshots:
       case PhotosType.screenshots:
-        final ScreenShotsController controller =
-            Get.find<ScreenShotsController>();
-        _assignPhotosAndSelections(controller);
+        // final ScreenShotsController controller =
+        //     Get.find<ScreenShotsController>();
+        // _assignPhotosAndSelections(controller);
         break;
         break;
       case PhotosType.similarPhotos:
       case PhotosType.similarPhotos:
         final SimilarPhotoController controller =
         final SimilarPhotoController controller =
@@ -138,14 +142,14 @@ class PhotoPreviewController extends BaseController
         _assignPhotosAndSelections(controller);
         _assignPhotosAndSelections(controller);
         break;
         break;
       case PhotosType.locationPhotos:
       case PhotosType.locationPhotos:
-        final LocationsSinglePhotoController controller =
-            Get.find<LocationsSinglePhotoController>();
-        _assignPhotosAndSelections(controller);
+        // final LocationsSinglePhotoController controller =
+        //     Get.find<LocationsSinglePhotoController>();
+        // _assignPhotosAndSelections(controller);
         break;
         break;
       case PhotosType.blurryPhotos:
       case PhotosType.blurryPhotos:
-        final ScreenShotsController controller =
-            Get.find<ScreenShotsController>();
-        _assignPhotosAndSelections(controller);
+        // final ScreenShotsController controller =
+        //     Get.find<ScreenShotsController>();
+        // _assignPhotosAndSelections(controller);
         break;
         break;
     }
     }
 
 
@@ -193,7 +197,6 @@ class PhotoPreviewController extends BaseController
     selectedFileCount.value = selectedPhotosIds.length;
     selectedFileCount.value = selectedPhotosIds.length;
   }
   }
 
 
-
   Future<void> updateSelectedFilesSize() async {
   Future<void> updateSelectedFilesSize() async {
     if (selectedPhotosIds.isEmpty) {
     if (selectedPhotosIds.isEmpty) {
       selectedFilesSize.value = 0;
       selectedFilesSize.value = 0;
@@ -208,10 +211,6 @@ class PhotoPreviewController extends BaseController
     PhotoManager.clearFileCache();
     PhotoManager.clearFileCache();
   }
   }
 
 
-
-
-
-
   void updateSelections(Set<String> selectedIds) {
   void updateSelections(Set<String> selectedIds) {
     print(
     print(
         'PhotoPreviewController updateSelections photosType $photosType selectedIds $selectedIds');
         'PhotoPreviewController updateSelections photosType $photosType selectedIds $selectedIds');
@@ -224,7 +223,6 @@ class PhotoPreviewController extends BaseController
     print('PhotoPreviewController recoverSelectPhoto');
     print('PhotoPreviewController recoverSelectPhoto');
 
 
     cardSwiperController.value.undo();
     cardSwiperController.value.undo();
-
   }
   }
 
 
   void clickSelect() {
   void clickSelect() {
@@ -242,7 +240,6 @@ class PhotoPreviewController extends BaseController
     cardSwiperController.value.dispose();
     cardSwiperController.value.dispose();
     // 清理缓存
     // 清理缓存
     PhotoManager.clearFileCache();
     PhotoManager.clearFileCache();
-
   }
   }
 
 
   void clickBack() {
   void clickBack() {
@@ -256,18 +253,19 @@ class PhotoPreviewController extends BaseController
     EventHandler.report(EventId.event_04005);
     EventHandler.report(EventId.event_04005);
     PhotoSelectedPreviewPage.start(photosType, selectedPhotosIds);
     PhotoSelectedPreviewPage.start(photosType, selectedPhotosIds);
   }
   }
+
   // // 保存选择的图片ID列表
   // // 保存选择的图片ID列表
   void _saveSelectedPhotos(PhotosType type) {
   void _saveSelectedPhotos(PhotosType type) {
     switch (type) {
     switch (type) {
       case PhotosType.peoplePhotos:
       case PhotosType.peoplePhotos:
-        PeoplePhotoController controller = Get.find<PeoplePhotoController>();
-        controller.updateSelections(selectedPhotosIds);
-        controller.restoreSelections();
+        // PeoplePhotoController controller = Get.find<PeoplePhotoController>();
+        // controller.updateSelections(selectedPhotosIds);
+        // controller.restoreSelections();
         break;
         break;
       case PhotosType.screenshots:
       case PhotosType.screenshots:
-        ScreenShotsController controller = Get.find<ScreenShotsController>();
-        controller.updateSelections(selectedPhotosIds);
-        controller.restoreSelections();
+        // ScreenShotsController controller = Get.find<ScreenShotsController>();
+        // controller.updateSelections(selectedPhotosIds);
+        // controller.restoreSelections();
         break;
         break;
       case PhotosType.similarPhotos:
       case PhotosType.similarPhotos:
         SimilarPhotoController controller = Get.find<SimilarPhotoController>();
         SimilarPhotoController controller = Get.find<SimilarPhotoController>();
@@ -275,15 +273,15 @@ class PhotoPreviewController extends BaseController
         controller.restoreSelections();
         controller.restoreSelections();
         break;
         break;
       case PhotosType.locationPhotos:
       case PhotosType.locationPhotos:
-        LocationsSinglePhotoController controller =
-            Get.find<LocationsSinglePhotoController>();
-        controller.updateSelections(selectedPhotosIds);
-        controller.restoreSelections();
+        // LocationsSinglePhotoController controller =
+        //     Get.find<LocationsSinglePhotoController>();
+        // controller.updateSelections(selectedPhotosIds);
+        // controller.restoreSelections();
         break;
         break;
       case PhotosType.blurryPhotos:
       case PhotosType.blurryPhotos:
-        ScreenShotsController controller = Get.find<ScreenShotsController>();
-        controller.updateSelections(selectedPhotosIds);
-        controller.restoreSelections();
+        // ScreenShotsController controller = Get.find<ScreenShotsController>();
+        // controller.updateSelections(selectedPhotosIds);
+        // controller.restoreSelections();
         break;
         break;
     }
     }
   }
   }
@@ -331,7 +329,6 @@ class PhotoPreviewController extends BaseController
     int currentIndex,
     int currentIndex,
     CardSwiperDirection direction,
     CardSwiperDirection direction,
   ) {
   ) {
-
     print(
     print(
         'onSwiperUndo The card $currentIndex was swiped back to the ${direction.name}. Now the card $previousIndex is on top');
         'onSwiperUndo The card $currentIndex was swiped back to the ${direction.name}. Now the card $previousIndex is on top');
 
 
@@ -347,7 +344,6 @@ class PhotoPreviewController extends BaseController
     selectedFileCount.value = selectedPhotosIds.length;
     selectedFileCount.value = selectedPhotosIds.length;
     updateSelectedFilesSize();
     updateSelectedFilesSize();
 
 
-
     return true;
     return true;
   }
   }
 
 
@@ -461,14 +457,16 @@ class PhotoPreviewController extends BaseController
 
 
   // 将selectedFilesSize转成String类型,然后单位转换,如果超过1MB,则转成MB,超过1GB,则转成GB,否则KB
   // 将selectedFilesSize转成String类型,然后单位转换,如果超过1MB,则转成MB,超过1GB,则转成GB,否则KB
   String get selectedFilesSizeString {
   String get selectedFilesSizeString {
-
     final double sizeInKB = selectedFilesSize.value;
     final double sizeInKB = selectedFilesSize.value;
 
 
-    if (sizeInKB >= 1024 * 1024) {  // 先检查最大单位(GB)
+    if (sizeInKB >= 1024 * 1024) {
+      // 先检查最大单位(GB)
       return "${(sizeInKB / (1024 * 1024)).toStringAsFixed(2)}GB";
       return "${(sizeInKB / (1024 * 1024)).toStringAsFixed(2)}GB";
-    } else if (sizeInKB >= 1024) {  // 然后检查MB
+    } else if (sizeInKB >= 1024) {
+      // 然后检查MB
       return "${(sizeInKB / 1024).toStringAsFixed(2)}MB";
       return "${(sizeInKB / 1024).toStringAsFixed(2)}MB";
-    } else {  // 最后是KB
+    } else {
+      // 最后是KB
       return "${sizeInKB.toStringAsFixed(2)}KB";
       return "${sizeInKB.toStringAsFixed(2)}KB";
     }
     }
   }
   }

+ 20 - 19
lib/module/photo_preview/photo_selected_preview_controller.dart

@@ -44,6 +44,7 @@ class PhotoSelectedPreviewController extends BasePhotoController {
   // 加载选中的照片预览
   // 加载选中的照片预览
   @override
   @override
   void loadPhotos() {
   void loadPhotos() {
+
     photoGroups.clear();
     photoGroups.clear();
     for (var assetsEntity in photoPreviewController.listAssetEntity) {
     for (var assetsEntity in photoPreviewController.listAssetEntity) {
       if (selectedPhotosIds.contains(assetsEntity.id)) {
       if (selectedPhotosIds.contains(assetsEntity.id)) {
@@ -63,17 +64,18 @@ class PhotoSelectedPreviewController extends BasePhotoController {
     EventHandler.report(EventId.event_04007);
     EventHandler.report(EventId.event_04007);
     print('PhotoSelectedPreviewController clickBack');
     print('PhotoSelectedPreviewController clickBack');
     photoPreviewController.updateSelections(selectedPhotosIds);
     photoPreviewController.updateSelections(selectedPhotosIds);
-    if (photosType == PhotosType.peoplePhotos) {
-      print(
-          'PhotoSelectedPreviewController clickBack selectedPhotosIds $selectedPhotosIds');
-      PeoplePhotoController controller = Get.find<PeoplePhotoController>();
-      controller.updateSelections(selectedPhotosIds);
-      controller.restoreSelections();
-    } else if (photosType == PhotosType.similarPhotos) {
-      SimilarPhotoController controller = Get.find<SimilarPhotoController>();
-      controller.updateSelections(selectedPhotosIds);
-      controller.restoreSelections();
-    }
+    // 注意:1
+    // if (photosType == PhotosType.peoplePhotos) {
+    //   print(
+    //       'PhotoSelectedPreviewController clickBack selectedPhotosIds $selectedPhotosIds');
+    //   PeoplePhotoController controller = Get.find<PeoplePhotoController>();
+    //   controller.updateSelections(selectedPhotosIds);
+    //   controller.restoreSelections();
+    // } else if (photosType == PhotosType.similarPhotos) {
+    //   SimilarPhotoController controller = Get.find<SimilarPhotoController>();
+    //   controller.updateSelections(selectedPhotosIds);
+    //   controller.restoreSelections();
+    // }
 
 
     Get.back();
     Get.back();
   }
   }
@@ -109,14 +111,13 @@ class PhotoSelectedPreviewController extends BasePhotoController {
             group.images.removeWhere(
             group.images.removeWhere(
                 (element) => selectedPhotosIds.contains(element.id));
                 (element) => selectedPhotosIds.contains(element.id));
 
 
-            // 更新 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);
+            // 更新 group 中的 selectedPhotosIds 状态
+            group.selectedPhotosIds.clear();
+            for (var image in group.images) {
+              if (selectedPhotosIds.contains(image.id)) {
+                group.selectedPhotosIds.add(image.id);
+              }
+            }
           }
           }
 
 
           photoPreviewController.selectedPhotosIds.assignAll(selectedPhotosIds);
           photoPreviewController.selectedPhotosIds.assignAll(selectedPhotosIds);

+ 1 - 1
lib/module/photo_preview/phtoto_selected_preview_view.dart

@@ -221,7 +221,7 @@ class PhotoSelectedPreviewPage
           onTap: () =>
           onTap: () =>
               controller.clickImage(images, index, controller.photosType),
               controller.clickImage(images, index, controller.photosType),
           child: Obx(() {
           child: Obx(() {
-            var isSelected = group.selectedImages[index];
+            var isSelected = group.isImageSelected(images[index]);
             return Stack(
             return Stack(
               children: [
               children: [
                 Container(
                 Container(

+ 32 - 0
lib/module/screenshots_blurry/screenshots_blurry_state.dart

@@ -0,0 +1,32 @@
+import '../image_picker/image_picker_util.dart';
+import '../people_photo/photo_group.dart';
+
+class ScreenshotsBlurryState {
+  static final PhotoGroup screenshotsPhotoGroup = PhotoGroup(
+    isSelected: false,
+    images: ImagePickerUtil.screenshotPhotos,
+  );
+
+  static final PhotoGroup blurryPhotoGroup = PhotoGroup(
+    isSelected: false,
+    images: ImagePickerUtil.blurryPhotos,
+  );
+
+  static void removePhotosData(Set<String> selectedPhotosIds) {
+    screenshotsPhotoGroup.images
+        .removeWhere((element) => selectedPhotosIds.contains(element.id));
+    screenshotsPhotoGroup.selectedPhotosIds
+        .removeWhere((element) => selectedPhotosIds.contains(element));
+
+    blurryPhotoGroup.images
+        .removeWhere((element) => selectedPhotosIds.contains(element.id));
+    blurryPhotoGroup.selectedPhotosIds
+        .removeWhere((element) => selectedPhotosIds.contains(element));
+
+    // 如果images为空,删除该 album
+    if (screenshotsPhotoGroup.images.isEmpty &&
+        blurryPhotoGroup.images.isEmpty) {
+      return;
+    }
+  }
+}

+ 12 - 36
lib/module/screenshots_blurry/screenshots_controller.dart

@@ -4,22 +4,24 @@ import 'package:clean/data/bean/photos_type.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
 import 'package:clean/module/people_photo/photo_group.dart';
 import 'package:clean/module/photo_preview/photo_preview_view.dart';
 import 'package:clean/module/photo_preview/photo_preview_view.dart';
+import 'package:clean/module/screenshots_blurry/screenshots_blurry_state.dart';
 import 'package:clean/utils/toast_util.dart';
 import 'package:clean/utils/toast_util.dart';
 import 'package:get/get.dart';
 import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
+import '../../base/base_photos_controller.dart';
 import '../../data/consts/event_report_id.dart';
 import '../../data/consts/event_report_id.dart';
 import '../../handler/event_handler.dart';
 import '../../handler/event_handler.dart';
 
 
-class ScreenShotsController extends BasePhotoController {
-  late String titleName;
+class ScreenShotsController extends BasePhotosController {
+late String titleName;
 
 
-  @override
-  void onInit() {
-    print("ScreenShotsController onInit");
-    _getArgs();
-    super.onInit();
-  }
+@override
+void onInit() {
+  _getArgs();
+  super.onInit();
+  loadPhotos();
+}
 
 
   void _getArgs() {
   void _getArgs() {
 
 
@@ -42,37 +44,11 @@ class ScreenShotsController extends BasePhotoController {
     EventHandler.report(EventId.event_03006);
     EventHandler.report(EventId.event_03006);
   }
   }
 
 
-  @override
   void loadPhotos() {
   void loadPhotos() {
-    photoGroups.clear();
-
     if (titleName == "Screenshots") {
     if (titleName == "Screenshots") {
-      final photoGroup = ImagePickerUtil.screenshotPhotos;
-      if (photoGroup.isNotEmpty) {
-        photoGroups.add(PhotoGroup(
-          isSelected: false,
-          images: photoGroup,
-        ));
-      }
-      selectedPhotosIds.assignAll(ImagePickerUtil.selectedScreenshotPhotosIds);
+      photoGroup.value = ScreenshotsBlurryState.screenshotsPhotoGroup;
     } else if (titleName == "Blurry") {
     } else if (titleName == "Blurry") {
-      final photoGroup = ImagePickerUtil.blurryPhotos;
-      if (photoGroup.isNotEmpty) {
-        photoGroups.add(PhotoGroup(
-          isSelected: false,
-          images: photoGroup,
-        ));
-      }
-      selectedPhotosIds.assignAll(ImagePickerUtil.selectedBlurryPhotosIds);
+      photoGroup.value = ScreenshotsBlurryState.blurryPhotoGroup;
     }
     }
   }
   }
-
-  clickBack() {
-    print("ScreenShotsController titleName $titleName clickBack ");
-    updateSelections(selectedPhotosIds);
-    Get.back();
-  }
-
-  @override
-  PhotosType getPhotosType() => titleName == "Screenshots" ? PhotosType.screenshots : PhotosType.blurryPhotos;
 }
 }

+ 17 - 26
lib/module/screenshots_blurry/screenshots_view.dart

@@ -42,8 +42,7 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
         child: Container(
         child: Container(
           child: SafeArea(
           child: SafeArea(
             child: Obx(() {
             child: Obx(() {
-              if (controller.photoGroups.isEmpty ||
-                  controller.photoGroups[0].images.isEmpty) {
+              if (controller.photoGroup.value.images.isEmpty) {
                 return _noNoPicturesCard();
                 return _noNoPicturesCard();
               }
               }
               return Column(
               return Column(
@@ -63,14 +62,16 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
                               mainAxisSpacing: 8.w, // 垂直间距
                               mainAxisSpacing: 8.w, // 垂直间距
                               crossAxisSpacing: 8.h, // 水平间距
                               crossAxisSpacing: 8.h, // 水平间距
                             ),
                             ),
-                            itemCount: controller.photoGroups[0].images.length,
+                            itemCount:
+                                controller.photoGroup.value.images.length,
                             itemBuilder: _buildPhotoItem(
                             itemBuilder: _buildPhotoItem(
-                                controller.photoGroups[0].images)),
+                                controller.photoGroup.value.images)),
                       );
                       );
                     }),
                     }),
                   ),
                   ),
                   Obx(() {
                   Obx(() {
-                    if (controller.selectedPhotosIds.isNotEmpty) {
+                    if (controller
+                        .photoGroup.value.selectedPhotosIds.isNotEmpty) {
                       return _bottomBarCard();
                       return _bottomBarCard();
                     } else {
                     } else {
                       return SizedBox();
                       return SizedBox();
@@ -110,18 +111,12 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
                   ),
                   ),
                 ),
                 ),
                 // 如果photoGroup数据为空,不显示全选按钮
                 // 如果photoGroup数据为空,不显示全选按钮
-                controller.photoGroups.isEmpty ||
-                        controller.photoGroups[0].images.isEmpty
+                controller.photoGroup.value.images.isEmpty
                     ? Container()
                     ? Container()
                     : GestureDetector(
                     : GestureDetector(
-                        onTap: () => controller.toggleGroupSelection(
-                            controller.photoGroups[0].images),
+                        onTap: () => controller.toggleGroupSelection(),
                         child: Obx(() => Text(
                         child: Obx(() => Text(
-                              controller
-                                      .getGroupByImages(
-                                          controller.photoGroups[0].images)
-                                      .isSelected
-                                      .value
+                              controller.photoGroup.value.isSelected.value
                                   ? 'Deselect All'
                                   ? 'Deselect All'
                                   : 'Select All',
                                   : 'Select All',
                               style: TextStyle(
                               style: TextStyle(
@@ -134,8 +129,7 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
               ],
               ],
             );
             );
           }),
           }),
-          controller.photoGroups.isEmpty ||
-                  controller.photoGroups[0].images.isEmpty
+          controller.photoGroup.value.images.isEmpty
               ? Container()
               ? Container()
               : Column(
               : Column(
                   children: [
                   children: [
@@ -181,7 +175,7 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
               SizedBox(width: 5.w),
               SizedBox(width: 5.w),
               Obx(() {
               Obx(() {
                 return Text(
                 return Text(
-                  'Delete ${controller.selectedFileCount.value} Photos (${controller.selectedFilesSizeString})',
+                  'Delete ${controller.photoGroup.value.selectedCount} Photos (${controller.selectedFilesSizeString})',
                   textAlign: TextAlign.center,
                   textAlign: TextAlign.center,
                   style: TextStyle(
                   style: TextStyle(
                     color: Colors.white,
                     color: Colors.white,
@@ -198,14 +192,12 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
   Widget Function(BuildContext, int) _buildPhotoItem(
   Widget Function(BuildContext, int) _buildPhotoItem(
           List<AssetEntity> images) =>
           List<AssetEntity> images) =>
       (context, index) {
       (context, index) {
-        final group =
-            controller.getGroupByImages(controller.photoGroups[0].images);
-
         return GestureDetector(
         return GestureDetector(
-          onTap: () =>
-              controller.clickImage(images, index, controller.getPhotosType()),
+          onTap: () => controller.clickImage(index),
           child: Obx(() {
           child: Obx(() {
-            var isSelected = group.selectedImages[index];
+            final photoId = controller.photoGroup.value.images[index].id;
+            final isSelected =
+                controller.photoGroup.value.selectedPhotosIds.contains(photoId);
             return Stack(
             return Stack(
               children: [
               children: [
                 Container(
                 Container(
@@ -220,7 +212,7 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
                     child: ClipRRect(
                     child: ClipRRect(
                       borderRadius: BorderRadius.circular(9.27.sp),
                       borderRadius: BorderRadius.circular(9.27.sp),
                       child: AssetEntityImage(
                       child: AssetEntityImage(
-                        group.images[index],
+                        controller.photoGroup.value.images[index],
                         width: 104.w,
                         width: 104.w,
                         height: 104.w,
                         height: 104.w,
                         thumbnailSize: const ThumbnailSize.square(300),
                         thumbnailSize: const ThumbnailSize.square(300),
@@ -237,8 +229,7 @@ class ScreenshotsPage extends BasePage<ScreenShotsController> {
                   right: 8.w,
                   right: 8.w,
                   bottom: 8.h,
                   bottom: 8.h,
                   child: GestureDetector(
                   child: GestureDetector(
-                      onTap: () =>
-                          controller.toggleImageSelection(images, index),
+                      onTap: () => controller.toggleImageSelection(index),
                       child: Container(
                       child: Container(
                         child: isSelected
                         child: isSelected
                             ? Center(
                             ? Center(

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

@@ -37,9 +37,10 @@ class SimilarPhotoController extends BasePhotoController {
       ),
       ),
     );
     );
     for (var group in photoGroups) {
     for (var group in photoGroups) {
-      for (int i = 0; i < group.images.length; i++) {
-        group.selectedImages[i] = i == 0 ? false : true;
-        updateSelectedPhotosIds(group.images[i].id, i != 0);
+      for (int i = 1; i < group.images.length; i++) {
+
+        group.selectedPhotosIds.add(group.images[i].id);
+        updateSelectedPhotosIds(group.images[i].id, true);
       }
       }
     }
     }
     ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
     ImagePickerUtil.selectedSimilarPhotosIds.assignAll(selectedPhotosIds);
@@ -54,7 +55,7 @@ class SimilarPhotoController extends BasePhotoController {
 
 
       // 获取该组中所有选中的图片
       // 获取该组中所有选中的图片
       final selectedImages = group.images
       final selectedImages = group.images
-          .where((image) => group.selectedImages[group.images.indexOf(image)])
+          .where((image) => group.selectedPhotosIds.contains(image.id))
           .toList();
           .toList();
 
 
       if (selectedImages.isEmpty) {
       if (selectedImages.isEmpty) {
@@ -95,7 +96,7 @@ class SimilarPhotoController extends BasePhotoController {
           for (int i = indexesToRemove.length - 1; i >= 0; i--) {
           for (int i = indexesToRemove.length - 1; i >= 0; i--) {
             int index = indexesToRemove[i];
             int index = indexesToRemove[i];
             group.images.removeAt(index);
             group.images.removeAt(index);
-            group.selectedImages.removeAt(index);
+            group.selectedPhotosIds.remove(imagesToRemove[i].id);
           }
           }
 
 
           // 如果当前组为空,则删除该组
           // 如果当前组为空,则删除该组

+ 23 - 35
lib/module/similar_photo/similar_photo_view.dart

@@ -12,6 +12,7 @@ import 'package:get/get.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
 
 
 import '../../utils/styles.dart';
 import '../../utils/styles.dart';
+import '../people_photo/photo_group.dart';
 
 
 class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
 class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
   const SimilarPhotoPage({super.key});
   const SimilarPhotoPage({super.key});
@@ -44,15 +45,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                     children: [
                     children: [
                       ...controller.photoGroups.map((group) => Column(
                       ...controller.photoGroups.map((group) => Column(
                             children: [
                             children: [
-                              _buildPhotoGroup(
-                                imagesList: group.images,
-                                imageCount: group.images.length,
-                                  selectCount:group.selectedImages
-                                      .asMap()
-                                      .entries
-                                      .where((entry) => entry.value && entry.key < group.images.length)
-                                      .length,
-                              ),
+                              _buildPhotoGroup(group: group),
                               SizedBox(height: 15.h),
                               SizedBox(height: 15.h),
                             ],
                             ],
                           ))
                           ))
@@ -179,9 +172,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
   }
   }
 
 
   Widget _buildPhotoGroup({
   Widget _buildPhotoGroup({
-    required List<AssetEntity> imagesList,
-    required int imageCount,
-    required int selectCount,
+    required PhotoGroup group,
   }) {
   }) {
     return Container(
     return Container(
       padding: EdgeInsets.symmetric(horizontal: 12.w),
       padding: EdgeInsets.symmetric(horizontal: 12.w),
@@ -203,7 +194,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
               Row(
               Row(
                 children: [
                 children: [
                   Text(
                   Text(
-                    "photos $imageCount",
+                    "photos ${group.images.length}",
                     textAlign: TextAlign.center,
                     textAlign: TextAlign.center,
                     style: TextStyle(
                     style: TextStyle(
                       color: Colors.white,
                       color: Colors.white,
@@ -214,11 +205,11 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                 ],
                 ],
               ),
               ),
               GestureDetector(
               GestureDetector(
-                onTap: () => controller.toggleGroupSelection(imagesList),
+                onTap: () => controller.toggleGroupSelection(group.images),
                 child: Obx(() => Text(
                 child: Obx(() => Text(
                       controller.photoGroups
                       controller.photoGroups
                               .firstWhere((g) =>
                               .firstWhere((g) =>
-                                  g.images.toSet().containsAll(imagesList))
+                                  g.images.toSet().containsAll(group.images))
                               .isSelected
                               .isSelected
                               .value
                               .value
                           ? 'Deselect All'
                           ? 'Deselect All'
@@ -239,16 +230,14 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
               physics: BouncingScrollPhysics(),
               physics: BouncingScrollPhysics(),
               children: [
               children: [
                 // 第一张大图
                 // 第一张大图
-                if (imageCount > 0)
+                if (group.images.isNotEmpty)
                   GestureDetector(
                   GestureDetector(
                     onTap: () => controller.clickImage(
                     onTap: () => controller.clickImage(
-                        imagesList, 0, PhotosType.similarPhotos),
+                        group.images, 0, PhotosType.similarPhotos),
                     child: SizedBox(
                     child: SizedBox(
                       width: 148.w,
                       width: 148.w,
                       height: 148.h,
                       height: 148.h,
                       child: Obx(() {
                       child: Obx(() {
-                        final group = controller.photoGroups.firstWhere(
-                            (g) => g.images.toSet().containsAll(imagesList));
                         return Stack(
                         return Stack(
                           children: [
                           children: [
                             Container(
                             Container(
@@ -317,9 +306,9 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                               bottom: 4.h,
                               bottom: 4.h,
                               child: GestureDetector(
                               child: GestureDetector(
                                 onTap: () => controller.toggleImageSelection(
                                 onTap: () => controller.toggleImageSelection(
-                                    imagesList, 0),
+                                    group.images, 0),
                                 child: Container(
                                 child: Container(
-                                  child: group.selectedImages[0]
+                                  child: group.isImageSelected(group.images[0])
                                       ? Center(
                                       ? Center(
                                           child:
                                           child:
                                               Assets.images.iconSelected.image(
                                               Assets.images.iconSelected.image(
@@ -343,8 +332,9 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                     ),
                     ),
                   ),
                   ),
                 // 其他图片2x2网格
                 // 其他图片2x2网格
-                if (imageCount > 1)
-                  ...List.generate(((imageCount - 1) / 4).ceil(), (gridIndex) {
+                if (group.images.length > 1)
+                  ...List.generate(((group.images.length - 1) / 4).ceil(),
+                      (gridIndex) {
                     return Container(
                     return Container(
                       margin: EdgeInsets.only(left: 8.w),
                       margin: EdgeInsets.only(left: 8.w),
                       width: 142.w,
                       width: 142.w,
@@ -354,17 +344,13 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                         mainAxisSpacing: 8.h,
                         mainAxisSpacing: 8.h,
                         crossAxisSpacing: 8.w,
                         crossAxisSpacing: 8.w,
                         children: List.generate(
                         children: List.generate(
-                          min(4, imageCount - 1 - gridIndex * 4),
+                          min(4, group.images.length - 1 - gridIndex * 4),
                           (index) {
                           (index) {
                             final realIndex = gridIndex * 4 + index + 1;
                             final realIndex = gridIndex * 4 + index + 1;
                             return GestureDetector(
                             return GestureDetector(
-                              onTap: () => controller.clickImage(imagesList,
+                              onTap: () => controller.clickImage(group.images,
                                   realIndex, PhotosType.similarPhotos),
                                   realIndex, PhotosType.similarPhotos),
                               child: Obx(() {
                               child: Obx(() {
-                                final group = controller.photoGroups.firstWhere(
-                                    (g) => g.images
-                                        .toSet()
-                                        .containsAll(imagesList));
                                 return Container(
                                 return Container(
                                   decoration: ShapeDecoration(
                                   decoration: ShapeDecoration(
                                     color: Colors.white.withValues(alpha: 0.12),
                                     color: Colors.white.withValues(alpha: 0.12),
@@ -380,7 +366,8 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                                         child: AssetEntityImage(
                                         child: AssetEntityImage(
                                           group.images[realIndex],
                                           group.images[realIndex],
                                           width: 142.w,
                                           width: 142.w,
-                                          frameBuilder: Styles.customFrameBuilder(
+                                          frameBuilder:
+                                              Styles.customFrameBuilder(
                                             width: 120.w,
                                             width: 120.w,
                                             height: 120.w,
                                             height: 120.w,
                                           ),
                                           ),
@@ -395,11 +382,12 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                                         bottom: 4.h,
                                         bottom: 4.h,
                                         child: Obx(() {
                                         child: Obx(() {
                                           final isSelected =
                                           final isSelected =
-                                              group.selectedImages[realIndex];
+                                              group.isImageSelected(
+                                                  group.images[realIndex]);
                                           return GestureDetector(
                                           return GestureDetector(
                                             onTap: () =>
                                             onTap: () =>
                                                 controller.toggleImageSelection(
                                                 controller.toggleImageSelection(
-                                                    imagesList, realIndex),
+                                                    group.images, realIndex),
                                             child: Container(
                                             child: Container(
                                               child: isSelected
                                               child: isSelected
                                                   ? Center(
                                                   ? Center(
@@ -436,7 +424,7 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
             ),
             ),
           ),
           ),
           GestureDetector(
           GestureDetector(
-            onTap: () => controller.clickSingleGroupDelete(imagesList),
+            onTap: () => controller.clickSingleGroupDelete(group.images),
             child: Container(
             child: Container(
               width: 162.w,
               width: 162.w,
               height: 38.h,
               height: 38.h,
@@ -447,8 +435,8 @@ class SimilarPhotoPage extends BasePage<SimilarPhotoController> {
                 ),
                 ),
               ),
               ),
               child: Center(
               child: Center(
-                child:  Text(
-                  'Move $selectCount to trash',
+                child: Text(
+                  'Move ${group.selectedCount} to trash',
                   style: TextStyle(
                   style: TextStyle(
                     color: Colors.white,
                     color: Colors.white,
                     fontSize: 16.sp,
                     fontSize: 16.sp,

+ 0 - 1
lib/module/splash/intro/intro_view.dart

@@ -130,7 +130,6 @@ class IntroPage extends BasePage<IntroController> {
         Lottie.asset(
         Lottie.asset(
           pageBean.animUrl,
           pageBean.animUrl,
           width: 360.w,
           width: 360.w,
-          height: 329.w,
           repeat: true,
           repeat: true,
         ),
         ),
       ],
       ],

Разлика између датотеке није приказан због своје велике величине
+ 374 - 386
pubspec.lock


+ 10 - 4
pubspec.yaml

@@ -63,7 +63,7 @@ dependencies:
   flutter_localizations:
   flutter_localizations:
     sdk: flutter
     sdk: flutter
   # 图片保存
   # 图片保存
-  image_gallery_saver: ^2.0.3
+  image_gallery_saver_plus: ^4.0.1
 
 
   # 卡片滑动
   # 卡片滑动
   flutter_card_swiper: ^7.0.2
   flutter_card_swiper: ^7.0.2
@@ -109,10 +109,10 @@ dependencies:
   path_provider: ^2.1.5
   path_provider: ^2.1.5
 
 
   #tencent mmkv
   #tencent mmkv
-  mmkv: ^1.3.9
+  mmkv: ^2.2.1
 
 
-  # 存储空间
-  disk_space: ^0.2.1
+#  # 存储空间
+#  disk_space_plus: ^0.2.5
 
 
   #网页跳转
   #网页跳转
   webview_flutter: ^4.10.0
   webview_flutter: ^4.10.0
@@ -147,6 +147,12 @@ dependencies:
   # 动画
   # 动画
   lottie: ^3.3.1
   lottie: ^3.3.1
 
 
+  photo_classifier:
+    git:
+      url: http://git.atmob.com/Groot/clean_pro_photo_classifier_plugin
+      ref: release/1.0.1
+
+
 
 
 dev_dependencies:
 dev_dependencies:
   flutter_test:
   flutter_test: