浏览代码

项目导出

qianxb 1 年之前
父节点
当前提交
d81d4da160

+ 27 - 0
src/main/java/org/springblade/modules/project/controller/ProjectInfoController.java

@@ -3,18 +3,28 @@ package org.springblade.modules.project.controller;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.tenant.annotation.NonDS;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.FileUtil;
 import org.springblade.modules.project.pojo.dto.*;
 import org.springblade.modules.project.pojo.vo.*;
 import org.springblade.modules.project.service.IProjectInfoService;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.ResponseEntity;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.List;
+
 /**
  * @Param
  * @Author wangwl
@@ -165,5 +175,22 @@ public class ProjectInfoController extends BladeController {
         return projectInfoService.importProject(file);
     }
 
+    @GetMapping("/build-report")
+    @ApiOperationSupport(order = 18)
+    @Operation(summary = "项目生成报告", description = "传入年和季度,返回生成文件")
+    @Parameters({
+            @Parameter(name = "year", description = "年:2024",required = true),
+            @Parameter(name = "quarter", description = "季度:1234",required = true)
+    })
+    public ResponseEntity<FileSystemResource> buildReport(Integer year, Integer quarter, HttpServletResponse response) {
+        return projectInfoService.buildReport(year,quarter,response);
+    }
+
+    @GetMapping("/get-project-year")
+    @ApiOperationSupport(order = 19)
+    @Operation(summary = "获取项目所有年份", description = "返回所有年数组")
+    public R<List<Integer>> getProjectYear() {
+        return projectInfoService.getProjectYear();
+    }
 
 }

+ 2 - 0
src/main/java/org/springblade/modules/project/mapper/ProjectInfoMapper.java

@@ -69,4 +69,6 @@ public interface ProjectInfoMapper extends BaseMapper<ProjectInfo> {
     Long getBuildTotal(@Param("dto") ProjectInfoPageDTO dto);
 
     void deleteProgressByProjectId(@Param("projectId") Long id);
+
+    ProjectInfo getProjectYear();
 }

+ 4 - 0
src/main/java/org/springblade/modules/project/mapper/ProjectInfoMapper.xml

@@ -121,5 +121,9 @@
             and end_year &lt;= #{dto.endYear}
         </if>
     </select>
+    <select id="getProjectYear" resultType="org.springblade.modules.project.pojo.entity.ProjectInfo">
+        SELECT min(start_year) AS startYear, max(end_year) AS endYear
+        FROM d_project_info;
+    </select>
 
 </mapper>

+ 6 - 0
src/main/java/org/springblade/modules/project/mapper/ProjectInvestPlanMapper.java

@@ -26,8 +26,13 @@
 package org.springblade.modules.project.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import lombok.Data;
+import org.apache.ibatis.annotations.Param;
 import org.springblade.modules.project.pojo.entity.ProjectInfo;
 import org.springblade.modules.project.pojo.entity.ProjectInvestPlan;
+import org.springblade.modules.project.pojo.vo.ProjectInvestPlanVO2;
+
+import java.util.List;
 
 /**
  *  Mapper 接口
@@ -36,4 +41,5 @@ import org.springblade.modules.project.pojo.entity.ProjectInvestPlan;
  */
 public interface ProjectInvestPlanMapper extends BaseMapper<ProjectInvestPlan> {
 
+    List<ProjectInvestPlanVO2> getYearAllProject(@Param("year") Integer year);
 }

+ 8 - 0
src/main/java/org/springblade/modules/project/mapper/ProjectInvestPlanMapper.xml

@@ -2,4 +2,12 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.springblade.modules.project.mapper.ProjectInvestPlanMapper">
 
+    <select id="getYearAllProject" resultType="org.springblade.modules.project.pojo.vo.ProjectInvestPlanVO2">
+        select *,
+               (select duty_unit from d_project_info dpi where dpi.id = dpip.project_id) as dutyUnit,
+               (select project_type from d_project_info dpi where dpi.id = dpip.project_id) as projectType,
+               (select name from d_project_info dpi where dpi.id = dpip.project_id) as name
+        from d_project_invest_plan dpip
+        where is_deleted = 0 and plan_year = #{year}
+    </select>
 </mapper>

+ 29 - 0
src/main/java/org/springblade/modules/project/pojo/vo/ProjectInvestPlanVO2.java

@@ -0,0 +1,29 @@
+package org.springblade.modules.project.pojo.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.modules.project.pojo.entity.ProjectInvestPlan;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @Param   生成报告获取指定年计划,和项目个别字段
+ * @Author wangwl
+ * @Date 2024/4/8 11:45
+ **/
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ProjectInvestPlanVO2 extends ProjectInvestPlan {
+
+    @Schema(description = "责任单位")
+    private String dutyUnit;
+
+    @Schema(description = "项目类型")
+    private Integer projectType;
+
+    @Schema(description = "项目名称")
+    private String name;
+
+}

+ 43 - 0
src/main/java/org/springblade/modules/project/pojo/vo/ReportVO1.java

@@ -0,0 +1,43 @@
+package org.springblade.modules.project.pojo.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Param   报告-投资完成情况表
+ * @Author wangwl
+ * @Date 2024/8/5 15:40
+ **/
+@Data
+public class ReportVO1 {
+
+    @Schema(description = "年项目数")
+    private Integer yearProjectTotal;
+
+    @Schema(description = "年计划投资亿元")
+    private BigDecimal yearPlanInvest;
+
+    @Schema(description = "季度计划投资亿元")
+    private BigDecimal quarterPlanInvest;
+
+    @Schema(description = "季度完成投资亿元")
+    private BigDecimal quarterFinishedInvest;
+
+    @Schema(description = "季度环比")
+    private BigDecimal quarterCompare;
+
+    @Schema(description = "季度完成率")
+    private BigDecimal quarterFinishedRatio;
+
+    @Schema(description = "季度累计完成投资亿元")
+    private BigDecimal quarterAddFinishedInvest;
+
+    @Schema(description = "季度累计占全年计划")
+    private BigDecimal quarterAddRatioYearPlan;
+
+    @Schema(description = "超前/滞后")
+    private BigDecimal LeadOrLag;
+
+}

+ 54 - 0
src/main/java/org/springblade/modules/project/pojo/vo/ReportVO2.java

@@ -0,0 +1,54 @@
+package org.springblade.modules.project.pojo.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Param   报告-各板块完成情况
+ * @Author wangwl
+ * @Date 2024/8/5 15:40
+ **/
+@Data
+public class ReportVO2 {
+
+    @Schema(description = "季度")
+    private Integer quarter;
+
+    @Schema(description = "季度完成投资亿元")
+    private BigDecimal quarterFinishedInvest;
+
+    @Schema(description = "季度完成率")
+    private BigDecimal quarterFinishedRatio;
+
+    @Schema(description = "季度累计完成投资亿元")
+    private BigDecimal quarterAddFinishedInvest;
+
+    @Schema(description = "季度累计占全年计划")
+    private BigDecimal quarterAddRatioYearPlan;
+
+    @Schema(description = "多少个项目投资进度超前")
+    private Integer advanceProjectTotal;
+
+    @Schema(description = "超前项目分别是")
+    private String advanceProject;
+
+    @Schema(description = "多少个项目投资进度滞后")
+    private Integer lagProjectTotal;
+
+    @Schema(description = "滞后项目分别是")
+    private String lagProject;
+
+    public ReportVO2() {
+        this.quarterFinishedInvest = BigDecimal.ZERO;
+        this.quarterFinishedRatio = BigDecimal.ZERO;
+        this.quarterAddFinishedInvest = BigDecimal.ZERO;
+        this.quarterAddRatioYearPlan = BigDecimal.ZERO;
+        this.advanceProjectTotal = 0;
+        this.advanceProject = "";
+        this.lagProjectTotal = 0;
+        this.lagProject = "";
+    }
+
+}

