5-23 修正定时任务逻辑

master
tianxinlei 2026-05-23 13:58:51 +08:00
parent 79caf647ce
commit ac0c567b2a
14 changed files with 194 additions and 139 deletions

View File

@ -10,7 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* - 2 * -
* <p> * <p>
* 10cron = "0 0 0 1 * ?" * 10cron = "0 0 0 1 * ?"
* <p> * <p>
@ -35,9 +35,6 @@ public class FeedbackExceptionCheckJob implements Job {
* <p> * <p>
* XXL-Job * XXL-Job
* SUCCESSFAIL * SUCCESSFAIL
*
* @param param XXL-Job使
* @return ReturnT.SUCCESSReturnT.FAIL_CODE
*/ */
@Override @Override
@JobRegister(cron = "0 55 10 * * ?", jobDesc = "安全责任清单-反馈异常检测", triggerStatus = 1) @JobRegister(cron = "0 55 10 * * ?", jobDesc = "安全责任清单-反馈异常检测", triggerStatus = 1)

View File

@ -10,7 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* - 1 * -
* <p> * <p>
* 10cron = "0 0 0 1 * ?" * 10cron = "0 0 0 1 * ?"
* <p> * <p>
@ -43,12 +43,12 @@ public class TaskStatusUpdateJob implements Job {
@JobRegister(cron = "0 0 0 1 * ?", jobDesc = "安全责任清单-更新清单和任务状态", triggerStatus = 1) @JobRegister(cron = "0 0 0 1 * ?", jobDesc = "安全责任清单-更新清单和任务状态", triggerStatus = 1)
@XxlJob("com.zcloud.safetyDutyList.job.TaskStatusUpdateJob") @XxlJob("com.zcloud.safetyDutyList.job.TaskStatusUpdateJob")
public ReturnT<String> execute(String param) { public ReturnT<String> execute(String param) {
log.info("【安全责任清单】开始执行更新清单和任务状态定时任务"); log.info("【定时任务-安全责任清单-检测任务完成】开始执行更新清单和任务状态定时任务");
try { try {
taskListService.updateExpiredTaskListStatus(); taskListService.updateExpiredTaskListStatus();
log.info("【安全责任清单】更新清单和任务状态定时任务执行完成"); log.info("【定时任务-安全责任清单-检测任务完成】更新清单和任务状态定时任务执行完成");
} catch (Exception e) { } catch (Exception e) {
log.error("【安全责任清单】更新清单和任务状态定时任务执行异常", e); log.error("【定时任务-安全责任清单-检测任务完成】更新清单和任务状态定时任务执行异常", e);
return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage()); return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
} }
return ReturnT.SUCCESS; return ReturnT.SUCCESS;

View File

@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
/** /**
* *
* <p> * <p>
* *
* TaskListServiceI * TaskListServiceI
*/ */
@Api(tags = "执行反馈") @Api(tags = "执行反馈")

View File

@ -17,11 +17,11 @@ import org.springframework.web.bind.annotation.*;
public class StatisticsController { public class StatisticsController {
private final TaskListServiceI taskListService; private final TaskListServiceI taskListService;
@ApiOperation("获取统计信息") // @ApiOperation("获取统计信息")
@PostMapping("/list") // @PostMapping("/list")
public MultiResponse<TaskListStatisticsCO> statistics(@RequestBody TaskListStatisticsQry qry) { // public MultiResponse<TaskListStatisticsCO> statistics(@RequestBody TaskListStatisticsQry qry) {
return taskListService.statistics(qry); // return taskListService.statistics(qry);
} // }
@ApiOperation("获取企业统计(股份端)") @ApiOperation("获取企业统计(股份端)")
@PostMapping("/corpStatistics") @PostMapping("/corpStatistics")

View File

@ -4,9 +4,11 @@ import com.zcloud.safetyDutyList.domain.enums.ExceptionTypeEnum;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.FeedbackExceptionGateway; import com.zcloud.safetyDutyList.domain.gateway.tasklist.FeedbackExceptionGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.FeedbackGateway; import com.zcloud.safetyDutyList.domain.gateway.tasklist.FeedbackGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskDetailGateway; import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskDetailGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskListGateway;
import com.zcloud.safetyDutyList.domain.model.tasklist.FeedbackE; import com.zcloud.safetyDutyList.domain.model.tasklist.FeedbackE;
import com.zcloud.safetyDutyList.domain.model.tasklist.FeedbackExceptionE; import com.zcloud.safetyDutyList.domain.model.tasklist.FeedbackExceptionE;
import com.zcloud.safetyDutyList.domain.model.tasklist.TaskDetailE; import com.zcloud.safetyDutyList.domain.model.tasklist.TaskDetailE;
import com.zcloud.safetyDutyList.domain.model.tasklist.TaskListE;
import com.zcloud.safetyDutyList.domain.util.FeedbackCycleUtil; import com.zcloud.safetyDutyList.domain.util.FeedbackCycleUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -19,20 +21,23 @@ import java.util.List;
/** /**
* *
* <p> * <p>
* 2 * 2
* <p> * <p>
* *
* 1. (task_status=1) * 1. issue_status=1, period_start_time/end_time
* 2. (feedback_cycle_type) * 2.
* 3. * 3.
* 4. * 4.
* 5. safety_accountability_feedback_exception * 5.
* 6.
* <p> * <p>
* * periodStartTime
* feedback_cycle_type=1= * periodStartTime
* feedback_cycle_type=2= * 202672026712
* feedback_cycle_type=3= * =2026-07=
* feedback_cycle_type=4= * =2026-Q3=
* =2026-H2=
* =2026-Y=
* <p> * <p>
* *
*/ */
@ -41,79 +46,101 @@ import java.util.List;
@AllArgsConstructor @AllArgsConstructor
public class FeedbackExceptionCheckExe { public class FeedbackExceptionCheckExe {
/** 任务详情网关,用于查询进行中的任务列表 */ private final TaskListGateway taskListGateway;
private final TaskDetailGateway taskDetailGateway; private final TaskDetailGateway taskDetailGateway;
/** 反馈网关,用于查询任务的反馈记录 */
private final FeedbackGateway feedbackGateway; private final FeedbackGateway feedbackGateway;
/** 反馈异常网关,用于查询已有异常记录和新增异常记录 */
private final FeedbackExceptionGateway feedbackExceptionGateway; private final FeedbackExceptionGateway feedbackExceptionGateway;
/** /**
* *
* <p> * <p>
* *
*
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void execute() { public void execute() {
// 步骤1获取所有进行中的任务
List<TaskDetailE> inProgressTasks = taskDetailGateway.listInProgress(); // 查询所有已下发且周期时间完整的清单
if (inProgressTasks == null || inProgressTasks.isEmpty()) { List<TaskListE> issuedList = taskListGateway.listIssuedWithPeriod();
log.info("【安全责任清单】没有进行中的任务需要检测"); if (issuedList == null || issuedList.isEmpty()) {
log.info("【定时任务-安全责任清单-检测反馈异常】没有已下发且周期时间完整的清单需要检测");
return; return;
} }
log.info("【安全责任清单】查询到{}条进行中任务需要检测反馈异常", inProgressTasks.size());
for (TaskDetailE taskDetail : inProgressTasks) { log.info("【定时任务-安全责任清单-检测反馈异常】查询到{}条已下发清单需要检测反馈异常", issuedList.size());
Integer feedbackCycleType = taskDetail.getFeedbackCycleType();
// 反馈周期类型为空则跳过,无法判定异常 // 遍历每个清单
if (feedbackCycleType == null) { for (TaskListE taskList : issuedList) {
log.warn("【安全责任清单】任务[{}]反馈周期类型为空,跳过检测", taskDetail.getTaskDetailId());
// 获取清单下的任务
List<TaskDetailE> taskDetails = taskDetailGateway.listByTaskListId(taskList.getTaskListId());
if (taskDetails == null || taskDetails.isEmpty()) {
continue; continue;
} }
// 步骤2根据反馈周期类型计算上一阶段的周期标识 // 遍历每个任务
// 例如:每月->上月"2026-04",每季度->上季度"2026-Q1",每半年->上半年"2025-H2",每年->去年"2025" for (TaskDetailE taskDetail : taskDetails) {
String previousPeriodFlag = FeedbackCycleUtil.generatePreviousPeriodFlag(feedbackCycleType); checkTaskFeedback(taskList, taskDetail);
if (previousPeriodFlag == null) {
log.warn("【安全责任清单】任务[{}]无法生成上一阶段周期标识feedbackCycleType={}",
taskDetail.getTaskDetailId(), feedbackCycleType);
continue;
}
// 步骤3检查上一阶段是否已有异常记录避免重复添加
boolean alreadyHasException = checkExistingException(taskDetail.getTaskDetailId(), previousPeriodFlag);
if (alreadyHasException) {
log.info("【安全责任清单】任务[{}]在周期[{}]已存在异常记录,跳过",
taskDetail.getTaskDetailId(), previousPeriodFlag);
continue;
}
// 步骤4获取该任务的反馈列表判断上一阶段是否有反馈记录
boolean hasFeedback = checkPreviousPeriodFeedback(taskDetail.getTaskDetailId(), previousPeriodFlag);
if (!hasFeedback) {
// 步骤5上一阶段无反馈记录判定为异常添加反馈异常记录
createFeedbackException(taskDetail, previousPeriodFlag);
log.info("【安全责任清单】任务[{}]在周期[{}]未反馈,已添加异常记录",
taskDetail.getTaskDetailId(), previousPeriodFlag);
} else {
log.info("【安全责任清单】任务[{}]在周期[{}]已正常反馈",
taskDetail.getTaskDetailId(), previousPeriodFlag);
} }
} }
} }
/**
*
*
* @param taskList
* @param taskDetail
*/
private void checkTaskFeedback(TaskListE taskList, TaskDetailE taskDetail) {
Integer feedbackCycleType = taskDetail.getFeedbackCycleType();
if (feedbackCycleType == null) {
log.warn("【定时任务-安全责任清单-检测反馈异常】任务[{}]反馈周期类型为空,跳过检测", taskDetail.getTaskDetailId());
return;
}
// 当前时间处于首周期,跳过
if (FeedbackCycleUtil.isFirstCycle(feedbackCycleType, taskList.getPeriodStartTime())) {
log.info("【定时任务-安全责任清单-检测反馈异常】清单[{}]任务[{}]周期类型为{},仍处于首周期内,跳过检测",
taskList.getTaskListId(), taskDetail.getTaskDetailId(), feedbackCycleType);
return;
}
// 上一阶段周期标识
String previousPeriodFlag = FeedbackCycleUtil.generatePreviousPeriodFlag(feedbackCycleType);
if (previousPeriodFlag == null) {
log.warn("【定时任务-安全责任清单-检测反馈异常】任务[{}]无法生成上一阶段周期标识feedbackCycleType={}",
taskDetail.getTaskDetailId(), feedbackCycleType);
return;
}
// 异常记录是否存在
boolean alreadyHasException = checkExistingException(taskDetail.getTaskDetailId(), previousPeriodFlag);
if (alreadyHasException) {
log.info("【定时任务-安全责任清单-检测反馈异常】任务[{}]在周期[{}]已存在异常记录,跳过",
taskDetail.getTaskDetailId(), previousPeriodFlag);
return;
}
// 上一阶段周期标识对应的反馈记录是否存在
boolean hasFeedback = checkPreviousPeriodFeedback(taskDetail.getTaskDetailId(), previousPeriodFlag);
if (!hasFeedback) {
createFeedbackException(taskDetail, previousPeriodFlag);
log.info("【定时任务-安全责任清单-检测反馈异常】任务[{}]在周期[{}]未反馈,已添加异常记录",
taskDetail.getTaskDetailId(), previousPeriodFlag);
} else {
log.info("【定时任务-安全责任清单-检测反馈异常】任务[{}]在周期[{}]已正常反馈",
taskDetail.getTaskDetailId(), previousPeriodFlag);
}
}
/** /**
* *
* <p>
*
*
* *
* @param taskDetailId ID * @param taskDetailId ID
* @param previousPeriodFlag "2026-04""2026-Q1" * @param previousPeriodFlag
* @return true-false- * @return true-false-
*/ */
private boolean checkExistingException(String taskDetailId, String previousPeriodFlag) { private boolean checkExistingException(String taskDetailId, String previousPeriodFlag) {
@ -121,19 +148,15 @@ public class FeedbackExceptionCheckExe {
if (exceptionList == null || exceptionList.isEmpty()) { if (exceptionList == null || exceptionList.isEmpty()) {
return false; return false;
} }
// 遍历异常记录,判断是否存在与上一阶段周期标识匹配的记录
return exceptionList.stream() return exceptionList.stream()
.anyMatch(e -> previousPeriodFlag.equals(e.getExceptionPeriodFlag())); .anyMatch(e -> previousPeriodFlag.equals(e.getExceptionPeriodFlag()));
} }
/** /**
* *
* <p>
*
*
* *
* @param taskDetailId ID * @param taskDetailId ID
* @param previousPeriodFlag "2026-04""2026-Q1" * @param previousPeriodFlag
* @return true-false- * @return true-false-
*/ */
private boolean checkPreviousPeriodFeedback(String taskDetailId, String previousPeriodFlag) { private boolean checkPreviousPeriodFeedback(String taskDetailId, String previousPeriodFlag) {
@ -141,23 +164,12 @@ public class FeedbackExceptionCheckExe {
if (feedbackList == null || feedbackList.isEmpty()) { if (feedbackList == null || feedbackList.isEmpty()) {
return false; return false;
} }
// 遍历反馈记录,判断是否存在与上一阶段周期标识匹配的反馈
return feedbackList.stream() return feedbackList.stream()
.anyMatch(f -> previousPeriodFlag.equals(f.getFeedbackPeriodFlag())); .anyMatch(f -> previousPeriodFlag.equals(f.getFeedbackPeriodFlag()));
} }
/** /**
* *
* <p>
*
* safety_accountability_feedback_exception
* <p>
*
* - IDID
* -
* -
* - (1)
* -
* *
* @param taskDetail * @param taskDetail
* @param previousPeriodFlag * @param previousPeriodFlag
@ -166,21 +178,17 @@ public class FeedbackExceptionCheckExe {
FeedbackExceptionE exceptionE = new FeedbackExceptionE(); FeedbackExceptionE exceptionE = new FeedbackExceptionE();
exceptionE.init(); exceptionE.init();
// 设置关联的任务详情ID和清单ID
exceptionE.setTaskDetailId(taskDetail.getTaskDetailId()); exceptionE.setTaskDetailId(taskDetail.getTaskDetailId());
exceptionE.setTaskListId(taskDetail.getTaskListId()); exceptionE.setTaskListId(taskDetail.getTaskListId());
// 设置异常周期标识(如"2026-04"、"2026-Q1"等)
exceptionE.setExceptionPeriodFlag(previousPeriodFlag); exceptionE.setExceptionPeriodFlag(previousPeriodFlag);
// 根据周期标识计算该周期的起止时间,用于记录异常的时间范围
LocalDateTime[] periodTime = FeedbackCycleUtil.getPeriodTime(previousPeriodFlag); LocalDateTime[] periodTime = FeedbackCycleUtil.getPeriodTime(previousPeriodFlag);
if (periodTime != null) { if (periodTime != null && periodTime.length == 2) {
exceptionE.setExceptionPeriodStartTime(periodTime[0]); exceptionE.setExceptionPeriodStartTime(periodTime[0]);
exceptionE.setExceptionPeriodEndTime(periodTime[1]); exceptionE.setExceptionPeriodEndTime(periodTime[1]);
} }
// 设置异常类型为"未按时反馈",异常时间为当前时间
exceptionE.setExceptionType(ExceptionTypeEnum.NOT_FEEDBACK.getCode()); exceptionE.setExceptionType(ExceptionTypeEnum.NOT_FEEDBACK.getCode());
exceptionE.setExceptionTime(LocalDateTime.now()); exceptionE.setExceptionTime(LocalDateTime.now());

View File

@ -47,16 +47,17 @@ public class TaskListStatusUpdateExe {
// 步骤1查询所有状态为进行中(status=1)且周期结束时间(period_end_time)小于当前时间的清单 // 步骤1查询所有状态为进行中(status=1)且周期结束时间(period_end_time)小于当前时间的清单
List<TaskListE> expiredList = taskListGateway.listExpiredInProgress(); List<TaskListE> expiredList = taskListGateway.listExpiredInProgress();
if (expiredList == null || expiredList.isEmpty()) { if (expiredList == null || expiredList.isEmpty()) {
log.info("【安全责任清单】没有需要更新的过期清单"); log.info("【定时任务-安全责任清单-检测任务完成】没有需要更新的过期清单");
return; return;
} }
log.info("【安全责任清单】查询到{}条过期清单需要更新状态", expiredList.size());
log.info("【定时任务-安全责任清单-检测任务完成】查询到{}条过期清单需要更新状态", expiredList.size());
for (TaskListE taskListE : expiredList) { for (TaskListE taskListE : expiredList) {
// 步骤2将清单状态从进行中(1)更新为已完成(2) // 步骤2将清单状态从进行中(1)更新为已完成(2)
taskListE.setStatus(TaskStatusEnum.COMPLETED.getCode()); taskListE.setStatus(TaskStatusEnum.COMPLETED.getCode());
taskListGateway.update(taskListE); taskListGateway.update(taskListE);
log.info("【安全责任清单】清单[{}]状态已更新为已完成", taskListE.getTaskListId()); log.info("【定时任务-安全责任清单-检测任务完成】清单[{}]状态已更新为已完成", taskListE.getTaskListId());
// 步骤3查询该清单下所有任务详情将进行中的任务更新为已完成 // 步骤3查询该清单下所有任务详情将进行中的任务更新为已完成
List<TaskDetailE> detailList = taskDetailGateway.listByTaskListId(taskListE.getTaskListId()); List<TaskDetailE> detailList = taskDetailGateway.listByTaskListId(taskListE.getTaskListId());
@ -66,7 +67,7 @@ public class TaskListStatusUpdateExe {
if (TaskStatusEnum.IN_PROGRESS.getCode().equals(detailE.getTaskStatus())) { if (TaskStatusEnum.IN_PROGRESS.getCode().equals(detailE.getTaskStatus())) {
detailE.setTaskStatus(TaskStatusEnum.COMPLETED.getCode()); detailE.setTaskStatus(TaskStatusEnum.COMPLETED.getCode());
taskDetailGateway.update(detailE); taskDetailGateway.update(detailE);
log.info("【安全责任清单】任务[{}]状态已更新为已完成", detailE.getTaskDetailId()); log.info("【定时任务-安全责任清单-检测任务完成】任务[{}]状态已更新为已完成", detailE.getTaskDetailId());
} }
} }
} }

View File

@ -68,4 +68,15 @@ public interface TaskListGateway {
* @return * @return
*/ */
List<TaskListE> listExpiredInProgress(); List<TaskListE> listExpiredInProgress();
/**
*
* <p>
* issue_status=1 period_start_time IS NOT NULL period_end_time IS NOT NULL
* period_end_time11
* 2
*
* @return
*/
List<TaskListE> listIssuedWithPeriod();
} }

View File

@ -25,9 +25,9 @@ public class TaskListE extends BaseE {
private Integer status; private Integer status;
private LocalDateTime periodStartTime; private LocalDateTime periodStartTime;
private LocalDateTime periodEndTime; private LocalDateTime periodEndTime;
private BigDecimal score; private BigDecimal ratingScore;
private Long scoreUserId; private Long ratingUserId;
private Long scoreDepartmentId; private Long ratingDepartmentId;
private Long createCorpId; private Long createCorpId;
private Long createDepartmentId; private Long createDepartmentId;
private Long createUserId; private Long createUserId;

View File

@ -16,7 +16,7 @@ import java.time.LocalDateTime;
* "2026-05" - * "2026-05" -
* "2026-Q1" -Q1=1-3Q2=4-6Q3=7-9Q4=10-12 * "2026-Q1" -Q1=1-3Q2=4-6Q3=7-9Q4=10-12
* "2026-H1" -H1=1-6H2=7-12 * "2026-H1" -H1=1-6H2=7-12
* "2026" * "2026-Y" -Y
*/ */
public class FeedbackCycleUtil { public class FeedbackCycleUtil {
@ -26,26 +26,21 @@ public class FeedbackCycleUtil {
* *
* 00:00:0023:59:59 * 00:00:0023:59:59
* *
* @param periodFlag "2026-05""2026-Q1""2026-H1""2026" * @param periodFlag "2026-05""2026-Q1""2026-H1""2026-Y"
* @return 2LocalDateTime[0]=[1]=null * @return 2LocalDateTime[0]=[1]=null
*/ */
public static LocalDateTime[] getPeriodTime(String periodFlag) { public static LocalDateTime[] getPeriodTime(String periodFlag) {
if (periodFlag == null || periodFlag.isEmpty()) { if (periodFlag == null || periodFlag.isEmpty()) {
return null; return null;
} }
// 根据周期标识中的特征字符判断周期类型
if (periodFlag.contains("-Q")) { if (periodFlag.contains("-Q")) {
// 包含"-Q"标识,为季度周期(如"2026-Q1"
return getQuarterPeriod(periodFlag); return getQuarterPeriod(periodFlag);
} else if (periodFlag.contains("-H")) { } else if (periodFlag.contains("-H")) {
// 包含"-H"标识,为半年周期(如"2026-H1"
return getHalfYearPeriod(periodFlag); return getHalfYearPeriod(periodFlag);
} else if (periodFlag.contains("-") && periodFlag.length() == 7) { } else if (periodFlag.contains("-Y")) {
// 包含"-"且长度为7为月度周期如"2026-05"
return getMonthPeriod(periodFlag);
} else if (periodFlag.length() == 4) {
// 长度为4的纯数字为年度周期如"2026"
return getYearPeriod(periodFlag); return getYearPeriod(periodFlag);
} else if (periodFlag.contains("-") && periodFlag.length() == 7) {
return getMonthPeriod(periodFlag);
} }
return null; return null;
} }
@ -62,9 +57,7 @@ public class FeedbackCycleUtil {
String[] parts = periodFlag.split("-"); String[] parts = periodFlag.split("-");
int year = Integer.parseInt(parts[0]); int year = Integer.parseInt(parts[0]);
int month = Integer.parseInt(parts[1]); int month = Integer.parseInt(parts[1]);
// 起始时间该月1日00:00:00
LocalDateTime start = LocalDateTime.of(year, month, 1, 0, 0, 0); LocalDateTime start = LocalDateTime.of(year, month, 1, 0, 0, 0);
// 结束时间该月最后一天23:59:59
LocalDateTime end = LocalDateTime.of(year, month, LocalDate.of(year, month, 1).lengthOfMonth(), 23, 59, 59); LocalDateTime end = LocalDateTime.of(year, month, LocalDate.of(year, month, 1).lengthOfMonth(), 23, 59, 59);
return new LocalDateTime[]{start, end}; return new LocalDateTime[]{start, end};
} }
@ -84,12 +77,9 @@ public class FeedbackCycleUtil {
String[] parts = periodFlag.split("-Q"); String[] parts = periodFlag.split("-Q");
int year = Integer.parseInt(parts[0]); int year = Integer.parseInt(parts[0]);
int quarter = Integer.parseInt(parts[1]); int quarter = Integer.parseInt(parts[1]);
// 计算季度的起始月份和结束月份
int startMonth = (quarter - 1) * 3 + 1; int startMonth = (quarter - 1) * 3 + 1;
int endMonth = startMonth + 2; int endMonth = startMonth + 2;
// 起始时间季度首月1日00:00:00
LocalDateTime start = LocalDateTime.of(year, startMonth, 1, 0, 0, 0); LocalDateTime start = LocalDateTime.of(year, startMonth, 1, 0, 0, 0);
// 结束时间季度末月最后一天23:59:59
LocalDateTime end = LocalDateTime.of(year, endMonth, LocalDate.of(year, endMonth, 1).lengthOfMonth(), 23, 59, 59); LocalDateTime end = LocalDateTime.of(year, endMonth, LocalDate.of(year, endMonth, 1).lengthOfMonth(), 23, 59, 59);
return new LocalDateTime[]{start, end}; return new LocalDateTime[]{start, end};
} }
@ -109,12 +99,9 @@ public class FeedbackCycleUtil {
String[] parts = periodFlag.split("-H"); String[] parts = periodFlag.split("-H");
int year = Integer.parseInt(parts[0]); int year = Integer.parseInt(parts[0]);
int half = Integer.parseInt(parts[1]); int half = Integer.parseInt(parts[1]);
// 计算半年的起始月份和结束月份
int startMonth = (half - 1) * 6 + 1; int startMonth = (half - 1) * 6 + 1;
int endMonth = startMonth + 5; int endMonth = startMonth + 5;
// 起始时间半年首月1日00:00:00
LocalDateTime start = LocalDateTime.of(year, startMonth, 1, 0, 0, 0); LocalDateTime start = LocalDateTime.of(year, startMonth, 1, 0, 0, 0);
// 结束时间半年末月最后一天23:59:59
LocalDateTime end = LocalDateTime.of(year, endMonth, LocalDate.of(year, endMonth, 1).lengthOfMonth(), 23, 59, 59); LocalDateTime end = LocalDateTime.of(year, endMonth, LocalDate.of(year, endMonth, 1).lengthOfMonth(), 23, 59, 59);
return new LocalDateTime[]{start, end}; return new LocalDateTime[]{start, end};
} }
@ -122,16 +109,15 @@ public class FeedbackCycleUtil {
/** /**
* *
* <p> * <p>
* "2026" -> [2026-01-01 00:00:00, 2026-12-31 23:59:59] * "2026-Y" -> [2026-01-01 00:00:00, 2026-12-31 23:59:59]
* *
* @param periodFlag "yyyy" * @param periodFlag "yyyy-Y"
* @return * @return
*/ */
private static LocalDateTime[] getYearPeriod(String periodFlag) { private static LocalDateTime[] getYearPeriod(String periodFlag) {
int year = Integer.parseInt(periodFlag); String yearStr = periodFlag.replace("-Y", "");
// 起始时间1月1日00:00:00 int year = Integer.parseInt(yearStr);
LocalDateTime start = LocalDateTime.of(year, 1, 1, 0, 0, 0); LocalDateTime start = LocalDateTime.of(year, 1, 1, 0, 0, 0);
// 结束时间12月31日23:59:59
LocalDateTime end = LocalDateTime.of(year, 12, 31, 23, 59, 59); LocalDateTime end = LocalDateTime.of(year, 12, 31, 23, 59, 59);
return new LocalDateTime[]{start, end}; return new LocalDateTime[]{start, end};
} }
@ -143,7 +129,7 @@ public class FeedbackCycleUtil {
* feedbackCycle=1 "2026-05" * feedbackCycle=1 "2026-05"
* feedbackCycle=2 "2026-Q1" * feedbackCycle=2 "2026-Q1"
* feedbackCycle=3 "2026-H1" * feedbackCycle=3 "2026-H1"
* feedbackCycle=4 "2026" * feedbackCycle=4 "2026-Y"
* *
* @param feedbackCycle 1-2-3-4- * @param feedbackCycle 1-2-3-4-
* @param time null使 * @param time null使
@ -156,21 +142,15 @@ public class FeedbackCycleUtil {
int year = time.getYear(); int year = time.getYear();
switch (feedbackCycle) { switch (feedbackCycle) {
case 1: case 1:
// 每月:格式为"年-月",如"2026-05"
return String.format("%d-%02d", year, time.getMonthValue()); return String.format("%d-%02d", year, time.getMonthValue());
case 2: case 2:
// 每季度:格式为"年-Q季度",如"2026-Q1"
// 季度计算:(月份-1)/3 + 1如5月=(5-1)/3+1=Q2
int quarter = (time.getMonthValue() - 1) / 3 + 1; int quarter = (time.getMonthValue() - 1) / 3 + 1;
return String.format("%d-Q%d", year, quarter); return String.format("%d-Q%d", year, quarter);
case 3: case 3:
// 每半年:格式为"年-H半年",如"2026-H1"
// 1-6月为H17-12月为H2
int half = time.getMonthValue() <= 6 ? 1 : 2; int half = time.getMonthValue() <= 6 ? 1 : 2;
return String.format("%d-H%d", year, half); return String.format("%d-H%d", year, half);
case 4: case 4:
// 每年:格式为"年",如"2026" return String.format("%d-Y", year);
return String.valueOf(year);
default: default:
return null; return null;
} }
@ -185,7 +165,7 @@ public class FeedbackCycleUtil {
* feedbackCycle=1 2026-05"2026-04" * feedbackCycle=1 2026-05"2026-04"
* feedbackCycle=2 Q1Q4Q2Q1 * feedbackCycle=2 Q1Q4Q2Q1
* feedbackCycle=3 H1H2H2H1 * feedbackCycle=3 H1H2H2H1
* feedbackCycle=4 2026"2025" * feedbackCycle=4 2026-Y"2025-Y"
* *
* @param feedbackCycle 1-2-3-4- * @param feedbackCycle 1-2-3-4-
* @return null * @return null
@ -194,12 +174,9 @@ public class FeedbackCycleUtil {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
switch (feedbackCycle) { switch (feedbackCycle) {
case 1: case 1:
// 每月回退一个月如2026-05 -> 2026-04
LocalDateTime lastMonth = now.minusMonths(1); LocalDateTime lastMonth = now.minusMonths(1);
return String.format("%d-%02d", lastMonth.getYear(), lastMonth.getMonthValue()); return String.format("%d-%02d", lastMonth.getYear(), lastMonth.getMonthValue());
case 2: case 2:
// 每季度:回退一个季度
// 若当前为Q1(1-3月)则上一季度为上年的Q4否则为当年的上一季度
int currentQuarter = (now.getMonthValue() - 1) / 3 + 1; int currentQuarter = (now.getMonthValue() - 1) / 3 + 1;
if (currentQuarter == 1) { if (currentQuarter == 1) {
return String.format("%d-Q4", now.getYear() - 1); return String.format("%d-Q4", now.getYear() - 1);
@ -207,8 +184,6 @@ public class FeedbackCycleUtil {
return String.format("%d-Q%d", now.getYear(), currentQuarter - 1); return String.format("%d-Q%d", now.getYear(), currentQuarter - 1);
} }
case 3: case 3:
// 每半年:回退一个半年
// 若当前为H1(1-6月)则上一半年为上年的H2否则为当年的H1
int currentHalf = now.getMonthValue() <= 6 ? 1 : 2; int currentHalf = now.getMonthValue() <= 6 ? 1 : 2;
if (currentHalf == 1) { if (currentHalf == 1) {
return String.format("%d-H2", now.getYear() - 1); return String.format("%d-H2", now.getYear() - 1);
@ -216,13 +191,47 @@ public class FeedbackCycleUtil {
return String.format("%d-H1", now.getYear()); return String.format("%d-H1", now.getYear());
} }
case 4: case 4:
// 每年回退一年如2026 -> 2025 return String.format("%d-Y", now.getYear() - 1);
return String.valueOf(now.getYear() - 1);
default: default:
return null; return null;
} }
} }
/**
*
* <p>
*
*
*
* <p>
* "首周期标识""当前周期标识"
*
* <p>
* 202672026712
* =2026-07=2026-07
* =2026-Q3=2026-Q3
* =2026-H2=2026-H2
* =2026-Y=2026-Y
* <p>
* 20267202681
* =2026-07=2026-08 2026-07
* =2026-Q3=2026-Q3
* =2026-H2=2026-H2
* =2026-Y=2026-Y
*
* @param feedbackCycle 1-2-3-4-
* @param periodStartTime
* @return true-false-
*/
public static boolean isFirstCycle(Integer feedbackCycle, LocalDateTime periodStartTime) {
if (periodStartTime == null) {
return true;
}
String firstCycleFlag = generatePeriodFlag(feedbackCycle, periodStartTime);
String currentCycleFlag = generatePeriodFlag(feedbackCycle, LocalDateTime.now());
return firstCycleFlag != null && firstCycleFlag.equals(currentCycleFlag);
}
/** /**
* *
* <p> * <p>

View File

@ -144,4 +144,18 @@ public class TaskListGatewayImpl implements TaskListGateway {
} }
return eList; return eList;
} }
@Override
public List<TaskListE> listIssuedWithPeriod() {
List<TaskListDO> doList = taskListRepository.listIssuedWithPeriod();
List<TaskListE> eList = new ArrayList<>();
if (doList != null) {
for (TaskListDO d : doList) {
TaskListE e = new TaskListE();
BeanUtils.copyProperties(d, e);
eList.add(e);
}
}
return eList;
}
} }

View File

@ -32,6 +32,8 @@ public interface TaskListMapper extends BaseMapper<TaskListDO> {
List<TaskListDO> listExpiredInProgress(); List<TaskListDO> listExpiredInProgress();
List<TaskListDO> listIssuedWithPeriod();
IPage<CorpStatisticsDO> corpStatistics(IPage<CorpStatisticsDO> iPage, Map<String, Object> params); IPage<CorpStatisticsDO> corpStatistics(IPage<CorpStatisticsDO> iPage, Map<String, Object> params);
IPage<EvaluationListDO> evaluationList(IPage<EvaluationListDO> iPage, Map<String, Object> params); IPage<EvaluationListDO> evaluationList(IPage<EvaluationListDO> iPage, Map<String, Object> params);

View File

@ -73,6 +73,11 @@ public class TaskListRepositoryImpl extends BaseRepositoryImpl<TaskListMapper, T
return taskListMapper.listExpiredInProgress(); return taskListMapper.listExpiredInProgress();
} }
@Override
public List<TaskListDO> listIssuedWithPeriod() {
return taskListMapper.listIssuedWithPeriod();
}
@Override @Override
public PageResponse<CorpStatisticsDO> corpStatistics(Map<String, Object> params) { public PageResponse<CorpStatisticsDO> corpStatistics(Map<String, Object> params) {
IPage<CorpStatisticsDO> iPage = new Query<CorpStatisticsDO>().getPage(params); IPage<CorpStatisticsDO> iPage = new Query<CorpStatisticsDO>().getPage(params);

View File

@ -32,6 +32,8 @@ public interface TaskListRepository extends BaseRepository<TaskListDO> {
List<TaskListDO> listExpiredInProgress(); List<TaskListDO> listExpiredInProgress();
List<TaskListDO> listIssuedWithPeriod();
PageResponse<CorpStatisticsDO> corpStatistics(Map<String, Object> params); PageResponse<CorpStatisticsDO> corpStatistics(Map<String, Object> params);
PageResponse<EvaluationListDO> evaluationList(Map<String, Object> params); PageResponse<EvaluationListDO> evaluationList(Map<String, Object> params);

View File

@ -141,6 +141,12 @@
WHERE status = 1 AND issue_status = 1 AND (period_end_time IS NOT NULL AND period_end_time &lt; NOW()) WHERE status = 1 AND issue_status = 1 AND (period_end_time IS NOT NULL AND period_end_time &lt; NOW())
</select> </select>
<select id="listIssuedWithPeriod" resultType="com.zcloud.safetyDutyList.persistence.dataobject.tasklist.TaskListDO">
SELECT * FROM safety_accountability_task_list
WHERE issue_status = 1 AND period_start_time IS NOT NULL AND period_end_time IS NOT NULL
AND period_end_time > DATE_SUB(NOW(), INTERVAL 1 MONTH)
</select>
<select id="corpStatistics" resultType="com.zcloud.safetyDutyList.persistence.dataobject.tasklist.CorpStatisticsDO"> <select id="corpStatistics" resultType="com.zcloud.safetyDutyList.persistence.dataobject.tasklist.CorpStatisticsDO">
SELECT tl.execute_corp_id AS corpId, SELECT tl.execute_corp_id AS corpId,
ci.corp_name AS corpName, ci.corp_name AS corpName,