فهرست منبع

更新 DiskAlbumController 接口, 调整了 DiskAlbum 和 DiskAlbumFile 的字段

reghao 6 ماه پیش
والد
کامیت
83001dab95
18فایلهای تغییر یافته به همراه422 افزوده شده و 201 حذف شده
  1. 23 15
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/controller/DiskAlbumController.java
  2. 21 3
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/db/mapper/DiskAlbumMapper.java
  3. 5 2
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/db/mapper/DiskFileMapper.java
  4. 9 6
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/db/repository/DiskAlbumRepository.java
  5. 4 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/dto/AlbumCreate.java
  6. 4 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/dto/AlbumEdit.java
  7. 9 4
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/po/DiskAlbum.java
  8. 8 4
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/po/DiskAlbumFile.java
  9. 4 5
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskAlbumDetail.java
  10. 0 22
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskAlbumImage.java
  11. 23 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskAlbumInfo.java
  12. 7 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskFileDetail.java
  13. 135 84
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/service/DiskAlbumService.java
  14. 28 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/service/DiskFileService.java
  15. 3 3
      content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/service/DiskFolderService.java
  16. 56 9
      content/content-service/src/main/resources/mapper/disk/DiskAlbumMapper.xml
  17. 27 42
      content/content-service/src/main/resources/mapper/disk/DiskFileMapper.xml
  18. 56 0
      content/content-service/src/test/java/cn/reghao/tnb/content/app/disk/service/DiskTest.java

+ 23 - 15
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/controller/DiskAlbumController.java

@@ -5,11 +5,11 @@ import cn.reghao.jutil.jdk.result.Result;
 import cn.reghao.jutil.web.WebResult;
 import cn.reghao.tnb.common.auth.AuthUser;
 import cn.reghao.tnb.common.db.SelectOption;
-import cn.reghao.tnb.content.app.disk.model.dto.AlbumAdd;
+import cn.reghao.tnb.content.app.disk.model.dto.AlbumEdit;
 import cn.reghao.tnb.content.app.disk.model.dto.AlbumCreate;
-import cn.reghao.tnb.content.app.disk.model.po.DiskAlbum;
 import cn.reghao.tnb.content.app.disk.model.vo.DiskAlbumDetail;
