Explorar el Código

导出关于文档等信息

chenendian hace 1 mes
padre
commit
da344d1b80

+ 48 - 1
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/controller/DecisionTaskController.java

@@ -6,10 +6,18 @@ import com.siwei.apply.domain.vo.DecisionTaskFilterVo;
 import com.siwei.apply.domain.vo.DecisionTaskVo;
 import com.siwei.apply.service.DecisionTaskService;
 import com.siwei.common.core.domain.R;
+import com.siwei.common.core.utils.StringUtils;
+import com.siwei.common.core.utils.file.FileUtils;
 import com.siwei.common.core.web.controller.BaseController;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.*;
 
+import javax.activation.MimetypesFileTypeMap;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.net.URLEncoder;
 import java.util.*;
 
 /**
@@ -21,6 +29,10 @@ import java.util.*;
 @RestController
 @RequestMapping("/decisionTask")
 public class DecisionTaskController extends BaseController {
+
+    @Value("${report_dir}")
+    private String reportDir;
+
     @Autowired
     private DecisionTaskService decisionTaskService;
 
@@ -103,6 +115,20 @@ public class DecisionTaskController extends BaseController {
             Map<String, Object> result = new HashMap<>();
             DecisionTask decisionTask = decisionTaskService.get(taskId);
             List<DecisionDetailsVo>  detailsList  = decisionTaskService.detailsList(taskId);
+
+            //这里生成当前任务分析报告
+            String reportPath = decisionTask.getReportPath();
+            if(StringUtils.isBlank(reportPath)) {
+                reportPath = reportDir + decisionTask.getName()+"/"+ decisionTask.getId () + ".docx";
+                decisionTaskService.getWordReport(detailsList, reportPath);
+                decisionTask.setReportPath(reportPath);
+
+                DecisionTaskVo updateTaskVo = new DecisionTaskVo();
+                updateTaskVo.setId(decisionTask.getId());
+                updateTaskVo.setReportPath(reportPath);
+                decisionTaskService.update(updateTaskVo);
+            }
+
             result.put("decisionTask", decisionTask);
             result.put("detailsList", detailsList);
             return R.ok(result);
@@ -111,7 +137,6 @@ public class DecisionTaskController extends BaseController {
         }
     }
 
-
     @GetMapping("/joinDetails")
     public R<Map<String, Object>> joinDetails(@RequestParam("joinId") String joinId,@RequestParam("detailsName") String detailsName,  @RequestParam("type") Integer type) {
         try {
@@ -123,6 +148,28 @@ public class DecisionTaskController extends BaseController {
     }
 
 
+    @GetMapping("/DownloadReport")
+    public void fileDownload(String filePath, HttpServletResponse response) throws IOException {
+        String realFileName = reportDir + filePath;
+
+        File file = new File(realFileName);
+        // 取得文件名。
+        String downloadName = file.getName();
+
+        int lastIndex = downloadName.lastIndexOf(".");
+        String extension = downloadName.substring(lastIndex + 1);
+        {
+            // 建议定义为静态常量,可复用
+            MimetypesFileTypeMap mimeTypeMap = new MimetypesFileTypeMap();
+            // 传入文件名,得到文件类型,判断失败则返回application/octet-stream
+            String contentType = mimeTypeMap.getContentType(downloadName.substring(lastIndex));
+            response.setCharacterEncoding("utf-8");
+            response.setContentType(contentType);
+            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(downloadName, "UTF-8"));
+            FileUtils.writeBytes(realFileName, response.getOutputStream());
+        }
+    }
+
 
 
 

+ 1 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/domain/vo/DecisionTaskVo.java

@@ -6,6 +6,7 @@ import java.math.BigDecimal;
 
 @Data
 public class DecisionTaskVo {
+    private String id;
     private String name;
     private String startTime;
     private String endTime;

+ 4 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/service/DecisionTaskService.java

@@ -26,4 +26,8 @@ public interface DecisionTaskService {
 
     Map<String,Object> getJoinDetails(String currentId,String detailsName,Integer type);
 
+    String getWordReport(List<DecisionDetailsVo> analyseResultList,String reportPath);
+
+
+
     }

+ 445 - 4
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/service/impl/DecisionTaskServiceImpl.java

@@ -15,11 +15,10 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.util.Units;
-import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.xwpf.usermodel.*;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -27,6 +26,7 @@ import javax.annotation.Resource;
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
 import java.io.*;
+import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -34,6 +34,7 @@ import java.util.stream.Collectors;
 @Slf4j
 @Service
 public class DecisionTaskServiceImpl implements DecisionTaskService {
+
     @Autowired
     private DecisionTaskMapper decisionTaskMapper;
 
@@ -138,6 +139,7 @@ public class DecisionTaskServiceImpl implements DecisionTaskService {
                     decisionTaskMapper.insertDecisionIntersection(param);
                 }
             });
+
             DecisionTask decisionTaskForUpdate = new DecisionTask();
             decisionTaskForUpdate.setId(decisionTask.getId());
             decisionTaskForUpdate.setStatus("2"); // 任务状态 0 创建 1 执行中 2 成功 3 失败
@@ -250,10 +252,448 @@ public class DecisionTaskServiceImpl implements DecisionTaskService {
             //todo 这里需要返回项目信息,根据nodeId
             return decisionTaskMapper.getJoinDetails(typeEnum.getTable(),typeEnum.getSourceId(),currentId);
         }
-
         return null;
     }
 
+    @Override
+    public String getWordReport(List<DecisionDetailsVo> analyseResultList,String reportPath) {
+        try {
+            createWordReport(analyseResultList,reportPath);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return reportPath;
+    }
+
+
+
+    /**
+     * 根据分析结果生成word报告
+     * @param analyseResultList
+     * @param reportPath
+     * @throws Exception
+     */
+    private void createWordReport(List<DecisionDetailsVo> analyseResultList, String reportPath) throws Exception {
+        if (CollectionUtils.isEmpty(analyseResultList)) {
+            throw new ServiceException("分析结果为空,无法生成报告");
+        }
+
+        XWPFDocument document = null;
+        OutputStream outputStream = null;
+        try {
+            document = new XWPFDocument();
+
+            // 1. 生成报告标题
+            addTitle(document, "分析报告");
+
+            // 2. 生成分析基本信息
+            DecisionDetailsVo firstVo = analyseResultList.get(0);
+            // 从dataList中获取第一个数据的node_id,用于获取分析范围的geom
+            String geom = null;
+            Double shapeArea = null;
+            String analyseName = null;
+            
+            if (CollectionUtils.isNotEmpty(firstVo.getDataList())) {
+                Map<String, Object> firstData = firstVo.getDataList().get(0);
+                String nodeId = (String) firstData.get("node_id");
+                if (StringUtils.isNotBlank(nodeId)) {
+                    // 根据nodeId查询任务信息获取geom和shapeArea
+                    DecisionTask task = decisionTaskMapper.get(nodeId);
+                    if (task != null) {
+                        geom = task.getGeom();
+                        shapeArea = task.getShapeArea() != null ? task.getShapeArea().doubleValue() : null;
+                        analyseName = task.getName();
+                    }
+                }
+            }
+
+            // 3. 生成分析信息段落
+            addParagraph(document, "\t分析名称:" + (StringUtils.isNotBlank(analyseName) ? analyseName : ""));
+            addParagraph(document, "\t分析范围:" + (shapeArea != null ? String.format("%.2f", shapeArea) : "0") + "㎡");
+
+            // 4. 生成分析范围图片
+            if (StringUtils.isNotBlank(geom)) {
+                generateAnalysisImage(document, geom);
+            }
+
+            // 5. 根据不同类型的分析结果生成表格
+            for (DecisionDetailsVo detailsVo : analyseResultList) {
+                generateAnalysisTable(document, detailsVo);
+            }
+
+            // 6. 输出文件
+            File fileDoc = new File(reportPath);
+
+            // 先创建父目录(如果不存在)
+            File parentDir = fileDoc.getParentFile();
+            if (parentDir != null && !parentDir.exists()) {
+                boolean created = parentDir.mkdirs();
+                if (!created) {
+                    throw new RuntimeException("创建目录失败: " + parentDir.getAbsolutePath());
+                }
+            }
+
+            if (fileDoc.exists()) {
+                FileUtils.forceDelete(fileDoc);
+            }
+            outputStream = new FileOutputStream(reportPath);
+            document.write(outputStream);
+            
+        } catch (Exception e) {
+            log.error("生成分析报告失败", e);
+            throw e;
+        } finally {
+            if (document != null) {
+                try {
+                    document.close();
+                } catch (Exception ex) {
+                    log.error("关闭文档失败", ex);
+                }
+            }
+            if (outputStream != null) {
+                try {
+                    outputStream.close();
+                } catch (IOException e) {
+                    log.error("关闭输出流失败", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * 添加标题
+     */
+    private void addTitle(XWPFDocument document, String title) {
+        XWPFParagraph paragraph = document.createParagraph();
+        paragraph.setAlignment(ParagraphAlignment.CENTER);
+        paragraph.setSpacingAfter(200);
+        XWPFRun run = paragraph.createRun();
+        run.setText(title);
+        run.setBold(true);
+        run.setFontSize(19);
+        run.setFontFamily("宋体");
+    }
+
+    /**
+     * 添加普通段落
+     */
+    private void addParagraph(XWPFDocument document, String text) {
+        XWPFParagraph paragraph = document.createParagraph();
+        XWPFRun run = paragraph.createRun();
+        run.setText(text);
+        run.setFontSize(12);
+        run.setFontFamily("宋体");
+    }
+
+    /**
+     * 添加目录/章节标题
+     */
+    private void addCatalog(XWPFDocument document, String text) {
+        XWPFParagraph paragraph = document.createParagraph();
+        XWPFRun run = paragraph.createRun();
+        run.setText(text);
+        run.setBold(true);
+        run.setFontSize(14);
+        run.setFontFamily("宋体");
+    }
+
+    /**
+     * 生成分析范围图片
+     */
+    private void generateAnalysisImage(XWPFDocument document, String geom) throws Exception {
+        WktsVo wktsVo = new WktsVo();
+        List<WktsVo.WktInfo> wktInfos = new ArrayList<>();
+        WktsVo.WktInfo wktInfoData = new WktsVo.WktInfo();
+        wktInfoData.setWkt(geom);
+        wktInfos.add(wktInfoData);
+        wktsVo.setWktInfos(wktInfos);
+
+        Map<String, String> imageMap = this.getImage(wktsVo);
+        if (imageMap != null && imageMap.get("path") != null) {
+            String path = imageMap.get("path");
+            try (InputStream is = new FileInputStream(path)) {
+                BufferedImage bufferedImage = ImageIO.read(new File(path));
+                int originalWidth = bufferedImage.getWidth();
+                int originalHeight = bufferedImage.getHeight();
+                int useWidth = 400;
+                int useHeight = useWidth * originalHeight / originalWidth;
+                XWPFParagraph paragraph = document.createParagraph();
+                paragraph.setAlignment(ParagraphAlignment.CENTER);
+                XWPFRun run = paragraph.createRun();
+                run.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, null, Units.toEMU(useWidth), Units.toEMU(useHeight));
+            }
+        }
+    }
+
+    /**
+     * 根据分析类型生成对应的表格
+     */
+    private void generateAnalysisTable(XWPFDocument document, DecisionDetailsVo detailsVo) {
+        if (detailsVo == null || CollectionUtils.isEmpty(detailsVo.getDataList())) {
+            return;
+        }
+
+        Integer type = detailsVo.getType();
+        String typeName = detailsVo.getName();
+        List<Map<String, Object>> dataList = detailsVo.getDataList();
+
+        // 添加分析类型标题
+        addCatalog(document, "与" + typeName + "分析情况:");
+
+        // 根据类型获取对应的表格配置
+        List<NpoiHelper.TableTitle> tableTitles = getTableTitlesByType(type);
+        
+        // 准备表格数据
+        List<Map<String, Object>> tableData = prepareTableData(dataList, type);
+
+        // 生成表格
+        createTable(document, tableTitles, tableData);
+        
+        // 添加空行
+        document.createParagraph();
+    }
+
+    /**
+     * 创建表格
+     */
+    private void createTable(XWPFDocument document, List<NpoiHelper.TableTitle> tableTitles, 
+                             List<Map<String, Object>> tableData) {
+        if (CollectionUtils.isEmpty(tableTitles) || CollectionUtils.isEmpty(tableData)) {
+            return;
+        }
+
+        XWPFTable table = document.createTable(tableData.size() + 1, tableTitles.size());
+        table.setWidth("100%");
+
+        // 设置表头
+        XWPFTableRow headerRow = table.getRow(0);
+        for (int i = 0; i < tableTitles.size(); i++) {
+            NpoiHelper.TableTitle title = tableTitles.get(i);
+            XWPFTableCell cell = headerRow.getCell(i);
+            cell.setColor("DBE5F1");
+            
+            XWPFParagraph paragraph = cell.getParagraphs().get(0);
+            paragraph.setAlignment(title.getAlign() != null ? title.getAlign() : ParagraphAlignment.CENTER);
+            XWPFRun run = paragraph.createRun();
+            run.setText(title.getName());
+            run.setBold(true);
+            run.setFontSize(12);
+            run.setFontFamily("宋体");
+        }
+
+        // 设置数据行
+        for (int row = 0; row < tableData.size(); row++) {
+            XWPFTableRow tableRow = table.getRow(row + 1);
+            Map<String, Object> data = tableData.get(row);
+            
+            for (int col = 0; col < tableTitles.size(); col++) {
+                NpoiHelper.TableTitle title = tableTitles.get(col);
+                XWPFTableCell cell = tableRow.getCell(col);
+                
+                Object value = data.get(title.getKey());
+                String text = value != null ? value.toString() : "";
+                
+                // 处理小数位
+                if (title.getXsw() > -1 && value instanceof Number) {
+                    BigDecimal bd = new BigDecimal(value.toString());
+                    text = bd.setScale(title.getXsw(), BigDecimal.ROUND_HALF_UP).toString();
+                }
+                
+                XWPFParagraph paragraph = cell.getParagraphs().get(0);
+                paragraph.setAlignment(title.getAlign() != null ? title.getAlign() : ParagraphAlignment.LEFT);
+                XWPFRun run = paragraph.createRun();
+                run.setText(text);
+                run.setFontSize(12);
+                run.setFontFamily("宋体");
+            }
+        }
+    }
+
+    /**
+     * 根据分析类型获取表格标题配置
+     */
+    private List<NpoiHelper.TableTitle> getTableTitlesByType(Integer type) {
+        List<NpoiHelper.TableTitle> titles = new ArrayList<>();
+
+        // 序号列(所有类型通用)
+        NpoiHelper.TableTitle seqTitle = new NpoiHelper.TableTitle();
+        seqTitle.setKey("seq");
+        seqTitle.setName("序号");
+        seqTitle.setWidth(1276);
+        seqTitle.setAlign(ParagraphAlignment.CENTER);
+        titles.add(seqTitle);
+
+        if (type == null) {
+            return titles;
+        }
+
+        switch (type) {
+            case 4: // 所有权宗地
+            case 5: // 使用权宗地
+                // 宗地代码
+                NpoiHelper.TableTitle zddmTitle = new NpoiHelper.TableTitle();
+                zddmTitle.setKey("zddm");
+                zddmTitle.setName("宗地代码");
+                zddmTitle.setWidth(2484);
+                zddmTitle.setAlign(ParagraphAlignment.CENTER);
+                titles.add(zddmTitle);
+
+                // 重叠面积
+                NpoiHelper.TableTitle areaTitle = new NpoiHelper.TableTitle();
+                areaTitle.setKey("shapearea");
+                areaTitle.setName("重叠面积");
+                areaTitle.setWidth(1880);
+                areaTitle.setAlign(ParagraphAlignment.CENTER);
+                areaTitle.setXsw(2); // 保留2位小数
+                titles.add(areaTitle);
+
+                // 权利人
+                NpoiHelper.TableTitle qlrTitle = new NpoiHelper.TableTitle();
+                qlrTitle.setKey("qlrsjsyrlxm");
+                qlrTitle.setName("权利人");
+                qlrTitle.setWidth(1880);
+                qlrTitle.setAlign(ParagraphAlignment.CENTER);
+                titles.add(qlrTitle);
+                break;
+
+            case 6: // 供地数据/土地供应数据
+                // 受让方
+                NpoiHelper.TableTitle srfTitle = new NpoiHelper.TableTitle();
+                srfTitle.setKey("srf");
+                srfTitle.setName("受让方");
+                srfTitle.setWidth(2484);
+                srfTitle.setAlign(ParagraphAlignment.CENTER);
+                titles.add(srfTitle);
+
+                // 重叠面积
+                NpoiHelper.TableTitle tdgyAreaTitle = new NpoiHelper.TableTitle();
+                tdgyAreaTitle.setKey("shapearea");
+                tdgyAreaTitle.setName("重叠面积");
+                tdgyAreaTitle.setWidth(1880);
+                tdgyAreaTitle.setAlign(ParagraphAlignment.CENTER);
+                tdgyAreaTitle.setXsw(2);
+                titles.add(tdgyAreaTitle);
+
+                // 供应年份/合同日期
+                NpoiHelper.TableTitle nfTitle = new NpoiHelper.TableTitle();
+                nfTitle.setKey("hbcrht_date");
+                nfTitle.setName("供应年份");
+                nfTitle.setWidth(1880);
+                nfTitle.setAlign(ParagraphAlignment.CENTER);
+                titles.add(nfTitle);
+                break;
+
+            case 7: // 报批数据/用地报批数据
+                // 项目名称
+                NpoiHelper.TableTitle xmmcTitle = new NpoiHelper.TableTitle();
+                xmmcTitle.setKey("project_name");
+                xmmcTitle.setName("项目名称");
+                xmmcTitle.setWidth(2484);
+                xmmcTitle.setAlign(ParagraphAlignment.CENTER);
+                titles.add(xmmcTitle);
+
+                // 重叠面积
+                NpoiHelper.TableTitle bpAreaTitle = new NpoiHelper.TableTitle();
+                bpAreaTitle.setKey("shapearea");
+                bpAreaTitle.setName("重叠面积");
+                bpAreaTitle.setWidth(1880);
+                bpAreaTitle.setAlign(ParagraphAlignment.CENTER);
+                bpAreaTitle.setXsw(2);
+                titles.add(bpAreaTitle);
+
+                // 项目类型
+                NpoiHelper.TableTitle xmlxTitle = new NpoiHelper.TableTitle();
+                xmlxTitle.setKey("xmlx");
+                xmlxTitle.setName("项目类型");
+                xmlxTitle.setWidth(1880);
+                xmlxTitle.setAlign(ParagraphAlignment.CENTER);
+                titles.add(xmlxTitle);
+                break;
+
+            default:
+                // 默认配置:显示所有数据的key和value
+                break;
+        }
+
+        return titles;
+    }
+
+    /**
+     * 准备表格数据
+     */
+    private List<Map<String, Object>> prepareTableData(List<Map<String, Object>> dataList, Integer type) {
+        List<Map<String, Object>> result = new ArrayList<>();
+        
+        if (CollectionUtils.isEmpty(dataList)) {
+            return result;
+        }
+
+        int seq = 1;
+        for (Map<String, Object> data : dataList) {
+            Map<String, Object> row = new HashMap<>();
+            row.put("seq", seq++);
+
+            if (type == 4 || type == 5) {
+                // 所有权/使用权宗地
+                row.put("zddm", getStringValue(data, "zddm"));
+                row.put("shapearea", getDoubleValue(data, "shapearea"));
+                row.put("qlrsjsyrlxm", getStringValue(data, "qlrsjsyrlxm"));
+            } else if (type == 6) {
+                // 供地数据
+                row.put("srf", getStringValue(data, "srf"));
+                row.put("shapearea", getDoubleValue(data, "shapearea"));
+                row.put("hbcrht_date", getStringValue(data, "hbcrht_date"));
+            } else if (type == 7) {
+                // 报批数据
+                row.put("project_name", getStringValue(data, "project_name"));
+                row.put("shapearea", getDoubleValue(data, "shapearea"));
+                row.put("xmlx", getStringValue(data, "xmlx"));
+            } else {
+                // 默认:复制所有数据
+                row.putAll(data);
+            }
+
+            result.add(row);
+        }
+
+        return result;
+    }
+
+    /**
+     * 获取字符串值
+     */
+    private String getStringValue(Map<String, Object> data, String key) {
+        if (data == null || key == null) {
+            return "";
+        }
+        Object value = data.get(key);
+        return value != null ? value.toString() : "";
+    }
+
+    /**
+     * 获取Double值
+     */
+    private Double getDoubleValue(Map<String, Object> data, String key) {
+        if (data == null || key == null) {
+            return 0.0;
+        }
+        Object value = data.get(key);
+        if (value == null) {
+            return 0.0;
+        }
+        if (value instanceof Number) {
+            return ((Number) value).doubleValue();
+        }
+        try {
+            return Double.parseDouble(value.toString());
+        } catch (NumberFormatException e) {
+            return 0.0;
+        }
+    }
+
+
+
+
 
 
     private void createReport(Map gdbhJgMap, String reportPath) throws Exception {
@@ -554,4 +994,5 @@ public class DecisionTaskServiceImpl implements DecisionTaskService {
 
 
 
+
 }

+ 1 - 1
siwei-modules/siwei-apply/src/main/resources/mapper/DecisionTaskMapper.xml

@@ -166,7 +166,7 @@
     </delete>
 
     <select id="getJoinDetails" resultType="map">
-        SELECT  d.*  FROM vector.${tableName}  d  WHERE   d.${fieldName}::varchar = #{fieldValue}
+        SELECT  d.*  FROM  ${tableName}  d  WHERE   d.${fieldName}::varchar = #{fieldValue}
     </select>