@@ -248,6 +248,11 @@ | |||||
<scope>system</scope> | <scope>system</scope> | ||||
<systemPath>${project.basedir}/src/lib/kingbase8-8.2.0.jar</systemPath> | <systemPath>${project.basedir}/src/lib/kingbase8-8.2.0.jar</systemPath> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>com.alibaba</groupId> | |||||
<artifactId>easyexcel-core</artifactId> | |||||
<version>3.1.2</version> | |||||
</dependency> | |||||
</dependencies> | </dependencies> | ||||
<!-- 打包 --> | <!-- 打包 --> | ||||
<!--配置环境的profile--> | <!--配置环境的profile--> | ||||
@@ -0,0 +1,154 @@ | |||||
package com.ningdatech.pmapi.common.constant; | |||||
/** | |||||
* 项目申报表单数据常量key | |||||
* @return | |||||
* @author CMM | |||||
* @since 2023/01/19 10:31 | |||||
*/ | |||||
public interface ProjectDeclareConstants { | |||||
/** | |||||
* 基本信息 | |||||
*/ | |||||
class BasicInformation { | |||||
// 项目名称 | |||||
public static final String PROJECT_NAME = "projectName"; | |||||
// 是否一地创新全省共享项目 | |||||
public static final String INNOVATION_SHARING_PROJECT = "innovationSharingProject"; | |||||
// 是否临时增补 | |||||
public static final String TEMPORARY_SUPPLEMENT = "temporarySupplement"; | |||||
// 项目负责人 | |||||
public static final String PROJECT_LEADER = "projectLeader"; | |||||
// 项目负责人手机号 | |||||
public static final String PROJECT_LEADER_PHONE_NUMBER = "projectLeaderPhoneNumber"; | |||||
// 项目联系人 | |||||
public static final String PROJECT_CONTACT = "projectContact"; | |||||
// 项目联系人手机号 | |||||
public static final String PROJECT_CONTACT_PHONE_NUMBER = "projectContactPhoneNumber"; | |||||
// 建设单位 | |||||
public static final String CONSTRUCTION_UNIT = "constructionUnit"; | |||||
// 建设单位统一信用代码 | |||||
public static final String CONSTRUCTION_UNIT_UNIFIED_CREDIT_CODE = "constructionUnitUnifiedCreditCode"; | |||||
// 项目类型 | |||||
public static final String PROJECT_TYPE = "projectType"; | |||||
// 是否首次新建 | |||||
public static final String FIRST_NEW_CONSTRUCTION = "firstNewConstruction"; | |||||
// 预算年度 | |||||
public static final String BUDGET_YEAR = "budgetYear"; | |||||
// 建设开始时间 | |||||
public static final String CONSTRUCTION_START_TIME = "constructionStartTime"; | |||||
// 建设结束时间 | |||||
public static final String CONSTRUCTION_END_TIME = "constructionEndTime"; | |||||
// 四大体系 | |||||
public static final String FOUR_SYSTEM = "fourSystem"; | |||||
// 是否数字化改革项目 | |||||
public static final String DIGITAL_REFORM_PROJECT = "digitalReformProject"; | |||||
// 建设层级 | |||||
public static final String CONSTRUCTION_HIERARCHY = "constructionHierarchy"; | |||||
// 立项依据材料 | |||||
public static final String PROJECT_BASIS_MATERIAL = "projectBasisMaterial"; | |||||
// 发改编码 | |||||
public static final String CHANGE_CODE = "changeCode"; | |||||
// 财政编码 | |||||
public static final String FISCAL_CODE = "fiscalCode"; | |||||
// 是否上云 | |||||
public static final String ON_CLOUD = "onCloud"; | |||||
// 项目简介 | |||||
public static final String PROJECT_INTRODUCTION = "projectIntroduction"; | |||||
} | |||||
/** | |||||
* 资金申报情况 | |||||
*/ | |||||
class FundDeclareInfo { | |||||
// 申报金额 | |||||
public static final String DECLARE_AMOUNT = "declareAmount"; | |||||
// 自有资金 | |||||
public static final String OWN_FUND = "ownFund"; | |||||
// 政府投资-本级财政资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SAME_LEVEL_FUND = "governmentInvestmentSameLevelFund"; | |||||
// 政府投资-上级补助资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SUPERIOR_FUND = "governmentInvestmentSuperiorFund"; | |||||
// 银行贷款 | |||||
public static final String BANK_LOAN = "bankLoan"; | |||||
// 其他资金 | |||||
public static final String OTHER_FUND = "otherFund"; | |||||
} | |||||
/** | |||||
* 总投资分配情况 | |||||
*/ | |||||
class TotalInvestmentAllocations { | |||||
// 软件开发 | |||||
public static final String SOFTWARE_DEVELOPMENT = "softwareDevelopment"; | |||||
// 云资源、硬件配置 | |||||
public static final String CLOUD_RESOURCE_HARDWARE_CONFIGURATION = "cloudResourceHardwareConfiguration"; | |||||
// 第三方服务 | |||||
public static final String THIRD_PARTY_SERVICE = "thirdPartyService"; | |||||
} | |||||
/** | |||||
* 年度支付计划 | |||||
*/ | |||||
class AnnualPaymentPlan { | |||||
// 年度支付金额 | |||||
public static final String ANNUAL_PAYMENT_AMOUNT = "annualPaymentAmount"; | |||||
// 自有资金 | |||||
public static final String OWN_FUND = "ownFund"; | |||||
// 政府投资-本级财政资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SAME_LEVEL_FUND = "governmentInvestmentSameLevelFund"; | |||||
// 政府投资-上级补助资金 | |||||
public static final String GOVERNMENT_INVESTMENT_SUPERIOR_FUND = "governmentInvestmentSuperiorFund"; | |||||
// 银行贷款 | |||||
public static final String BANK_LOAN = "bankLoan"; | |||||
// 其他 | |||||
public static final String OTHER = "other"; | |||||
} | |||||
/** | |||||
* 核心业务 | |||||
*/ | |||||
class CoreBusiness { | |||||
} | |||||
/** | |||||
* 安全投入 | |||||
*/ | |||||
class SafetyInput { | |||||
// 投入项 | |||||
public static final String INPUT_ITEM = "inputItem"; | |||||
// 内容描述 | |||||
public static final String CONTENT_DESCRIPTION = "contentDescription"; | |||||
// 金额 | |||||
public static final String AMOUNT = "amount"; | |||||
} | |||||
/** | |||||
* 工程形象进度 | |||||
*/ | |||||
class ProjectImageProgress { | |||||
// 第一季度 | |||||
public static final String FIRST_QUARTER = "firstQuarter"; | |||||
// 第二季度 | |||||
public static final String SECOND_QUARTER = "secondQuarter"; | |||||
// 第三季度 | |||||
public static final String THIRD_QUARTER = "thirdQuarter"; | |||||
// 第四季度 | |||||
public static final String FOURTH_QUARTER = "fourthQuarter"; | |||||
} | |||||
/** | |||||
* 附件 | |||||
*/ | |||||
class Appendix { | |||||
} | |||||
/** | |||||
* 备注 | |||||
*/ | |||||
class Remark { | |||||
} | |||||
/** | |||||
* 应用信息 | |||||
*/ | |||||
class ApplicationInformation { | |||||
} | |||||
} |
@@ -0,0 +1,71 @@ | |||||
package com.ningdatech.pmapi.common.util; | |||||
import java.io.UnsupportedEncodingException; | |||||
import java.net.URLEncoder; | |||||
import java.util.UUID; | |||||
import java.util.function.BiConsumer; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import org.apache.http.HttpStatus; | |||||
import com.alibaba.fastjson.JSON; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import com.ningdatech.basic.util.StrPool; | |||||
import cn.hutool.poi.excel.ExcelUtil; | |||||
import lombok.SneakyThrows; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
/** | |||||
* <p> | |||||
* ExcelDownUtil | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 00:48 2022/11/5 | |||||
*/ | |||||
@Slf4j | |||||
public class ExcelDownUtil { | |||||
private static String encodeName(String name) { | |||||
String fileName; | |||||
try { | |||||
fileName = URLEncoder.encode(name, "UTF-8"); | |||||
} catch (UnsupportedEncodingException e) { | |||||
log.error("文件名编码异常:", e); | |||||
fileName = UUID.randomUUID().toString().replace("-", ""); | |||||
} | |||||
return fileName; | |||||
} | |||||
@SneakyThrows | |||||
private static <T> void down(HttpServletResponse response, T param, BiConsumer<HttpServletResponse, T> consumer) { | |||||
response.setCharacterEncoding("utf-8"); | |||||
try { | |||||
consumer.accept(response, param); | |||||
} catch (Exception e) { | |||||
log.error("文件导出失败:", e); | |||||
response.reset(); | |||||
response.setContentType(StrPool.CONTENT_TYPE); | |||||
ApiResponse<Void> res = ApiResponse.of(HttpStatus.SC_BAD_REQUEST, "导出失败", null); | |||||
response.setStatus(HttpStatus.SC_BAD_REQUEST); | |||||
response.getWriter().println(JSON.toJSONString(res)); | |||||
} | |||||
} | |||||
public static <T> void downXls(HttpServletResponse response, T param, BiConsumer<HttpServletResponse, T> consumer) { | |||||
response.setContentType(ExcelUtil.XLS_CONTENT_TYPE); | |||||
down(response, param, consumer); | |||||
} | |||||
public static <T> void downXlsx(HttpServletResponse response, T param, BiConsumer<HttpServletResponse, T> consumer) { | |||||
response.setContentType(ExcelUtil.XLSX_CONTENT_TYPE); | |||||
down(response, param, consumer); | |||||
} | |||||
public static void setFileName(String fileName, HttpServletResponse response) { | |||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodeName(fileName) + ".xls"); | |||||
} | |||||
} |
@@ -0,0 +1,80 @@ | |||||
package com.ningdatech.pmapi.common.util; | |||||
import org.apache.poi.ss.usermodel.*; | |||||
import com.alibaba.excel.write.metadata.style.WriteCellStyle; | |||||
import com.alibaba.excel.write.metadata.style.WriteFont; | |||||
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; | |||||
/** | |||||
* <p> | |||||
* ExcelExportStyle | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 01:39 2022/11/5 | |||||
*/ | |||||
public class ExcelExportStyle { | |||||
public static HorizontalCellStyleStrategy formalStyle() { | |||||
// 表头样式策略 | |||||
WriteCellStyle headStyle = new WriteCellStyle(); | |||||
// 是否换行 | |||||
headStyle.setWrapped(false); | |||||
// 水平对齐方式 | |||||
headStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); | |||||
// 垂直对齐方式 | |||||
headStyle.setVerticalAlignment(VerticalAlignment.CENTER); | |||||
// 前景色 | |||||
headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); | |||||
// 背景色 | |||||
headStyle.setFillBackgroundColor(IndexedColors.AUTOMATIC.getIndex()); | |||||
// 设置为1时,单元格将被前景色填充 | |||||
headStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); | |||||
// 控制单元格是否应自动调整大小以适应文本过长时的大小 | |||||
headStyle.setShrinkToFit(false); | |||||
// 单元格边框类型 | |||||
headStyle.setBorderBottom(BorderStyle.NONE); | |||||
headStyle.setBorderLeft(BorderStyle.NONE); | |||||
headStyle.setBorderRight(BorderStyle.NONE); | |||||
headStyle.setBorderTop(BorderStyle.NONE); | |||||
// 单元格边框颜色 | |||||
headStyle.setLeftBorderColor(IndexedColors.BLACK.index); | |||||
headStyle.setRightBorderColor(IndexedColors.BLACK.index); | |||||
headStyle.setTopBorderColor(IndexedColors.BLACK.index); | |||||
headStyle.setBottomBorderColor(IndexedColors.BLACK.index); | |||||
// 字体策略 | |||||
WriteFont writeFont = new WriteFont(); | |||||
// 是否加粗/黑体 | |||||
writeFont.setBold(false); | |||||
// 字体颜色 | |||||
writeFont.setColor(Font.COLOR_NORMAL); | |||||
// 字体名称 | |||||
writeFont.setFontName("宋体"); | |||||
// 字体大小 | |||||
writeFont.setFontHeightInPoints((short) 11); | |||||
// 是否使用斜体 | |||||
writeFont.setItalic(false); | |||||
// 是否在文本中使用横线删除 | |||||
writeFont.setStrikeout(false); | |||||
// 设置要使用的文本下划线的类型 | |||||
writeFont.setUnderline(Font.U_NONE); | |||||
// 设置要使用的字符集 | |||||
writeFont.setCharset((int) Font.DEFAULT_CHARSET); | |||||
headStyle.setWriteFont(writeFont); | |||||
// 内容样式策略策略 | |||||
WriteCellStyle contentStyle = new WriteCellStyle(); | |||||
contentStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); | |||||
contentStyle.setHorizontalAlignment(HorizontalAlignment.GENERAL); | |||||
contentStyle.setBorderBottom(BorderStyle.NONE); | |||||
contentStyle.setBorderLeft(BorderStyle.NONE); | |||||
contentStyle.setBorderRight(BorderStyle.NONE); | |||||
contentStyle.setBorderTop(BorderStyle.NONE); | |||||
contentStyle.setFillPatternType(FillPatternType.NO_FILL); | |||||
contentStyle.setWrapped(false); | |||||
return new HorizontalCellStyleStrategy(headStyle, contentStyle); | |||||
} | |||||
} |
@@ -16,4 +16,8 @@ public interface TaskContant { | |||||
public static final String HOST_207 = "iZbp13nwyvib53j4j1p2xoZ"; | public static final String HOST_207 = "iZbp13nwyvib53j4j1p2xoZ"; | ||||
} | } | ||||
class Wflow { | |||||
public static final String DEFAULT_FORM_NAME = "丽水申报项目表单"; | |||||
} | |||||
} | } |
@@ -1,21 +1,37 @@ | |||||
package com.ningdatech.pmapi.scheduler.task; | package com.ningdatech.pmapi.scheduler.task; | ||||
import cn.hutool.core.bean.BeanUtil; | |||||
import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||
import cn.hutool.core.date.StopWatch; | import cn.hutool.core.date.StopWatch; | ||||
import cn.hutool.core.util.IdUtil; | |||||
import com.alibaba.fastjson.JSON; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
import com.google.common.collect.Maps; | |||||
import com.ningdatech.basic.exception.BizException; | import com.ningdatech.basic.exception.BizException; | ||||
import com.ningdatech.pmapi.scheduler.contants.TaskContant; | import com.ningdatech.pmapi.scheduler.contants.TaskContant; | ||||
import com.ningdatech.pmapi.sys.contants.RegionContant; | import com.ningdatech.pmapi.sys.contants.RegionContant; | ||||
import com.ningdatech.pmapi.sys.entity.Region; | import com.ningdatech.pmapi.sys.entity.Region; | ||||
import com.ningdatech.pmapi.sys.service.IRegionService; | import com.ningdatech.pmapi.sys.service.IRegionService; | ||||
import com.wflow.bean.entity.WflowForms; | |||||
import com.wflow.bean.entity.WflowModelHistorys; | |||||
import com.wflow.bean.entity.WflowModels; | |||||
import com.wflow.contants.WflowContant; | |||||
import com.wflow.mapper.WflowModelHistorysMapper; | |||||
import com.wflow.mapper.WflowModelsMapper; | |||||
import com.wflow.workflow.service.ProcessModelService; | |||||
import com.wflow.workflow.service.WflowFormsService; | |||||
import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.scheduling.annotation.Scheduled; | import org.springframework.scheduling.annotation.Scheduled; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
import javax.annotation.Resource; | |||||
import java.net.InetAddress; | import java.net.InetAddress; | ||||
import java.net.UnknownHostException; | import java.net.UnknownHostException; | ||||
import java.util.List; | |||||
import java.time.LocalDateTime; | |||||
import java.time.ZoneOffset; | |||||
import java.util.*; | |||||
/** | /** | ||||
* @author ZPF | * @author ZPF | ||||
@@ -29,8 +45,16 @@ public class InitProcessTask { | |||||
private final IRegionService regionService; | private final IRegionService regionService; | ||||
private final WflowFormsService formsService; | |||||
private final ProcessModelService processModelService; | |||||
private final WflowModelHistorysMapper modelHistoriesMapper; | |||||
private final WflowModelsMapper modelsMapper; | |||||
// 定时更新车辆状态 | // 定时更新车辆状态 | ||||
@Scheduled(cron = "0 52 15 18 1 ?") | |||||
@Scheduled(cron = "0 47 15 28 1 ?") | |||||
public void doTask() throws UnknownHostException { | public void doTask() throws UnknownHostException { | ||||
if (TaskContant.Host.HOST_ZPF.equals(InetAddress.getLocalHost().getHostName())) { | if (TaskContant.Host.HOST_ZPF.equals(InetAddress.getLocalHost().getHostName())) { | ||||
log.info("=========== 初始化丽水二期 系统表单和流程配置 ======== 任务开始"); | log.info("=========== 初始化丽水二期 系统表单和流程配置 ======== 任务开始"); | ||||
@@ -45,14 +69,85 @@ public class InitProcessTask { | |||||
throw new BizException("丽水地区数据为空 任务结束!"); | throw new BizException("丽水地区数据为空 任务结束!"); | ||||
} | } | ||||
//2.首先插入表单默认配置 | |||||
// Map<String,WflowForms> formsMap = Maps.newConcurrentMap(); | |||||
// //2.首先插入表单默认配置 | |||||
// for(Region region : regions){ | |||||
// log.info("当前初始化的是 【{}】 表单信息",region.getName()); | |||||
// | |||||
// WflowForms existsForm = formsService.getOne(Wrappers.lambdaQuery(WflowForms.class) | |||||
// .eq(WflowForms::getRegionCode, region.getRegionCode()) | |||||
// .last("limit 1")); | |||||
// if(Objects.nonNull(existsForm)){ | |||||
// log.info("当前区域 【{}】 已经有表单数据 不需要初始化",region.getName()); | |||||
// formsMap.put(existsForm.getRegionCode(),existsForm); | |||||
// continue; | |||||
// } | |||||
// | |||||
// WflowForms wflowForms = new WflowForms(); | |||||
// wflowForms.setFormId("fm" + IdUtil.objectId()); | |||||
// wflowForms.setCreateOn(LocalDateTime.now()); | |||||
// wflowForms.setUpdateOn(LocalDateTime.now()); | |||||
// wflowForms.setFormName(TaskContant.Wflow.DEFAULT_FORM_NAME); | |||||
// wflowForms.setRegionCode(region.getRegionCode()); | |||||
// wflowForms.setRegionName(region.getName()); | |||||
// if(formsService.save(wflowForms)){ | |||||
// log.info("当前区域 【{}】 表单数据已经保存成功",region.getName()); | |||||
// formsMap.put(wflowForms.getRegionCode(),wflowForms); | |||||
// }else{ | |||||
// log.info("当前区域 【{}】 表单数据已经保存失败",region.getName()); | |||||
// } | |||||
// } | |||||
//3.接着插入流程默认配置 | |||||
for(Region region : regions){ | for(Region region : regions){ | ||||
log.info("当前初始化的是 【{}】",region.getName()); | |||||
log.info("当前初始化的是 【{}】 流程配置",region.getName()); | |||||
if(processModelService.count(Wrappers.lambdaQuery(WflowModels.class) | |||||
.eq(WflowModels::getRegionCode,region.getRegionCode())) > 0){ | |||||
log.info("当前区域 【{}】 已经有流程数据 不需要初始化",region.getName()); | |||||
continue; | |||||
} | |||||
// WflowForms form = formsMap.get(region.getRegionCode()); | |||||
// if(Objects.isNull(form)){ | |||||
// log.info("此区域 【{}】 没有对应form 不进行 流程配置初始化",region.getName()); | |||||
// continue; | |||||
// } | |||||
WflowModelHistorys models = new WflowModelHistorys(); | |||||
models.setCreated(GregorianCalendar.getInstance().getTime()); | |||||
models.setFormId("wf" + IdUtil.objectId()); | |||||
models.setVersion(1); | |||||
models.setGroupId(1); | |||||
models.setProcessDefId("pd" + IdUtil.objectId()); | |||||
models.setRegionCode(region.getRegionCode()); | |||||
models.setFormName(TaskContant.Wflow.DEFAULT_FORM_NAME); | |||||
WflowModels wflowModels = new WflowModels(); | |||||
BeanUtil.copyProperties(models, wflowModels); | |||||
wflowModels.setFormId(models.getFormId()); | |||||
wflowModels.setIsDelete(false); | |||||
wflowModels.setIsStop(false); | |||||
wflowModels.setUpdated(new Date()); | |||||
wflowModels.setSort(0); | |||||
wflowModels.setProcessDefId(models.getProcessDefId()); | |||||
wflowModels.setFormName(models.getFormName()); | |||||
// wflowModels.setFormItems(JSON.toJSONString(form)); | |||||
wflowModels.setGroupId(models.getGroupId()); | |||||
wflowModels.setRegionCode(models.getRegionCode()); | |||||
// model.setProcess(); | |||||
// model.setSettings(); | |||||
if(modelHistoriesMapper.insert(models) > 0){ | |||||
//初始的流程在部署表也存一份,用来查询 | |||||
modelsMapper.insert(wflowModels); | |||||
log.info("当前区域 【{}】 流程数据已经保存成功",region.getName()); | |||||
}else{ | |||||
log.info("当前区域 【{}】 流程数据已经保存失败",region.getName()); | |||||
} | |||||
} | } | ||||
stopWatch.stop(); | stopWatch.stop(); | ||||
log.info("=========== 更新车辆在线状态 ======== 任务结束 {}s",stopWatch.getTotalTimeSeconds()); | |||||
log.info("=========== 初始化丽水二期 系统表单和流程配置 ======== 任务结束 {}s",stopWatch.getTotalTimeSeconds()); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -0,0 +1,61 @@ | |||||
package com.ningdatech.pmapi.todocenter.controller; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import javax.validation.Valid; | |||||
import com.ningdatech.pmapi.common.util.ExcelDownUtil; | |||||
import org.springframework.web.bind.annotation.GetMapping; | |||||
import org.springframework.web.bind.annotation.ModelAttribute; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.web.bind.annotation.RestController; | |||||
import com.ningdatech.basic.model.ApiResponse; | |||||
import com.ningdatech.basic.model.PageVo; | |||||
import com.ningdatech.pmapi.todocenter.manage.TodoCenterManage; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqToBeProcessedDTO; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProcessedDTO; | |||||
import io.swagger.annotations.Api; | |||||
import lombok.AllArgsConstructor; | |||||
/** | |||||
* <p> | |||||
* 待办中心 前端控制器 | |||||
* </p> | |||||
* | |||||
* @author CMM | |||||
* @since 2023-01-12 | |||||
*/ | |||||
@RestController | |||||
@AllArgsConstructor | |||||
@Api(tags = "待办中心控制器") | |||||
@RequestMapping("/api/v1/todo-center") | |||||
public class TodoCenterController { | |||||
private final TodoCenterManage todoCenterManage; | |||||
/** | |||||
* 待办中心-待我处理项目列表查询 | |||||
* @param param | |||||
* @return | |||||
*/ | |||||
@GetMapping("/NotAppendProjectList") | |||||
public ApiResponse<PageVo<ResToBeProcessedDTO>> queryProjectList(@Valid @ModelAttribute ReqToBeProcessedDTO param){ | |||||
PageVo<ResToBeProcessedDTO> result = todoCenterManage.queryProjectList(param); | |||||
return ApiResponse.ofSuccess(result); | |||||
} | |||||
/** | |||||
* 待办中心-待我处理项目列表导出 | |||||
* | |||||
* @param param | |||||
* @param response | |||||
* @return void | |||||
*/ | |||||
@GetMapping("/export") | |||||
public void exportProjectList(ReqToBeProcessedDTO param, HttpServletResponse response){ | |||||
ExcelDownUtil.downXlsx(response,param,todoCenterManage::exportProjectList); | |||||
} | |||||
} |
@@ -0,0 +1,70 @@ | |||||
package com.ningdatech.pmapi.todocenter.enums; | |||||
import java.util.Objects; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import io.swagger.annotations.ApiModel; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* 是否增补项目枚举 | |||||
* @author CMM | |||||
*/ | |||||
@Getter | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
@ApiModel(value = "IsAppendProjectEnum", description = "是否增补项目-枚举") | |||||
public enum IsAppendProjectEnum { | |||||
/** | |||||
* 非增补项目 | |||||
*/ | |||||
NOT_APPEND_PROJECT(0, "非增补项目"), | |||||
/** | |||||
*增补项目 | |||||
*/ | |||||
APPEND_PROJECT(1, "增补项目"); | |||||
private Integer code; | |||||
private String desc; | |||||
public String getDesc() { | |||||
return desc; | |||||
} | |||||
public void setDesc(String desc) { | |||||
this.desc = desc; | |||||
} | |||||
public static String getDescByCode(Integer code) { | |||||
if(Objects.isNull(code)){ | |||||
return StringUtils.EMPTY; | |||||
} | |||||
for (IsAppendProjectEnum t : IsAppendProjectEnum.values()) { | |||||
if (code.equals(t.getCode())) { | |||||
return t.desc; | |||||
} | |||||
} | |||||
return StringUtils.EMPTY; | |||||
} | |||||
public static IsAppendProjectEnum getEnumByValue(Integer code) { | |||||
if(Objects.isNull(code)){ | |||||
return null; | |||||
} | |||||
for (IsAppendProjectEnum t : IsAppendProjectEnum.values()) { | |||||
if (code.equals(t.getCode())) { | |||||
return t; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
public boolean eq(String val) { | |||||
return this.name().equals(val); | |||||
} | |||||
} |
@@ -0,0 +1,93 @@ | |||||
package com.ningdatech.pmapi.todocenter.enums; | |||||
import java.util.Objects; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import io.swagger.annotations.ApiModel; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* 待办中心-流程状态枚举 | |||||
* @author CMM | |||||
*/ | |||||
@Getter | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
@ApiModel(value = "ProcessStatusEnum", description = "流程状态-枚举") | |||||
public enum ProcessStatusEnum { | |||||
/** | |||||
* 审核中 | |||||
*/ | |||||
UNDER_REVIEW(1, "审核中"), | |||||
/** | |||||
* 被退回 | |||||
*/ | |||||
BE_RETURNED(2, "被退回"), | |||||
/** | |||||
* 被驳回 | |||||
*/ | |||||
BE_REJECTED(3,"被驳回"), | |||||
/** | |||||
* 审核通过 | |||||
*/ | |||||
APPROVED(4,"审核通过"); | |||||
private Integer code; | |||||
private String desc; | |||||
public String getDesc() { | |||||
return desc; | |||||
} | |||||
public void setDesc(String desc) { | |||||
this.desc = desc; | |||||
} | |||||
public static String getDescByCode(Integer code) { | |||||
if(Objects.isNull(code)){ | |||||
return StringUtils.EMPTY; | |||||
} | |||||
for (ProcessStatusEnum t : ProcessStatusEnum.values()) { | |||||
if (code.equals(t.getCode())) { | |||||
return t.desc; | |||||
} | |||||
} | |||||
return StringUtils.EMPTY; | |||||
} | |||||
public static Integer getCodeByDesc(String desc) { | |||||
if(Objects.isNull(desc)){ | |||||
return null; | |||||
} | |||||
for (ProcessStatusEnum t : ProcessStatusEnum.values()) { | |||||
if (desc.equals(t.getCode())) { | |||||
return t.code; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
public static ProcessStatusEnum getEnumByValue(Integer code) { | |||||
if(Objects.isNull(code)){ | |||||
return null; | |||||
} | |||||
for (ProcessStatusEnum t : ProcessStatusEnum.values()) { | |||||
if (code.equals(t.getCode())) { | |||||
return t; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
public boolean eq(String val) { | |||||
return this.name().equals(val); | |||||
} | |||||
} |
@@ -0,0 +1,152 @@ | |||||
package com.ningdatech.pmapi.todocenter.manage; | |||||
import cn.hutool.core.collection.CollectionUtil; | |||||
import com.alibaba.excel.EasyExcel; | |||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||||
import com.ningdatech.basic.util.NdDateUtils; | |||||
import com.ningdatech.pmapi.common.constant.ProjectDeclareConstants; | |||||
import com.ningdatech.pmapi.common.util.ExcelDownUtil; | |||||
import com.ningdatech.pmapi.common.util.ExcelExportStyle; | |||||
import com.ningdatech.pmapi.todocenter.enums.ProcessStatusEnum; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProjectListExportDTO; | |||||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||||
import com.wflow.workflow.bean.dto.ProcessInstanceOwnerDto; | |||||
import com.wflow.workflow.bean.process.OrgUser; | |||||
import com.wflow.workflow.bean.vo.ProcessProgressVo; | |||||
import com.wflow.workflow.bean.vo.ProcessTaskVo; | |||||
import com.wflow.workflow.service.ProcessInstanceService; | |||||
import com.wflow.workflow.service.UserDeptOrLeaderService; | |||||
import org.flowable.engine.RepositoryService; | |||||
import org.flowable.engine.RuntimeService; | |||||
import org.flowable.engine.TaskService; | |||||
import org.flowable.engine.repository.ProcessDefinition; | |||||
import org.flowable.engine.runtime.ProcessInstance; | |||||
import org.flowable.task.api.Task; | |||||
import org.flowable.task.api.TaskQuery; | |||||
import org.springframework.stereotype.Component; | |||||
import com.ningdatech.basic.model.PageVo; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqToBeProcessedDTO; | |||||
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProcessedDTO; | |||||
import lombok.RequiredArgsConstructor; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.IOException; | |||||
import java.util.HashSet; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
import java.util.stream.Collectors; | |||||
/** | |||||
* @author CMM | |||||
* @since 2023/01/12 16:09 | |||||
*/ | |||||
@Component | |||||
@RequiredArgsConstructor | |||||
public class TodoCenterManage { | |||||
private final TaskService taskService; | |||||
private final RepositoryService repositoryService; | |||||
private final RuntimeService runtimeService; | |||||
private final UserDeptOrLeaderService userDeptOrLeaderService; | |||||
private final ProcessInstanceService processService; | |||||
public PageVo<ResToBeProcessedDTO> queryProjectList(ReqToBeProcessedDTO param) { | |||||
// 获取登录用户ID | |||||
Long userId = LoginUserUtil.getUserId(); | |||||
// 获取入参分页信息 | |||||
Integer pageSize = param.getPageSize(); | |||||
Integer pageNumber = param.getPageNumber(); | |||||
TaskQuery taskQuery = taskService.createTaskQuery(); | |||||
taskQuery.active().taskCandidateOrAssigned(String.valueOf(userId)).orderByTaskCreateTime().desc(); | |||||
Page<ResToBeProcessedDTO> page = param.page(); | |||||
List<Task> taskList = taskQuery.listPage(pageSize * (pageNumber - 1), pageSize); | |||||
Set<String> staterUsers = new HashSet<>(); | |||||
List<ResToBeProcessedDTO> resVos = taskList.stream().map(task -> { | |||||
String nodeId = task.getTaskDefinitionKey(); | |||||
String instanceId = task.getProcessInstanceId(); | |||||
ProcessProgressVo instanceProgress = processService.getInstanceProgress(nodeId, instanceId); | |||||
Map<String, Object> formData = instanceProgress.getFormData(); | |||||
String status = instanceProgress.getStatus(); | |||||
Boolean temporarySupplement = (Boolean) formData.get(ProjectDeclareConstants.BasicInformation.TEMPORARY_SUPPLEMENT); | |||||
ResToBeProcessedDTO res = new ResToBeProcessedDTO(); | |||||
if (temporarySupplement.equals(param.getIsSupplement())) { | |||||
ProcessDefinition processDef = repositoryService.createProcessDefinitionQuery() | |||||
.processDefinitionId(task.getProcessDefinitionId()) | |||||
.singleResult(); | |||||
//从缓存取 | |||||
ProcessInstanceOwnerDto owner = runtimeService.getVariable(task.getExecutionId(), "owner", ProcessInstanceOwnerDto.class); | |||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); | |||||
staterUsers.add(owner.getOwner()); | |||||
ProcessTaskVo processTaskVo = ProcessTaskVo.builder() | |||||
.taskId(task.getId()) | |||||
.taskName(task.getName()) | |||||
.taskDefKey(task.getTaskDefinitionKey()) | |||||
.processDefId(task.getProcessDefinitionId()) | |||||
.executionId(task.getExecutionId()) | |||||
.nodeId(nodeId) | |||||
.deployId(processDef.getDeploymentId()) | |||||
.processDefName(processDef.getName()) | |||||
.version(processDef.getVersion()) | |||||
.instanceId(instanceId) | |||||
.ownerId(processInstance.getStartUserId()) | |||||
.ownerDeptId(owner.getOwnerDeptId()) | |||||
.ownerDeptName(owner.getOwnerDeptName()) | |||||
.createTime(processInstance.getStartTime()) | |||||
.taskCreateTime(task.getCreateTime()) | |||||
.build(); | |||||
res.setProcessTaskVo(processTaskVo); | |||||
String projectName = (String) formData.get(ProjectDeclareConstants.BasicInformation.PROJECT_NAME); | |||||
res.setProjectName(projectName); | |||||
res.setReportUnitId(owner.getOwnerDeptId()); | |||||
res.setReportUnitName(owner.getOwnerDeptName()); | |||||
res.setReportAmount((Integer) formData.get(ProjectDeclareConstants.FundDeclareInfo.DECLARE_AMOUNT)); | |||||
res.setBudgetYear((Integer) formData.get(ProjectDeclareConstants.BasicInformation.BUDGET_YEAR)); | |||||
res.setProcessStatus(ProcessStatusEnum.getCodeByDesc(status)); | |||||
res.setProcessStatusName(status); | |||||
res.setProcessLaunchTime(NdDateUtils.date2LocalDateTime(processInstance.getStartTime())); | |||||
} | |||||
return res; | |||||
}).collect(Collectors.toList()); | |||||
List<ResToBeProcessedDTO> result = resVos.stream() | |||||
.filter(r -> r.getProjectName().equals(param.getProjectName())) | |||||
.filter(r -> r.getReportUnitName().equals(param.getReportUnitName())) | |||||
.filter(r -> r.getBudgetYear().equals(param.getBudgetYear())) | |||||
.filter(r -> r.getProcessLaunchTime().isBefore(param.getProcessLaunchStartTime())) | |||||
.filter(r -> r.getProcessLaunchTime().isAfter(param.getProcessLaunchEndTime())).collect(Collectors.toList()); | |||||
//取用户信息,减少数据库查询,一次构建 | |||||
if (CollectionUtil.isNotEmpty(staterUsers)) { | |||||
Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(staterUsers); | |||||
page.setRecords(result.stream().peek(v -> v.getProcessTaskVo().setOwner(userMap.get(v.getProcessTaskVo().getOwnerId()))).collect(Collectors.toList())); | |||||
} | |||||
return PageVo.of(resVos,page.getTotal()); | |||||
} | |||||
public void exportProjectList(HttpServletResponse response, ReqToBeProcessedDTO param) { | |||||
PageVo<ResToBeProcessedDTO> page = | |||||
queryProjectList(param); | |||||
List<ResToBeProcessedDTO> collect = (List<ResToBeProcessedDTO>) page.getRecords(); | |||||
String fileName = null; | |||||
if (param.getIsSupplement()){ | |||||
fileName = "增补项目列表"; | |||||
}else { | |||||
fileName = "非增补项目列表"; | |||||
} | |||||
ExcelDownUtil.setFileName(fileName,response); | |||||
//数据导出处理函数 | |||||
try { | |||||
EasyExcel.write(response.getOutputStream(), ResToBeProjectListExportDTO.class) | |||||
.autoCloseStream(false) | |||||
.registerWriteHandler(ExcelExportStyle.formalStyle()) | |||||
.sheet(fileName) | |||||
.doWrite(collect); | |||||
} catch (IOException e) { | |||||
throw new RuntimeException(e); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,42 @@ | |||||
package com.ningdatech.pmapi.todocenter.model.dto.req; | |||||
import java.io.Serializable; | |||||
import java.time.LocalDateTime; | |||||
import com.ningdatech.basic.model.PagePo; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* 待办中心-待我处理查询实体信息 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/12 16:01 | |||||
*/ | |||||
@Data | |||||
@NoArgsConstructor | |||||
@AllArgsConstructor | |||||
public class ReqToBeProcessedDTO extends PagePo implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
@ApiModelProperty("项目名称") | |||||
private String projectName; | |||||
@ApiModelProperty("申报单位名称") | |||||
private String reportUnitName; | |||||
@ApiModelProperty("预算年度") | |||||
private Integer budgetYear; | |||||
@ApiModelProperty("流程发起开始时间") | |||||
private LocalDateTime processLaunchStartTime; | |||||
@ApiModelProperty("流程发起结束时间") | |||||
private LocalDateTime processLaunchEndTime; | |||||
@ApiModelProperty(value = "是否增补项目",allowableValues = "非增补项目 false,增补项目 true") | |||||
private Boolean isSupplement; | |||||
} |
@@ -0,0 +1,53 @@ | |||||
package com.ningdatech.pmapi.todocenter.model.dto.res; | |||||
import java.io.Serializable; | |||||
import java.time.LocalDateTime; | |||||
import com.wflow.workflow.bean.vo.ProcessTaskVo; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
/** | |||||
* 待办中心-待我处理返回实体信息 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/12 14:57 | |||||
*/ | |||||
@Data | |||||
@NoArgsConstructor | |||||
@AllArgsConstructor | |||||
public class ResToBeProcessedDTO implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
@ApiModelProperty("项目ID") | |||||
private String projectId; | |||||
@ApiModelProperty("项目名称") | |||||
private String projectName; | |||||
@ApiModelProperty("申报单位ID") | |||||
private String reportUnitId; | |||||
@ApiModelProperty("申报单位名称") | |||||
private String reportUnitName; | |||||
@ApiModelProperty("申报金额") | |||||
private Integer reportAmount; | |||||
@ApiModelProperty("预算年度") | |||||
private Integer budgetYear; | |||||
@ApiModelProperty("流程状态") | |||||
private Integer processStatus; | |||||
@ApiModelProperty("流程状态名称") | |||||
private String processStatusName; | |||||
@ApiModelProperty("流程发起时间") | |||||
private LocalDateTime processLaunchTime; | |||||
@ApiModelProperty("流程任务信息") | |||||
private ProcessTaskVo processTaskVo; | |||||
} |
@@ -0,0 +1,42 @@ | |||||
package com.ningdatech.pmapi.todocenter.model.dto.res; | |||||
import com.alibaba.excel.annotation.ExcelProperty; | |||||
import com.wflow.workflow.bean.vo.ProcessTaskVo; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import java.io.Serializable; | |||||
import java.time.LocalDateTime; | |||||
/** | |||||
* 待办中心待我处理项目列表导出实体 | |||||
* | |||||
* @author CMM | |||||
* @since 2023/01/19 16:42 | |||||
*/ | |||||
@Data | |||||
@NoArgsConstructor | |||||
@AllArgsConstructor | |||||
public class ResToBeProjectListExportDTO implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
@ExcelProperty("项目名称") | |||||
private String projectName; | |||||
@ExcelProperty("申报单位") | |||||
private String reportUnitName; | |||||
@ExcelProperty("申报金额") | |||||
private Integer reportAmount; | |||||
@ExcelProperty("预算年度") | |||||
private Integer budgetYear; | |||||
@ExcelProperty("流程状态") | |||||
private String processStatusName; | |||||
@ExcelProperty("发起时间") | |||||
private LocalDateTime processLaunchTime; | |||||
} |
@@ -0,0 +1,71 @@ | |||||
package com.ningdatech.pmapi.user.model; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
import org.springframework.security.core.GrantedAuthority; | |||||
import org.springframework.security.core.userdetails.UserDetails; | |||||
import com.ningdatech.basic.auth.AbstractLoginUser; | |||||
import lombok.Data; | |||||
import lombok.EqualsAndHashCode; | |||||
/** | |||||
* @author LiuXinXin | |||||
* @date 2022/8/1 下午3:32 | |||||
*/ | |||||
@Data | |||||
@EqualsAndHashCode(callSuper = true) | |||||
public class UserInfoDetails extends AbstractLoginUser implements UserDetails { | |||||
private static final long serialVersionUID = 1L; | |||||
private String nickName; | |||||
private String password; | |||||
private List<String> roleList; | |||||
private Integer dataScope; | |||||
private Long roleId; | |||||
private Long companyId; | |||||
private String companyName; | |||||
private Long regionId; | |||||
private String regionName; | |||||
/** | |||||
* 获取用户权限 | |||||
*/ | |||||
@Override | |||||
public Collection<? extends GrantedAuthority> getAuthorities() { | |||||
return new ArrayList<>(); | |||||
} | |||||
@Override | |||||
public boolean isAccountNonExpired() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isAccountNonLocked() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isCredentialsNonExpired() { | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isEnabled() { | |||||
return true; | |||||
} | |||||
} |
@@ -0,0 +1,18 @@ | |||||
package com.ningdatech.pmapi.user.util; | |||||
import com.ningdatech.basic.auth.AbstractLoginUserUtil; | |||||
import com.ningdatech.pmapi.user.model.UserInfoDetails; | |||||
/** | |||||
* @Author liuxinxin | |||||
* @Date 2022/9/30 12:26 下午 | |||||
* @Version 1.0 | |||||
**/ | |||||
public class LoginUserUtil extends AbstractLoginUserUtil { | |||||
public static UserInfoDetails loginUserDetail() { | |||||
return getLoginUserPrincipal(); | |||||
} | |||||
} |