business/src/main/java/com/ycl/mapper/ProjectInfoMapper.java
@@ -1,5 +1,6 @@ package com.ycl.mapper; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ycl.common.annotation.DataScope; @@ -34,6 +35,7 @@ * 分页 */ @DataScope(deptAlias = "d") @InterceptorIgnore(tenantLine = "true") IPage getPage(@Param("query") ProjectInfoQuery query, IPage page); @DataScope(deptAlias = "d") @@ -42,4 +44,6 @@ List<ProjectVO> selectProjectDetailByIds(@Param("dataIdList") List<Long> dataIdList); ProjectInfo queryById(Integer recordId); List<ProjectInfo> checkProjectNameAndIdIsUnique(@Param("id")Long id,@Param("name") String name,@Param("code")String code); } business/src/main/java/com/ycl/service/ProcessConfigInfoService.java
@@ -1,5 +1,6 @@ package com.ycl.service; import com.ycl.domain.entity.ProcessCoding; import com.ycl.domain.entity.ProcessConfigInfo; import com.baomidou.mybatisplus.extension.service.IService; import com.ycl.common.base.Result; @@ -45,4 +46,5 @@ * @return */ Result getPage(ProcessConfigInfoQuery query); } business/src/main/java/com/ycl/service/impl/ProcessConfigInfoServiceImpl.java
@@ -117,4 +117,5 @@ } return Result.ok().data(page.getRecords()).total(page.getTotal()); } } business/src/main/java/com/ycl/service/impl/ProjectInfoServiceImpl.java
@@ -113,8 +113,11 @@ entity.setCreateBy(userId); entity.setUpdateBy(userId); //如果是储备项目(未开工项目)不需要审核 if(ProjectConstant.COMMIT.equals(entity.getUsedStatus()) && ProjectStatusEnum.PENDDING.getType().equals(entity.getProjectStatus())){ if (ProjectConstant.COMMIT.equals(entity.getUsedStatus()) && ProjectStatusEnum.PENDDING.getType().equals(entity.getProjectStatus())) { entity.setUsedStatus(ProjectConstant.PASS); } if(!checkProjectNameAndIdIsUnique(entity,null)){ return Result.error("项目名或项目码已存在"); } baseMapper.insert(entity); addPlan(entity.getId()); //添加计划表 @@ -127,12 +130,39 @@ fileService.saveBatch(fileList); //添加项目中标单位 saveUnit(entity.getId(),form.getWinUnitList()); saveUnit(entity.getId(), form.getWinUnitList()); //添加年度投资计划 saveYearPlan(entity.getId(),form.getYearPlanList()); saveYearPlan(entity.getId(), form.getYearPlanList()); return Result.ok("添加成功").data(entity.getId()); } /** * 判断项目名和项目码是否唯一 * @param entity from true 来自add() false 来自edit() * @return */ public boolean checkProjectNameAndIdIsUnique(ProjectInfo entity,Long updateId){ QueryWrapper<ProjectInfo> queryWrapper = new QueryWrapper<ProjectInfo>(); if (updateId == null) { queryWrapper.eq("project_name", entity.getProjectName()); if (StringUtils.isNotEmpty(entity.getProjectCode())) { queryWrapper.or(); queryWrapper.eq("project_code", entity.getProjectCode()); } List<ProjectInfo> project = projectInfoMapper.selectList(queryWrapper); return project == null || project.isEmpty(); }else { List<ProjectInfo> project = projectInfoMapper.checkProjectNameAndIdIsUnique(updateId,entity.getProjectName(),entity.getProjectCode()); return project == null || project.isEmpty(); } } public void addPlan(Long projectInfoId) { Plan plan = new Plan(); @@ -154,6 +184,7 @@ @Override public Result update(ProjectInfoForm form) { ProjectInfo entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); ProjectInfoForm.getEntityByForm(form, entity); @@ -162,6 +193,9 @@ //如果是储备项目(未开工项目)不需要审核 if (ProjectConstant.COMMIT.equals(entity.getUsedStatus()) && ProjectStatusEnum.PENDDING.getType().equals(entity.getProjectStatus())) { entity.setUsedStatus(ProjectConstant.PASS); } if(!checkProjectNameAndIdIsUnique(entity,form.getId())){ return Result.error("项目名或项目码已存在"); } //更新项目信息 baseMapper.updateById(entity); @@ -437,7 +471,8 @@ city.add(item); } else if (ImportanceTypeEnum.SHEHONG_KEY.getType().equals(item.getImportanceType())) { county.add(item); } else if (ImportanceTypeEnum.NORMAL.getType().equals(item.getImportanceType())) { } else // if (ImportanceTypeEnum.NORMAL.getType().equals(item.getImportanceType())) { normal.add(item); } }); @@ -445,22 +480,22 @@ proPhaseCountVO.add(new IndexProPhaseCountVO("储备规划阶段", reserve.size(), reserve.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "储")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "储")); proPhaseCountVO.add(new IndexProPhaseCountVO("项目前期阶段", previous.size(), previous.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "新")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "新")); proPhaseCountVO.add(new IndexProPhaseCountVO("实施阶段", implement.size(), implement.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "建")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "建")); proPhaseCountVO.add(new IndexProPhaseCountVO("竣工投用阶段", finish.size(), finish.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "竣")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "竣")); indexCountVO.setProPhaseCountVO(proPhaseCountVO); @@ -468,22 +503,22 @@ impTypeCountVO.add(new IndexImpTypeCountVO("一般项目", normal.size(), normal.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "普")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "普")); impTypeCountVO.add(new IndexImpTypeCountVO("县重点项目", county.size(), county.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "县")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "县")); impTypeCountVO.add(new IndexImpTypeCountVO("市重点项目", city.size(), city.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "市")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "市")); impTypeCountVO.add(new IndexImpTypeCountVO("省重点项目", province.size(), province.stream(). filter(item -> !StringUtils.isEmpty(item.getTotalInvestment())) .map(item -> new BigDecimal(item.getTotalInvestment()).setScale(2, RoundingMode.HALF_UP)) .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("100000000"), 2, RoundingMode.HALF_UP).toString(), "省")); .reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP).toString(), "省")); indexCountVO.setImpTypeCountVO(impTypeCountVO); return indexCountVO; } @@ -774,12 +809,14 @@ @Transactional(rollbackFor = Exception.class) public Result editProject(ProjectForm form) { if (ObjectUtil.isNotNull(form.getProjectInfoForm())) { if (ObjectUtil.isNull(form.getProjectInfoForm().getId())) { //新增 ((ProjectInfoServiceImpl) AopContext.currentProxy()).add(form.getProjectInfoForm()); return ((ProjectInfoServiceImpl) AopContext.currentProxy()).add(form.getProjectInfoForm()); } else { //更新 ((ProjectInfoServiceImpl) AopContext.currentProxy()).update(form.getProjectInfoForm()); return ((ProjectInfoServiceImpl) AopContext.currentProxy()).update(form.getProjectInfoForm()); } } if (ObjectUtil.isNotNull(form.getProjectInvestmentInfoForm())) { business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java
@@ -89,6 +89,7 @@ private final ISysDeptService deptService; private final ProcessLogService processLogService; private final ISysDictTypeService dictTypeService; private final ProcessConfigInfoService processConfigInfoService; /** * 分页查询 @@ -406,6 +407,20 @@ if (processLogService.taskIsHangup(task.getId(), task.getProcessInstanceId())) { taskVO.setTaskStatus(TaskStatusEnum.HANGUP); } // 计算办理时间 ProcessCoding processCoding = processCodingService.getByTaskId(task.getId()); if (processCoding != null) { if (StringUtils.isNotBlank(processCoding.getOvertime())) { Long overtime = getTime(processCoding.getOvertime()); long durationTime = ((new Date()).getTime() - processCoding.getStartTaskTime().getTime()) / 1000; taskVO.setRemainingTime((overtime - durationTime) / 3600 + "小时"); } else { taskVO.setRemainingTime("-"); } } this.distinctVo(taskVO); vos.add(taskVO); } @@ -413,6 +428,23 @@ result.total(vos.size()); } result.put("taskList", vos); } private Long getTime(String timeStr) { Long time = null; if (StringUtils.isNotBlank(timeStr)) { String[] timeArr = timeStr.split("-"); // 解析天数和小时数 int days = Integer.parseInt(timeArr[0]); int hours = 0; if (timeArr.length > 1) { hours = Integer.parseInt(timeArr[1]); } time = (days * 24L + hours) * 3600L; // //分-秒 // time= (days * 60L) + hours; } return time; } @Override @@ -606,7 +638,7 @@ jsonData.setAfterHandlerIds(afterHandlerIds); jsonData.setAfterHandlerType(form.getPeopleType()); // 发布转办事件 publisher.publishEvent(new TaskLogEvent(this, null,SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), task.getId(), task.getName(),ProcessLogEventTypeEnum.DELEGATE, jsonData)); publisher.publishEvent(new TaskLogEvent(this, null, SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), task.getId(), task.getName(), ProcessLogEventTypeEnum.DELEGATE, jsonData)); return Result.ok("转办成功"); } @@ -617,7 +649,7 @@ Task task = taskService.createTaskQuery().taskId(form.getTaskId()).processInstanceId(form.getProcessInsId()).singleResult(); if (Objects.nonNull(task)) { // 添加跳过日志 publisher.publishEvent(new TaskLogEvent(this, null,SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(),ProcessLogEventTypeEnum.JUMP, new JumpData(form.getDesc()))); publisher.publishEvent(new TaskLogEvent(this, null, SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(), ProcessLogEventTypeEnum.JUMP, new JumpData(form.getDesc()))); // 查出该任务绑定的表单 Map<String, Object> data = new HashMap<>(1); @@ -661,7 +693,7 @@ } dataList.add(jsonData); //添加督办日志 publisher.publishEvent(new TaskLogEvent(this, processLog.getId(), processLog.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(),ProcessLogEventTypeEnum.SUPERVISE, dataList)); publisher.publishEvent(new TaskLogEvent(this, processLog.getId(), processLog.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(), ProcessLogEventTypeEnum.SUPERVISE, dataList)); return Result.ok("操作成功"); } @@ -691,7 +723,7 @@ task.getName(), ProcessLogEventTypeEnum.HANGUP, new HangupData(form.getReason()) )); )); return Result.ok("操作成功"); } @@ -747,11 +779,11 @@ newV.put(task.getTaskDefinitionKey() + "&" + key, form.getVariables().get(key)); //字典里有就放入流程变量中 if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(dictList) && dictList.contains(key)) { processVariables.put(key,form.getVariables().get(key)); processVariables.put(key, form.getVariables().get(key)); } } } if( !processVariables.isEmpty() ) { if (!processVariables.isEmpty()) { taskService.setVariables(form.getTaskId(), processVariables); } business/src/main/java/com/ycl/task/FlowableTask.java
@@ -44,6 +44,7 @@ private ProcessLogService processLogService; @Autowired private ProcessLogMapper processLogMapper; /** * 赋码任务 * 两个逻辑 改项目码、改节点颜色 @@ -111,17 +112,16 @@ durationTime = subNodeHangupTime(hangupLogMap, task, durationTime); String status = GREEN; // 默认状态为绿色 if (redTime != null && redTime !=0 && durationTime >= redTime) { if (redTime != null && redTime != 0 && durationTime >= redTime) { status = RED; // 如果超过红色时间阈值,则状态为红色 } else if (yellowTime != null && yellowTime !=0 && durationTime >= yellowTime) { } else if (yellowTime != null && yellowTime != 0 && durationTime >= yellowTime) { status = YELLOW; // 否则,如果超过黄色时间阈值,则状态为黄色 } //处理办理期限 String overtimeStatus = NORMAL; if (overtime != null && overtime !=0 && durationTime >= overtime) { if (overtime != null && overtime != 0 && durationTime >= overtime) { overtimeStatus = OVERTIME; // 如果超过办理期限 } else if (overtime != null && overtime != 0 && durationTime >= (overtime - 12 * 60 * 60)) { } else if (overtime != null && overtime != 0 && durationTime >= (overtime - 12 * 60 * 60)) { overtimeStatus = WILLOVERTIME; // 如果临期(固定超时前12小时为临期) } // else if (overtime != null && overtime != 0 && durationDay >= (overtime - 60)) { @@ -130,9 +130,10 @@ map.get(status).add(task.getProcessInstanceId()); processCoding.setStatus(status); processCoding.setOvertimeStatus(overtimeStatus); processCoding.setStartTaskTime(task.getCreateTime()); list.add(processCoding); } catch (Exception e) { log.error(e.getMessage(),"赋码时间格式有误"); log.error(e.getMessage(), "赋码时间格式有误"); } } //更新项目码 business/src/main/resources/mapper/ProjectInfoMapper.xml
@@ -234,4 +234,17 @@ <select id="queryById" resultType="com.ycl.domain.entity.ProjectInfo"> select * from t_project_info where id = #{id} and deleted = 0 </select> <resultMap id="pInfo" type="com.ycl.domain.entity.ProjectInfo"> <id column="id" property="id"/> </resultMap> <select id="checkProjectNameAndIdIsUnique" resultMap="pInfo"> select p.id from t_project_info p where p.project_name =#{name} <if test="code !=null and code !=''"> or p.project_code =#{code} </if> having p.id != #{id} </select> </mapper> business/src/main/resources/mapper/ProjectPlanExamineRecordMapper.xml
@@ -189,7 +189,7 @@ from t_project_plan_examine_record ppe LEFT JOIN t_project_plan_info ppi on ppe.project_plan_info_id = ppi.id LEFT JOIN t_project_plan_record ppr on ppe.project_plan_record_id = ppr.id INNER JOIN t_project_info pi on ppr.project_info_id = pi.id AND pi.deleted = 0 Left JOIN t_project_info pi on ppr.project_info_id = pi.id AND pi.deleted = 0 WHERE ppe.department_user_id = #{userId} or manager_user_id = #{userId} </select> flowable/src/main/java/com/ycl/domain/entity/ProcessCoding.java
@@ -5,6 +5,8 @@ import com.ycl.system.domain.base.AbsEntity; import lombok.Data; import java.util.Date; /** * * @@ -52,4 +54,7 @@ @TableField("overtime_status") /** 任务超时状态 */ private String overtimeStatus; @TableField("start_task_time") private Date startTaskTime; } flowable/src/main/java/com/ycl/mapper/ProcessCodingMapper.java
@@ -36,4 +36,6 @@ * @param list */ void updateBatch(@Param("list") List<ProcessCoding> list); List<ProcessCoding> findByTaskId(@Param("taskId") String taskId); } flowable/src/main/java/com/ycl/service/ProcessCodingService.java
@@ -63,4 +63,7 @@ * @return */ Result all(); ProcessCoding getByTaskId(String id); } flowable/src/main/java/com/ycl/service/impl/ProcessCodingServiceImpl.java
@@ -1,6 +1,8 @@ package com.ycl.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.common.base.Result; import com.ycl.domain.entity.ProcessCoding; @@ -19,7 +21,7 @@ import java.util.stream.Collectors; /** * 服务实现类 * 服务实现类 * * @author flq * @since 2025-01-02 @@ -32,6 +34,7 @@ /** * 添加 * * @param form * @return */ @@ -44,6 +47,7 @@ /** * 修改 * * @param form * @return */ @@ -60,6 +64,7 @@ /** * 批量删除 * * @param ids * @return */ @@ -71,6 +76,7 @@ /** * id删除 * * @param id * @return */ @@ -82,6 +88,7 @@ /** * 分页查询 * * @param query * @return */ @@ -94,6 +101,7 @@ /** * 根据id查找 * * @param id * @return */ @@ -106,6 +114,7 @@ /** * 列表 * * @return */ @Override @@ -116,4 +125,14 @@ .collect(Collectors.toList()); return Result.ok().data(vos); } @Override public ProcessCoding getByTaskId(String taskId) { List<ProcessCoding> list = baseMapper.findByTaskId(taskId); if (list.size() > 0) { return list.get(0); } return null; } } flowable/src/main/resources/mapper/ProcessCodingMapper.xml
@@ -52,6 +52,9 @@ WHERE TPC.deleted = 0 </select> <select id="findByTaskId" resultType="com.ycl.domain.entity.ProcessCoding"> SELECT * from t_process_coding where task_id = #{taskId} </select> <!-- 自定义批量更新,使用前判断list是否为空 转换为sql update t_process_coding start/src/main/resources/application.yml
@@ -5,6 +5,7 @@ # 实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.ycl.**.domain configuration: shrink-whitespaces-in-sql: true #从SQL中删除多余的空格字符 default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler # 通用枚举处理器 # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志打印 global-config: