ソースを参照

添加巡检报告生成逻辑

Lucien 1 年間 前
コミット
8d2c9795de

+ 6 - 1
pom.xml

@@ -34,6 +34,7 @@
 		<minio.version>3.0.10</minio.version>
 		<commons.net.version>3.3</commons.net.version>
 		<com.jcraft.version>0.1.54</com.jcraft.version>
+		<freemarker.version>2.3.28</freemarker.version>
 	</properties>
 
 	<dependencies>
@@ -179,7 +180,11 @@
 		</dependency>
 
 
-
+		<dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+			<version>${freemarker.version}</version>
+		</dependency>
 	</dependencies>
 
 	<dependencyManagement>

+ 21 - 0
src/main/java/com/keystar/plane/inspection/bo/PlaneInspectionPicBo.java

@@ -0,0 +1,21 @@
+package com.keystar.plane.inspection.bo;
+
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe 报告结果图片实体类
+ */
+
+import lombok.Data;
+
+@Data
+public class PlaneInspectionPicBo {
+
+    //可见光图片minio地址(从bucket开始)
+    private String visible;
+
+    //红外minio地址(从bucket开始)
+    private String infrared;
+
+}

+ 26 - 0
src/main/java/com/keystar/plane/inspection/bo/PlaneInspectionResultBo.java

@@ -0,0 +1,26 @@
+package com.keystar.plane.inspection.bo;
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe 报告结果实体类
+ */
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class PlaneInspectionResultBo implements Serializable {
+
+    //巡检点序号
+    private String id;
+
+    //巡检点异常结果详情集合
+    private List<PlaneInspectionResultDetailBo> details;
+
+    //巡检点异常图片集合
+    private List<PlaneInspectionPicBo> pics;
+
+}

+ 30 - 0
src/main/java/com/keystar/plane/inspection/bo/PlaneInspectionResultDetailBo.java

@@ -0,0 +1,30 @@
+package com.keystar.plane.inspection.bo;
+
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe 报告结果详情实体类
+ */
+
+import lombok.Data;
+
+@Data
+public class PlaneInspectionResultDetailBo {
+
+    //序号
+    private String num;
+
+    //异常组串编号
+    private String name;
+
+    //是否二极管故障
+    private String dioe;
+
+    //是否热斑
+    private String htspte;
+
+    //是否掉串
+    private String oce;
+
+}

+ 201 - 0
src/main/java/com/keystar/plane/inspection/controller/ReportController.java

