diff --git a/pmapi/pom.xml b/pmapi/pom.xml index 016a7fe..8bb2f6d 100644 --- a/pmapi/pom.xml +++ b/pmapi/pom.xml @@ -262,6 +262,11 @@ com.itextpdf html2pdf + + + cn.afterturn + easypoi-base + diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConst.java b/pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConst.java index 7f1dd50..734c9c8 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConst.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/common/constant/CommonConst.java @@ -45,6 +45,7 @@ public interface CommonConst { String NEW_CONSTRUCTION = "新建"; String CONTINUED_CONSTRUCTION = "续建"; String MONTH = "月"; + String ZHI = "至"; diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/constant/ImportTemplateConstant.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/constant/ImportTemplateConstant.java index 2b9f020..bc0c61f 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/constant/ImportTemplateConstant.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/constant/ImportTemplateConstant.java @@ -1,6 +1,6 @@ package com.ningdatech.pmapi.projectlib.constant; -import com.ningdatech.pmapi.projectlib.enumeration.ImportTemplateEnum; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectLibFlagEnum; import java.util.*; @@ -15,16 +15,16 @@ import java.util.*; */ public class ImportTemplateConstant { - public static final List ANNUAL_PLAN_COL_LIST = Arrays.asList("序号","项目id","项目名称","建设内容","建设依据","建设性质","建设起止年限(填写到月)", "总投资", "自有资金", "政府投资-本级财政","政府投资-上级补助资金","银行贷款","其他","一季度","二季度","三季度","四季度","建设单位","项目联系人","项目分管领导","备注"); + public static final List ANNUAL_PLAN_COL_LIST = Arrays.asList("序号","项目id","项目名称","建设内容","建设依据","建设性质","建设起止年限(填写到月)", "总投资", "自有资金","年度投资额","政府投资-本级财政","政府投资-上级补助资金","银行贷款","其他","一季度","二季度","三季度","四季度","建设单位","项目联系人","项目分管领导","备注"); - private static final Map> IMPORT_TEMPLATE_MAP; + private static final Map> IMPORT_TEMPLATE_MAP; static { - IMPORT_TEMPLATE_MAP = new HashMap<>(ImportTemplateEnum.values().length); - IMPORT_TEMPLATE_MAP.put(ImportTemplateEnum.ANNUAL_PLAN, ANNUAL_PLAN_COL_LIST); + IMPORT_TEMPLATE_MAP = new HashMap<>(ProjectLibFlagEnum.values().length); + IMPORT_TEMPLATE_MAP.put(ProjectLibFlagEnum.ANNUAL_PLAN, ANNUAL_PLAN_COL_LIST); } - public static List getTemplateTitle(ImportTemplateEnum template) { + public static List getTemplateTitle(ProjectLibFlagEnum template) { return IMPORT_TEMPLATE_MAP.getOrDefault(template, Collections.emptyList()); } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/AnnualPlanController.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/AnnualPlanController.java index 901d3e4..311b76e 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/AnnualPlanController.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/controller/AnnualPlanController.java @@ -2,7 +2,7 @@ package com.ningdatech.pmapi.projectlib.controller; import com.ningdatech.basic.model.PageVo; import com.ningdatech.log.annotation.WebLog; -import com.ningdatech.pmapi.projectlib.enumeration.ImportTemplateEnum; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectLibFlagEnum; import com.ningdatech.pmapi.projectlib.manage.AnnualPlanLibManage; import com.ningdatech.pmapi.projectlib.model.dto.ProjectDTO; import com.ningdatech.pmapi.projectlib.model.req.ProjectApprovedReq; @@ -65,8 +65,8 @@ public class AnnualPlanController { @PostMapping("/importAnnualPlan") @ApiOperation("导入年度计划") @WebLog("导入年度计划") - public void importAnnualPlan(@RequestParam("template") ImportTemplateEnum template, MultipartFile file) { - annualPlanLibManage.importAnnualPlan(template,file); + public void importAnnualPlan(@RequestParam("importFlag") ProjectLibFlagEnum importFlag, MultipartFile file) { + annualPlanLibManage.importAnnualPlan(importFlag,file); } @PostMapping("/modify") @@ -77,9 +77,15 @@ public class AnnualPlanController { } @PostMapping("/exportList") - @ApiOperation("项目库【列表|编辑表】导出") + @ApiOperation("项目(增补)库列表导出") public void exportList(@Valid @RequestBody ProjectListReq param, HttpServletResponse response) { annualPlanLibManage.exportList(param, response); } + @PostMapping("/exportModifyList") + @ApiOperation("项目(增补)库编辑表导出") + public void exportModifyList(@Valid @RequestBody ProjectListReq param, HttpServletResponse response) { + annualPlanLibManage.exportModifyList(param, response); + } + } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/ImportTemplateEnum.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/ProjectLibFlagEnum.java similarity index 52% rename from pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/ImportTemplateEnum.java rename to pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/ProjectLibFlagEnum.java index de78e8f..53707ae 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/ImportTemplateEnum.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/enumeration/ProjectLibFlagEnum.java @@ -4,24 +4,25 @@ import lombok.Getter; /** *

- * 导入模版枚举 + * 项目库标志枚举 *

* * @author WendyYang * @since 2022-11-04 */ @Getter -public enum ImportTemplateEnum { +public enum ProjectLibFlagEnum { /** - * 通用导入模版枚举 + * 项目库标志枚举 */ - ANNUAL_PLAN("年度计划(增补)库导入"); + ANNUAL_PLAN("年度计划库"), + ANNUAL_PLAN_SUPPLEMENT("年度计划增补库"); private final String value; - ImportTemplateEnum(String value) { + ProjectLibFlagEnum(String value) { this.value = value; } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java index 9684ec4..82d6c42 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java @@ -1,12 +1,11 @@ package com.ningdatech.pmapi.projectlib.manage; +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ImportParams; +import cn.afterturn.easypoi.excel.entity.TemplateExportParams; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.poi.excel.ExcelReader; import cn.hutool.poi.excel.ExcelUtil; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.context.AnalysisContext; -import com.alibaba.excel.event.AnalysisEventListener; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -14,7 +13,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ningdatech.basic.exception.BizException; import com.ningdatech.basic.model.PageVo; import com.ningdatech.basic.util.CollUtils; -import com.ningdatech.basic.util.ValidUtil; import com.ningdatech.pmapi.common.constant.CommonConst; import com.ningdatech.pmapi.common.enumeration.CommonEnum; import com.ningdatech.pmapi.common.helper.UserInfoHelper; @@ -23,35 +21,42 @@ import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils; import com.ningdatech.pmapi.common.util.ExcelDownUtil; import com.ningdatech.pmapi.datascope.model.DataScopeDTO; import com.ningdatech.pmapi.datascope.utils.DataScopeUtil; -import com.ningdatech.pmapi.projectlib.constant.ImportTemplateConstant; -import com.ningdatech.pmapi.projectlib.enumeration.ImportTemplateEnum; +import com.ningdatech.pmapi.expert.constant.ExpertUserInfoSensitiveFieldEnum; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectLibFlagEnum; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectRenewalApprovalStatusEnum; import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; import com.ningdatech.pmapi.projectlib.helper.ProjectHelper; import com.ningdatech.pmapi.projectlib.model.dto.AnnualLibImportDTO; import com.ningdatech.pmapi.projectlib.model.dto.ProjectDTO; import com.ningdatech.pmapi.projectlib.model.entity.Project; +import com.ningdatech.pmapi.projectlib.model.entity.ProjectRenewalFundDeclaration; import com.ningdatech.pmapi.projectlib.model.req.ProjectApprovedReq; import com.ningdatech.pmapi.projectlib.model.req.ProjectIdReq; import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq; import com.ningdatech.pmapi.projectlib.model.req.StartProjectDeclareReq; import com.ningdatech.pmapi.projectlib.model.vo.AnnualPlanListItemVO; import com.ningdatech.pmapi.projectlib.service.INdProjectStatusChangeService; +import com.ningdatech.pmapi.projectlib.service.IProjectRenewalFundDeclarationService; import com.ningdatech.pmapi.projectlib.service.IProjectService; import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; import com.ningdatech.pmapi.user.util.LoginUserUtil; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.ss.usermodel.Workbook; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; +import java.net.URLEncoder; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; +import static com.ningdatech.pmapi.expert.constant.ExpertUserInfoSensitiveFieldEnum.UnitType.list; import static com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum.*; /** @@ -71,6 +76,7 @@ public class AnnualPlanLibManage { private final StateMachineUtils stateMachine; private final INdProjectStatusChangeService statusChangeService; private final UserInfoHelper userInfoHelper; + private final IProjectRenewalFundDeclarationService projectRenewalFundDeclarationService; /** * 年度计划查询状态 @@ -169,112 +175,6 @@ public class AnnualPlanLibManage { projectService.updateById(project); } - @Transactional(rollbackFor = Exception.class) - public void importAnnualPlan(ImportTemplateEnum template, MultipartFile file) { - String contentType = file.getContentType(); - if (!contentType.equals(ExcelUtil.XLS_CONTENT_TYPE) && - !contentType.equals(ExcelUtil.XLSX_CONTENT_TYPE) - ) { - throw BizException.wrap("导入失败,不支持的文件类型,请按照提供的模板导入文件!"); - } - try (InputStream inputStream = file.getInputStream(); - ExcelReader reader = ExcelUtil.getReader(inputStream)) { - Map alias; - List title = ImportTemplateConstant.getTemplateTitle(template); - switch (template) { - case ANNUAL_PLAN: - alias = new HashMap<>(title.size()); - alias.put(title.get(0), "id"); - alias.put(title.get(1), "projectId"); - alias.put(title.get(2), "projectName"); - alias.put(title.get(3), "projectIntroduction"); - alias.put(title.get(4), "buildBasis"); - alias.put(title.get(5), "isFirst"); - alias.put(title.get(6), "buildCycle"); - alias.put(title.get(7), "declaredAmount"); - alias.put(title.get(8), "annualPlanAmount"); - alias.put(title.get(9), "declareHaveAmount"); - alias.put(title.get(10), "declareGovOwnFinanceAmount"); - alias.put(title.get(11), "declareGovSuperiorFinanceAmount"); - alias.put(title.get(12), "declareBankLendingAmount"); - alias.put(title.get(13), "declareOtherAmount"); - alias.put(title.get(14), "firstQuarter"); - alias.put(title.get(15), "secondQuarter"); - alias.put(title.get(16), "thirdQuarter"); - alias.put(title.get(17), "fourthQuarter"); - alias.put(title.get(18), "buildUnitName"); - alias.put(title.get(19), "contactName"); - alias.put(title.get(20), "responsibleMan"); - alias.put(title.get(21), "projectRemarks"); - reader.setHeaderAlias(alias); - importAnnualPlanData(reader.readAll(AnnualLibImportDTO.class)); - break; - default: - throw new BizException("不支持的数据导入类型"); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void importAnnualPlanData(List importDataList) { - if (CollectionUtils.isEmpty(importDataList)) { - return; - } - List projectList = new ArrayList<>(); - List projectIds = CollUtils.fieldList(importDataList, AnnualLibImportDTO::getProjectId); - Assert.isTrue(projectIds.size() == importDataList.size(), "项目ID不可重复"); - Long userId = LoginUserUtil.getUserId(); - LocalDateTime now = LocalDateTime.now(); - importDataList.forEach(w -> { - Project project = new Project(); - project.setCreateBy(userId); - project.setCreateOn(now); - project.setUpdateBy(userId); - project.setUpdateOn(now); - - project.setId(w.getProjectId()); - project.setProjectName(w.getProjectName()); - project.setProjectIntroduction(w.getProjectIntroduction()); - // 建设依据(立项依据忽略) - if (CommonConst.NEW_CONSTRUCTION.equals(w.getIsFirst())){ - project.setIsFirst(CommonEnum.YES.getCode()); - }else if (CommonConst.CONTINUED_CONSTRUCTION.equals(w.getIsFirst())){ - project.setIsFirst(CommonEnum.NO.getCode()); - } - String buildCycle = w.getBuildCycle(); - int index = buildCycle.indexOf(CommonConst.MONTH); - if (-1 == index){ - throw new BizException("项目ID为:" + w.getProjectId() + "的建设起止年限格式不正确,请按照xx年xx月至xx年xx月的格式输入!"); - } - String beginTime = buildCycle.substring(0, index + 1); - project.setBeginTime(beginTime); - String endTime = buildCycle.substring(index + 2); - project.setEndTime(endTime); - project.setDeclareAmount(w.getDeclaredAmount()); - project.setAnnualPlanAmount(w.getAnnualPlanAmount()); - project.setDeclareHaveAmount(w.getDeclareHaveAmount()); - project.setDeclareGovOwnFinanceAmount(w.getDeclareGovOwnFinanceAmount()); - project.setDeclareGovSuperiorFinanceAmount(w.getDeclareGovSuperiorFinanceAmount()); - project.setDeclareBankLendingAmount(w.getDeclareBankLendingAmount()); - project.setDeclareOtherAmount(w.getDeclareOtherAmount()); - project.setEngineeringSpeedOne(w.getFirstQuarter()); - project.setEngineeringSpeedTwo(w.getSecondQuarter()); - project.setEngineeringSpeedThree(w.getThirdQuarter()); - project.setEngineeringSpeedFour(w.getFourthQuarter()); - - project.setBuildOrgName(w.getBuildUnitName()); - project.setContactName(w.getContactName()); - project.setResponsibleMan(w.getResponsibleMan()); - project.setProjectRemarks(w.getProjectRemarks()); - projectList.add(project); - }); - LambdaQueryWrapper delQuery = Wrappers.lambdaQuery(Project.class) - .in(Project::getId, projectIds); - projectService.remove(delQuery); - projectService.saveBatch(projectList); - } - public void updateAnnualPlan(ProjectDTO req) { Project project = BeanUtil.copyProperties(req, Project.class); projectService.updateById(project); @@ -295,15 +195,12 @@ public class AnnualPlanLibManage { ExcelExportWriter excelExportWriter = new ExcelExportWriter(); - Integer tableFlag = param.getTableFlag(); - if (Objects.isNull(tableFlag)) { - throw new BizException("请传入要导出的表格类型!"); - } + ProjectLibFlagEnum projectLibFlag = param.getProjectLibFlag(); String fileName = null; - if (tableFlag == 0) { - fileName = "年度计划库编辑表"; - } else if (tableFlag == 1) { + if (ProjectLibFlagEnum.ANNUAL_PLAN.equals(projectLibFlag)){ fileName = "年度计划库列表"; + }else if (ProjectLibFlagEnum.ANNUAL_PLAN_SUPPLEMENT.equals(projectLibFlag)){ + fileName = "年度计划增补库列表"; } excelExportWriter.setFileName(fileName); List sheetsNames = new ArrayList<>(); @@ -356,4 +253,152 @@ public class AnnualPlanLibManage { } return user; } + + @Transactional(rollbackFor = Exception.class) + public void importAnnualPlan(ProjectLibFlagEnum importFlag, MultipartFile file) { + Long userId = LoginUserUtil.getUserId(); + ImportParams params = new ImportParams(); + // 标题行数 + params.setTitleRows(2); + // 从第几行开始,因为第一、二个大标题被上面的参数给占了,所以不是5 + params.setHeadRows(3); + // 表格数量 + params.setSheetNum(2); + List list = null; + try { + list = ExcelImportUtil.importExcel(file.getInputStream(), AnnualLibImportDTO.class, params); + } catch (Exception e) { + throw new BizException(e.getMessage()); + } + // 筛选出导入的新建项目 + List newList = list.stream() + .filter(d -> CommonConst.NEW_CONSTRUCTION.equals(d.getIsFirst())) + .collect(Collectors.toList()); + List projectList = newList.stream().map(n -> { + Project project = new Project(); + assemblyProjectInfo(n, project); + // 根据传入标志判断是否临时增补 + if (ProjectLibFlagEnum.ANNUAL_PLAN.equals(importFlag)){ + project.setIsTemporaryAugment(CommonEnum.NO.getCode()); + }else if (ProjectLibFlagEnum.ANNUAL_PLAN_SUPPLEMENT.equals(importFlag)){ + project.setIsTemporaryAugment(CommonEnum.YES.getCode()); + } + project.setCreateBy(userId); + project.setUpdateBy(userId); + project.setCreateOn(LocalDateTime.now()); + project.setUpdateOn(LocalDateTime.now()); + return project; + }).collect(Collectors.toList()); + // 保存到项目库中 + projectService.saveBatch(projectList); + + // 筛选出导入的续建项目 + List continuedList = list.stream() + .filter(d -> CommonConst.CONTINUED_CONSTRUCTION.equals(d.getIsFirst())) + .collect(Collectors.toList()); + List renewalFundDeclarationList = continuedList.stream().map(c -> { + ProjectRenewalFundDeclaration renewalFundDeclaration = new ProjectRenewalFundDeclaration(); + BeanUtils.copyProperties(c, renewalFundDeclaration); + renewalFundDeclaration.setAnnualPaymentAmount(c.getAnnualPlanAmount()); + renewalFundDeclaration.setOtherAmount(c.getDeclareOtherAmount()); + renewalFundDeclaration.setApprovalStatus(ProjectRenewalApprovalStatusEnum.PENDING.name()); + renewalFundDeclaration.setCreateOn(LocalDateTime.now()); + renewalFundDeclaration.setUpdateOn(LocalDateTime.now()); + return renewalFundDeclaration; + }).collect(Collectors.toList()); + // 保存到续建项目资金库中 + projectRenewalFundDeclarationService.saveBatch(renewalFundDeclarationList); + } + + private void assemblyProjectInfo(AnnualLibImportDTO data, Project project) { + project.setId(data.getProjectId()); + project.setProjectName(data.getProjectName()); + project.setProjectIntroduction(data.getProjectIntroduction()); + // 建设依据忽略 + project.setIsFirst(CommonConst.NEW_CONSTRUCTION.equals(data.getIsFirst()) ? 1 : 0); + String[] dataArr = data.getBuildCycle().split(CommonConst.ZHI); + if (CollectionUtils.isEmpty(Arrays.asList(dataArr))){ + throw new BizException("项目ID为:" + data.getProjectId() + "的建设起止年限格式不正确,请按照xx年xx月至xx年xx月的格式输入!"); + } + project.setBeginTime(dataArr[0].trim()); + project.setEndTime(dataArr[1].trim()); + project.setDeclareAmount(data.getDeclaredAmount()); + project.setAnnualPlanAmount(data.getAnnualPlanAmount()); + project.setDeclareHaveAmount(data.getDeclareHaveAmount()); + project.setDeclareGovOwnFinanceAmount(data.getDeclareGovOwnFinanceAmount()); + project.setDeclareGovSuperiorFinanceAmount(data.getDeclareGovSuperiorFinanceAmount()); + project.setDeclareBankLendingAmount(data.getDeclareBankLendingAmount()); + project.setDeclareOtherAmount(data.getDeclareOtherAmount()); + project.setEngineeringSpeedOne(data.getFirstQuarter()); + project.setEngineeringSpeedTwo(data.getSecondQuarter()); + project.setEngineeringSpeedThree(data.getThirdQuarter()); + project.setEngineeringSpeedFour(data.getFourthQuarter()); + project.setBuildOrgName(data.getBuildUnitName()); + project.setContactName(data.getContactName()); + project.setResponsibleMan(data.getResponsibleMan()); + project.setProjectRemarks(data.getProjectRemarks()); + } + + public void exportModifyList(ProjectListReq param, HttpServletResponse response) { + ProjectLibFlagEnum projectLibFlag = param.getProjectLibFlag(); + int year = LocalDateTime.now().getYear(); + Integer isTemporaryAugment = null; + String fileName = null; + // 设置excel的文件名称和是否增补 + if (ProjectLibFlagEnum.ANNUAL_PLAN.equals(projectLibFlag)){ + isTemporaryAugment = 0; + fileName = "丽水市" + year + "年数字化项目年度计划库编辑表"; + }else if (ProjectLibFlagEnum.ANNUAL_PLAN_SUPPLEMENT.equals(projectLibFlag)){ + isTemporaryAugment = 1; + fileName = "丽水市" + year + "年数字化项目年度计划增补库编辑表"; + } + param.setIsTemporaryAugment(isTemporaryAugment); + param.setStatusList(CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode)); + LambdaQueryWrapper query = ProjectHelper.projectQuery(param); + query.orderByDesc(Project::getAnnualPlanAddTime); + List projects = projectService.list(query); + List list = projects.stream().map(p -> { + AnnualLibImportDTO dto = new AnnualLibImportDTO(); + BeanUtils.copyProperties(p, dto); + dto.setFirstQuarter(p.getEngineeringSpeedOne()); + dto.setSecondQuarter(p.getEngineeringSpeedTwo()); + dto.setThirdQuarter(p.getEngineeringSpeedThree()); + dto.setFourthQuarter(p.getEngineeringSpeedFour()); + return dto; + }).collect(Collectors.toList()); + + // 获取本地目录的年度计划编辑表Excel模板 + File directory = new File(""); + String templateName = "丽水市" + year + "年数字化项目年度计划编辑表"; + String templatePath = directory.getAbsolutePath() + File.separator + "template" + File.separator + templateName + ".xls"; + TemplateExportParams temp = new TemplateExportParams(templatePath); + HashMap map = new HashMap<>(); + map.put("mapList", list); + Workbook workbook = ExcelExportUtil.exportExcel(temp, map); + if (workbook == null) { + throw new BizException("读取模板失败!"); + } + // 重置响应对象 + response.reset(); + try { + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(Objects.requireNonNull(fileName),"UTF-8") + ".xls"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.setContentType(ExcelUtil.XLS_CONTENT_TYPE); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + // 写出数据输出流到页面 + try { + OutputStream output = response.getOutputStream(); + BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output); + workbook.write(bufferedOutPut); + bufferedOutPut.flush(); + bufferedOutPut.close(); + output.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/dto/AnnualLibImportDTO.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/dto/AnnualLibImportDTO.java index 69f35a2..4e2bf9c 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/dto/AnnualLibImportDTO.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/dto/AnnualLibImportDTO.java @@ -1,5 +1,6 @@ package com.ningdatech.pmapi.projectlib.model.dto; +import cn.afterturn.easypoi.excel.annotation.Excel; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -18,91 +19,104 @@ import java.math.BigDecimal; @Data public class AnnualLibImportDTO { - @ExcelProperty("序号") - @NotNull(message = "序号不能为空") - private Integer serialNumber; - - @ExcelProperty("项目id") - @NotNull(message = "项目ID不能为空") - private Long projectId; - - @ExcelProperty("项目名称") - @NotBlank(message = "项目名称不能为空") - private String projectName; - - @NotBlank(message = "建设内容不能为空") - @ExcelProperty("建设内容") - private String projectIntroduction; - - @NotBlank(message = "建设依据不能为空") - @ExcelProperty("建设依据") - private String buildBasis; - - @ExcelProperty("建设性质") - @NotBlank(message = "建设性质不能为空") - private String isFirst; - - @ExcelProperty("建设起止年限") - @NotBlank(message = "建设起止年限不能为空") - private String buildCycle; - - @NotBlank(message = "总投资不能为空") - @ExcelProperty("总投资") - private BigDecimal declaredAmount; + @Excel(name = "项目进展",groupName = "到2022年底完成情况") + @NotNull(message = "项目进展不能为空") + private String projectProgress; + @Excel(name = "累计投资") + @NotNull(message = "累计投资不能为空") + private BigDecimal cumulativeInvest; @NotNull(message = "年度投资额不能为空") - @ExcelProperty("年度投资额") + @Excel(name = "年度投资额",groupName = "2023年计划") private BigDecimal annualPlanAmount; - @ExcelProperty("自有资金") @NotNull(message = "自由资金不能为空") + @Excel(name = "自有资金",groupName = "资金来源") private BigDecimal declareHaveAmount; - - @ExcelProperty("政府投资-本级财政") + @Excel(name = "政府投资-本级财政资金") @NotNull(message = "政府投资-本级财政不能为空") private BigDecimal declareGovOwnFinanceAmount; - - @ExcelProperty("政府投资-上级补助资金") + @Excel(name = "政府投资-上级补助资金") @NotNull(message = "政府投资-上级补助资金不能为空") private BigDecimal declareGovSuperiorFinanceAmount; - - @ExcelProperty("银行贷款") + @Excel(name = "银行贷款") @NotNull(message = "银行贷款不能为空") private BigDecimal declareBankLendingAmount; - - @ExcelProperty("其他") + @Excel(name = "国家、省补助",groupName = "资金来源") + @NotNull(message = "国家、省补助不能为空") + private BigDecimal govSuperiorFinanceAmount; + @Excel(name = "地方财政统筹") + @NotNull(message = "地方财政统筹不能为空") + private BigDecimal govOwnFinanceAmount; + @Excel(name = "建设单位自筹") + @NotNull(message = "建设单位自筹不能为空") + private BigDecimal haveAmount; + @Excel(name = "其他") @NotNull(message = "其他不能为空") private BigDecimal declareOtherAmount; - @ExcelProperty("一季度") + @Excel(name = "一季度",groupName = "进度和支付计划") @NotBlank(message = "一季度不能为空") private String firstQuarter; - - @ExcelProperty("二季度") + @Excel(name = "二季度") @NotBlank(message = "二季度不能为空") private String secondQuarter; - - @ExcelProperty("三季度") + @Excel(name = "三季度") @NotBlank(message = "三季度不能为空") private String thirdQuarter; - - @ExcelProperty("四季度") + @Excel(name = "四季度") @NotBlank(message = "四季度不能为空") private String fourthQuarter; - @ExcelProperty("建设单位") + @NotNull(message = "序号不能为空") + @Excel(name = "序号") + private Integer serialNumber; + + @Excel(name = "项目id") + @NotNull(message = "项目ID不能为空") + private Long projectId; + + @Excel(name = "项目名称") + @NotBlank(message = "项目名称不能为空") + private String projectName; + + @NotBlank(message = "建设内容不能为空") + @Excel(name = "建设内容") + private String projectIntroduction; + + @NotBlank(message = "建设依据不能为空") + @Excel(name = "建设依据") + private String buildBasis; + + @Excel(name = "建设性质") + @NotBlank(message = "建设性质不能为空") + private String isFirst; + + @Excel(name = "建设周期") + @NotBlank(message = "建设周期不能为空") + private String constructionCycle; + + @Excel(name = "建设起止年限(填写到月)") + @NotBlank(message = "建设起止年限不能为空") + private String buildCycle; + + @NotBlank(message = "总投资不能为空") + @Excel(name = "总投资") + private BigDecimal declaredAmount; + + @Excel(name = "建设单位") @NotBlank(message = "建设单位不能为空") private String buildUnitName; - @ExcelProperty("项目联系人") + @Excel(name = "项目联系人") @NotBlank(message = "项目联系人不能为空") private String contactName; - @ExcelProperty("项目分管领导") + @Excel(name = "项目分管领导") @NotBlank(message = "项目分管领导不能为空") private String responsibleMan; - @ExcelProperty("备注") + @Excel(name = "备注") private String projectRemarks; } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/AnalysisEventMonitor.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/AnalysisEventMonitor.java new file mode 100644 index 0000000..41416a5 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/AnalysisEventMonitor.java @@ -0,0 +1,92 @@ +package com.ningdatech.pmapi.projectlib.model.entity; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ningdatech.basic.exception.BizException; +import com.ningdatech.basic.util.CollUtils; +import com.ningdatech.pmapi.common.constant.CommonConst; +import com.ningdatech.pmapi.projectlib.service.IProjectService; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; + +import java.util.*; + +/** + * @author CMM + * @since 2023/04/17 18:26 + */ +@Data +public class AnalysisEventMonitor extends AnalysisEventListener> { + + private final List records = new ArrayList<>(); + + /** + * 存储Key + */ + Map key = new HashMap<>(); + /** + * keyList + */ + List keyList = new ArrayList<>(); + + @Override + public void onException(Exception exception, AnalysisContext context) throws Exception { + super.onException(exception, context); + throw BizException.wrap("导入年度计划解析失败"); + } + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + Set integerSet = headMap.keySet(); + for (Integer integer : integerSet) { + keyList.add(headMap.get(integer)); + } + key.putAll(headMap); + } + + @Override + public void invoke(Map integerStringMap, AnalysisContext context) { + //Project project = new Project(); + //project.setId(data.getProjectId()); + //project.setProjectName(data.getProjectName()); + //project.setProjectIntroduction(data.getProjectIntroduction()); + //// 建设依据忽略 + //project.setIsFirst(CommonConst.NEW_CONSTRUCTION.equals(data.getIsFirst()) ? 1 : 0); + //String[] dataArr = data.getBuildCycle().split(CommonConst.ZHI); + //project.setBeginTime(dataArr[0].trim()); + //project.setEndTime(dataArr[1].trim()); + //project.setDeclareAmount(data.getDeclaredAmount()); + //project.setAnnualPlanAmount(data.getAnnualPlanAmount()); + //project.setDeclareHaveAmount(data.getDeclareHaveAmount()); + //project.setDeclareGovOwnFinanceAmount(data.getDeclareGovOwnFinanceAmount()); + //project.setDeclareGovSuperiorFinanceAmount(data.getDeclareGovSuperiorFinanceAmount()); + //project.setDeclareBankLendingAmount(data.getDeclareBankLendingAmount()); + //project.setDeclareOtherAmount(data.getDeclareOtherAmount()); + //project.setEngineeringSpeedOne(data.getFirstQuarter()); + //project.setEngineeringSpeedTwo(data.getSecondQuarter()); + //project.setEngineeringSpeedThree(data.getThirdQuarter()); + //project.setEngineeringSpeedFour(data.getFourthQuarter()); + //project.setBuildOrgName(data.getBuildUnitName()); + //project.setContactName(data.getContactName()); + //project.setResponsibleMan(data.getResponsibleMan()); + //project.setProjectRemarks(data.getProjectRemarks()); + //records.add(project); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + //if (records.isEmpty()) { + // throw BizException.wrap("导入年度计划为空"); + //} + //List projectIds = CollUtils.fieldList(records, Project::getId); + //long count = projectService.count(Wrappers.lambdaQuery(Project.class) + // .in(Project::getId, projectIds)); + //if (count != records.size()) { + // throw BizException.wrap("请确保所有项目都存在"); + //} + //projectService.updateBatchById(records); + } +} diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java index 856f522..57b0bd9 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java @@ -2,12 +2,12 @@ package com.ningdatech.pmapi.projectlib.model.req; import com.ningdatech.basic.model.PagePo; import com.ningdatech.pmapi.common.enumeration.ExportOptionEnum; +import com.ningdatech.pmapi.projectlib.enumeration.ProjectLibFlagEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.*; import org.springframework.format.annotation.DateTimeFormat; -import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -92,6 +92,6 @@ public class ProjectListReq extends PagePo { @ApiModelProperty("导出选项") private List exportOptionList; - @ApiModelProperty(value = "表格类型",allowableValues = "0,1") - private Integer tableFlag; + @ApiModelProperty(value = "项目库标志枚举") + private ProjectLibFlagEnum projectLibFlag; } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/utils/MergeUtil.java b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/utils/MergeUtil.java new file mode 100644 index 0000000..b7d5bc1 --- /dev/null +++ b/pmapi/src/main/java/com/ningdatech/pmapi/projectlib/utils/MergeUtil.java @@ -0,0 +1,80 @@ +package com.ningdatech.pmapi.projectlib.utils; + +import java.util.List; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import lombok.Data; + +/** + * @description: 多表头excel导出合并单元格策略 + * @author:YJ + **/ +@Data +public class MergeUtil implements CellWriteHandler { + private int[] mergeColumnIndex; + private int mergeRowIndex; + + public MergeUtil() { + } + + public MergeUtil(int mergeRowIndex, int[] mergeColumnIndex) { + this.mergeRowIndex = mergeRowIndex; + this.mergeColumnIndex = mergeColumnIndex; + } + + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { + // 当前行 + int curRowIndex = cell.getRowIndex(); + // 当前列 + int curColIndex = cell.getColumnIndex(); + + if (curRowIndex > mergeRowIndex) { + for (int i = 0; i < mergeColumnIndex.length; i++) { + if (curColIndex == mergeColumnIndex[i]) { + mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); + break; + } + } + } + } + + + private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { + // 获取当前行的当前列和上一行的当前列列数据,通过上一行数据是否相同进行合并 + Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); + Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); + Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); + + // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行 + if (curData.equals(preData)) { + Sheet sheet = writeSheetHolder.getSheet(); + List mergedRegions = sheet.getMergedRegions(); + boolean isMerged = false; + for (int i = 0; i < mergedRegions.size() && !isMerged; i++) { + CellRangeAddress cellRangeAddr = mergedRegions.get(i); + // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元 + if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) { + sheet.removeMergedRegion(i); + cellRangeAddr.setLastRow(curRowIndex); + sheet.addMergedRegion(cellRangeAddr); + isMerged = true; + } + } + // 若上一个单元格未被合并,则新增合并单元 + if (!isMerged) { + CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex); + sheet.addMergedRegion(cellRangeAddress); + } + } + } +} + diff --git a/pmapi/src/main/resources/template/丽水市2023年数字化项目年度计划编辑表.xls b/pmapi/src/main/resources/template/丽水市2023年数字化项目年度计划编辑表.xls new file mode 100644 index 0000000..04432a4 Binary files /dev/null and b/pmapi/src/main/resources/template/丽水市2023年数字化项目年度计划编辑表.xls differ diff --git a/pom.xml b/pom.xml index b4e66e4..916325b 100644 --- a/pom.xml +++ b/pom.xml @@ -175,6 +175,12 @@ html2pdf 2.0.2 + + + cn.afterturn + easypoi-base + 4.2.0 + diff --git a/template/丽水市2023年数字化项目年度计划编辑表.xls b/template/丽水市2023年数字化项目年度计划编辑表.xls new file mode 100644 index 0000000..04432a4 Binary files /dev/null and b/template/丽水市2023年数字化项目年度计划编辑表.xls differ