浏览代码

质检-影响资料
1、新增时绑定照片关联信息
2、删除时删除照片关联信息
3、修改时从新生成pdf

LHB 1 月之前
父节点
当前提交
654e85ec00

+ 36 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/AlbumImages.java

@@ -0,0 +1,36 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 相册与照片关联关系表
+ * @TableName m_album_images
+ */
+@TableName(value ="m_album_images")
+@Data
+public class AlbumImages {
+    /**
+     * id
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 相册表id
+     */
+    private Long albumId;
+
+    /**
+     * 照片表id
+     */
+    private Long imageId;
+    /**
+     * 照片表id
+     */
+    @TableField(exist = false)
+    private String imagesUrl;
+
+}

+ 419 - 214
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/AlbumController.java

@@ -26,6 +26,7 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
+
 import javax.validation.Valid;
 
 import org.apache.poi.ss.usermodel.*;
@@ -42,15 +43,14 @@ import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
-import org.springblade.core.tool.utils.BeanUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.IoUtil;
-import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.*;
 import org.springblade.manager.dto.AlbumDTO;
 import org.springblade.manager.dto.AlbumDTO1;
+import org.springblade.manager.entity.AlbumImages;
 import org.springblade.manager.entity.ExcelTab;
 import org.springblade.manager.feign.ExcelTabClient;
 import org.springblade.manager.feign.ImageClassificationConfigClient;
+import org.springblade.manager.service.AlbumImagesService;
 import org.springblade.manager.utils.FileUtils;
 import org.springblade.resource.feign.CommonFileClient;
 import org.springblade.resource.feign.NewIOSSClient;
@@ -77,7 +77,7 @@ import java.util.HashMap;
 import java.util.List;
 
 /**
- *  控制器
+ * 控制器
  *
  * @author BladeX
  * @since 2025-07-15
@@ -88,37 +88,39 @@ import java.util.List;
 @Api(value = "", tags = "接口")
 public class AlbumController extends BladeController {
 
-	private final IAlbumService albumService;
+    private final IAlbumService albumService;
+
+    private final NewIOSSClient newIOSSClient;
 
-	private final NewIOSSClient newIOSSClient;
+    private final ExcelTabClient excelTabClient;
 
-	private final ExcelTabClient excelTabClient;
+    private final ImageClassificationFileClient imageClassificationFileClient;
 
-	private final ImageClassificationFileClient imageClassificationFileClient;
+    private final CommonFileClient commonFileClient;
 
-	private final CommonFileClient commonFileClient;
+    private final AlbumImagesService albumImagesService;
 
-	/**
-	 * 详情
-	 */
-	@GetMapping("/detail")
-	@ApiOperationSupport(order = 1)
-	@ApiOperation(value = "详情", notes = "传入album")
-	public R<AlbumVO> detail(Album album) {
-		Album detail = albumService.getOne(Condition.getQueryWrapper(album));
-		return R.data(AlbumWrapper.build().entityVO(detail));
-	}
+    /**
+     * 详情
+     */
+    @GetMapping("/detail")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "详情", notes = "传入album")
+    public R<AlbumVO> detail(Album album) {
+        Album detail = albumService.getOne(Condition.getQueryWrapper(album));
+        return R.data(AlbumWrapper.build().entityVO(detail));
+    }
 
-	/**
-	 * 分页 
-	 */
-	@PostMapping("/page")
-	@ApiOperationSupport(order = 2)
-	@ApiOperation(value = "分页", notes = "传入album")
-	public R<IPage<AlbumVO>> page(Long projectId,Long contractId,Query query) {
-		IPage<AlbumVO> pages = albumService.selectPage1(projectId,contractId,Condition.getPage(query));
-		return R.data(pages);
-	}
+    /**
+     * 分页
+     */
+    @PostMapping("/page")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "分页", notes = "传入album")
+    public R<IPage<AlbumVO>> page(Long projectId, Long contractId, Query query) {
+        IPage<AlbumVO> pages = albumService.selectPage1(projectId, contractId, Condition.getPage(query));
+        return R.data(pages);
+    }
 
 
 //	/**