@@ -0,0 +1,201 @@
+package com.keystar.plane.inspection.controller;
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe 报告接口调用测试类
+ */
+
+import com.keystar.plane.inspection.bo.PlaneInspectionPicBo;
+import com.keystar.plane.inspection.bo.PlaneInspectionResultBo;
+import com.keystar.plane.inspection.bo.PlaneInspectionResultDetailBo;
+import com.keystar.plane.inspection.service.IReportService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping(value = "/report")
+@Slf4j
+public class ReportController {
+
+    @Autowired
+    private IReportService reportService;
+
+    @GetMapping("/test")
+    public void test() {
+
+        Map<String, String> mFlyCountMap = new HashMap<>();
+        //下面这些参数是查库得出, 所以不写在Service里面, 生成时候查库生成即可, 下面用到的都是测试数据
+        //本月飞行总架次
+        mFlyCountMap.put("TotalSortie", "10");
+        //有效巡检架次
+        mFlyCountMap.put("EffectiveSortie", "10");
+        //有效巡检天数
+        mFlyCountMap.put("EffectiveInspectionDate", "10");
+
+        Map<String, String> mSummaryMap = new HashMap<>();
+        //方阵总数(16不需要修改)
+        mSummaryMap.put("TotalFZ", "16");
+        //组串总数(4624不需要修改)
+        mSummaryMap.put("TotalPVString", "4624");
+        //光伏板总数(124848不需要修改)
+        mSummaryMap.put("TotalPVPanel", "124848");
+        //无人机巡检覆盖方阵数
+        mSummaryMap.put("CoveredFZ", "16");
+        //无人机巡检覆盖方阵百分比
+        mSummaryMap.put("CoveredFZPct", "100%");
+        //本月巡检覆盖组串总数
+        mSummaryMap.put("CoveredPVString", "4624");
+        //本月巡检覆盖组串百分比
+        mSummaryMap.put("CoveredPVStringPct", "100%");
+        //本月巡检覆盖光伏板总数
+        mSummaryMap.put("CoveredPVPanel", "124848");
+        //本月巡检覆盖光伏板百分比
+        mSummaryMap.put("CoveredPVPanelPct", "100%");
+        //无人机未巡检方阵数
+        mSummaryMap.put("UncoveredFZ", "0");
+        //无人机未巡检方阵百分比
+        mSummaryMap.put("UnCoveredFZPct", "0");
+        //本月未巡检组串总数
+        mSummaryMap.put("UncoveredPVString", "0");
+        //本月未巡检组串百分比
+        mSummaryMap.put("UncoveredPVStringPct", "0");
+        //本月未巡检光伏板总数
+        mSummaryMap.put("UncoveredPVPanel", "0");
+        //本月未巡检光伏板百分比
+        mSummaryMap.put("UncoveredPVPanelPct", "0");
+        //存在异常方阵数
+        mSummaryMap.put("FltFZ", "1");
+        //存在异常方阵百分比
+        mSummaryMap.put("FltFZPct", "10%");
+        //存在异常组串总数
+        mSummaryMap.put("FltPVString", "50");
+        //存在异常组串百分比
+        mSummaryMap.put("FltPVStringPct", "1%");
+        //存在异常光伏板总数
+        mSummaryMap.put("FltPVPanel", "12345");
+        //存在异常光伏板百分比
+        mSummaryMap.put("FltPVPanelPct", "9%");
+        //存在二极管故障的方阵数
+        mSummaryMap.put("DioFZ", "10");
+        //存在二极管故障的方阵百分比
+        mSummaryMap.put("DioFZPct", "1%");
+        //存在二极管故障的组串总数
+        mSummaryMap.put("DioPVString", "10");
+        //存在二极管故障的组串百分比
+        mSummaryMap.put("DioPVStringPct", "1%");
+        //存在二极管故障的光伏板总数
+        mSummaryMap.put("DioPVPanel", "10");
+        //存在二极管故障的光伏板百分比
+        mSummaryMap.put("DioPVPanelPct", "1%");
+        //存在热斑的方阵数
+        mSummaryMap.put("HtsptFZ", "10");
+        //存在热斑的方阵百分比
+        mSummaryMap.put("HtsptFZPct", "1%");
+        //存在热斑的组串总数
+        mSummaryMap.put("HtsptPVString", "10");
+        //存在热斑的组串百分比
+        mSummaryMap.put("HtsptPVStringPct", "1%");
+        //存在热斑的光伏板总数
+        mSummaryMap.put("HtsptPVPanel", "10");
+        //存在热斑的光伏板百分比
+        mSummaryMap.put("HtsptPVPanelPct", "1%");
+        //存在掉串的方阵数
+        mSummaryMap.put("OcFZ", "10");
+        //存在掉串的方阵百分比
+        mSummaryMap.put("OcFZPct", "1%");
+        //存在掉串的组串总数
+        mSummaryMap.put("OcPVString", "10");
+        //存在掉串的组串百分比
+        mSummaryMap.put("OcPVStringPct", "1%");
+        //存在掉串的光伏板总数
+        mSummaryMap.put("OcPVPanel", "10");
+        //存在掉串的光伏板百分比
+        mSummaryMap.put("OcPVPanelPct", "1%");
+
+        //下面这些可能要宇峰那边帮忙算
+        //月度损失电量
+        mSummaryMap.put("TotalLose", "111");
+        //二极管故障损失量
+        mSummaryMap.put("DioLose", "222");
+        //热斑损失电量
+        mSummaryMap.put("HtsptLose", "333");
+        //掉串损失电量
+        mSummaryMap.put("OcLose", "444");
+
+        //查库组装巡检结果集合传入函数即可
+        List<PlaneInspectionResultBo> planeInspectionResultBoList = new ArrayList<>();
+        PlaneInspectionResultBo planeInspectionResultBo = new PlaneInspectionResultBo();
+
+        planeInspectionResultBo.setId("1");
+        planeInspectionResultBo.setDetails(new ArrayList<>());
+        PlaneInspectionResultDetailBo planeInspectionResultDetailBo1 = new PlaneInspectionResultDetailBo();
+        planeInspectionResultDetailBo1.setNum("1");
+        planeInspectionResultDetailBo1.setName("FZ01-HL03");
+        planeInspectionResultDetailBo1.setDioe("1");
+        planeInspectionResultDetailBo1.setHtspte("0");
+        planeInspectionResultDetailBo1.setOce("1");
+        planeInspectionResultBo.getDetails().add(planeInspectionResultDetailBo1);
+        PlaneInspectionResultDetailBo planeInspectionResultDetailBo2 = new PlaneInspectionResultDetailBo();
+        planeInspectionResultDetailBo2.setNum("2");
+        planeInspectionResultDetailBo2.setName("FZ01-HL04");
+        planeInspectionResultDetailBo2.setDioe("0");
+        planeInspectionResultDetailBo2.setHtspte("1");
+        planeInspectionResultDetailBo2.setOce("0");
+        planeInspectionResultBo.getDetails().add(planeInspectionResultDetailBo2);
+
+        planeInspectionResultBo.setPics(new ArrayList<>());
+        PlaneInspectionPicBo planeInspectionPicBo1 = new PlaneInspectionPicBo();
+        planeInspectionPicBo1.setVisible(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-29-DJI_20230226144300_0006_THRM.jpg"));
+        planeInspectionPicBo1.setInfrared(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-38-DJI_20230226144304_0007_ZOOM.jpg"));
+        planeInspectionResultBo.getPics().add(planeInspectionPicBo1);
+        PlaneInspectionPicBo planeInspectionPicBo2 = new PlaneInspectionPicBo();
+        planeInspectionPicBo2.setVisible(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-34-DJI_20230226144302_0006_ZOOM.jpg"));
+        planeInspectionPicBo2.setInfrared(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-48-DJI_20230226144308_0010_THRM.jpg"));
+        planeInspectionResultBo.getPics().add(planeInspectionPicBo2);
+
+        planeInspectionResultBoList.add(planeInspectionResultBo);
+
+        PlaneInspectionResultBo planeInspectionResultBoNext = new PlaneInspectionResultBo();
+
+        planeInspectionResultBoNext.setId("2x");
+        planeInspectionResultBoNext.setDetails(new ArrayList<>());
+        PlaneInspectionResultDetailBo planeInspectionResultDetailBo3 = new PlaneInspectionResultDetailBo();
+        planeInspectionResultDetailBo3.setNum("3");
+        planeInspectionResultDetailBo3.setName("FZ03-HL03");
+        planeInspectionResultDetailBo3.setDioe("0");
+        planeInspectionResultDetailBo3.setHtspte("0");
+        planeInspectionResultDetailBo3.setOce("1");
+        planeInspectionResultBoNext.getDetails().add(planeInspectionResultDetailBo3);
+        PlaneInspectionResultDetailBo planeInspectionResultDetailBo4 = new PlaneInspectionResultDetailBo();
+        planeInspectionResultDetailBo4.setNum("4");
+        planeInspectionResultDetailBo4.setName("FZ03-HL04");
+        planeInspectionResultDetailBo4.setDioe("0");
+        planeInspectionResultDetailBo4.setHtspte("1");
+        planeInspectionResultDetailBo4.setOce("1");
+        planeInspectionResultBoNext.getDetails().add(planeInspectionResultDetailBo4);
+
+        planeInspectionResultBoNext.setPics(new ArrayList<>());
+        PlaneInspectionPicBo planeInspectionPicBo3 = new PlaneInspectionPicBo();
+        planeInspectionPicBo3.setInfrared(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-39-DJI_20230226144304_0008_THRM.jpg"));
+        planeInspectionPicBo3.setVisible(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-52-DJI_20230226144310_0010_ZOOM.jpg"));
+        planeInspectionResultBoNext.getPics().add(planeInspectionPicBo3);
+        PlaneInspectionPicBo planeInspectionPicBo4 = new PlaneInspectionPicBo();
+        planeInspectionPicBo4.setInfrared(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-35-DJI_20230226144302_0007_THRM.jpg"));
+        planeInspectionPicBo4.setVisible(reportService.pic2Base64FromMinio("/nest/photo/2420/1872/方阵13-16巡检任务0224-2023-02-26-15-18-42-DJI_20230226144306_0008_ZOOM.jpg"));
+        planeInspectionResultBoNext.getPics().add(planeInspectionPicBo4);
+
+        planeInspectionResultBoList.add(planeInspectionResultBoNext);
+
+        //生成报告主函数
+        reportService.createReport(mFlyCountMap, mSummaryMap, planeInspectionResultBoList);
+    }
+}

+ 20 - 0
src/main/java/com/keystar/plane/inspection/service/IReportService.java

@@ -0,0 +1,20 @@
+package com.keystar.plane.inspection.service;
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe 报告接口类
+ */
+
+import com.keystar.plane.inspection.bo.PlaneInspectionResultBo;
+
+import java.util.List;
+import java.util.Map;
+
+public interface IReportService {
+
+    void createReport(Map<String, String> mFlyCountMap, Map<String, String> mSummaryMap, List<PlaneInspectionResultBo> planeInspectionResultBoList);
+
+    String pic2Base64FromMinio(String minioAddr);
+
+}

+ 141 - 0
src/main/java/com/keystar/plane/inspection/service/impl/ReportServiceImpl.java

@@ -0,0 +1,141 @@
+package com.keystar.plane.inspection.service.impl;
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe 报告接口实现类
+ */
+
+import cn.hutool.core.text.CharSequenceUtil;
+import cn.hutool.core.util.StrUtil;
+import com.keystar.plane.inspection.bo.PlaneInspectionResultBo;
+import com.keystar.plane.inspection.service.IReportService;
+import freemarker.cache.ClassTemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.Version;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@Service
+@Slf4j
+public class ReportServiceImpl implements IReportService {
+
+    final MinioService minioService;
+
+    @Autowired
+    public ReportServiceImpl(MinioService minioService) {
+        this.minioService = minioService;
+    }
+
+    //具体参数参照报告关键词
+    @Override
+    public void createReport(Map<String, String> mFlyCountMap, Map<String, String> mSummaryMap, List<PlaneInspectionResultBo> planeInspectionResultBoList) {
+
+        try {
+
+            Calendar mCalendar = Calendar.getInstance();
+            mCalendar.setTime(new Date());
+
+            Map<String, Object> mValueMap = new HashMap<>();
+            //报告标题(不用改)
+            mValueMap.put("ReportTitle", "大唐安徽新能源唐阳光伏电站无人机智能巡检");
+            mCalendar.add(Calendar.MONTH, -1);
+            //报告福标题(已适配不用修改, 每个月生成一次, 可以每个月的第一天凌晨生成)
+            mValueMap.put("ReportSubTitle", new SimpleDateFormat("yyyy年MM月").format(mCalendar.getTime()) + " 光伏区月度巡检报告");
+            mCalendar.setTime(new Date());
+            //生成报告日期(已适配不用修改)
+            mValueMap.put("GenerateDate", new SimpleDateFormat("yyyy/MM/dd").format(mCalendar.getTime()));
+
+            //电站名字(不需要修改)
+            mValueMap.put("StationName", "大唐安徽新能源 唐阳光伏电站");
+            //电站占地(问钰尧拿数据后填死即可)
+            mValueMap.put("StationArea", "1000 亩");
+            //电站装机容量(问钰尧拿数据后填死即可)
+            mValueMap.put("StationInstalledCapacity", "50MW");
+            //巡检设备(不需要修改)
+            mValueMap.put("InspectionUAV", "DJI MK300 H20T");
+            //巡检类型(不需要修改)
+            mValueMap.put("InspectionType", "可见光、红外");
+
+            mValueMap.putAll(mFlyCountMap);
+
+            mValueMap.putAll(mSummaryMap);
+
+            mValueMap.put("pirs", planeInspectionResultBoList);
+
+
+            Configuration configuration = new Configuration(new Version("2.3.28"));
+            configuration.setDefaultEncoding(StandardCharsets.UTF_8.toString());
+
+            ClassTemplateLoader classTemplateLoader = new ClassTemplateLoader(this.getClass(), "/template/");
+            configuration.setTemplateLoader(classTemplateLoader);
+
+            Template template = configuration.getTemplate("report.ftl", StandardCharsets.UTF_8.toString());
+
+            Writer writer = null;
+
+            //todo: 记得修改路径和名字(这里后面确定路径后要挂载目录)
+            File mFile = new File("D:\\temp\\1.doc");
+            writer = new OutputStreamWriter(new FileOutputStream(mFile), StandardCharsets.UTF_8);
+
+            template.process(mValueMap, writer);
+
+            writer.flush();
+            writer.close();
+        }catch (Exception e) {
+            log.error(e.toString());
+        }
+
+    }
+
+    @Override
+    public String pic2Base64FromMinio(String minioAddr) {
+
+        String[] paths = StrUtil.splitToArray(minioAddr, "/");
+
+        InputStream inputStream = null;
+        ByteArrayOutputStream byteArrayOutputStream = null;
+
+        try {
+            inputStream = minioService.getObject(paths[1], StrUtil.sub(minioAddr,
+                    CharSequenceUtil.length(paths[1]) + 2, CharSequenceUtil.length(minioAddr)));
+
+            byteArrayOutputStream = new ByteArrayOutputStream();
+
+            byte[] bytes = new byte[10240];
+            int mReadLength = 0;
+
+            while ((mReadLength = inputStream.read(bytes)) != -1) {
+                byteArrayOutputStream.write(bytes, 0, mReadLength);
+            }
+
+            return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
+        }catch (Exception e) {
+
+        }finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                }catch (Exception e) {
+
+                }
+            }
+            if (byteArrayOutputStream != null) {
+                try {
+                    byteArrayOutputStream.close();
+                }catch (Exception e) {
+
+                }
+            }
+        }
+
+        return "";
+    }
+}

+ 116 - 0
src/main/java/com/keystar/plane/inspection/utils/Base64Util.java

@@ -0,0 +1,116 @@
+package com.keystar.plane.inspection.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Base64;
+
+/**
+ * @Author Lucien
+ * @Date 2023-03-02 08:00:00
+ * @Describe Java Base64编码通用工具类
+ */
+
+public class Base64Util {
+
+    public static final String UTF_8 = "UTF-8";
+    public static Base64.Encoder encoder;
+    //安全的编码方式, 替换“+” “/” “-”为“_”
+    public static Base64.Encoder urlEncoder;
+    public static Base64.Decoder decoder;
+    public static Base64.Decoder urlDecoder;
+
+    static {
+        encoder = Base64.getEncoder();
+        urlEncoder = Base64.getUrlEncoder();
+        decoder = Base64.getDecoder();
+        urlDecoder = Base64.getUrlDecoder();
+    }
+    //encode
+    public static byte[] encode(byte[] bytes) {
+        return encoder.encode(bytes);
+    }
+
+    public static String encode(String string) {
+        byte[] encode = encode(string.getBytes());
+        try {
+            return new String(encode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static String encode2String(byte[] bytes) {
+        return encoder.encodeToString(bytes);
+    }
+    public static byte[] encode2Byte(String string) {
+        return encode(string.getBytes());
+    }
+
+    //urlEncoder
+    public static byte[] urlEncode(byte[] bytes) {
+        return urlEncoder.encode(bytes);
+    }
+    public static String urlEncode(String string) {
+        byte[] encode = urlEncode(string.getBytes());
+        try {
+            return new String(encode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static String urlEncode2String(byte[] bytes) {
+        return urlEncoder.encodeToString(bytes);
+    }
+    public static byte[] urlEncode2Byte(String string) {
+        return urlEncode(string.getBytes());
+    }
+    //decode
+    public static byte[] decode(byte[] bytes) {
+        return decoder.decode(bytes);
+    }
+    public static byte[] decode2Byte(String string) {
+        return decoder.decode(string.getBytes());
+    }
+    public static String decode2String(byte[] bytes) {
+        try {
+            return new String(decoder.decode(bytes),UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static String decode(String string) {
+        byte[] decode = decode(string.getBytes());
+        try {
+            return new String(decode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    //urlDecode
+    public static byte[] urlDecode(byte[] bytes) {
+        return urlDecoder.decode(bytes);
+    }
+    public static byte[] urlDecode2Byte(String string) {
+        return urlDecode(string.getBytes());
+    }
+    public static String urlDecode2String(byte[] bytes) {
+        try {
+            return new String(urlDecode(bytes),UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static String urlDecode(String string) {
+        byte[] decode = urlDecode(string.getBytes());
+        try {
+            return new String(decode, UTF_8);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+}

ファイルの差分が大きいため隠しています
+ 6042 - 0
src/main/resources/template/report.ftl


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません