|
@@ -34,6 +34,8 @@ import org.springframework.util.Assert;
|
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.LocalTime;
|
|
import java.time.LocalTime;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
@@ -321,14 +323,16 @@ public class RiskInspectionTaskServiceImpl implements IRiskInspectionTaskService
|
|
|
applyStatusFilter(lqw, status);
|
|
applyStatusFilter(lqw, status);
|
|
|
lqw.orderByDesc(RiskInspectionTask::getPlanStartTime);
|
|
lqw.orderByDesc(RiskInspectionTask::getPlanStartTime);
|
|
|
Page<RiskInspectionTask> page = baseMapper.selectPage(pageQuery.build(), lqw);
|
|
Page<RiskInspectionTask> page = baseMapper.selectPage(pageQuery.build(), lqw);
|
|
|
- List<MobileInspectionTaskVo> rows = page.getRecords().stream()
|
|
|
|
|
- .map(this::convertToMobileVo)
|
|
|
|
|
- .toList();
|
|
|
|
|
|
|
+ // 2. 实体 → 基础 vo + 按 time_slot 拆分为多个"待办"(每日任务多时段 → 移动端 N 条)
|
|
|
|
|
+ List<MobileInspectionTaskVo> rows = new ArrayList<>();
|
|
|
|
|
+ for (RiskInspectionTask task : page.getRecords()) {
|
|
|
|
|
+ rows.addAll(expandByTimeSlots(task));
|
|
|
|
|
+ }
|
|
|
return TableDataInfo.build(new Page<MobileInspectionTaskVo>()
|
|
return TableDataInfo.build(new Page<MobileInspectionTaskVo>()
|
|
|
.setRecords(rows)
|
|
.setRecords(rows)
|
|
|
- .setTotal(page.getTotal())
|
|
|
|
|
- .setSize(page.getSize())
|
|
|
|
|
- .setCurrent(page.getCurrent()));
|
|
|
|
|
|
|
+ .setTotal((long) rows.size())
|
|
|
|
|
+ .setSize((long) rows.size())
|
|
|
|
|
+ .setCurrent(1L));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -347,14 +351,96 @@ public class RiskInspectionTaskServiceImpl implements IRiskInspectionTaskService
|
|
|
applyStatusFilter(lqw, status);
|
|
applyStatusFilter(lqw, status);
|
|
|
lqw.orderByDesc(RiskInspectionTask::getPlanStartTime);
|
|
lqw.orderByDesc(RiskInspectionTask::getPlanStartTime);
|
|
|
Page<RiskInspectionTask> page = baseMapper.selectPage(pageQuery.build(), lqw);
|
|
Page<RiskInspectionTask> page = baseMapper.selectPage(pageQuery.build(), lqw);
|
|
|
- List<MobileInspectionTaskVo> rows = page.getRecords().stream()
|
|
|
|
|
- .map(this::convertToMobileVo)
|
|
|
|
|
- .toList();
|
|
|
|
|
|
|
+ // 同 queryMobileList:按 time_slot 拆分
|
|
|
|
|
+ List<MobileInspectionTaskVo> rows = new ArrayList<>();
|
|
|
|
|
+ for (RiskInspectionTask task : page.getRecords()) {
|
|
|
|
|
+ rows.addAll(expandByTimeSlots(task));
|
|
|
|
|
+ }
|
|
|
return TableDataInfo.build(new Page<MobileInspectionTaskVo>()
|
|
return TableDataInfo.build(new Page<MobileInspectionTaskVo>()
|
|
|
.setRecords(rows)
|
|
.setRecords(rows)
|
|
|
- .setTotal(page.getTotal())
|
|
|
|
|
- .setSize(page.getSize())
|
|
|
|
|
- .setCurrent(page.getCurrent()));
|
|
|
|
|
|
|
+ .setTotal((long) rows.size())
|
|
|
|
|
+ .setSize((long) rows.size())
|
|
|
|
|
+ .setCurrent(1L));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按 task.time_slot 把单条 task 拆成 N 个移动端 vo(每日多时段场景)
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 拆分规则:
|
|
|
|
|
+ * <ul>
|
|
|
|
|
+ * <li>time_slot 为空 / 解析不出 slot → 原样返回 1 个 vo(非每日任务或单时段任务)</li>
|
|
|
|
|
+ * <li>time_slot = "08:00-08:30,10:00-10:30,12:00-12:30" → 返回 3 个 vo</li>
|
|
|
|
|
+ * <li>每个 vo 的 planStartTime/planEndTime = 今天 + slot 起止时间(独立时段)</li>
|
|
|
|
|
+ * <li>每个 vo 的 punchStatus 共享 task 级别(同一 task 一次打卡所有 slot 都视为已打卡)</li>
|
|
|
|
|
+ * <li>若 task 还没打卡且当前时间已过 slot.planEndTime → 单独把该 slot 标记为 OVERDUE</li>
|
|
|
|
|
+ * </ul>
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<MobileInspectionTaskVo> expandByTimeSlots(RiskInspectionTask task) {
|
|
|
|
|
+ List<MobileInspectionTaskVo> result = new ArrayList<>();
|
|
|
|
|
+ // 1) 基础 vo(含 task 级别 punchStatus/打卡时间等)
|
|
|
|
|
+ MobileInspectionTaskVo baseVo = convertToMobileVo(task);
|
|
|
|
|
+ // 2) 解析 slot 列表
|
|
|
|
|
+ List<String> slots = parseTimeSlots(task.getTimeSlot());
|
|
|
|
|
+ baseVo.setAllTimeSlots(task.getTimeSlot());
|
|
|
|
|
+ if (slots.isEmpty()) {
|
|
|
|
|
+ // 无 time_slot(每周/每月/单时段)→ 原样返回
|
|
|
|
|
+ result.add(baseVo);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 3) 每个 slot 复制一份,planStartTime/planEndTime 改为今天+slot 时间
|
|
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
|
|
+ Date now = new Date();
|
|
|
|
|
+ boolean isPunchable = "PENDING".equals(baseVo.getPunchStatus());
|
|
|
|
|
+ for (String slot : slots) {
|
|
|
|
|
+ MobileInspectionTaskVo vo = new MobileInspectionTaskVo();
|
|
|
|
|
+ BeanUtil.copyProperties(baseVo, vo);
|
|
|
|
|
+ vo.setSlot(slot);
|
|
|
|
|
+ String[] parts = slot.split("-");
|
|
|
|
|
+ if (parts.length == 2) {
|
|
|
|
|
+ vo.setPlanStartTime(mergeDateTime(today, parts[0].trim()));
|
|
|
|
|
+ vo.setPlanEndTime(mergeDateTime(today, parts[1].trim()));
|
|
|
|
|
+ // 未打卡的 slot:如果当前时间已过 slot.planEndTime → 标 OVERDUE
|
|
|
|
|
+ if (isPunchable && vo.getPlanEndTime() != null && vo.getPlanEndTime().before(now)) {
|
|
|
|
|
+ vo.setPunchStatus("OVERDUE");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ result.add(vo);
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解析 task.time_slot(逗号分隔)为 slot 列表
|
|
|
|
|
+ * 格式: "08:00-08:30,10:00-10:30,12:00-12:30"
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<String> parseTimeSlots(String timeSlot) {
|
|
|
|
|
+ List<String> slots = new ArrayList<>();
|
|
|
|
|
+ if (StringUtils.isBlank(timeSlot)) {
|
|
|
|
|
+ return slots;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (String s : timeSlot.split(",")) {
|
|
|
|
|
+ String trimmed = s.trim();
|
|
|
|
|
+ if (!trimmed.isEmpty() && trimmed.contains("-")) {
|
|
|
|
|
+ slots.add(trimmed);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return slots;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 合并日期 + HH:mm 为 Date
|
|
|
|
|
+ */
|
|
|
|
|
+ private Date mergeDateTime(LocalDate date, String hhmm) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ String[] parts = hhmm.split(":");
|
|
|
|
|
+ int hour = Integer.parseInt(parts[0]);
|
|
|
|
|
+ int minute = parts.length > 1 ? Integer.parseInt(parts[1]) : 0;
|
|
|
|
|
+ LocalDateTime dt = date.atTime(hour, minute);
|
|
|
|
|
+ return Date.from(dt.atZone(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("解析时间段失败: date={}, hhmm={}", date, hhmm);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|