-import cn.reghao.tnb.content.app.disk.model.vo.DiskAlbumImage;
+import cn.reghao.tnb.content.app.disk.model.vo.DiskAlbumInfo;
+import cn.reghao.tnb.content.app.disk.model.vo.DiskFileDetail;
 import cn.reghao.tnb.content.app.disk.service.DiskAlbumService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -28,7 +28,6 @@ import java.util.List;
 @RequestMapping("/api/content/disk/album")
 @AuthUser
 public class DiskAlbumController {
-    private final int pageSize = 120;
     private final DiskAlbumService diskAlbumService;
 
     public DiskAlbumController(DiskAlbumService diskAlbumService) {
@@ -42,10 +41,19 @@ public class DiskAlbumController {
         return WebResult.success();
     }
 
-    @Operation(summary = "添加文件到相册", description = "N")
-    @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String addToDiskAlbum(@RequestBody @Validated AlbumAdd albumAdd) {
-        Result result = diskAlbumService.addAlbumFile(albumAdd);
+    @Operation(summary = "编辑相册", description = "N")
+    @PostMapping(value = "/edit", produces = MediaType.APPLICATION_JSON_VALUE)
+    public String editDiskAlbum(@RequestBody @Validated AlbumEdit albumEdit) {
+        int operation = albumEdit.getOperation();
+        Result result = Result.fail("operation unknown");
+        if (operation == 1) {
+            result = diskAlbumService.addAlbumFile(albumEdit.getAlbumId(), albumEdit.getFileIds());
+        } else if (operation == 2) {
+            result = diskAlbumService.updateAlbumFilePosition(albumEdit.getAlbumId(), albumEdit.getFileIds());
+        } else if (operation == 3) {
+            result = diskAlbumService.deleteAlbumFile(albumEdit.getAlbumId(), albumEdit.getFileIds());
+        }
+
         return WebResult.result(result);
     }
 
@@ -59,14 +67,14 @@ public class DiskAlbumController {
     @Operation(summary = "获取相册列表", description = "N")
     @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
     public String getDiskAlbum() {
-        List<DiskAlbum> diskAlbumList = diskAlbumService.getAlbumList();
+        List<DiskAlbumInfo> diskAlbumList = diskAlbumService.getAlbumList();
         return WebResult.success(diskAlbumList);
     }
 
     @Operation(summary = "获取相册详情", description = "N")
     @GetMapping(value = "/detail/{albumId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String getDiskAlbumDetail(@PathVariable("albumId") long albumId) {
-        DiskAlbumDetail diskAlbumDetail = diskAlbumService.getDiskAlbumDetail(albumId);
+    public String getDiskAlbumDetail(@PathVariable("albumId") long albumId, @RequestParam("pn") int pageNumber) {
+        DiskAlbumDetail diskAlbumDetail = diskAlbumService.getDiskAlbumDetail(albumId, pageNumber);
         if (diskAlbumDetail != null) {
             return WebResult.success(diskAlbumDetail);
         }
@@ -74,10 +82,10 @@ public class DiskAlbumController {
         return WebResult.fail();
     }
 
-    @Operation(summary = "获取相册中不存在的图片文件列表", description = "N")
-    @GetMapping("/image")
-    public String getDiskImages(@RequestParam("pn") int pageNumber) {
-        PageList<DiskAlbumImage> pageList = diskAlbumService.getAlbumImages(pageNumber, pageSize);
+    @Operation(summary = "获取合集中不存在的文件列表", description = "N")
+    @GetMapping("/exclude")
+    public String getAlbumExcludeFiles(@RequestParam("fileType") int fileType, @RequestParam("pn") int pageNumber) {
+        PageList<DiskFileDetail> pageList = diskAlbumService.getAlbumExcludeFiles(fileType, pageNumber);
         return WebResult.success(pageList);
     }
 }

+ 21 - 3
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/db/mapper/DiskAlbumMapper.java

@@ -1,12 +1,15 @@
 package cn.reghao.tnb.content.app.disk.db.mapper;
 
 import cn.reghao.jutil.jdk.db.BaseMapper;
+import cn.reghao.jutil.jdk.db.Page;
 import cn.reghao.tnb.content.app.disk.model.po.DiskAlbum;
 import cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author reghao
@@ -15,11 +18,26 @@ import java.util.List;
 @Mapper
 public interface DiskAlbumMapper extends BaseMapper<DiskAlbum> {
     void saveAlbumFiles(List<DiskAlbumFile> list);
-    void updateCoverUrl(@Param("albumId") long albumId, @Param("coverUrl") String coverUrl);
-    void updateNum(@Param("albumId") long albumId, @Param("num") int num);
+    void updateDiskAlbum(@Param("albumId") long albumId,
+                         @Param("coverFileId") String coverFileId,
+                         @Param("num") int num);
+    void updateDiskAlbumNum(@Param("albumId") long albumId, @Param("num") int num);
+    void updateDiskAlbumCover(@Param("albumId") long albumId, @Param("coverFileId") String coverFileId);
+    @Deprecated
+    void updateSha256sum(@Param("id") int id, @Param("sha256sum") String sha256sum);
+    void updateDiskAlbumFilePos(@Param("id") int id, @Param("pos") int pos);
+    void deleteDiskAlbumFiles(@Param("albumId") long albumId,
+                              @Param("sha256sumList") Collection<String> sha256sumList);
 
     DiskAlbum findDiskAlbum(long albumId);
     List<DiskAlbum> findByCreateBy(long createBy);
     List<DiskAlbumFile> findDiskAlbumFiles(long albumId);
-    List<String> findBykAlbumIds(List<Long> list);
+    List<DiskAlbumFile> findDiskAlbumFileList(@Param("albumId") long albumId,
+                                           @Param("sha256sumList") Collection<String> sha256sumList);
+    @Deprecated
+    List<DiskAlbumFile> findAllDiskAlbumFile();
+    List<String> findSha256sumByAlbumIds(List<Long> list);
+
+    int countDiskAlbumFile(long albumId);
+    List<DiskAlbumFile> findDiskAlbumFileByPage(@Param("page") Page page, @Param("albumId") long albumId);
 }

+ 5 - 2
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/db/mapper/DiskFileMapper.java

@@ -24,6 +24,9 @@ public interface DiskFileMapper extends BaseMapper<DiskFile> {
     List<DiskFile> findByFileIds(List<String> list);
     DiskFile findRoot();
 
-    List<String> countSha256sumGroupByDiskQuery(DiskQuery diskQuery);
-    List<DiskFile> findSha256sumGroupByPage(@Param("page") Page page, @Param("diskQuery") DiskQuery diskQuery);
+    List<String> countSha256sumGroupByDiskQuery(@Param("fileType") int fileType, @Param("userId") long userId);
+    List<DiskFile> findSha256sumGroupByPage(@Param("page") Page page,
+                                            @Param("fileType") int fileType,
+                                            @Param("userId") long userId);
+    List<DiskFile> findSha256sumGroup(List<String> sha256sumList);
 }

+ 9 - 6
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/db/repository/DiskAlbumRepository.java

@@ -6,6 +6,7 @@ import cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -21,12 +22,14 @@ public class DiskAlbumRepository {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public void saveDiskAlbum(long albumId, String coverUrl, int num, List<DiskAlbumFile> list) {
-        if (!coverUrl.isBlank()) {
-            diskAlbumMapper.updateCoverUrl(albumId, coverUrl);
-        }
-
-        diskAlbumMapper.updateNum(albumId, num);
+    public void saveDiskAlbum(long albumId, String coverFileId, int num, List<DiskAlbumFile> list) {
+        diskAlbumMapper.updateDiskAlbum(albumId, coverFileId, num);
         diskAlbumMapper.saveAlbumFiles(list);
     }
+
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteDiskAlbumFiles(long albumId, int num, Collection<String> sha256sumList) {
+        diskAlbumMapper.deleteDiskAlbumFiles(albumId, sha256sumList);
+        diskAlbumMapper.updateDiskAlbumNum(albumId, num);
+    }
 }

+ 4 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/dto/AlbumCreate.java

@@ -3,6 +3,8 @@ package cn.reghao.tnb.content.app.disk.model.dto;
 import lombok.Getter;
 import org.hibernate.validator.constraints.Length;
 
+import javax.validation.constraints.NotNull;
+
 /**
  * @author reghao
  * @date 2025-09-01 14:39:27
@@ -11,4 +13,6 @@ import org.hibernate.validator.constraints.Length;
 public class AlbumCreate {
     @Length(min = 1, max = 10, message = "相册名长度为 1 ~ 10 个字符")
     private String albumName;
+    @NotNull
+    private Integer fileType;
 }

+ 4 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/dto/AlbumAdd.java → content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/dto/AlbumEdit.java

@@ -11,9 +11,12 @@ import java.util.List;
  * @date 2025-09-01 15:40:36
  */
 @Getter
-public class AlbumAdd {
+public class AlbumEdit {
     @NotNull
     private Long albumId;
+    // 1 - 添加, 2 - 保存新顺序, 3 - 删除
+    @NotNull
+    private Integer operation;
     @Size(min = 1, max = 100, message = "每次添加到相册的文件不超过 100 个")
     private List<String> fileIds;
 }

+ 9 - 4
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/po/DiskAlbum.java

@@ -2,6 +2,7 @@ package cn.reghao.tnb.content.app.disk.model.po;
 
 import cn.reghao.jutil.jdk.db.BaseObject;
 import cn.reghao.tnb.common.auth.UserContext;
+import cn.reghao.tnb.content.app.disk.model.dto.AlbumCreate;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
@@ -16,15 +17,19 @@ import lombok.Setter;
 public class DiskAlbum extends BaseObject<Integer> {
     private long albumId;
     private String albumName;
-    private String coverUrl;
+    private Integer fileType;
+    private String coverFileId;
+    //@Deprecated
+    //private transient String coverUrl;
     private Integer num;
     private Long createAt;
     private Long createBy;
 
-    public DiskAlbum(long albumId, String albumName) {
+    public DiskAlbum(long albumId, AlbumCreate albumCreate) {
         this.albumId = albumId;
-        this.albumName = albumName;
-        this.coverUrl = "";
+        this.albumName = albumCreate.getAlbumName();
+        this.fileType = albumCreate.getFileType();
+        this.coverFileId = "";
         this.num = 0;
         this.createAt = System.currentTimeMillis();
         this.createBy = UserContext.getUserId();

+ 8 - 4
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/po/DiskAlbumFile.java

@@ -16,14 +16,18 @@ import lombok.Setter;
 @Getter
 public class DiskAlbumFile extends BaseObject<Integer> {
     private Long albumId;
-    private String fileId;
-    private Integer fileType;
+    //@Deprecated
+    //private String fileId;
+    private String sha256sum;
+    //@Deprecated
+    //private Integer fileType;
     private Integer pos;
 
     public DiskAlbumFile(long albumId, DiskFile diskFile, int pos) {
         this.albumId = albumId;
-        this.fileId = diskFile.getFileId();
-        this.fileType = diskFile.getFileType();
+        //this.fileId = diskFile.getFileId();
+        this.sha256sum = diskFile.getSha256sum();
+        //this.fileType = diskFile.getFileType();
         this.pos = pos;
     }
 }

+ 4 - 5
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskAlbumDetail.java

@@ -1,9 +1,8 @@
 package cn.reghao.tnb.content.app.disk.model.vo;
 
+import cn.reghao.jutil.jdk.db.PageList;
 import cn.reghao.tnb.content.app.disk.model.po.DiskAlbum;
 
-import java.util.List;
-
 /**
  * @author reghao
  * @date 2025-09-02 23:18:19
@@ -11,11 +10,11 @@ import java.util.List;
 public class DiskAlbumDetail {
     private long albumId;
     private String albumName;
-    private List<DiskFileDetail> diskFileList;
+    private PageList<DiskFileDetail> pageList;
 
-    public DiskAlbumDetail(DiskAlbum diskAlbum, List<DiskFileDetail> diskFileList) {
+    public DiskAlbumDetail(DiskAlbum diskAlbum, PageList<DiskFileDetail> pageList) {
         this.albumId = diskAlbum.getAlbumId();
         this.albumName = diskAlbum.getAlbumName();
-        this.diskFileList = diskFileList;
+        this.pageList = pageList;
     }
 }

+ 0 - 22
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskAlbumImage.java

@@ -1,22 +0,0 @@
-package cn.reghao.tnb.content.app.disk.model.vo;
-
-import cn.reghao.tnb.content.app.disk.model.po.DiskFile;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * @author reghao
- * @date 2025-09-03 16:11:18
- */
-@Setter
-@Getter
-public class DiskAlbumImage {
-    private String fileId;
-    private String filename;
-    private String url;
-
-    public DiskAlbumImage(DiskFile diskFile) {
-        this.fileId = diskFile.getFileId();
-        this.filename = diskFile.getFilename();
-    }
-}

+ 23 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskAlbumInfo.java

@@ -0,0 +1,23 @@
+package cn.reghao.tnb.content.app.disk.model.vo;
+
+import cn.reghao.tnb.content.app.disk.model.po.DiskAlbum;
+
+/**
+ * @author reghao
+ * @date 2025-09-04 15:56:59
+ */
+public class DiskAlbumInfo {
+    private long albumId;
+    private String albumName;
+    private Integer fileType;
+    private String coverUrl;
+    private Integer num;
+
+    public DiskAlbumInfo(DiskAlbum diskAlbum, String coverUrl) {
+        this.albumId = diskAlbum.getAlbumId();
+        this.albumName = diskAlbum.getAlbumName();
+        this.fileType = diskAlbum.getFileType();
+        this.coverUrl =coverUrl;
+        this.num = diskAlbum.getNum();
+    }
+}

+ 7 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/model/vo/DiskFileDetail.java

@@ -1,6 +1,7 @@
 package cn.reghao.tnb.content.app.disk.model.vo;
 
 import cn.reghao.oss.sdk.model.dto.ObjectInfo;
+import cn.reghao.tnb.content.app.disk.model.po.DiskFile;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
@@ -24,4 +25,10 @@ public class DiskFileDetail {
         this.filename = objectInfo.getFilename();
         this.url = signedUrl;
     }
+
+    public DiskFileDetail(DiskFile diskFile) {
+        this.fileId = diskFile.getFileId();
+        this.fileType = diskFile.getFileType();
+        this.filename = diskFile.getFilename();
+    }
 }

+ 135 - 84
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/service/DiskAlbumService.java

@@ -12,7 +12,6 @@ import cn.reghao.tnb.common.db.SelectOption;
 import cn.reghao.tnb.content.app.disk.db.mapper.DiskAlbumMapper;
 import cn.reghao.tnb.content.app.disk.db.mapper.DiskFileMapper;
 import cn.reghao.tnb.content.app.disk.db.repository.DiskAlbumRepository;
-import cn.reghao.tnb.content.app.disk.model.dto.AlbumAdd;
 import cn.reghao.tnb.content.app.disk.model.dto.AlbumCreate;
 import cn.reghao.tnb.content.app.disk.model.po.DiskAlbum;
 import cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile;
@@ -37,6 +36,7 @@ public class DiskAlbumService {
     private OssService ossService;
     private final int channelCode = 111;
     private final int albumMaxFiles = 1000;
+    private final int pageSize = 12;
     private final DiskFileMapper diskFileMapper;
     private final DiskAlbumMapper diskAlbumMapper;
     private final DiskAlbumRepository diskAlbumRepository;
@@ -54,65 +54,124 @@ public class DiskAlbumService {
 
     public void createAlbum(AlbumCreate albumCreate) {
         long albumId = idGenerator.nextId();
-        DiskAlbum diskAlbum = new DiskAlbum(albumId, albumCreate.getAlbumName());
+        DiskAlbum diskAlbum = new DiskAlbum(albumId, albumCreate);
         diskAlbumMapper.save(diskAlbum);
     }
 
-    public Result addAlbumFile(AlbumAdd albumAdd) {
-        long albumId = albumAdd.getAlbumId();
-        Set<String> existFileIds = diskAlbumMapper.findDiskAlbumFiles(albumId).stream()
-                .map(DiskAlbumFile::getFileId)
-                .collect(Collectors.toSet());
-        if (existFileIds.size() >= albumMaxFiles) {
-            return Result.fail(String.format("单个相册最多能容纳 %s 张照片", albumMaxFiles));
-        }
-
-        Set<String> existSha256sums = new HashSet<>();
-        if (!existFileIds.isEmpty()) {
-            existSha256sums = diskFileMapper.findByFileIds(new ArrayList<>(existFileIds)).stream()
-                    .map(DiskFile::getSha256sum)
-                    .collect(Collectors.toSet());
+    /**
+     * 添加新文件到合集中
+     *
+     * @param
+     * @return
+     * @date 2025-09-04 17:47:40
+     */
+    public synchronized Result addAlbumFile(long albumId, List<String> fileIds) {
+        DiskAlbum diskAlbum = diskAlbumMapper.findDiskAlbum(albumId);
+        if (diskAlbum == null) {
+            return Result.fail("album not exist");
         }
 
-        List<String> fileIds = albumAdd.getFileIds().stream()
-                .filter(fileId -> !existFileIds.contains(fileId))
+        List<String> existSha256sumList = diskAlbumMapper.findDiskAlbumFiles(albumId).stream()
+                .map(DiskAlbumFile::getSha256sum)
                 .collect(Collectors.toList());
-        if (fileIds.isEmpty()) {
-            return Result.fail("添加的照片在当前相册中已存在");
+        if (existSha256sumList.size() >= albumMaxFiles) {
+            return Result.fail(String.format("单个合集最多能容纳 %s 张文件", albumMaxFiles));
         }
 
+        Set<String> set = new HashSet<>(existSha256sumList);
         long loginUser = UserContext.getUserId();
-        List<DiskFile> diskFileList = diskFileMapper.findByFileIds(fileIds).stream()
+        int fileType = diskAlbum.getFileType();
+        List<DiskFile> diskFileList = diskFileService.findByFileIds(fileIds).stream()
+                .filter(diskFile -> !set.contains(diskFile.getSha256sum()))
                 .filter(diskFile -> diskFile.getOwner() == loginUser)
-                .filter(diskFile -> diskFile.getFileType() == ObjectType.Image.getCode()
-                        || diskFile.getFileType() == ObjectType.Video.getCode())
+                .filter(diskFile -> diskFile.getFileType() == fileType)
                 .collect(Collectors.toList());
 
-        int startPos = existFileIds.size()+1;
+        if (diskFileList.isEmpty()) {
+            return Result.fail("添加的文件在当前合集中已存在");
+        }
+
+        int startPos = existSha256sumList.size()+1;
         List<DiskAlbumFile> list = new ArrayList<>();
         for (DiskFile diskFile : diskFileList) {
-            if (existSha256sums.add(diskFile.getSha256sum())) {
-                list.add(new DiskAlbumFile(albumId, diskFile, startPos));
-                startPos++;
+            list.add(new DiskAlbumFile(albumId, diskFile, startPos));
+            startPos++;
+        }
+
+        String coverFileId = diskFileList.get(0).getFileId();
+        int num = existSha256sumList.size() + diskFileList.size();
+        diskAlbumRepository.saveDiskAlbum(albumId, coverFileId, num, list);
+        return Result.successWithMsg(String.format("当前合集中新添加了 %s 张文件", list.size()));
+    }
+
+    /**
+     * 调整合集内文件的顺序
+     *
+     * @param
+     * @return
+     * @date 2025-09-04 17:47:19
+     */
+    public Result updateAlbumFilePosition(long albumId, List<String> fileIds) {
+        // fileId -> pos
+        Map<String, Integer> positionMap = new HashMap<>();
+        int startPos = 1;
+        for (int i = 0; i < fileIds.size(); i++) {
+            positionMap.put(fileIds.get(i), i+startPos);
+        }
+
+        // sha256sum -> fileId
+        Map<String, String> map = new HashMap<>();
+        diskFileService.findByFileIds(fileIds).forEach(diskFile -> {
+                    map.put(diskFile.getSha256sum(), diskFile.getFileId());
+                });
+
+        List<DiskAlbumFile> diskAlbumFileList = diskAlbumMapper.findDiskAlbumFileList(albumId, map.keySet());
+        for (DiskAlbumFile diskAlbumFile : diskAlbumFileList) {
+            int id = diskAlbumFile.getId();
+            String sha256sum = diskAlbumFile.getSha256sum();
+            Integer pos = positionMap.get(map.get(sha256sum));
+            if (pos != null) {
+                diskAlbumMapper.updateDiskAlbumFilePos(id, pos);
             }
         }
 
-        if (list.isEmpty()) {
-            return Result.fail("添加的照片在当前相册中已存在");
+        return Result.success();
+    }
+
+    /**
+     * 删除合集内的文件
+     *
+     * @param
+     * @return
+     * @date 2025-09-04 17:48:05
+     */
+    public Result deleteAlbumFile(long albumId, List<String> fileIds) {
+        Set<String> deletedSha256sumSet = diskFileService.findByFileIds(fileIds).stream()
+                .map(DiskFile::getSha256sum)
+                .collect(Collectors.toSet());
+
+        DiskAlbum diskAlbum = diskAlbumMapper.findDiskAlbum(albumId);
+        int num = diskAlbum.getNum()-deletedSha256sumSet.size();
+        if (!deletedSha256sumSet.isEmpty()) {
+            diskAlbumRepository.deleteDiskAlbumFiles(albumId, num, deletedSha256sumSet);
         }
 
-        DiskAlbumFile diskAlbumFile = list.get(0);
-        String objectId = diskAlbumFile.getFileId();
-        String coverUrl = "";
-        try {
-            ObjectInfo objectInfo = ossService.getObjectInfo(channelCode, objectId);
-            coverUrl = objectInfo.getUrl();
-        } catch (Exception e) {
-            e.printStackTrace();
+        DiskFile diskFile = diskFileService.findByFileId(diskAlbum.getCoverFileId());
+        if (diskFile != null && deletedSha256sumSet.contains(diskFile.getSha256sum())) {
+            List<DiskAlbumFile> diskAlbumFileList = diskAlbumMapper.findDiskAlbumFiles(albumId);
+            String coverFileId = "";
+            if (!diskAlbumFileList.isEmpty()) {
+                String sha256sum = diskAlbumFileList.get(diskAlbumFileList.size()-1).getSha256sum();
+                List<DiskFile> diskFileList = diskFileService.findBySha256sum(sha256sum);
+                if (!diskFileList.isEmpty()) {
+                    coverFileId = diskFileList.get(0).getFileId();
+                }
+            }
+
+            diskAlbumMapper.updateDiskAlbumCover(albumId, coverFileId);
         }
 
-        diskAlbumRepository.saveDiskAlbum(albumId, coverUrl, existSha256sums.size(), list);
-        return Result.successWithMsg(String.format("当前相册中新添加了 %s 张照片", list.size()));
+        return Result.success();
     }
 
     public List<SelectOption> getAlbumKeyValues() {
@@ -124,23 +183,21 @@ public class DiskAlbumService {
         }).collect(Collectors.toList());
     }
 
-    public List<DiskAlbum> getAlbumList() {
+    public List<DiskAlbumInfo> getAlbumList() {
         long loginUser = UserContext.getUserId();
-        List<DiskAlbum> diskAlbumList = diskAlbumMapper.findByCreateBy(loginUser);
-        diskAlbumList.forEach(diskAlbum -> {
-            String coverUrl = diskAlbum.getCoverUrl();
+        return diskAlbumMapper.findByCreateBy(loginUser).stream().map(diskAlbum -> {
+            String coverUrl = "";
             try {
-                String signedUrl = ossService.getSignedUrlByUrl(channelCode, coverUrl);
-                diskAlbum.setCoverUrl(signedUrl);
+                String coverFileId = diskAlbum.getCoverFileId();
+                coverUrl = ossService.getSignedUrl(channelCode, coverFileId);
             } catch (Exception e) {
-                log.error("{}", e.getMessage());
+                log.error("getSignedUrl error: {}", e.getMessage());
             }
-        });
-
-        return diskAlbumList;
+            return new DiskAlbumInfo(diskAlbum, coverUrl);
+        }).collect(Collectors.toList());
     }
 
-    public DiskAlbumDetail getDiskAlbumDetail(long albumId) {
+    public DiskAlbumDetail getDiskAlbumDetail(long albumId, int pageNumber) {
         long loginUser = UserContext.getUserId();
         DiskAlbum diskAlbum = diskAlbumMapper.findDiskAlbum(albumId);
         if (diskAlbum == null) {
@@ -152,61 +209,55 @@ public class DiskAlbumService {
             return null;
         }
 
-        List<DiskAlbumFile> diskAlbumFileList = diskAlbumMapper.findDiskAlbumFiles(albumId);
-        List<String> fileIds = diskAlbumFileList.stream().map(DiskAlbumFile::getFileId).collect(Collectors.toList());
-        if (fileIds.isEmpty()) {
-            return new DiskAlbumDetail(diskAlbum, Collections.emptyList());
+        int total = diskAlbumMapper.countDiskAlbumFile(albumId);
+        Page page = new Page(pageNumber, pageSize);
+        List<DiskAlbumFile> diskAlbumFileList = diskAlbumMapper.findDiskAlbumFileByPage(page, albumId);
+        List<String> sha256sumList = diskAlbumFileList.stream().map(DiskAlbumFile::getSha256sum).collect(Collectors.toList());
+        if (sha256sumList.isEmpty()) {
+            return new DiskAlbumDetail(diskAlbum, PageList.empty());
         }
 
         Map<String, Integer> map = new HashMap<>();
         for (DiskAlbumFile diskAlbumFile : diskAlbumFileList) {
-            map.put(diskAlbumFile.getFileId(), diskAlbumFile.getPos());
+            map.put(diskAlbumFile.getSha256sum(), diskAlbumFile.getPos());
         }
 
-        List<DiskFileDetail> diskFileDetailList = diskFileMapper.findByFileIds(fileIds).stream().
-                map(diskFile -> {
+        List<DiskFileDetail> diskFileDetailList = diskFileService.findBySha256sumList(sha256sumList).stream()
+                .sorted(Comparator.comparingInt(o -> map.get(o.getSha256sum())))
+                .map(diskFile -> {
                     String objectId = diskFile.getFileId();
                     return diskFileService.getDiskFileDetail(channelCode, objectId);
                 })
                 .filter(Objects::nonNull)
-                .sorted(Comparator.comparingInt(o -> map.get(o.getFileId())))
                 .collect(Collectors.toList());
-        return new DiskAlbumDetail(diskAlbum, diskFileDetailList);
+
+        PageList<DiskFileDetail> pageList = PageList.pageList(pageNumber, pageSize, total, diskFileDetailList);
+        return new DiskAlbumDetail(diskAlbum, pageList);
     }
 
-    public PageList<DiskAlbumImage> getAlbumImages(int pageNumber, int pageSize) {
+    /**
+     * 获取不存在于合集中的文件
+     *
+     * @param
+     * @return
+     * @date 2025-09-04 17:42:38
+     */
+    public PageList<DiskFileDetail> getAlbumExcludeFiles(int fileType, int pageNumber) {
         long loginUser = UserContext.getUserId();
-        List<Long> albumIds = diskAlbumMapper.findByCreateBy(loginUser).stream()
-                .map(DiskAlbum::getAlbumId)
-                .collect(Collectors.toList());
-        Set<String> imageFileIdSet = new HashSet<>();
-        if (!albumIds.isEmpty()) {
-            imageFileIdSet.addAll(diskAlbumMapper.findBykAlbumIds(albumIds));
-        }
-
-        DiskQuery.Builder builder  = new DiskQuery.Builder()
-                .pageNumber(pageNumber)
-                .pageSize(pageSize)
-                .fileType(ObjectType.Image.getCode())
-                .owner(loginUser);
-        DiskQuery diskQuery = builder.build();
         Page page = new Page(pageNumber, pageSize);
-        int total = diskFileMapper.countSha256sumGroupByDiskQuery(diskQuery).size();
-
-        List<DiskFile> diskFileList = diskFileMapper.findSha256sumGroupByPage(page, diskQuery).stream()
-                .filter(diskFile -> !imageFileIdSet.contains(diskFile.getFileId()))
-                .collect(Collectors.toList());
+        List<DiskFile> diskFileList = diskFileMapper.findSha256sumGroupByPage(page, fileType, loginUser);
+        int total = diskFileMapper.countSha256sumGroupByDiskQuery(fileType, loginUser).size();
 
-        List<DiskAlbumImage> list = diskFileList.stream().map(DiskAlbumImage::new).collect(Collectors.toList());
-        for (DiskAlbumImage diskAlbumImage : list) {
-            String fileId = diskAlbumImage.getFileId();
+        List<DiskFileDetail> list = diskFileList.stream().map(DiskFileDetail::new).collect(Collectors.toList());
+        for (DiskFileDetail diskFileDetail : list) {
+            String fileId = diskFileDetail.getFileId();
             try {
                 String signedUrl = ossService.getSignedUrl(channelCode, fileId);
-                diskAlbumImage.setUrl(signedUrl);
+                diskFileDetail.setUrl(signedUrl);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
-        return PageList.pageList(diskQuery.getPageNumber(), diskQuery.getPageSize(), total, list);
+        return PageList.pageList(pageNumber, pageSize, total, list);
     }
 }

+ 28 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/service/DiskFileService.java

@@ -17,6 +17,7 @@ import cn.reghao.tnb.content.app.disk.model.dto.MoveFile;
 import cn.reghao.tnb.content.app.disk.model.po.DiskFile;
 import cn.reghao.tnb.content.app.disk.model.query.DiskQuery;
 import cn.reghao.tnb.content.app.disk.model.vo.*;
+import cn.reghao.tnb.content.app.disk.util.FileUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.springframework.stereotype.Service;
@@ -54,7 +55,7 @@ public class DiskFileService {
             String uploadId = uploadedFile.getUploadId();
             ObjectInfo objectInfo = ossService.getObjectInfo(channelCode, uploadId);
             String filename = objectInfo.getFilename();
-            String path = String.format("%s/%s", parentPath, filename);
+            String path = FileUtil.getCanonicalPath(String.format("%s/%s", parentPath, filename));
             DiskFile diskFile2 = findByPath(path);
             if (diskFile2 != null) {
                 return Result.fail("file exist");
@@ -455,6 +456,16 @@ public class DiskFileService {
         return pathList;
     }
 
+    public List<DiskFile> findBySha256sum(String sha256sum) {
+        long owner = UserContext.getUserId();
+        DiskQuery diskQuery = new DiskQuery.Builder()
+                .sha256sum(sha256sum)
+                .owner(owner)
+                .build();
+        Page page = new Page(1, 10);
+        return diskFileMapper.findDiskQueryByPage(page, diskQuery);
+    }
+
     public DiskFile findByPath(String path) {
         long owner = UserContext.getUserId();
         DiskQuery diskQuery = new DiskQuery.Builder()
@@ -481,6 +492,22 @@ public class DiskFileService {
         return diskFileList.isEmpty() ? null : diskFileList.get(0);
     }
 
+    public List<DiskFile> findByFileIds(List<String> fileIds) {
+        if (fileIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        return diskFileMapper.findByFileIds(fileIds);
+    }
+
+    public List<DiskFile> findBySha256sumList(List<String> sha256sumList) {
+        if (sha256sumList.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        return diskFileMapper.findSha256sumGroup(sha256sumList);
+    }
+
     public PageList<FileInfo> findByDiskQuery(DiskQuery diskQuery) {
         int pageNumber = diskQuery.getPageNumber();
         int pageSize = diskQuery.getPageSize();

+ 3 - 3
content/content-service/src/main/java/cn/reghao/tnb/content/app/disk/service/DiskFolderService.java

@@ -32,7 +32,7 @@ public class DiskFolderService {
         String parentPath = FileUtil.getCanonicalPath(createFolder.getParentPath());
         DiskFile parentDiskFile = findByPath(parentPath);
         if (parentDiskFile == null) {
-            return Result.fail("parent dir not exit");
+            return Result.fail("parent dir not exist");
         }
         String pid = parentDiskFile.getFileId();
 
@@ -41,7 +41,7 @@ public class DiskFolderService {
         String folderPath0 = FileUtil.getCanonicalPath(folderPath);
         DiskFile diskFile = findByPath(folderPath0);
         if (diskFile != null) {
-            return Result.fail("current dir exit");
+            return Result.fail("current dir exist");
         }
 
         DiskFile folder = new DiskFile(FileUtil.getFileId(), pid, folderPath0, folderName);
@@ -98,7 +98,7 @@ public class DiskFolderService {
                 pid = diskFileList.get(0).getFileId();
             } else {
                 String fileId = FileUtil.getFileId();
-                String path = parent;
+                String path = FileUtil.getCanonicalPath(parent);
                 String dirname = parent.substring(parent.lastIndexOf("/")+1);
                 diskFileMapper.save(new DiskFile(fileId, pid, path, dirname));
                 pid = fileId;

+ 56 - 9
content/content-service/src/main/resources/mapper/disk/DiskAlbumMapper.xml

@@ -4,29 +4,52 @@
 <mapper namespace="cn.reghao.tnb.content.app.disk.db.mapper.DiskAlbumMapper">
     <insert id="save" useGeneratedKeys="true" keyProperty="id">
         insert into my_disk_album
-        (`album_id`,`album_name`,`cover_url`,`num`,`create_at`,`create_by`)
+        (`album_id`,`album_name`,`cover_file_id`,`num`,`create_at`,`create_by`)
         values
-        (#{albumId},#{albumName},#{coverUrl},#{num},#{createAt},#{createBy})
+        (#{albumId},#{albumName},#{coverFileId},#{num},#{createAt},#{createBy})
     </insert>
     <insert id="saveAlbumFiles" useGeneratedKeys="true" keyProperty="id">
         insert into my_disk_album_file
-        (`album_id`,`file_id`,`file_type`,`pos`)
+        (`album_id`,`sha256sum`,`pos`)
         values
         <foreach collection="list" item="item" index="index" separator=",">
-            (#{item.albumId},#{item.fileId},#{item.fileType},#{item.pos})
+            (#{item.albumId},#{item.sha256sum},#{item.pos})
         </foreach>
     </insert>
 
-    <update id="updateCoverUrl">
+    <update id="updateDiskAlbum">
         update my_disk_album
-        set update_time=now(),cover_url=#{coverUrl}
+        set update_time=now(),cover_file_id=#{coverFileId},num=#{num}
         where album_id=#{albumId}
     </update>
-    <update id="updateNum">
+    <update id="updateDiskAlbumNum">
         update my_disk_album
         set update_time=now(),num=#{num}
         where album_id=#{albumId}
     </update>
+    <update id="updateDiskAlbumCover">
+        update my_disk_album
+        set update_time=now(),cover_file_id=#{coverFileId}
+        where album_id=#{albumId}
+    </update>
+    <update id="updateDiskAlbumFilePos">
+        update my_disk_album_file
+        set pos=#{pos}
+        where id=#{id}
+    </update>
+    <update id="updateSha256sum">
+        update my_disk_album_file
+        set sha256sum=#{sha256sum}
+        where id=#{id}
+    </update>
+
+    <delete id="deleteDiskAlbumFiles">
+        delete from my_disk_album_file
+        where album_id=#{albumId} and sha256sum in
+        <foreach collection="sha256sumList" item="id" index="index" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+    </delete>
     
     <select id="findDiskAlbum" resultType="cn.reghao.tnb.content.app.disk.model.po.DiskAlbum">
         select *
@@ -44,12 +67,36 @@
         where album_id=#{albumId}
         order by pos asc
     </select>
-    <select id="findBykAlbumIds" resultType="java.lang.String">
-        select file_id
+    <select id="findDiskAlbumFileList" resultType="cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile">
+        select *
+        from my_disk_album_file
+        where album_id=#{albumId} and sha256sum in
+        <foreach collection="sha256sumList" item="id" index="index" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+    </select>
+    <select id="findAllDiskAlbumFile" resultType="cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile">
+        select *
+        from my_disk_album_file
+    </select>
+    <select id="findSha256sumByAlbumIds" resultType="java.lang.String">
+        select sha256sum
         from my_disk_album_file
         where album_id in
         <foreach collection="list" item="id" index="index" open="(" close=")" separator=",">
             #{id}
         </foreach>
     </select>
+
+    <select id="countDiskAlbumFile" resultType="java.lang.Integer">
+        select count(*)
+        from my_disk_album_file
+        where album_id=#{albumId}
+    </select>
+    <select id="findDiskAlbumFileByPage" resultType="cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile">
+        select *
+        from my_disk_album_file
+        where album_id=#{albumId}
+        order by pos asc
+    </select>
 </mapper>

+ 27 - 42
content/content-service/src/main/resources/mapper/disk/DiskFileMapper.xml

@@ -103,53 +103,38 @@
     <select id="countSha256sumGroupByDiskQuery" resultType="java.lang.String">
         select sha256sum
         from my_disk_file
-        <where>
-            deleted=0
-            <if test="fileType != null">
-                and file_type=#{fileType}
-            </if>
-            <if test="owner != null">
-                and owner=#{owner}
-            </if>
-            <if test="pid != null">
-                and pid=#{pid}
-            </if>
-            <if test="fileId != null">
-                and file_id=#{fileId}
-            </if>
-            <if test="path != null">
-                and path=#{path}
-            </if>
-            <if test="sha256sum != null">
-                and sha256sum=#{sha256sum}
-            </if>
-        </where>
+        where deleted=0 and `owner`=#{userId} and file_type=#{fileType} and sha256sum not in (
+            select sha256sum
+            from my_disk_album_file A
+            where exists (
+                          select album_id
+                          from my_disk_album B
+                          where B.create_by=#{userId} and B.album_id=A.album_id
+                      )
+        )
         group by sha256sum
     </select>
     <select id="findSha256sumGroupByPage" resultType="cn.reghao.tnb.content.app.disk.model.po.DiskFile">
         select *
         from my_disk_file
-        <where>
-            deleted=0
-            <if test="diskQuery.fileType != null">
-                and file_type=#{diskQuery.fileType}
-            </if>
-            <if test="diskQuery.owner != null">
-                and owner=#{diskQuery.owner}
-            </if>
-            <if test="diskQuery.pid != null">
-                and pid=#{diskQuery.pid}
-            </if>
-            <if test="diskQuery.fileId != null">
-                and file_id=#{diskQuery.fileId}
-            </if>
-            <if test="diskQuery.path != null">
-                and path=#{diskQuery.path}
-            </if>
-            <if test="diskQuery.sha256sum != null">
-                and sha256sum=#{diskQuery.sha256sum}
-            </if>
-        </where>
+        where deleted=0 and `owner`=#{userId} and file_type=#{fileType} and sha256sum not in (
+            select sha256sum
+            from my_disk_album_file A
+            where exists (
+                          select album_id
+                          from my_disk_album B
+                          where B.create_by=#{userId} and B.album_id=A.album_id
+                      )
+        )
+        group by sha256sum
+    </select>
+    <select id="findSha256sumGroup" resultType="cn.reghao.tnb.content.app.disk.model.po.DiskFile">
+        select *
+        from my_disk_file
+        where deleted=0 and sha256sum in
+        <foreach collection="list" item="id" index="index" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
         group by sha256sum
     </select>
 </mapper>

+ 56 - 0
content/content-service/src/test/java/cn/reghao/tnb/content/app/disk/service/DiskTest.java

@@ -0,0 +1,56 @@
+package cn.reghao.tnb.content.app.disk.service;
+
+import cn.reghao.jutil.jdk.db.Page;
+import cn.reghao.tnb.content.app.ContentApplication;
+import cn.reghao.tnb.content.app.disk.db.mapper.DiskAlbumMapper;
+import cn.reghao.tnb.content.app.disk.db.mapper.DiskFileMapper;
+import cn.reghao.tnb.content.app.disk.model.po.DiskAlbum;
+import cn.reghao.tnb.content.app.disk.model.po.DiskAlbumFile;
+import cn.reghao.tnb.content.app.disk.model.po.DiskFile;
+import cn.reghao.tnb.content.app.disk.model.query.DiskQuery;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2025-09-03 19:12:34
+ */
+@Slf4j
+@ActiveProfiles("dev")
+@SpringBootTest(classes = ContentApplication.class)
+public class DiskTest {
+    @Autowired
+    DiskAlbumMapper diskAlbumMapper;
+    @Autowired
+    DiskFileMapper diskFileMapper;
+    DiskFileService diskFileService;
+
+    @Test
+    public void diskTest() {
+        List<DiskAlbumFile> list = diskAlbumMapper.findAllDiskAlbumFile();
+        for (DiskAlbumFile diskAlbumFile : list) {
+            /*int id = diskAlbumFile.getId();
+            String fileId = diskAlbumFile.getFileId();
+
+            DiskQuery.Builder builder  = new DiskQuery.Builder()
+                    .fileId(fileId);
+            DiskQuery diskQuery = builder.build();
+            Page page = new Page(1, 1);
+            List<DiskFile> diskFileList = diskFileMapper.findSha256sumGroupByPage(page, diskQuery);
+            if (!diskFileList.isEmpty()) {
+                DiskFile diskFile = diskFileList.get(0);
+                String sha256sum = diskFile.getSha256sum();
+                diskAlbumMapper.updateSha256sum(id, sha256sum);
+            } else {
+                System.out.println();
+            }*/
+        }
+    }
+}