fix:优化app统计报表查询速度

main
HuangHuiKang 3 weeks ago
parent 728121dd77
commit c2ec3f0dbf

@ -102,4 +102,8 @@ public interface MoldService {
List<MoldDO> getInTransitMoldAllList(); List<MoldDO> getInTransitMoldAllList();
List<MoldDO> getMoldListByStatus(Long status); List<MoldDO> getMoldListByStatus(Long status);
List<MoldDO> getMoldListByIds(Collection<Long> ids);
} }

@ -136,4 +136,11 @@ public class MoldServiceImpl implements MoldService {
.eqIfPresent(MoldDO::getStatus, status); .eqIfPresent(MoldDO::getStatus, status);
return moldMapper.selectList(queryWrapper); return moldMapper.selectList(queryWrapper);
} }
@Override
public List<MoldDO> getMoldListByIds(Collection<Long> ids) {
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
return moldMapper.selectBatchIds(ids); }
} }

@ -137,9 +137,9 @@ public class DeviceController {
} }
@GetMapping("/deviceList") @GetMapping("/deviceList")
// @PreAuthorize("@ss.hasPermission('iot:device:query')") // @PreAuthorize("@ss.hasPermission('iot:device:query')")
public CommonResult<List<DeviceRespVO>> deviceList(@Valid DevicePageReqVO pageReqVO) { public CommonResult<List<DeviceDO>> deviceList(@Valid DevicePageReqVO pageReqVO) {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); // List<DeviceRespVO> list = deviceService.getDevicePage(pageReqVO).getList();
List<DeviceRespVO> list = deviceService.getDevicePage(pageReqVO).getList(); List<DeviceDO> list = deviceService.deviceList(pageReqVO);
return success(list); return success(list);
} }

