平台修改意见20251120-新增设备点位清单上传接口

This commit is contained in:
gaojinming
2025-11-28 11:58:45 +08:00
parent e87abc2807
commit d9c0ff733a
11 changed files with 446 additions and 1 deletions

View File

@ -70,6 +70,10 @@ public class EmsPointMatch extends BaseEntity
@Excel(name = "点位是否需要区分多设备0-不需要 1-需要")
private Long needDiffDeviceId;
/** 设备唯一标识符 */
@Excel(name = "设备唯一标识符")
private String deviceId;
public void setId(Long id)
{
this.id = id;
@ -208,6 +212,14 @@ public class EmsPointMatch extends BaseEntity
return needDiffDeviceId;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -230,6 +242,7 @@ public class EmsPointMatch extends BaseEntity
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.append("deviceId", getDeviceId())
.toString();
}
}

View File

@ -0,0 +1,96 @@
package com.xzzn.ems.domain.vo;
import com.xzzn.common.annotation.Excel;
import java.io.Serializable;
/**
* 点位清单上传参数
*/
public class DevicePointMatchVo implements Serializable {
private static final long serialVersionUID = 1L;
/** 点位匹配字段 */
@Excel(name = "点位匹配字段")
private String matchField;
/** 数据点位 */
@Excel(name = "数据点位")
private String dataPoint;
/** 数据点位名称 */
@Excel(name = "数据点位名称")
private String dataPointName;
/** 数据单位 */
@Excel(name = "数据单位")
private String dataUnit;
//
// /** 数据点位来源设备 */
// @Excel(name = "数据点位来源设备")
// private String dataDevice;
/** 寄存器地址 */
@Excel(name = "寄存器地址")
private String ipAddress;
/** 错误信息 */
@Excel(name = "错误信息")
private String errorMsg;
public String getMatchField() {
return matchField;
}
public void setMatchField(String matchField) {
this.matchField = matchField;
}
public String getDataPoint() {
return dataPoint;
}
public void setDataPoint(String dataPoint) {
this.dataPoint = dataPoint;
}
public String getDataPointName() {
return dataPointName;
}
public void setDataPointName(String dataPointName) {
this.dataPointName = dataPointName;
}
public String getDataUnit() {
return dataUnit;
}
public void setDataUnit(String dataUnit) {
this.dataUnit = dataUnit;
}
// public String getDataDevice() {
// return dataDevice;
// }
//
// public void setDataDevice(String dataDevice) {
// this.dataDevice = dataDevice;
// }
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
}

View File

@ -0,0 +1,61 @@
package com.xzzn.ems.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import org.springframework.web.multipart.MultipartFile;
/**
* 上传设备点位清单请求参数
*/
public class ImportPointDataRequest {
/** 站点id */
@NotBlank(message = "站点ID不能为空")
private String siteId;
/** 设备id */
@NotBlank(message = "设备ID不能为空")
private String deviceId;
/** 设备类型 */
@NotBlank(message = "设备类型不能为空")
private String deviceCategory;
/** 上传点位清单文件 */
@NotNull(message = "点位清单文件不能为空")
private MultipartFile file;
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 getDeviceCategory() {
return deviceCategory;
}
public void setDeviceCategory(String deviceCategory) {
this.deviceCategory = deviceCategory;
}
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file = file;
}
}

View File

