From 79c2d5fa54ca680f5fc439b3607d7f0482a2ff32 Mon Sep 17 00:00:00 2001
From: linwei <872216696@qq.com>
Date: Wed, 08 Jul 2026 19:55:17 +0800
Subject: [PATCH] feat(office): 添加ONLYOFFICE回调处理功能

---
 drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java |  149 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 141 insertions(+), 8 deletions(-)

diff --git a/drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java b/drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java
index 6e649c0..0a4a1dd 100644
--- a/drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java
+++ b/drone-ops/drone-resource/src/main/java/org/sxkj/resource/service/impl/AttachServiceImpl.java
@@ -23,6 +23,8 @@
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import io.minio.GetObjectArgs;
+import io.minio.MinioClient;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ibatis.annotations.Param;
@@ -41,6 +43,7 @@
 import org.sxkj.common.enums.AttachResultTypeEnum;
 import org.sxkj.common.enums.TypeOfOutcome;
 import org.sxkj.common.func.Streams;
+import org.sxkj.common.model.ResponseResult;
 import org.sxkj.common.query.PaginationUtils;
 import org.sxkj.common.redis.RedisOpsUtils;
 import org.sxkj.common.utils.*;
@@ -48,6 +51,7 @@
 import org.sxkj.resource.builder.OssBuilder;
 import org.sxkj.resource.dto.WaylineJobInfoQueryParam;
 import org.sxkj.resource.entity.Attach;
+import org.sxkj.resource.entity.Oss;
 import org.sxkj.resource.mapper.AttachMapper;
 import org.sxkj.resource.model.FileMetadataDTO;
 import org.sxkj.resource.model.MinioPojo;
