综合查询页面

This commit is contained in:
2025-09-05 13:45:39 +08:00
parent 15e230babb
commit aa37e2a881
23 changed files with 1300 additions and 7 deletions

View File

@ -0,0 +1,72 @@
package com.xzzn.web.controller.ems;
import com.xzzn.common.core.controller.BaseController;
import com.xzzn.common.core.domain.AjaxResult;
import com.xzzn.common.enums.DeviceCategory;
import com.xzzn.ems.domain.vo.*;
import com.xzzn.ems.service.IGeneralQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
*
* 综合查询
*
*/
@RestController
@RequestMapping("/ems/generalQuery")
public class EmsGeneralQueryController extends BaseController{
@Autowired
private IGeneralQueryService iGeneralQueryService;
/**
* 获取设备枚举
*/
@GetMapping("/getAllDeviceCategory")
public AjaxResult getDeviceCategory()
{
// 获取所有枚举的中文信息
List<String> deviceCategoryName = new ArrayList<>();
for (DeviceCategory category : DeviceCategory.values()) {
deviceCategoryName.add(category.getInfo());
}
return success(deviceCategoryName);
}
/**
* 点位模糊查询
*/
@PostMapping("/pointFuzzyQuery")
public AjaxResult pointFuzzyQuery(@RequestBody PointNameRequest request)
{
return success(iGeneralQueryService.getPointNameList(request));
}
/**
* 根据点位查询点位数据变化
*/
@PostMapping("/getPointValueList")
public AjaxResult getPointValueList(@RequestBody PointNameRequest request)
{
List<GeneralQueryResponse> result = new ArrayList<>();
try {
result = iGeneralQueryService.getPointValueList(request);
} catch (Exception e) {
return error("报错请重试!");
}
return success(result);
}
/**
* 获取设备枚举
*/
@GetMapping("/getAllBatteryIdsBySites/{siteIds}")
public AjaxResult getAllBatteryIdsBySites(@PathVariable String[] siteIds)
{
return success(iGeneralQueryService.getAllBatteryIdsBySites(siteIds));
}
}

View File

@ -1,5 +1,8 @@
package com.xzzn.common.enums;
import java.util.HashMap;
import java.util.Map;
/**
* device-设备类别
*
@ -13,7 +16,10 @@ public enum DeviceCategory
CLUSTER("CLUSTER", "电池簇"),
BATTERY("BATTERY", "单体电池"),
AMMETER("AMMETER", "电表"),
COOLING("COOLING", "液体");
COOLING("COOLING", ""),
DH("DH", "动环"),
XF("XF", "消防"),
BATTERY_GROUP("BATTERY_GROUP", "电池组");
private final String code;
private final String info;
@ -33,4 +39,19 @@ public enum DeviceCategory
{
return info;
}
// 缓存info与code的映射优化查询效率
private static final Map<String, String> INFO_CODE_MAP = new HashMap<>();
// 静态块初始化缓存
static {
for (DeviceCategory category : DeviceCategory.values()) {
INFO_CODE_MAP.put(category.info, category.code);
}
}
// 通过info获取code的方法
public static String getCodeByInfo(String info) {
return INFO_CODE_MAP.get(info); // 从缓存中直接获取,效率高
}
}

View File

@ -32,6 +32,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
public static String YYYYMMDD = "yyyyMMdd";
public static String YYYY_MM_DD_HH_MM_00 = "yyyy-MM-dd HH:mm:00";
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
@ -252,4 +254,39 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
return time.format(DateTimeFormatter.ofPattern("yyyy-MM"));
}
/**
* 增加 LocalDateTime ==> String
*/
public static String convertToString(LocalDateTime time) {
return time.format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
}
/**
* 将输入时间调整到下一分钟的整点秒数强制为00
* 例如2026-09-03 18:34:49 -> 2026-09-03 18:35:00
* @param timeStr 输入时间字符串支持yyyy-MM-dd HH:mm:ss格式
* @return 调整后的时间字符串yyyy-MM-dd HH:mm:00
* @throws ParseException 时间格式错误时抛出
*/
public static String adjustToNextMinute(String timeStr) throws ParseException {
// 1. 解析原始时间(使用包含秒数的格式)
SimpleDateFormat fullFormat = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);
Date originalDate = fullFormat.parse(timeStr);
// 2. 使用Calendar调整时间
Calendar cal = Calendar.getInstance();
cal.setTime(originalDate);
// 3. 如果当前秒数大于0自动进1分钟否则保持当前分钟
if (cal.get(Calendar.SECOND) > 0) {
cal.add(Calendar.MINUTE, 1); // 分钟+1
}
// 4. 强制设置秒数和毫秒为0
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
// 5. 格式化为目标字符串
return new SimpleDateFormat(YYYY_MM_DD_HH_MM_00).format(cal.getTime());
}
}

View File