@ -0,0 +1,82 @@
package com.xzzn.ems.enums;
import com.xzzn.ems.domain.EmsAmmeterData;
import com.xzzn.ems.domain.EmsBatteryCluster;
import com.xzzn.ems.domain.EmsBatteryData;
import com.xzzn.ems.domain.EmsBatteryGroup;
import com.xzzn.ems.domain.EmsBatteryStack;
import com.xzzn.ems.domain.EmsCoolingData;
import com.xzzn.ems.domain.EmsPcsBranchData;
import com.xzzn.ems.domain.EmsPcsData;
import com.xzzn.ems.domain.EmsXfData;
import java.util.HashMap;
import java.util.Map;
/**
* 设备匹配表枚举类
*/
public enum DeviceMatchTable
{
PCS("PCS", "ems_pcs_data", EmsPcsData.class),
BRANCH("BRANCH", "ems_pcs_branch_data", EmsPcsBranchData.class),
STACK("STACK", "ems_battery_stack", EmsBatteryStack.class),
CLUSTER("CLUSTER", "ems_battery_cluster", EmsBatteryCluster.class),
BATTERY("BATTERY", "ems_battery_data", EmsBatteryData.class),
AMMETER("AMMETER", "ems_ammeter_data", EmsAmmeterData.class),
COOLING("COOLING", "ems_cooling_data", EmsCoolingData.class),
DH("DH", "ems_dh_data", EmsBatteryData.class),
XF("XF", "ems_xf_data", EmsXfData.class),
BATTERY_GROUP("BATTERY_GROUP", "ems_battery_group", EmsBatteryGroup.class);
private final String code;
private final String matchTable;
private final Class<?> matchTableClass;
DeviceMatchTable(String code, String matchTable, Class<?> matchTableClass)
{
this.code = code;
this.matchTable = matchTable;
this.matchTableClass = matchTableClass;
}
public String getCode()
{
return code;
}
public String getMatchTable() {
return matchTable;
}
public Class<?> getMatchTableClass() {
return matchTableClass;
}
// 缓存code与matchTable的映射优化查询效率
private static final Map<String, String> DEVICE_MATCH_TABLE_MAP = new HashMap<>();
// 缓存table与实体类的映射优化查询效率
private static final Map<String, Class<?>> TABLE_TO_CLASS_MAP = new HashMap<>();
// 静态块初始化缓存
static {
for (DeviceMatchTable category : DeviceMatchTable.values()) {
DEVICE_MATCH_TABLE_MAP.put(category.code, category.matchTable);
TABLE_TO_CLASS_MAP.put(category.matchTable, category.matchTableClass);
}
}
// 通过code获取matchTable的方法
public static String getMatchTableByCode(String code) {
return DEVICE_MATCH_TABLE_MAP.get(code); // 从缓存中直接获取,效率高
}
// 通过table获取实体类的方法
public static Class<?> getClassByTable(String matchTable) {
return TABLE_TO_CLASS_MAP.get(matchTable); // 从缓存中直接获取,效率高
}
}

View File

@ -140,4 +140,8 @@ public interface EmsPointMatchMapper
// 根据站点,设备类别,点位,获取唯一数据
public EmsPointMatch getUniquePoint(@Param("siteId")String siteId, @Param("deviceCategory")String deviceCategory, @Param("dataPoint")String dataPoint);
EmsPointMatch getOnePointMatch(@Param("siteId") String siteId, @Param("deviceId") String deviceId, @Param("deviceCategory") String deviceCategory, @Param("dataPoint") String dataPoint);
List<EmsPointMatch> getDevicePointMatchList(@Param("siteId") String siteId, @Param("deviceId") String deviceId, @Param("deviceCategory") String deviceCategory);
}

View File

@ -3,6 +3,8 @@ package com.xzzn.ems.service;
import java.util.List;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
/**
* 点位匹配Service接口
@ -29,4 +31,6 @@ public interface IEmsPointMatchService
* @return
*/
public String importPoint(List<EmsPointMatch> userList, boolean updateSupport, String operName);
public List<DevicePointMatchVo> importDataByDevice(ImportPointDataRequest request, String operName);
}

View File