@@ -132,54 +134,55 @@ public class AlbumController extends BladeController {
 //		return R.data(pages);
 //	}
 
-	/**
-	 * 新增 
-	 */
-	@PostMapping("/save")
-	@ApiOperationSupport(order = 4)
-	@ApiOperation(value = "新增", notes = "传入album")
-	public R save(@Valid @RequestBody AlbumDTO albumDTO) {
-		if(albumDTO.getMargePdfUrls().isEmpty()){
-			throw new ServiceException("相册不能为空");
-		}
-		List<String>uris=new ArrayList<>();
-		HashMap<String, Long> map = new HashMap<>();
-		for (AlbumDTO1 margePdfUrl : albumDTO.getMargePdfUrls()) {
-			String imageUrl = margePdfUrl.getImageUrl();
-			String[] urlss = imageUrl.split(",");
-			for (String string : urlss) {
-				map.put(string,margePdfUrl.getId());
-				uris.add(string);
-			}
-		}
-		if(uris.isEmpty()){
-			throw new ServiceException("相册不能为空");
-		}
-		Album album=new Album();
-		BeanUtil.copy(albumDTO,album);
-		String dateValue = albumDTO.getDateValue();
-		String[] strings = dateValue.split("~");
-		album.setStartDate(strings[0]);
-		album.setEndDate(strings[1]);
-		//获取固定表格
-		ExcelTab excelTab = this.excelTabClient.getById("1950465427890794498"); //影像资料模板
-		String file_path = null;
-		if (SystemUtils.isWindows()) {
-			file_path = "C:\\pdfFiles\\";
-			File file = new File(file_path);
-			if (!file.exists()) {
-				file.mkdirs();
-			}
-		}
-		if (SystemUtils.isLinux()) {
-			file_path = "/home/pdfFiles";
-			File file = new File(file_path);
-			if (!file.exists()) {
-				file.mkdirs();
-			}
-		}
-		if (excelTab != null) {
-			//获取数据
+    /**
+     * 新增
+     */
+    @PostMapping("/save")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "新增", notes = "传入album")
+    public R save(@Valid @RequestBody AlbumDTO albumDTO) {
+        if (albumDTO.getMargePdfUrls().isEmpty()) {
+            throw new ServiceException("相册不能为空");
+        }
+        List<String> uris = new ArrayList<>();
+        HashMap<String, Long> map = new HashMap<>();
+        for (AlbumDTO1 margePdfUrl : albumDTO.getMargePdfUrls()) {
+            String imageUrl = margePdfUrl.getImageUrl();
+            String[] urlss = imageUrl.split(",");
+            for (String string : urlss) {
+                map.put(string, margePdfUrl.getId());
+                uris.add(string);
+            }
+        }
+        if (uris.isEmpty()) {
+            throw new ServiceException("相册不能为空");
+        }
+        Album album = new Album();
+        album.setId(SnowFlakeUtil.getId());
+        BeanUtil.copy(albumDTO, album);
+        String dateValue = albumDTO.getDateValue();
+        String[] strings = dateValue.split("~");
+        album.setStartDate(strings[0]);
+        album.setEndDate(strings[1]);
+        //获取固定表格
+        ExcelTab excelTab = this.excelTabClient.getById("1950465427890794498"); //影像资料模板
+        String file_path = null;
+        if (SystemUtils.isWindows()) {
+            file_path = "C:\\pdfFiles\\";
+            File file = new File(file_path);
+            if (!file.exists()) {
+                file.mkdirs();
+            }
+        }
+        if (SystemUtils.isLinux()) {
+            file_path = "/home/pdfFiles";
+            File file = new File(file_path);
+            if (!file.exists()) {
+                file.mkdirs();
+            }
+        }
+        if (excelTab != null) {
+            //获取数据
 //			try {
 //					//需要删除的本地文件集合
 //					List<String> removeList = new ArrayList<>();
@@ -294,134 +297,334 @@ public class AlbumController extends BladeController {
 //			} catch (Exception e) {
 //				e.printStackTrace();
 //			}
-			try {
-				//需要删除的本地文件集合
-				List<String> removeList = new ArrayList<>();
-				//获取模板文件流
-				InputStream modInput = null;
-				FileInputStream excelFileInput = null;
-				FileOutputStream outputStream = null;
-				Workbook workbook = null;
-
-				List<String> pdfFileList = new ArrayList<>();
-				//两个图片一组
-				List<List<String>> groupUrls = CommonUtil.getBatchSize(uris, 2);
-				for (List<String> urls : groupUrls) {
-					try {
-						//创建模板Workbook
-						modInput = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
-						if (modInput != null) {
-							workbook = WorkbookFactory.create(modInput);
-							for (int i = 0, l = urls.size(); i < l; i++) {
-								try {
-									CreationHelper helper = workbook.getCreationHelper();
-									Sheet sheet = workbook.getSheetAt(0);
-									Drawing<?> drawing = sheet.createDrawingPatriarch();
-									ClientAnchor anchor = helper.createClientAnchor();
-									Long id = map.get(urls.get(i));
-									ImageClassificationFile file = imageClassificationFileClient.getImageClassificationFileById(id);
-
-									//获取文件流
-									byte[] bytes = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(urls.get(i)));
-									if (bytes[0] == 82 && bytes[1] == 73 && bytes[2] == 70) {
-										bytes = CommonUtil.webpToPngBytes(CommonUtil.getOSSInputStream(urls.get(i)));
-									}
-									//压缩文件大小
-									byte[] byteNew = FileUtils.compressImage(bytes);
-									//创建图片
-									Picture picture = drawing.createPicture(anchor, workbook.addPicture(byteNew, Workbook.PICTURE_TYPE_PNG));
-									picture.resize();
-
-									//图片定位
-									FileUtils.imageOrientation(sheet, anchor, i == 1 ? new DataVO(0, 8) : new DataVO(0, 3));
-
-									//定位其它信息
-									int baseRow = i == 0 ? 0 : 5; // 第一组在0-4行,第二组在5-9行
-
-									// 分组号 (C列,索引2)
-									sheet.getRow(baseRow ).getCell(3).setCellValue(albumDTO.getGroupNumber() != null ? albumDTO.getGroupNumber() : "");
-									// 照片编号 (C列,索引2)
-									sheet.getRow(baseRow + 1).getCell(3).setCellValue(file.getPhotoCode() != null ? file.getPhotoCode() : "");
-									// 摄影者 (C列,索引2)
-									sheet.getRow(baseRow + 2).getCell(3).setCellValue(file.getShootingUser() != null ? file.getShootingUser() : "");
-									// 拍摄时间 (C列,索引2)
-									sheet.getRow(baseRow + 3).getCell(3).setCellValue(file.getShootingTime() != null ?
-											DateUtil.format(file.getShootingTime(), "yyyy-MM-dd") : "");
-									// 照片说明 (A列,索引0)
-									String a=albumDTO.getImagesName()!=null?albumDTO.getImagesName():"";
-									String b=file.getTextContent() != null ? file.getTextContent() : "";
-									sheet.getRow(baseRow+4).getCell(1).setCellValue(a+b);
-
-								} catch (Exception e) {
-									e.printStackTrace();
-								}
-							}
-							String locationFile = file_path + SnowFlakeUtil.getId() + ".xlsx";
-							outputStream = new FileOutputStream(locationFile);
-							//记录文件删除
-							removeList.add(locationFile);
-							//生成一份新的excel
-							workbook.write(outputStream);
-							//将excel转PDF
-							File excelFile = new File(locationFile);
-							excelFileInput = new FileInputStream(excelFile);
-							MultipartFile files = new MockMultipartFile("file", excelFile.getName(), "text/plain", IOUtils.toByteArray(excelFileInput));
-							NewBladeFile bladeFile = this.commonFileClient.excelToPdf(files);
-							if (bladeFile != null) {
-								pdfFileList.add(bladeFile.getPdfUrl());
-							}
-						}
-					} catch (Exception e) {
-						e.printStackTrace();
-					} finally {
-						if (outputStream != null) {
-							IoUtil.closeQuietly(outputStream);
-						}
-						if (modInput != null) {
-							IoUtil.closeQuietly(modInput);
-						}
-						if (excelFileInput != null) {
-							IoUtil.closeQuietly(excelFileInput);
-						}
-						if (workbook != null) {
-							IoUtil.closeQuietly(workbook);
-						}
-					}
-				}
-
-				//合并pdf并上传
-				String mergeName = SnowFlakeUtil.getId() + ".pdf";
-				String mergeUrl = file_path + mergeName;
-				FileUtils.mergePdfPublicMethods(pdfFileList, mergeUrl);
-				//记录文件删除
-				removeList.add(mergeUrl);
-				//上传
-				BladeFile bladeFile = this.newIOSSClient.uploadFile(mergeName, mergeUrl);
-				if (bladeFile != null) {
-					album.setImagesPdf(bladeFile.getLink());
-				}
-
-				if (removeList.size() > 0) {
-					//删除本地文件
-					CommonUtil.removeFile(removeList);
-				}
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
-		}
-		return R.status(albumService.save(album));
-	}
-
-	/**
-	 * 修改 
-	 */
-	@PostMapping("/update")
-	@ApiOperationSupport(order = 5)
-	@ApiOperation(value = "修改", notes = "传入album")
-	public R update(@Valid @RequestBody AlbumDTO albumDTO) {
-
-		return R.status(albumService.update(albumDTO));
-	}
+            try {
+                //需要删除的本地文件集合
+                List<String> removeList = new ArrayList<>();
+                //获取模板文件流
+                InputStream modInput = null;
+                FileInputStream excelFileInput = null;
+                FileOutputStream outputStream = null;
+                Workbook workbook = null;
+
+                List<String> pdfFileList = new ArrayList<>();
+                //两个图片一组
+                List<List<String>> groupUrls = CommonUtil.getBatchSize(uris, 2);
+                for (List<String> urls : groupUrls) {
+                    try {
+                        //创建模板Workbook
+                        modInput = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
+                        if (modInput != null) {
+                            workbook = WorkbookFactory.create(modInput);
+                            for (int i = 0, l = urls.size(); i < l; i++) {
+                                try {
+                                    CreationHelper helper = workbook.getCreationHelper();
+                                    Sheet sheet = workbook.getSheetAt(0);
+                                    Drawing<?> drawing = sheet.createDrawingPatriarch();
+                                    ClientAnchor anchor = helper.createClientAnchor();
+                                    Long id = map.get(urls.get(i));
+                                    ImageClassificationFile file = imageClassificationFileClient.getImageClassificationFileById(id);
+
+                                    //获取文件流
+                                    byte[] bytes = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(urls.get(i)));
+                                    if (bytes[0] == 82 && bytes[1] == 73 && bytes[2] == 70) {
+                                        bytes = CommonUtil.webpToPngBytes(CommonUtil.getOSSInputStream(urls.get(i)));
+                                    }
+                                    //压缩文件大小
+                                    byte[] byteNew = FileUtils.compressImage(bytes);
+                                    //创建图片
+                                    Picture picture = drawing.createPicture(anchor, workbook.addPicture(byteNew, Workbook.PICTURE_TYPE_PNG));
+                                    picture.resize();
+
+                                    //图片定位
+                                    FileUtils.imageOrientation(sheet, anchor, i == 1 ? new DataVO(0, 8) : new DataVO(0, 3));
+
+                                    //定位其它信息
+                                    int baseRow = i == 0 ? 0 : 5; // 第一组在0-4行,第二组在5-9行
+
+                                    // 分组号 (C列,索引2)
+                                    sheet.getRow(baseRow).getCell(3).setCellValue(albumDTO.getGroupNumber() != null ? albumDTO.getGroupNumber() : "");
+                                    // 照片编号 (C列,索引2)
+                                    sheet.getRow(baseRow + 1).getCell(3).setCellValue(file.getPhotoCode() != null ? file.getPhotoCode() : "");
+                                    // 摄影者 (C列,索引2)
+                                    sheet.getRow(baseRow + 2).getCell(3).setCellValue(file.getShootingUser() != null ? file.getShootingUser() : "");
+                                    // 拍摄时间 (C列,索引2)
+                                    sheet.getRow(baseRow + 3).getCell(3).setCellValue(file.getShootingTime() != null ?
+                                            DateUtil.format(file.getShootingTime(), "yyyy-MM-dd") : "");
+                                    // 照片说明 (A列,索引0)
+                                    String a = albumDTO.getImagesName() != null ? albumDTO.getImagesName() : "";
+                                    String b = file.getTextContent() != null ? file.getTextContent() : "";
+                                    sheet.getRow(baseRow + 4).getCell(1).setCellValue(a + b);
+
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                            }
+                            String locationFile = file_path + SnowFlakeUtil.getId() + ".xlsx";
+                            outputStream = new FileOutputStream(locationFile);
+                            //记录文件删除
+                            removeList.add(locationFile);
+                            //生成一份新的excel
+                            workbook.write(outputStream);
+                            //将excel转PDF
+                            File excelFile = new File(locationFile);
+                            excelFileInput = new FileInputStream(excelFile);
+                            MultipartFile files = new MockMultipartFile("file", excelFile.getName(), "text/plain", IOUtils.toByteArray(excelFileInput));
+                            NewBladeFile bladeFile = this.commonFileClient.excelToPdf(files);
+                            if (bladeFile != null) {
+                                pdfFileList.add(bladeFile.getPdfUrl());
+                            }
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    } finally {
+                        if (outputStream != null) {
+                            IoUtil.closeQuietly(outputStream);
+                        }
+                        if (modInput != null) {
+                            IoUtil.closeQuietly(modInput);
+                        }
+                        if (excelFileInput != null) {
+                            IoUtil.closeQuietly(excelFileInput);
+                        }
+                        if (workbook != null) {
+                            IoUtil.closeQuietly(workbook);
+                        }
+                    }
+                }
+
+                //合并pdf并上传
+                String mergeName = SnowFlakeUtil.getId() + ".pdf";
+                String mergeUrl = file_path + mergeName;
+                FileUtils.mergePdfPublicMethods(pdfFileList, mergeUrl);
+                //记录文件删除
+                removeList.add(mergeUrl);
+                //上传
+                BladeFile bladeFile = this.newIOSSClient.uploadFile(mergeName, mergeUrl);
+                if (bladeFile != null) {
+                    album.setImagesPdf(bladeFile.getLink());
+                }
+
+                if (removeList.size() > 0) {
+                    //删除本地文件
+                    CommonUtil.removeFile(removeList);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        //添加相册与照片的关联关系 用于编辑时重新生成pdf
+        List<AlbumImages> albumImages = new ArrayList<>();
+        albumDTO.getMargePdfUrls().forEach(f -> {
+            AlbumImages albumImage = new AlbumImages();
+            albumImage.setId(SnowFlakeUtil.getId());
+            albumImage.setAlbumId(album.getId());
+            albumImage.setImageId(f.getId());
+            albumImages.add(albumImage);
+        });
+        albumImagesService.saveBatch(albumImages);
+
+        return R.status(albumService.save(album));
+    }
+
+    /**
+     * 修改
+     */
+    @PostMapping("/update")
+    @ApiOperationSupport(order = 5)
+    @ApiOperation(value = "修改", notes = "传入album")
+    public R update(@Valid @RequestBody AlbumDTO albumDTO) {
+
+        //查询关联关系
+        List<ImageClassificationFile> list = albumImagesService.selectImageUrlByAlbumId(albumDTO.getId());
+        if (CollectionUtil.isNotEmpty(list)) {
+            //旧pdf地址
+            String imagesPdf = albumDTO.getImagesPdf();
+
+            //获取起止编码
+            String codes = albumDTO.getCodes();
+            //初始值
+            Integer startInt = null, endInt = null, middleInt = null;
+            //图片计算值 最终值
+
+            if (StringUtils.isBlank(codes)) {
+                startInt = 1;
+            } else if (codes.contains("~")) {
+                String[] split = codes.split("~");
+                try {
+                    startInt = Integer.valueOf(split[0]);
+                    endInt = Integer.valueOf(split[1]);
+                } catch (NumberFormatException e) {
+                    throw new ServiceException("无法识别的数字");
+                }
+            } else {
+                try {
+                    startInt = Integer.valueOf(codes);
+                } catch (NumberFormatException e) {
+                    throw new ServiceException("无法识别的数字");
+                }
+            }
+            int count = startInt;
+
+            //重新生成pdf 并设置起止编号
+            //获取固定表格
+            //影像资料模板
+            ExcelTab excelTab = this.excelTabClient.getById("1950465427890794498");
+            String file_path = null;
+            if (SystemUtils.isWindows()) {
+                file_path = "C:\\pdfFiles\\";
+                File file = new File(file_path);
+                if (!file.exists()) {
+                    file.mkdirs();
+                }
+            }
+            Album album = new Album();
+            BeanUtil.copy(albumDTO, album);
+            String dateValue = albumDTO.getDateValue();
+            String[] strings = dateValue.split("~");
+            album.setStartDate(strings[0]);
+            album.setEndDate(strings[1]);
+            if (SystemUtils.isLinux()) {
+                file_path = "/home/pdfFiles";
+                File file = new File(file_path);
+                if (!file.exists()) {
+                    file.mkdirs();
+                }
+            }
+            if (excelTab != null) {
+                try {
+                    //需要删除的本地文件集合
+                    List<String> removeList = new ArrayList<>();
+                    //获取模板文件流
+                    InputStream modInput = null;
+                    FileInputStream excelFileInput = null;
+                    FileOutputStream outputStream = null;
+                    Workbook workbook = null;
+
+                    List<String> pdfFileList = new ArrayList<>();
+                    List<List<ImageClassificationFile>> batchSize = CommonUtil.getBatchSize(list, 2);
+
+
+                    for (List<ImageClassificationFile> imageClassificationFiles : batchSize) {
+                        try {
+                            //创建模板Workbook
+                            modInput = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
+                            if (modInput != null) {
+                                workbook = WorkbookFactory.create(modInput);
+
+                                //一个pdf 两个图片
+                                int i = 0;
+                                for (ImageClassificationFile file : imageClassificationFiles) {
+                                    try {
+                                        CreationHelper helper = workbook.getCreationHelper();
+                                        Sheet sheet = workbook.getSheetAt(0);
+                                        Drawing<?> drawing = sheet.createDrawingPatriarch();
+                                        ClientAnchor anchor = helper.createClientAnchor();
+                                        Long id = file.getId();
+                                        //获取文件流
+                                        byte[] bytes = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(file.getImageUrl()));
+                                        if (bytes[0] == 82 && bytes[1] == 73 && bytes[2] == 70) {
+                                            bytes = CommonUtil.webpToPngBytes(CommonUtil.getOSSInputStream(file.getImageUrl()));
+                                        }
+                                        //压缩文件大小
+                                        byte[] byteNew = FileUtils.compressImage(bytes);
+                                        //创建图片
+                                        Picture picture = drawing.createPicture(anchor, workbook.addPicture(byteNew, Workbook.PICTURE_TYPE_PNG));
+                                        picture.resize();
+
+                                        //图片定位
+                                        FileUtils.imageOrientation(sheet, anchor, i == 1 ? new DataVO(0, 8) : new DataVO(0, 3));
+                                        //定位其它信息
+                                        int baseRow = i == 0 ? 0 : 5; // 第一组在0-4行,第二组在5-9行
+                                        // 分组号 (C列,索引2)
+                                        sheet.getRow(baseRow).getCell(3).setCellValue(albumDTO.getGroupNumber() != null ? albumDTO.getGroupNumber() : "");
+                                        // 照片编号 (C列,索引2)
+                                        sheet.getRow(baseRow + 1).getCell(3).setCellValue(endInt != null && count > endInt ? "" : count + "");
+                                        // 摄影者 (C列,索引2)
+                                        sheet.getRow(baseRow + 2).getCell(3).setCellValue(file.getShootingUser() != null ? file.getShootingUser() : "");
+                                        // 拍摄时间 (C列,索引2)
+                                        sheet.getRow(baseRow + 3).getCell(3).setCellValue(file.getShootingTime() != null ?
+                                                DateUtil.format(file.getShootingTime(), "yyyy-MM-dd") : "");
+                                        // 照片说明 (A列,索引0)
+                                        String a = albumDTO.getImagesName() != null ? albumDTO.getImagesName() : "";
+                                        String b = file.getTextContent() != null ? file.getTextContent() : "";
+                                        sheet.getRow(baseRow + 4).getCell(1).setCellValue(a + b);
+                                        i++;
+
+                                        if(endInt != null && count > endInt){
+                                            middleInt = count - 1;
+                                        }else{
+                                            count++;
+                                        }
+                                    } catch (Exception e) {
+                                        e.printStackTrace();
+                                    }
+                                }
+                                String locationFile = file_path + SnowFlakeUtil.getId() + ".xlsx";
+                                outputStream = new FileOutputStream(locationFile);
+                                //记录文件删除
+                                removeList.add(locationFile);
+                                //生成一份新的excel
+                                workbook.write(outputStream);
+                                //将excel转PDF
+                                File excelFile = new File(locationFile);
+                                excelFileInput = new FileInputStream(excelFile);
+                                MultipartFile files = new MockMultipartFile("file", excelFile.getName(), "text/plain", IOUtils.toByteArray(excelFileInput));
+                                NewBladeFile bladeFile = this.commonFileClient.excelToPdf(files);
+                                if (bladeFile != null) {
+                                    pdfFileList.add(bladeFile.getPdfUrl());
+                                }
+                            }
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        } finally {
+                            if (outputStream != null) {
+                                IoUtil.closeQuietly(outputStream);
+                            }
+                            if (modInput != null) {
+                                IoUtil.closeQuietly(modInput);
+                            }
+                            if (excelFileInput != null) {
+                                IoUtil.closeQuietly(excelFileInput);
+                            }
+                            if (workbook != null) {
+                                IoUtil.closeQuietly(workbook);
+                            }
+                        }
+                    }
+                    //合并pdf并上传
+                    String mergeName = SnowFlakeUtil.getId() + ".pdf";
+                    String mergeUrl = file_path + mergeName;
+                    FileUtils.mergePdfPublicMethods(pdfFileList, mergeUrl);
+                    //记录文件删除
+                    removeList.add(mergeUrl);
+                    //上传
+                    BladeFile bladeFile = this.newIOSSClient.uploadFile(mergeName, mergeUrl);
+                    if (bladeFile != null) {
+                        album.setImagesPdf(bladeFile.getLink());
+                        //删除旧pdf
+                        if(StringUtils.isNotBlank(imagesPdf)){
+                            String pdfName = imagesPdf.split("upload")[1];
+                            this.newIOSSClient.removeFile("upload" + pdfName);
+                        }
+                    }
+                    if (removeList.size() > 0) {
+                        //删除本地文件
+                        CommonUtil.removeFile(removeList);
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            if(middleInt != null){
+                album.setCodes(startInt + "~" + middleInt);
+            }else{
+                album.setCodes(startInt + "~" + (count - 1));
+            }
+            return R.status(albumService.updateById(album));
+        }
+        throw new ServiceException("相册不能为空");
+    }
 
 //	/**
 //	 * 新增或修改
@@ -433,7 +636,7 @@ public class AlbumController extends BladeController {
 //		return R.status(albumService.saveOrUpdate(album));
 //	}
 
-	
+
 //	/**
 //	 * 删除
 //	 */
@@ -445,13 +648,15 @@ public class AlbumController extends BladeController {
 //	}
 
 
+    @PostMapping("/remove")
+    @ApiOperationSupport(order = 7)
+    @ApiOperation(value = "逻辑删除", notes = "传入ids")
+    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam Long id) {
+        //同时删除关联关系
+        albumImagesService.remove(Wrappers.<AlbumImages>lambdaQuery()
+                .eq(AlbumImages::getAlbumId, id));
+        return R.status(albumService.removeById(id));
+    }
 
-	@PostMapping("/remove")
-	@ApiOperationSupport(order = 7)
-	@ApiOperation(value = "逻辑删除", notes = "传入ids")
-	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam Long id) {
-		return R.status(albumService.removeById(id));
-	}
 
-	
 }

+ 23 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/AlbumImagesMapper.java

@@ -0,0 +1,23 @@
+package org.springblade.manager.mapper;
+
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.ImageClassificationFile;
+import org.springblade.manager.entity.AlbumImages;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+
+/**
+* @author LHB
+* @description 针对表【m_album_images(相册与照片关联关系表)】的数据库操作Mapper
+* @createDate 2025-08-21 14:28:24
+* @Entity generator.domain.UAlbumImages
+*/
+public interface AlbumImagesMapper extends BaseMapper<AlbumImages> {
+
+    List<ImageClassificationFile> selectImageUrlByAlbumId(@Param("id") Long id);
+}
+
+
+
+

+ 21 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/AlbumImagesMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.manager.mapper.AlbumImagesMapper">
+
+    <resultMap id="BaseResultMap" type="org.springblade.manager.entity.AlbumImages">
+            <id property="id" column="id" />
+            <result property="albumId" column="album_id" />
+            <result property="imageId" column="image_id" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,album_id,image_id
+    </sql>
+    <select id="selectImageUrlByAlbumId" resultType="org.springblade.business.entity.ImageClassificationFile">
+        select b.* from m_album_images a
+        left join u_image_classification_file b on a.image_id = b.id
+        where a.album_id = #{id} and b.image_url is not null and b.is_deleted = 0
+    </select>
+</mapper>

+ 17 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/AlbumImagesService.java

@@ -0,0 +1,17 @@
+package org.springblade.manager.service;
+
+import org.springblade.business.entity.ImageClassificationFile;
+import org.springblade.manager.entity.AlbumImages;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+* @author LHB
+* @description 针对表【m_album_images(相册与照片关联关系表)】的数据库操作Service
+* @createDate 2025-08-21 14:28:24
+*/
+public interface AlbumImagesService extends IService<AlbumImages> {
+
+    List<ImageClassificationFile> selectImageUrlByAlbumId(Long id);
+}

+ 0 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IAlbumService.java

@@ -42,5 +42,4 @@ public interface IAlbumService extends BaseService<Album> {
 
 	IPage<AlbumVO> selectPage1(Long projectId, Long contractId, IPage<AlbumVO> page);
 
-	boolean update(AlbumDTO albumDTO);
 }

+ 30 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/AlbumImagesServiceImpl.java

@@ -0,0 +1,30 @@
+package org.springblade.manager.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.business.entity.ImageClassificationFile;
+import org.springblade.manager.entity.AlbumImages;
+import org.springblade.manager.service.AlbumImagesService;
+import org.springblade.manager.mapper.AlbumImagesMapper;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+* @author LHB
+* @description 针对表【m_album_images(相册与照片关联关系表)】的数据库操作Service实现
+* @createDate 2025-08-21 14:28:24
+*/
+@Service
+public class AlbumImagesServiceImpl extends ServiceImpl<AlbumImagesMapper, AlbumImages>
+    implements AlbumImagesService {
+
+    @Override
+    public List<ImageClassificationFile> selectImageUrlByAlbumId(Long id) {
+        return baseMapper.selectImageUrlByAlbumId(id);
+    }
+}
+
+
+
+

+ 0 - 77
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/AlbumServiceImpl.java

@@ -17,28 +17,14 @@
 package org.springblade.manager.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import org.springblade.common.utils.SnowFlakeUtil;
-import org.springblade.core.oss.model.BladeFile;
-import org.springblade.core.tool.utils.BeanUtil;
-import org.springblade.core.tool.utils.ResourceUtil;
-import org.springblade.core.tool.utils.StringUtil;
-import org.springblade.manager.dto.AlbumDTO;
 import org.springblade.manager.entity.Album;
-import org.springblade.manager.utils.FileUtils;
-import org.springblade.manager.utils.PhotoAndNegativeNumberFiller;
 import org.springblade.manager.vo.AlbumVO;
 import org.springblade.manager.mapper.AlbumMapper;
 import org.springblade.manager.service.IAlbumService;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springblade.resource.feign.NewIOSSClient;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.util.List;
 
 /**
@@ -55,9 +41,6 @@ public class AlbumServiceImpl extends BaseServiceImpl<AlbumMapper, Album> implem
 //		return page.setRecords(baseMapper.selectAlbumPage(page, album));
 //	}
 
-    @Autowired
-    private NewIOSSClient newIOSSClient;
-
     @Override
     public IPage<AlbumVO> selectPage1(Long projectId, Long contractId, IPage<AlbumVO> page) {
         Long count = baseMapper.selectCount(new LambdaQueryWrapper<>(Album.class).eq(Album::getProjectId, projectId).eq(Album::getContractId, contractId));
@@ -67,64 +50,4 @@ public class AlbumServiceImpl extends BaseServiceImpl<AlbumMapper, Album> implem
         return page;
     }
 
-    @Override
-    public boolean update(AlbumDTO albumDTO) {
-        Album album = new Album();
-        BeanUtil.copy(albumDTO, album);
-        String dateValue = albumDTO.getDateValue();
-        String[] strings = dateValue.split("~");
-        album.setStartDate(strings[0]);
-        album.setEndDate(strings[1]);
-
-        //pdf文件
-        String imagesPdf = albumDTO.getImagesPdf();
-        String codes = albumDTO.getCodes();
-
-        //起止编号
-        Integer startInt = null , endInt = null;
-        if (StringUtil.isNotBlank(codes)) {
-            startInt = 1;
-        } else if (codes.contains("~")){
-            //存在起止值
-            String[] split = codes.split("~");
-            startInt = Integer.valueOf(split[0]);
-            endInt = Integer.valueOf(split[1]);
-        } else{
-            startInt = Integer.valueOf(codes);
-        }
-
-
-
-        try {
-            //写入临时文件 在上传到oss 再删除旧文件和临时文件
-            try {
-                String filePath = FileUtils.getSysLocalFileUrl();
-                Long id = SnowFlakeUtil.getId();
-                String trialPdf = filePath + "/pdf/" + id + ".pdf";
-                //旧pdf 新pdf 开始编号 结束编号 分组号
-                int endValue = PhotoAndNegativeNumberFiller.fillNumbers(imagesPdf, trialPdf, startInt, endInt, albumDTO.getGroupNumber());
-                File trialPdf2 = ResourceUtil.getFile(trialPdf);
-
-                if (trialPdf2.exists()) {
-                    trialPdf2.delete();
-                }
-                //合并日志pdf
-                BladeFile bladeFile = this.newIOSSClient.uploadFile(id + ".pdf", trialPdf);
-                if (bladeFile != null && ObjectUtils.isNotEmpty(bladeFile.getLink())) {
-                    album.setCodes(startInt + "~" + endValue);
-                    album.setImagesPdf(bladeFile.getLink());
-
-                    //删除旧pdf
-                    String pdfName = imagesPdf.split("upload")[1];
-                    this.newIOSSClient.removeFile("upload" + pdfName);
-                }
-
-                return updateById(album);
-            } catch (FileNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
 }

+ 0 - 178
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/PhotoAndNegativeNumberFiller.java

@@ -1,178 +0,0 @@
-package org.springblade.manager.utils;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.apache.pdfbox.pdmodel.PDPageContentStream;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.font.PDType1Font;
-import org.apache.pdfbox.text.PDFTextStripper;
-import org.apache.pdfbox.text.TextPosition;
-import org.springblade.common.utils.CommonUtil;
-import org.springblade.manager.service.impl.AlbumServiceImpl;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-/**
- * 识别pdf 照片号和底片号
- * @author LHB
- */
-public class PhotoAndNegativeNumberFiller {
-    // 内部类用于存储标记位置信息
-    private static class MarkerPosition {
-        int pageIndex;
-        float x;
-        float y;
-        float width;
-        float height;
-        boolean isPhotoMarker; // true表示照片号,false表示底片号
-
-        MarkerPosition(int pageIndex, float x, float y, float width, float height, boolean isPhotoMarker) {
-            this.pageIndex = pageIndex;
-            this.x = x;
-            this.y = y;
-            this.width = width;
-            this.height = height;
-            this.isPhotoMarker = isPhotoMarker;
-        }
-    }
-
-
-    /**
-     * @param inputPath 旧pdf地址
-     * @param outputPath 新pdf地址
-     * @param initialValue 开始值
-     * @param endValue 结束值
-     * @param negativeNumber 底片号
-     * @throws IOException
-     */
-    public static int fillNumbers(String inputPath, String outputPath,
-                            int initialValue, Integer endValue,
-                            String negativeNumber) throws IOException {
-
-        List<MarkerPosition> markers = new ArrayList<>();
-        int currentPhotoNumber = initialValue;
-
-        try (PDDocument document = PDDocument.load(CommonUtil.getOSSInputStream(inputPath))) {
-            // 第一步:查找所有【照片号:】和【底片号:】标记的位置
-            PDFTextStripper stripper = new PDFTextStripper() {
-                private int currentPage = 0;
-
-                @Override
-                protected void startPage(PDPage page) throws IOException {
-                    super.startPage(page);
-                }
-
-                @Override
-                protected void writeString(String string, List<TextPosition> textPositions) throws IOException {
-                    /// 检查是否包含目标文本
-                    if (string.contains("照片号:")) {
-                        // 找到目标文本的位置
-                        for (TextPosition text : textPositions) {
-                            String unicode = text.getUnicode();
-                            if (unicode.contains(":")) {
-                                // 记录冒号后的位置
-                                float x = text.getXDirAdj() + text.getWidthDirAdj();
-                                float y = text.getYDirAdj();
-                                float width = text.getWidthDirAdj();
-                                float height = text.getHeightDir();
-
-                                markers.add(new MarkerPosition(
-                                        currentPage,
-                                        x, y, width, height, true
-                                ));
-                            }
-                        }
-                    }
-
-                    /// 检查是否包含目标文本
-                    if (string.contains("底片号:")) {
-                        // 找到目标文本的位置
-                        for (TextPosition text : textPositions) {
-                            String unicode = text.getUnicode();
-                            if (unicode.contains(":")) {
-                                // 记录冒号后的位置
-                                float x = text.getXDirAdj() + text.getWidthDirAdj();
-                                float y = text.getYDirAdj();
-                                float width = text.getWidthDirAdj();
-                                float height = text.getHeightDir();
-
-                                markers.add(new MarkerPosition(
-                                        currentPage,
-                                        x, y, width, height, false
-                                ));
-                            }
-                        }
-                    }
-                }
-
-                @Override
-                protected void endPage(PDPage page) throws IOException {
-                    super.endPage(page);
-                    currentPage++;
-                }
-            };
-
-            // 处理所有页面以查找标记
-            stripper.getText(document);
-
-            // 第二步:在标记位置填充号码
-            for (int i = 0; i < document.getNumberOfPages(); i++) {
-                PDPage page = document.getPage(i);
-                PDRectangle pageSize = page.getMediaBox();
-
-                // 收集当前页的所有标记
-                List<MarkerPosition> pageMarkers = new ArrayList<>();
-                for (MarkerPosition marker : markers) {
-                    if (marker.pageIndex == i) {
-                        pageMarkers.add(marker);
-                    }
-                }
-
-                if (!pageMarkers.isEmpty()) {
-                    try (PDPageContentStream contentStream = new PDPageContentStream(
-                            document, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
-
-                        contentStream.setFont(PDType1Font.HELVETICA, 10);
-                        contentStream.setNonStrokingColor(0, 0, 0); // 黑色
-
-                        // 计算并绘制号码
-                        for (MarkerPosition marker : pageMarkers) {
-
-                            if (endValue != null && currentPhotoNumber > endValue) {
-                                break;
-                            }
-
-                            // 调整坐标系统
-                            float x = marker.x + 2;
-                            float y = pageSize.getHeight() - marker.y - marker.height + 4;
-
-                            contentStream.beginText();
-                            contentStream.newLineAtOffset(x, y);
-
-                            if (marker.isPhotoMarker) {
-                                // 处理照片号
-                                if (endValue != null && currentPhotoNumber > endValue) {
-                                    continue; // 跳过超过结束值的照片号
-                                }
-
-                                contentStream.showText(String.valueOf(currentPhotoNumber));
-                                currentPhotoNumber++;
-                            } else {
-                                // 处理底片号
-                                contentStream.showText(negativeNumber);
-                            }
-
-                            contentStream.endText();
-                        }
-                    }
-                }
-            }
-
-            // 保存文档
-            document.save(outputPath);
-        }
-
-        return currentPhotoNumber - 1;
-    }
-}