diff --git a/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java b/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java index 1d2bc7a..3c1dd6f 100644 --- a/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java +++ b/ems-admin/src/main/java/com/xzzn/web/controller/ems/EmsSiteConfigController.java @@ -8,21 +8,19 @@ import com.xzzn.common.core.page.TableDataInfo; import com.xzzn.common.enums.BusinessType; import com.xzzn.common.utils.file.FileUploadUtils; import com.xzzn.common.utils.file.MimeTypeUtils; +import com.xzzn.common.utils.poi.ExcelUtil; import com.xzzn.ems.domain.EmsSiteSetting; import com.xzzn.ems.domain.vo.DeviceUpdateRequest; import com.xzzn.ems.domain.vo.DevicesSettingVo; import com.xzzn.ems.domain.vo.PointDataRequest; import com.xzzn.ems.domain.vo.PointQueryResponse; -import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest; import com.xzzn.ems.domain.vo.SiteDeviceListVo; +import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo; import com.xzzn.ems.domain.vo.WorkStatusEnumMappingSaveRequest; import com.xzzn.ems.service.IEmsDeviceSettingService; import com.xzzn.ems.service.IEmsSiteService; - -import java.util.List; - -import javax.validation.Valid; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; @@ -35,14 +33,17 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + /** - * - * 站点配置 - * + * 绔欑偣閰嶇疆 */ @RestController @RequestMapping("/ems/siteConfig") -public class EmsSiteConfigController extends BaseController{ +public class EmsSiteConfigController extends BaseController { @Autowired private IEmsSiteService iEmsSiteService; @@ -50,216 +51,163 @@ public class EmsSiteConfigController extends BaseController{ @Autowired private IEmsDeviceSettingService iEmsDeviceSettingService; - /** - * 获取站点列表 - */ @GetMapping("/getSiteInfoList") - public TableDataInfo getSiteInfoList(@RequestParam String siteName, @RequestParam String startTime, @RequestParam String endTime) - { + public TableDataInfo getSiteInfoList(@RequestParam String siteName, @RequestParam String startTime, @RequestParam String endTime) { startPage(); - List list = iEmsSiteService.getAllSiteInfoList(siteName,startTime,endTime); + List list = iEmsSiteService.getAllSiteInfoList(siteName, startTime, endTime); return getDataTable(list); } - /** - * 新增站点 - */ @PostMapping("/addSite") - public AjaxResult addSite(@RequestBody EmsSiteSetting emsSiteSetting) - { + public AjaxResult addSite(@RequestBody EmsSiteSetting emsSiteSetting) { emsSiteSetting.setCreateBy(getUsername()); return toAjax(iEmsSiteService.addSite(emsSiteSetting)); } - /** - * 编辑站点 - */ @PostMapping("/updateSite") - public AjaxResult updateSite(@RequestBody EmsSiteSetting emsSiteSetting) - { + public AjaxResult updateSite(@RequestBody EmsSiteSetting emsSiteSetting) { emsSiteSetting.setUpdateBy(getUsername()); return toAjax(iEmsSiteService.updateSite(emsSiteSetting)); } - /** - * 获取设备列表-分页 - */ @GetMapping("/getDeviceInfoList") - public TableDataInfo getDeviceInfoList(@RequestParam(value = "siteId", required = false) String siteId, - @RequestParam(value = "deviceCategory", required = false) String deviceCategory) - { + public TableDataInfo getDeviceInfoList(@RequestParam(value = "siteId", required = false) String siteId, + @RequestParam(value = "deviceCategory", required = false) String deviceCategory) { startPage(); List list = iEmsSiteService.getAllDeviceListNoDisp(siteId, deviceCategory); - return getDataTable(list); } - /** - * 获取设备详细信息 - */ @GetMapping("/getDeviceDetailInfo") - public AjaxResult getDeviceDetailInfo(@RequestParam Long id) - { + public AjaxResult getDeviceDetailInfo(@RequestParam Long id) { return success(iEmsDeviceSettingService.getDeviceDetailInfo(id)); } - /** - * 获取设备列表-不分页 - */ @GetMapping("/getDeviceList") - public AjaxResult getDeviceInfoList2(@RequestParam String siteId) - { + public AjaxResult getDeviceInfoList2(@RequestParam String siteId) { return success(iEmsSiteService.getAllDeviceList(siteId, null)); } - /** - * 获取所有设备类别 - */ @GetMapping("/getDeviceCategory") - public AjaxResult getDeviceCategory() - { + public AjaxResult getDeviceCategory() { return success(iEmsDeviceSettingService.getDeviceCategory()); } - /** - * 新增设备 - */ @PostMapping("/addDevice") - public AjaxResult addDevice(@RequestBody DevicesSettingVo devicesSetting) - { + public AjaxResult addDevice(@RequestBody DevicesSettingVo devicesSetting) { int result = iEmsDeviceSettingService.addDevice(devicesSetting); - if (result > 0) { + if (result > 0) { return AjaxResult.success(result); - } else { - return AjaxResult.error("该设备已存在"); } + return AjaxResult.error("璇ヨ澶囧凡瀛樺湪"); } - /** - * 上传设备图片 - */ @PostMapping("/uploadDeviceImg") - public AjaxResult uploadDeviceImg(@RequestParam("avatarfile") MultipartFile file) throws Exception - { + public AjaxResult uploadDeviceImg(@RequestParam("avatarfile") MultipartFile file) throws Exception { if (!file.isEmpty()) { String avatar = FileUploadUtils.upload(RuoYiConfig.getDevicePath(), file, MimeTypeUtils.IMAGE_EXTENSION); - AjaxResult ajax = AjaxResult.success(); ajax.put("imgUrl", avatar); return ajax; } - return error("上传图片异常,请联系管理员"); + return error("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛?"); } - /** - * 修改Modbus设备配置 - */ @PostMapping("/updateDevice") - public AjaxResult updateDevice(@RequestBody DevicesSettingVo emsDevicesSetting) - { + public AjaxResult updateDevice(@RequestBody DevicesSettingVo emsDevicesSetting) { int result = iEmsDeviceSettingService.updateDevice(emsDevicesSetting); - if (result > 0) { + if (result > 0) { return AjaxResult.success(result); - } else if (result == -1) { - return AjaxResult.error("数据不存在"); - } else if (result == -2) { - return AjaxResult.error("该设备已存在"); + } else if (result == -1) { + return AjaxResult.error("鏁版嵁涓嶅瓨鍦?"); + } else if (result == -2) { + return AjaxResult.error("璇ヨ澶囧凡瀛樺湪"); } return AjaxResult.success(result); } - /** - * 删除Modbus设备配置 - */ @DeleteMapping("/deleteService/{id}") - public AjaxResult deleteService(@PathVariable Long id) - { + public AjaxResult deleteService(@PathVariable Long id) { return toAjax(iEmsDeviceSettingService.deleteEmsDevicesSettingById(id)); } - /** - * 单个站点单个设备点位查询-点位清单 - */ @GetMapping("/getDevicePointList") - public TableDataInfo getDevicePointList(@Validated PointDataRequest request) - { + public TableDataInfo getDevicePointList(@Validated PointDataRequest request) { List result = iEmsDeviceSettingService.getSingleSiteDevicePoints(request); return getDataTable2(result); } - /** - * 获取指定站点下的所有设备类别 - */ @GetMapping("/getSiteAllDeviceCategory") - public AjaxResult getSiteAllDeviceCategory(String siteId) - { + public AjaxResult getSiteAllDeviceCategory(String siteId) { return success(iEmsDeviceSettingService.getSiteAllDeviceCategory(siteId)); } - /** - * 根据设备类别获取父类的设备id - */ @GetMapping("/getParentDeviceId") - public AjaxResult getParentDeviceId(@RequestParam String siteId, @RequestParam String deviceCategory) - { + public AjaxResult getParentDeviceId(@RequestParam String siteId, @RequestParam String deviceCategory) { return success(iEmsSiteService.getParentCategoryDeviceId(siteId, deviceCategory)); } - /** - * 获取指定站点下的指定设备类型的设备 - */ @GetMapping("/getDeviceListBySiteAndCategory") - public AjaxResult getDeviceListBySiteAndCategory(String siteId,String deviceCategory) - { + public AjaxResult getDeviceListBySiteAndCategory(String siteId, String deviceCategory) { return success(iEmsDeviceSettingService.getDeviceListBySiteAndCategory(siteId, deviceCategory)); } - /** - * 获取单站监控项目点位映射 - */ @GetMapping("/getSingleMonitorProjectPointMapping") - public AjaxResult getSingleMonitorProjectPointMapping(@RequestParam String siteId) - { + public AjaxResult getSingleMonitorProjectPointMapping(@RequestParam String siteId) { return success(iEmsDeviceSettingService.getSiteMonitorProjectPointMapping(siteId)); } - /** - * 保存单站监控项目点位映射 - */ @PostMapping("/saveSingleMonitorProjectPointMapping") - public AjaxResult saveSingleMonitorProjectPointMapping(@RequestBody SiteMonitorProjectPointMappingSaveRequest request) - { + public AjaxResult saveSingleMonitorProjectPointMapping(@RequestBody SiteMonitorProjectPointMappingSaveRequest request) { int rows = iEmsDeviceSettingService.saveSiteMonitorProjectPointMapping(request, getUsername()); return AjaxResult.success(rows); } - /** - * 获取单站监控工作状态枚举映射(PCS) - */ @GetMapping("/getSingleMonitorWorkStatusEnumMappings") - public AjaxResult getSingleMonitorWorkStatusEnumMappings(@RequestParam String siteId) - { + public AjaxResult getSingleMonitorWorkStatusEnumMappings(@RequestParam String siteId) { return success(iEmsDeviceSettingService.getSiteWorkStatusEnumMappings(siteId)); } - /** - * 保存单站监控工作状态枚举映射(PCS) - */ @PostMapping("/saveSingleMonitorWorkStatusEnumMappings") - public AjaxResult saveSingleMonitorWorkStatusEnumMappings(@RequestBody WorkStatusEnumMappingSaveRequest request) - { + public AjaxResult saveSingleMonitorWorkStatusEnumMappings(@RequestBody WorkStatusEnumMappingSaveRequest request) { int rows = iEmsDeviceSettingService.saveSiteWorkStatusEnumMappings(request.getSiteId(), request.getMappings(), getUsername()); return AjaxResult.success(rows); } - /** - * PCS设备开关机 - */ + @GetMapping("/downloadSingleBatteryMonitorImportTemplate") + public void downloadSingleBatteryMonitorImportTemplate(HttpServletResponse response) { + ExcelUtil util = new ExcelUtil<>(SingleBatteryMonitorImportRowVo.class); + util.importTemplateExcel(response, "单体电池导入模板", "单体电池导入模板"); + } + + @PostMapping("/importSingleBatteryMonitorMappings") + public AjaxResult importSingleBatteryMonitorMappings(@RequestParam("siteId") String siteId, + @RequestParam("file") MultipartFile file) throws Exception { + ExcelUtil util = new ExcelUtil<>(SingleBatteryMonitorImportRowVo.class); + List rowList = util.importExcel(file.getInputStream(), 1); + if (rowList == null) { + return AjaxResult.error("导入失败:未读取到任何数据,请检查 Excel 文件内容"); + } + List validRowList = new ArrayList<>(); + for (int i = 0; i < rowList.size(); i++) { + SingleBatteryMonitorImportRowVo row = rowList.get(i); + if (row == null) { + continue; + } + row.setRowNum(i + 3); + validRowList.add(row); + } + if (validRowList.isEmpty()) { + return AjaxResult.error("导入失败:未识别到有效数据,请使用系统导出的最新模板,并保持表头名称不变"); + } + SingleBatteryMonitorImportResultVo result = iEmsDeviceSettingService.importSingleBatteryMonitorMappings(siteId, validRowList, getUsername()); + return AjaxResult.success(result); + } + // @PreAuthorize("@ss.hasPermi('system:device:onAndOff')") - @Log(title = "开关机", businessType = BusinessType.UPDATE) + @Log(title = "寮€鍏虫満", businessType = BusinessType.UPDATE) @PostMapping("/updateDeviceStatus") - public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request) - { + public AjaxResult updateDeviceStatus(@Valid @RequestBody DeviceUpdateRequest request) { return success(iEmsDeviceSettingService.updateDeviceStatus(request)); } } diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointConfig.java b/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointConfig.java index 2f2040a..b341652 100644 --- a/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointConfig.java +++ b/ems-system/src/main/java/com/xzzn/ems/domain/EmsPointConfig.java @@ -81,6 +81,9 @@ public class EmsPointConfig extends BaseEntity { @Excel(name = "Modbus分组") private String modbusGroup; + @Excel(name = "小数位数") + private Integer decimalScale; + public Long getId() { return id; } @@ -265,6 +268,14 @@ public class EmsPointConfig extends BaseEntity { this.modbusGroup = modbusGroup; } + public Integer getDecimalScale() { + return decimalScale; + } + + public void setDecimalScale(Integer decimalScale) { + this.decimalScale = decimalScale; + } + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) @@ -291,6 +302,7 @@ public class EmsPointConfig extends BaseEntity { .append("modbusDataType", getModbusDataType()) .append("modbusReadOrder", getModbusReadOrder()) .append("modbusGroup", getModbusGroup()) + .append("decimalScale", getDecimalScale()) .append("createBy", getCreateBy()) .append("createTime", getCreateTime()) .append("updateBy", getUpdateBy()) diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterRevenueStatisListVo.java b/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterRevenueStatisListVo.java index 4f9dd7e..a0cd43b 100644 --- a/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterRevenueStatisListVo.java +++ b/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterRevenueStatisListVo.java @@ -53,6 +53,8 @@ public class AmmeterRevenueStatisListVo { /** 实际收益 */ private BigDecimal actualRevenue = BigDecimal.ZERO; + private String remark; + public String getDataTime() { return dataTime; } @@ -172,4 +174,12 @@ public class AmmeterRevenueStatisListVo { public void setActualRevenue(BigDecimal actualRevenue) { this.actualRevenue = actualRevenue; } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } } diff --git a/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterStatisListVo.java b/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterStatisListVo.java index d53917c..7dbd633 100644 --- a/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterStatisListVo.java +++ b/ems-system/src/main/java/com/xzzn/ems/domain/vo/AmmeterStatisListVo.java @@ -46,6 +46,8 @@ public class AmmeterStatisListVo { /** 效率-有功总/无功总 */ private BigDecimal effect = BigDecimal.ZERO; + private String remark; + public String getDataTime() { return dataTime; } @@ -149,4 +151,12 @@ public class AmmeterStatisListVo { public void setEffect(BigDecimal effect) { this.effect = effect; } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } } diff --git a/ems-system/src/main/java/com/xzzn/ems/mapper/EmsSiteMonitorPointMatchMapper.java b/ems-system/src/main/java/com/xzzn/ems/mapper/EmsSiteMonitorPointMatchMapper.java index b9fa099..68a196b 100644 --- a/ems-system/src/main/java/com/xzzn/ems/mapper/EmsSiteMonitorPointMatchMapper.java +++ b/ems-system/src/main/java/com/xzzn/ems/mapper/EmsSiteMonitorPointMatchMapper.java @@ -18,4 +18,6 @@ public interface EmsSiteMonitorPointMatchMapper { int deleteBySiteIdAndDeviceId(@Param("siteId") String siteId, @Param("deviceId") String deviceId); int insertBatch(@Param("list") List list); + + int updateEmsSiteMonitorPointMatch(EmsSiteMonitorPointMatch pointMatch); } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java b/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java index 72d8f5d..d8c940c 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/IEmsDeviceSettingService.java @@ -10,6 +10,8 @@ import com.xzzn.ems.domain.vo.SiteMonitorDataSaveRequest; import com.xzzn.ems.domain.vo.SiteMonitorProjectDisplayVo; import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest; import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingVo; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo; import com.xzzn.ems.domain.vo.WorkStatusEnumMappingVo; import java.util.Date; @@ -56,4 +58,6 @@ public interface IEmsDeviceSettingService public int saveSiteMonitorProjectData(SiteMonitorDataSaveRequest request, String operName); public int syncSiteMonitorDataByMqtt(String siteId, String deviceId, String jsonData, Date valueTime); + + public SingleBatteryMonitorImportResultVo importSingleBatteryMonitorMappings(String siteId, List rows, String operName); } diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/DeviceDataProcessServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/DeviceDataProcessServiceImpl.java index 00e346d..9f7df84 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/DeviceDataProcessServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/DeviceDataProcessServiceImpl.java @@ -840,6 +840,12 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i Date queryEndTime = DateUtils.getNowDate(); Date queryStartTime = new Date(queryEndTime.getTime() - CALC_POINT_INFLUX_QUERY_WINDOW_MS); Map contextValues = new HashMap<>(); + Set reservedCalcContextKeys = calcPointConfigs.stream() + .map(this::resolveCalcContextKey) + .filter(StringUtils::isNotBlank) + .map(String::trim) + .map(String::toUpperCase) + .collect(Collectors.toSet()); Date latestDataTime = null; for (EmsPointConfig sourcePointConfig : sourcePointConfigs) { if (sourcePointConfig == null) { @@ -855,7 +861,7 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i if (latestPointValue == null || latestPointValue.getPointValue() == null) { continue; } - putSourcePointValueToContext(sourcePointConfig, latestPointValue.getPointValue(), contextValues); + putSourcePointValueToContext(sourcePointConfig, latestPointValue.getPointValue(), contextValues, reservedCalcContextKeys); if (latestDataTime == null || (latestPointValue.getDataTime() != null && latestPointValue.getDataTime().after(latestDataTime))) { latestDataTime = latestPointValue.getDataTime(); @@ -1578,6 +1584,9 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i String pointId = resolveInfluxPointKey(calcPointConfig); if (StringUtils.isNotBlank(pointId)) { BigDecimal storedValue = calcValue.asNumber(); + if (calcPointConfig.getDecimalScale() != null && calcPointConfig.getDecimalScale() >= 0) { + storedValue = storedValue.setScale(calcPointConfig.getDecimalScale(), RoundingMode.HALF_UP); + } enqueuePointData(siteId, deviceId, pointId, storedValue, dataUpdateTime); calcPointIdValueMap.put(pointId, storedValue); } @@ -1949,7 +1958,10 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i return new ArrayList<>(uniqueByPointId.values()); } - private void putSourcePointValueToContext(EmsPointConfig pointConfig, BigDecimal pointValue, Map contextValues) { + private void putSourcePointValueToContext(EmsPointConfig pointConfig, + BigDecimal pointValue, + Map contextValues, + Set reservedCalcContextKeys) { if (pointConfig == null || pointValue == null || contextValues == null) { return; } @@ -1959,7 +1971,13 @@ public class DeviceDataProcessServiceImpl extends AbstractBatteryDataProcessor i } String normalizedDataKey = normalizeVariablePart(pointConfig.getDataKey()); if (StringUtils.isNotBlank(normalizedDataKey)) { - contextValues.put(normalizedDataKey, pointValue); + String reservedKey = normalizedDataKey.trim().toUpperCase(); + if (CollectionUtils.isEmpty(reservedCalcContextKeys) || !reservedCalcContextKeys.contains(reservedKey)) { + contextValues.put(normalizedDataKey, pointValue); + } else { + log.debug("计算点上下文跳过源点位 dataKey 裸变量,避免覆盖计算点,siteId/deviceId/pointId={}/{}/{}, dataKey={}", + pointConfig.getSiteId(), pointConfig.getDeviceId(), pointConfig.getPointId(), pointConfig.getDataKey()); + } String devicePrefix = normalizeVariablePart(pointConfig.getDeviceId()); if (StringUtils.isNotBlank(devicePrefix)) { contextValues.put(devicePrefix + "_" + normalizedDataKey, pointValue); diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java index 4336a71..80b3c8c 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsDeviceSettingServiceImpl.java @@ -11,7 +11,9 @@ import com.xzzn.common.core.modbus.domain.WriteTagConfig; import com.xzzn.common.core.redis.RedisCache; import com.xzzn.common.enums.BusinessStatus; import com.xzzn.common.enums.BusinessType; +import com.xzzn.common.enums.CommunicationStatus; import com.xzzn.common.enums.DeviceCategory; +import com.xzzn.common.enums.DeviceRunningStatus; import com.xzzn.common.enums.DeviceType; import com.xzzn.common.enums.OperatorType; import com.xzzn.common.enums.PointType; @@ -37,6 +39,9 @@ import com.xzzn.ems.domain.vo.SiteMonitorDataVo; import com.xzzn.ems.domain.vo.SiteMonitorProjectDisplayVo; import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest; import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingVo; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportFailureVo; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo; +import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo; import com.xzzn.ems.domain.vo.WorkStatusEnumMappingVo; import com.xzzn.ems.mapper.EmsBatteryDataMinutesMapper; import com.xzzn.ems.mapper.EmsDailyChargeDataMapper; @@ -113,8 +118,16 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService private static final String MATCH_FIELD_PCS_COMMUNICATION_STATUS = "pcsCommunicationStatus"; private static final String MATCH_FIELD_EMS_COMMUNICATION_STATUS = "emsCommunicationStatus"; private static final String SITE_LEVEL_CALC_DEVICE_ID = "SITE_CALC"; + private static final String BATTERY_FIELD_VOLTAGE = "SBJK_DTDC__voltage"; + private static final String BATTERY_FIELD_TEMPERATURE = "SBJK_DTDC__temperature"; + private static final String BATTERY_FIELD_SOC = "SBJK_DTDC__soc"; + private static final String BATTERY_FIELD_SOH = "SBJK_DTDC__soh"; + private static final Set SINGLE_BATTERY_IMPORT_FIELD_CODES = new HashSet<>(Arrays.asList( + BATTERY_FIELD_VOLTAGE, BATTERY_FIELD_TEMPERATURE, BATTERY_FIELD_SOC, BATTERY_FIELD_SOH + )); private static final Set DEVICE_DIMENSION_MENU_CODES = new HashSet<>(Arrays.asList( - "SBJK_EMS", "SBJK_PCS", "SBJK_BMSZL", "SBJK_BMSDCC", "SBJK_DTDC", "SBJK_DB", "SBJK_YL", "SBJK_DH", "SBJK_XF" + "SBJK_EMS", "SBJK_PCS", "SBJK_BMSZL", "SBJK_BMSDCC", "SBJK_DTDC", "SBJK_DB", "SBJK_YL", "SBJK_DH", "SBJK_XF", + "TJBB_PCSQX", "TJBB_DCDQX", "TJBB_DCWD" )); private static final Set DEVICE_DIMENSION_FIELD_CODES = new HashSet<>(Arrays.asList( FIELD_CURVE_PCS_ACTIVE_POWER, @@ -200,6 +213,9 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService map.put("SBJK_YL", DeviceCategory.COOLING.getCode()); map.put("SBJK_DH", DeviceCategory.DH.getCode()); map.put("SBJK_XF", DeviceCategory.XF.getCode()); + map.put("TJBB_PCSQX", DeviceCategory.PCS.getCode()); + map.put("TJBB_DCDQX", DeviceCategory.STACK.getCode()); + map.put("TJBB_DCWD", DeviceCategory.CLUSTER.getCode()); return map; } @@ -1065,6 +1081,362 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService } } + @Override + @Transactional(rollbackFor = Exception.class) + public SingleBatteryMonitorImportResultVo importSingleBatteryMonitorMappings(String siteId, List rows, String operName) { + SingleBatteryMonitorImportResultVo result = new SingleBatteryMonitorImportResultVo(); + String normalizedSiteId = StringUtils.trim(siteId); + List sourceRows = rows == null ? Collections.emptyList() : rows; + result.setCommitted(false); + result.setTotalRows(sourceRows.size()); + result.setInsertedBatteryCount(0); + result.setUpdatedBatteryCount(0); + result.setInsertedMappingCount(0); + result.setUpdatedMappingCount(0); + + if (StringUtils.isBlank(normalizedSiteId)) { + result.setFailureRows(sourceRows.size()); + result.setSuccessRows(0); + result.setMessage("导入失败:站点ID不能为空"); + return result; + } + if (CollectionUtils.isEmpty(sourceRows)) { + result.setFailureRows(0); + result.setSuccessRows(0); + result.setCommitted(true); + result.setMessage("导入文件中未读取到任何数据"); + return result; + } + + List settingList = emsDevicesMapper.selectEmsDevicesSettingList(buildSiteDeviceQuery(normalizedSiteId)); + Map deviceMap = settingList.stream() + .filter(Objects::nonNull) + .filter(item -> StringUtils.isNotBlank(item.getDeviceId())) + .collect(Collectors.toMap( + item -> StringUtils.trim(item.getDeviceId()), + item -> item, + (left, right) -> right, + LinkedHashMap::new + )); + + List failureList = new ArrayList<>(); + Set seenBatteryKeys = new HashSet<>(); + Map seenClusterBatteryRowMap = new HashMap<>(); + Map seenSiteBatteryRowMap = new HashMap<>(); + Set pointIds = new HashSet<>(); + List validRows = new ArrayList<>(); + + for (SingleBatteryMonitorImportRowVo row : sourceRows) { + SingleBatteryMonitorImportRowVo normalizedRow = normalizeSingleBatteryImportRow(row); + String duplicateKey = normalizedRow.getSiteId() + "|" + normalizedRow.getBatteryDeviceId(); + String clusterDuplicateKey = normalizedRow.getSiteId() + "|" + normalizedRow.getClusterDeviceId() + "|" + normalizedRow.getBatteryDeviceId(); + String rowError = validateSingleBatteryImportRow(normalizedSiteId, normalizedRow, deviceMap, duplicateKey, clusterDuplicateKey, + seenBatteryKeys, seenSiteBatteryRowMap, seenClusterBatteryRowMap); + if (rowError != null) { + failureList.add(buildSingleBatteryImportFailure(normalizedRow, rowError)); + continue; + } + collectPointIds(pointIds, normalizedRow); + validRows.add(normalizedRow); + } + + if (!pointIds.isEmpty()) { + Map pointConfigMap = emsPointConfigMapper.selectBySiteIdAndPointIds(normalizedSiteId, new ArrayList<>(pointIds)) + .stream() + .filter(Objects::nonNull) + .filter(item -> StringUtils.isNotBlank(item.getPointId())) + .collect(Collectors.toMap( + item -> StringUtils.trim(item.getPointId()), + item -> item, + (left, right) -> right + )); + for (SingleBatteryMonitorImportRowVo row : validRows) { + String missingPointMessage = validateSingleBatteryImportPoints(row, pointConfigMap); + if (missingPointMessage != null) { + failureList.add(buildSingleBatteryImportFailure(row, missingPointMessage)); + } + } + } + + if (!failureList.isEmpty()) { + result.setFailureDetails(failureList); + result.setFailureRows(failureList.size()); + result.setSuccessRows(Math.max(sourceRows.size() - failureList.size(), 0)); + result.setMessage("导入校验未通过,请根据失败明细修改后重试"); + return result; + } + + Map existingPointMatchMap = emsSiteMonitorPointMatchMapper.selectBySiteId(normalizedSiteId) + .stream() + .filter(Objects::nonNull) + .filter(item -> SINGLE_BATTERY_IMPORT_FIELD_CODES.contains(StringUtils.trim(item.getFieldCode()))) + .filter(item -> StringUtils.isNotBlank(item.getDeviceId())) + .collect(Collectors.toMap( + item -> buildMatchKey(StringUtils.trim(item.getFieldCode()), StringUtils.trim(item.getDeviceId())), + item -> item, + (left, right) -> right, + LinkedHashMap::new + )); + + List insertList = new ArrayList<>(); + Set importedBatteryIds = new HashSet<>(); + Date now = DateUtils.getNowDate(); + for (SingleBatteryMonitorImportRowVo row : validRows) { + String batteryId = row.getBatteryDeviceId(); + importedBatteryIds.add(batteryId); + EmsDevicesSetting batterySetting = deviceMap.get(batteryId); + if (batterySetting == null) { + EmsDevicesSetting insertDevice = new EmsDevicesSetting(); + insertDevice.setSiteId(normalizedSiteId); + insertDevice.setDeviceId(batteryId); + insertDevice.setDeviceName(StringUtils.defaultIfBlank(row.getBatteryDeviceName(), batteryId)); + insertDevice.setDeviceType(DeviceType.TCP.name()); + insertDevice.setCommunicationStatus(CommunicationStatus.OK.getCode()); + insertDevice.setDeviceCategory(DeviceCategory.BATTERY.getCode()); + insertDevice.setDeviceStatus(DeviceRunningStatus.OFFLINE.getCode()); + insertDevice.setWorkStatus(WorkStatus.NORMAL.getCode()); + insertDevice.setParentId(row.getClusterDeviceId()); + insertDevice.setDescription("single battery import"); + insertDevice.setCreatedAt(now); + insertDevice.setUpdatedAt(now); + emsDevicesMapper.insertEmsDevicesSetting(insertDevice); + deviceMap.put(batteryId, insertDevice); + result.setInsertedBatteryCount(result.getInsertedBatteryCount() + 1); + batterySetting = insertDevice; + } else { + boolean shouldUpdateBattery = false; + if (!StringUtils.equals(StringUtils.trimToEmpty(batterySetting.getParentId()), row.getClusterDeviceId())) { + batterySetting.setParentId(row.getClusterDeviceId()); + shouldUpdateBattery = true; + } + if (StringUtils.isNotBlank(row.getBatteryDeviceName()) && + !StringUtils.equals(StringUtils.trimToEmpty(batterySetting.getDeviceName()), row.getBatteryDeviceName())) { + batterySetting.setDeviceName(row.getBatteryDeviceName()); + shouldUpdateBattery = true; + } + if (shouldUpdateBattery) { + batterySetting.setUpdatedAt(now); + emsDevicesMapper.updateEmsDevicesSetting(batterySetting); + result.setUpdatedBatteryCount(result.getUpdatedBatteryCount() + 1); + } + } + + upsertSingleBatteryPointMatch(insertList, existingPointMatchMap, result, normalizedSiteId, batteryId, BATTERY_FIELD_VOLTAGE, row.getVoltagePointId(), operName); + upsertSingleBatteryPointMatch(insertList, existingPointMatchMap, result, normalizedSiteId, batteryId, BATTERY_FIELD_TEMPERATURE, row.getTemperaturePointId(), operName); + upsertSingleBatteryPointMatch(insertList, existingPointMatchMap, result, normalizedSiteId, batteryId, BATTERY_FIELD_SOC, row.getSocPointId(), operName); + upsertSingleBatteryPointMatch(insertList, existingPointMatchMap, result, normalizedSiteId, batteryId, BATTERY_FIELD_SOH, row.getSohPointId(), operName); + } + + if (!insertList.isEmpty()) { + emsSiteMonitorPointMatchMapper.insertBatch(insertList); + } + + refreshSingleBatteryImportCache(normalizedSiteId, importedBatteryIds); + + result.setCommitted(true); + result.setFailureRows(0); + result.setSuccessRows(sourceRows.size()); + result.setMessage(String.format("导入完成:成功 %d 行,新增单体 %d 个,更新单体 %d 个,新增映射 %d 条,更新映射 %d 条", + result.getSuccessRows(), + result.getInsertedBatteryCount(), + result.getUpdatedBatteryCount(), + result.getInsertedMappingCount(), + result.getUpdatedMappingCount())); + return result; + } + + private EmsDevicesSetting buildSiteDeviceQuery(String siteId) { + EmsDevicesSetting query = new EmsDevicesSetting(); + query.setSiteId(siteId); + return query; + } + + private SingleBatteryMonitorImportRowVo normalizeSingleBatteryImportRow(SingleBatteryMonitorImportRowVo row) { + SingleBatteryMonitorImportRowVo normalized = row == null ? new SingleBatteryMonitorImportRowVo() : row; + normalized.setSiteId(StringUtils.trimToEmpty(normalized.getSiteId())); + normalized.setStackDeviceId(StringUtils.trimToEmpty(normalized.getStackDeviceId())); + normalized.setClusterDeviceId(StringUtils.trimToEmpty(normalized.getClusterDeviceId())); + normalized.setBatteryDeviceId(StringUtils.trimToEmpty(normalized.getBatteryDeviceId())); + normalized.setBatteryDeviceName(StringUtils.trimToEmpty(normalized.getBatteryDeviceName())); + normalized.setVoltagePointId(StringUtils.trimToEmpty(normalized.getVoltagePointId())); + normalized.setTemperaturePointId(StringUtils.trimToEmpty(normalized.getTemperaturePointId())); + normalized.setSocPointId(StringUtils.trimToEmpty(normalized.getSocPointId())); + normalized.setSohPointId(StringUtils.trimToEmpty(normalized.getSohPointId())); + return normalized; + } + + private String validateSingleBatteryImportRow(String siteId, + SingleBatteryMonitorImportRowVo row, + Map deviceMap, + String duplicateKey, + String clusterDuplicateKey, + Set seenBatteryKeys, + Map seenSiteBatteryRowMap, + Map seenClusterBatteryRowMap) { + if (row == null) { + return "导入行为空,请检查模板内容"; + } + if (StringUtils.isBlank(row.getSiteId())) { + return "站点ID不能为空"; + } + if (!StringUtils.equals(siteId, row.getSiteId())) { + return String.format("站点ID不一致:当前导入站点为[%s],Excel中为[%s]", siteId, row.getSiteId()); + } + if (StringUtils.isBlank(row.getStackDeviceId())) { + return "电池堆编号不能为空"; + } + if (StringUtils.isBlank(row.getClusterDeviceId())) { + return "电池簇编号不能为空"; + } + if (StringUtils.isBlank(row.getBatteryDeviceId())) { + return "单体编号不能为空"; + } + if (StringUtils.isAllBlank(row.getVoltagePointId(), row.getTemperaturePointId(), row.getSocPointId(), row.getSohPointId())) { + return "电压/温度/SOC/SOH 点位ID至少需要填写一个"; + } + int currentRowNum = safeRowNum(row); + Integer duplicateClusterRowNum = seenClusterBatteryRowMap.putIfAbsent(clusterDuplicateKey, currentRowNum); + if (duplicateClusterRowNum != null) { + return String.format("同一电池簇[%s]下的单体编号[%s]重复,首次出现在第%d行", + row.getClusterDeviceId(), row.getBatteryDeviceId(), duplicateClusterRowNum); + } + if (!seenBatteryKeys.add(duplicateKey)) { + Integer duplicateSiteRowNum = seenSiteBatteryRowMap.get(duplicateKey); + return String.format("单体编号[%s]在当前导入文件中重复,首次出现在第%d行", + row.getBatteryDeviceId(), duplicateSiteRowNum == null ? safeRowNum(row) : duplicateSiteRowNum); + } + seenSiteBatteryRowMap.putIfAbsent(duplicateKey, currentRowNum); + EmsDevicesSetting stackSetting = deviceMap.get(row.getStackDeviceId()); + if (stackSetting == null || !StringUtils.equals(DeviceCategory.STACK.getCode(), StringUtils.trimToEmpty(stackSetting.getDeviceCategory()))) { + return String.format("电池堆编号[%s]不存在,请先确认设备已创建", row.getStackDeviceId()); + } + EmsDevicesSetting clusterSetting = deviceMap.get(row.getClusterDeviceId()); + if (clusterSetting == null || !StringUtils.equals(DeviceCategory.CLUSTER.getCode(), StringUtils.trimToEmpty(clusterSetting.getDeviceCategory()))) { + return String.format("电池簇编号[%s]不存在,请先确认设备已创建", row.getClusterDeviceId()); + } + if (!StringUtils.equals(StringUtils.trimToEmpty(clusterSetting.getParentId()), row.getStackDeviceId())) { + return String.format("电池簇[%s]不属于电池堆[%s],请检查堆簇关系", row.getClusterDeviceId(), row.getStackDeviceId()); + } + EmsDevicesSetting batterySetting = deviceMap.get(row.getBatteryDeviceId()); + if (batterySetting != null && !StringUtils.equals(DeviceCategory.BATTERY.getCode(), StringUtils.trimToEmpty(batterySetting.getDeviceCategory()))) { + return String.format("单体编号[%s]已存在,但对应设备类型不是单体电池", row.getBatteryDeviceId()); + } + return null; + } + + private void collectPointIds(Set pointIds, SingleBatteryMonitorImportRowVo row) { + if (row == null || pointIds == null) { + return; + } + if (StringUtils.isNotBlank(row.getVoltagePointId())) { + pointIds.add(row.getVoltagePointId()); + } + if (StringUtils.isNotBlank(row.getTemperaturePointId())) { + pointIds.add(row.getTemperaturePointId()); + } + if (StringUtils.isNotBlank(row.getSocPointId())) { + pointIds.add(row.getSocPointId()); + } + if (StringUtils.isNotBlank(row.getSohPointId())) { + pointIds.add(row.getSohPointId()); + } + } + + private String validateSingleBatteryImportPoints(SingleBatteryMonitorImportRowVo row, Map pointConfigMap) { + if (row == null) { + return "导入行为空,请检查模板内容"; + } + if (StringUtils.isNotBlank(row.getVoltagePointId()) && !pointConfigMap.containsKey(row.getVoltagePointId())) { + return String.format("电压点位ID[%s]不存在,请确认当前站点已配置该点位", row.getVoltagePointId()); + } + if (StringUtils.isNotBlank(row.getTemperaturePointId()) && !pointConfigMap.containsKey(row.getTemperaturePointId())) { + return String.format("温度点位ID[%s]不存在,请确认当前站点已配置该点位", row.getTemperaturePointId()); + } + if (StringUtils.isNotBlank(row.getSocPointId()) && !pointConfigMap.containsKey(row.getSocPointId())) { + return String.format("SOC点位ID[%s]不存在,请确认当前站点已配置该点位", row.getSocPointId()); + } + if (StringUtils.isNotBlank(row.getSohPointId()) && !pointConfigMap.containsKey(row.getSohPointId())) { + return String.format("SOH点位ID[%s]不存在,请确认当前站点已配置该点位", row.getSohPointId()); + } + return null; + } + + private int safeRowNum(SingleBatteryMonitorImportRowVo row) { + if (row == null || row.getRowNum() == null || row.getRowNum() < 1) { + return 0; + } + return row.getRowNum(); + } + + private SingleBatteryMonitorImportFailureVo buildSingleBatteryImportFailure(SingleBatteryMonitorImportRowVo row, String message) { + SingleBatteryMonitorImportFailureVo failure = new SingleBatteryMonitorImportFailureVo(); + if (row != null) { + failure.setRowNum(row.getRowNum()); + failure.setSiteId(row.getSiteId()); + failure.setStackDeviceId(row.getStackDeviceId()); + failure.setClusterDeviceId(row.getClusterDeviceId()); + failure.setBatteryDeviceId(row.getBatteryDeviceId()); + } + failure.setErrorMessage(message); + return failure; + } + + private void upsertSingleBatteryPointMatch(List insertList, + Map existingPointMatchMap, + SingleBatteryMonitorImportResultVo result, + String siteId, + String batteryId, + String fieldCode, + String pointId, + String operName) { + if (StringUtils.isBlank(pointId)) { + return; + } + String key = buildMatchKey(fieldCode, batteryId); + EmsSiteMonitorPointMatch existing = existingPointMatchMap.get(key); + if (existing == null) { + EmsSiteMonitorPointMatch insertItem = new EmsSiteMonitorPointMatch(); + insertItem.setSiteId(siteId); + insertItem.setFieldCode(fieldCode); + insertItem.setDeviceId(batteryId); + insertItem.setDataPoint(pointId); + insertItem.setFixedDataPoint(null); + insertItem.setUseFixedDisplay(0); + insertItem.setCreateBy(operName); + insertItem.setUpdateBy(operName); + insertList.add(insertItem); + result.setInsertedMappingCount(result.getInsertedMappingCount() + 1); + return; + } + boolean changed = !StringUtils.equals(StringUtils.trimToEmpty(existing.getDataPoint()), pointId) + || StringUtils.isNotBlank(existing.getFixedDataPoint()) + || (existing.getUseFixedDisplay() != null && existing.getUseFixedDisplay() != 0); + if (!changed) { + return; + } + existing.setDataPoint(pointId); + existing.setFixedDataPoint(null); + existing.setUseFixedDisplay(0); + existing.setUpdateBy(operName); + emsSiteMonitorPointMatchMapper.updateEmsSiteMonitorPointMatch(existing); + result.setUpdatedMappingCount(result.getUpdatedMappingCount() + 1); + } + + private void refreshSingleBatteryImportCache(String siteId, Set batteryIds) { + redisCache.deleteObject(RedisKeyConstants.INIT_DEVICE_INFO); + if (!CollectionUtils.isEmpty(batteryIds)) { + for (String batteryId : batteryIds) { + if (StringUtils.isBlank(batteryId)) { + continue; + } + redisCache.deleteObject(RedisKeyConstants.DEVICE_SETTING + siteId + "_" + batteryId); + } + } + redisCache.deleteObject(buildSiteMonitorPointMatchRedisKey(siteId)); + clearSiteMonitorLatestCache(siteId); + projectDisplayCache.remove(siteId); + } + @Override public List getSiteMonitorProjectDisplay(String siteId) { String normalizedSiteId = StringUtils.trim(siteId); diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointConfigServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointConfigServiceImpl.java index 09e9515..8f4b8c0 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointConfigServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsPointConfigServiceImpl.java @@ -306,7 +306,7 @@ public class EmsPointConfigServiceImpl implements IEmsPointConfigService { } String siteId = StringUtils.trim(request.getSiteId()); String pointId = StringUtils.trim(request.getPointId()); - String deviceId = StringUtils.trimToEmpty(request.getDeviceId()); + String deviceId = StringUtils.isBlank(request.getDeviceId()) ? "SITE_CALC" : StringUtils.trim(request.getDeviceId()); EmsPointConfig targetConfig = selectPointConfigByExactPointId(siteId, pointId); if (targetConfig == null || !"calc".equalsIgnoreCase(StringUtils.defaultString(targetConfig.getPointType()))) { @@ -317,7 +317,8 @@ public class EmsPointConfigServiceImpl implements IEmsPointConfigService { throw new ServiceException("计算点缺少表达式,无法生成数据"); } - List payloads = buildCalcRecentPayloads(siteId, deviceId, pointId, expression); + Integer decimalScale = targetConfig.getDecimalScale(); + List payloads = buildCalcRecentPayloads(siteId, deviceId, pointId, expression, decimalScale); if (payloads.isEmpty()) { throw new ServiceException("未生成有效数据,请检查表达式依赖点是否有历史数据"); } @@ -325,7 +326,7 @@ public class EmsPointConfigServiceImpl implements IEmsPointConfigService { return String.format("已生成点位 %s 最近7天数据,共 %d 条", pointId, payloads.size()); } - private List buildCalcRecentPayloads(String siteId, String deviceId, String pointId, String expression) { + private List buildCalcRecentPayloads(String siteId, String deviceId, String pointId, String expression, Integer decimalScale) { CompiledExpression compiledExpression = new CompiledExpression(expression); List evaluateTimes = buildEvaluateTimes(expression); if (evaluateTimes.isEmpty()) { @@ -348,7 +349,9 @@ public class EmsPointConfigServiceImpl implements IEmsPointConfigService { BigDecimal value; try { prepareAutoPeriodDiffContextValues(expression, contextValues, evaluateTime, periodDiffStateMap); - value = compiledExpression.evaluate(contextValues).asNumber().setScale(4, RoundingMode.HALF_UP); + value = compiledExpression.evaluate(contextValues).asNumber(); + int scale = (decimalScale != null && decimalScale >= 0) ? decimalScale : 4; + value = value.setScale(scale, RoundingMode.HALF_UP); } catch (IllegalArgumentException ex) { continue; } @@ -1758,6 +1761,7 @@ public class EmsPointConfigServiceImpl implements IEmsPointConfigService { pointConfig.setModbusDataType(getString(valueList, headerIndex, "modbus_data_type")); pointConfig.setModbusReadOrder(getInteger(valueList, headerIndex, "modbus_read_order", lineNo)); pointConfig.setModbusGroup(getString(valueList, headerIndex, "modbus_group")); + pointConfig.setDecimalScale(getInteger(valueList, headerIndex, "decimal_scale", lineNo)); pointConfig.setRemark(getString(valueList, headerIndex, "remark")); normalizeAndValidatePointConfig(pointConfig); applyCollectDefaultsForInsert(pointConfig); @@ -1921,6 +1925,9 @@ public class EmsPointConfigServiceImpl implements IEmsPointConfigService { case "modbusgroup": case "modbus分组": return "modbus_group"; + case "decimalscale": + case "小数位数": + return "decimal_scale"; case "remark": case "备注": return "remark"; diff --git a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsStatsReportServiceImpl.java b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsStatsReportServiceImpl.java index d730df3..ab873b9 100644 --- a/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsStatsReportServiceImpl.java +++ b/ems-system/src/main/java/com/xzzn/ems/service/impl/EmsStatsReportServiceImpl.java @@ -28,6 +28,7 @@ import com.xzzn.ems.mapper.EmsDevicesSettingMapper; import com.xzzn.ems.mapper.EmsEnergyPriceConfigMapper; import com.xzzn.ems.mapper.EmsPcsDataMapper; import com.xzzn.ems.service.IEmsStatsReportService; +import com.xzzn.ems.service.ISysBizRemarkService; import java.math.BigDecimal; import java.math.RoundingMode; @@ -99,6 +100,40 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService private EmsDailyEnergyDataMapper emsDailyEnergyDataMapper; @Autowired private EmsEnergyPriceConfigMapper emsEnergyPriceConfigMapper; + @Autowired + private ISysBizRemarkService sysBizRemarkService; + + private static final String STATS_REPORT_BIZ_TYPE = "stats_report"; + private static final String AMMETER_REPORT_KEY = "DBBB"; + private static final String REVENUE_REPORT_KEY = "SYBB"; + + private String buildRemarkBizKey(String siteId, String dataTime) { + String safeSiteId = siteId == null ? "" : siteId.trim(); + String safeDate = dataTime == null ? "" : dataTime.trim(); + return safeSiteId + "_" + safeDate; + } + + private void fillAmmeterRemarks(String siteId, String reportKey, List rows) { + if (CollectionUtils.isEmpty(rows)) { + return; + } + List bizKeys = rows.stream() + .map(row -> buildRemarkBizKey(siteId, row.getDataTime())) + .collect(Collectors.toList()); + Map remarkMap = sysBizRemarkService.getRemarkMap(STATS_REPORT_BIZ_TYPE, reportKey, bizKeys); + rows.forEach(row -> row.setRemark(remarkMap.getOrDefault(buildRemarkBizKey(siteId, row.getDataTime()), ""))); + } + + private void fillRevenueRemarks(String siteId, String reportKey, List rows) { + if (CollectionUtils.isEmpty(rows)) { + return; + } + List bizKeys = rows.stream() + .map(row -> buildRemarkBizKey(siteId, row.getDataTime())) + .collect(Collectors.toList()); + Map remarkMap = sysBizRemarkService.getRemarkMap(STATS_REPORT_BIZ_TYPE, reportKey, bizKeys); + rows.forEach(row -> row.setRemark(remarkMap.getOrDefault(buildRemarkBizKey(siteId, row.getDataTime()), ""))); + } // 电量指标 @Override @@ -374,6 +409,7 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService } dataList.add(totalVo);*/ + fillAmmeterRemarks(requestVo.getSiteId(), AMMETER_REPORT_KEY, dataList); return dataList; } @@ -447,6 +483,7 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService weatherMissingCount, allPriceZeroCount); + fillRevenueRemarks(requestVo.getSiteId(), REVENUE_REPORT_KEY, resultList); return resultList; } @@ -707,6 +744,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService cell3.setCellValue("放电量"); Cell cell4 = row1.createCell(11); cell4.setCellValue("效率"); + Cell cell5Top = row1.createCell(12); + cell5Top.setCellValue("备注"); // 合并充电量列 CellRangeAddress mergeRegion1 = new CellRangeAddress(0, 0, 1, 5); @@ -742,6 +781,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService cell15.setCellValue("总"); Cell cell16 = row2.createCell(11); cell16.setCellValue(""); + Cell cell17 = row2.createCell(12); + cell17.setCellValue("备注"); // 设置背景颜色 CellStyle headerStyle = workbook.createCellStyle(); @@ -821,6 +862,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService dataCell11.setCellValue(ammeterStatisVo.getReActiveTotalKwh().doubleValue()); Cell dataCell12 = dataRow.createCell(11); dataCell12.setCellValue(ammeterStatisVo.getEffect().doubleValue()); + Cell dataCell13 = dataRow.createCell(12); + dataCell13.setCellValue(ammeterStatisVo.getRemark() == null ? "" : ammeterStatisVo.getRemark()); // 根据行号设置背景色 if (i % 2 == 0) { @@ -868,7 +911,9 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService Cell cell3 = row1.createCell(8); cell3.setCellValue("放电价格"); Cell cell4 = row1.createCell(13); - cell4.setCellValue(""); + cell4.setCellValue("实际收益"); + Cell cell5Top = row1.createCell(14); + cell5Top.setCellValue("备注"); // 合并充电量列 CellRangeAddress mergeRegion1 = new CellRangeAddress(0, 0, 3, 7); @@ -908,6 +953,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService cell17.setCellValue("总"); Cell cell18 = row2.createCell(13); cell18.setCellValue("实际收益"); + Cell cell19 = row2.createCell(14); + cell19.setCellValue("备注"); // 设置背景颜色 CellStyle headerStyle = workbook.createCellStyle(); @@ -1002,6 +1049,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService dataCell13.setCellValue(ammeterRevenueStatisVo.getReActiveTotalPrice().doubleValue()); Cell dataCell14 = dataRow.createCell(13); dataCell14.setCellValue(ammeterRevenueStatisVo.getActualRevenue().doubleValue()); + Cell dataCell15 = dataRow.createCell(14); + dataCell15.setCellValue(ammeterRevenueStatisVo.getRemark() == null ? "" : ammeterRevenueStatisVo.getRemark()); // 根据行号设置背景色 if (i % 2 == 0) { @@ -1059,6 +1108,8 @@ public class EmsStatsReportServiceImpl implements IEmsStatsReportService lastRowCell13.setCellValue(reActiveTotalPrice.doubleValue()); Cell lastRowCell14 = lastRow.createCell(13); lastRowCell14.setCellValue(actualRevenue.doubleValue()); + Cell lastRowCell15 = lastRow.createCell(14); + lastRowCell15.setCellValue(""); Iterator lastRowCellIterator = lastRow.cellIterator(); while (lastRowCellIterator.hasNext()) { int i = lastRowCellIterator.next().getColumnIndex(); diff --git a/ems-system/src/main/resources/mapper/ems/EmsDailyEnergyDataMapper.xml b/ems-system/src/main/resources/mapper/ems/EmsDailyEnergyDataMapper.xml index dbcadb5..0785e57 100644 --- a/ems-system/src/main/resources/mapper/ems/EmsDailyEnergyDataMapper.xml +++ b/ems-system/src/main/resources/mapper/ems/EmsDailyEnergyDataMapper.xml @@ -346,7 +346,7 @@ group by t.data_date, COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) < 5 THEN 1 ELSE 0 END), COALESCE(NULLIF(TRIM(w.weather_desc), ''), '--') - order by t.data_date desc + order by t.data_date asc diff --git a/ems-system/src/main/resources/mapper/ems/EmsPointConfigMapper.xml b/ems-system/src/main/resources/mapper/ems/EmsPointConfigMapper.xml index f3d1d68..5ff952f 100644 --- a/ems-system/src/main/resources/mapper/ems/EmsPointConfigMapper.xml +++ b/ems-system/src/main/resources/mapper/ems/EmsPointConfigMapper.xml @@ -28,6 +28,7 @@ + @@ -39,7 +40,7 @@ select id, point_id, site_id, device_category, device_id, point_name, data_key, point_desc, register_address, data_unit, data_a, data_k, data_b, data_bit, is_alarm, point_type, calc_expression, collect_enabled, collect_source, modbus_register_type, modbus_data_type, modbus_read_order, modbus_group, - create_by, create_time, update_by, update_time, remark + decimal_scale, create_by, create_time, update_by, update_time, remark from ems_point_config @@ -92,6 +93,7 @@ modbus_data_type, modbus_read_order, modbus_group, + decimal_scale, create_by, create_time, update_by, @@ -121,6 +123,7 @@ #{modbusDataType}, #{modbusReadOrder}, #{modbusGroup}, + #{decimalScale}, #{createBy}, #{createTime}, #{updateBy}, @@ -134,7 +137,7 @@ point_id, site_id, device_category, device_id, point_name, data_key, point_desc, register_address, data_unit, data_a, data_k, data_b, data_bit, is_alarm, point_type, calc_expression, collect_enabled, collect_source, modbus_register_type, modbus_data_type, modbus_read_order, modbus_group, - create_by, create_time, update_by, update_time, remark + decimal_scale, create_by, create_time, update_by, update_time, remark ) values @@ -161,6 +164,7 @@ #{item.modbusDataType}, #{item.modbusReadOrder}, #{item.modbusGroup}, + #{item.decimalScale}, #{item.createBy}, now(), #{item.updateBy}, @@ -195,6 +199,7 @@ modbus_data_type = #{modbusDataType}, modbus_read_order = #{modbusReadOrder}, modbus_group = #{modbusGroup}, + decimal_scale = #{decimalScale}, update_by = #{updateBy}, update_time = #{updateTime}, remark = #{remark}, @@ -226,6 +231,7 @@ modbus_data_type = #{modbusDataType}, modbus_read_order = #{modbusReadOrder}, modbus_group = #{modbusGroup}, + decimal_scale = #{decimalScale}, update_by = #{updateBy}, update_time = now(), remark = #{remark} @@ -259,13 +265,13 @@ point_id, site_id, device_category, device_id, point_name, data_key, point_desc, register_address, data_unit, data_a, data_k, data_b, data_bit, is_alarm, point_type, calc_expression, collect_enabled, collect_source, modbus_register_type, modbus_data_type, modbus_read_order, modbus_group, - create_by, create_time, update_by, update_time, remark + decimal_scale, create_by, create_time, update_by, update_time, remark ) select concat('PT_', replace(uuid(), '-', '')), #{targetSiteId}, device_category, device_id, point_name, data_key, point_desc, register_address, data_unit, data_a, data_k, data_b, data_bit, is_alarm, point_type, calc_expression, collect_enabled, collect_source, modbus_register_type, modbus_data_type, modbus_read_order, modbus_group, - #{operName}, now(), #{operName}, now(), remark + decimal_scale, #{operName}, now(), #{operName}, now(), remark from ems_point_config where site_id = #{templateSiteId} diff --git a/ems-system/src/main/resources/mapper/ems/EmsSiteMonitorPointMatchMapper.xml b/ems-system/src/main/resources/mapper/ems/EmsSiteMonitorPointMatchMapper.xml index e01124b..3f520d1 100644 --- a/ems-system/src/main/resources/mapper/ems/EmsSiteMonitorPointMatchMapper.xml +++ b/ems-system/src/main/resources/mapper/ems/EmsSiteMonitorPointMatchMapper.xml @@ -54,4 +54,14 @@ + + update ems_site_monitor_point_match + set data_point = #{dataPoint}, + fixed_data_point = #{fixedDataPoint}, + use_fixed_display = #{useFixedDisplay}, + update_by = #{updateBy}, + update_time = now() + where id = #{id} + +