@@ -63,6 +67,9 @@
 import org.sxkj.tools.model.TifConvertResult;
 
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
@@ -70,6 +77,9 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 /**
  * 附件表 服务实现类
@@ -106,7 +116,12 @@
 
 	@Override
 	public IPage<AttachVO> selectAttachPage(IPage<AttachVO> page, AttachPageParam attach) {
- 		List<AttachVO> attachVOS   = baseMapper.selectAttachPage(page, attach);
+		// 创建部门
+		if (!AuthUtil.isAdministrator()) {
+			List<Long> deptList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
+			attach.setDeptList(deptList);
+		}
+		List<AttachVO> attachVOS = baseMapper.selectAttachPage(page, attach);
 		return page.setRecords(attachVOS);
 	}
 
@@ -116,11 +131,11 @@
 		attach.setAreaCode(HeaderUtils.getAreaCodeHeaderAreaCode(attach.getAreaCode()));
 		if (Objects.isNull(attach.getResultTypes())) {
 			// 使用常量定义避免魔法数字
-			attach.setResultTypes(Arrays.asList(TypeOfOutcome.IMAGE.getType(),
-				TypeOfOutcome.VIDEO.getType(),
-				TypeOfOutcome.AI.getType(),
-				TypeOfOutcome.SURVEY.getType(),
-				TypeOfOutcome.PANORAMA.getType()));
+			// attach.setResultTypes(Arrays.asList(TypeOfOutcome.IMAGE.getType(),
+			// 	TypeOfOutcome.VIDEO.getType(),
+			// 	TypeOfOutcome.AI.getType(),
+			// 	TypeOfOutcome.SURVEY.getType(),
+			// 	TypeOfOutcome.PANORAMA.getType()));
 		}
 		List<Long> deptIdList = SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId()));
 		String permissionCondition = permissionBuilder.buildDataPermissionCondition(AuthUtil.getUserId(), "attach");
@@ -520,9 +535,8 @@
 	@Override
 	public Long findResultNumByJobId(String jobId) {
 		return baseMapper.selectCount(Wrappers.<Attach>lambdaQuery()
-			.eq(Attach::getIsGenerateAiImg, 0)
 			.eq(Attach::getIsDeleted, 0)
-			.eq(Attach::getWayLineJobId, jobId).in(Attach::getResultType, AttachResultTypeEnum.getTheAttachmentType()));
+			.eq(Attach::getPatrolTaskId, jobId).in(Attach::getResultType, AttachResultTypeEnum.getTheAttachmentType()));
 	}
 
 	@Override
@@ -770,4 +784,123 @@
 		return attachTypeStatisticsVOS;
 	}
 
+	/**
+	 * 下载附件
+	 *
+	 * @param param        下载参数
+	 * @param outputStream 输出流
+	 * @return 下载是否成功
+	 * @throws IOException IO异常
+	 */
+	@Override
+	public Boolean downloadByByte(String param, OutputStream outputStream) throws IOException {
+		// 步骤1:构建下载参数并获取附件列表
+		AttachmentDownloadParam attachmentDownloadParam = new AttachmentDownloadParam();
+		attachmentDownloadParam.setAttachIds(Func.toLongList(param));
+		List<AttachVO> attachList = getAttachList(attachmentDownloadParam);
+		if (CollectionUtils.isEmpty(attachList)) {
+			return false;
+		}
+
+		// 步骤2:获取当前租户ID
+		String tenantId = AuthUtil.getTenantId();
+		if (StringUtils.isBlank(tenantId)) {
+			tenantId = "000000";
+		}
+
+		// 步骤3:通过OssBuilder获取OSS配置
+		Oss oss = ossBuilder.getOss(tenantId, "");
+
+		try {
+			// 步骤4:创建ZipOutputStream并设置压缩级别
+			ZipOutputStream zos = new ZipOutputStream(outputStream);
+			zos.setLevel(Deflater.BEST_SPEED);
+
+			// 步骤5:设置缓冲区大小
+			final int BUFFER_SIZE = 1024 * 1024;
+			byte[] buffer = new byte[BUFFER_SIZE];
+
+			// 步骤6:根据OSS配置创建MinioClient
+			MinioClient minioClient = MinioClient.builder()
+				.endpoint(oss.getEndpoint())
+				.credentials(oss.getAccessKey(), oss.getSecretKey())
+				.build();
+
+			// 步骤7:创建文件名集合用于去重
+			Set<String> usedFileNames = new HashSet<>();
+
+			// 步骤8:遍历附件列表,逐个下载并打包
+			for (AttachVO attachVO : attachList) {
+				String objectName = attachVO.getName();
+				try {
+					// 步骤8.1:从MinIO获取文件流
+					InputStream is = minioClient.getObject(
+						GetObjectArgs.builder()
+							.bucket(oss.getBucketName())
+							.object(objectName)
+							.build());
+
+					// 步骤8.2:提取文件名(不包含路径)
+					String fileName = objectName.substring(objectName.lastIndexOf("/") + 1);
+
+					// 步骤8.3:处理文件名冲突
+					String uniqueFileName = fileName;
+					int counter = 1;
+					while (usedFileNames.contains(uniqueFileName)) {
+						int dotIndex = fileName.lastIndexOf(".");
+						if (dotIndex > 0) {
+							uniqueFileName = fileName.substring(0, dotIndex) + "_" + counter + fileName.substring(dotIndex);
+						} else {
+							uniqueFileName = fileName + "_" + counter;
+						}
+						counter++;
+					}
+
+					// 步骤8.4:记录已使用的文件名
+					usedFileNames.add(uniqueFileName);
+
+					// 步骤8.5:创建ZIP条目并写入文件内容
+					ZipEntry zipEntry = new ZipEntry(uniqueFileName);
+					zos.putNextEntry(zipEntry);
+
+					int length;
+					while ((length = is.read(buffer)) > 0) {
+						zos.write(buffer, 0, length);
+						zos.flush();
+					}
+
+					// 步骤8.6:关闭当前条目和输入流
+					zos.closeEntry();
+					is.close();
+				} catch (Exception e) {
+					log.error("处理文件 {} 失败: {}", objectName, e.getMessage());
+				}
+			}
+
+			// 步骤9:完成ZIP文件写入
+			zos.finish();
+			zos.flush();
+
+			return true;
+
+		} catch (Exception e) {
+			log.error("创建zip文件失败", e);
+			return false;
+		} finally {
+			// 步骤10:确保输出流被正确关闭
+			if (outputStream != null) {
+				try {
+					outputStream.flush();
+				} catch (IOException e) {
+					log.error("Error flushing output stream: {}", e.getMessage());
+				}
+				try {
+					outputStream.close();
+				} catch (IOException e) {
+					log.error("Error closing output stream: {}", e.getMessage());
+				}
+			}
+		}
+	}
+
 }

--
Gitblit v1.9.3