diff --git a/dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlert.java b/dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlert.java index e98774b..a78da95 100644 --- a/dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlert.java +++ b/dk-modules/business/src/main/java/org/dromara/business/domain/BusinessAlert.java @@ -257,4 +257,10 @@ public class BusinessAlert { //预警扩展施工信息 @TableField(exist = false) private BusinessAlertConstructInfoVo alertConstructInfoVo; + + /** + * 指南针 + */ + @TableField(exist = false) + private String icon; } diff --git a/dk-modules/business/src/main/java/org/dromara/business/feign/FeignDeviceGroup.java b/dk-modules/business/src/main/java/org/dromara/business/feign/FeignDeviceGroup.java index 21924a8..648aabe 100644 --- a/dk-modules/business/src/main/java/org/dromara/business/feign/FeignDeviceGroup.java +++ b/dk-modules/business/src/main/java/org/dromara/business/feign/FeignDeviceGroup.java @@ -22,4 +22,8 @@ public interface FeignDeviceGroup { @GetMapping("/device/flight/count") public Map getDevices(); + + @GetMapping("/media/api/v1/files/degree") + public Double getGimbalYawDegree(@RequestParam("fileId") String fileId); + } diff --git a/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java b/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java index bd99d4b..6e78ebb 100644 --- a/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java +++ b/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java @@ -24,12 +24,11 @@ import org.dromara.business.domain.BusinessAlertConstructInfo; import org.dromara.business.domain.bo.BusinessAlertBo; import org.dromara.business.domain.vo.BusinessAlertConstructInfoVo; import org.dromara.business.domain.vo.BusinessAlertVo; +import org.dromara.business.feign.FeignDeviceGroup; import org.dromara.business.mapper.BusinessAlertConstructInfoMapper; import org.dromara.business.mapper.BusinessAlertMapper; import org.dromara.business.service.IBusinessAlertService; -import org.dromara.business.utils.BatchProcessorUtil; -import org.dromara.business.utils.FreemarkerUtil; -import org.dromara.business.utils.MinioUntil; +import org.dromara.business.utils.*; import org.dromara.business.utils.constants.MinIOConstants; import org.dromara.common.core.enums.BusinessStatusEnum; import org.dromara.common.core.enums.FormatsType; @@ -39,7 +38,6 @@ import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.business.utils.MinioUtil; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.api.RemoteLabelPostService; import org.dromara.system.api.RemoteUserService; @@ -101,6 +99,9 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService { @DubboReference private RemoteUserService remoteUserService; + @Autowired + FeignDeviceGroup feignDeviceGroup; + /** * 新增预警任务 * @@ -833,7 +834,7 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService { //根据前端查询条件查询 List alertList = this.baseMapper.exportAlert(wrapper,ptPrefix); - + alertList = alertList.stream().filter(p-> !p.getHandleType().equalsIgnoreCase("cancel")).toList(); long todoCount = alertList.stream().filter(p -> p.getHandleType().equalsIgnoreCase("waiting")).count(); long finishCount = alertList.stream().filter(p -> p.getHandleType().equalsIgnoreCase("finish")).count(); @@ -852,33 +853,36 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService { alertList.parallelStream().forEach(businessAlert->{ try { - if (ObjectUtil.isNotEmpty(userIdMap.get(businessAlert.getAssignUserId()))){ - businessAlert.setAssignUserName(userIdMap.get(businessAlert.getAssignUserId()).get(0).getNickName()); + if (ObjectUtil.isNotEmpty(userIdMap.get(Long.valueOf(businessAlert.getAssignUserId())))){ + businessAlert.setAssignUserName(userIdMap.get(Long.valueOf(businessAlert.getAssignUserId())).get(0).getNickName()); } businessAlert.setHandleType(businessAlert.getHandleType().equalsIgnoreCase("waiting")?"未处理":businessAlert.getHandleType().equalsIgnoreCase("finish")?"已完结":businessAlert.getHandleType().equalsIgnoreCase("cancel")?"已忽略":"待验证"); if (businessAlert.getBusinessType() == 1){ businessAlert.setImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString())); - if (ObjectUtil.isEmpty(businessAlert.getImages())){ - log.info("images为null"); - } businessAlert.setMaxImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxImages(), 3600).toString())); - if (ObjectUtil.isEmpty(businessAlert.getMaxImages())){ - log.info("MaxImages为null"); - } businessAlert.setMaxMateSourceImgUrl(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxMateSourceImgUrl(), 3600).toString())); - if (ObjectUtil.isEmpty(businessAlert.getMaxMateSourceImgUrl())){ - log.info("MaxMateSourceImgUrl为null"); - } businessAlert.setMateSourceImgUrl(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMateSourceImgUrl(), 3600).toString())); - if (ObjectUtil.isEmpty(businessAlert.getMateSourceImgUrl())){ - log.info("MateSourceImgUrl为null"); - } }else { businessAlert.setImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString())); } + //获取指南针 + Double gimbalYawDegree = feignDeviceGroup.getGimbalYawDegree(businessAlert.getTaskImageId()); + if (ObjectUtil.isNotEmpty(gimbalYawDegree)){ + if (gimbalYawDegree < 0){ + gimbalYawDegree = gimbalYawDegree - 180; + }else { + gimbalYawDegree = 180 - gimbalYawDegree; + } + + log.info("旋转角度${}",gimbalYawDegree); + + String rotatedAndOverlayImage = ImageRotator.rotateAndOverlayImage(null, null, gimbalYawDegree); + businessAlert.setIcon(rotatedAndOverlayImage); + } + } catch (Exception e) { log.error(e.getMessage(),e); } diff --git a/dk-modules/business/src/main/java/org/dromara/business/utils/ImageRotator.java b/dk-modules/business/src/main/java/org/dromara/business/utils/ImageRotator.java new file mode 100644 index 0000000..6d2b843 --- /dev/null +++ b/dk-modules/business/src/main/java/org/dromara/business/utils/ImageRotator.java @@ -0,0 +1,125 @@ + +package org.dromara.business.utils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Base64; + +public class ImageRotator { + + /** + * 旋转图片并叠加到另一个图片上 + * @param sourceImagePath 源图片路径 + * @param targetImagePath 目标图片路径 + * @param angle 旋转角度(顺时针) + * @return 处理后的图片的Base64字符串 + */ + public static String rotateAndOverlayImage(String sourceImagePath, String targetImagePath, double angle) { + try { + URL resourceUrl = ImageRotator.class.getClassLoader().getResource("templates/1.png"); + URL targetUrl = ImageRotator.class.getClassLoader().getResource("templates/2.png"); + + // 读取源图片和目标图片 + BufferedImage sourceImage = ImageIO.read(new File(resourceUrl.getPath())); + BufferedImage targetImage = ImageIO.read(new File(targetUrl.getPath())); + + // 创建旋转后的图片 + BufferedImage rotatedImage = rotateImage(sourceImage, angle); + + // 创建新的画布,使用目标图片的尺寸 + BufferedImage resultImage = new BufferedImage( + targetImage.getWidth(), + targetImage.getHeight(), + BufferedImage.TYPE_INT_ARGB + ); + + // 创建图形上下文 + Graphics2D g2d = resultImage.createGraphics(); + + // 绘制目标图片 + g2d.drawImage(targetImage, 0, 0, null); + + // 计算旋转图片的位置(居中) + int x = (targetImage.getWidth() - rotatedImage.getWidth()) / 2; + int y = (targetImage.getHeight() - rotatedImage.getHeight()) / 2; + + // 绘制旋转后的图片 + g2d.drawImage(rotatedImage, x, y, null); + + // 释放图形上下文 + g2d.dispose(); + + // 转换为Base64 + return convertToBase64(resultImage); + + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /** + * 旋转图片 + * @param image 要旋转的图片 + * @param angle 旋转角度(顺时针) + * @return 旋转后的图片 + */ + private static BufferedImage rotateImage(BufferedImage image, double angle) { + double rads = Math.toRadians(angle); + double sin = Math.abs(Math.sin(rads)); + double cos = Math.abs(Math.cos(rads)); + + int w = image.getWidth(); + int h = image.getHeight(); + + int newWidth = (int) Math.floor(w * cos + h * sin); + int newHeight = (int) Math.floor(h * cos + w * sin); + + BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = rotated.createGraphics(); + + g2d.translate((newWidth - w) / 2, (newHeight - h) / 2); + g2d.rotate(rads, w / 2, h / 2); + g2d.drawImage(image, 0, 0, null); + g2d.dispose(); + + return rotated; + } + + /** + * 将图片转换为Base64字符串 + * @param image 要转换的图片 + * @return Base64字符串 + */ + private static String convertToBase64(BufferedImage image) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ImageIO.write(image, "jpeg", outputStream); + byte[] imageBytes = outputStream.toByteArray(); + return Base64.getEncoder().encodeToString(imageBytes); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + // 使用示例 + public static void main(String[] args) { + String sourceImagePath = "C:\\Users\\Administrator\\Desktop\\1.png"; // 源图片路径 + String targetImagePath = "C:\\Users\\Administrator\\Desktop\\2.png"; // 目标图片路径 + double angle = 90; // 旋转角度 + + String base64Result = rotateAndOverlayImage(sourceImagePath, targetImagePath, angle); + if (base64Result != null) { + System.out.println("处理成功,Base64结果:" + base64Result); + } else { + System.out.println("处理失败"); + } + } +} + diff --git a/dk-modules/business/src/main/resources/templates/1.png b/dk-modules/business/src/main/resources/templates/1.png new file mode 100644 index 0000000..b6a9e23 Binary files /dev/null and b/dk-modules/business/src/main/resources/templates/1.png differ diff --git a/dk-modules/business/src/main/resources/templates/2.png b/dk-modules/business/src/main/resources/templates/2.png new file mode 100644 index 0000000..c86474c Binary files /dev/null and b/dk-modules/business/src/main/resources/templates/2.png differ diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java index 6a91180..905b9fb 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java @@ -85,4 +85,15 @@ public class FileController { } return HttpResultResponse.success(filesList); } + + /** + * 根据文件id查询图片的偏航角 + * @param fileId + * @return + */ + @GetMapping("/degree") + @Operation(summary = "根据文件id查询图片的偏航角", description = "根据文件id查询图片的偏航角") + public Double getGimbalYawDegree(@RequestParam("fileId") String fileId) { + return fileService.getGimbalYawDegree(fileId); + } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java index 6ece33f..144bfb9 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java @@ -88,4 +88,6 @@ public interface IFileService { List getMediaFileDTO( String jobId,String fileType); String copyFile(String sourceBucket, String originFileUrl, String targetBucket); + + Double getGimbalYawDegree(String fileId); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java index 437abc1..8b2ae4d 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java @@ -201,6 +201,19 @@ public class FileServiceImpl implements IFileService { return fileUrl; } + + @Override + public Double getGimbalYawDegree(String fileId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(MediaFileEntity::getFileId, fileId); + List mediaFileEntities = mapper.selectList(wrapper); + if (ObjectUtil.isNotEmpty(mediaFileEntities)){ + return mediaFileEntities.get(0).getGimbalYawDegree(); + } + + return 0.0; + } + /** * Convert the received file object into a database entity object. * @param file