+ 49 - 0
src/main/java/org/springblade/modules/project/pojo/vo/ReportVO3.java

@@ -0,0 +1,49 @@
+package org.springblade.modules.project.pojo.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Param   报告-各板块完成情况的表格
+ * @Author wangwl
+ * @Date 2024/8/5 15:40
+ **/
+@Data
+public class ReportVO3 {
+
+    @Schema(description = "一季度投资完成率")
+    private BigDecimal oneInvestRatio;
+
+    @Schema(description = "一季度项目数")
+    private Integer oneProjectTotal;
+
+    @Schema(description = "二季度投资完成率")
+    private BigDecimal twoInvestRatio;
+
+    @Schema(description = "二季度项目数")
+    private Integer twoProjectTotal;
+
+    @Schema(description = "前两季度累计投资完成率")
+    private BigDecimal twoAggregateRatio;
+
+    @Schema(description = "三季度投资完成率")
+    private BigDecimal threeInvestRatio;
+
+    @Schema(description = "三季度项目数")
+    private Integer threeProjectTotal;
+
+    @Schema(description = "前三季度累计投资完成率")
+    private BigDecimal threeAggregateRatio;
+
+    @Schema(description = "四季度投资完成率")
+    private BigDecimal fourInvestRatio;
+
+    @Schema(description = "四季度项目数")
+    private Integer fourProjectTotal;
+
+    @Schema(description = "全年累计投资完成率")
+    private BigDecimal fourAggregateRatio;
+
+}

+ 9 - 0
src/main/java/org/springblade/modules/project/service/IProjectInfoService.java

@@ -2,13 +2,18 @@ package org.springblade.modules.project.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
 import org.springblade.core.mp.base.BaseService;
 import org.springblade.core.tool.api.R;
 import org.springblade.modules.project.pojo.dto.*;
 import org.springblade.modules.project.pojo.entity.ProjectInfo;
 import org.springblade.modules.project.pojo.vo.*;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.List;
+
 /**
  * @Param
  * @Author wangwl
@@ -46,4 +51,8 @@ public interface IProjectInfoService extends BaseService<ProjectInfo> {
     void repealWarning(ProjectRepealDTO dto);
 
     R importProject(MultipartFile file);
+
+    ResponseEntity<FileSystemResource> buildReport(Integer year, Integer quarter, HttpServletResponse response);
+
+    R<List<Integer>> getProjectYear();
 }

+ 4 - 0
src/main/java/org/springblade/modules/project/service/IProjectInvestPlanService.java

@@ -4,6 +4,9 @@ import org.springblade.core.mp.base.BaseService;
 import org.springblade.modules.project.pojo.dto.ProjectInfoDTO;
 import org.springblade.modules.project.pojo.entity.ProjectInfo;
 import org.springblade.modules.project.pojo.entity.ProjectInvestPlan;
+import org.springblade.modules.project.pojo.vo.ProjectInvestPlanVO2;
+
+import java.util.List;
 
 /**
  * @Param
@@ -12,4 +15,5 @@ import org.springblade.modules.project.pojo.entity.ProjectInvestPlan;
  **/
 public interface IProjectInvestPlanService extends BaseService<ProjectInvestPlan> {
 
+    List<ProjectInvestPlanVO2> getYearAllProject(Integer year);
 }

+ 760 - 3
src/main/java/org/springblade/modules/project/service/impl/ProjectInfoServiceImpl.java

@@ -5,17 +5,23 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.bstek.ureport.font.yahei.YaheiFontRegister;
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.HttpServletResponse;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.xwpf.usermodel.*;
+import org.bouncycastle.asn1.isismtt.x509.ProfessionInfo;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.FileUtil;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.modules.project.mapper.ProjectInfoMapper;
 import org.springblade.modules.project.pojo.dto.*;
 import org.springblade.modules.project.pojo.entity.*;
@@ -26,14 +32,19 @@ import org.springblade.modules.project.utils.ObjectUtils;
 import org.springblade.modules.project.utils.SnowFlakeUtil;
 import org.springblade.modules.system.service.IDictBizService;
 import org.springframework.beans.BeanUtils;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.nio.file.Paths;
 import java.text.DateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
@@ -41,6 +52,7 @@ import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.apache.poi.ss.usermodel.TableStyleType.headerRow;
 
@@ -651,7 +663,9 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
             //添加要修改年计划
             projectInvestFinished = projectInvestFinished.add(allInvestFinished);
             yearPlan.setYearFinishInvest(projectInvestFinished);
-            yearPlan.setYearUnfinishedInvest(year.getYearlyInvest().subtract(allInvestFinished));
+            if (year.getYearlyInvest() != null) {
+                yearPlan.setYearUnfinishedInvest(year.getYearlyInvest().subtract(allInvestFinished));
+            }
             updateYearPlan.add(yearPlan);
         }
         //修改年计划
@@ -1313,6 +1327,749 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
         return R.success("导入成功:新增"+add+"个项目,修改"+update+"个项目");
     }
 