@ -0,0 +1,117 @@
package com.xzzn.ems.domain;
import com.xzzn.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.xzzn.common.annotation.Excel;
/**
* 点位匹配对象 ems_point_match
*
* @author xzzn
* @date 2025-09-02
*/
public class EmsPointMatch extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 设备ID主键自增长 */
private Long id;
/** 点位名称 */
@Excel(name = "点位名称")
private String pointName;
/** 点位所在表 */
@Excel(name = "点位所在表")
private String matchTable;
/** 点位匹配字段 */
@Excel(name = "点位匹配字段")
private String matchField;
/** 站点id */
@Excel(name = "站点id")
private String siteId;
/** 设备类别例如“STACK/CLUSTER/PCS等” */
@Excel(name = "设备类别例如“STACK/CLUSTER/PCS等”")
private String deviceCategory;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setPointName(String pointName)
{
this.pointName = pointName;
}
public String getPointName()
{
return pointName;
}
public void setMatchTable(String matchTable)
{
this.matchTable = matchTable;
}
public String getMatchTable()
{
return matchTable;
}
public void setMatchField(String matchField)
{
this.matchField = matchField;
}
public String getMatchField()
{
return matchField;
}
public void setSiteId(String siteId)
{
this.siteId = siteId;
}
public String getSiteId()
{
return siteId;
}
public void setDeviceCategory(String deviceCategory)
{
this.deviceCategory = deviceCategory;
}
public String getDeviceCategory()
{
return deviceCategory;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("pointName", getPointName())
.append("matchTable", getMatchTable())
.append("matchField", getMatchField())
.append("siteId", getSiteId())
.append("deviceCategory", getDeviceCategory())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@ -0,0 +1,36 @@
package com.xzzn.ems.domain.vo;
import java.util.List;
/**
* 综合查询返回-设备数据list
*/
public class DevicePointDataList
{
// 设备id
private String deviceId;
// 该设备点位数据list
private List<GeneralQueryDataVo> pointValueList;
public DevicePointDataList(String deviceId, List<GeneralQueryDataVo> pointValueList) {
this.deviceId = deviceId;
this.pointValueList = pointValueList;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public List<GeneralQueryDataVo> getPointValueList() {
return pointValueList;
}
public void setPointValueList(List<GeneralQueryDataVo> pointValueList) {
this.pointValueList = pointValueList;
}
}

View File

@ -0,0 +1,47 @@
package com.xzzn.ems.domain.vo;
import java.math.BigDecimal;
/**
* 综合查询-数据库返回结果
*/
public class GeneralQueryDataVo {
// 站点
private String siteId;
private String deviceId;
private String valueDate;
private Object pointValue;
public String getSiteId() {
return siteId;
}
public void setSiteId(String siteId) {
this.siteId = siteId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getValueDate() {
return valueDate;
}
public void setValueDate(String valueDate) {
this.valueDate = valueDate;
}
public Object getPointValue() {
return pointValue;
}
public void setPointValue(Object pointValue) {
this.pointValue = pointValue;
}
}

View File

@ -0,0 +1,37 @@
package com.xzzn.ems.domain.vo;
import java.util.List;
/**
* 综合查询结果
*
*/
public class GeneralQueryResponse {
// 站点
private String siteId;
// 设备数据
private List<DevicePointDataList> deviceList;
public GeneralQueryResponse(String siteId, List<DevicePointDataList> deviceList) {
this.siteId = siteId;
this.deviceList = deviceList;
}
public String getSiteId() {
return siteId;
}
public void setSiteId(String siteId) {
this.siteId = siteId;
}
public List<DevicePointDataList> getDeviceList() {
return deviceList;
}
public void setDeviceList(List<DevicePointDataList> deviceList) {
this.deviceList = deviceList;
}
}

View File

@ -0,0 +1,49 @@
package com.xzzn.ems.domain.vo;
import java.time.LocalDateTime;
/**
* 每月时间范围实体
*/
public class MonthlyTimeRange {
// 站点ID
private String siteId;
// 月份YYYY-MM
private String month;
// 当月最早时间
private LocalDateTime firstDataTime;
// 当月最晚时间
private LocalDateTime lastDataTime;
public String getSiteId() {
return siteId;
}
public void setSiteId(String siteId) {
this.siteId = siteId;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public LocalDateTime getFirstDataTime() {
return firstDataTime;
}
public void setFirstDataTime(LocalDateTime firstDataTime) {
this.firstDataTime = firstDataTime;
}
public LocalDateTime getLastDataTime() {
return lastDataTime;
}
public void setLastDataTime(LocalDateTime lastDataTime) {
this.lastDataTime = lastDataTime;
}
}

View File

@ -0,0 +1,82 @@
package com.xzzn.ems.domain.vo;
import java.util.List;
import java.util.Map;
/**
* 点位模糊查询入参
*
*/
public class PointNameRequest {
private List<String> siteIds;
private String categoryName;
private String pointName;
/** 数据分组 1-分钟 2-小时 3-天 */
private int dataUnit;
private String startDate;
private String endDate;
private Map<String,List<String>> siteDeviceMap;
public List<String> getSiteIds() {
return siteIds;
}
public void setSiteIds(List<String> siteIds) {
this.siteIds = siteIds;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getPointName() {
return pointName;
}
public void setPointName(String pointName) {
this.pointName = pointName;
}
public int getDataUnit() {
return dataUnit;
}
public void setDataUnit(int dataUnit) {
this.dataUnit = dataUnit;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public Map<String, List<String>> getSiteDeviceMap() {
return siteDeviceMap;
}
public void setSiteDeviceMap(Map<String, List<String>> siteDeviceMap) {
this.siteDeviceMap = siteDeviceMap;
}
}

View File

@ -0,0 +1,27 @@
package com.xzzn.ems.domain.vo;
/**
* 综合查询-站点下单体电池实际数据
*
*/
public class SiteBatteryListVo {
/** 站点id */
private String siteId;
private String deviceId;
public String getSiteId() {
return siteId;
}
public void setSiteId(String siteId) {
this.siteId = siteId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
}

View File

@ -0,0 +1,33 @@
package com.xzzn.ems.domain.vo;
import java.time.LocalDateTime;
/**
* 时间点参数实体
*/
public class TimePointQuery {
private String siteId;
// 要查询的时间点
private LocalDateTime dataTime;
public TimePointQuery(String siteId, LocalDateTime dataTime) {
this.siteId = siteId;
this.dataTime = dataTime;
}
public String getSiteId() {
return siteId;
}
public void setSiteId(String siteId) {
this.siteId = siteId;
}
public LocalDateTime getDataTime() {
return dataTime;
}
public void setDataTime(LocalDateTime dataTime) {
this.dataTime = dataTime;
}
}

View File

@ -0,0 +1,48 @@
package com.xzzn.ems.domain.vo;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 时间点-总充放电数据
*/
public class TimePointValue {
private String siteId;
private LocalDateTime dataUpdateTime;
// 总充电量
private BigDecimal totalChargeData;
// 总放电量
private BigDecimal totalDischargeData;
public String getSiteId() {
return siteId;
}
public void setSiteId(String siteId) {
this.siteId = siteId;
}
public LocalDateTime getDataUpdateTime() {
return dataUpdateTime;
}
public void setDataUpdateTime(LocalDateTime dataUpdateTime) {
this.dataUpdateTime = dataUpdateTime;
}
public BigDecimal getTotalChargeData() {
return totalChargeData;
}
public void setTotalChargeData(BigDecimal totalChargeData) {
this.totalChargeData = totalChargeData;
}
public BigDecimal getTotalDischargeData() {
return totalDischargeData;
}
public void setTotalDischargeData(BigDecimal totalDischargeData) {
this.totalDischargeData = totalDischargeData;
}
}

View File

@ -4,6 +4,7 @@ import java.time.LocalDateTime;
import java.util.List;
import com.xzzn.ems.domain.EmsBatteryDataMonth;
import com.xzzn.ems.domain.vo.SiteBatteryListVo;
import org.apache.ibatis.annotations.Param;
/**
@ -69,4 +70,7 @@ public interface EmsBatteryDataMonthMapper
* 批量插入或更新月级数据(存在则更新,不存在则插入)
*/
void batchInsertOrUpdate(@Param("list") List<EmsBatteryDataMonth> monthDataList);
// 查找siteId下面所有的单体电池编码
public List<SiteBatteryListVo> getAllBatteryIdsBySites(@Param("siteIds")String[] siteIds);
}

View File

@ -87,4 +87,6 @@ public interface EmsDevicesSettingMapper
public List<Map<String, Object>> getClusterIdsByFuzzyQuery(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory,
@Param("parentId")String parentId);
public List<String> getDeviceIdsBySiteIdAndCategory(@Param("siteId")String siteId,@Param("deviceCategory")String deviceCategory);
}

View File

@ -0,0 +1,97 @@
package com.xzzn.ems.mapper;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.GeneralQueryDataVo;
import org.apache.ibatis.annotations.Param;
/**
* 点位匹配Mapper接口
*
* @author xzzn
* @date 2025-09-02
*/
public interface EmsPointMatchMapper
{
/**
* 查询点位匹配
*
* @param id 点位匹配主键
* @return 点位匹配
*/
public EmsPointMatch selectEmsPointMatchById(Long id);
/**
* 查询点位匹配列表
*
* @param emsPointMatch 点位匹配
* @return 点位匹配集合
*/
public List<EmsPointMatch> selectEmsPointMatchList(EmsPointMatch emsPointMatch);
/**
* 新增点位匹配
*
* @param emsPointMatch 点位匹配
* @return 结果
*/
public int insertEmsPointMatch(EmsPointMatch emsPointMatch);
/**
* 修改点位匹配
*
* @param emsPointMatch 点位匹配
* @return 结果
*/
public int updateEmsPointMatch(EmsPointMatch emsPointMatch);
/**
* 删除点位匹配
*
* @param id 点位匹配主键
* @return 结果
*/
public int deleteEmsPointMatchById(Long id);
/**
* 批量删除点位匹配
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteEmsPointMatchByIds(Long[] ids);
// 模糊查询所有点位
public List<String> getPointNameList(@Param("siteIds") List<String> siteIds,
@Param("deviceCategory")String deviceCategory,
@Param("pointName") String pointName);
// 获取匹配信息
public List<EmsPointMatch> getMatchInfo(@Param("siteIds") List<String> siteIds,
@Param("deviceCategory")String deviceCategory,
@Param("pointName") String pointName);
// 根据条件查询数据-按分钟
public List<GeneralQueryDataVo> getPointDataListByMinutes(@Param("siteIds")List<String> siteIds,
@Param("tableName")String tableName,
@Param("tableField")String tableField,
@Param("startDate")Date startDate,
@Param("endDate")Date endDate,
@Param("params") Map<String, List<String>> params);
// 根据条件查询数据-按小时
public List<GeneralQueryDataVo> getPointDataListByHours(@Param("siteIds")List<String> siteIds,
@Param("tableName")String tableName,
@Param("tableField")String tableField,
@Param("startDate") Date startDate,
@Param("endDate")Date endDate,
@Param("params") Map<String, List<String>> params);
// 根据条件查询数据-按天
public List<GeneralQueryDataVo> getPointDataListByDays(@Param("siteIds")List<String> siteIds,
@Param("tableName")String tableName,
@Param("tableField")String tableField,
@Param("startDate")Date startDate,
@Param("endDate")Date endDate,
@Param("params") Map<String, List<String>> params);
}

View File

@ -0,0 +1,23 @@
package com.xzzn.ems.service;
import com.xzzn.ems.domain.vo.*;
import java.util.List;
import java.util.Map;
/**
* 综合查询 服务层
*
*/
public interface IGeneralQueryService
{
// 模糊查询获取点位名称List
public List<String> getPointNameList(PointNameRequest request);
// 根据条件获取点位数据变化
public List<GeneralQueryResponse> getPointValueList(PointNameRequest request);
// 根据siteId获取下面对应的单体电池编号
public Map<String,List<String>> getAllBatteryIdsBySites(String[] siteIds);
}

View File

@ -112,11 +112,11 @@ public class DDSDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
} else if (deviceId.contains("XF")) {
meteXFProcess(deviceId, jsonData);
} else if (deviceId.contains("DH")) {
meteDHProcess(deviceId, jsonData);
dhDataProcess(deviceId, jsonData);
}
}
private void meteDHProcess(String deviceId, String dataJson) {
private void dhDataProcess(String deviceId, String dataJson) {
//动环
Map<String, Object> obj = JSON.parseObject(dataJson, new TypeReference<Map<String, Object>>() {
});

View File

@ -64,6 +64,8 @@ public class FXXDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
private EmsBatteryDataMinutesMapper emsBatteryDataMinutesMapper;
@Autowired
private EmsDailyChargeDataMapper emsDailyChargeDataMapper;
@Autowired
private EmsDhDataMapper emsDhDataMapper;
// 构造方法(调用父类构造)
public FXXDataProcessServiceImpl(ObjectMapper objectMapper) {
@ -101,10 +103,34 @@ public class FXXDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
loadDataProcess(deviceId, jsonData);
} else if (deviceId.contains("METE")) {
meteDataProcess(deviceId, jsonData);
} else if (deviceId.contains("donghuan")) {
dhDataProcess(deviceId, jsonData);
}
}
}
private void dhDataProcess(String deviceId, String dataJson) {
//动环
Map<String, Object> obj = JSON.parseObject(dataJson, new TypeReference<Map<String, Object>>() {
});
//DH
EmsDhData dhData = new EmsDhData();
dhData.setHumidity(StringUtils.getBigDecimal(obj.get("SD3")));
dhData.setTemperature(StringUtils.getBigDecimal(obj.get("WD3")));
dhData.setCreateBy("system");
dhData.setCreateTime(DateUtils.getNowDate());
dhData.setUpdateBy("system");
dhData.setUpdateTime(DateUtils.getNowDate());
dhData.setSiteId(SITE_ID);
dhData.setDeviceId(deviceId);
emsDhDataMapper.insertEmsDhData(dhData);
redisCache.setCacheObject(RedisKeyConstants.DH + SITE_ID + "_" +deviceId, dhData);
}
private void batteryStackDataProcess(String deviceId, String dataJson) {
//电池堆
@ -433,6 +459,7 @@ public class FXXDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
EmsPcsBranchData data = new EmsPcsBranchData();
data.setDeviceId(deviceId);
data.setSiteId(SITE_ID);
data.setGridStatus(GridStatus.GRID.getCode());
data.setDcPower(StringUtils.getBigDecimal(fields.get("ZLGL")));
data.setDcVoltage(StringUtils.getBigDecimal(fields.get("ZLDY")));
@ -457,6 +484,10 @@ public class FXXDataProcessServiceImpl extends AbstractBatteryDataProcessor impl
data.setAcLeakageCurrent(StringUtils.getBigDecimal(fields.get("JLLDL")));
data.setInsulationResistance(StringUtils.getBigDecimal(fields.get("JYZK")));
data.setBranchId(recordId);
data.setCreateBy("system");
data.setCreateTime(DateUtils.getNowDate());
data.setUpdateBy("system");
data.setUpdateTime(DateUtils.getNowDate());
list.add(data);
}
if (list.size() > 0 ) {

View File

@ -0,0 +1,284 @@
package com.xzzn.ems.service.impl;
import com.xzzn.common.enums.DeviceCategory;
import com.xzzn.common.utils.DateUtils;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.*;
import com.xzzn.ems.mapper.EmsBatteryDataMonthMapper;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.mapper.EmsPointMatchMapper;
import com.xzzn.ems.service.IGeneralQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
/**
* 综合查询 服务层实现
*
*/
@Service
public class GeneralQueryServiceImpl implements IGeneralQueryService
{
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:00");
@Autowired
private EmsPointMatchMapper emsPointMatchMapper;
@Autowired
private EmsDevicesSettingMapper emsDevicesSettingMapper;
@Autowired
private EmsBatteryDataMonthMapper emsBatteryDataMonthMapper;
@Override
public List<String> getPointNameList(PointNameRequest request) {
List<String> siteIds = request.getSiteIds();
if (siteIds == null || siteIds.isEmpty()) {
return Collections.emptyList();
}
String categoryName = request.getCategoryName();
String deviceCategory = DeviceCategory.getCodeByInfo(categoryName);
if (deviceCategory == null) {
return Collections.emptyList();
}
return emsPointMatchMapper.getPointNameList(siteIds,deviceCategory,request.getPointName());
}
@Override
public Map<String, List<String>> getAllBatteryIdsBySites(String[] siteIds) {
Map<String, List<String>> resultMap = new HashMap<>();
if (siteIds == null || siteIds.length == 0) {
return resultMap;
}
List<SiteBatteryListVo> siteBatteryListVos = emsBatteryDataMonthMapper.getAllBatteryIdsBySites(siteIds);
resultMap = convertToMap(siteBatteryListVos);
return resultMap;
}
public static Map<String, List<String>> convertToMap(List<SiteBatteryListVo> siteDeviceList) {
Map<String, List<String>> resultMap = new HashMap<>();
for (SiteBatteryListVo item : siteDeviceList) {
String siteId = item.getSiteId ();
String deviceId = item.getDeviceId ();
if (!resultMap.containsKey (siteId)) {
resultMap.put (siteId, new ArrayList<>());
}
resultMap.get (siteId).add (deviceId);
}
return resultMap;
}
@Override
public List<GeneralQueryResponse> getPointValueList(PointNameRequest request){
List<GeneralQueryResponse> result = new ArrayList<>();
List<String> querySiteIds = new ArrayList<>();
List<String> siteIds = request.getSiteIds();
String categoryName = request.getCategoryName();
String deviceCategory = DeviceCategory.getCodeByInfo(categoryName);
// 根据入参获取点位对应的表和字段
List<EmsPointMatch> matchInfo = emsPointMatchMapper.getMatchInfo(siteIds,deviceCategory,request.getPointName());
if (matchInfo == null || matchInfo.size() == 0) {
return result;
} else {
for (EmsPointMatch emsPointMatch : matchInfo) {
querySiteIds.add(emsPointMatch.getSiteId());
}
}
Map<String,List<String>> siteDeviceMap = request.getSiteDeviceMap();
if (DeviceCategory.BATTERY.getCode().equals(deviceCategory) && (siteDeviceMap == null || siteDeviceMap.size() == 0)) {
return result;
}
// 处理时间范围,如果未传根据单位设默认值
dealDataTime(request);
int dataUnit = request.getDataUnit();
Date startDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS,request.getStartDate());
Date endDate = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS,request.getEndDate());
try {
// 不同的site_id根据设备类型和字段默认取第一个匹配到的表和表字段只会有一个
String tableName = matchInfo.get(0).getMatchTable();
String tableField = matchInfo.get(0).getMatchField();
List<GeneralQueryDataVo> dataVoList = new ArrayList<>();
if (dataUnit == 1) { // 分钟
dataVoList = emsPointMatchMapper.getPointDataListByMinutes(querySiteIds,tableName,tableField,startDate,endDate,siteDeviceMap);
if (dataVoList != null && dataVoList.size() > 0) {
dataVoList = dealWithMinutesData(querySiteIds,dataVoList,deviceCategory,
request.getStartDate(),request.getEndDate(),siteDeviceMap);
}
} else if (dataUnit == 2) { // 小时
if (DeviceCategory.BATTERY.getCode().equals(deviceCategory)) {
// 单体电池特殊处理,已经提前按小时分表
tableName = "ems_battery_data_hour";
}
dataVoList = emsPointMatchMapper.getPointDataListByHours(querySiteIds,tableName,tableField,startDate,endDate,siteDeviceMap);
} else if (dataUnit == 3) { // 天
if (DeviceCategory.BATTERY.getCode().equals(deviceCategory)) {
tableName = "ems_battery_data_day";
}
dataVoList = emsPointMatchMapper.getPointDataListByDays(querySiteIds,tableName,tableField,startDate,endDate,siteDeviceMap);
}
// 数据转换: 先按siteId分组再按deviceId分组
result = dataVoList.stream()
// 第一层分组按siteId分组得到 <siteId, 该站点所有数据>
.collect(Collectors.groupingBy(GeneralQueryDataVo::getSiteId))
.entrySet().stream()
.map(siteEntry -> {
String siteId = siteEntry.getKey();
List<GeneralQueryDataVo> siteAllData = siteEntry.getValue();
// 第二层分组在当前站点下按deviceId分组得到 <deviceId, 该设备所有数据>
List<DevicePointDataList> deviceList = siteAllData.stream()
.collect(Collectors.groupingBy(GeneralQueryDataVo::getDeviceId))
.entrySet().stream()
.map(deviceEntry -> new DevicePointDataList(
deviceEntry.getKey(),
deviceEntry.getValue()
))
.collect(Collectors.toList());
return new GeneralQueryResponse(siteId, deviceList);
})
.collect(Collectors.toList());
} catch (ParseException e) {
throw new RuntimeException(e);
}
return result;
}
private void dealDataTime(PointNameRequest request) {
String startDate = request.getStartDate();
String endDate = request.getEndDate();
int dataUnit = request.getDataUnit();
if (startDate == null || endDate == null) {
// 前端未传递时根据dataunit设置默认时间范围
LocalDateTime now = LocalDateTime.now();
LocalDateTime start;
LocalDateTime end;
switch (dataUnit) {
case 1: // 按分钟 - 前一小时
end = now;
start = now.minusHours(1);
break;
case 2: // 按小时 - 当天
end = now.with(LocalTime.MAX);
start = now.with(LocalTime.MIN);
break;
case 3: // 按天 - 当月
end = now.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
start = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
break;
default:
throw new IllegalArgumentException("无效的dataunit值: " + dataUnit);
}
// 格式化为字符串(与前端传递的格式一致)
startDate = DateUtils.convertToString(start);
endDate = DateUtils.convertToString(end);
}
request.setStartDate(startDate);
request.setEndDate(endDate);
}
private List<GeneralQueryDataVo> dealWithMinutesData(List<String> querySiteIds, List<GeneralQueryDataVo> dataVoList,
String deviceCategory, String startDate, String endDate, Map<String, List<String>> siteDeviceMap) throws ParseException {
List<GeneralQueryDataVo> fullData = new ArrayList<>();
Map<String, GeneralQueryDataVo> dataMap = new HashMap<>();
for (GeneralQueryDataVo data : dataVoList) {
String key = data.getSiteId() + "_" + data.getDeviceId() + "_" + data.getValueDate();
dataMap.put(key, data);
}
// 生成分钟序列
Set<String> minuteSeries = generateMinuteSeries(startDate, endDate);
// 遍历每个站点,动态获取该站点下的所有设备
for (String siteId : querySiteIds) {
List<String> deviceIds = new ArrayList<>();
// 单体电池deviceId特殊处理
if (DeviceCategory.BATTERY.getCode().equals(deviceCategory) && (siteDeviceMap != null || siteDeviceMap.size() > 0)) {
deviceIds = siteDeviceMap.get(siteId);
} else {
deviceIds = emsDevicesSettingMapper.getDeviceIdsBySiteIdAndCategory(siteId,deviceCategory);
}
if (deviceIds.isEmpty()) {
continue; // 跳过无设备的站点
}
// 处理该站点下的所有设备
for (String deviceId : deviceIds) {
Object lastValue = null;
for (String minute : minuteSeries) {
String dataKey = siteId + "_" + deviceId + "_" + minute;
GeneralQueryDataVo data = dataMap.get(dataKey);
// 空值填充逻辑
if (data == null) {
data = new GeneralQueryDataVo();
data.setValueDate(minute);
data.setSiteId(siteId);
data.setDeviceId(deviceId);
data.setPointValue(lastValue); // 用上一分钟值填充
} else {
lastValue = data.getPointValue(); // 更新最新值
}
fullData.add(data);
}
}
}
fullData.sort(Comparator.comparing(GeneralQueryDataVo::getValueDate)
.thenComparing(GeneralQueryDataVo::getSiteId)
.thenComparing(GeneralQueryDataVo::getDeviceId));
return fullData;
}
/**
* 根据前端传递的startDate和endDate生成所有分钟点的序列
* @param startDate 起始时间格式yyyy-MM-dd HH:mm:00
* @param endDate 结束时间格式yyyy-MM-dd HH:mm:00
* @return 包含所有分钟点的有序集合
* @throws ParseException 时间格式解析失败时抛出
*/
private Set<String> generateMinuteSeries(String startDate, String endDate) throws ParseException {
Set<String> minutes = new TreeSet<>(); // TreeSet保证时间有序
// 解析起止时间
startDate = DateUtils.adjustToNextMinute(startDate);
Date startTime = TIME_FORMAT.parse(startDate.substring(0, 16) + ":00");
Date endTime = TIME_FORMAT.parse(endDate.substring(0, 16) + ":00");
// 验证时间有效性
if (startTime.after(endTime)) {
throw new IllegalArgumentException("起始时间不能晚于结束时间");
}
// 初始化日历对象,从起始时间开始
Calendar cal = Calendar.getInstance();
cal.setTime(startTime);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
// 循环生成从startDate到endDate的所有分钟点
while (!cal.getTime().after(endTime)) {
// 添加当前分钟格式yyyy-MM-dd HH:mm:00
minutes.add(TIME_FORMAT.format(cal.getTime()));
// 递增1分钟
cal.add(Calendar.MINUTE, 1);
}
return minutes;
}
}

View File

@ -17,6 +17,8 @@ import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
@ -75,7 +77,7 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
if (dataMap != null) {
siteMonitorHomeVo.setTotalChargedCap(dataMap.get("totalChargedCap"));
siteMonitorHomeVo.setTotalDischargedCap(dataMap.get("totalDischargedCap"));
siteMonitorHomeVo.setGridNrtPower(dataMap.get("gridNrtPower"));
//siteMonitorHomeVo.setGridNrtPower(dataMap.get("gridNrtPower"));
}
// 实时告警数据 名称+状态+告警内容
List<SiteMonitorHomeAlarmVo> siteMonitorHomeAlarmVo = emsAlarmRecordsMapper.getAlarmRecordsBySiteId(siteId);
@ -121,9 +123,20 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
SiteMonitorRunningHeadInfoVo siteMonitorRunningHeadInfoVo = new SiteMonitorRunningHeadInfoVo();
if (!StringUtils.isEmpty(siteId)) {
// 实时有功功率/实时无功功率/今日充电量/今日放电量
// 实时有功功率/实时无功功率
SiteMonitorRunningHeadInfoVo tempVo = emsPcsDataMapper.getSiteRunningHeadInfo(siteId);
siteMonitorRunningHeadInfoVo = tempVo != null ? tempVo : siteMonitorRunningHeadInfoVo;
siteMonitorRunningHeadInfoVo.setTotalActivePower(tempVo.getTotalActivePower());
siteMonitorRunningHeadInfoVo.setTotalReactivePower(tempVo.getTotalReactivePower());
// 今日充放电
LocalDateTime now = LocalDateTime.now();
LocalDateTime startOfDay = now.with(LocalTime.MIN);
Date startDate = DateUtils.toDate(startOfDay);
Date endDate = new Date();
List<SiteMonitorDataVo> siteMonitorDataVoList = emsDailyChargeDataMapper.getSingleSiteChargeData(siteId,startDate,endDate);
if (siteMonitorDataVoList != null && siteMonitorDataVoList.size() > 0) {
siteMonitorRunningHeadInfoVo.setDayChargedCap(siteMonitorDataVoList.get(0).getChargedCap());
siteMonitorRunningHeadInfoVo.setDayDisChargedCap(siteMonitorDataVoList.get(0).getDisChargedCap());
}
// 电池堆SOC + 电池堆SOH
EmsBatteryStack emsBatteryStack = emsBatteryStackMapper.getSiteSumStackInfo(siteId);
if (emsBatteryStack != null) {

View File

@ -199,4 +199,13 @@
update_by = IF(VALUES(temperature) > temperature, VALUES(update_by), update_by),
temperature = IF(VALUES(temperature) > temperature, VALUES(temperature), temperature)
</insert>
<select id="getAllBatteryIdsBySites" resultType="com.xzzn.ems.domain.vo.SiteBatteryListVo">
select DISTINCT t.site_id as siteId, t.device_id as deviceId
from ems_battery_data_month t
where t.site_id in
<foreach collection="siteIds" item="siteId" open="(" close=")" separator=",">
#{siteId}
</foreach>
</select>
</mapper>

View File

@ -210,4 +210,8 @@
</if>
and device_category = #{deviceCategory}
</select>
<select id="getDeviceIdsBySiteIdAndCategory" resultType="java.lang.String">
select DISTINCT device_id from ems_devices_setting where site_id = #{siteId} and device_category = #{deviceCategory}
</select>
</mapper>

View File

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xzzn.ems.mapper.EmsPointMatchMapper">
<resultMap type="EmsPointMatch" id="EmsPointMatchResult">
<result property="id" column="id" />
<result property="pointName" column="point_name" />
<result property="matchTable" column="match_table" />
<result property="matchField" column="match_field" />
<result property="siteId" column="site_id" />
<result property="deviceCategory" column="device_category" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectEmsPointMatchVo">
select id, point_name, match_table, match_field, site_id, device_category, create_by, create_time, update_by, update_time, remark from ems_point_match
</sql>
<select id="selectEmsPointMatchList" parameterType="EmsPointMatch" resultMap="EmsPointMatchResult">
<include refid="selectEmsPointMatchVo"/>
<where>
<if test="pointName != null and pointName != ''"> and point_name like concat('%', #{pointName}, '%')</if>
<if test="matchTable != null and matchTable != ''"> and match_table = #{matchTable}</if>
<if test="matchField != null and matchField != ''"> and match_field = #{matchField}</if>
<if test="siteId != null and siteId != ''"> and site_id = #{siteId}</if>
<if test="deviceCategory != null and deviceCategory != ''"> and device_category = #{deviceCategory}</if>
</where>
</select>
<select id="selectEmsPointMatchById" parameterType="Long" resultMap="EmsPointMatchResult">
<include refid="selectEmsPointMatchVo"/>
where id = #{id}
</select>
<insert id="insertEmsPointMatch" parameterType="EmsPointMatch" useGeneratedKeys="true" keyProperty="id">
insert into ems_point_match
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="pointName != null">point_name,</if>
<if test="matchTable != null">match_table,</if>
<if test="matchField != null">match_field,</if>
<if test="siteId != null">site_id,</if>
<if test="deviceCategory != null">device_category,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null">remark,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="pointName != null">#{pointName},</if>
<if test="matchTable != null">#{matchTable},</if>
<if test="matchField != null">#{matchField},</if>
<if test="siteId != null">#{siteId},</if>
<if test="deviceCategory != null">#{deviceCategory},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null">#{remark},</if>
</trim>
</insert>
<update id="updateEmsPointMatch" parameterType="EmsPointMatch">
update ems_point_match
<trim prefix="SET" suffixOverrides=",">
<if test="pointName != null">point_name = #{pointName},</if>
<if test="matchTable != null">match_table = #{matchTable},</if>
<if test="matchField != null">match_field = #{matchField},</if>
<if test="siteId != null">site_id = #{siteId},</if>
<if test="deviceCategory != null">device_category = #{deviceCategory},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteEmsPointMatchById" parameterType="Long">
delete from ems_point_match where id = #{id}
</delete>
<delete id="deleteEmsPointMatchByIds" parameterType="String">
delete from ems_point_match where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="getPointNameList" resultType="String">
select distinct t.point_name
from ems_point_match t
where 1=1
<if test="siteIds != null and siteIds.size() > 0">
AND t.site_id IN
<foreach collection="siteIds" item="siteId" open="(" separator="," close=")">
#{siteId}
</foreach>
</if>
<if test="deviceCategory != null and deviceCategory != ''">
and t.device_category = #{deviceCategory}
</if>
<if test="pointName != null and pointName != ''">
and t.point_name like CONCAT('%', #{pointName}, '%')
</if>
</select>
<select id="getMatchInfo" resultType="com.xzzn.ems.domain.EmsPointMatch">
select distinct t.site_id as siteId,
t.match_table as matchTable,
t.match_field as matchField,
t.device_category as deviceCategory,
t.point_name as pointName
from ems_point_match t
where 1=1
<if test="siteIds != null and siteIds.size() > 0">
AND t.site_id IN
<foreach collection="siteIds" item="siteId" open="(" separator="," close=")">
#{siteId}
</foreach>
</if>
<if test="deviceCategory != null and deviceCategory != ''">
and t.device_category = #{deviceCategory}
</if>
<if test="pointName != null and pointName != ''">
and t.point_name = #{pointName}
</if>
</select>
<sql id="commonFilter">
<choose>
<when test="params != null and !params.isEmpty()">
AND ( <trim prefixOverrides="OR">
<foreach collection="params.entrySet()" item="devices" index="siteId" separator="OR">
( site_id = #{siteId}
AND device_id IN
<foreach collection="devices" item="deviceId" open="(" close=")" separator=",">
#{deviceId}
</foreach>
)
</foreach>
</trim>
)
</when>
<otherwise>
AND site_id IN
<foreach collection="siteIds" item="siteId" open="(" close=")" separator=",">
#{siteId}
</foreach>
</otherwise>
</choose>
</sql>
<select id="getPointDataListByMinutes" resultType="com.xzzn.ems.domain.vo.GeneralQueryDataVo">
SELECT DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:00') AS valueDate,
site_id as siteId,
device_id as deviceId,
${tableField} as pointValue
FROM ${tableName}
WHERE create_time &gt;= #{startDate}
AND create_time &lt;= #{endDate}
AND ${tableField} is not null
<include refid="commonFilter"/>
GROUP BY valueDate, site_id, device_id,pointValue
ORDER BY site_id, valueDate ASC
</select>
<select id="getPointDataListByHours" resultType="com.xzzn.ems.domain.vo.GeneralQueryDataVo">
SELECT DATE_FORMAT(t.create_time, '%Y-%m-%d %H:00') AS valueDate,
t.site_id as siteId,
t.device_id as deviceId,
t.${tableField} as pointValue,
t.create_time AS last_update_time
FROM ${tableName} t
INNER JOIN ( SELECT site_id, device_id, DATE_FORMAT(create_time, '%Y-%m-%d %H:00') AS hour_group,
MAX(create_time) AS max_time
FROM ${tableName}
WHERE create_time &gt;= #{startDate}
AND create_time &lt; #{endDate}
AND ${tableField} is not null
<include refid="commonFilter"/>
GROUP BY site_id, device_id, hour_group
) tmp ON t.site_id = tmp.site_id
AND t.device_id = tmp.device_id
AND DATE_FORMAT(t.create_time, '%Y-%m-%d %H:00') = tmp.hour_group
AND t.create_time = tmp.max_time
where ${tableField} is not null
ORDER BY t.site_id, t.device_id, valueDate ASC
</select>
<select id="getPointDataListByDays" resultType="com.xzzn.ems.domain.vo.GeneralQueryDataVo">
SELECT DATE_FORMAT(t.create_time, '%Y-%m-%d') AS valueDate,
t.site_id as siteId,
t.device_id as deviceId,
t.${tableField} as pointValue,
t.create_time AS last_update_time
FROM ${tableName} t
INNER JOIN ( SELECT site_id, device_id, DATE_FORMAT(create_time, '%Y-%m-%d') AS day_group,
MAX(create_time) AS max_time
FROM ${tableName}
WHERE create_time &gt;= #{startDate}
AND create_time &lt;= #{endDate}
AND ${tableField} is not null
<include refid="commonFilter"/>
GROUP BY site_id, device_id, day_group
) tmp ON t.site_id = tmp.site_id
AND t.device_id = tmp.device_id
AND DATE_FORMAT(t.create_time, '%Y-%m-%d') = tmp.day_group
AND t.create_time = tmp.max_time
WHERE t.${tableField} is not null
ORDER BY t.site_id, t.device_id, valueDate ASC
</select>
</mapper>