diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/OpsSchedulingDate.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/OpsSchedulingDate.java index 4c6726e..c5fa90c 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/OpsSchedulingDate.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/OpsSchedulingDate.java @@ -31,6 +31,11 @@ public class OpsSchedulingDate extends BaseEntity { @TableId(value = "id") private Long id; + /** + * 项目id + */ + private Long projectId; + /** * 排班名称 */ @@ -46,5 +51,10 @@ public class OpsSchedulingDate extends BaseEntity { */ private LocalTime endTime; + /** + * 时长 + */ + private Double duration; + } diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/bo/OpsSchedulingDateBo.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/bo/OpsSchedulingDateBo.java index 6a6cd2f..92a88ec 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/bo/OpsSchedulingDateBo.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/bo/OpsSchedulingDateBo.java @@ -27,8 +27,15 @@ public class OpsSchedulingDateBo extends BaseEntity { /** * id */ + @NotNull(message = "id不能为空", groups = { EditGroup.class }) private Long id; + /** + * 项目id + */ + @NotNull(message = "项目id不能为空", groups = { AddGroup.class, EditGroup.class }) + private Long projectId; + /** * 排班名称 */ @@ -47,5 +54,10 @@ public class OpsSchedulingDateBo extends BaseEntity { @NotNull(message = "结束时间不能为空", groups = { AddGroup.class, EditGroup.class }) private LocalTime endTime; + /** + * 时长 + */ + private Double duration; + } diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/dto/SchedulingUserGroupDTO.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/dto/SchedulingUserGroupDTO.java index ca7a089..d18dbf7 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/dto/SchedulingUserGroupDTO.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/dto/SchedulingUserGroupDTO.java @@ -11,6 +11,10 @@ import java.util.List; public class SchedulingUserGroupDTO implements Serializable { private Long opsUserId; // 运维人员ID private String opsUserName; // 运维人员ID + /** + * 总时长 + */ + private Double durationCount; private List userTypePairs; // 日期-类型对应列表 } diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingDateVo.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingDateVo.java index 7386188..222ba5a 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingDateVo.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingDateVo.java @@ -3,6 +3,9 @@ package org.dromara.personnel.domain.vo; import java.time.LocalTime; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.constraints.NotNull; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; import org.dromara.personnel.domain.OpsSchedulingDate; import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; @@ -37,6 +40,11 @@ public class OpsSchedulingDateVo implements Serializable { @ExcelProperty(value = "id") private Long id; + /** + * 项目id + */ + private Long projectId; + /** * 排班名称 */ @@ -55,5 +63,10 @@ public class OpsSchedulingDateVo implements Serializable { @ExcelProperty(value = "结束时间") private LocalTime endTime; + /** + * 时长 + */ + private Double duration; + } diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingVo.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingVo.java index 085034a..146d4a3 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingVo.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/domain/vo/OpsSchedulingVo.java @@ -74,5 +74,10 @@ public class OpsSchedulingVo implements Serializable { // @ExcelProperty(value = "排班结束时间") private LocalDateTime schedulingEndTime; + /** + * 时长 + */ + private Double duration; + } diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingDateServiceImpl.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingDateServiceImpl.java index 094479f..8a6a150 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingDateServiceImpl.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingDateServiceImpl.java @@ -16,6 +16,8 @@ import org.dromara.personnel.domain.OpsSchedulingDate; import org.dromara.personnel.mapper.OpsSchedulingDateMapper; import org.dromara.personnel.service.IOpsSchedulingDateService; +import java.time.Duration; +import java.time.LocalTime; import java.util.List; import java.util.Map; import java.util.Collection; @@ -74,6 +76,7 @@ public class OpsSchedulingDateServiceImpl implements IOpsSchedulingDateService { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.orderByAsc(OpsSchedulingDate::getId); + lqw.eq(bo.getProjectId() != null, OpsSchedulingDate::getProjectId, bo.getProjectId()); lqw.like(StringUtils.isNotBlank(bo.getSchedulingName()), OpsSchedulingDate::getSchedulingName, bo.getSchedulingName()); lqw.eq(bo.getStartTime() != null, OpsSchedulingDate::getStartTime, bo.getStartTime()); lqw.eq(bo.getEndTime() != null, OpsSchedulingDate::getEndTime, bo.getEndTime()); @@ -89,6 +92,8 @@ public class OpsSchedulingDateServiceImpl implements IOpsSchedulingDateService { @Override public Boolean insertByBo(OpsSchedulingDateBo bo) { OpsSchedulingDate add = MapstructUtils.convert(bo, OpsSchedulingDate.class); + double duration = getDuration(add); + add.setDuration(duration); validEntityBeforeSave(add); boolean flag = baseMapper.insert(add) > 0; if (flag) { @@ -106,10 +111,27 @@ public class OpsSchedulingDateServiceImpl implements IOpsSchedulingDateService { @Override public Boolean updateByBo(OpsSchedulingDateBo bo) { OpsSchedulingDate update = MapstructUtils.convert(bo, OpsSchedulingDate.class); + double duration = getDuration(update); + update.setDuration(duration); validEntityBeforeSave(update); return baseMapper.updateById(update) > 0; } + /** + * 计算时长 + * @param update + * @return + */ + private static double getDuration(OpsSchedulingDate update) { + double duration = 0.0; + if (update.getStartTime().isAfter(update.getEndTime())) { + duration =calculateHourDiffWithDecimal(update.getStartTime(), update.getEndTime()); + }else { + duration = calculateHourDiffWithDecimalAndCrossDay(update.getStartTime(), update.getEndTime()); + } + return duration; + } + /** * 保存前的数据校验 */ @@ -131,4 +153,30 @@ public class OpsSchedulingDateServiceImpl implements IOpsSchedulingDateService { } return baseMapper.deleteByIds(ids) > 0; } + + /** + * 计算两个LocalTime的小时差(保留小数,不处理跨天) + * @param startTime 开始时间 + * @param endTime 结束时间 + * @return 小时差(如1.5表示1小时30分钟) + */ + public static double calculateHourDiffWithDecimal(LocalTime startTime, LocalTime endTime) { + // 1. 计算总分钟差(endTime - startTime) + long totalMinutes = Duration.between(startTime, endTime).toMinutes(); + // 2. 转换为小时(除以60.0保留小数) + return totalMinutes / 60.0; + } + + /** + * 计算小时差(处理跨天,保留小数) + * 适用场景:如23:00到次日01:30 → 2.5小时 + */ + public static double calculateHourDiffWithDecimalAndCrossDay(LocalTime startTime, LocalTime endTime) { + long totalMinutes = Duration.between(startTime, endTime).toMinutes(); + // 若为负数,说明跨天,加上24*60分钟(一天的总分钟数) + if (totalMinutes < 0) { + totalMinutes += 24 * 60; + } + return totalMinutes / 60.0; + } } diff --git a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingServiceImpl.java b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingServiceImpl.java index c6c580c..402edf5 100644 --- a/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingServiceImpl.java +++ b/ruoyi-modules/xny-ops/src/main/java/org/dromara/personnel/service/impl/OpsSchedulingServiceImpl.java @@ -193,12 +193,15 @@ public class OpsSchedulingServiceImpl implements IOpsSchedulingService { List userTypePairDTOS = new ArrayList<>(); dto.setOpsUserId(entry.getKey()); dto.setOpsUserName(remoteUserService.selectNicknameById(entry.getKey())); - entry.getValue().forEach(schedulingDate -> { + double durationCount = 0.0; + for (OpsSchedulingVo schedulingDate : entry.getValue()) { UserTypePairDTO pairDTO = new UserTypePairDTO(); pairDTO.setSchedulingDate(schedulingDate.getSchedulingDate()); pairDTO.setSchedulingType(schedulingDate.getSchedulingType()); pairDTO.setSchedulingTypeName(schedulingDate.getSchedulingTypeName()); - }); + durationCount += schedulingDate.getDuration(); + } + dto.setDurationCount(durationCount); dto.setUserTypePairs(userTypePairDTOS); schedulingDateGroupDTOS.add(dto); } diff --git a/ruoyi-modules/xny-ops/src/main/resources/mapper/personnel/OpsSchedulingMapper.xml b/ruoyi-modules/xny-ops/src/main/resources/mapper/personnel/OpsSchedulingMapper.xml index 3b62d01..ad3794d 100644 --- a/ruoyi-modules/xny-ops/src/main/resources/mapper/personnel/OpsSchedulingMapper.xml +++ b/ruoyi-modules/xny-ops/src/main/resources/mapper/personnel/OpsSchedulingMapper.xml @@ -13,7 +13,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" os.scheduling_date as schedulingDate, os.scheduling_start_time as schedulingStartTime, os.scheduling_end_time as schedulingEndTime, - osd.scheduling_name as schedulingTypeName + osd.scheduling_name as schedulingTypeName, + osd.duration AS duration FROM ops_scheduling os LEFT JOIN ops_scheduling_date osd ON os.scheduling_type = osd.id