+    @Override
+    public ResponseEntity<FileSystemResource> buildReport(Integer year, Integer quarter, HttpServletResponse response) {
+        //文件地址
+        String rootUrl = System.getProperty("user.dir")+ File.separator + "temporaryFile";
+        String tempFile = rootUrl + File.separator + "季度报告模板.docx";
+        System.out.println("模板地址:"+tempFile);
+        String fileName = year+"年"+quarter+"季度报告"+".docx";
+        String fileOutUrl = rootUrl+File.separator+fileName;
+        System.out.println(fileOutUrl);
+        //转换季度
+        String[] quarterValue = {"","一","二","三","四",};
+        String quarterZh = quarterValue[quarter];
+        //项目类型值
+        String[] typeValue = {"","高速公路","铁路","水运","枢纽","城市轨道","城市道路","民航"};
+        String[] typeValue2 = {"","(一)高速公路类型","(二)铁路类型","(三)水运类型","(四)枢纽类型","(五)城市轨道类型","(六)城市道路类型","(七)民航类型"};
+        /** 投资计划情况*/
+        //重大项目个数(当年所有项目)
+        List<ProjectInvestPlanVO2> projectList = investPlanService.getYearAllProject(year);
+        if (projectList.size() == 0){
+            throw new ServiceException(year+"年没有投资计划");
+        }
+        int projectTotal = projectList.size();
+        //计划总投资
+        BigDecimal currentYearlyPlanInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .map(ProjectInvestPlan::getYearlyInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        if (currentYearlyPlanInvest.equals(BigDecimal.ZERO)){
+            throw new ServiceException(year+"年没有投资计划,请重新选择时间");
+        }
+        //市交通运输委完成金额
+        BigDecimal trafficMoney = projectList.stream().filter(l -> l.getDutyUnit().contains("市交通建设委") && ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .map(ProjectInvestPlan::getYearlyInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //铁路公路等项目个数
+        long trafficTotal = projectList.stream().filter(l -> l.getDutyUnit().contains("市交通建设委") && "1,2,3,4,7".contains(l.getProjectType()+"")).count();
+        //市住房城乡建委完成金额
+        BigDecimal houseMoney = projectList.stream().filter(l -> l.getDutyUnit().contains("市住房城乡建委") && ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .map(ProjectInvestPlan::getYearlyInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //城市轨道和城市项目个数
+        long houseTotal = projectList.stream().filter(l -> l.getDutyUnit().contains("市住房城乡建委") && "5,6".contains(l.getProjectType()+"")).count();
+        //一季度计划完成投资
+        BigDecimal oneInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvest()) && l.getOneInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度计划完成投资
+        BigDecimal twoInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvest()) && l.getTwoInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度计划完成投资
+        BigDecimal threeInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvest()) && l.getThreeInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度计划完成投资
+        BigDecimal fourInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvest()) && l.getFourInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+
+
+        /** 投资完成情况表*/
+        //总计
+        ReportVO1 vo1 = this.calculateTableOne(projectList, quarter);
+        Map<String,ReportVO1> reportVOMap1 = new HashMap<>();
+        Map<String,ReportVO1> reportVOMap2 = new HashMap<>();
+        //当前季度完成投资
+        BigDecimal currentQuarterFinished = vo1.getQuarterFinishedInvest();
+        //当前季度完成投资率
+        BigDecimal currentQuarterFinishedRatio = vo1.getQuarterFinishedRatio();
+        //前几季度累计完成投资金额
+        BigDecimal frontQuarterFinished = vo1.getQuarterAddFinishedInvest();
+        //占全年投资计划
+        BigDecimal currentYearlyFinishedRatio = vo1.getQuarterAddRatioYearPlan();
+        //市交通运输委
+        List<ProjectInvestPlanVO2> traffics = projectList.stream().filter(l -> l.getDutyUnit().contains("市交通建设委") && ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .collect(Collectors.toList());
+        reportVOMap1.put("一、市交通运输委",this.calculateTableOne(traffics, quarter));
+        for (int i = 1; i < typeValue.length; i++) {
+            int j = i;
+            reportVOMap1.put(typeValue[i], this.calculateTableOne(traffics.stream().filter(l->l.getProjectType()==j).collect(Collectors.toList()), quarter));
+        }
+        //市住房城乡建委
+        List<ProjectInvestPlanVO2> houses = projectList.stream().filter(l -> l.getDutyUnit().contains("市住房城乡建委") && ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .collect(Collectors.toList());
+        reportVOMap2.put("二、市住房城乡建委",this.calculateTableOne(houses, quarter));
+        for (int i = 1; i < typeValue.length; i++) {
+            int j = i;
+            reportVOMap2.put(typeValue[i], this.calculateTableOne(houses.stream().filter(l->l.getProjectType()==j).collect(Collectors.toList()), quarter));
+        }
+
+        Set<String> heads1 = reportVOMap1.keySet();
+        Set<String> heads2 = reportVOMap2.keySet();
+        /** 各板块完成情况*/
+        //获取系统中配置的投资进展比例
+        ProjectWarning projectWarning = warningService.getOne(new LambdaQueryWrapper<ProjectWarning>()
+                .eq(ProjectWarning::getWarningType, 1));
+        if (ObjectUtil.isEmpty(projectWarning)){
+            throw new ServiceException("请先配置进展比例");
+        }
+        Map<String,ReportVO2> reportVO2Map = new HashMap<>();
+        List<List<ReportVO3>> VO3listList = new ArrayList<>();
+        for (int i = 1; i < typeValue2.length; i++) {
+            int j = i;
+            List<ProjectInvestPlanVO2> list = projectList.stream().filter(l -> l.getProjectType() == j).collect(Collectors.toList());
+            //插值
+            reportVO2Map.put(typeValue2[i], this.calculateTableProjectType(list, quarter));
+            //表单
+            VO3listList.add(this.calculateTableSeven(list,projectWarning));
+        }
+        Set<String> heads3 = reportVO2Map.keySet();
+
+        /** 读取模板文件*/
+        File directory = new File(rootUrl);
+        if (!directory.exists()) {
+            // mkdirs()方法会创建多级目录,mkdir()只创建单级目录
+            boolean created = directory.mkdirs();
+            if (!created){
+                throw new ServiceException("创建输出文件夹失败");
+            }
+        }
+        File outFile = new File(fileOutUrl);  // 加载Word模板
+        if (!outFile.exists()){
+            try {
+                boolean isCreate = outFile.createNewFile();
+                if (!isCreate){
+                    throw new ServiceException("创建输出文件失败");
+                }
+            } catch (IOException e) {
+                throw new ServiceException("创建输出文件失败");
+            }
+        }
+        try (
+            FileInputStream file = new FileInputStream(tempFile);
+            FileOutputStream outputStream = new FileOutputStream(outFile);
+            XWPFDocument document = new XWPFDocument(file);
+        ){
+            /** 表单插值*/
+            List<XWPFTable> tables = document.getTables();
+            //单独处理第一张表单
+            List<XWPFTableRow> tableRows = tables.get(0).getRows();
+            List<XWPFTableCell> tableCellList = tableRows.get(0).getTableCells();
+            XWPFRun xwpfRun = tableCellList.get(1).getParagraphs().get(0).getRuns().get(0);
+            xwpfRun.setText(year+"",0);
+            XWPFRun xwpfRun2 = tableCellList.get(2).getParagraphs().get(0).getRuns().get(0);
+            xwpfRun2.setText(quarterZh,0);
+            XWPFRun xwpfRun3 = tableCellList.get(3).getParagraphs().get(0).getRuns().get(1);
+            xwpfRun3.setText(quarterZh,0);
+            Integer tag = 0;
+            for (XWPFTableRow row : tableRows) {
+                List<XWPFTableCell> cells = row.getTableCells();
+                String rowHead = cells.get(0).getText().replaceAll("\\s*", "");
+                ReportVO1 rowData = null;
+                if (rowHead.contains("一、市交通运输委")){
+                    rowData = reportVOMap1.get("一、市交通运输委");
+                    tag = 1;
+                }else if (rowHead.contains("二、市住房城乡建委")){
+                    rowData = reportVOMap1.get("二、市住房城乡建委");
+                    tag = 2;
+                }
+                if (tag == 0 && "合计".equals(rowHead)){
+                    rowData = vo1;
+                }
+                if (tag == 1 && heads1.contains(rowHead)){
+                    rowData = reportVOMap1.get(rowHead);
+                }
+                if (tag == 2 && heads2.contains(rowHead)){
+                    rowData = reportVOMap2.get(rowHead);
+                }
+
+                if (rowData != null) {
+                    cells.get(1).getParagraphs().get(0).getRuns().get(0).setText(rowData.getYearProjectTotal() + "", 0);
+                    cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(rowData.getYearPlanInvest() + "", 0);
+                    cells.get(3).getParagraphs().get(0).getRuns().get(0).setText(rowData.getQuarterPlanInvest() + "", 0);
+                    cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(rowData.getQuarterFinishedInvest() + "", 0);
+                    cells.get(5).getParagraphs().get(0).getRuns().get(0).setText(rowData.getQuarterCompare() + "", 0);
+                    cells.get(6).getParagraphs().get(0).getRuns().get(0).setText(rowData.getQuarterFinishedRatio() + "", 0);
+                    cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(rowData.getQuarterAddFinishedInvest() + "", 0);
+                    cells.get(8).getParagraphs().get(0).getRuns().get(0).setText(rowData.getQuarterAddRatioYearPlan() + "", 0);
+                    cells.get(9).getParagraphs().get(0).getRuns().get(0).setText(rowData.getLeadOrLag() + "", 0);
+                }
+            }
+            //批量处理后面7张相同格式表单
+            for (int i = 1; i < tables.size(); i++) {
+                List<ReportVO3> vo3List = VO3listList.get(i - 1);
+                XWPFTable table = tables.get(i);
+                List<XWPFTableRow> rows = table.getRows();
+                //小计
+                ReportVO3 v1 = vo3List.get(0);
+                List<XWPFTableCell> cells = rows.get(2).getTableCells();
+                cells.get(1).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneInvestRatio().toString() , 0);
+                cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneProjectTotal().toString()  , 0);
+                cells.get(3).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoInvestRatio().toString() , 0);
+                cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoProjectTotal().toString() , 0);
+                cells.get(5).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoAggregateRatio().toString() , 0);
+                cells.get(6).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeInvestRatio().toString() , 0);
+                cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeProjectTotal().toString() , 0);
+                cells.get(8).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeAggregateRatio().toString() , 0);
+                cells.get(9).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourInvestRatio().toString() , 0);
+                cells.get(10).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourProjectTotal().toString() , 0);
+                cells.get(11).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourAggregateRatio().toString() , 0);
+                //正常
+                v1 = vo3List.get(1);
+                cells = rows.get(3).getTableCells();
+                cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneProjectTotal().toString()  , 0);
+                cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoProjectTotal().toString() , 0);
+                cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeProjectTotal().toString() , 0);
+                cells.get(10).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourProjectTotal().toString() , 0);
+                //超前
+                v1 = vo3List.get(2);
+                cells = rows.get(4).getTableCells();
+                cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneProjectTotal().toString() , 0);
+                cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoProjectTotal().toString() , 0);
+                cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeProjectTotal().toString() , 0);
+                cells.get(10).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourProjectTotal().toString() , 0);
+                //轻微滞后
+                v1 = vo3List.get(3);
+                cells = rows.get(5).getTableCells();
+                cells.get(1).getParagraphs().get(0).getRuns().get(1).setText(v1.getOneInvestRatio().toString() , 0);
+                cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneProjectTotal().toString() , 0);
+                cells.get(3).getParagraphs().get(0).getRuns().get(1).setText(v1.getTwoInvestRatio().toString() , 0);
+                cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoProjectTotal().toString() , 0);
+                cells.get(5).getParagraphs().get(0).getRuns().get(1).setText(v1.getTwoAggregateRatio().toString() , 0);
+                cells.get(6).getParagraphs().get(0).getRuns().get(1).setText(v1.getThreeInvestRatio().toString() , 0);
+                cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeProjectTotal().toString() , 0);
+                cells.get(8).getParagraphs().get(0).getRuns().get(1).setText(v1.getThreeAggregateRatio().toString() , 0);
+                cells.get(9).getParagraphs().get(0).getRuns().get(1).setText(v1.getFourInvestRatio().toString() , 0);
+                cells.get(10).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourProjectTotal().toString() , 0);
+                cells.get(11).getParagraphs().get(0).getRuns().get(1).setText(v1.getFourAggregateRatio().toString() , 0);
+                //中度滞后
+                v1 = vo3List.get(4);
+                cells = rows.get(6).getTableCells();
+                cells.get(1).getParagraphs().get(0).getRuns().get(1).setText(v1.getOneInvestRatio().toString() , 0);
+                cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneProjectTotal().toString() , 0);
+                cells.get(3).getParagraphs().get(0).getRuns().get(1).setText(v1.getTwoInvestRatio().toString() , 0);
+                cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoProjectTotal().toString() , 0);
+                cells.get(5).getParagraphs().get(0).getRuns().get(1).setText(v1.getTwoAggregateRatio().toString() , 0);
+                cells.get(6).getParagraphs().get(0).getRuns().get(1).setText(v1.getThreeInvestRatio().toString() , 0);
+                cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeProjectTotal().toString() , 0);
+                cells.get(8).getParagraphs().get(0).getRuns().get(1).setText(v1.getThreeAggregateRatio().toString() , 0);
+                cells.get(9).getParagraphs().get(0).getRuns().get(1).setText(v1.getFourInvestRatio().toString() , 0);
+                cells.get(10).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourProjectTotal().toString() , 0);
+                cells.get(11).getParagraphs().get(0).getRuns().get(1).setText(v1.getFourAggregateRatio().toString() , 0);
+                //严重滞后
+                v1 = vo3List.get(5);
+                cells = rows.get(7).getTableCells();
+                cells.get(1).getParagraphs().get(0).getRuns().get(1).setText(v1.getOneInvestRatio().toString() , 0);
+                cells.get(2).getParagraphs().get(0).getRuns().get(0).setText(v1.getOneProjectTotal().toString() , 0);
+                cells.get(3).getParagraphs().get(0).getRuns().get(1).setText(v1.getTwoInvestRatio().toString() , 0);
+                cells.get(4).getParagraphs().get(0).getRuns().get(0).setText(v1.getTwoProjectTotal().toString() , 0);
+                cells.get(5).getParagraphs().get(0).getRuns().get(1).setText(v1.getTwoAggregateRatio().toString() , 0);
+                cells.get(6).getParagraphs().get(0).getRuns().get(1).setText(v1.getThreeInvestRatio().toString() , 0);
+                cells.get(7).getParagraphs().get(0).getRuns().get(0).setText(v1.getThreeProjectTotal().toString() , 0);
+                cells.get(8).getParagraphs().get(0).getRuns().get(1).setText(v1.getThreeAggregateRatio().toString() , 0);
+                cells.get(9).getParagraphs().get(0).getRuns().get(1).setText(v1.getFourInvestRatio().toString() , 0);
+                cells.get(10).getParagraphs().get(0).getRuns().get(0).setText(v1.getFourProjectTotal().toString() , 0);
+                cells.get(11).getParagraphs().get(0).getRuns().get(1).setText(v1.getFourAggregateRatio().toString() , 0);
+            }
+
+            /** 文本插值*/
+            Integer status = 0;
+            ReportVO2 vo2 = new ReportVO2();
+            for (XWPFParagraph paragraph : document.getParagraphs()) {
+                String paragraphText = paragraph.getText();
+                if ("投资完成情况表".equals(paragraphText)){
+                    status = 1;
+                }
+                if (status == 0) {
+                    //paragraph为一个段落
+                    List<XWPFRun> runs = paragraph.getRuns();
+                    //runs为一个段落数据分词后集合
+                    for (XWPFRun run : runs) {
+                        String text = run.getText(0);
+                        if (text != null && text.contains("${")) {
+                            if (text.contains("${YEAR}")){
+                                text = text.replace("${YEAR}", year + "");
+                            } else if (text.contains("${QUARTERZH}")) {
+                                text = text.replace("${QUARTERZH}", quarterZh);
+                            } else if (text.contains("${PROJECTTOTAL}")) {
+                                text = text.replace("${PROJECTTOTAL}", projectTotal + "");
+                            } else if (text.contains("${CURRENTYEARLYPLANINVEST}")) {
+                                text = text.replace("${CURRENTYEARLYPLANINVEST}", currentYearlyPlanInvest + "");
+                            } else if (text.contains("${TRAFFICMONEY}")) {
+                                text = text.replace("${TRAFFICMONEY}", trafficMoney + "");
+                            } else if (text.contains("${TRAFFICTOTAL}")) {
+                                text = text.replace("${TRAFFICTOTAL}", trafficTotal + "");
+                            } else if (text.contains("${HOUSEMONEY}")) {
+                                text = text.replace("${HOUSEMONEY}", houseMoney + "");
+                            } else if (text.contains("${HOUSETOTAL}")) {
+                                text = text.replace("${HOUSETOTAL}", houseTotal + "");
+                            } else if (text.contains("${ONEINVEST}")) {
+                                text = text.replace("${ONEINVEST}", oneInvest + "");
+                            } else if (text.contains("${TWOINVEST}")) {
+                                text = text.replace("${TWOINVEST}", twoInvest + "");
+                            } else if (text.contains("${THREEINVEST}")) {
+                                text = text.replace("${THREEINVEST}", threeInvest + "");
+                            } else if (text.contains("${FOURINVEST}")) {
+                                text = text.replace("${FOURINVEST}", fourInvest + "");
+                            } else if (text.contains("${CURRENTQUARTERFINISHED}")) {
+                                text = text.replace("${CURRENTQUARTERFINISHED}", currentQuarterFinished + "");
+                            } else if (text.contains("${CURRENTQUARTERFINISHEDRATIO}")) {
+                                text = text.replace("${CURRENTQUARTERFINISHEDRATIO}", currentQuarterFinishedRatio + "");
+                            } else if (text.contains("${FRONTQUARTERFINISHED}")) {
+                                text = text.replace("${FRONTQUARTERFINISHED}", frontQuarterFinished + "");
+                            } else if (text.contains("${CURRENTYEARLYFINISHEDRATIO}")) {
+                                text = text.replace("${CURRENTYEARLYFINISHEDRATIO}", currentYearlyFinishedRatio + "");
+                            }
+                            run.setText(text, 0);
+                        }
+                    }
+                }else if (status == 1){
+                    if (heads3.contains(paragraphText)){
+                        vo2 = reportVO2Map.get(paragraphText);
+                    }
+                    List<XWPFRun> runs = paragraph.getRuns();
+                    //runs为一个段落数据分词后集合
+                    for (XWPFRun run : runs) {
+                        String text = run.getText(0);
+                        if (text != null && text.contains("${")) {
+                            switch (text){
+                                case "${QUARTERZH}":
+                                    text = text.replace("${QUARTERZH}", quarterZh);
+                                    break;
+                                case "${QUARTERFINISHEDINVEST}":
+                                    text = text.replace("${QUARTERFINISHEDINVEST}", vo2.getQuarterFinishedInvest().toString());
+                                    break;
+                                case "${QUARTERFINISHEDRATIO}":
+                                    text = text.replace("${QUARTERFINISHEDRATIO}", vo2.getQuarterFinishedRatio().toString());
+                                    break;
+                                case "${QUARTERADDFINISHEDINVEST}":
+                                    text = text.replace("${QUARTERADDFINISHEDINVEST}", vo2.getQuarterAddFinishedInvest().toString());
+                                    break;
+                                case "${QUARTERADDRATIOYEARPLAN}":
+                                    text = text.replace("${QUARTERADDRATIOYEARPLAN}", vo2.getQuarterAddRatioYearPlan().toString());
+                                    break;
+                                case "${ADVANCEPROJECTTOTAL}":
+                                    text = text.replace("${ADVANCEPROJECTTOTAL}", vo2.getAdvanceProjectTotal().toString());
+                                    break;
+                                case "${ADVANCEPROJECT}":
+                                    text = text.replace("${ADVANCEPROJECT}", vo2.getAdvanceProject());
+                                    break;
+                                case "${LAGPROJECTTOTAL}":
+                                    text = text.replace("${LAGPROJECTTOTAL}", vo2.getLagProjectTotal().toString());
+                                    break;
+                                case "${LAGPROJECT}":
+                                    text = text.replace("${LAGPROJECT}", vo2.getLagProject());
+                                    break;
+                            }
+                            run.setText(text, 0);
+                        }
+                    }
+                }
+            }
+            /** 写入指定位置,上传并返回URL*/
+            // 保存并关闭Word文件
+            document.write(outputStream);
+        } catch (Exception e) {
+            throw new ServiceException("生成报告失败:"+e.getMessage());
+        }
+        //返回响应
+
+
+        try {
+            FileSystemResource file = new FileSystemResource(fileOutUrl);
+            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
+            HttpHeaders headers = new HttpHeaders();
+            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
+            return ResponseEntity.ok()
+                    .headers(headers)
+                    .contentLength(file.contentLength())
+                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
+                    .body(file);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public R<List<Integer>> getProjectYear() {
+        ProjectInfo info = baseMapper.getProjectYear();
+        List<Integer> list = new ArrayList<>();
+        for (int i = info.getStartYear(); i <= info.getEndYear(); i++) {
+            list.add(i);
+        }
+        return R.data(list);
+    }
+
+    //计算项目7个类型的表单部分
+    private List<ReportVO3> calculateTableSeven(List<ProjectInvestPlanVO2> projectList,ProjectWarning projectWarning) {
+        BigDecimal oneHundred = new BigDecimal(100);
+        List<ReportVO3> list = new ArrayList<>();
+        /** 计划投资*/
+        //一季度计划完成投资
+        BigDecimal oneInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvest()) && l.getOneInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度计划完成投资
+        BigDecimal twoInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvest()) && l.getTwoInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度计划完成投资
+        BigDecimal threeInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvest()) && l.getThreeInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度计划完成投资
+        BigDecimal fourInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvest()) && l.getFourInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        /** 投资完成*/
+        //一季度完成投资
+        BigDecimal oneInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvestFinish()) && l.getOneInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度完成投资
+        BigDecimal twoInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvestFinish()) && l.getTwoInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度完成投资
+        BigDecimal threeInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvestFinish()) && l.getThreeInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度完成投资
+        BigDecimal fourInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvestFinish()) && l.getFourInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        //二季度累计计划投资
+        BigDecimal twoAddInvest = oneInvest.add(twoInvest);
+        //三季度累计计划投资
+        BigDecimal threeAddInvest = twoAddInvest.add(threeInvest);
+        //全年累计计划投资
+        BigDecimal fourAddInvest = threeAddInvest.add(fourInvest);
+
+        //二季度累计投资
+        BigDecimal twoAddInvestFinish = oneInvestFinish.add(twoInvestFinish);
+        //三季度累计投资
+        BigDecimal threeAddInvestFinish = twoAddInvestFinish.add(threeInvestFinish);
+        //全年累计投资
+        BigDecimal fourAddInvestFinish = threeAddInvestFinish.add(fourInvestFinish);
+
+        //小计
+        ReportVO3 v1 = new ReportVO3();
+        v1.setOneInvestRatio(oneInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : oneInvestFinish.multiply(
+                new BigDecimal(100)).divide(oneInvest,2,RoundingMode.HALF_UP));
+        v1.setOneProjectTotal((int) projectList.stream().filter(l->l.getIsOneInvestFinish() == 1).count());
+        v1.setTwoInvestRatio(twoInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : twoInvestFinish.multiply(
+                new BigDecimal(100)).divide(twoInvest,2,RoundingMode.HALF_UP));
+        v1.setTwoProjectTotal((int) projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1).count());
+        v1.setTwoAggregateRatio(twoAddInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : twoAddInvestFinish.multiply(
+                new BigDecimal(100)).divide(twoAddInvest,2,RoundingMode.HALF_UP));
+        v1.setThreeInvestRatio(threeInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : threeInvestFinish.multiply(
+                new BigDecimal(100)).divide(threeInvest,2,RoundingMode.HALF_UP));
+        v1.setThreeProjectTotal((int) projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1).count());
+        v1.setThreeAggregateRatio(threeAddInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : threeAddInvestFinish.multiply(
+                new BigDecimal(100)).divide(threeAddInvest,2,RoundingMode.HALF_UP));
+        v1.setFourInvestRatio(fourInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : fourInvestFinish.multiply(
+                new BigDecimal(100)).divide(fourInvest,2,RoundingMode.HALF_UP));
+        v1.setFourProjectTotal((int) projectList.stream().filter(l->l.getIsFourInvestFinish() == 1).count());
+        v1.setFourAggregateRatio(fourAddInvest.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : fourAddInvestFinish.multiply(
+                new BigDecimal(100)).divide(fourAddInvest,2,RoundingMode.HALF_UP));
+        list.add(v1);
+        //正常
+        ReportVO3 v2 = new ReportVO3();
+        v2.setOneProjectTotal((int) projectList.stream().filter(l->l.getIsOneInvestFinish() == 1 && l.getOneInvestRatio().compareTo(oneHundred) == 0).count());
+        v2.setTwoProjectTotal((int) projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1 && l.getTwoInvestRatio().compareTo(oneHundred) == 0).count());
+        v2.setThreeProjectTotal((int) projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1 && l.getThreeInvestRatio().compareTo(oneHundred) == 0).count());
+        v2.setFourProjectTotal((int) projectList.stream().filter(l->l.getIsFourInvestFinish() == 1 && l.getFourInvestRatio().compareTo(oneHundred) == 0).count());
+        list.add(v2);
+        //超前
+        ReportVO3 v3 = new ReportVO3();
+        v3.setOneProjectTotal((int) projectList.stream().filter(l->l.getIsOneInvestFinish() == 1 && l.getOneInvestRatio().compareTo(oneHundred) > 0).count());
+        v3.setTwoProjectTotal((int) projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1 && l.getTwoInvestRatio().compareTo(oneHundred) > 0).count());
+        v3.setThreeProjectTotal((int) projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1 && l.getThreeInvestRatio().compareTo(oneHundred) > 0).count());
+        v3.setFourProjectTotal((int) projectList.stream().filter(l->l.getIsFourInvestFinish() == 1 && l.getFourInvestRatio().compareTo(oneHundred) > 0).count());
+        list.add(v3);
+        //轻微滞后
+        ReportVO3 v4 = new ReportVO3();
+        v4.setOneInvestRatio(projectWarning.getOneThree());
+        v4.setOneProjectTotal((int) projectList.stream().filter(l->l.getIsOneInvestFinish() == 1
+                && l.getOneInvestRatio().compareTo(projectWarning.getOneThree()) > 0 && l.getOneInvestRatio().compareTo(oneHundred) < 0).count());
+        v4.setTwoInvestRatio(projectWarning.getTwoThree());
+        v4.setTwoProjectTotal((int) projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1
+                && l.getTwoInvestRatio().compareTo(projectWarning.getTwoThree()) > 0 && l.getTwoInvestRatio().compareTo(oneHundred) < 0).count());
+        v4.setTwoAggregateRatio(projectWarning.getTwoThreeAll());
+        v4.setThreeInvestRatio(projectWarning.getThreeThree());
+        v4.setThreeProjectTotal((int) projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1
+                && l.getThreeInvestRatio().compareTo(projectWarning.getThreeThree()) > 0 && l.getThreeInvestRatio().compareTo(oneHundred) < 0).count());
+        v4.setThreeAggregateRatio(projectWarning.getThreeThreeAll());
+        v4.setFourInvestRatio(projectWarning.getFourThree());
+        v4.setFourProjectTotal((int) projectList.stream().filter(l->l.getIsFourInvestFinish() == 1
+                && l.getFourInvestRatio().compareTo(projectWarning.getFourThree()) > 0 && l.getFourInvestRatio().compareTo(oneHundred) < 0).count());
+        v4.setFourAggregateRatio(projectWarning.getFourThreeAll());
+        list.add(v4);
+        //中度滞后
+        ReportVO3 v5 = new ReportVO3();
+        v5.setOneInvestRatio(projectWarning.getOneTwo());
+        v5.setOneProjectTotal((int) projectList.stream().filter(l->l.getIsOneInvestFinish() == 1
+                && l.getOneInvestRatio().compareTo(projectWarning.getOneTwo()) > 0 && l.getOneInvestRatio().compareTo(projectWarning.getOneThree()) < 0).count());
+        v5.setTwoInvestRatio(projectWarning.getTwoTwo());
+        v5.setTwoProjectTotal((int) projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1
+                && l.getTwoInvestRatio().compareTo(projectWarning.getTwoTwo()) > 0 && l.getTwoInvestRatio().compareTo(projectWarning.getTwoThree()) < 0).count());
+        v5.setTwoAggregateRatio(projectWarning.getTwoTwoAll());
+        v5.setThreeInvestRatio(projectWarning.getThreeTwo());
+        v5.setThreeProjectTotal((int) projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1
+                && l.getThreeInvestRatio().compareTo(projectWarning.getThreeTwo()) > 0 && l.getThreeInvestRatio().compareTo(projectWarning.getThreeThree()) < 0).count());
+        v5.setThreeAggregateRatio(projectWarning.getThreeTwoAll());
+        v5.setFourInvestRatio(projectWarning.getFourTwo());
+        v5.setFourProjectTotal((int) projectList.stream().filter(l->l.getIsFourInvestFinish() == 1
+                && l.getFourInvestRatio().compareTo(projectWarning.getFourTwo()) > 0 && l.getFourInvestRatio().compareTo(projectWarning.getFourThree()) < 0).count());
+        v5.setFourAggregateRatio(projectWarning.getFourTwoAll());
+        list.add(v5);
+        //严重滞后
+        ReportVO3 v6 = new ReportVO3();
+        v6.setOneInvestRatio(projectWarning.getOneOne());
+        v6.setOneProjectTotal((int) projectList.stream().filter(l->l.getIsOneInvestFinish() == 1
+                && l.getOneInvestRatio().compareTo(projectWarning.getOneOne()) < 0).count());
+        v6.setTwoInvestRatio(projectWarning.getTwoOne());
+        v6.setTwoProjectTotal((int) projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1
+                && l.getTwoInvestRatio().compareTo(projectWarning.getTwoOne()) > 0).count());
+        v6.setTwoAggregateRatio(projectWarning.getTwoOneAll());
+        v6.setThreeInvestRatio(projectWarning.getThreeOne());
+        v6.setThreeProjectTotal((int) projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1
+                && l.getThreeInvestRatio().compareTo(projectWarning.getThreeOne()) > 0).count());
+        v6.setThreeAggregateRatio(projectWarning.getThreeOneAll());
+        v6.setFourInvestRatio(projectWarning.getFourOne());
+        v6.setFourProjectTotal((int) projectList.stream().filter(l->l.getIsFourInvestFinish() == 1
+                && l.getFourInvestRatio().compareTo(projectWarning.getFourOne()) > 0).count());
+        v6.setFourAggregateRatio(projectWarning.getFourOneAll());
+        list.add(v6);
+        return list;
+    }
+
+    //计算项目7个类型的插值部分
+    private ReportVO2 calculateTableProjectType(List<ProjectInvestPlanVO2> projectList,Integer quarter) {
+        ReportVO2 vo2 = new ReportVO2();
+        if (projectList.size() == 0){
+            return vo2;
+        }
+        BigDecimal currentYearlyPlanInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .map(ProjectInvestPlan::getYearlyInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        /** 计划投资*/
+        //一季度计划完成投资
+        BigDecimal oneInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvest()) && l.getOneInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度计划完成投资
+        BigDecimal twoInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvest()) && l.getTwoInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度计划完成投资
+        BigDecimal threeInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvest()) && l.getThreeInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度计划完成投资
+        BigDecimal fourInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvest()) && l.getFourInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        /** 投资完成*/
+        //一季度完成投资
+        BigDecimal oneInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvestFinish()) && l.getOneInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度完成投资
+        BigDecimal twoInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvestFinish()) && l.getTwoInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度完成投资
+        BigDecimal threeInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvestFinish()) && l.getThreeInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度完成投资
+        BigDecimal fourInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvestFinish()) && l.getFourInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //当前季度完成投资
+        BigDecimal currentQuarterFinished = BigDecimal.ZERO;
+        //当前季度计划完成投资(实际为上面一到四季度的某个季度)
+        BigDecimal currentQuarterPlanInvest = BigDecimal.ZERO;
+        //当前季度完成投资率
+        BigDecimal currentQuarterFinishedRatio = BigDecimal.ZERO;
+        //前几季度累计完成投资金额
+        BigDecimal frontQuarterFinished = BigDecimal.ZERO;
+        //占全年投资计划
+        BigDecimal currentYearlyFinishedRatio = BigDecimal.ZERO;
+        //超前项目
+        List<ProjectInvestPlanVO2> advanceProjects = new ArrayList<>();
+        //滞后项目
+        List<ProjectInvestPlanVO2> lagProjects = new ArrayList<>();
+        switch (quarter){
+            case 1 : currentQuarterFinished = oneInvestFinish;
+                frontQuarterFinished = oneInvestFinish;
+                currentQuarterPlanInvest = oneInvest;
+                advanceProjects = projectList.stream().filter(l->l.getIsOneInvestFinish() == 1 && l.getOneInvestRatio().compareTo(new BigDecimal(100)) > 0)
+                        .collect(Collectors.toList());
+                lagProjects = projectList.stream().filter(l->l.getIsOneInvestFinish() == 1 && l.getOneInvestRatio().compareTo(new BigDecimal(100)) < 0)
+                        .collect(Collectors.toList());
+                break;
+            case 2 : currentQuarterFinished = twoInvestFinish;
+                frontQuarterFinished = oneInvestFinish.add(twoInvestFinish);
+                currentQuarterPlanInvest = twoInvest;
+                advanceProjects = projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1 && l.getTwoAggregateRatio().compareTo(new BigDecimal(100)) > 0)
+                        .collect(Collectors.toList());
+                lagProjects = projectList.stream().filter(l->l.getIsTwoInvestFinish() == 1 && l.getTwoAggregateRatio().compareTo(new BigDecimal(100)) < 0)
+                        .collect(Collectors.toList());
+                break;
+            case 3 : currentQuarterFinished = threeInvestFinish;
+                frontQuarterFinished = oneInvestFinish.add(threeInvestFinish).add(twoInvestFinish);
+                currentQuarterPlanInvest = threeInvest;
+                advanceProjects = projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1 && l.getThreeAggregateRatio().compareTo(new BigDecimal(100)) > 0)
+                        .collect(Collectors.toList());
+                lagProjects = projectList.stream().filter(l->l.getIsThreeInvestFinish() == 1 && l.getThreeAggregateRatio().compareTo(new BigDecimal(100)) < 0)
+                        .collect(Collectors.toList());
+                break;
+            case 4 : currentQuarterFinished = fourInvestFinish;
+                frontQuarterFinished = oneInvestFinish.add(twoInvestFinish).add(threeInvestFinish).add(fourInvestFinish);
+                currentQuarterPlanInvest = fourInvest;
+                advanceProjects = projectList.stream().filter(l->l.getIsFourInvestFinish() == 1 && l.getFourAggregateRatio().compareTo(new BigDecimal(100)) > 0)
+                        .collect(Collectors.toList());
+                lagProjects = projectList.stream().filter(l->l.getIsFourInvestFinish() == 1 && l.getFourAggregateRatio().compareTo(new BigDecimal(100)) < 0)
+                        .collect(Collectors.toList());
+                break;
+            default : throw new ServiceException("季度不在规定范围内");
+        }
+
+        if (currentQuarterFinished.compareTo(BigDecimal.ZERO) > 0){
+            currentQuarterFinishedRatio = currentQuarterFinished.multiply(new BigDecimal(100))
+                    .divide(currentQuarterPlanInvest,2, RoundingMode.HALF_UP);
+        }
+        if (frontQuarterFinished.compareTo(BigDecimal.ZERO) > 0){
+            currentYearlyFinishedRatio = frontQuarterFinished.multiply(new BigDecimal(100))
+                    .divide(currentYearlyPlanInvest,2, RoundingMode.HALF_UP);
+        }
+        //季度完成投资
+        vo2.setQuarterFinishedInvest(currentQuarterFinished);
+        //季度完成率
+        vo2.setQuarterFinishedRatio(currentQuarterFinishedRatio);
+        //前季度累计完成
+        vo2.setQuarterAddFinishedInvest(frontQuarterFinished);
+        //前季度累计完成占全年
+        vo2.setQuarterAddRatioYearPlan(currentYearlyFinishedRatio);
+        //多少个项目投资进度超前
+        //超前项目分别是
+        if (advanceProjects.size() > 0){
+            vo2.setAdvanceProjectTotal(advanceProjects.size());
+            vo2.setAdvanceProject(advanceProjects.stream().map(l->l.getName()).collect(Collectors.joining(",")));
+        }
+        //多少个项目投资进度滞后
+        //滞后项目分别是
+        if (lagProjects.size() > 0){
+            vo2.setLagProjectTotal(lagProjects.size());
+            vo2.setLagProject(lagProjects.stream().map(l->l.getName()).collect(Collectors.joining(",")));
+        }
+
+        return vo2;
+    }
+
+    private ReportVO1 calculateTableOne(List<ProjectInvestPlanVO2> projectList,Integer quarter) {
+        if (projectList.size() == 0){
+            return null;
+        }
+        ReportVO1 vo1 = new ReportVO1();
+        BigDecimal currentYearlyPlanInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getYearlyInvest()))
+                .map(ProjectInvestPlan::getYearlyInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        /** 计划投资*/
+        //一季度计划完成投资
+        BigDecimal oneInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvest()) && l.getOneInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度计划完成投资
+        BigDecimal twoInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvest()) && l.getTwoInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度计划完成投资
+        BigDecimal threeInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvest()) && l.getThreeInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度计划完成投资
+        BigDecimal fourInvest = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvest()) && l.getFourInvest().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvest).reduce(BigDecimal.ZERO, BigDecimal::add);
+        /** 投资完成*/
+        //一季度完成投资
+        BigDecimal oneInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getOneInvestFinish()) && l.getOneInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getOneInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //二季度完成投资
+        BigDecimal twoInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getTwoInvestFinish()) && l.getTwoInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getTwoInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //三季度完成投资
+        BigDecimal threeInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getThreeInvestFinish()) && l.getThreeInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getThreeInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //四季度完成投资
+        BigDecimal fourInvestFinish = projectList.stream().filter(l-> ObjectUtil.isNotEmpty(l.getFourInvestFinish()) && l.getFourInvestFinish().compareTo(BigDecimal.ZERO) != 0)
+                .map(ProjectInvestPlan::getFourInvestFinish).reduce(BigDecimal.ZERO, BigDecimal::add);
+        //当前季度完成投资
+        BigDecimal currentQuarterFinished = BigDecimal.ZERO;
+        //当前季度上一个季度完成投资(当第一季度时,则为0)
+        BigDecimal currentLastQuarterFinished = BigDecimal.ZERO;
+        //当前季度计划完成投资(实际为上面一到四季度的某个季度)
+        BigDecimal currentQuarterPlanInvest = BigDecimal.ZERO;
+        //当前季度完成投资率
+        BigDecimal currentQuarterFinishedRatio = BigDecimal.ZERO;
+        //前几季度累计计划投资金额
+        BigDecimal frontQuarterPlanInvest = BigDecimal.ZERO;
+        //前几季度累计完成投资金额
+        BigDecimal frontQuarterFinished = BigDecimal.ZERO;
+        //占全年投资计划
+        BigDecimal currentYearlyFinishedRatio = BigDecimal.ZERO;
+
+        switch (quarter){
+            case 1 : currentQuarterFinished = oneInvestFinish;
+                frontQuarterFinished = oneInvestFinish;
+                currentQuarterPlanInvest = oneInvest;
+                frontQuarterPlanInvest = oneInvest;
+                break;
+            case 2 : currentQuarterFinished = twoInvestFinish;
+                currentLastQuarterFinished = oneInvestFinish;
+                frontQuarterFinished = oneInvestFinish.add(twoInvestFinish);
+                currentQuarterPlanInvest = twoInvest;
+                frontQuarterPlanInvest = oneInvest.add(twoInvest);
+                break;
+            case 3 : currentQuarterFinished = threeInvestFinish;
+                currentLastQuarterFinished = twoInvestFinish;
+                frontQuarterFinished = oneInvestFinish.add(threeInvestFinish).add(twoInvestFinish);
+                currentQuarterPlanInvest = threeInvest;
+                frontQuarterPlanInvest = oneInvest.add(twoInvest).add(threeInvest);
+                break;
+            case 4 : currentQuarterFinished = fourInvestFinish;
+                currentLastQuarterFinished = threeInvestFinish;
+                frontQuarterFinished = oneInvestFinish.add(twoInvestFinish).add(threeInvestFinish).add(fourInvestFinish);
+                currentQuarterPlanInvest = fourInvest;
+                frontQuarterPlanInvest = threeInvest.add(oneInvest).add(twoInvest).add(fourInvest);
+                break;
+            default : throw new ServiceException("季度不在规定范围内");
+        }
+
+        if (currentQuarterFinished.compareTo(BigDecimal.ZERO) > 0){
+            currentQuarterFinishedRatio = currentQuarterFinished.multiply(new BigDecimal(100))
+                    .divide(currentQuarterPlanInvest,2, RoundingMode.HALF_UP);
+        }
+        if (frontQuarterFinished.compareTo(BigDecimal.ZERO) > 0){
+            currentYearlyFinishedRatio = frontQuarterFinished.multiply(new BigDecimal(100))
+                    .divide(currentYearlyPlanInvest,2, RoundingMode.HALF_UP);
+        }
+        //年
+        vo1.setYearProjectTotal(projectList.size());
+        vo1.setYearPlanInvest(currentYearlyPlanInvest);
+        //季度
+        vo1.setQuarterPlanInvest(currentQuarterPlanInvest);
+        vo1.setQuarterFinishedInvest(currentQuarterFinished);
+        //环比
+        if (currentLastQuarterFinished.compareTo(BigDecimal.ZERO) == 0 || currentQuarterFinished.compareTo(BigDecimal.ZERO) == 0){
+            vo1.setQuarterCompare(BigDecimal.ZERO);
+        }else {
+            vo1.setQuarterCompare(currentLastQuarterFinished.multiply(new BigDecimal(100))
+                            .divide(currentQuarterFinished,2, RoundingMode.HALF_UP));
+        }
+        vo1.setQuarterFinishedRatio(currentQuarterFinishedRatio);
+        vo1.setQuarterAddFinishedInvest(frontQuarterFinished);
+        vo1.setQuarterAddRatioYearPlan(currentYearlyFinishedRatio);
+        //超前或滞后
+        if (frontQuarterPlanInvest.compareTo(BigDecimal.ZERO) == 0) {
+            vo1.setLeadOrLag(BigDecimal.ZERO);
+        }else {
+            if (frontQuarterPlanInvest.compareTo(frontQuarterFinished) == 0){
+                vo1.setLeadOrLag(new BigDecimal(100));
+            }else {
+                vo1.setLeadOrLag(frontQuarterFinished.subtract(frontQuarterPlanInvest).multiply(new BigDecimal(100)).divide(frontQuarterPlanInvest,2,RoundingMode.HALF_UP));
+            }
+        }
+        return vo1;
+    }
+
     /**
      * 按照Map解析出指定格式的集合
      * @param file

+ 5 - 0
src/main/java/org/springblade/modules/project/service/impl/ProjectInvestPlanServiceImpl.java

@@ -7,6 +7,7 @@ import org.springblade.modules.project.mapper.ProjectInvestPlanMapper;
 import org.springblade.modules.project.pojo.dto.ProjectInfoDTO;
 import org.springblade.modules.project.pojo.entity.ProjectInfo;
 import org.springblade.modules.project.pojo.entity.ProjectInvestPlan;
+import org.springblade.modules.project.pojo.vo.ProjectInvestPlanVO2;
 import org.springblade.modules.project.service.IProjectInfoService;
 import org.springblade.modules.project.service.IProjectInvestPlanService;
 import org.springblade.modules.project.utils.ObjectUtils;
@@ -25,4 +26,8 @@ import java.util.List;
 @Service
 @AllArgsConstructor
 public class ProjectInvestPlanServiceImpl extends BaseServiceImpl<ProjectInvestPlanMapper, ProjectInvestPlan> implements IProjectInvestPlanService {
+    @Override
+    public List<ProjectInvestPlanVO2> getYearAllProject(Integer year) {
+        return baseMapper.getYearAllProject(year);
+    }
 }