@ -9,6 +9,10 @@ import java.time.temporal.TemporalAdjusters;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_RATE_TREND_PERIOD_INVALID; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_RATE_TREND_PERIOD_INVALID;
/**
*/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum DeviceRateTrendPeriodEnum { public enum DeviceRateTrendPeriodEnum {

@ -111,10 +111,11 @@ public class DeviceOperationRecordController {
} }
@GetMapping("/deviceRateTrendByDeviceId") @GetMapping("/deviceRateTrendByDeviceId")
@Operation(summary = "根据设备ID查询某个设备近7日开机率和稼动率") @Operation(summary = "根据设备ID查询某个设备开机率和稼动率")
@PreAuthorize("@ss.hasPermission('iot:device-operation-record:query')") @PreAuthorize("@ss.hasPermission('iot:device-operation-record:query')")
public CommonResult<List<DeviceOperationRateTrendRespVO>> getDeviceRateTrendByDeviceId(@RequestParam("deviceId") Long deviceId) { public CommonResult<List<DeviceOperationRateTrendRespVO>> getDeviceRateTrendByDeviceId(@RequestParam("deviceId") Long deviceId,
return success(deviceOperationRecordService.getDeviceRateTrendByDeviceId(deviceId)); @RequestParam(value = "period", required = false) String period) {
return success(deviceOperationRecordService.getDeviceRateTrendByDeviceId(deviceId, period));
} }

@ -14,6 +14,9 @@ import lombok.ToString;
@ToString(callSuper = true) @ToString(callSuper = true)
public class DeviceTotalTimeRecordReqVO extends PageParam{ public class DeviceTotalTimeRecordReqVO extends PageParam{
@Schema(description = "时间区间LAST_WEEK/THIS_WEEK/LAST_7_DAYS/LAST_MONTH/THIS_MONTH")
private String period;
@Schema(description = "设备编码") @Schema(description = "设备编码")
private String deviceCode; private String deviceCode;

@ -140,6 +140,9 @@ public interface DeviceMapper extends BaseMapperX<DeviceDO> {
List<Date> selectHolidayDays(@Param("startDay") Date startDay, @Param("endDay") Date endDay); List<Date> selectHolidayDays(@Param("startDay") Date startDay, @Param("endDay") Date endDay);
List<DeviceSelectRespVO> getAvailableDevicePage(@Param("page") Page<DeviceSelectRespVO> page,@Param("param") DevicePageReqVO pageReqVO); List<DeviceSelectRespVO> getAvailableDevicePage(@Param("page") Page<DeviceSelectRespVO> page,@Param("param") DevicePageReqVO pageReqVO);
List<Date> selectHolidayDaysInRange(@Param("startDay") Date startDay, @Param("endDayExclusive") Date endDayExclusive);
} }

@ -157,4 +157,6 @@ public interface DeviceService {
PageResult<DeviceSelectRespVO> getAvailableDevicePage(DevicePageReqVO pageReqVO); PageResult<DeviceSelectRespVO> getAvailableDevicePage(DevicePageReqVO pageReqVO);
List<DeviceDO> deviceList(@Valid DevicePageReqVO pageReqVO);
} }

@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.scheduler.T
import cn.iocoder.yudao.module.iot.controller.admin.device.utils.DataTypeParseUtil; import cn.iocoder.yudao.module.iot.controller.admin.device.utils.DataTypeParseUtil;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
import cn.iocoder.yudao.module.iot.controller.admin.devicecontactmodel.vo.DeviceContactModelPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.devicecontactmodel.vo.DeviceContactModelPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.utils.TimeConverterUtil;
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordReqVO; import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordRespVO; import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.vo.DeviceTotalTimeRecordRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.mqttdatarecord.vo.MqttDataRecordPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.mqttdatarecord.vo.MqttDataRecordPageReqVO;
@ -64,10 +65,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Duration; import java.time.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
@ -1746,40 +1744,97 @@ public class DeviceServiceImpl implements DeviceService {
return new PageResult<>(availableDeviceList, page.getTotal()); return new PageResult<>(availableDeviceList, page.getTotal());
} }
@Override
public List<DeviceDO> deviceList(DevicePageReqVO pageReqVO) {
return deviceMapper.selectList(pageReqVO);
}
/** /**
* *
* deviceOperationPage *
*/ */
@Override @Override
public List<DeviceRateTrendPointRespVO> getDeviceRateTrend(DeviceRateTrendReqVO reqVO) { public List<DeviceRateTrendPointRespVO> getDeviceRateTrend(DeviceRateTrendReqVO reqVO) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
// 根据 period 解析查询日期范围,不包含当天
DeviceRateTrendPeriodEnum.DateRange dateRange = DeviceRateTrendPeriodEnum.valueOfCode(reqVO.getPeriod()).resolve(LocalDate.now()); DeviceRateTrendPeriodEnum.DateRange dateRange =
LocalDateTime startDateTime = dateRange.getStart().atStartOfDay(); DeviceRateTrendPeriodEnum.valueOfCode(reqVO.getPeriod()).resolve(LocalDate.now());
LocalDateTime endDateTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0);
// 默认只统计排产设备,这里先得到最终参与统计的设备集合 LocalDate startDate = dateRange.getStart();
LocalDate endDate = dateRange.getEnd();
LocalDateTime startDateTime = startDate.atStartOfDay();
LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX).withNano(0);
String filteredIds = buildFilteredDeviceIds(reqVO); String filteredIds = buildFilteredDeviceIds(reqVO);
if (StringUtils.isBlank(filteredIds)) {
return Collections.emptyList();
}
List<Long> deviceIds = Arrays.stream(filteredIds.split(","))
.filter(StringUtils::isNotBlank)
.map(Long::valueOf)
.distinct()
.collect(Collectors.toList());
List<Map<String, Object>> statsList = tdengineService.selectDeviceStatsTrendFromTD(
deviceIds,
startDateTime.format(formatter),
endDateTime.format(formatter)
);
// day -> (deviceId -> record)
Map<LocalDate, Map<Long, DeviceTotalTimeRecordRespVO>> dayDeviceRecordMap = convertTrendStatsToMap(statsList);
// skipHoliday 时,区间一次查出所有节假日,避免按天查库
Set<LocalDate> holidaySet = Collections.emptySet();
if (Boolean.TRUE.equals(reqVO.getSkipHoliday())) {
List<Date> holidays = deviceMapper.selectHolidayDaysInRange(
java.sql.Timestamp.valueOf(startDate.atStartOfDay()),
java.sql.Timestamp.valueOf(endDate.plusDays(1).atStartOfDay())
);
holidaySet = holidays == null ? Collections.emptySet() : holidays.stream()
.filter(Objects::nonNull)
.map(this::toLocalDateSafe)
.collect(Collectors.toSet());
}
int deviceCount = deviceIds.size();
List<DeviceRateTrendPointRespVO> result = new ArrayList<>(); List<DeviceRateTrendPointRespVO> result = new ArrayList<>();
for (LocalDate day = startDateTime.toLocalDate(); !day.isAfter(endDateTime.toLocalDate()); day = day.plusDays(1)) {
// 跳过节假日时,这一天不查询,也不返回 for (LocalDate day = startDate; !day.isAfter(endDate); day = day.plusDays(1)) {
if (Boolean.TRUE.equals(reqVO.getSkipHoliday()) && isHoliday(day)) { if (Boolean.TRUE.equals(reqVO.getSkipHoliday()) && holidaySet.contains(day)) {
continue; continue;
} }
LocalDateTime dayStart = day.atStartOfDay();
LocalDateTime dayEnd = day.atTime(LocalTime.MAX).withNano(0); Map<Long, DeviceTotalTimeRecordRespVO> dayMap =
// 复用现有 deviceOperationPage查出当天每台设备的开机率、稼动率基础数据 dayDeviceRecordMap.getOrDefault(day, Collections.emptyMap());
List<DeviceTotalTimeRecordRespVO> deviceDayList = queryDeviceDayList(reqVO, filteredIds, dayStart.format(formatter), dayEnd.format(formatter));
double powerOnRateSum = 0D; double powerOnRateSum = 0D;
double utilizationRateSum = 0D; double utilizationRateSum = 0D;
int deviceCount = deviceDayList.size();
for (DeviceTotalTimeRecordRespVO record : deviceDayList) { for (Long deviceId : deviceIds) {
powerOnRateSum += parsePercentValue(record.getPowerOnRate()); DeviceTotalTimeRecordRespVO record = dayMap.get(deviceId);
utilizationRateSum += parsePercentValue(record.getUtilizationRate()); if (record == null) {
} // 无数据按 0
continue;
}
// 直接按秒计算,不走字符串百分比解析
double offlineSec = record.getTotalOfflineTime();
double runningSec = record.getTotalRunningTime();
double standbySec = record.getTotalStandbyTime();
double faultSec = record.getTotalFaultTime();
double onlineSec = runningSec + standbySec + faultSec;
double totalSec = offlineSec + onlineSec;
double powerOnRate = totalSec > 0 ? (onlineSec / totalSec) : 0D;
double utilizationRate = onlineSec > 0 ? (runningSec / onlineSec) : 0D;
powerOnRateSum += powerOnRate * 100D;
utilizationRateSum += utilizationRate * 100D;
}
DeviceRateTrendPointRespVO point = new DeviceRateTrendPointRespVO(); DeviceRateTrendPointRespVO point = new DeviceRateTrendPointRespVO();
point.setDay(day.toString()); point.setDay(day.toString());
@ -1787,11 +1842,101 @@ public class DeviceServiceImpl implements DeviceService {
point.setPowerOnRate(formatPercentValue(deviceCount > 0 ? powerOnRateSum / deviceCount : 0D)); point.setPowerOnRate(formatPercentValue(deviceCount > 0 ? powerOnRateSum / deviceCount : 0D));
point.setUtilizationRate(formatPercentValue(deviceCount > 0 ? utilizationRateSum / deviceCount : 0D)); point.setUtilizationRate(formatPercentValue(deviceCount > 0 ? utilizationRateSum / deviceCount : 0D));
result.add(point); result.add(point);
}
return result;
}
private Map<LocalDate, Map<Long, DeviceTotalTimeRecordRespVO>> convertTrendStatsToMap(List<Map<String, Object>> statsList) {
Map<LocalDate, Map<Long, DeviceTotalTimeRecordRespVO>> result = new LinkedHashMap<>();
if (statsList == null || statsList.isEmpty()) {
return result;
}
for (Map<String, Object> row : statsList) {
Object statDayObj = row.get("statDay");
if (statDayObj == null) {
statDayObj = row.get("statday");
}
if (statDayObj == null || row.get("deviceId") == null) {
continue;
}
LocalDate statDay;
if (statDayObj instanceof Timestamp) {
statDay = ((Timestamp) statDayObj).toLocalDateTime().toLocalDate();
} else if (statDayObj instanceof LocalDateTime) {
statDay = ((LocalDateTime) statDayObj).toLocalDate();
} else {
statDay = LocalDateTime.parse(statDayObj.toString().replace(" ", "T")).toLocalDate();
}
Long deviceId = ((Number) row.get("deviceId")).longValue();
DeviceTotalTimeRecordRespVO vo = new DeviceTotalTimeRecordRespVO();
vo.setId(deviceId);
vo.setTotalOfflineTime(getDoubleValue(row, "totalOfflineTime"));
vo.setTotalRunningTime(getDoubleValue(row, "totalRunningTime"));
vo.setTotalStandbyTime(getDoubleValue(row, "totalStandbyTime"));
vo.setTotalFaultTime(getDoubleValue(row, "totalFaultTime"));
result.computeIfAbsent(statDay, key -> new HashMap<>()).put(deviceId, vo);
}
return result;
}
/**
* day -> device stats
*/
private Map<LocalDate, List<DeviceTotalTimeRecordRespVO>> convertTrendStats(List<Map<String, Object>> statsList) {
Map<LocalDate, List<DeviceTotalTimeRecordRespVO>> result = new LinkedHashMap<>();
if (statsList == null || statsList.isEmpty()) {
return result;
}
for (Map<String, Object> row : statsList) {
Object statDayObj = row.get("statDay");
if (statDayObj == null) {
statDayObj = row.get("statday");
}
if (statDayObj == null) {
continue;
}
LocalDate statDay;
if (statDayObj instanceof Timestamp) {
statDay = ((Timestamp) statDayObj).toLocalDateTime().toLocalDate();
} else if (statDayObj instanceof LocalDateTime) {
statDay = ((LocalDateTime) statDayObj).toLocalDate();
} else {
statDay = LocalDateTime.parse(statDayObj.toString().replace(" ", "T")).toLocalDate();
}
DeviceTotalTimeRecordRespVO vo = new DeviceTotalTimeRecordRespVO();
vo.setId(((Number) row.get("deviceId")).longValue());
vo.setTotalOfflineTime(getDoubleValue(row, "totalOfflineTime"));
vo.setTotalRunningTime(getDoubleValue(row, "totalRunningTime"));
vo.setTotalStandbyTime(getDoubleValue(row, "totalStandbyTime"));
vo.setTotalFaultTime(getDoubleValue(row, "totalFaultTime"));
result.computeIfAbsent(statDay, key -> new ArrayList<>()).add(vo);
} }
return result; return result;
} }
private DeviceTotalTimeRecordReqVO buildTrendReqVO(LocalDate day) {
DeviceTotalTimeRecordReqVO reqVO = new DeviceTotalTimeRecordReqVO();
reqVO.setStartTime(day.atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
reqVO.setEndTime(day.atTime(LocalTime.MAX).withNano(0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return reqVO;
}
private double parsePercentValue(String percent) { private double parsePercentValue(String percent) {
if (StringUtils.isBlank(percent)) { if (StringUtils.isBlank(percent)) {
return 0D; return 0D;
@ -1810,37 +1955,57 @@ public class DeviceServiceImpl implements DeviceService {
return String.format("%.2f%%", value); return String.format("%.2f%%", value);
} }
private LocalDate toLocalDateSafe(Date date) {
if (date instanceof java.sql.Date) {
return ((java.sql.Date) date).toLocalDate();
}
if (date instanceof java.sql.Timestamp) {
return ((java.sql.Timestamp) date).toLocalDateTime().toLocalDate();
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
private List<DeviceTotalTimeRecordRespVO> queryDeviceDayList(DeviceRateTrendReqVO reqVO, String ids, String startTime, String endTime) {
DeviceTotalTimeRecordReqVO pageReqVO =
new DeviceTotalTimeRecordReqVO();
pageReqVO.setDeviceCode(reqVO.getDeviceCode());
pageReqVO.setDeviceName(reqVO.getDeviceName());
pageReqVO.setIds(ids);
pageReqVO.setStartTime(startTime);
pageReqVO.setEndTime(endTime);
return deviceOperationRecordService.deviceOperationPageList(pageReqVO);
}
private String buildFilteredDeviceIds(DeviceRateTrendReqVO reqVO) { private String buildFilteredDeviceIds(DeviceRateTrendReqVO reqVO) {
boolean onlyScheduled = reqVO.getOnlyScheduled() == null || reqVO.getOnlyScheduled(); boolean onlyScheduled = reqVO.getOnlyScheduled() == null || reqVO.getOnlyScheduled();
// 不只看排产设备时:
// 1. 如果前端传了 ids就按传入 ids 查询
// 2. 如果前端没传 ids就查询全部设备 id
if (!onlyScheduled) { if (!onlyScheduled) {
return reqVO.getIds(); if (StringUtils.isNotBlank(reqVO.getIds())) {
return reqVO.getIds();
}
List<Long> allDeviceIds = deviceMapper.getAllDeviceIds();
if (CollectionUtils.isEmpty(allDeviceIds)) {
return "-1";
}
return allDeviceIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
} }
// 只统计排产设备
Collection<Long> requestIds = parseIds(reqVO.getIds()); Collection<Long> requestIds = parseIds(reqVO.getIds());
List<Long> filteredDvIds = deviceMapper.selectScheduledDvIds(requestIds); List<Long> filteredDvIds = deviceMapper.selectScheduledDvIds(requestIds);
// 如果前端传了 ids则在排产设备中再次过滤
if (StringUtils.isNotBlank(reqVO.getIds())) { if (StringUtils.isNotBlank(reqVO.getIds())) {
Set<Long> requestIdSet = new HashSet<>(requestIds); Set<Long> requestIdSet = new HashSet<>(requestIds);
filteredDvIds = filteredDvIds.stream().filter(requestIdSet::contains).collect(Collectors.toList()); filteredDvIds = filteredDvIds.stream()
.filter(requestIdSet::contains)
.collect(Collectors.toList());
} }
if (filteredDvIds.isEmpty()) { if (filteredDvIds.isEmpty()) {
return "-1"; return "-1";
} }
return filteredDvIds.stream().map(String::valueOf).collect(Collectors.joining(","));
return filteredDvIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
} }
private boolean isHoliday(LocalDate day) { private boolean isHoliday(LocalDate day) {
@ -1848,10 +2013,6 @@ public class DeviceServiceImpl implements DeviceService {
return !CollectionUtils.isEmpty(holidays); return !CollectionUtils.isEmpty(holidays);
} }
private String toPercent(double value) {
return String.format("%.2f%%", value * 100);
}
private Collection<Long> parseIds(String ids) { private Collection<Long> parseIds(String ids) {
if (StringUtils.isBlank(ids)) { if (StringUtils.isBlank(ids)) {
return Collections.emptyList(); return Collections.emptyList();
@ -1865,5 +2026,71 @@ public class DeviceServiceImpl implements DeviceService {
/**
*
* calculateAndSetConvertedValues
* = 线 /
* = / 线
*/
private void calculateRate(DeviceTotalTimeRecordRespVO record) {
if (record == null) {
return;
}
double offlineSec = record.getTotalOfflineTime();
double runningSec = record.getTotalRunningTime();
double standbySec = record.getTotalStandbyTime();
double faultSec = record.getTotalFaultTime();
// 在线时间 = 运行 + 待机 + 故障
double onlineSec = runningSec + standbySec + faultSec;
double totalSec = offlineSec + onlineSec;
// 防止异常值
if (totalSec < 0) {
totalSec = 0;
}
// 开机率 = 在线时间 / 总时间
double powerOnRate = 0D;
if (totalSec > 0) {
powerOnRate = onlineSec / totalSec;
}
// 稼动率 = 运行时间 / 在线时间
double utilizationRate = 0D;
if (onlineSec > 0) {
utilizationRate = runningSec / onlineSec;
}
record.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate));
record.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate));
}
private Double getDoubleValue(Map<String, Object> row, String key) {
if (row == null || key == null) {
return 0D;
}
Object value = row.get(key);
if (value == null) {
value = row.get(key.toLowerCase());
}
if (value == null) {
return 0D;
}
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
try {
return Double.parseDouble(value.toString());
} catch (Exception e) {
return 0D;
}
}
} }

@ -2535,4 +2535,109 @@ public class TDengineService {
} }
} }
// ========================= app报表相关接口 ===================
@DS("tdengine")
public List<Map<String, Object>> selectDeviceStatsTrendFromTD(List<Long> deviceIds, String startTime, String endTime) {
StringBuilder sql = new StringBuilder();
List<Object> params = new ArrayList<>();
sql.append("SELECT ")
.append("_wstart AS statDay, ")
.append("device_id AS deviceId, ")
.append("SUM(CASE WHEN rule = '0' THEN 1 ELSE 0 END) * 60 AS totalOfflineTime, ")
.append("SUM(CASE WHEN rule = '1' THEN 1 ELSE 0 END) * 60 AS totalRunningTime, ")
.append("SUM(CASE WHEN rule = '2' THEN 1 ELSE 0 END) * 60 AS totalStandbyTime, ")
.append("SUM(CASE WHEN rule = '3' THEN 1 ELSE 0 END) * 60 AS totalFaultTime ")
.append("FROM besure_server.iot_device_operation_record ")
.append("WHERE deleted = 0 ");
if (startTime != null && !startTime.trim().isEmpty()) {
sql.append("AND create_time >= ? ");
params.add(startTime);
}
if (endTime != null && !endTime.trim().isEmpty()) {
sql.append("AND create_time <= ? ");
params.add(endTime);
}
// deviceIds 不为空时才加过滤
if (deviceIds != null && !deviceIds.isEmpty()) {
sql.append("AND device_id IN (");
for (int i = 0; i < deviceIds.size(); i++) {
if (i > 0) {
sql.append(", ");
}
sql.append("?");
params.add(deviceIds.get(i));
}
sql.append(") ");
}
sql.append("PARTITION BY device_id ")
.append("INTERVAL(1d) ")
.append("ORDER BY statDay ASC");
try {
return jdbcTemplate.queryForList(sql.toString(), params.toArray());
} catch (Exception e) {
log.error("TDengine 查询设备日趋势统计失败sql={}, params={}", sql, params, e);
return Collections.emptyList();
}
}
@DS("tdengine")
public List<Map<String, Object>> queryDeviceDayTrend(Long deviceId, String startTime, String endTime) {
StringBuilder sql = new StringBuilder();
List<Object> params = new ArrayList<>();
sql.append("SELECT ")
.append("_wstart AS statDay, ")
.append("device_id AS deviceId, ")
.append("SUM(CASE WHEN rule = '0' THEN 1 ELSE 0 END) * 60 AS totalOfflineTime, ")
.append("SUM(CASE WHEN rule = '1' THEN 1 ELSE 0 END) * 60 AS totalRunningTime, ")
.append("SUM(CASE WHEN rule = '2' THEN 1 ELSE 0 END) * 60 AS totalStandbyTime, ")
.append("SUM(CASE WHEN rule = '3' THEN 1 ELSE 0 END) * 60 AS totalFaultTime ")
.append("FROM besure_server.iot_device_operation_record ")
.append("WHERE deleted = 0 ")
.append("AND device_id = ? ");
params.add(deviceId);
if (startTime != null && !startTime.trim().isEmpty()) {
sql.append("AND create_time >= ? ");
params.add(startTime);
}
if (endTime != null && !endTime.trim().isEmpty()) {
sql.append("AND create_time <= ? ");
params.add(endTime);
}
sql.append("PARTITION BY device_id ")
.append("INTERVAL(1d) ")
.append("ORDER BY statDay ASC");
try {
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
for (Map<String, Object> row : list) {
Object statDay = row.get("statDay");
if (statDay instanceof java.sql.Timestamp) {
row.put("day", ((java.sql.Timestamp) statDay).toLocalDateTime().toLocalDate().toString());
} else if (statDay != null) {
String text = String.valueOf(statDay);
row.put("day", text.length() >= 10 ? text.substring(0, 10) : text);
} else {
row.put("day", null);
}
}
return list;
} catch (Exception e) {
log.error("TDengine 查询单设备日趋势失败sql={}, params={}", sql, params, e);
return Collections.emptyList();
}
}
} }

@ -56,7 +56,7 @@ public interface DeviceOperationRecordService {
List<DeviceTotalTimeRecordRespVO> deviceOperationPageList(@Valid DeviceTotalTimeRecordReqVO pageReqVO); List<DeviceTotalTimeRecordRespVO> deviceOperationPageList(@Valid DeviceTotalTimeRecordReqVO pageReqVO);
List<DeviceOperationRateTrendRespVO> getDeviceRateTrendByDeviceId(Long deviceId); List<DeviceOperationRateTrendRespVO> getDeviceRateTrendByDeviceId(Long deviceId, String period);
List<DeviceTotalTimeRecordRespVO> deviceOperationList(@Valid DeviceTotalTimeRecordReqVO pageReqVO); List<DeviceTotalTimeRecordRespVO> deviceOperationList(@Valid DeviceTotalTimeRecordReqVO pageReqVO);
} }

@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.iot.service.deviceoperationrecord; package cn.iocoder.yudao.module.iot.service.deviceoperationrecord;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceRateTrendPeriodEnum;
import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.utils.TimeConverterUtil; import cn.iocoder.yudao.module.iot.controller.admin.deviceoperationrecord.utils.TimeConverterUtil;
import cn.iocoder.yudao.module.iot.service.device.TDengineService; import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@ -12,11 +14,9 @@ import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.Duration; import java.time.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -92,6 +92,8 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
@Override @Override
public PageResult<DeviceTotalTimeRecordRespVO> deviceOperationPage(DeviceTotalTimeRecordReqVO pageReqVO) { public PageResult<DeviceTotalTimeRecordRespVO> deviceOperationPage(DeviceTotalTimeRecordReqVO pageReqVO) {
applyPeriodIfNecessary(pageReqVO);
// 1. 先从 MySQL 查询设备分页信息 // 1. 先从 MySQL 查询设备分页信息
Page<DeviceTotalTimeRecordRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); Page<DeviceTotalTimeRecordRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
IPage<DeviceTotalTimeRecordRespVO> mysqlDevicePage = IPage<DeviceTotalTimeRecordRespVO> mysqlDevicePage =
@ -106,6 +108,9 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
.map(DeviceTotalTimeRecordRespVO::getId) .map(DeviceTotalTimeRecordRespVO::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
log.info("deviceOperationPage mysql设备ID列表 pageReqVO.startTime={}, pageReqVO.endTime={}, deviceIds={}",
pageReqVO.getStartTime(), pageReqVO.getEndTime(), deviceIds);
// 3. 从 TDengine 批量查询统计数据 // 3. 从 TDengine 批量查询统计数据
List<Map<String, Object>> statsList = List<Map<String, Object>> statsList =
deviceOperationRecordMapper.selectDeviceStatsFromTD( deviceOperationRecordMapper.selectDeviceStatsFromTD(
@ -114,6 +119,9 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
pageReqVO.getEndTime() pageReqVO.getEndTime()
); );
log.info("deviceOperationPage TD原始统计 startTime={}, endTime={}, statsList={}",
pageReqVO.getStartTime(), pageReqVO.getEndTime(), statsList);
// 4. 转换为 Map<设备ID, 统计数据> // 4. 转换为 Map<设备ID, 统计数据>
Map<Long, DeviceTotalTimeRecordRespVO> tdStatsMap = convertStatsListToMap(statsList); Map<Long, DeviceTotalTimeRecordRespVO> tdStatsMap = convertStatsListToMap(statsList);
@ -122,6 +130,10 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
List<DeviceTotalTimeRecordRespVO> result = new ArrayList<>(); List<DeviceTotalTimeRecordRespVO> result = new ArrayList<>();
for (DeviceTotalTimeRecordRespVO device : mysqlDevicePage.getRecords()) { for (DeviceTotalTimeRecordRespVO device : mysqlDevicePage.getRecords()) {
DeviceTotalTimeRecordRespVO stats = tdStatsMap.get(device.getId()); DeviceTotalTimeRecordRespVO stats = tdStatsMap.get(device.getId());
log.info("deviceOperationPage 合并前 deviceId={}, deviceCode={}, deviceName={}, stats={}",
device.getId(), device.getDeviceCode(), device.getDeviceName(), stats);
if (stats != null) { if (stats != null) {
// 设置统计数据 // 设置统计数据
device.setTotalOfflineTime(stats.getTotalOfflineTime()); device.setTotalOfflineTime(stats.getTotalOfflineTime());
@ -137,6 +149,7 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
} }
result.add(device); result.add(device);
} }
log.info("deviceOperationPage mysql设备ID列表: {}", deviceIds);
// 5. 计算和转换 // 5. 计算和转换
calculateAndSetConvertedValues(result, pageReqVO); calculateAndSetConvertedValues(result, pageReqVO);
@ -148,6 +161,8 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
@Override @Override
public List<DeviceTotalTimeRecordRespVO> deviceOperationPageList(DeviceTotalTimeRecordReqVO pageReqVO) { public List<DeviceTotalTimeRecordRespVO> deviceOperationPageList(DeviceTotalTimeRecordReqVO pageReqVO) {
applyPeriodIfNecessary(pageReqVO);
List<DeviceTotalTimeRecordRespVO> deviceList = List<DeviceTotalTimeRecordRespVO> deviceList =
deviceOperationRecordMapper.selectDeviceListFromMySQL(pageReqVO); deviceOperationRecordMapper.selectDeviceListFromMySQL(pageReqVO);
@ -191,33 +206,153 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
} }
@Override @Override
public List<DeviceOperationRateTrendRespVO> getDeviceRateTrendByDeviceId(Long deviceId) { public List<DeviceOperationRateTrendRespVO> getDeviceRateTrendByDeviceId(Long deviceId, String period) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); DeviceRateTrendPeriodEnum.DateRange dateRange = resolvePeriodRange(period);
List<DeviceOperationRateTrendRespVO> result = new ArrayList<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
for (int offset = 6; offset >= 0; offset--) { String startTime = dateRange.getStart().atStartOfDay().format(formatter);
LocalDate day = LocalDate.now().minusDays(offset); String endTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0).format(formatter);
LocalDateTime dayStart = day.atStartOfDay();
LocalDateTime dayEnd = day.atTime(LocalTime.MAX).withNano(0);
DeviceTotalTimeRecordReqVO reqVO = new DeviceTotalTimeRecordReqVO(); log.info("getDeviceRateTrendByDeviceId 开始 deviceId={}, period={}, startTime={}, endTime={}",
reqVO.setIds(String.valueOf(deviceId)); deviceId, period, startTime, endTime);
reqVO.setStartTime(dayStart.format(formatter));
reqVO.setEndTime(dayEnd.format(formatter)); // queryDeviceDayTrend 改成“按 create_time 的日期分组”,
// 则这里每一天的结果就等价于 deviceOperationPage 单独查当天
List<Map<String, Object>> dayRows = tDengineService.queryDeviceDayTrend(deviceId, startTime, endTime);
log.info("getDeviceRateTrendByDeviceId TD原始结果 deviceId={}, dayRows={}", deviceId, dayRows);
Map<LocalDate, Map<String, Object>> dayMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(dayRows)) {
for (Map<String, Object> row : dayRows) {
Object dayObj = row.get("day");
if (dayObj == null) {
continue;
}
try {
dayMap.put(LocalDate.parse(String.valueOf(dayObj)), row);
} catch (Exception e) {
log.warn("解析设备日趋势日期失败deviceId={}, day={}", deviceId, dayObj);
}
}
}
List<DeviceTotalTimeRecordRespVO> dayList = deviceOperationPageList(reqVO); List<DeviceOperationRateTrendRespVO> result = new ArrayList<>();
DeviceTotalTimeRecordRespVO record = CollectionUtils.isNotEmpty(dayList) ? dayList.get(0) : null; for (LocalDate day = dateRange.getStart(); !day.isAfter(dateRange.getEnd()); day = day.plusDays(1)) {
Map<String, Object> row = dayMap.get(day);
DeviceOperationRateTrendRespVO trend = new DeviceOperationRateTrendRespVO(); DeviceOperationRateTrendRespVO trend = new DeviceOperationRateTrendRespVO();
trend.setDay(day.toString()); trend.setDay(day.toString());
trend.setPowerOnRate(record != null ? record.getPowerOnRate() : "0%");
trend.setUtilizationRate(record != null ? record.getUtilizationRate() : "0%"); if (row == null) {
trend.setPowerOnRate("0%");
trend.setUtilizationRate("0%");
result.add(trend);
continue;
}
try {
// 与 calculateAndSetConvertedValues 完全一致
double offlineSec = toDouble(row, "totalOfflineTime");
double runningSec = toDouble(row, "totalRunningTime");
double standbySec = toDouble(row, "totalStandbyTime");
double faultSec = toDouble(row, "totalFaultTime");
double onlineSec = runningSec + standbySec + faultSec;
double totalSec = offlineSec + onlineSec;
if (totalSec < 0) {
totalSec = 0;
}
double powerOnRate = 0D;
if (totalSec > 0D) {
powerOnRate = onlineSec / totalSec;
}
double utilizationRate = 0D;
if (onlineSec > 0D) {
utilizationRate = runningSec / onlineSec;
}
trend.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate));
trend.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate));
log.info("getDeviceRateTrendByDeviceId 每日计算 deviceId={}, day={}, row={}, " +
"offlineSec={}, runningSec={}, standbySec={}, faultSec={}, onlineSec={}, totalSec={}, " +
"powerOnRateRaw={}, utilizationRateRaw={}, powerOnRateStr={}, utilizationRateStr={}",
deviceId,
day,
row,
offlineSec,
runningSec,
standbySec,
faultSec,
onlineSec,
totalSec,
powerOnRate,
utilizationRate,
TimeConverterUtil.getPercentString(powerOnRate),
TimeConverterUtil.getPercentString(utilizationRate)
);
} catch (Exception e) {
log.error("计算设备日趋势失败deviceId={}, day={}", deviceId, day, e);
trend.setPowerOnRate("0%");
trend.setUtilizationRate("0%");
}
result.add(trend); result.add(trend);
} }
return result; return result;
} }
private static double toDouble(Map<String, Object> row, String key) {
if (row == null || row.get(key) == null) {
return 0D;
}
Object value = row.get(key);
if (value instanceof Number) {
return ((Number) value).doubleValue();
}
try {
return Double.parseDouble(String.valueOf(value));
} catch (Exception e) {
return 0D;
}
}
private void applyPeriodIfNecessary(DeviceTotalTimeRecordReqVO reqVO) {
if (StringUtils.isNotBlank(reqVO.getStartTime()) && StringUtils.isNotBlank(reqVO.getEndTime())) {
return;
}
String period = StringUtils.defaultIfBlank(
reqVO.getPeriod(),
DeviceRateTrendPeriodEnum.LAST_7_DAYS.getCode()
);
DeviceRateTrendPeriodEnum.DateRange dateRange = DeviceRateTrendPeriodEnum
.valueOfCode(period)
.resolve(LocalDate.now());
LocalDateTime startDateTime = dateRange.getStart().atStartOfDay();
LocalDateTime endDateTime = dateRange.getEnd().atTime(LocalTime.MAX).withNano(0);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
reqVO.setStartTime(startDateTime.format(formatter));
reqVO.setEndTime(endDateTime.format(formatter));
}
private DeviceRateTrendPeriodEnum.DateRange resolvePeriodRange(String period) {
String actualPeriod = StringUtils.defaultIfBlank(period, DeviceRateTrendPeriodEnum.LAST_7_DAYS.getCode());
return DeviceRateTrendPeriodEnum.valueOfCode(actualPeriod).resolve(LocalDate.now());
}
@Override @Override
public List<DeviceTotalTimeRecordRespVO> deviceOperationList(DeviceTotalTimeRecordReqVO deviceTotalTimeRecordReqVO) { public List<DeviceTotalTimeRecordRespVO> deviceOperationList(DeviceTotalTimeRecordReqVO deviceTotalTimeRecordReqVO) {
@ -391,6 +526,25 @@ public class DeviceOperationRecordServiceImpl implements DeviceOperationRecordSe
record.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate)); record.setPowerOnRate(TimeConverterUtil.getPercentString(powerOnRate));
record.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate)); record.setUtilizationRate(TimeConverterUtil.getPercentString(utilizationRate));
log.info("calculateAndSetConvertedValues deviceId={}, deviceCode={}, startTime={}, endTime={}, " +
"offlineSec={}, runningSec={}, standbySec={}, faultSec={}, onlineSec={}, totalSec={}, " +
"powerOnRateRaw={}, utilizationRateRaw={}, powerOnRateStr={}, utilizationRateStr={}",
record.getId(),
record.getDeviceCode(),
startTimeStr,
endTimeStr,
offlineSec,
runningSec,
standbySec,
faultSec,
onlineSec,
totalSec,
powerOnRate,
utilizationRate,
TimeConverterUtil.getPercentString(powerOnRate),
TimeConverterUtil.getPercentString(utilizationRate)
);
} catch (Exception e) { } catch (Exception e) {
log.error("计算设备{}时间统计出错: {}", record.getDeviceCode(), e.getMessage()); log.error("计算设备{}时间统计出错: {}", record.getDeviceCode(), e.getMessage());
setDefaultValues(record); setDefaultValues(record);

@ -299,5 +299,13 @@
ORDER BY d.id DESC ORDER BY d.id DESC
</select> </select>
<select id="selectHolidayDaysInRange" resultType="java.util.Date">
SELECT DISTINCT the_day
FROM mes_cal_holiday
WHERE deleted = b'0'
AND the_day &gt;= #{startDay}
AND the_day &lt; #{endDayExclusive}
AND holiday_type = 'HOLIDAY'
</select>
</mapper> </mapper>

@ -139,39 +139,6 @@ public class DashboardController {
item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX<TaskDO>() item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX<TaskDO>()
.betweenIfPresent(TaskDO::getCreateTime, taskReqVO.getStartTime()))); // 创建时间 .betweenIfPresent(TaskDO::getCreateTime, taskReqVO.getStartTime()))); // 创建时间
taskItems.add(item); taskItems.add(item);
// // 未开工任务数
// item = new TaskRespVO.Item();
// item.setKey("2");
// item.setLabel("未开工任务数");
// Collection<Long> count1 = new ArrayList<>();
// count1.add(1L);
// count1.add(2L);
// count1.add(3L);
// item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX<TaskDO>()
// .in(TaskDO::getStatus, count1)
// .betweenIfPresent(TaskDO::getOrderDate, taskReqVO.getStartTime()))); // 下达时间
// taskItems.add(item);
// // 生产中任务数
// item = new TaskRespVO.Item();
// item.setKey("3");
// item.setLabel("生产中任务数");
// Collection<Long> count2 = new ArrayList<>();
// count2.add(4L);
// item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX<TaskDO>()
// .in(TaskDO::getStatus, count2)
// .betweenIfPresent(TaskDO::getOrderDate, taskReqVO.getStartTime())));
// taskItems.add(item);
// // 完工任务数
// item = new TaskRespVO.Item();
// item.setKey("4");
// item.setLabel("完工任务数");
// Collection<Long> count3 = new ArrayList<>();
// count3.add(5L);
// count3.add(6L);
// item.setValue(taskMapper.selectCount(new LambdaQueryWrapperX<TaskDO>()
// .in(TaskDO::getStatus, count3)
// .betweenIfPresent(TaskDO::getOrderDate, taskReqVO.getStartTime())));
// taskItems.add(item);
// 生产计划总数 // 生产计划总数
@ -347,66 +314,108 @@ public class DashboardController {
@GetMapping("/getTodoList") @GetMapping("/getTodoList")
@Operation(summary = "获得待办任务") @Operation(summary = "获得待办任务")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
// @PreAuthorize("@ss.hasPermission('mes:bom:query')") // @PreAuthorize("@ss.hasPermission('mes:bom:query')")
public CommonResult<List<TodoRespVO>> getTodoList() { public CommonResult<List<TodoRespVO>> getTodoList() {
// 待办结果集
List<TodoRespVO> todoRespVOList = new ArrayList<>(); List<TodoRespVO> todoRespVOList = new ArrayList<>();
// 设备维修
// 1. 查询各类待办数据
List<DvRepairDO> dvRepairDOList = dvRepairService.getDvRepairDOListByStatus(); List<DvRepairDO> dvRepairDOList = dvRepairService.getDvRepairDOListByStatus();
List<TicketManagementDO> ticketManagementDOList = ticketManagementService.getListByJobStatus();
List<MoldRepairDO> moldRepairDOList = moldRepairService.getMoldRepairDOListByStatus();
List<MoldTicketManagementDO> moldTicketManagementDOList = moldTicketManagementService.getListByJobStatus();
// 2. 批量查询设备名称,避免循环中逐条查库
Map<Long, String> deviceNameMap = new HashMap<>();
if (dvRepairDOList != null && !dvRepairDOList.isEmpty()) {
List<Long> deviceIds = dvRepairDOList.stream()
.map(DvRepairDO::getDeviceId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (!deviceIds.isEmpty()) {
List<DeviceLedgerDO> deviceLedgerList = deviceLedgerService.getDeviceLedgerListByIds(deviceIds);
deviceNameMap = deviceLedgerList.stream()
.collect(Collectors.toMap(
DeviceLedgerDO::getId,
DeviceLedgerDO::getDeviceName,
(a, b) -> a
));
}
}
// 3. 批量查询模具名称,避免循环中逐条查库
Map<Long, String> moldNameMap = new HashMap<>();
if (moldRepairDOList != null && !moldRepairDOList.isEmpty()) {
List<Long> moldIds = moldRepairDOList.stream()
.map(MoldRepairDO::getMoldId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (!moldIds.isEmpty()) {
List<MoldDO> moldList = moldService.getMoldListByIds(moldIds);
moldNameMap = moldList.stream()
.collect(Collectors.toMap(
MoldDO::getId,
MoldDO::getName,
(a, b) -> a
));
}
}
// 4. 组装设备维修待办
for (DvRepairDO dvRepairDO : dvRepairDOList) { for (DvRepairDO dvRepairDO : dvRepairDOList) {
TodoRespVO todoRespVO = new TodoRespVO(); TodoRespVO todoRespVO = new TodoRespVO();
todoRespVO.setCode(dvRepairDO.getRepairCode()); todoRespVO.setCode(dvRepairDO.getRepairCode());
todoRespVO.setName(dvRepairDO.getRepairName()); todoRespVO.setName(dvRepairDO.getRepairName());
todoRespVO.setType("设备维修"); todoRespVO.setType("设备维修");
todoRespVO.setDeviceName(deviceLedgerService.getDeviceLedger(dvRepairDO.getDeviceId()).getDeviceName()); todoRespVO.setDeviceName(deviceNameMap.getOrDefault(dvRepairDO.getDeviceId(), "未知设备"));
todoRespVO.setCreateTime(dvRepairDO.getCreateTime()); todoRespVO.setCreateTime(dvRepairDO.getCreateTime());
todoRespVOList.add(todoRespVO); todoRespVOList.add(todoRespVO);
} }
// 设备保养 点检
List<TicketManagementDO> ticketManagementDOList = ticketManagementService.getListByJobStatus(); // 5. 组装设备保养 / 点检待办
for (TicketManagementDO ticketManagementDO : ticketManagementDOList) { for (TicketManagementDO ticketManagementDO : ticketManagementDOList) {
TodoRespVO todoRespVO = new TodoRespVO(); TodoRespVO todoRespVO = new TodoRespVO();
todoRespVO.setCode(ticketManagementDO.getPlanNo()); todoRespVO.setCode(ticketManagementDO.getPlanNo());
todoRespVO.setName(ticketManagementDO.getConfigName()); todoRespVO.setName(ticketManagementDO.getConfigName());
if (ticketManagementDO.getPlanType() == 2) { todoRespVO.setType(ticketManagementDO.getPlanType() == 2 ? "设备保养" : "设备点检");
todoRespVO.setType("设备保养");
} else {
todoRespVO.setType("设备点检");
}
todoRespVO.setDeviceName(ticketManagementDO.getDeviceName()); todoRespVO.setDeviceName(ticketManagementDO.getDeviceName());
todoRespVO.setCreateTime(ticketManagementDO.getCreateTime()); todoRespVO.setCreateTime(ticketManagementDO.getCreateTime());
todoRespVOList.add(todoRespVO); todoRespVOList.add(todoRespVO);
} }
// 模具维修
List<MoldRepairDO> moldRepairDOList = moldRepairService.getMoldRepairDOListByStatus(); // 6. 组装模具维修待办
for (MoldRepairDO moldRepairDO : moldRepairDOList) { for (MoldRepairDO moldRepairDO : moldRepairDOList) {
TodoRespVO todoRespVO = new TodoRespVO(); TodoRespVO todoRespVO = new TodoRespVO();
todoRespVO.setCode(moldRepairDO.getRepairCode()); todoRespVO.setCode(moldRepairDO.getRepairCode());
todoRespVO.setName(moldRepairDO.getRepairName()); todoRespVO.setName(moldRepairDO.getRepairName());
todoRespVO.setType("模具维修"); todoRespVO.setType("模具维修");
todoRespVO.setDeviceName( moldRepairDO.getMoldId() != null && moldService.getMold(moldRepairDO.getMoldId()) != null todoRespVO.setDeviceName(moldNameMap.getOrDefault(moldRepairDO.getMoldId(), "未知设备"));
? moldService.getMold(moldRepairDO.getMoldId()).getName()
: "未知设备");
todoRespVO.setCreateTime(moldRepairDO.getCreateTime()); todoRespVO.setCreateTime(moldRepairDO.getCreateTime());
todoRespVOList.add(todoRespVO); todoRespVOList.add(todoRespVO);
} }
// 模具保养 点检
List<MoldTicketManagementDO> moldTicketManagementDOList = moldTicketManagementService.getListByJobStatus(); // 7. 组装模具保养 / 点检待办
for (MoldTicketManagementDO moldTicketManagementDO : moldTicketManagementDOList) { for (MoldTicketManagementDO moldTicketManagementDO : moldTicketManagementDOList) {
TodoRespVO todoRespVO = new TodoRespVO(); TodoRespVO todoRespVO = new TodoRespVO();
todoRespVO.setCode(moldTicketManagementDO.getPlanNo()); todoRespVO.setCode(moldTicketManagementDO.getPlanNo());
todoRespVO.setName(moldTicketManagementDO.getConfigName()); todoRespVO.setName(moldTicketManagementDO.getConfigName());
if (moldTicketManagementDO.getPlanType() == 2) { todoRespVO.setType(moldTicketManagementDO.getPlanType() == 2 ? "模具保养" : "模具点检");
todoRespVO.setType("模具保养");
} else {
todoRespVO.setType("模具点检");
}
todoRespVO.setDeviceName(moldTicketManagementDO.getMoldName()); todoRespVO.setDeviceName(moldTicketManagementDO.getMoldName());
todoRespVO.setCreateTime(moldTicketManagementDO.getCreateTime()); todoRespVO.setCreateTime(moldTicketManagementDO.getCreateTime());
todoRespVOList.add(todoRespVO); todoRespVOList.add(todoRespVO);
} }
return success(todoRespVOList);
// 8. 按创建时间倒序排序,最近的待办排前面
todoRespVOList.sort(Comparator.comparing(
TodoRespVO::getCreateTime,
Comparator.nullsLast(Comparator.reverseOrder())
));
return success(todoRespVOList);
} }
@GetMapping("/getDeviceRepairLineOptions") @GetMapping("/getDeviceRepairLineOptions")

@ -83,5 +83,7 @@ public interface DeviceLedgerService {
Map<Long, DeviceLedgerDO> getDeviceMap(Set<Long> longs); Map<Long, DeviceLedgerDO> getDeviceMap(Set<Long> longs);
List<DeviceLedgerDO> getDeviceLedgerListByIds(Collection<Long> ids);
} }

@ -431,4 +431,11 @@ public class DeviceLedgerServiceImpl implements DeviceLedgerService {
return deviceLedgerMapper.selectListByIds(ids).stream() return deviceLedgerMapper.selectListByIds(ids).stream()
.collect(Collectors.toMap(DeviceLedgerDO::getId, Function.identity(), (a, b) -> a)); .collect(Collectors.toMap(DeviceLedgerDO::getId, Function.identity(), (a, b) -> a));
} }
@Override
public List<DeviceLedgerDO> getDeviceLedgerListByIds(Collection<Long> ids) {
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
return deviceLedgerMapper.selectBatchIds(ids); }
} }
Loading…
Cancel
Save