qianxb 1 éve
szülő
commit
f574f4206b

+ 20 - 3
src/main/java/org/springblade/modules/project/controller/ProjectInfoController.java

@@ -11,7 +11,9 @@ import org.springblade.core.tool.api.R;
 import org.springblade.modules.project.pojo.dto.*;
 import org.springblade.modules.project.pojo.vo.*;
 import org.springblade.modules.project.service.IProjectInfoService;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * @Param
@@ -24,8 +26,11 @@ import org.springframework.web.bind.annotation.*;
 @RequestMapping(  "/blade-attach/project")
 @Tag(name = "项目信息接口", description = "项目信息接口")
 public class ProjectInfoController extends BladeController {
+
     private final IProjectInfoService projectInfoService;
 
+    private final JdbcTemplate jdbcTemplate;
+
     @PostMapping("/add")
     @ApiOperationSupport(order = 1)
     @Operation(summary = "新增项目", description = "新增项目,传入项目信息和每一年的计划数组")
@@ -69,8 +74,8 @@ public class ProjectInfoController extends BladeController {
     @PostMapping("/update-project-finished")
     @ApiOperationSupport(order = 6)
     @Operation(summary = "修改项目完成情况", description = "修改项目完成情况,传入项目信息与计划年份和每年12个月的详情")
-    public R<String> updateFinished(@RequestBody ProjectAndPlanDetailDTO dto) {
-        projectInfoService.updateFinished(dto);
+    public R<String> updateFinished(@RequestBody ProjectAndPlanDetailVO vo) {
+        projectInfoService.updateFinished(vo);
         return R.success("修改成功");
     }
 
@@ -145,8 +150,20 @@ public class ProjectInfoController extends BladeController {
         return R.success("撤销成功");
     }
 
+    @PostMapping("/import-temp")
+    @ApiOperationSupport(order = 16)
+    @Operation(summary = "项目导入模板", description = "")
+    public R<String> importProject() {
+        String url = jdbcTemplate.queryForObject("select dict_value from blade_dict where code = 'project_template' and dict_key = 1 and is_deleted = 0", String.class);
+        return R.data(url);
+    }
 
-
+    @PostMapping("/import-project")
+    @ApiOperationSupport(order = 17)
+    @Operation(summary = "项目导入", description = "传入Excel")
+    public R importProject(MultipartFile file) {
+        return projectInfoService.importProject(file);
+    }
 
 
 }

+ 3 - 0
src/main/java/org/springblade/modules/project/pojo/entity/ProjectInvestPlan.java

@@ -154,5 +154,8 @@ public class ProjectInvestPlan extends BaseEntity {
     @Schema(description = "联系人")
     private String linkman;
 
+    @Schema(description = "联系电话")
+    private String phone;
+
 
 }

+ 124 - 0
src/main/java/org/springblade/modules/project/pojo/excel/ProjectImportExcel.java

@@ -0,0 +1,124 @@
+package org.springblade.modules.project.pojo.excel;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @Param   项目导入Excel,手动解析
+ * @Author wangwl
+ * @Date 2024/4/29 14:21
+ **/
+@Data
+public class ProjectImportExcel {
+    /* 项目计划 */
+    @Schema(description = "项目名称")
+    private String name;
+
+    @Schema(description = "建设规模")
+    private String buildScale;
+
+    @Schema(description = "建设规模单位1公里2空")
+    private Integer buildScaleUnit;
+
+    @Schema(description = "总投资")
+    private BigDecimal allInvestMoney;
+
+    @Schema(description = "项目阶段")
+    private Integer projectStage;
+
+    @Schema(description = "项目类型")
+    private Integer projectType;
+
+    @Schema(description = "开工年")
+    private Integer startYear;
+
+    @Schema(description = "完工年")
+    private Integer endYear;
+
+    @Schema(description = "责任单位")
+    private String dutyUnit;
+
+    @Schema(description = "是否重点项目")
+    private Integer isFocusProject;
+
+    @Schema(description = "是否试点任务")
+    private Integer isPilotPlan;
+
+    /* 年计划 */
+    @Schema(description = "计划年份")
+    private Integer planYear;
+
+    @Schema(description = "全年投资")
+    private BigDecimal yearlyInvest;
+
+    @Schema(description = "是否有计划")
+    private Integer isPlan;
+
+    @Schema(description = "是否填写计划")
+    private Integer isFillPlan;
+
+    @Schema(description = "一季度投资")
+    private BigDecimal oneInvest;
+
+    @Schema(description = "二季度投资")
+    private BigDecimal twoInvest;
+
+    @Schema(description = "三季度投资")
+    private BigDecimal threeInvest;
+
+    @Schema(description = "四季度投资")
+    private BigDecimal fourInvest;
+
+    @Schema(description = "全年目标")
+    private String yearlyTarget;
+
+    @Schema(description = "一季度计划")
+    private String onePlan;
+
+    @Schema(description = "二季度计划")
+    private String twoPlan;
+
+    @Schema(description = "三季度计划")
+    private String threePlan;
+
+    @Schema(description = "四季度计划")
+    private String fourPlan;
+
+    @Schema(description = "计划月份")
+    private Integer planMonth;
+
+    @Schema(description = "投资完成")
+    private BigDecimal investMoney;
+
+    @Schema(description = "工作进展情况")
+    private String workProgress;
+
+    @Schema(description = "累计进展情况")
+    private String workProgressAll;
+
+    @Schema(description = "进度百分比")
+    private BigDecimal planRatio;
+
+    @Schema(description = "存在问题")
+    private String questionable;
+
+    @Schema(description = "工作建议")
+    private String workAdvise;
+
+    @Schema(description = "联系人")
+    private String linkman;
+
+    @Schema(description = "联系电话")
+    private String phone;
+
+    @Schema(description = "是否已经存在,1存在0不存在")
+    private Boolean isExist;
+
+    @Schema(description = "项目id")
+    private Long projectId;
+
+    @Schema(description = "是否有完成计划")
+    private Boolean hasFinished;
+}

+ 12 - 0
src/main/java/org/springblade/modules/project/pojo/vo/ProjectInvestPlanVO.java

@@ -41,15 +41,27 @@ public class ProjectInvestPlanVO{
     @Schema(description = "一季度投资")
     private BigDecimal oneInvest;
 
+    @Schema(description = "一季度已投资")
+    private BigDecimal oneInvestFinish;
+
     @Schema(description = "二季度投资")
     private BigDecimal twoInvest;
 
+    @Schema(description = "二季度已投资")
+    private BigDecimal twoInvestFinish;
+
     @Schema(description = "三季度投资")
     private BigDecimal threeInvest;
 
+    @Schema(description = "三季度已投资")
+    private BigDecimal threeInvestFinish;
+
     @Schema(description = "四季度投资")
     private BigDecimal fourInvest;
 
+    @Schema(description = "四季度已投资")
+    private BigDecimal fourInvestFinish;
+
     @Schema(description = "一季度计划")
     private String onePlan;
 

+ 6 - 2
src/main/java/org/springblade/modules/project/service/IProjectInfoService.java

@@ -3,9 +3,11 @@ package org.springblade.modules.project.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 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.web.multipart.MultipartFile;
 
 /**
  * @Param
@@ -13,7 +15,7 @@ import org.springblade.modules.project.pojo.vo.*;
  * @Date 2024/4/8 11:59
  **/
 public interface IProjectInfoService extends BaseService<ProjectInfo> {
-    void add(ProjectInfoDTO dto);
+    Long add(ProjectInfoDTO dto);
 
     PageVO<ProjectInfoVO> page2(ProjectInfoPageDTO dto);
 
@@ -23,7 +25,7 @@ public interface IProjectInfoService extends BaseService<ProjectInfo> {
 
     ProjectAndPlanDetailVO detail2(Long id);
 
-    void updateFinished(ProjectAndPlanDetailDTO dto);
+    void updateFinished(ProjectAndPlanDetailVO vo);
 
     void delete(ProjectInfoPageDTO dto);
 
@@ -42,4 +44,6 @@ public interface IProjectInfoService extends BaseService<ProjectInfo> {
     ProjectWarningDTO detailWarning();
 
     void repealWarning(ProjectRepealDTO dto);
+
+    R importProject(MultipartFile file);
 }

+ 358 - 22
src/main/java/org/springblade/modules/project/service/impl/ProjectInfoServiceImpl.java

@@ -7,28 +7,41 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.bstek.ureport.font.yahei.YaheiFontRegister;
 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.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.modules.project.mapper.ProjectInfoMapper;
 import org.springblade.modules.project.pojo.dto.*;
 import org.springblade.modules.project.pojo.entity.*;
+import org.springblade.modules.project.pojo.excel.ProjectImportExcel;
 import org.springblade.modules.project.pojo.vo.*;
 import org.springblade.modules.project.service.*;
 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.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.DateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import static org.apache.poi.ss.usermodel.TableStyleType.headerRow;
+
 /**
  * @Param
  * @Author wangwl
@@ -46,9 +59,11 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
 
     private final IRepealRecordService repealRecordService;
 
+    private final IDictBizService dictBizService;
+
     @Override
     @Transactional
-    public void add(ProjectInfoDTO dto) {
+    public Long add(ProjectInfoDTO dto) {
         //校验是否已经存在相同的项目名称
         List<ProjectInfo> infos = this.list(new LambdaQueryWrapper<ProjectInfo>()
                 .eq(ProjectInfo::getName, dto.getName()));
@@ -63,7 +78,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
         //保存计划信息
         List<ProjectInvestPlan> list = dto.getList();
         if (list == null || list.size() == 0){
-            return;
+            return info.getId();
         }
         BigDecimal projectAll = BigDecimal.ZERO;
         for (ProjectInvestPlan plan : list) {
@@ -94,19 +109,22 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
                 all = all.add(plan.getFourInvest());
             }
             if ((plan.getYearlyInvest() == null && !all.equals(BigDecimal.ZERO)) || (plan.getYearlyInvest() != null && all.compareTo(plan.getYearlyInvest()) != 0)){
-                throw new ServiceException(plan.getPlanYear()+"年全年计划投资与每季度总和不对");
+                throw new ServiceException(dto.getName() +"的"+plan.getPlanYear()+"年全年计划投资与每季度总和不对");
             }
             projectAll = projectAll.add(all);
         }
         if (info.getAllInvestMoney() != null && info.getAllInvestMoney().compareTo(projectAll) == -1){
-            throw new ServiceException("所有年计划投资之和不能大于总投资,请修改后重新保存");
+            throw new ServiceException(dto.getName() +"的"+"所有年计划投资之和不能大于总投资,请修改后重新保存");
         }
         investPlanService.saveBatch(list);
+        return info.getId();
     }
 
     @Override
     public PageVO<ProjectInfoVO> page2(ProjectInfoPageDTO dto) {
         PageVO<ProjectInfoVO> page = new PageVO();
+        page.setCurrent(dto.getCurrent());
+        page.setSize(dto.getSize());
         PageVO<ProjectInfoVO> iPage = baseMapper.page(page, dto);
         //获取所有建设规模
         Long buildTotal = baseMapper.getBuildTotal(dto);
@@ -179,7 +197,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
                 all = all.add(plan.getFourInvest());
             }
                 if ((plan.getYearlyInvest() == null && all.compareTo(BigDecimal.ZERO) != 0) || (plan.getYearlyInvest() != null && all.compareTo(plan.getYearlyInvest()) != 0)){
-                throw new ServiceException(plan.getPlanYear()+"年全年计划投资与每季度总和不对");
+                throw new ServiceException(dto.getName() +"的"+plan.getPlanYear()+"年全年计划投资与每季度总和不对");
             }
             if (plan.getYearlyInvest() != null || StringUtils.isNotBlank(plan.getYearlyTarget()) || StringUtils.isNotBlank(plan.getOnePlan())
                 || StringUtils.isNotBlank(plan.getTwoPlan()) || StringUtils.isNotBlank(plan.getThreePlan()) || StringUtils.isNotBlank(plan.getFourPlan())){
@@ -200,7 +218,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
                     investFinish = investFinish.add(plan.getOneInvestFinish());
                 }
                 if (plan.getOneInvestFinish() != null && (plan.getOneInvest() == null || plan.getOneInvest().equals(BigDecimal.ZERO))){
-                    throw new ServiceException(plan.getPlanYear()+"年一月已有投资金额,不能修改为0");
+                    throw new ServiceException(dto.getName() +"的"+plan.getPlanYear()+"年一季度已有投资金额,不能修改为0");
                 }
                 if (plan.getIsOnePlanFinish() == 1){
                     plan.setOneInvestRatio(plan.getOneInvestFinish().divide(plan.getOneInvestFinish(),4, RoundingMode.DOWN).multiply(new BigDecimal(100)).setScale(2));
@@ -214,7 +232,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
                     investFinish = investFinish.add(plan.getTwoInvestFinish());
                 }
                 if (plan.getTwoInvestFinish() != null && (plan.getTwoInvest() == null || plan.getTwoInvest().equals(BigDecimal.ZERO))){
-                    throw new ServiceException(plan.getPlanYear()+"年一月已有投资金额,不能修改为0");
+                    throw new ServiceException(dto.getName() +"的"+plan.getPlanYear()+"年二季度已有投资金额,不能修改为0");
                 }
                 if (plan.getIsTwoPlanFinish() == 1){
                     plan.setTwoInvestRatio(plan.getTwoInvestFinish().divide(plan.getTwoInvestFinish(),4, RoundingMode.DOWN).multiply(new BigDecimal(100)).setScale(2));
@@ -223,7 +241,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
 
                 //校验三月已有投资,则不能删除或改为0
                 if (plan.getThreeInvestFinish() != null && (plan.getThreeInvest() == null || plan.getThreeInvest().equals(BigDecimal.ZERO))){
-                    throw new ServiceException(plan.getPlanYear()+"年一月已有投资金额,不能修改为0");
+                    throw new ServiceException(dto.getName() +"的"+plan.getPlanYear()+"年三季度已有投资金额,不能修改为0");
                 }
                 if (plan.getIsThreePlanFinish() == 1){
                     plan.setThreeInvestRatio(plan.getThreeInvestFinish().divide(plan.getThreeInvestFinish(),4, RoundingMode.DOWN).multiply(new BigDecimal(100)).setScale(2));
@@ -232,7 +250,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
 
                 //校验四月已有投资,则不能删除或改为0
                 if (plan.getFourInvestFinish() != null && (plan.getFourInvest() == null || plan.getFourInvest().equals(BigDecimal.ZERO))){
-                    throw new ServiceException(plan.getPlanYear()+"年一月已有投资金额,不能修改为0");
+                    throw new ServiceException(dto.getName() +"的"+plan.getPlanYear()+"年四季度已有投资金额,不能修改为0");
                 }
                 if (plan.getIsFourPlanFinish() == 1){
                     plan.setFourInvestRatio(plan.getFourInvestFinish().divide(plan.getFourInvestFinish(),4, RoundingMode.DOWN).multiply(new BigDecimal(100)).setScale(2));
@@ -321,39 +339,35 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
                     Integer i = progress.getPlanMonth();
                     progress.setPlanMonthName(monthNames[i]);
                     progress.setYearlyTarget(planVO.getYearlyTarget());
-                    monthFinished = monthFinished.add(progress.getInvestMoney() == null ? BigDecimal.ZERO : progress.getInvestMoney());
                     if (i <= 3){
                         progress.setPlanQuarterName("一季度");
                         if (planVO.getOneInvest() != null) {
                             progress.setPlanInvestMoney(planVO.getOneInvest());
-                            progress.setInvestUnfinishedMoney(planVO.getOneInvest().subtract(monthFinished));
+                            progress.setInvestUnfinishedMoney(planVO.getOneInvest().subtract(planVO.getOneInvestFinish()));
                         }
                         progress.setWorkPlan(planVO.getOnePlan());
                     }else if (i <= 6){
                         progress.setPlanQuarterName("二季度");
                         if (planVO.getTwoInvest() != null) {
                             progress.setPlanInvestMoney(planVO.getTwoInvest());
-                            progress.setInvestUnfinishedMoney(planVO.getTwoInvest().subtract(monthFinished));
+                            progress.setInvestUnfinishedMoney(planVO.getTwoInvest().subtract(planVO.getTwoInvestFinish()));
                         }
                         progress.setWorkPlan(planVO.getTwoPlan());
                     }else if (i <= 9){
                         progress.setPlanQuarterName("三季度");
                         if (planVO.getThreeInvest() != null) {
                             progress.setPlanInvestMoney(planVO.getThreeInvest());
-                            progress.setInvestUnfinishedMoney(planVO.getThreeInvest().subtract(monthFinished));
+                            progress.setInvestUnfinishedMoney(planVO.getThreeInvest().subtract(planVO.getThreeInvestFinish()));
                         }
                         progress.setWorkPlan(planVO.getThreePlan());
                     }else {
                         progress.setPlanQuarterName("四季度");
                         if (planVO.getFourInvest() != null) {
                             progress.setPlanInvestMoney(planVO.getFourInvest());
-                            progress.setInvestUnfinishedMoney(planVO.getFourInvest().subtract(monthFinished));
+                            progress.setInvestUnfinishedMoney(planVO.getFourInvest().subtract(planVO.getFourInvestFinish()));
                         }
                         progress.setWorkPlan(planVO.getFourPlan());
                     }
-                    if (i % 3 == 0){
-                        monthFinished = BigDecimal.ZERO;
-                    }
                 }
                 progresses = vos;
             }
@@ -365,16 +379,16 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
 
     @Override
     @Transactional
-    public void updateFinished(ProjectAndPlanDetailDTO dto) {
+    public void updateFinished(ProjectAndPlanDetailVO dto) {
         //获取年数组,如果数组为null则跳过保存
-        List<ProjectInvestPlanDTO> years = dto.getList();
+        List<ProjectInvestPlanVO> years = dto.getList();
         if (years == null || years.size() == 0){
             return;
         }
         //删除所有年的详情
         baseMapper.deleteProgressByProjectId(dto.getId());
         List<ProjectInvestPlan> updateYearPlan = new ArrayList<>();
-        for (ProjectInvestPlanDTO year : years) {
+        for (ProjectInvestPlanVO year : years) {
             //如果此年不能填写,则直接跳过
             if (year.getIsCanFill() == 0){
                 continue;
@@ -400,7 +414,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
             //当季进度填写次数
             Integer quarterPlanTotal = 0;
 
-            List<ProjectPlanProgress> monthList = year.getList();
+            List<ProjectPlanProgressVO> monthList = year.getList();
             for (ProjectPlanProgress progress : monthList) {
                 progress.setInvestMoneyAll(null);
                 //设置当前行已经填写字段
@@ -616,9 +630,18 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
                     }
                 }
                 progress.setFillField(fillField);
+                if (fillField > 0){
+                    yearPlan.setIsFillPlan(1);
+                }
             }
             //直接保存月计划集合
-            planProgressService.saveBatch(monthList);
+            List<ProjectPlanProgress> progresses = new ArrayList<>();
+            for (ProjectPlanProgressVO vo : monthList) {
+                ProjectPlanProgress progress = new ProjectPlanProgress();
+                BeanUtils.copyProperties(vo,progress);
+                progresses.add(progress);
+            }
+            planProgressService.saveBatch(progresses);
             //添加要修改年计划
             yearPlan.setYearFinishInvest(allInvestFinished);
             yearPlan.setYearUnfinishedInvest(year.getYearlyInvest().subtract(allInvestFinished));
@@ -1137,6 +1160,317 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
 
     }
 
+    /**
+     * 导入项目
+     * @param file
+     * @return
+     */
+    @Override
+    @Transactional
+    public R importProject(MultipartFile file) {
+        /*解析excel*/
+        List<ProjectImportExcel>  list = this.parseExcelFile(file);
+        if (list.size() == 0){
+            throw new ServiceException("excel中未发现数据,请检查后再导入");
+        }
+        for (ProjectImportExcel project : list) {
+            //判断是新增项目还是修改项目
+            if (project.getIsExist()){
+                /*修改项目*/
+                //查询出项目详情
+                ProjectInfoDetailVO detailVO = this.detail(project.getProjectId());
+                ProjectInfoDTO dto = new ProjectInfoDTO();
+                BeanUtils.copyProperties(detailVO,dto);
+                //修改指定几个项目信息
+                dto.setBuildScale(project.getBuildScale());
+                dto.setBuildScaleUnit(project.getBuildScaleUnit());
+                dto.setAllInvestMoney(project.getAllInvestMoney());
+                dto.setProjectType(project.getProjectType());
+                dto.setProjectStage(project.getProjectStage());
+                dto.setDutyUnit(project.getDutyUnit());
+                dto.setIsPilotPlan(project.getIsPilotPlan());
+                //修改指定年的计划信息
+                for (ProjectInvestPlan plan : dto.getList()) {
+                    if (plan.getPlanYear() == project.getPlanYear()){
+                        plan.setYearlyInvest(project.getYearlyInvest());
+                        plan.setOneInvest(project.getOneInvest());
+                        plan.setTwoInvest(project.getTwoInvest());
+                        plan.setThreeInvest(project.getThreeInvest());
+                        plan.setFourInvest(project.getFourInvest());
+                        plan.setYearlyTarget(project.getYearlyTarget());
+                        plan.setOnePlan(project.getOnePlan());
+                        plan.setTwoPlan(project.getTwoPlan());
+                        plan.setThreePlan(project.getThreePlan());
+                        plan.setFourPlan(project.getFourPlan());
+                        plan.setQuestionable(project.getQuestionable());
+                        plan.setWorkAdvise(project.getWorkAdvise());
+                        plan.setLinkman(project.getLinkman());
+                        plan.setPhone(project.getPhone());
+                    }
+                }
+                //调用项目修改接口修改
+                this.update2(dto);
+            }else {
+                /*新增项目*/
+                //组装项目新增DTO,调用项目新增接口生成 项目信息与年信息
+                ProjectInfoDTO infoDTO = new ProjectInfoDTO();
+                BeanUtils.copyProperties(project,infoDTO);
+                List<ProjectInvestPlan> plans = new ArrayList<>();
+                //创建年数组
+                for (int i = project.getStartYear(); i < project.getEndYear(); i++) {
+                    ProjectInvestPlan plan = new ProjectInvestPlan();
+                    if (i == project.getPlanYear()) {
+                        plan.setPlanYear(project.getPlanYear());
+                        plan.setYearlyInvest(project.getYearlyInvest());
+                        plan.setOneInvest(project.getOneInvest());
+                        plan.setTwoInvest(project.getTwoInvest());
+                        plan.setThreeInvest(project.getThreeInvest());
+                        plan.setFourInvest(project.getFourInvest());
+                        plan.setYearlyTarget(project.getYearlyTarget());
+                        plan.setOnePlan(project.getOnePlan());
+                        plan.setTwoPlan(project.getTwoPlan());
+                        plan.setThreePlan(project.getThreePlan());
+                        plan.setFourPlan(project.getFourPlan());
+                        plan.setQuestionable(project.getQuestionable());
+                        plan.setWorkAdvise(project.getWorkAdvise());
+                        plan.setLinkman(project.getLinkman());
+                        plan.setPhone(project.getPhone());
+                    }else {
+                        plan.setPlanYear(i);
+                    }
+                    plans.add(plan);
+                }
+                infoDTO.setList(plans);
+                project.setProjectId(this.add(infoDTO));
+            }
+            //是否存在完成数据,存在则组装月修改DTO,生成月信息和修改年信息
+            if (project.getHasFinished()){
+                //获取项目和详情
+                ProjectAndPlanDetailVO vo = this.detail2(project.getProjectId());
+                Map<Integer, ProjectInvestPlanVO> planVOMap = vo.getList().stream().collect(Collectors.toMap(l -> l.getPlanYear(), l -> l));
+                Map<Integer, ProjectPlanProgressVO> map = planVOMap.get(project.getPlanYear()).getList().stream().collect(Collectors.toMap(l -> l.getPlanMonth(), l -> l));
+                ProjectPlanProgressVO progressVO = map.get(project.getPlanMonth());
+                progressVO.setInvestMoney(project.getInvestMoney());
+                progressVO.setWorkProgress(project.getWorkProgress());
+                progressVO.setWorkProgressAll(project.getWorkProgressAll());
+                progressVO.setPlanRatio(project.getPlanRatio());
+                //调用修改接口保存
+                this.updateFinished(vo);
+            }
+        }
+        long add = list.stream().filter(l -> !l.getIsExist()).count();
+        long update = list.stream().filter(l -> l.getIsExist()).count();
+        return R.success("导入成功:新增"+add+"个项目,修改"+update+"个项目");
+    }
+
+    private List<ProjectImportExcel> parseExcelFile(MultipartFile file) {
+        //获取项目类型,项目进展类型,并转换为map
+        Map<String, Integer> typeMap = dictBizService.getList("projectType").stream().collect(Collectors.toMap(l -> l.getDictValue(), l -> Integer.valueOf(l.getDictKey())));
+        Map<String, Integer> stageMap = dictBizService.getList("projectStage").stream().collect(Collectors.toMap(l -> l.getDictValue(), l -> Integer.valueOf(l.getDictKey())));
+        if (typeMap.size() == 0 || stageMap.size() == 0){
+            throw new ServiceException("请先设置项目类型和项目进展类型后再导入");
+        }
+        //获取当前已有项目,转换为:项目名称->项目信息
+        Map<String, ProjectInfo> projectMap = this.list().stream().collect(Collectors.toMap(l -> l.getName(), l -> l));
+        //解析Excel
+        List<ProjectImportExcel> list = new ArrayList<>();
+        try (InputStream inputStream = file.getInputStream()) {
+            Workbook workbook;
+            if (Objects.requireNonNull(file.getOriginalFilename()).toLowerCase().endsWith(".xls")) {
+                workbook = new HSSFWorkbook(inputStream);
+            } else if (file.getOriginalFilename().toLowerCase().endsWith(".xlsx")) {
+                workbook = new XSSFWorkbook(inputStream);
+            } else {
+                throw new ServiceException("解析Excel失败");
+            }
+            //获取第一个sheet
+            Sheet sheet = workbook.getSheetAt(0);
+            //获取总行数
+            int rows = sheet.getPhysicalNumberOfRows();
+            //获取第二行名称,然后解析出项目类型,年月
+            Row row2 = sheet.getRow(1);
+            String title = row2.getCell(0, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+            if (StringUtils.isBlank(title)){
+                throw new ServiceException("未获取到标题,请检查Excel格式");
+            }
+            String pattern = "\\d{4}年\\d{1,2}月";
+            Pattern regex = Pattern.compile(pattern);
+            Matcher matcher = regex.matcher(title);
+            int year,month;
+            if (matcher.find()){
+                String yearMonth = matcher.group();
+                year = Integer.parseInt(yearMonth.substring(0,4));
+                month = Integer.parseInt(yearMonth.substring(5,yearMonth.length()-1));
+            }else {
+                throw new ServiceException("标题中未获取到年月");
+            }
+            if (year > LocalDate.now().getYear()){
+                throw new ServiceException("标题年份不能大于今年");
+            }
+            Integer projectType;
+            Integer projectStage = 0;
+            if (title.contains("重")){
+                String name = title.substring(title.lastIndexOf("月") + 1, title.lastIndexOf("重"));
+                Integer type = typeMap.get(name);
+                if (type == null){
+                    throw new ServiceException("未获取到项目类型:"+name);
+                }else {
+                    projectType = type;
+                }
+            }else {
+                throw new ServiceException("标题格式错误,无法获取项目类型");
+            }
+            //从第四行重获取建设规模
+            Row row4 = sheet.getRow(2);
+            String buildS = row4.getCell(2, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+            int buildScaleUnit = 2;
+            if (buildS.contains("公里")){
+                buildScaleUnit = 1;
+            }
+            DataFormatter dataFormatter = new DataFormatter();
+            //从第5行开始循环
+            List<String> stages = Arrays.asList("一、","二、","三、","四、","五、","六、","七、","八、","九、","十、");
+            for (int i = 4; i < rows; i++) {
+                Row row = sheet.getRow(i);
+                String oneColumn =  dataFormatter.formatCellValue(row.getCell(0,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK));
+                if (StringUtils.isBlank(oneColumn)){
+                    /*空行 或者 末尾行直接退出*/
+                }else if (oneColumn.contains("注:")){
+                    break;
+                }else if (stages.contains(oneColumn)){
+                    /*项目进程行*/
+                    String stageTypeName = row.getCell(1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                    Integer type = stageMap.get(stageTypeName);
+                    if (type == null){
+                        throw new ServiceException("未获取到项目进程类型:"+stageTypeName);
+                    }else {
+                        projectStage = type;
+                    }
+                }else {
+                    /*项目信息行*/
+                    //校验年是否被改变
+                    ProjectImportExcel pro = new ProjectImportExcel();
+                    String name = row.getCell(1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+
+                    try {
+                        if (projectStage == 0){
+                            throw new ServiceException("未获取到项目进程");
+                        }
+                        String buildScale =  dataFormatter.formatCellValue(row.getCell(2,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK));
+                        BigDecimal allInvestMoney = StringChangeBigdecimal( dataFormatter.formatCellValue(row.getCell(3,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        String start = dataFormatter.formatCellValue(row.getCell(4, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK));
+                        String end = dataFormatter.formatCellValue(row.getCell(5, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK));
+                        if (StringUtils.isBlank(start ) || StringUtils.isBlank(end)){
+                            throw new ServiceException("开工年完工年不能为空");
+                        }
+                        Integer startYear = Integer.valueOf(start);
+                        Integer endYear = Integer.valueOf(end);
+                        //校验计划年份是否在开工和完工之间
+                        if (startYear > endYear){
+                            throw new ServiceException("开工年不能大于完工年");
+                        }
+                        //todo 如果后面可以导入不是标题年的项目,则修改先判断是否存在计划,存在计划才校验
+                        //校验标题年份是否在开工和完工之间
+                        if (year < startYear || year > endYear){
+                            throw new ServiceException("标题年份不在开工和完工年之间");
+                        }
+                        ProjectInfo info = projectMap.get(name);
+                        if (info != null){
+                            pro.setProjectId(info.getId());
+                            pro.setIsExist(true);
+                            if (!startYear.equals(info.getStartYear()) || !endYear.equals(info.getEndYear())){
+                                throw new ServiceException("项目已存在,开工年完工年和已有数据不同");
+                            }
+                        }else {
+                            pro.setIsExist(false);
+                        }
+                        String dutyUnit = row.getCell(6, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String isPilotPlan = row.getCell(7, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        Integer isPilotPlan2 = 0;
+                        if (StringUtils.isNotBlank(isPilotPlan) && isPilotPlan.contains("是")){
+                            isPilotPlan2 = 1;
+                        }
+                        /*年度信息行*/
+                        BigDecimal yearlyInvest = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(8,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        BigDecimal oneInvest = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(9,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        BigDecimal twoInvest = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(10,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        BigDecimal threeInvest = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(11,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        BigDecimal fourInvest = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(12,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        String yearlyTarget = row.getCell(13, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String onePlan = row.getCell(14, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String twoPlan = row.getCell(15, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String threePlan = row.getCell(16, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String fourPlan = row.getCell(17, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String questionable = row.getCell(22, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String workAdvise = row.getCell(23, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String linkman = row.getCell(24, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String phone = row.getCell(25, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        /*月度信息行*/
+                        BigDecimal investMoney = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(18,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        String workProgress = row.getCell(19, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        String workProgressAll = row.getCell(20, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue();
+                        BigDecimal planRatio = StringChangeBigdecimal(dataFormatter.formatCellValue(row.getCell(21,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)));
+                        if (planRatio != null && (planRatio.compareTo(BigDecimal.ZERO) == -1 || planRatio.compareTo(new BigDecimal(100)) == 1)){
+                            throw new ServiceException("工程整体形象进度要在0-100之间");
+                        }
+                        /*设置信息*/
+                        pro.setName(name);
+                        pro.setPlanYear(year);
+                        pro.setPlanMonth(month);
+                        pro.setProjectType(projectType);
+                        pro.setProjectStage(projectStage);
+                        pro.setBuildScale(buildScale);
+                        pro.setBuildScaleUnit(buildScaleUnit);
+                        pro.setAllInvestMoney(allInvestMoney);
+                        pro.setStartYear(startYear);
+                        pro.setEndYear(endYear);
+                        pro.setDutyUnit(dutyUnit);
+                        pro.setIsPilotPlan(isPilotPlan2);
+                        pro.setYearlyInvest(yearlyInvest);
+                        pro.setOneInvest(oneInvest);
+                        pro.setTwoInvest(twoInvest);
+                        pro.setThreeInvest(threeInvest);
+                        pro.setFourInvest(fourInvest);
+                        pro.setYearlyTarget(yearlyTarget);
+                        pro.setOnePlan(onePlan);
+                        pro.setTwoPlan(twoPlan);
+                        pro.setThreePlan(threePlan);
+                        pro.setFourPlan(fourPlan);
+                        pro.setQuestionable(questionable);
+                        pro.setWorkAdvise(workAdvise);
+                        pro.setLinkman(linkman);
+                        pro.setPhone(phone);
+                        pro.setInvestMoney(investMoney);
+                        pro.setWorkProgress(workProgress);
+                        pro.setWorkProgressAll(workProgressAll);
+                        pro.setPlanRatio(planRatio);
+                        if (investMoney != null || StringUtils.isNotBlank(workProgress) || StringUtils.isNotBlank(workProgressAll) || planRatio != null){
+                            pro.setHasFinished(true);
+                        }else {
+                            pro.setHasFinished(false);
+                        }
+                        list.add(pro);
+                    }catch (Exception e){
+                        throw new ServiceException("项目:"+name+" 解析失败,原因:"+e.getMessage());
+                    }
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new ServiceException("excel解析失败:" + e.getMessage());
+        }
+        return list;
+    }
+
+    //string转化为Big,如果string为空,则返回null
+    private BigDecimal StringChangeBigdecimal(String big){
+        BigDecimal b = null;
+        if (StringUtils.isNotBlank(big)){
+            b = new BigDecimal(big);
+        }
+        return b;
+    }
+
     @Override
     public IPage<pageWarningVO> pageWarning(pageWarningDTO dto) {
         Integer current = dto.getCurrent();
@@ -1469,4 +1803,6 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
         return iPage;
     }
 
+
+
 }