@ -1,15 +1,33 @@
package com.xzzn.ems.service.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson2.JSON;
import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.exception.ServiceException;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.common.utils.bean.BeanValidators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import com.xzzn.common.utils.poi.ExcelUtil;
import com.xzzn.ems.domain.vo.DevicePointMatchVo;
import com.xzzn.ems.domain.vo.ImportPointDataRequest;
import com.xzzn.ems.enums.DeviceMatchTable;
import com.xzzn.ems.mapper.EmsPointMatchMapper;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.service.IEmsPointMatchService;
import com.xzzn.ems.utils.MatchTableUtils;
import javax.validation.Validator;
@ -22,10 +40,13 @@ import javax.validation.Validator;
@Service
public class EmsPointMatchServiceImpl implements IEmsPointMatchService
{
private static final Logger log = LoggerFactory.getLogger(EmsPointMatchServiceImpl.class);
@Autowired
private EmsPointMatchMapper emsPointMatchMapper;
@Autowired
protected Validator validator;
@Autowired
private RedisCache redisCache;
/**
* 查询点位匹配列表
@ -92,5 +113,89 @@ public class EmsPointMatchServiceImpl implements IEmsPointMatchService
return successMsg.toString();
}
@Override
@Transactional(rollbackFor = Exception.class)
public List<DevicePointMatchVo> importDataByDevice(ImportPointDataRequest request, String operName) {
ExcelUtil<DevicePointMatchVo> util = new ExcelUtil<>(DevicePointMatchVo.class);
List<DevicePointMatchVo> pointMatchList = new ArrayList<>();
MultipartFile file = request.getFile();
if (file.isEmpty()) {
throw new ServiceException("点位清单文件不能为空");
}
try {
pointMatchList = util.importExcel(file.getInputStream());
} catch (IOException e) {
log.info("点位清单导入失败:{}", e.getMessage());
throw new ServiceException("点位清单导入失败!");
}
if (CollectionUtils.isEmpty(pointMatchList)) {
throw new ServiceException("导入用户数据不能为空!");
}
String siteId = request.getSiteId();
String deviceId = request.getDeviceId();
String deviceCategory = request.getDeviceCategory();
List<DevicePointMatchVo> errorList = new ArrayList<>();
for (DevicePointMatchVo pointMatch : pointMatchList) {
try {
//校验点位清单文件内容
if (validDevicePointMatch(pointMatch, errorList)) {
continue;
}
EmsPointMatch savePoint = new EmsPointMatch();
BeanUtils.copyProperties(pointMatch, savePoint);
savePoint.setSiteId(siteId);
savePoint.setDeviceId(deviceId);
savePoint.setDeviceCategory(deviceCategory);
savePoint.setMatchTable(DeviceMatchTable.getMatchTableByCode(deviceCategory));
savePoint.setPointName(MatchTableUtils.getFieldAnnotation(DeviceMatchTable.getClassByTable(savePoint.getMatchTable()), StringUtils.toCamelCase(savePoint.getMatchField())));
savePoint.setCreateBy(operName);
savePoint.setUpdateBy(operName);
// 验证点位是否存在
EmsPointMatch dbPoint = emsPointMatchMapper.getOnePointMatch(siteId, deviceId, deviceCategory, pointMatch.getDataPoint());
if (StringUtils.isNull(dbPoint)) {
emsPointMatchMapper.insertEmsPointMatch(savePoint);
} else {
emsPointMatchMapper.updateEmsPointMatch(savePoint);
}
} catch (Exception e) {
log.info("点位清单导入失败:{}", e.getMessage());
throw new ServiceException("点位清单导入失败!");
}
}
// 同步到Redis
syncToRedis(siteId, deviceId, deviceCategory);
return errorList;
}
private boolean validDevicePointMatch(DevicePointMatchVo pointMatch, List<DevicePointMatchVo> errorList) {
StringBuilder errorMsg = new StringBuilder();
if (StringUtils.isBlank(pointMatch.getMatchField())) {
errorMsg.append("点位匹配字段不能为空;");
}
if (StringUtils.isBlank(pointMatch.getDataPoint())) {
errorMsg.append("数据点位不能为空;");
}
if (StringUtils.isBlank(pointMatch.getDataPointName())) {
errorMsg.append("数据点位名称不能为空;");
}
// if (StringUtils.isBlank(pointMatch.getDataDevice())) {
// errorMsg.append("数据点位来源设备不能为空;");
// }
if (errorMsg.length() > 0) {
pointMatch.setErrorMsg(errorMsg.toString());
errorList.add(pointMatch);
return true;
}
return false;
}
private void syncToRedis(String siteId, String deviceId, String deviceCategory) {
// 同步到Redis
String pointMatchKey = RedisKeyConstants.POINT_MATCH + deviceCategory + "_" + siteId + "_" + deviceId;
List<EmsPointMatch> pointMatchData = emsPointMatchMapper.getDevicePointMatchList(siteId, deviceId, deviceCategory);
// log.info("同步点位匹配数据到Redis key:{} data:{}", pointMatchKey, pointMatchData);
redisCache.setCacheObject(pointMatchKey, pointMatchData);
log.info("点位匹配数据同步完成 data:{}", JSON.toJSONString(redisCache.getCacheObject(pointMatchKey)));
}
}

View File

@ -0,0 +1,33 @@
package com.xzzn.ems.utils;
import com.xzzn.common.annotation.Excel;
import com.xzzn.common.utils.StringUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 匹配表工具类
*/
public class MatchTableUtils {
/**
* 获取字段注解信息
*/
public static String getFieldAnnotation(Class<?> clazz, String filedName)
{
List<Field> tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
for (Field field : tempFields) {
if (StringUtils.equals(filedName, field.getName()) && field.isAnnotationPresent(Excel.class))
{
Excel column = field.getAnnotation(Excel.class);
return column.name();
}
}
return null;
}
}