package com.ruoyi.safety.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.framework.redis.RedisCache; import com.ruoyi.safety.dto.SafetyInspectionTodayStatistics; import com.ruoyi.safety.dto.SafetyInspectionTrendStat; import com.ruoyi.safety.dto.SafetyInspectionTypeStat; import com.ruoyi.safety.dto.SafetyInspectorStat; import com.ruoyi.safety.mapper.SafetyInspectionRecordMapper; import com.ruoyi.safety.pojo.SafetyInspectionRecord; import com.ruoyi.safety.service.SafetyInspectionRecordService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @Service public class SafetyInspectionRecordServiceImpl extends SafetyBaseServiceImpl implements SafetyInspectionRecordService { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private static final String SYNC_DAILY_KEY_PREFIX = "safety:inspection:sync:daily:"; @Autowired private RedisCache redisCache; @Override public IPage queryPage(Page page, SafetyInspectionRecord query, String startDate, String endDate) { QueryWrapper wrapper = new QueryWrapper().orderByDesc("inspection_time"); if (query != null) { if (query.getInspectorId() != null) { wrapper.eq("inspector_id", query.getInspectorId()); } if (hasText(query.getInspector())) { wrapper.like("inspector", query.getInspector()); } if (query.getAreaId() != null) { wrapper.eq("area_id", query.getAreaId()); } if (hasText(query.getArea())) { wrapper.like("area", query.getArea()); } if (hasText(query.getType())) { wrapper.eq("type", query.getType()); } if (query.getStatus() != null) { wrapper.eq("status", query.getStatus()); } } if (hasText(startDate)) { wrapper.ge("inspection_time", startDate + " 00:00:00"); } if (hasText(endDate)) { wrapper.le("inspection_time", endDate + " 23:59:59"); } return page(page, wrapper); } @Override public IPage queryPage(Page page, SafetyInspectionRecord query) { return queryPage(page, query, null, null); } @Override public SafetyInspectionTodayStatistics getTodayStatistics() { return baseMapper.selectTodayStatistics(LocalDate.now()); } @Override public List getTrendStatistics(String startDate, String endDate) { String[] range = normalizeRange(startDate, endDate); return baseMapper.selectTrendStatistics(range[0], range[1]); } @Override public List getTypeStatistics(String startDate, String endDate) { String[] range = normalizeRange(startDate, endDate); return baseMapper.selectTypeStatistics(range[0], range[1]); } @Override public List getInspectorStatistics(String startDate, String endDate) { String[] range = normalizeRange(startDate, endDate); return baseMapper.selectInspectorStatistics(range[0], range[1]); } @Override public List syncMockSubsystemData() { String todaySyncKey = buildTodaySyncKey(); if (Boolean.TRUE.equals(redisCache.hasKey(todaySyncKey))) { throw new ServiceException("今日已同步,明天再试"); } List mockRecords = buildMockRecords(); saveBatch(mockRecords); int secondsToEndOfDay = secondsToEndOfDay(); redisCache.setCacheObject(todaySyncKey, "1", secondsToEndOfDay, TimeUnit.SECONDS); return mockRecords; } private String[] normalizeRange(String startDate, String endDate) { LocalDate end = hasText(endDate) ? LocalDate.parse(endDate, DATE_FORMATTER) : LocalDate.now(); LocalDate start = hasText(startDate) ? LocalDate.parse(startDate, DATE_FORMATTER) : end.minusDays(6); return new String[]{start.format(DATE_FORMATTER), end.format(DATE_FORMATTER)}; } private List buildMockRecords() { LocalDate today = LocalDate.now(); LocalDateTime now = LocalDateTime.now(); String operator = currentUsername(); List records = new ArrayList(18); records.add(createMockRecord(today.minusDays(6), LocalTime.of(8, 30), 101L, "李静", 1L, "大厅", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(6), LocalTime.of(10, 20), 102L, "李世杰", 2L, "前台", "fire", 1, 0, "\u706d\u706b\u5668\u538b\u529b\u4f4e", now, operator)); records.add(createMockRecord(today.minusDays(5), LocalTime.of(9, 15), 101L, "王亚伟", 3L, "大厅", "equipment", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(5), LocalTime.of(14, 0), 103L, "王亚伟", 1L, "大厅", "daily", 3, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(4), LocalTime.of(8, 45), 102L, "李世杰", 2L, "机电房", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(4), LocalTime.of(15, 30), 104L, "顾全", 4L, "机房", "night", 2, 1, "\u5de1\u68c0\u70b9A3\u6f0f\u68c0", now, operator)); records.add(createMockRecord(today.minusDays(3), LocalTime.of(9, 5), 101L, "李静", 1L, "锅炉房", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(3), LocalTime.of(16, 20), 103L, "王亚伟", 3L, "机电房", "fire", 1, 0, "\u5e94\u6025\u901a\u9053\u5806\u653e\u5835\u585e", now, operator)); records.add(createMockRecord(today.minusDays(2), LocalTime.of(8, 55), 102L, "李世杰", 2L, "机电房", "equipment", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(2), LocalTime.of(13, 40), 104L, "顾全", 4L, "机房", "night", 3, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(1), LocalTime.of(8, 40), 101L, "李静", 1L, "机房", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(1), LocalTime.of(10, 5), 102L, "李世杰", 2L, "储物间", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today.minusDays(1), LocalTime.of(14, 35), 103L, "王亚伟", 3L, "储物间", "fire", 1, 0, "\u5b89\u5168\u6807\u8bc6\u7834\u635f", now, operator)); records.add(createMockRecord(today.minusDays(1), LocalTime.of(17, 10), 104L, "顾全", 4L, "储物间", "equipment", 2, 1, "\u5de5\u5177\u7bb1\u70b9\u68c0\u6f0f\u68c0", now, operator)); records.add(createMockRecord(today, LocalTime.of(8, 20), 101L, "李静", 1L, "二楼消防间", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today, LocalTime.of(10, 10), 102L, "李世杰", 2L, "二楼消防间", "daily", 0, 0, null, now, operator)); records.add(createMockRecord(today, LocalTime.of(14, 25), 103L, "王亚伟", 3L, "二楼消防间", "equipment", 0, 0, null, now, operator)); records.add(createMockRecord(today, LocalTime.of(16, 50), 104L, "顾全", 4L, "大厅", "night", 3, 0, null, now, operator)); return records; } private SafetyInspectionRecord createMockRecord(LocalDate date, LocalTime time, Long inspectorId, String inspector, Long areaId, String area, String type, Integer status, Integer isMissed, String abnormalDesc, LocalDateTime createTime, String createBy) { SafetyInspectionRecord record = new SafetyInspectionRecord(); record.setInspectionTime(LocalDateTime.of(date, time)); record.setInspectorId(inspectorId); record.setInspector(inspector); record.setAreaId(areaId); record.setArea(area); record.setType(type); record.setStatus(status); record.setIsMissed(isMissed); record.setAbnormalDesc(abnormalDesc); record.setRemark("mock-subsystem-sync"); record.setCreateTime(createTime); record.setCreateBy(createBy); record.setDelFlag(0); return record; } private String buildTodaySyncKey() { String tenantPart = "default"; try { Long tenantId = com.ruoyi.common.utils.SecurityUtils.getLoginUser().getTenantId(); if (tenantId != null) { tenantPart = String.valueOf(tenantId); } } catch (Exception ignored) { } return SYNC_DAILY_KEY_PREFIX + tenantPart + ":" + LocalDate.now().format(DATE_FORMATTER); } private int secondsToEndOfDay() { LocalDateTime now = LocalDateTime.now(); LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); long seconds = java.time.Duration.between(now, endOfDay).getSeconds(); return (int) Math.max(seconds, 1L); } }