增加告警年统计、月统计接口,增加设备列表接口
This commit is contained in:
parent
94953eb330
commit
4cda521e81
|
|
@ -0,0 +1,128 @@
|
|||
package org.jeecg.modules.appmana.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.constant.PollutionConstants;
|
||||
import org.jeecg.common.dto.AlertSummaryDTO;
|
||||
import org.jeecg.common.entity.SurvDeviceDeploy;
|
||||
import org.jeecg.common.entity.SurvDisplayInfo;
|
||||
import org.jeecg.common.entity.SurvPestlightAlert;
|
||||
import org.jeecg.common.entity.SurvStationInfo;
|
||||
import org.jeecg.common.util.DateTimeRangeUtil;
|
||||
import org.jeecg.common.vo.PestLightAlertVo;
|
||||
import org.jeecg.common.vo.result.DataCenterDataSummary;
|
||||
import org.jeecg.common.vo.statistic.AlertSummaryVo;
|
||||
import org.jeecg.modules.appmana.service.ISurvAlertRecordService;
|
||||
import org.jeecg.modules.appmana.service.ISurvDeviceDeployService;
|
||||
import org.jeecg.modules.appmana.service.ISurvPestlightAlertService;
|
||||
import org.jeecg.modules.appmana.service.ISurvStationInfoService;
|
||||
import org.jeecg.modules.appmana.service.impl.CommonServiceImpl;
|
||||
import org.jeecg.modules.appmana.service.impl.IotCommonP3ServiceImpl;
|
||||
import org.jeecg.modules.appmana.utils.MonitoringDataRichTextBuilder;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@Api(tags="公共接口")
|
||||
@RestController
|
||||
@RequestMapping("/appmana/dataCenter")
|
||||
@Slf4j
|
||||
public class DataCenterController {
|
||||
@Autowired
|
||||
private ISurvDeviceDeployService survDeviceDeployService;
|
||||
|
||||
@Autowired
|
||||
private CommonServiceImpl commonService;
|
||||
|
||||
@Autowired
|
||||
private ISurvAlertRecordService survAlertRecordService;
|
||||
|
||||
@Autowired
|
||||
private ISurvStationInfoService survStationInfoService;
|
||||
|
||||
/**
|
||||
* 获取所有大屏信息
|
||||
*/
|
||||
@GetMapping(value = "/dataSummary")
|
||||
public Result<DataCenterDataSummary> dataSummary() {
|
||||
DataCenterDataSummary re = new DataCenterDataSummary();
|
||||
//当前租户所有设备
|
||||
List<SurvDeviceDeploy> deviceList = survDeviceDeployService.lambdaQuery()
|
||||
.list();
|
||||
LocalDateTime weekStart = DateTimeRangeUtil.getWeekStart();
|
||||
LocalDateTime weekEnd = DateTimeRangeUtil.getWeekEnd();
|
||||
|
||||
LocalDateTime monthStart = DateTimeRangeUtil.getMonthStart();
|
||||
LocalDateTime monthEnd = DateTimeRangeUtil.getMonthEnd();
|
||||
|
||||
LocalDateTime yearStart = DateTimeRangeUtil.getYearStart();
|
||||
LocalDateTime yearEnd = DateTimeRangeUtil.getYearEnd();
|
||||
|
||||
|
||||
re.setWeekHtml(commonService.buildDeviceReport(deviceList,weekStart,weekEnd));
|
||||
re.setMonthHtml(commonService.buildDeviceReport(deviceList,monthStart,monthEnd));
|
||||
re.setYearHtml(commonService.buildDeviceReport(deviceList,yearStart,yearEnd));
|
||||
return Result.OK(re);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备统计监测统计数据
|
||||
*/
|
||||
@PostMapping(value = "/deviceAlertStatistic")
|
||||
public Result<AlertSummaryVo> deviceAlertStatistic(@RequestBody AlertSummaryDTO alertSummaryDTO) {
|
||||
|
||||
alertSummaryDTO.setTenantId(TenantContext.getTenant());
|
||||
AlertSummaryVo alertSummaryVo = survAlertRecordService.getSummary(alertSummaryDTO);
|
||||
return Result.OK(alertSummaryVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有设备数据
|
||||
*/
|
||||
@GetMapping(value = "/deviceList")
|
||||
public Result< List<SurvDeviceDeploy>> deviceList() {
|
||||
List<String> deployTypes = new ArrayList<>();
|
||||
deployTypes.add(PollutionConstants.SOIL_SURV);
|
||||
deployTypes.add(PollutionConstants.AIR_SURV);
|
||||
deployTypes.add(PollutionConstants.WATER_QULITY);
|
||||
deployTypes.add(PollutionConstants.STINK);
|
||||
deployTypes.add(PollutionConstants.WATER_LIVE);
|
||||
deployTypes.add(PollutionConstants.WATER_ORIENT);
|
||||
|
||||
List<SurvDeviceDeploy> deviceList = survDeviceDeployService.lambdaQuery()
|
||||
.in(SurvDeviceDeploy::getDeployType,deployTypes)
|
||||
.orderByDesc(SurvDeviceDeploy::getDeployType)
|
||||
.orderByAsc(SurvDeviceDeploy::getSortNo)
|
||||
.orderByDesc(SurvDeviceDeploy::getCreateTime)
|
||||
.list();
|
||||
if(deviceList!=null){
|
||||
List<SurvStationInfo> stationList = survStationInfoService.list();
|
||||
Map<String,SurvStationInfo> stationInfoMap = new HashMap<>();
|
||||
stationList.forEach(item->{
|
||||
stationInfoMap.put(item.getStationCode(),item);
|
||||
});
|
||||
deviceList.forEach(item->{
|
||||
SurvStationInfo stationInfo = stationInfoMap.get(item.getStationCode());
|
||||
if(stationInfo!=null){
|
||||
item.setDeployDes(stationInfo.getStationName()+" - " + item.getDeployDes());
|
||||
}
|
||||
});
|
||||
}
|
||||
return Result.OK(deviceList);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,9 +20,10 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* @Description: 大屏信息管理
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2023-07-14
|
||||
|
|
@ -168,4 +169,15 @@ public class SurvDisplayInfoController extends JeecgController<SurvDisplayInfo,
|
|||
return super.importExcel(request, response, SurvDisplayInfo.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有大屏信息
|
||||
*/
|
||||
@GetMapping(value = "/getQualityData")
|
||||
public Result<SurvDisplayInfo> getQualityData(@RequestParam String infoKey) {
|
||||
List<SurvDisplayInfo> dis5 = survDisplayInfoService.getInfoByType(infoKey);
|
||||
SurvDisplayInfo re = dis5.size()>0?dis5.get(0):null;
|
||||
return Result.OK(re);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.jeecg.common.entity.SurvAlertRecord;
|
||||
import org.jeecg.common.vo.statistic.AlertSummayDetail;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -20,4 +22,22 @@ public interface SurvAlertRecordMapper extends BaseMapper<SurvAlertRecord> {
|
|||
|
||||
IPage<SurvAlertRecord> pageByDevice(IPage<SurvAlertRecord> page, @Param("deviceList") List<String> deviceList, @Param("yearStr") String yearStr);
|
||||
|
||||
List<AlertSummayDetail> getSpotCheckData(@Param("deployId")String deployId,@Param("itemCode")String itemCode, @Param("dateList") List<String> dateList,@Param("startDateTime")LocalDateTime startDateTime,@Param("endDateTime")LocalDateTime endDateTime);
|
||||
|
||||
List<AlertSummayDetail> getDailyMaxSpotCheckData(
|
||||
@Param("dateList") List<String> dateList,
|
||||
@Param("startDateTime") LocalDateTime startDateTime,
|
||||
@Param("endDateTime") LocalDateTime endDateTime,
|
||||
@Param("deployId") String deployId,
|
||||
@Param("itemCode") String itemCode
|
||||
);
|
||||
|
||||
|
||||
List<AlertSummayDetail> getMonthMaxSpotCheckData(
|
||||
@Param("dateList") List<String> dateList,
|
||||
@Param("startDateTime") LocalDateTime startDateTime,
|
||||
@Param("endDateTime") LocalDateTime endDateTime,
|
||||
@Param("deployId") String deployId,
|
||||
@Param("itemCode") String itemCode
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,4 +28,7 @@ public interface SurvDeviceDeployMapper extends BaseMapper<SurvDeviceDeploy> {
|
|||
|
||||
@InterceptorIgnore(illegalSql = "true", tenantLine = "true")
|
||||
SurvDeviceDeploy getDeviceById(@Param("deployId")String deployId, @Param("tenantId")String tenantId);
|
||||
|
||||
@InterceptorIgnore(illegalSql = "true", tenantLine = "true")
|
||||
SurvDeviceDeploy getDeployZhibiao(@Param("deployId")String deployId, @Param("tenantId")String tenantId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
<result property="survUnit" column="SURV_UNIT" jdbcType="VARCHAR"/>
|
||||
<result property="readStatus" column="READ_STATUS" jdbcType="VARCHAR"/>
|
||||
<result property="stationName" column="STATION_NAME" jdbcType="VARCHAR"/>
|
||||
<!-- <association property="stationName" select="getStationName" column="DEPLOY_CODE"/>-->
|
||||
<!-- <association property="stationName" select="getStationName" column="DEPLOY_CODE"/>-->
|
||||
</resultMap>
|
||||
|
||||
<sql id="baseSql">
|
||||
|
|
@ -77,4 +77,108 @@
|
|||
</where>
|
||||
order by ALERT_TIME desc
|
||||
</select>
|
||||
|
||||
|
||||
<select id="getSpotCheckData" resultType="org.jeecg.common.vo.statistic.AlertSummayDetail">
|
||||
SELECT
|
||||
ti.interval_start as alertTime,
|
||||
COALESCE(ad.ID, 0) as id,
|
||||
COALESCE(ad.DEPLOY_ID, #{deployId}) as deployId,
|
||||
COALESCE(ad.NORMAL_VALUE, 0) as normalValue,
|
||||
COALESCE(ad.SURV_VALUE, 0) as survValue,
|
||||
COALESCE(ad.ITEM_CODE, #{itemCode}) as itemCode,
|
||||
CASE WHEN ad.ALERT_TIME IS NULL THEN 0 ELSE 1 END as hasData
|
||||
FROM (
|
||||
<foreach item="items" collection="dateList" separator="union all">
|
||||
SELECT CAST(#{items} AS DATETIME) as interval_start
|
||||
</foreach>
|
||||
) ti
|
||||
LEFT JOIN (
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
t.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(t.ALERT_TIME), HOUR(t.ALERT_TIME), FLOOR(MINUTE(t.ALERT_TIME) / 15)
|
||||
ORDER BY t.ALERT_TIME ASC
|
||||
) AS rn
|
||||
FROM surv_alert_record t
|
||||
WHERE t.ALERT_TIME >= #{startDateTime}
|
||||
AND t.ALERT_TIME <= #{endDateTime}
|
||||
AND t.DEPLOY_ID = #{deployId}
|
||||
AND t.ITEM_CODE = #{itemCode}
|
||||
) temp
|
||||
WHERE temp.rn = 1
|
||||
) ad ON ad.ALERT_TIME >= ti.interval_start
|
||||
AND ad.ALERT_TIME < DATE_ADD(ti.interval_start, INTERVAL 5 MINUTE)
|
||||
ORDER BY ti.interval_start;
|
||||
</select>
|
||||
|
||||
<select id="getDailyMaxSpotCheckData" resultType="org.jeecg.common.vo.statistic.AlertSummayDetail">
|
||||
SELECT
|
||||
ti.interval_start as alertTime,
|
||||
COALESCE(ad.ID, 0) as id,
|
||||
COALESCE(ad.DEPLOY_ID, #{deployId}) as deployId,
|
||||
COALESCE(ad.NORMAL_VALUE, 0) as normalValue,
|
||||
COALESCE(ad.SURV_VALUE, 0) as survValue,
|
||||
COALESCE(ad.ITEM_CODE, #{itemCode}) as itemCode,
|
||||
CASE WHEN ad.ALERT_TIME IS NULL THEN 0 ELSE 1 END as hasData
|
||||
FROM (
|
||||
<foreach item="items" collection="dateList" separator="union all">
|
||||
SELECT CAST(#{items} AS DATE) as interval_start
|
||||
</foreach>
|
||||
) ti
|
||||
LEFT JOIN (
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
t.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY DATE(t.ALERT_TIME)
|
||||
ORDER BY CAST(t.SURV_VALUE AS DECIMAL(18,2)) DESC, t.ALERT_TIME ASC
|
||||
) AS rn
|
||||
FROM surv_alert_record t
|
||||
WHERE t.ALERT_TIME >= #{startDateTime}
|
||||
AND t.ALERT_TIME <= #{endDateTime}
|
||||
AND t.DEPLOY_ID = #{deployId}
|
||||
AND t.ITEM_CODE = #{itemCode}
|
||||
) temp
|
||||
WHERE temp.rn = 1
|
||||
) ad ON DATE(ad.ALERT_TIME) = ti.interval_start
|
||||
ORDER BY ti.interval_start;
|
||||
</select>
|
||||
|
||||
<!-- 按月查询,取每月 SURV_VALUE 最大的记录 -->
|
||||
<select id="getMonthMaxSpotCheckData" resultType="org.jeecg.common.vo.statistic.AlertSummayDetail">
|
||||
SELECT
|
||||
ti.interval_start as alertTime,
|
||||
COALESCE(ad.ID, 0) as id,
|
||||
COALESCE(ad.DEPLOY_ID, #{deployId}) as deployId,
|
||||
COALESCE(ad.NORMAL_VALUE, 0) as normalValue,
|
||||
COALESCE(ad.SURV_VALUE, 0) as survValue,
|
||||
COALESCE(ad.ITEM_CODE, #{itemCode}) as itemCode,
|
||||
CASE WHEN ad.ALERT_TIME IS NULL THEN 0 ELSE 1 END as hasData
|
||||
FROM (
|
||||
<foreach item="items" collection="dateList" separator="union all">
|
||||
-- 支持 yyyy-MM 和 yyyy-MM-dd 两种格式
|
||||
SELECT CAST(CONCAT(#{items}, IF(LENGTH(#{items}) = 7, '-01', '')) AS DATE) as interval_start
|
||||
</foreach>
|
||||
) ti
|
||||
LEFT JOIN (
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
t.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY YEAR(t.ALERT_TIME), MONTH(t.ALERT_TIME)
|
||||
ORDER BY CAST(t.SURV_VALUE AS DECIMAL(18,2)) DESC, t.ALERT_TIME ASC
|
||||
) AS rn
|
||||
FROM surv_alert_record t
|
||||
WHERE t.ALERT_TIME >= #{startDateTime}
|
||||
AND t.ALERT_TIME <= #{endDateTime}
|
||||
AND t.DEPLOY_ID = #{deployId}
|
||||
AND t.ITEM_CODE = #{itemCode}
|
||||
) temp
|
||||
WHERE temp.rn = 1
|
||||
) ad ON YEAR(ad.ALERT_TIME) = YEAR(ti.interval_start)
|
||||
AND MONTH(ad.ALERT_TIME) = MONTH(ti.interval_start)
|
||||
ORDER BY ti.interval_start;
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -147,4 +147,8 @@
|
|||
<select id="getDeviceById" resultType="org.jeecg.common.entity.SurvDeviceDeploy">
|
||||
select <include refid="basesql"/> from surv_device_deploy where IS_DEL = 0 AND ID = #{deployId} AND TENANT_ID = #{tenantId} limit 1
|
||||
</select>
|
||||
|
||||
<select id="getDeployZhibiao" resultMap="zhibiaoMap">
|
||||
select <include refid="basesql"/> from surv_device_deploy where IS_DEL = 0 AND ID = #{deployId} AND TENANT_ID = #{tenantId} limit 1
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -2,7 +2,9 @@ package org.jeecg.modules.appmana.service;
|
|||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.common.dto.AlertSummaryDTO;
|
||||
import org.jeecg.common.entity.SurvAlertRecord;
|
||||
import org.jeecg.common.vo.statistic.AlertSummaryVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -17,4 +19,6 @@ public interface ISurvAlertRecordService extends IService<SurvAlertRecord> {
|
|||
IPage<SurvAlertRecord> pages(IPage<SurvAlertRecord> page, SurvAlertRecord survAlertRecord);
|
||||
|
||||
IPage<SurvAlertRecord> pageByDevice(IPage<SurvAlertRecord> page, List<String> deviceList, String yearStr);
|
||||
|
||||
AlertSummaryVo getSummary(AlertSummaryDTO alertSummaryDTO);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,4 +37,6 @@ public interface ISurvDeviceDeployService extends IService<SurvDeviceDeploy> {
|
|||
SurvDeviceDeploy getOrientDeviceByStation(String stationCode);
|
||||
|
||||
SurvDeviceDeploy getDeviceById(String deployId,String tenantId);
|
||||
|
||||
SurvDeviceDeploy getDeployZhibiao(String deployId, String tenantId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,34 @@
|
|||
package org.jeecg.modules.appmana.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.beanutils.BeanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.config.TenantContext;
|
||||
import org.jeecg.common.constant.CommonConstants;
|
||||
import org.jeecg.common.constant.DeviceReadConstants;
|
||||
import org.jeecg.common.constant.PollutionConstants;
|
||||
import org.jeecg.common.constant.enums.PollutionEnum;
|
||||
import org.jeecg.common.dto.CommonDTO;
|
||||
import org.jeecg.common.entity.*;
|
||||
import org.jeecg.common.vo.VOHisResult;
|
||||
import org.jeecg.common.vo.statistic.AlertReport;
|
||||
import org.jeecg.common.vo.statistic.ScreenIndexSummaryDetailVo;
|
||||
import org.jeecg.modules.appmana.service.ISurvHisdataAirService;
|
||||
import org.jeecg.modules.appmana.service.ISurvHisdataLivestockwaterService;
|
||||
import org.jeecg.modules.appmana.service.ISurvHisdataOrientwaterService;
|
||||
import org.jeecg.modules.appmana.service.ISurvHisdataSoilService;
|
||||
import org.jeecg.modules.appmana.service.*;
|
||||
import org.jeecg.modules.appmana.utils.HttpServletRequestUtil;
|
||||
import org.jeecg.modules.appmana.utils.MonitoringDataRichTextBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
|
|
@ -37,6 +38,8 @@ public class CommonServiceImpl {
|
|||
@Autowired
|
||||
private ISurvHisdataSoilService hisdataSoilService;
|
||||
@Autowired
|
||||
private ISurvHisdataVocsService vocsService;
|
||||
@Autowired
|
||||
private ISurvHisdataOrientwaterService hisdataOrientwaterService;
|
||||
@Autowired
|
||||
private ISurvHisdataLivestockwaterService hisdataLivestockwaterService;
|
||||
|
|
@ -47,6 +50,11 @@ public class CommonServiceImpl {
|
|||
@Autowired
|
||||
@Lazy
|
||||
private ScEquZhibiaoServiceImpl zhibiaoService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private ISurvAlertRecordService alertRecordService;
|
||||
|
||||
/**
|
||||
* 获取监测设备的数据
|
||||
*/
|
||||
|
|
@ -248,4 +256,206 @@ public class CommonServiceImpl {
|
|||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造设备的数据报告
|
||||
*/
|
||||
public String buildDeviceReport(List<SurvDeviceDeploy> deploys,LocalDateTime startTime,LocalDateTime endTime){
|
||||
/**
|
||||
* 遍历设备类型,根据设备类型查询数据
|
||||
*/
|
||||
List<String> airList = new ArrayList<>();
|
||||
List<String> soilList = new ArrayList<>();
|
||||
List<String> waterList = new ArrayList<>();
|
||||
List<String> orientIdList = new ArrayList<>();
|
||||
List<String> liveIdList = new ArrayList<>();
|
||||
List<String> stinkIdList = new ArrayList<>();
|
||||
|
||||
List<String> totalList = new ArrayList<>();
|
||||
for (SurvDeviceDeploy survDeviceDeploy : deploys) {
|
||||
if (PollutionConstants.SOIL_SURV.equals(survDeviceDeploy.getDeployType())) {//土壤设备
|
||||
soilList.add(survDeviceDeploy.getId());
|
||||
totalList.add(survDeviceDeploy.getId());
|
||||
} else if (PollutionConstants.AIR_SURV.equals(survDeviceDeploy.getDeployType())) {//气象设备
|
||||
airList.add(survDeviceDeploy.getId());
|
||||
totalList.add(survDeviceDeploy.getId());
|
||||
} else if (PollutionConstants.WATER_QULITY.equals(survDeviceDeploy.getDeployType())) {//水质设备
|
||||
waterList.add(survDeviceDeploy.getId());
|
||||
totalList.add(survDeviceDeploy.getId());
|
||||
}else if (PollutionConstants.WATER_ORIENT.equals(survDeviceDeploy.getDeployType())) {//面源
|
||||
orientIdList.add(survDeviceDeploy.getId());
|
||||
totalList.add(survDeviceDeploy.getId());
|
||||
} else if (PollutionConstants.WATER_LIVE.equals(survDeviceDeploy.getDeployType())) {//畜禽
|
||||
liveIdList.add(survDeviceDeploy.getId());
|
||||
totalList.add(survDeviceDeploy.getId());
|
||||
} else if (PollutionConstants.STINK.equals(survDeviceDeploy.getDeployType())) {//恶臭
|
||||
stinkIdList.add(survDeviceDeploy.getId());
|
||||
totalList.add(survDeviceDeploy.getId());
|
||||
}
|
||||
}
|
||||
|
||||
Long dataCounts = 0L;
|
||||
//step2 根据设备类型查询数据
|
||||
if(!airList.isEmpty()){
|
||||
dataCounts = dataCounts + hisdataAirService.count(new LambdaUpdateWrapper<SurvHisdataAir>()
|
||||
.in(SurvHisdataAir::getDeployId, airList)
|
||||
.between(SurvHisdataAir::getDataDateTime, startTime, endTime)
|
||||
|
||||
);
|
||||
}
|
||||
if(!soilList.isEmpty()){
|
||||
dataCounts = dataCounts + hisdataSoilService.count(new LambdaUpdateWrapper<SurvHisdataSoil>()
|
||||
.in(SurvHisdataSoil::getDeployId, soilList)
|
||||
.between(SurvHisdataSoil::getDataDateTime, startTime, endTime)
|
||||
);
|
||||
}
|
||||
if(!waterList.isEmpty()){
|
||||
dataCounts = dataCounts + hisdataSoilService.count(new LambdaUpdateWrapper<SurvHisdataSoil>()
|
||||
.in(SurvHisdataSoil::getDeployId, waterList)
|
||||
.between(SurvHisdataSoil::getDataDateTime, startTime, endTime)
|
||||
);
|
||||
}
|
||||
if(!orientIdList.isEmpty()){
|
||||
dataCounts = dataCounts + hisdataOrientwaterService.count(new LambdaUpdateWrapper<SurvHisdataOrientwater>()
|
||||
.in(SurvHisdataOrientwater::getDeviceId, orientIdList)
|
||||
.between(SurvHisdataOrientwater::getDataDateTime, startTime, endTime)
|
||||
);
|
||||
}
|
||||
if(!liveIdList.isEmpty()){
|
||||
dataCounts = dataCounts + hisdataLivestockwaterService.count(new LambdaUpdateWrapper<SurvHisdataLivestockwater>()
|
||||
.in(SurvHisdataLivestockwater::getDeviceId, liveIdList)
|
||||
.between(SurvHisdataLivestockwater::getDataDateTime, startTime, endTime)
|
||||
);
|
||||
}
|
||||
if(!stinkIdList.isEmpty()){
|
||||
dataCounts = dataCounts + vocsService.count(new LambdaUpdateWrapper<SurvHisdataVocs>()
|
||||
.in(SurvHisdataVocs::getDeployId, stinkIdList)
|
||||
.between(SurvHisdataVocs::getDataDateTime, startTime, endTime)
|
||||
);
|
||||
}
|
||||
|
||||
List<ScEquZhibiao> zhibiaoList = zhibiaoService.getAllChemical(totalList);
|
||||
Map<String,String> zhibiaoMap = new HashMap<>();
|
||||
if(!zhibiaoList.isEmpty()){
|
||||
for (ScEquZhibiao scEquZhibiao : zhibiaoList) {
|
||||
zhibiaoMap.put(scEquZhibiao.getEntityField(),scEquZhibiao.getName());
|
||||
}
|
||||
}
|
||||
|
||||
//异常数据
|
||||
Integer abnormalCount = 0;
|
||||
|
||||
List<SurvAlertRecord> alertRecordList = alertRecordService.lambdaQuery()
|
||||
.between(SurvAlertRecord::getAlertTime, startTime, endTime)
|
||||
.list();
|
||||
Map<String, AlertReport> alertHighMap = new HashMap<>();
|
||||
Map<String, AlertReport> alertLowMap = new HashMap<>();
|
||||
List<String> unnormalList = new ArrayList<>();
|
||||
if(!alertRecordList.isEmpty()){
|
||||
abnormalCount = alertRecordList.size();
|
||||
|
||||
for (SurvAlertRecord survAlertRecord : alertRecordList) {
|
||||
unnormalList.add(survAlertRecord.getItemCode());
|
||||
|
||||
if(DeviceReadConstants.READ_TOO_LOW.equals(survAlertRecord.getReadStatus())){
|
||||
AlertReport alertReport = alertLowMap.get(survAlertRecord.getItemCode());
|
||||
|
||||
if(alertReport != null){
|
||||
BigDecimal extremeValue = new BigDecimal(survAlertRecord.getSurvValue());//当前值
|
||||
BigDecimal lastValue = new BigDecimal(alertReport.getExtremeValue());//上一个值
|
||||
//对比上一个值,如果比上一个小,就更新为当前值
|
||||
if(extremeValue.compareTo(lastValue) <= 0){
|
||||
alertReport.setExtremeValue(extremeValue.toPlainString());
|
||||
}
|
||||
}else{
|
||||
alertReport = new AlertReport();
|
||||
alertReport.setItemName(survAlertRecord.getItemName());
|
||||
alertReport.setItemUnit(survAlertRecord.getSurvUnit());
|
||||
alertReport.setExtremeValue(survAlertRecord.getSurvValue());
|
||||
alertReport.setAlertCount(0);
|
||||
}
|
||||
alertReport.setAlertCount(alertReport.getAlertCount() + 1);
|
||||
alertLowMap.put(survAlertRecord.getItemCode(),alertReport);
|
||||
|
||||
}else if(DeviceReadConstants.READ_TOO_HIGH.equals(survAlertRecord.getReadStatus())){
|
||||
AlertReport alertHighReport = alertHighMap.get(survAlertRecord.getItemCode());
|
||||
|
||||
if(alertHighReport != null){
|
||||
BigDecimal extremeValue = new BigDecimal(survAlertRecord.getSurvValue());//当前值
|
||||
BigDecimal lastValue = new BigDecimal(alertHighReport.getExtremeValue());//上一个值
|
||||
//对比上一个值,如果比上一个大,就更新为当前值
|
||||
if(extremeValue.compareTo(lastValue) >= 0){
|
||||
alertHighReport.setExtremeValue(extremeValue.toPlainString());
|
||||
}
|
||||
}else{
|
||||
alertHighReport = new AlertReport();
|
||||
alertHighReport.setItemName(survAlertRecord.getItemName());
|
||||
alertHighReport.setItemUnit(survAlertRecord.getSurvUnit());
|
||||
alertHighReport.setExtremeValue(survAlertRecord.getSurvValue());
|
||||
alertHighReport.setAlertCount(0);
|
||||
}
|
||||
alertHighReport.setAlertCount(alertHighReport.getAlertCount() + 1);
|
||||
alertHighMap.put(survAlertRecord.getItemCode(),alertHighReport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MonitoringDataRichTextBuilder.MonitoringStats stats = new MonitoringDataRichTextBuilder.MonitoringStats();
|
||||
stats.setTotalSamples(dataCounts.intValue());
|
||||
stats.setIndicatorsCount(zhibiaoMap.size());
|
||||
BigDecimal total = new BigDecimal(dataCounts);
|
||||
BigDecimal abnormal = new BigDecimal(abnormalCount);
|
||||
|
||||
stats.setAbnormalRate(abnormal.divide(total, 3,RoundingMode.HALF_UP).doubleValue() * 100);
|
||||
|
||||
|
||||
// 超上限
|
||||
List<MonitoringDataRichTextBuilder.AbnormalItem> aboveList = new ArrayList<>();
|
||||
|
||||
if(!alertHighMap.isEmpty()){
|
||||
for (String s : alertHighMap.keySet()) {
|
||||
AlertReport alertReport = alertHighMap.get(s);
|
||||
|
||||
MonitoringDataRichTextBuilder.AbnormalItem tempItem = new MonitoringDataRichTextBuilder.AbnormalItem();
|
||||
tempItem.setIndicatorName(alertReport.getItemName());
|
||||
tempItem.setCount(alertReport.getAlertCount());
|
||||
tempItem.setExtremeValue("最高 " + alertReport.getExtremeValue());
|
||||
aboveList.add(tempItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stats.setAboveUpperLimit(aboveList);
|
||||
|
||||
// 低于下限
|
||||
List<MonitoringDataRichTextBuilder.AbnormalItem> belowList = new ArrayList<>();
|
||||
if(!alertLowMap.isEmpty()){
|
||||
for (String s : alertLowMap.keySet()) {
|
||||
AlertReport alertReport = alertLowMap.get(s);
|
||||
|
||||
MonitoringDataRichTextBuilder.AbnormalItem tempItem = new MonitoringDataRichTextBuilder.AbnormalItem();
|
||||
tempItem.setIndicatorName(alertReport.getItemName());
|
||||
tempItem.setCount(alertReport.getAlertCount());
|
||||
tempItem.setExtremeValue("最低 " + alertReport.getExtremeValue());
|
||||
belowList.add(tempItem);
|
||||
}
|
||||
}
|
||||
stats.setBelowLowerLimit(belowList);
|
||||
|
||||
|
||||
// 正常指标
|
||||
List<String> allItems = new ArrayList<>(zhibiaoMap.keySet());
|
||||
allItems.removeAll(unnormalList);
|
||||
List<String> normalItems = new ArrayList<>();
|
||||
if(!allItems.isEmpty()){
|
||||
for (String allItem : allItems) {
|
||||
String zhibiao = zhibiaoMap.get(allItem);
|
||||
normalItems.add(zhibiao);
|
||||
}
|
||||
}
|
||||
stats.setNormalIndicators(normalItems);
|
||||
|
||||
return MonitoringDataRichTextBuilder.buildRichText(stats);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,36 @@
|
|||
package org.jeecg.modules.appmana.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.constant.IotConstants;
|
||||
import org.jeecg.common.constant.enums.PollutionEnum;
|
||||
import org.jeecg.common.dto.AlertSummaryDTO;
|
||||
import org.jeecg.common.entity.ScEquZhibiao;
|
||||
import org.jeecg.common.entity.SurvAlertRecord;
|
||||
import org.jeecg.common.entity.SurvDeviceDeploy;
|
||||
import org.jeecg.common.util.DateRangeUtil;
|
||||
import org.jeecg.common.util.TimeIntervalUtils;
|
||||
import org.jeecg.common.vo.iot.common.SurvItemInfo;
|
||||
import org.jeecg.common.vo.statistic.AlertSummaryVo;
|
||||
import org.jeecg.common.vo.statistic.AlertSummayDetail;
|
||||
import org.jeecg.common.vo.statistic.CommonDateListResult;
|
||||
import org.jeecg.modules.appmana.mapper.SurvAlertRecordMapper;
|
||||
import org.jeecg.modules.appmana.service.ISurvAlertRecordService;
|
||||
import org.jeecg.modules.appmana.service.ISurvDeviceDeployService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Description: surv_alert_record
|
||||
|
|
@ -16,8 +39,13 @@ import java.util.List;
|
|||
* @Version: V1.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class SurvAlertRecordServiceImpl extends ServiceImpl<SurvAlertRecordMapper, SurvAlertRecord> implements ISurvAlertRecordService {
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private ISurvDeviceDeployService deployService;
|
||||
|
||||
@Override
|
||||
public IPage<SurvAlertRecord> pages(IPage<SurvAlertRecord> page, SurvAlertRecord survAlertRecord) {
|
||||
return baseMapper.pages(page,survAlertRecord);
|
||||
|
|
@ -27,4 +55,130 @@ public class SurvAlertRecordServiceImpl extends ServiceImpl<SurvAlertRecordMappe
|
|||
public IPage<SurvAlertRecord> pageByDevice(IPage<SurvAlertRecord> page, List<String> deviceList, String yearStr) {
|
||||
return baseMapper.pageByDevice(page,deviceList,yearStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertSummaryVo getSummary(AlertSummaryDTO alertSummaryDTO) {
|
||||
Assert.notNull(alertSummaryDTO,"传入格式错误");
|
||||
String tenantId = alertSummaryDTO.getTenantId();
|
||||
SurvDeviceDeploy deploy = deployService.getDeployZhibiao(alertSummaryDTO.getDeployId(),tenantId);
|
||||
Assert.notNull(deploy,"设备无效");
|
||||
AlertSummaryVo alertSummaryVo = new AlertSummaryVo();
|
||||
List<SurvItemInfo> survItemInfos = new ArrayList<>();
|
||||
// step 1 所有监测项字典信息
|
||||
if(deploy.getZhibiaos()!=null && !deploy.getZhibiaos().isEmpty()){
|
||||
for (ScEquZhibiao zhibiao : deploy.getZhibiaos()) {
|
||||
SurvItemInfo survItemInfo = new SurvItemInfo();
|
||||
PollutionEnum pollutionEnum = PollutionEnum.catchPollution(zhibiao.getEntityField());
|
||||
survItemInfo.setItemName(zhibiao.getName());
|
||||
survItemInfo.setColor(pollutionEnum.getColor());
|
||||
survItemInfo.setHighVal(zhibiao.getValHeight()!=null ?zhibiao.getValHeight()+"":null);
|
||||
survItemInfo.setLowVal(zhibiao.getValLow()!=null?zhibiao.getValLow()+"":null);
|
||||
survItemInfo.setUnit(zhibiao.getNuit());
|
||||
survItemInfo.setEntity(zhibiao.getEntityField());
|
||||
survItemInfo.setPid(zhibiao.getEleKey());
|
||||
survItemInfos.add(survItemInfo);
|
||||
}
|
||||
}
|
||||
alertSummaryVo.setItemList(survItemInfos);
|
||||
Map<String, SurvItemInfo> itemMap = survItemInfos.stream()
|
||||
.collect(Collectors.toMap(SurvItemInfo::getEntity, itemss -> itemss));
|
||||
alertSummaryVo.setItemInfo(itemMap);
|
||||
|
||||
//step 2:获取每5分钟 的数据
|
||||
|
||||
|
||||
String startTime = alertSummaryDTO.getStartTime();
|
||||
|
||||
|
||||
|
||||
LocalDateTime startDateTime = null;
|
||||
LocalDateTime endDateTime = null;
|
||||
boolean isToday = false;
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
LocalDate nowDate = nowTime.toLocalDate();
|
||||
if(StringUtils.isNotBlank(startTime)){
|
||||
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
if(IotConstants.day_hours.equals(alertSummaryDTO.getSummaryMode())){
|
||||
|
||||
startDateTime = LocalDateTime.of(LocalDate.parse(startTime,dtf), LocalTime.MIN);
|
||||
endDateTime = LocalDateTime.of(LocalDate.parse(startTime,dtf), LocalTime.MAX).withNano(999999000);
|
||||
//检查是否传入的今天
|
||||
if(nowDate.equals(startDateTime.toLocalDate())){
|
||||
isToday = true;
|
||||
}
|
||||
}
|
||||
else if(IotConstants.month_days.equals(alertSummaryDTO.getSummaryMode())){
|
||||
startDateTime = LocalDateTime.of(LocalDate.parse(startTime + "-01",dtf), LocalTime.MIN);
|
||||
endDateTime = LocalDateTime.of(startDateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth()), LocalTime.MAX).withNano(999999000);
|
||||
//检查是否传入的今天
|
||||
if(nowDate.equals(startDateTime.toLocalDate())){
|
||||
isToday = true;
|
||||
}
|
||||
}
|
||||
else if(IotConstants.year_months.equals(alertSummaryDTO.getSummaryMode())){
|
||||
startDateTime = LocalDateTime.of(LocalDate.parse(startTime+"-01-01",dtf), LocalTime.MIN);
|
||||
endDateTime = LocalDateTime.of(LocalDate.parse(startTime+"-12-31",dtf), LocalTime.MAX).withNano(999999000);
|
||||
//检查是否传入的今天
|
||||
if(nowDate.equals(startDateTime.toLocalDate())){
|
||||
isToday = true;
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
isToday = true;
|
||||
}
|
||||
|
||||
if(isToday){//如果查询的是今天,只查询到当前时间
|
||||
if(IotConstants.day_hours.equals(alertSummaryDTO.getSummaryMode())){
|
||||
startDateTime = nowTime.minusDays(1);
|
||||
endDateTime = nowTime.withNano(999999000);
|
||||
}
|
||||
else if(IotConstants.month_days.equals(alertSummaryDTO.getSummaryMode())){
|
||||
startDateTime = LocalDateTime.of(nowDate.getYear(),nowDate.getMonthValue(),1,0,0,0,999999000);
|
||||
endDateTime = LocalDateTime.of(nowDate.getYear(),nowDate.getMonthValue(),nowDate.getDayOfMonth(),23,59,59,0);
|
||||
}
|
||||
else if(IotConstants.year_months.equals(alertSummaryDTO.getSummaryMode())){
|
||||
startDateTime = LocalDateTime.of(nowDate.getYear(),1,1,0,0,0,999999000);
|
||||
endDateTime = LocalDateTime.of(nowDate.getYear(),12,31,23,59,59,0);
|
||||
}
|
||||
}
|
||||
List<String> showTime = new ArrayList<>();
|
||||
|
||||
|
||||
Map<String,List<String>> dataMap = new HashMap<>();
|
||||
if(!survItemInfos.isEmpty()){
|
||||
for (SurvItemInfo survItemInfo : survItemInfos) {
|
||||
List<AlertSummayDetail> records = new ArrayList<>();
|
||||
if(IotConstants.day_hours.equals(alertSummaryDTO.getSummaryMode())){
|
||||
CommonDateListResult commonDateListResult = TimeIntervalUtils.generate5MinuteIntervals(startDateTime,endDateTime);
|
||||
showTime = commonDateListResult.getShowList();
|
||||
records = baseMapper.getSpotCheckData(alertSummaryDTO.getDeployId(),survItemInfo.getEntity(),commonDateListResult.getQueryList(),startDateTime,endDateTime);
|
||||
}
|
||||
else if(IotConstants.month_days.equals(alertSummaryDTO.getSummaryMode())){
|
||||
List<String> dateList = DateRangeUtil.getDateListBetween(startDateTime,endDateTime);
|
||||
showTime = DateRangeUtil.convertDateFormatStream(dateList,"yyyy-MM-dd","MM月dd日");
|
||||
records = baseMapper.getDailyMaxSpotCheckData(dateList,startDateTime,endDateTime,alertSummaryDTO.getDeployId(),survItemInfo.getEntity());
|
||||
}
|
||||
else if(IotConstants.year_months.equals(alertSummaryDTO.getSummaryMode())){
|
||||
List<String> dateList = DateRangeUtil.getMonthListBetween(startDateTime,endDateTime);
|
||||
|
||||
records = baseMapper.getMonthMaxSpotCheckData(dateList,startDateTime,endDateTime,alertSummaryDTO.getDeployId(),survItemInfo.getEntity());
|
||||
List<String> monthList = new ArrayList<>();
|
||||
dateList.forEach(date -> {
|
||||
date = date+"-01";
|
||||
monthList.add(date);
|
||||
});
|
||||
showTime = DateRangeUtil.convertDateFormatStream(monthList,"yyyy-MM-dd","MM月");
|
||||
}
|
||||
//组装map
|
||||
if(!records.isEmpty()){
|
||||
List<String> dataList = records.stream().map(AlertSummayDetail::getSurvValue).collect(Collectors.toList());
|
||||
dataMap.put(survItemInfo.getEntity(),dataList);
|
||||
}
|
||||
}
|
||||
}
|
||||
alertSummaryVo.setTimeList(showTime);
|
||||
alertSummaryVo.setDataMap(dataMap);
|
||||
return alertSummaryVo;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -631,4 +631,9 @@ public class SurvDeviceDeployServiceImpl extends ServiceImpl<SurvDeviceDeployMap
|
|||
public SurvDeviceDeploy getDeviceById(String deployId, String tenantId) {
|
||||
return baseMapper.getDeviceById(deployId,tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurvDeviceDeploy getDeployZhibiao(String deployId, String tenantId) {
|
||||
return baseMapper.getDeployZhibiao(deployId,tenantId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,196 @@
|
|||
package org.jeecg.modules.appmana.utils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MonitoringDataRichTextBuilder {
|
||||
|
||||
/**
|
||||
* 监测数据统计信息
|
||||
*/
|
||||
public static class MonitoringStats {
|
||||
/**
|
||||
* 总样本数
|
||||
*/
|
||||
private int totalSamples;
|
||||
/**
|
||||
* 指标总数
|
||||
*/
|
||||
private int indicatorsCount;
|
||||
/**
|
||||
* 异常指标占比
|
||||
*/
|
||||
private double abnormalRate;
|
||||
|
||||
private List<AbnormalItem> aboveUpperLimit;
|
||||
private List<AbnormalItem> belowLowerLimit;
|
||||
private List<String> normalIndicators;
|
||||
|
||||
// getter/setter
|
||||
public int getTotalSamples() { return totalSamples; }
|
||||
public void setTotalSamples(int totalSamples) { this.totalSamples = totalSamples; }
|
||||
public int getIndicatorsCount() { return indicatorsCount; }
|
||||
public void setIndicatorsCount(int indicatorsCount) { this.indicatorsCount = indicatorsCount; }
|
||||
public double getAbnormalRate() { return abnormalRate; }
|
||||
public void setAbnormalRate(double abnormalRate) { this.abnormalRate = abnormalRate; }
|
||||
public List<AbnormalItem> getAboveUpperLimit() { return aboveUpperLimit; }
|
||||
public void setAboveUpperLimit(List<AbnormalItem> aboveUpperLimit) { this.aboveUpperLimit = aboveUpperLimit; }
|
||||
public List<AbnormalItem> getBelowLowerLimit() { return belowLowerLimit; }
|
||||
public void setBelowLowerLimit(List<AbnormalItem> belowLowerLimit) { this.belowLowerLimit = belowLowerLimit; }
|
||||
public List<String> getNormalIndicators() { return normalIndicators; }
|
||||
public void setNormalIndicators(List<String> normalIndicators) { this.normalIndicators = normalIndicators; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常项
|
||||
*/
|
||||
public static class AbnormalItem {
|
||||
/**
|
||||
* 异常指标名称
|
||||
*/
|
||||
private String indicatorName;
|
||||
/**
|
||||
* 异常指标数量
|
||||
*/
|
||||
private int count;
|
||||
/**
|
||||
* 异常指标异常值
|
||||
*/
|
||||
private String extremeValue;
|
||||
|
||||
public String getIndicatorName() { return indicatorName; }
|
||||
public void setIndicatorName(String indicatorName) { this.indicatorName = indicatorName; }
|
||||
public int getCount() { return count; }
|
||||
public void setCount(int count) { this.count = count; }
|
||||
public String getExtremeValue() { return extremeValue; }
|
||||
public void setExtremeValue(String extremeValue) { this.extremeValue = extremeValue; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成富文本HTML内容(无Emoji,使用通用符号)
|
||||
*/
|
||||
public static String buildRichText(MonitoringStats stats) {
|
||||
StringBuilder html = new StringBuilder();
|
||||
|
||||
// 1. 标题 - 监测数据概况
|
||||
html.append("<div style='font-size:18px;font-weight:bold;color:#333;margin-bottom:12px;'>")
|
||||
.append("【监测数据概况】")
|
||||
.append("</div>");
|
||||
|
||||
// 2. 摘要统计信息
|
||||
html.append("<div style='background:#f5f7fa;padding:10px 14px;border-radius:6px;margin-bottom:14px;'>")
|
||||
.append("<span style='margin-right:20px;'>共采集 <strong style='color:#1890ff;'>")
|
||||
.append(stats.totalSamples)
|
||||
.append("</strong> 次</span>")
|
||||
.append("<span style='margin-right:20px;'>覆盖 <strong style='color:#1890ff;'>")
|
||||
.append(stats.indicatorsCount)
|
||||
.append("</strong> 项指标</span>")
|
||||
.append("<span>异常率 <strong style='color:")
|
||||
.append(stats.abnormalRate > 5 ? "#f5222d" : "#faad14")
|
||||
.append(";'>")
|
||||
.append(String.format("%.1f", stats.abnormalRate))
|
||||
.append("%</strong></span>")
|
||||
.append("</div>");
|
||||
|
||||
// 3. 超上限部分(使用 [↑] 符号)
|
||||
if (stats.aboveUpperLimit != null && !stats.aboveUpperLimit.isEmpty()) {
|
||||
html.append("<div style='margin-bottom:8px;'>")
|
||||
.append("<span style='font-weight:bold;color:#cf1322;'>[↑] 超上限:</span>")
|
||||
.append("<span style='font-size:14px;'>");
|
||||
|
||||
List<String> items = new ArrayList<>();
|
||||
for (AbnormalItem item : stats.aboveUpperLimit) {
|
||||
String text = item.getIndicatorName() + ":<span style='color:#cf1322;font-weight:bold;'>"
|
||||
+ item.getCount() + " 次</span>";
|
||||
if (item.getExtremeValue() != null && !item.getExtremeValue().isEmpty()) {
|
||||
text += "(" + item.getExtremeValue() + ")";
|
||||
}
|
||||
items.add(text);
|
||||
}
|
||||
html.append(String.join(" | ", items));
|
||||
html.append("</span></div>");
|
||||
}
|
||||
|
||||
// 4. 低于下限部分(使用 [↓] 符号)
|
||||
if (stats.belowLowerLimit != null && !stats.belowLowerLimit.isEmpty()) {
|
||||
html.append("<div style='margin-bottom:8px;'>")
|
||||
.append("<span style='font-weight:bold;color:#389e0d;'>[↓] 低于下限:</span>")
|
||||
.append("<span style='font-size:14px;'>");
|
||||
|
||||
List<String> items = new ArrayList<>();
|
||||
for (AbnormalItem item : stats.belowLowerLimit) {
|
||||
String text = item.getIndicatorName() + ":<span style='color:#389e0d;font-weight:bold;'>"
|
||||
+ item.getCount() + " 次</span>";
|
||||
if (item.getExtremeValue() != null && !item.getExtremeValue().isEmpty()) {
|
||||
text += "(" + item.getExtremeValue() + ")";
|
||||
}
|
||||
items.add(text);
|
||||
}
|
||||
html.append(String.join(" | ", items));
|
||||
html.append("</span></div>");
|
||||
}
|
||||
|
||||
// 5. 正常指标(使用 [√] 符号)
|
||||
if (stats.normalIndicators != null && !stats.normalIndicators.isEmpty()) {
|
||||
html.append("<div style='margin-top:8px;padding-top:8px;border-top:1px dashed #e8e8e8;'>")
|
||||
.append("<span style='font-weight:bold;color:#52c41a;'>[√] 正常指标:</span>")
|
||||
.append("<span style='font-size:14px;color:#595959;'>")
|
||||
.append(String.join("、", stats.normalIndicators))
|
||||
.append("</span>")
|
||||
.append("</div>");
|
||||
}
|
||||
|
||||
return html.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从原始数据构建(示例)
|
||||
*/
|
||||
public static String buildFromRawText() {
|
||||
MonitoringStats stats = new MonitoringStats();
|
||||
stats.setTotalSamples(1284);
|
||||
stats.setIndicatorsCount(6);
|
||||
stats.setAbnormalRate(3.2);
|
||||
|
||||
// 超上限
|
||||
List<AbnormalItem> aboveList = new ArrayList<>();
|
||||
AbnormalItem tempItem = new AbnormalItem();
|
||||
tempItem.setIndicatorName("温度");
|
||||
tempItem.setCount(23);
|
||||
tempItem.setExtremeValue("最高 42.6℃");
|
||||
aboveList.add(tempItem);
|
||||
|
||||
AbnormalItem pressureItem = new AbnormalItem();
|
||||
pressureItem.setIndicatorName("气压");
|
||||
pressureItem.setCount(5);
|
||||
pressureItem.setExtremeValue(null);
|
||||
aboveList.add(pressureItem);
|
||||
stats.setAboveUpperLimit(aboveList);
|
||||
|
||||
// 低于下限
|
||||
List<AbnormalItem> belowList = new ArrayList<>();
|
||||
AbnormalItem humidityItem = new AbnormalItem();
|
||||
humidityItem.setIndicatorName("湿度");
|
||||
humidityItem.setCount(8);
|
||||
humidityItem.setExtremeValue("最低 18.3%");
|
||||
belowList.add(humidityItem);
|
||||
stats.setBelowLowerLimit(belowList);
|
||||
|
||||
// 正常指标
|
||||
List<String> normalList = new ArrayList<>();
|
||||
normalList.add("PM2.5");
|
||||
normalList.add("CO₂");
|
||||
normalList.add("噪声");
|
||||
stats.setNormalIndicators(normalList);
|
||||
|
||||
return buildRichText(stats);
|
||||
}
|
||||
|
||||
// ========== 主方法测试 ==========
|
||||
public static void main(String[] args) {
|
||||
String richText = buildFromRawText();
|
||||
System.out.println("生成的富文本HTML内容:");
|
||||
System.out.println("================================");
|
||||
System.out.println(richText);
|
||||
System.out.println("================================");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package org.jeecg.common.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AlertSummaryDTO {
|
||||
@ApiModelProperty("设备ID")
|
||||
private String deployId;
|
||||
|
||||
@ApiModelProperty("统计模式")
|
||||
private String summaryMode;
|
||||
|
||||
@ApiModelProperty("开始时间")
|
||||
private String startTime;
|
||||
|
||||
@ApiModelProperty("结束时间")
|
||||
private String endTime;
|
||||
|
||||
@ApiModelProperty("租户ID")
|
||||
private String tenantId;
|
||||
}
|
||||
|
|
@ -0,0 +1,549 @@
|
|||
package org.jeecg.common.util;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.YearMonth;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 日期范围工具类 - 获取两个日期之间的所有日期和月份
|
||||
*/
|
||||
public class DateRangeUtil {
|
||||
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");
|
||||
|
||||
// ==================== 日期相关方法 ====================
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(包含开始和结束日期)
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return 日期字符串列表,格式 yyyy-MM-dd,正序排列
|
||||
*/
|
||||
public static List<String> getDateListBetween(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
LocalDate startDate = start.toLocalDate();
|
||||
LocalDate endDate = end.toLocalDate();
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (startDate.isAfter(endDate)) {
|
||||
LocalDate temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
return getDateListBetween(startDate, endDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(包含开始和结束日期)
|
||||
* @param start 开始日期
|
||||
* @param end 结束日期
|
||||
* @return 日期字符串列表,格式 yyyy-MM-dd,正序排列
|
||||
*/
|
||||
public static List<String> getDateListBetween(LocalDate start, LocalDate end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (start.isAfter(end)) {
|
||||
LocalDate temp = start;
|
||||
start = end;
|
||||
end = temp;
|
||||
}
|
||||
|
||||
List<String> dateList = new ArrayList<>();
|
||||
LocalDate current = start;
|
||||
|
||||
while (!current.isAfter(end)) {
|
||||
dateList.add(current.format(DATE_FORMATTER));
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
|
||||
return dateList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(包含开始和结束日期)
|
||||
* 使用 Stream 流式处理
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return 日期字符串列表,格式 yyyy-MM-dd,正序排列
|
||||
*/
|
||||
public static List<String> getDateListBetweenStream(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
LocalDate startDate = start.toLocalDate();
|
||||
LocalDate endDate = end.toLocalDate();
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (startDate.isAfter(endDate)) {
|
||||
LocalDate temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
return Stream.iterate(startDate, date -> date.plusDays(1))
|
||||
.limit(startDate.until(endDate).getDays() + 1)
|
||||
.map(date -> date.format(DATE_FORMATTER))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(不包含结束日期)
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间(不包含)
|
||||
* @return 日期字符串列表,格式 yyyy-MM-dd,正序排列
|
||||
*/
|
||||
public static List<String> getDateListBetweenExclusiveEnd(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
LocalDate startDate = start.toLocalDate();
|
||||
LocalDate endDate = end.toLocalDate();
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (startDate.isAfter(endDate)) {
|
||||
LocalDate temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
List<String> dateList = new ArrayList<>();
|
||||
LocalDate current = startDate;
|
||||
|
||||
while (current.isBefore(endDate)) {
|
||||
dateList.add(current.format(DATE_FORMATTER));
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
|
||||
return dateList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(不包含开始日期)
|
||||
* @param start 开始时间(不包含)
|
||||
* @param end 结束时间
|
||||
* @return 日期字符串列表,格式 yyyy-MM-dd,正序排列
|
||||
*/
|
||||
public static List<String> getDateListBetweenExclusiveStart(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
LocalDate startDate = start.toLocalDate();
|
||||
LocalDate endDate = end.toLocalDate();
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (startDate.isAfter(endDate)) {
|
||||
LocalDate temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
List<String> dateList = new ArrayList<>();
|
||||
LocalDate current = startDate.plusDays(1);
|
||||
|
||||
while (!current.isAfter(endDate)) {
|
||||
dateList.add(current.format(DATE_FORMATTER));
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
|
||||
return dateList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(包含开始和结束日期),返回 LocalDate 对象列表
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return LocalDate 列表,正序排列
|
||||
*/
|
||||
public static List<LocalDate> getLocalDateListBetween(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
LocalDate startDate = start.toLocalDate();
|
||||
LocalDate endDate = end.toLocalDate();
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (startDate.isAfter(endDate)) {
|
||||
LocalDate temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
List<LocalDate> dateList = new ArrayList<>();
|
||||
LocalDate current = startDate;
|
||||
|
||||
while (!current.isAfter(endDate)) {
|
||||
dateList.add(current);
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
|
||||
return dateList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有日期(包含开始和结束日期)
|
||||
* 使用自定义日期格式
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @param pattern 日期格式,如 "yyyy/MM/dd"
|
||||
* @return 日期字符串列表,正序排列
|
||||
*/
|
||||
public static List<String> getDateListBetween(LocalDateTime start, LocalDateTime end, String pattern) {
|
||||
if (start == null || end == null || pattern == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
LocalDate startDate = start.toLocalDate();
|
||||
LocalDate endDate = end.toLocalDate();
|
||||
|
||||
// 如果开始日期在结束日期之后,交换位置
|
||||
if (startDate.isAfter(endDate)) {
|
||||
LocalDate temp = startDate;
|
||||
startDate = endDate;
|
||||
endDate = temp;
|
||||
}
|
||||
|
||||
List<String> dateList = new ArrayList<>();
|
||||
LocalDate current = startDate;
|
||||
|
||||
while (!current.isAfter(endDate)) {
|
||||
dateList.add(current.format(formatter));
|
||||
current = current.plusDays(1);
|
||||
}
|
||||
|
||||
return dateList;
|
||||
}
|
||||
|
||||
// ==================== 月份相关方法(新增) ====================
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有月份(包含开始和结束月份)
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return 月份字符串列表,格式 yyyy-MM,正序排列
|
||||
*/
|
||||
public static List<String> getMonthListBetween(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
YearMonth startMonth = YearMonth.from(start);
|
||||
YearMonth endMonth = YearMonth.from(end);
|
||||
|
||||
// 如果开始月份在结束月份之后,交换位置
|
||||
if (startMonth.isAfter(endMonth)) {
|
||||
YearMonth temp = startMonth;
|
||||
startMonth = endMonth;
|
||||
endMonth = temp;
|
||||
}
|
||||
|
||||
List<String> monthList = new ArrayList<>();
|
||||
YearMonth current = startMonth;
|
||||
|
||||
while (!current.isAfter(endMonth)) {
|
||||
monthList.add(current.format(MONTH_FORMATTER));
|
||||
current = current.plusMonths(1);
|
||||
}
|
||||
|
||||
return monthList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有月份(包含开始和结束月份)
|
||||
* 使用 Stream 流式处理
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return 月份字符串列表,格式 yyyy-MM,正序排列
|
||||
*/
|
||||
public static List<String> getMonthListBetweenStream(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
YearMonth startMonth = YearMonth.from(start);
|
||||
YearMonth endMonth = YearMonth.from(end);
|
||||
|
||||
// 如果开始月份在结束月份之后,交换位置
|
||||
if (startMonth.isAfter(endMonth)) {
|
||||
YearMonth temp = startMonth;
|
||||
startMonth = endMonth;
|
||||
endMonth = temp;
|
||||
}
|
||||
|
||||
long monthsBetween = startMonth.until(endMonth, java.time.temporal.ChronoUnit.MONTHS);
|
||||
|
||||
return Stream.iterate(startMonth, month -> month.plusMonths(1))
|
||||
.limit(monthsBetween + 1)
|
||||
.map(month -> month.format(MONTH_FORMATTER))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有月份(不包含结束月份)
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间(不包含)
|
||||
* @return 月份字符串列表,格式 yyyy-MM,正序排列
|
||||
*/
|
||||
public static List<String> getMonthListBetweenExclusiveEnd(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
YearMonth startMonth = YearMonth.from(start);
|
||||
YearMonth endMonth = YearMonth.from(end);
|
||||
|
||||
// 如果开始月份在结束月份之后,交换位置
|
||||
if (startMonth.isAfter(endMonth)) {
|
||||
YearMonth temp = startMonth;
|
||||
startMonth = endMonth;
|
||||
endMonth = temp;
|
||||
}
|
||||
|
||||
List<String> monthList = new ArrayList<>();
|
||||
YearMonth current = startMonth;
|
||||
|
||||
while (current.isBefore(endMonth)) {
|
||||
monthList.add(current.format(MONTH_FORMATTER));
|
||||
current = current.plusMonths(1);
|
||||
}
|
||||
|
||||
return monthList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有月份(不包含开始月份)
|
||||
* @param start 开始时间(不包含)
|
||||
* @param end 结束时间
|
||||
* @return 月份字符串列表,格式 yyyy-MM,正序排列
|
||||
*/
|
||||
public static List<String> getMonthListBetweenExclusiveStart(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
YearMonth startMonth = YearMonth.from(start);
|
||||
YearMonth endMonth = YearMonth.from(end);
|
||||
|
||||
// 如果开始月份在结束月份之后,交换位置
|
||||
if (startMonth.isAfter(endMonth)) {
|
||||
YearMonth temp = startMonth;
|
||||
startMonth = endMonth;
|
||||
endMonth = temp;
|
||||
}
|
||||
|
||||
List<String> monthList = new ArrayList<>();
|
||||
YearMonth current = startMonth.plusMonths(1);
|
||||
|
||||
while (!current.isAfter(endMonth)) {
|
||||
monthList.add(current.format(MONTH_FORMATTER));
|
||||
current = current.plusMonths(1);
|
||||
}
|
||||
|
||||
return monthList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有月份(包含开始和结束月份),返回 YearMonth 对象列表
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return YearMonth 列表,正序排列
|
||||
*/
|
||||
public static List<YearMonth> getYearMonthListBetween(LocalDateTime start, LocalDateTime end) {
|
||||
if (start == null || end == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
YearMonth startMonth = YearMonth.from(start);
|
||||
YearMonth endMonth = YearMonth.from(end);
|
||||
|
||||
// 如果开始月份在结束月份之后,交换位置
|
||||
if (startMonth.isAfter(endMonth)) {
|
||||
YearMonth temp = startMonth;
|
||||
startMonth = endMonth;
|
||||
endMonth = temp;
|
||||
}
|
||||
|
||||
List<YearMonth> monthList = new ArrayList<>();
|
||||
YearMonth current = startMonth;
|
||||
|
||||
while (!current.isAfter(endMonth)) {
|
||||
monthList.add(current);
|
||||
current = current.plusMonths(1);
|
||||
}
|
||||
|
||||
return monthList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期之间的所有月份(包含开始和结束月份)
|
||||
* 使用自定义月份格式
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @param pattern 月份格式,如 "yyyy年MM月"
|
||||
* @return 月份字符串列表,正序排列
|
||||
*/
|
||||
public static List<String> getMonthListBetween(LocalDateTime start, LocalDateTime end, String pattern) {
|
||||
if (start == null || end == null || pattern == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
YearMonth startMonth = YearMonth.from(start);
|
||||
YearMonth endMonth = YearMonth.from(end);
|
||||
|
||||
// 如果开始月份在结束月份之后,交换位置
|
||||
if (startMonth.isAfter(endMonth)) {
|
||||
YearMonth temp = startMonth;
|
||||
startMonth = endMonth;
|
||||
endMonth = temp;
|
||||
}
|
||||
|
||||
List<String> monthList = new ArrayList<>();
|
||||
YearMonth current = startMonth;
|
||||
|
||||
while (!current.isAfter(endMonth)) {
|
||||
monthList.add(current.format(formatter));
|
||||
current = current.plusMonths(1);
|
||||
}
|
||||
|
||||
return monthList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量转换日期字符串格式
|
||||
* @param dateList 日期字符串列表
|
||||
* @param sourcePattern 源日期格式,如 "yyyy-MM-dd"
|
||||
* @param targetPattern 目标日期格式,如 "yyyy/MM/dd"
|
||||
* @return 转换后的日期字符串列表,保持原有顺序
|
||||
*/
|
||||
public static List<String> convertDateFormat(List<String> dateList, String sourcePattern, String targetPattern) {
|
||||
if (dateList == null || dateList.isEmpty() || sourcePattern == null || targetPattern == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern(sourcePattern);
|
||||
DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern(targetPattern);
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String dateStr : dateList) {
|
||||
try {
|
||||
// 先解析为 LocalDate,再格式化为目标格式
|
||||
LocalDate date = LocalDate.parse(dateStr, sourceFormatter);
|
||||
result.add(date.format(targetFormatter));
|
||||
} catch (DateTimeParseException e) {
|
||||
// 如果解析失败,跳过该日期或保留原值
|
||||
// 这里选择保留原值并打印警告
|
||||
e.printStackTrace();
|
||||
System.err.println("日期格式转换失败: " + dateStr + ", 格式: " + sourcePattern);
|
||||
result.add(dateStr);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量转换日期字符串格式(使用 Stream 流式处理)
|
||||
* @param dateList 日期字符串列表
|
||||
* @param sourcePattern 源日期格式,如 "yyyy-MM-dd"
|
||||
* @param targetPattern 目标日期格式,如 "yyyy/MM/dd"
|
||||
* @return 转换后的日期字符串列表,保持原有顺序
|
||||
*/
|
||||
public static List<String> convertDateFormatStream(List<String> dateList, String sourcePattern, String targetPattern) {
|
||||
if (dateList == null || dateList.isEmpty() || sourcePattern == null || targetPattern == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern(sourcePattern);
|
||||
DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern(targetPattern);
|
||||
|
||||
return dateList.stream()
|
||||
.map(dateStr -> {
|
||||
try {
|
||||
LocalDate date = LocalDate.parse(dateStr, sourceFormatter);
|
||||
return date.format(targetFormatter);
|
||||
} catch (DateTimeParseException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("日期格式转换失败: " + dateStr + ", 格式: " + sourcePattern);
|
||||
return dateStr;
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==================== 使用示例 ====================
|
||||
public static void main(String[] args) {
|
||||
LocalDateTime start = LocalDateTime.of(2026, 1, 15, 10, 0, 0);
|
||||
LocalDateTime end = LocalDateTime.of(2026, 7, 20, 18, 30, 0);
|
||||
|
||||
System.out.println("========== 获取所有日期 ==========");
|
||||
System.out.println("开始时间: " + start);
|
||||
System.out.println("结束时间: " + end);
|
||||
|
||||
List<String> dateList = getDateListBetween(start, end);
|
||||
System.out.println("日期列表 (包含开始和结束):");
|
||||
System.out.println("共 " + dateList.size() + " 天");
|
||||
dateList.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 获取所有月份(新增功能) ==========");
|
||||
List<String> monthList = getMonthListBetween(start, end);
|
||||
System.out.println("月份列表 (包含开始和结束月份):");
|
||||
System.out.println("共 " + monthList.size() + " 个月");
|
||||
monthList.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 跨年月份测试 ==========");
|
||||
LocalDateTime crossYearStart = LocalDateTime.of(2026, 11, 15, 0, 0, 0);
|
||||
LocalDateTime crossYearEnd = LocalDateTime.of(2027, 3, 20, 0, 0, 0);
|
||||
List<String> crossYearMonths = getMonthListBetween(crossYearStart, crossYearEnd);
|
||||
System.out.println("跨年月份列表:");
|
||||
crossYearMonths.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 不包含结束月份 ==========");
|
||||
List<String> exclusiveEndMonths = getMonthListBetweenExclusiveEnd(start, end);
|
||||
System.out.println("月份列表 (不包含结束月份):");
|
||||
exclusiveEndMonths.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 不包含开始月份 ==========");
|
||||
List<String> exclusiveStartMonths = getMonthListBetweenExclusiveStart(start, end);
|
||||
System.out.println("月份列表 (不包含开始月份):");
|
||||
exclusiveStartMonths.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 使用 Stream 方式 ==========");
|
||||
List<String> streamMonths = getMonthListBetweenStream(start, end);
|
||||
streamMonths.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 返回 YearMonth 对象 ==========");
|
||||
List<YearMonth> yearMonthList = getYearMonthListBetween(start, end);
|
||||
yearMonthList.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 自定义月份格式 ==========");
|
||||
List<String> customFormatMonths = getMonthListBetween(start, end, "yyyy年MM月");
|
||||
customFormatMonths.forEach(System.out::println);
|
||||
|
||||
System.out.println("\n========== 开始日期大于结束日期(自动交换) ==========");
|
||||
LocalDateTime startLater = LocalDateTime.of(2026, 7, 20, 0, 0, 0);
|
||||
LocalDateTime endEarlier = LocalDateTime.of(2026, 1, 15, 0, 0, 0);
|
||||
List<String> swappedMonths = getMonthListBetween(startLater, endEarlier);
|
||||
System.out.println("自动交换后的月份列表:");
|
||||
swappedMonths.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
package org.jeecg.common.util;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
|
||||
/**
|
||||
* 日期时间工具类 - 用于获取本周、本月、本年的时间范围
|
||||
*/
|
||||
public class DateTimeRangeUtil {
|
||||
|
||||
/**
|
||||
* 获取本周的开始时间(周一 00:00:00)
|
||||
*/
|
||||
public static LocalDateTime getWeekStart() {
|
||||
LocalDate monday = LocalDate.now().with(DayOfWeek.MONDAY);
|
||||
return LocalDateTime.of(monday, LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本周的结束时间(周日 23:59:59)
|
||||
*/
|
||||
public static LocalDateTime getWeekEnd() {
|
||||
LocalDate sunday = LocalDate.now().with(DayOfWeek.SUNDAY);
|
||||
return LocalDateTime.of(sunday, LocalTime.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本月的开始时间(1号 00:00:00)
|
||||
*/
|
||||
public static LocalDateTime getMonthStart() {
|
||||
LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
|
||||
return LocalDateTime.of(firstDay, LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本月的结束时间(最后一天 23:59:59)
|
||||
*/
|
||||
public static LocalDateTime getMonthEnd() {
|
||||
LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
|
||||
return LocalDateTime.of(lastDay, LocalTime.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本年的开始时间(1月1日 00:00:00)
|
||||
*/
|
||||
public static LocalDateTime getYearStart() {
|
||||
LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfYear());
|
||||
return LocalDateTime.of(firstDay, LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本年的结束时间(12月31日 23:59:59)
|
||||
*/
|
||||
public static LocalDateTime getYearEnd() {
|
||||
LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfYear());
|
||||
return LocalDateTime.of(lastDay, LocalTime.MAX);
|
||||
}
|
||||
|
||||
// ==================== 指定日期时间的扩展方法 ====================
|
||||
|
||||
/**
|
||||
* 获取指定日期所在周的开始时间(周一 00:00:00)
|
||||
*/
|
||||
public static LocalDateTime getWeekStart(LocalDateTime dateTime) {
|
||||
LocalDate monday = dateTime.toLocalDate().with(DayOfWeek.MONDAY);
|
||||
return LocalDateTime.of(monday, LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期所在周的结束时间(周日 23:59:59)
|
||||
*/
|
||||
public static LocalDateTime getWeekEnd(LocalDateTime dateTime) {
|
||||
LocalDate sunday = dateTime.toLocalDate().with(DayOfWeek.SUNDAY);
|
||||
return LocalDateTime.of(sunday, LocalTime.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期所在月的开始时间(1号 00:00:00)
|
||||
*/
|
||||
public static LocalDateTime getMonthStart(LocalDateTime dateTime) {
|
||||
LocalDate firstDay = dateTime.toLocalDate().with(TemporalAdjusters.firstDayOfMonth());
|
||||
return LocalDateTime.of(firstDay, LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期所在月的结束时间(最后一天 23:59:59)
|
||||
*/
|
||||
public static LocalDateTime getMonthEnd(LocalDateTime dateTime) {
|
||||
LocalDate lastDay = dateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
|
||||
return LocalDateTime.of(lastDay, LocalTime.MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期所在年的开始时间(1月1日 00:00:00)
|
||||
*/
|
||||
public static LocalDateTime getYearStart(LocalDateTime dateTime) {
|
||||
LocalDate firstDay = dateTime.toLocalDate().with(TemporalAdjusters.firstDayOfYear());
|
||||
return LocalDateTime.of(firstDay, LocalTime.MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期所在年的结束时间(12月31日 23:59:59)
|
||||
*/
|
||||
public static LocalDateTime getYearEnd(LocalDateTime dateTime) {
|
||||
LocalDate lastDay = dateTime.toLocalDate().with(TemporalAdjusters.lastDayOfYear());
|
||||
return LocalDateTime.of(lastDay, LocalTime.MAX);
|
||||
}
|
||||
|
||||
// ==================== 使用示例 ====================
|
||||
public static void main(String[] args) {
|
||||
System.out.println("========== 当前时间范围 ==========");
|
||||
System.out.println("本周开始: " + getWeekStart());
|
||||
System.out.println("本周结束: " + getWeekEnd());
|
||||
System.out.println("本月开始: " + getMonthStart());
|
||||
System.out.println("本月结束: " + getMonthEnd());
|
||||
System.out.println("本年开始: " + getYearStart());
|
||||
System.out.println("本年结束: " + getYearEnd());
|
||||
|
||||
System.out.println("\n========== 指定时间范围 ==========");
|
||||
LocalDateTime customTime = LocalDateTime.of(2026, 7, 15, 14, 30, 0);
|
||||
System.out.println("指定时间: " + customTime);
|
||||
System.out.println("所在周开始: " + getWeekStart(customTime));
|
||||
System.out.println("所在周结束: " + getWeekEnd(customTime));
|
||||
System.out.println("所在月开始: " + getMonthStart(customTime));
|
||||
System.out.println("所在月结束: " + getMonthEnd(customTime));
|
||||
System.out.println("所在年开始: " + getYearStart(customTime));
|
||||
System.out.println("所在年结束: " + getYearEnd(customTime));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package org.jeecg.common.vo.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DataCenterDataSummary {
|
||||
|
||||
private String weekHtml;
|
||||
private String monthHtml;
|
||||
private String yearHtml;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package org.jeecg.common.vo.statistic;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AlertReport {
|
||||
/**
|
||||
* 异常项名称
|
||||
*/
|
||||
private String itemName;
|
||||
/**
|
||||
* 异常项单位
|
||||
*/
|
||||
private String itemUnit;
|
||||
/**
|
||||
* 极限值
|
||||
*/
|
||||
private String extremeValue;
|
||||
/**
|
||||
* 异常次数
|
||||
*/
|
||||
private Integer alertCount;
|
||||
}
|
||||
Loading…
Reference in New Issue