Compare commits

18 Commits

Author SHA1 Message Date
hzj
27841f0f4e 修改时间同步频次为10分钟 2025-11-19 15:41:14 +08:00
hzj
35cd056870 用户上送逻辑修改 2025-11-17 14:42:27 +08:00
3d29e5a64c 北京暂降平台短信功能加固 2025-11-17 14:37:48 +08:00
hzj
a7d34296c7 用户上送逻辑修改 2025-11-17 11:14:03 +08:00
hzj
cf7a2e04d5 用户上送逻辑修改 2025-11-14 15:12:53 +08:00
hzj
8f0a739564 添加字段 2025-11-14 14:37:00 +08:00
hzj
a627125a9e 添加字段 2025-11-14 14:20:16 +08:00
ab1c777432 北京暂降平台短信功能加固 2025-11-14 14:18:40 +08:00
000e201ed7 北京暂降平台短信功能加固 2025-11-13 16:04:45 +08:00
hzj
9501880933 缓存手动刷新接口 2025-11-12 13:46:26 +08:00
c9896fd52d 北京暂降平台 2025-11-11 11:13:55 +08:00
hzj
2524b13661 暂态事件同步排除以同步的事件 2025-11-11 11:00:04 +08:00
hzj
55f03e3244 修改前端显示bug 2025-11-10 14:12:53 +08:00
cdf
8f5d9a13d8 bug修改 2025-11-05 15:39:35 +08:00
hzj
a8c1498738 变电站绑定 2025-11-04 13:57:15 +08:00
00fabe3b6b 1.无锡地图电站打点接口 2025-11-03 10:24:01 +08:00
hzj
37f95daaf0 北京暂降10月出差开发版本 2025-11-03 09:02:44 +08:00
hzj
005f73e19d 北京暂降10月出差开发版本 2025-11-03 09:02:32 +08:00
93 changed files with 2758 additions and 569 deletions

View File

@@ -49,11 +49,11 @@ public class RespDataResultServiceImpl extends ServiceImpl<RespDataResultMapper,
@Override
public List<ResponsibilityResult> displayHistoryData(String id, Integer time) {
List<ResponsibilityResult> responsibilityResults = new ArrayList<>();
//if (Objects.isNull(time)) {
RespData respDataQuery = respDataService.getById(id);
String[] split = respDataQuery.getDataTimes().split(StrPool.COMMA);
RespData respDataQuery = respDataService.getById(id);
String[] split = respDataQuery.getDataTimes().split(StrPool.COMMA);
if (Objects.isNull(time)) {
time = Integer.parseInt(split[0]);
//}
}
LambdaQueryWrapper<RespDataResult> respDataResultLambdaQueryWrapper = new LambdaQueryWrapper<>();
respDataResultLambdaQueryWrapper.eq(RespDataResult::getResDataId, id)
.eq(RespDataResult::getTime, time);

View File

@@ -10,7 +10,7 @@ import com.njcn.product.diagram.LedgerScale.pojo.dto.EventSourceDTO;
import com.njcn.product.diagram.LedgerScale.pojo.dto.LedgerScaleDTO;
import com.njcn.product.diagram.LedgerScale.pojo.vo.EventDetailVO;
import com.njcn.product.diagram.LedgerScale.pojo.vo.EventLedgerVO;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.LedgerBaseInfo;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.PqStation;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.TerminalShowVO;
import com.njcn.product.diagram.LedgerScale.service.LedgerScaleService;
import com.njcn.product.terminal.mysqlTerminal.pojo.param.LargeScreenCountParam;
@@ -94,12 +94,12 @@ public class LedgerScaleController extends BaseController {
@OperateInfo(info = LogEnum.SYSTEM_COMMON)
@GetMapping("/clickImage")
@PostMapping("/clickImage")
@ApiOperation("一次接线图点击事件")
@ApiImplicitParam(name = "lineId", value = "查询参数", required = true)
public HttpResult<EventLedgerVO> clickImage(@RequestParam("lineId")String lineId) {
public HttpResult<EventLedgerVO> clickImage(@RequestBody LargeScreenCountParam param) {
String methodDescribe = getMethodDescribe("clickImage");
EventLedgerVO result = ledgerScaleService.clickImage(lineId);
EventLedgerVO result = ledgerScaleService.clickImage(param);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
@@ -168,4 +168,16 @@ public class LedgerScaleController extends BaseController {
}
@OperateInfo(info = LogEnum.SYSTEM_COMMON)
@PostMapping("/stationMap")
@ApiOperation("获取变电站详情")
@ApiImplicitParam(name = "param", value = "查询参数", required = true)
public HttpResult<List<PqStation>> stationMap(@RequestBody LargeScreenCountParam param) {
String methodDescribe = getMethodDescribe("stationMap");
List<PqStation> result = ledgerScaleService.stationMap(param);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
}

View File

@@ -6,7 +6,7 @@ import com.njcn.product.diagram.LedgerScale.pojo.dto.EventSourceDTO;
import com.njcn.product.diagram.LedgerScale.pojo.dto.LedgerScaleDTO;
import com.njcn.product.diagram.LedgerScale.pojo.vo.EventDetailVO;
import com.njcn.product.diagram.LedgerScale.pojo.vo.EventLedgerVO;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.LedgerBaseInfo;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.PqStation;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.TerminalShowVO;
import com.njcn.product.terminal.mysqlTerminal.pojo.param.LargeScreenCountParam;
@@ -30,8 +30,7 @@ public interface LedgerScaleService {
List<EventLedgerVO> hasUpEventList(LargeScreenCountParam param);
EventLedgerVO clickImage(String lineId);
EventLedgerVO clickImage(LargeScreenCountParam param);
Page<EventDetailVO> eventList(LargeScreenCountParam param);
Page<EventDetailVO> eventListByLineId(LargeScreenCountParam param);
@@ -44,4 +43,6 @@ public interface LedgerScaleService {
List<CustomerResponsibility> harmOneImage(String id, Integer time);
List<PqStation> stationMap(LargeScreenCountParam param);
}

View File

@@ -3,7 +3,6 @@ package com.njcn.product.diagram.LedgerScale.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
@@ -20,24 +19,25 @@ import com.njcn.product.advance.eventSource.pojo.po.RmpEventDetailAssPO;
import com.njcn.product.advance.harmonicUp.mapper.UpHarmonicDetailMapper;
import com.njcn.product.advance.harmonicUp.pojo.po.UpHarmonicDetail;
import com.njcn.product.advance.responsility.mapper.RespDataResultMapper;
import com.njcn.product.advance.responsility.pojo.dto.CustomerData;
import com.njcn.product.advance.responsility.pojo.dto.CustomerResponsibility;
import com.njcn.product.advance.responsility.pojo.dto.ResponsibilityResult;
import com.njcn.product.advance.responsility.pojo.po.RespDataResult;
import com.njcn.product.cnzutai.zutai.pojo.po.CsConfigurationPO;
import com.njcn.product.cnzutai.zutai.pojo.po.CsSubConfigurationAss;
import com.njcn.product.cnzutai.zutai.service.CsConfigurationService;
import com.njcn.product.cnzutai.zutai.service.CsSubConfigurationAssService;
import com.njcn.product.diagram.LedgerScale.pojo.dto.EventSourceDTO;
import com.njcn.product.diagram.LedgerScale.pojo.dto.LedgerScaleDTO;
import com.njcn.product.diagram.LedgerScale.pojo.vo.EventDetailVO;
import com.njcn.product.diagram.LedgerScale.pojo.vo.EventLedgerVO;
import com.njcn.product.terminal.mysqlTerminal.mapper.LineMapper;
import com.njcn.product.terminal.mysqlTerminal.mapper.UserReportPOMapper;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.UserReportPO;
import com.njcn.product.terminal.mysqlTerminal.mapper.*;
import com.njcn.product.terminal.mysqlTerminal.pojo.enums.LineBaseEnum;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.Line;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.PqStation;
import com.njcn.product.terminal.mysqlTerminal.pojo.vo.TerminalShowVO;
import com.njcn.product.diagram.LedgerScale.service.LedgerScaleService;
import com.njcn.product.system.dict.mapper.DictDataMapper;
import com.njcn.product.system.dict.pojo.enums.DicDataTypeEnum;
import com.njcn.product.system.dict.pojo.po.DictData;
import com.njcn.product.terminal.mysqlTerminal.mapper.LedgerScaleMapper;
import com.njcn.product.terminal.mysqlTerminal.mapper.RmpEventDetailMapper;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.LedgerBaseInfo;
import com.njcn.product.terminal.mysqlTerminal.pojo.enums.RunFlagEnum;
import com.njcn.product.terminal.mysqlTerminal.pojo.param.LargeScreenCountParam;
@@ -51,7 +51,6 @@ import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -80,9 +79,10 @@ public class LedgerScaleServiceImpl implements LedgerScaleService {
private final RespDataResultMapper respDataResultMapper;
private final FileStorageUtil fileStorageUtil;
private final UserReportPOMapper userReportPOMapper;
private final UpHarmonicDetailMapper upHarmonicDetailMapper;
private final PqStationMapper pqStationMapper;
private final CsSubConfigurationAssService csSubConfigurationAssService;
private final CsConfigurationService csConfigurationService;
@Override
public LedgerScaleDTO ledgerScaleStatistic(LargeScreenCountParam param) {
@@ -281,16 +281,18 @@ public class LedgerScaleServiceImpl implements LedgerScaleService {
}
@Override
public EventLedgerVO clickImage(String lineId) {
List<LedgerBaseInfo> ledgerBaseInfoList = ledgerScaleMapper.getLedgerBaseInfo(Stream.of(lineId).collect(Collectors.toList()));
public EventLedgerVO clickImage(LargeScreenCountParam param) {
List<LedgerBaseInfo> ledgerBaseInfoList = ledgerScaleMapper.getLedgerBaseInfo(Stream.of(param.getLineId()).collect(Collectors.toList()));
if (CollUtil.isEmpty(ledgerBaseInfoList)) {
throw new BusinessException(CommonResponseEnum.FAIL, "当前节点未查询到测点信息");
}
EventLedgerVO eventLedgerVO = new EventLedgerVO();
BeanUtil.copyProperties(ledgerBaseInfoList.get(0), eventLedgerVO);
DateTime start = DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime()));
DateTime end = DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime()));
LambdaQueryWrapper<RmpEventDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(RmpEventDetailPO::getLineId, lineId);
lambdaQueryWrapper.eq(RmpEventDetailPO::getLineId, param.getLineId()).between(RmpEventDetailPO::getStartTime, start, end).orderByDesc(RmpEventDetailPO::getStartTime);;
List<RmpEventDetailPO> rmpEventDetailPOList = rmpEventDetailMapper.selectList(lambdaQueryWrapper);
List<DictData> dictDataList = dictDataMapper.getDicDataByTypeCode(DicDataTypeEnum.EVENT_STATIS.getCode());
@@ -301,6 +303,7 @@ public class LedgerScaleServiceImpl implements LedgerScaleService {
}
@Override
public Page<EventDetailVO> eventList(LargeScreenCountParam param) {
Page<EventDetailVO> result = new Page<>(PageFactory.getPageNum(param), PageFactory.getPageSize(param));
@@ -489,5 +492,42 @@ public class LedgerScaleServiceImpl implements LedgerScaleService {
return new ArrayList<>();
}
@Override
public List<PqStation> stationMap(LargeScreenCountParam param) {
List<PqStation> result = new ArrayList<>();
List<String> runIds = commGeneralService.getRunLineIdsByDept(param.getDeptId());
if(CollUtil.isEmpty(runIds)){
return result;
}
List<Line> lineList = lineMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getId,runIds));
List<String> stationIds = lineList.stream().map(it->it.getPids().split(StrUtil.COMMA)[LineBaseEnum.SUB_LEVEL.getCode()]).distinct().collect(Collectors.toList());
List<Line> stationResult = lineMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getId,stationIds));
List<String> ids = stationResult.stream().map(Line::getId).distinct().collect(Collectors.toList());
List<PqStation> pqStationList = pqStationMapper.selectList(new LambdaQueryWrapper<PqStation>().in(PqStation::getId,ids));
Map<String, PqStation> substationMap = pqStationList.stream().collect(Collectors.toMap(PqStation::getId, po->po));
stationResult.forEach(it->{
PqStation pqStation = new PqStation();
if(substationMap.containsKey(it.getId())){
PqStation tem = substationMap.get(it.getId());
pqStation.setLng(tem.getLng());
pqStation.setLat(tem.getLat());
}
pqStation.setId(it.getId());
pqStation.setName(it.getName());
CsSubConfigurationAss one = csSubConfigurationAssService.lambdaQuery().eq(CsSubConfigurationAss::getSubId, it.getId()).one();
if(Objects.isNull(one)){
pqStation.setBindFlag(false);
}else {
CsConfigurationPO csConfigurationPO = csConfigurationService.lambdaQuery().eq(CsConfigurationPO::getId, one.getConfigId()).one();
pqStation.setBindFlag(true);
pqStation.setConfigId(csConfigurationPO.getId());
pqStation.setConfigName(csConfigurationPO.getName());
}
result.add(pqStation);
});
return result;
}
}

View File

@@ -1,10 +0,0 @@
package com.njcn.product.terminal.device.service;
import com.njcn.product.terminal.device.pojo.dto.OracleLedgerTreeDTO;
import java.util.List;
public interface LedgerTreeService {
List<OracleLedgerTreeDTO> getTree();
}

View File

@@ -1,12 +1,10 @@
package com.njcn.product.terminal.mysqlTerminal.controller;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.dto.SimpleDTO;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.product.terminal.device.service.LedgerTreeService;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.LedgerTreeDTO;
import com.njcn.product.terminal.mysqlTerminal.pojo.enums.StatisticsEnum;
import com.njcn.product.terminal.mysqlTerminal.pojo.param.DeviceInfoParam;

View File

@@ -5,7 +5,6 @@ import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.product.terminal.device.pojo.dto.OracleLedgerTreeDTO;
import com.njcn.product.terminal.mysqlTerminal.pojo.dto.LedgerTreeDTO;
import com.njcn.product.terminal.mysqlTerminal.service.LineService;
import com.njcn.web.controller.BaseController;

View File

@@ -0,0 +1,8 @@
package com.njcn.product.terminal.mysqlTerminal.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.PqStation;
public interface PqStationMapper extends BaseMapper<PqStation> {
}

View File

@@ -93,7 +93,7 @@
and (dev.name like CONCAT('%', #{searchValue}, '%')
or a.name like CONCAT('%', #{searchValue}, '%'))
</if>
order by c.name,a.name
<!-- order by c.name,a.name-->
</select>
<select id="getLineList" resultType="TerminalShowVO">
@@ -131,7 +131,7 @@
or a.name like CONCAT('%', #{searchValue}, '%')
or c.name like CONCAT('%', #{searchValue}, '%'))
</if>
order by c.name,a.name
<!-- order by c.name,a.name-->
</select>
<select id="getMonitorDetail" resultType="com.njcn.product.terminal.mysqlTerminal.pojo.dto.LineDevGetDTO">

View File

@@ -1,6 +1,5 @@
package com.njcn.product.terminal.mysqlTerminal.pojo.dto;
import com.njcn.product.terminal.device.pojo.dto.OracleLedgerTreeDTO;
import lombok.Data;
import java.util.ArrayList;

View File

@@ -0,0 +1,58 @@
package com.njcn.product.terminal.mysqlTerminal.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* <p>
*
* </p>
*
* @author cdf
* @since 2022-01-04
*/
@Data
@TableName("pq_substation")
public class PqStation implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 变电站序号
*/
private String id;
/**
* 电压等级Id字典表
*/
private String scale;
/**
* 经度
*/
private BigDecimal lng;
/**
* 纬度
*/
private BigDecimal lat;
@TableField(exist = false)
private String name;
@TableField(exist = false)
private boolean bindFlag;
@TableField(exist = false)
private String configId;
@TableField(exist = false)
private String configName;
}

View File

@@ -1,7 +1,7 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.po.PqDeviceDetail;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqDeviceDetail;
/**
* CN_Gather

View File

@@ -1,11 +1,11 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.product.terminal.device.pojo.dto.DeviceDTO;
import com.njcn.product.terminal.device.pojo.dto.DeviceDeptDTO;
import com.njcn.product.terminal.device.pojo.po.PqDevice;
import com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDTO;
import com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDeptDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqDevice;
import org.apache.ibatis.annotations.Param;
import java.util.List;

View File

@@ -1,7 +1,7 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.po.PqGdCompany;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqGdCompany;
/**
*

View File

@@ -1,8 +1,8 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.terminal.device.pojo.po.PqLine;
import com.njcn.product.terminal.oracleDevice.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqLine;
import org.apache.ibatis.annotations.Param;
import java.util.List;

View File

@@ -1,7 +1,7 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.po.PqLinedetail;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqLinedetail;
import org.apache.ibatis.annotations.Mapper;
@Mapper

View File

@@ -1,9 +1,9 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.dto.SubstationDTO;
import com.njcn.product.terminal.device.pojo.po.PqSubstation;
import com.njcn.product.terminal.oracleDevice.pojo.dto.SubstationDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqSubstation;
import org.apache.ibatis.annotations.Param;
import java.util.List;

View File

@@ -1,7 +1,7 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.po.PqsDeptsline;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqsDeptsline;
/**
*

View File

@@ -1,8 +1,8 @@
package com.njcn.product.terminal.device.mapper;
package com.njcn.product.terminal.oracleDevice.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.terminal.device.pojo.po.PqsStationMap;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqsStationMap;
/**
*

View File

@@ -1,7 +1,7 @@
<?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.njcn.product.terminal.device.mapper.PqDeviceMapper">
<resultMap id="BaseResultMap" type="com.njcn.product.terminal.device.pojo.po.PqDevice">
<resultMap id="BaseResultMap" type="com.njcn.product.terminal.oracleDevice.pojo.po.PqDevice">
<!--@mbg.generated-->
<!--@Table PQ_DEVICE-->
<id column="DEV_INDEX" jdbcType="DECIMAL" property="devIndex" />
@@ -28,7 +28,7 @@
NODE_INDEX, PORTID, DEVFLAG, DEV_SERIES, DEV_KEY, IP, DEVMODEL, CALLFLAG, DATATYPE
</sql>
<select id="queryListByIds" resultType="com.njcn.product.terminal.device.pojo.dto.DeviceDTO">
<select id="queryListByIds" resultType="com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDTO">
select
pq_device.dev_index devId,
pq_device.name devName,
@@ -52,7 +52,7 @@
</foreach>
</select>
<select id="selectDeviceDTOPage" resultType="com.njcn.product.terminal.device.pojo.dto.DeviceDTO">
<select id="selectDeviceDTOPage" resultType="com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDTO">
SELECT DISTINCT
pq_device.dev_index devId,

View File

@@ -1,7 +1,7 @@
<?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.njcn.product.terminal.device.mapper.PqLineMapper">
<resultMap id="BaseResultMap" type="com.njcn.product.terminal.device.pojo.po.PqLine">
<resultMap id="BaseResultMap" type="com.njcn.product.terminal.oracleDevice.pojo.po.PqLine">
<!--@mbg.generated-->
<!--@Table PQ_LINE-->
<id column="LINE_INDEX" jdbcType="DECIMAL" property="lineIndex" />
@@ -29,7 +29,7 @@
</sql>
<select id="getBaseLineInfo" resultType="com.njcn.product.terminal.device.pojo.dto.LedgerBaseInfoDTO">
<select id="getBaseLineInfo" resultType="com.njcn.product.terminal.oracleDevice.pojo.dto.LedgerBaseInfoDTO">
WITH temp AS(
select PQ_USER_LINE_ASS.LINE_INDEX LINE_INDEX,listagg(PQ_USER_LEDGER.CUSTOMER_NAME,';') within GROUP (order by PQ_USER_LEDGER.CUSTOMER_NAME) objName from PQ_USER_LINE_ASS ,PQ_USER_LEDGER where PQ_USER_LINE_ASS.USER_INDEX=PQ_USER_LEDGER.ID group by PQ_USER_LINE_ASS.LINE_INDEX
@@ -62,7 +62,7 @@ where 1=1
</select>
<select id="getBaseLedger" resultType="com.njcn.product.terminal.device.pojo.dto.LedgerBaseInfoDTO">
<select id="getBaseLedger" resultType="com.njcn.product.terminal.oracleDevice.pojo.dto.LedgerBaseInfoDTO">
select
PQ_GDINFORMATION.name gdName,
pq_line.GD_INDEX gdIndex,

View File

@@ -1,7 +1,7 @@
<?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.njcn.product.terminal.device.mapper.PqSubstationMapper">
<resultMap id="BaseResultMap" type="com.njcn.product.terminal.device.pojo.po.PqSubstation">
<resultMap id="BaseResultMap" type="com.njcn.product.terminal.oracleDevice.pojo.po.PqSubstation">
<!--@mbg.generated-->
<!--@Table PQ_SUBSTATION-->
<id column="SUB_INDEX" jdbcType="DECIMAL" property="subIndex" />
@@ -14,7 +14,7 @@
SUB_INDEX, GD_INDEX, "NAME", "SCALE"
</sql>
<select id="queryListByIds" resultType="com.njcn.product.terminal.device.pojo.dto.SubstationDTO">
<select id="queryListByIds" resultType="com.njcn.product.terminal.oracleDevice.pojo.dto.SubstationDTO">
select
PQ_SUBSTATION.sub_index stationId,
PQ_SUBSTATION.name stationName,

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.dto;
package com.njcn.product.terminal.oracleDevice.pojo.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.dto;
package com.njcn.product.terminal.oracleDevice.pojo.dto;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.dto;
package com.njcn.product.terminal.oracleDevice.pojo.dto;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.dto;
package com.njcn.product.terminal.oracleDevice.pojo.dto;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.dto;
package com.njcn.product.terminal.oracleDevice.pojo.dto;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.dto;
package com.njcn.product.terminal.oracleDevice.pojo.dto;
import lombok.Data;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
/**
* @Author: cdf

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;

View File

@@ -1,9 +1,8 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*

View File

@@ -1,4 +1,4 @@
package com.njcn.product.terminal.device.pojo.po;
package com.njcn.product.terminal.oracleDevice.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;

View File

@@ -0,0 +1,10 @@
package com.njcn.product.terminal.oracleDevice.service;
import com.njcn.product.terminal.oracleDevice.pojo.dto.OracleLedgerTreeDTO;
import java.util.List;
public interface LedgerTreeService {
List<OracleLedgerTreeDTO> getTree();
}

View File

@@ -1,11 +1,11 @@
package com.njcn.product.terminal.device.service;
package com.njcn.product.terminal.oracleDevice.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.product.terminal.device.pojo.dto.DeviceDTO;
import com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDTO;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.product.terminal.device.pojo.dto.DeviceDeptDTO;
import com.njcn.product.terminal.device.pojo.po.PqDevice;
import com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDeptDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqDevice;
import java.util.List;

View File

@@ -1,9 +1,9 @@
package com.njcn.product.terminal.device.service;
package com.njcn.product.terminal.oracleDevice.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.product.terminal.device.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.terminal.device.pojo.po.PqLine;
import com.njcn.product.terminal.oracleDevice.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqLine;
import org.apache.ibatis.annotations.Param;
import java.util.List;

View File

@@ -1,9 +1,9 @@
package com.njcn.product.terminal.device.service;
package com.njcn.product.terminal.oracleDevice.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.product.terminal.device.pojo.dto.SubstationDTO;
import com.njcn.product.terminal.device.pojo.po.PqSubstation;
import com.njcn.product.terminal.oracleDevice.pojo.dto.SubstationDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqSubstation;
import java.util.List;

View File

@@ -1,7 +1,7 @@
package com.njcn.product.terminal.device.service;
package com.njcn.product.terminal.oracleDevice.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.product.terminal.device.pojo.po.PqsDeptsline;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqsDeptsline;
/**
*

View File

@@ -1,17 +1,17 @@
package com.njcn.product.terminal.device.service.impl;
package com.njcn.product.terminal.oracleDevice.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.product.terminal.device.mapper.PqDeviceMapper;
import com.njcn.product.terminal.device.mapper.PqGdCompanyMapper;
import com.njcn.product.terminal.device.mapper.PqLineMapper;
import com.njcn.product.terminal.device.mapper.PqSubstationMapper;
import com.njcn.product.terminal.device.pojo.dto.OracleLedgerTreeDTO;
import com.njcn.product.terminal.device.pojo.po.PqDevice;
import com.njcn.product.terminal.device.pojo.po.PqGdCompany;
import com.njcn.product.terminal.device.pojo.po.PqLine;
import com.njcn.product.terminal.device.pojo.po.PqSubstation;
import com.njcn.product.terminal.device.service.LedgerTreeService;
import com.njcn.product.terminal.oracleDevice.mapper.PqDeviceMapper;
import com.njcn.product.terminal.oracleDevice.mapper.PqGdCompanyMapper;
import com.njcn.product.terminal.oracleDevice.mapper.PqLineMapper;
import com.njcn.product.terminal.oracleDevice.mapper.PqSubstationMapper;
import com.njcn.product.terminal.oracleDevice.pojo.dto.OracleLedgerTreeDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqDevice;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqGdCompany;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqLine;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqSubstation;
import com.njcn.product.terminal.oracleDevice.service.LedgerTreeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

View File

@@ -1,12 +1,12 @@
package com.njcn.product.terminal.device.service.impl;
package com.njcn.product.terminal.oracleDevice.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.product.terminal.device.mapper.PqDeviceMapper;
import com.njcn.product.terminal.device.pojo.dto.DeviceDTO;
import com.njcn.product.terminal.device.pojo.dto.DeviceDeptDTO;
import com.njcn.product.terminal.device.pojo.po.PqDevice;
import com.njcn.product.terminal.device.service.PqDeviceService;
import com.njcn.product.terminal.oracleDevice.mapper.PqDeviceMapper;
import com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDTO;
import com.njcn.product.terminal.oracleDevice.pojo.dto.DeviceDeptDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqDevice;
import com.njcn.product.terminal.oracleDevice.service.PqDeviceService;
import org.springframework.stereotype.Service;
import java.util.List;

View File

@@ -1,12 +1,12 @@
package com.njcn.product.terminal.device.service.impl;
package com.njcn.product.terminal.oracleDevice.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.product.terminal.device.mapper.PqLineMapper;
import com.njcn.product.terminal.device.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.terminal.device.pojo.po.PqLine;
import com.njcn.product.terminal.device.service.PqLineService;
import com.njcn.product.terminal.oracleDevice.mapper.PqLineMapper;
import com.njcn.product.terminal.oracleDevice.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqLine;
import com.njcn.product.terminal.oracleDevice.service.PqLineService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;

View File

@@ -1,9 +1,9 @@
package com.njcn.product.terminal.device.service.impl;
package com.njcn.product.terminal.oracleDevice.service.impl;
import com.njcn.product.terminal.device.mapper.PqSubstationMapper;
import com.njcn.product.terminal.device.pojo.dto.SubstationDTO;
import com.njcn.product.terminal.device.pojo.po.PqSubstation;
import com.njcn.product.terminal.device.service.PqSubstationService;
import com.njcn.product.terminal.oracleDevice.mapper.PqSubstationMapper;
import com.njcn.product.terminal.oracleDevice.pojo.dto.SubstationDTO;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqSubstation;
import com.njcn.product.terminal.oracleDevice.service.PqSubstationService;
import org.springframework.stereotype.Service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

View File

@@ -1,8 +1,8 @@
package com.njcn.product.terminal.device.service.impl;
package com.njcn.product.terminal.oracleDevice.service.impl;
import com.njcn.product.terminal.device.mapper.PqsDeptslineMapper;
import com.njcn.product.terminal.device.pojo.po.PqsDeptsline;
import com.njcn.product.terminal.device.service.PqsDeptslineService;
import com.njcn.product.terminal.oracleDevice.mapper.PqsDeptslineMapper;
import com.njcn.product.terminal.oracleDevice.pojo.po.PqsDeptsline;
import com.njcn.product.terminal.oracleDevice.service.PqsDeptslineService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

View File

@@ -54,6 +54,12 @@
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.njcn.product</groupId>
<artifactId>cn-terminal</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@@ -0,0 +1,15 @@
package com.njcn.product.cnzutai.zutai.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.cnzutai.zutai.pojo.po.CsSubConfigurationAss;
/**
*
* Description:
* Date: 2025/11/04 上午 11:07【需求编号】
*
* @author clam
* @version V1.0.0
*/
public interface CsSubConfigurationAssMapper extends BaseMapper<CsSubConfigurationAss> {
}

View File

@@ -0,0 +1,14 @@
<?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.njcn.product.cnzutai.zutai.mapper.CsSubConfigurationAssMapper">
<resultMap id="BaseResultMap" type="com.njcn.product.cnzutai.zutai.pojo.po.CsSubConfigurationAss">
<!--@mbg.generated-->
<!--@Table cs_sub_configuration_ass-->
<id column="sub_id" jdbcType="VARCHAR" property="subId" />
<result column="config_id" jdbcType="VARCHAR" property="configId" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
sub_id, config_id
</sql>
</mapper>

View File

@@ -30,6 +30,8 @@ public class CsConfigurationParm {
private List<String> projectIds;
private List<String> substionIds;
private Integer orderBy;

View File

@@ -0,0 +1,33 @@
package com.njcn.product.cnzutai.zutai.pojo.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
*
* Description:
* Date: 2025/11/04 上午 11:07【需求编号】
*
* @author clam
* @version V1.0.0
*/
@TableName(value = "cs_sub_configuration_ass")
@Data
public class CsSubConfigurationAss {
/**
* 变电站序号
*/
@TableId(value = "sub_id", type = IdType.INPUT)
private String subId;
/**
* 组态id
*/
@TableField(value = "config_id")
private String configId;
}

View File

@@ -37,6 +37,9 @@ public class CsConfigurationVO extends BaseEntity {
private List<String> projectIds;
private List<String> substionIds;
private List<String> substionName;
@ApiModelProperty(value = "操作人")
private String operater;

View File

@@ -0,0 +1,16 @@
package com.njcn.product.cnzutai.zutai.service;
import com.njcn.product.cnzutai.zutai.pojo.po.CsSubConfigurationAss;
import com.baomidou.mybatisplus.extension.service.IService;
/**
*
* Description:
* Date: 2025/11/04 上午 11:07【需求编号】
*
* @author clam
* @version V1.0.0
*/
public interface CsSubConfigurationAssService extends IService<CsSubConfigurationAss>{
}

View File

@@ -1,6 +1,7 @@
package com.njcn.product.cnzutai.zutai.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -11,11 +12,16 @@ import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.product.cnzutai.zutai.mapper.CsPagePOMapper;
import com.njcn.product.cnzutai.zutai.pojo.po.CsPagePO;
import com.njcn.product.cnzutai.zutai.pojo.po.CsSubConfigurationAss;
import com.njcn.product.cnzutai.zutai.service.CsConfigurationService;
import com.njcn.product.cnzutai.zutai.mapper.CsConfigurationMapper;
import com.njcn.product.cnzutai.zutai.pojo.param.CsConfigurationParm;
import com.njcn.product.cnzutai.zutai.pojo.po.CsConfigurationPO;
import com.njcn.product.cnzutai.zutai.pojo.vo.CsConfigurationVO;
import com.njcn.product.cnzutai.zutai.service.CsSubConfigurationAssService;
import com.njcn.product.terminal.mysqlTerminal.mapper.LineMapper;
import com.njcn.product.terminal.mysqlTerminal.mapper.PqStationMapper;
import com.njcn.product.terminal.mysqlTerminal.pojo.po.Line;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@@ -46,6 +52,8 @@ public class CsConfigurationServiceImpl extends ServiceImpl<CsConfigurationMappe
private final FileStorageUtil fileStorageUtil;
private final CsPagePOMapper csPagePOMapper;
private final CsSubConfigurationAssService csSubConfigurationAssService;
private final LineMapper lineMapper;
//private final UserFeignClient userFeignClient;
@@ -72,21 +80,44 @@ public class CsConfigurationServiceImpl extends ServiceImpl<CsConfigurationMappe
csConfigurationPO.setStatus("1");
boolean save = this.save(csConfigurationPO);
String name = csConfigurationPO.getName();
Integer count = this.lambdaQuery().eq(CsConfigurationPO::getName, name).eq(CsConfigurationPO::getStatus, "1").count();
if(count>1){
throw new BusinessException("存在相同的组态项目名称");
}
//添加变电站绑定
if(!CollectionUtils.isEmpty(csConfigurationParm.getSubstionIds())){
List<CsSubConfigurationAss> list = csSubConfigurationAssService.lambdaQuery().in(CsSubConfigurationAss::getSubId, csConfigurationParm.getSubstionIds()).list();
if (!CollectionUtils.isEmpty(list)){
List<Line> stationResult = lineMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getId,list));
String subNameList = stationResult.stream().map(Line::getName).collect(Collectors.joining(StrUtil.COMMA));
throw new BusinessException("变电站"+subNameList+"已绑定其他项目请修改");
}else {
List<CsSubConfigurationAss> csSubConfigurationAsses = csConfigurationParm.getSubstionIds().stream().map(temp -> {
CsSubConfigurationAss csSubConfigurationAss = new CsSubConfigurationAss();
csSubConfigurationAss.setSubId(temp);
csSubConfigurationAss.setConfigId(csConfigurationPO.getId());
return csSubConfigurationAss;
}).collect(Collectors.toList());
csSubConfigurationAssService.saveBatch(csSubConfigurationAsses);
}
}
return save;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean audit(CsConfigurationParm.CsConfigurationAuditParam auditParm) {
CsConfigurationPO tem = this.getById(auditParm.getId());
if(Objects.isNull(tem)){
throw new BusinessException(CommonResponseEnum.FAIL,"未查询到项目信息,无法操作!");
}
//删除关联表信息
csSubConfigurationAssService.lambdaUpdate().eq(CsSubConfigurationAss::getConfigId,tem.getId()).remove();
CsConfigurationPO csConfigurationPO = new CsConfigurationPO();
if(Objects.equals(auditParm.getStatus(),"0")){
@@ -126,6 +157,26 @@ public class CsConfigurationServiceImpl extends ServiceImpl<CsConfigurationMappe
boolean b = this.updateById(csConfigurationPO);
//添加变电站绑定
if(!CollectionUtils.isEmpty(auditParm.getSubstionIds())){
List<CsSubConfigurationAss> list = csSubConfigurationAssService.lambdaQuery().in(CsSubConfigurationAss::getSubId, auditParm.getSubstionIds()).list();
if (!CollectionUtils.isEmpty(list)){
List<Line> stationResult = lineMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getId,list));
String subNameList = stationResult.stream().map(Line::getName).collect(Collectors.joining(StrUtil.COMMA));
throw new BusinessException("变电站"+subNameList+"已绑定其他项目请修改");
}else {
List<CsSubConfigurationAss> csSubConfigurationAsses = auditParm.getSubstionIds().stream().map(temp -> {
CsSubConfigurationAss csSubConfigurationAss = new CsSubConfigurationAss();
csSubConfigurationAss.setSubId(temp);
csSubConfigurationAss.setConfigId(csConfigurationPO.getId());
return csSubConfigurationAss;
}).collect(Collectors.toList());
csSubConfigurationAssService.saveBatch(csSubConfigurationAsses);
}
}
return b;
}
@@ -198,7 +249,14 @@ public class CsConfigurationServiceImpl extends ServiceImpl<CsConfigurationMappe
}
}
List<CsSubConfigurationAss> csSubConfigurationAssList = csSubConfigurationAssService.lambdaQuery().eq(CsSubConfigurationAss::getConfigId, page.getId()).list();
if(!CollectionUtils.isEmpty(csSubConfigurationAssList)){
List<String> subIds = csSubConfigurationAssList.stream().map(CsSubConfigurationAss::getSubId).collect(Collectors.toList());
csDevModelPageVO.setSubstionIds(subIds);
// List<Line> stationResult = lineMapper.selectList(new LambdaQueryWrapper<Line>().in(Line::getId,subIds));
// csDevModelPageVO.setSubstionName();
}
csDevModelPageVO.setOperater(collect2.get(csDevModelPageVO.getCreateBy()));
return csDevModelPageVO;

View File

@@ -0,0 +1,21 @@
package com.njcn.product.cnzutai.zutai.service.impl;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.product.cnzutai.zutai.mapper.CsSubConfigurationAssMapper;
import com.njcn.product.cnzutai.zutai.pojo.po.CsSubConfigurationAss;
import com.njcn.product.cnzutai.zutai.service.CsSubConfigurationAssService;
/**
*
* Description:
* Date: 2025/11/04 上午 11:07【需求编号】
*
* @author clam
* @version V1.0.0
*/
@Service
public class CsSubConfigurationAssServiceImpl extends ServiceImpl<CsSubConfigurationAssMapper, CsSubConfigurationAss> implements CsSubConfigurationAssService{
}

View File

@@ -18,13 +18,32 @@
<version>0.0.1</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.njcn</groupId>-->
<!-- <artifactId>common-redis</artifactId>-->
<!-- <version>1.0.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.njcn</groupId>
<artifactId>common-redis</artifactId>
<version>1.0.0</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version> <!-- 建议使用最新版本 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -0,0 +1,130 @@
package com.njcn.product.event.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;
import java.time.Duration;
import java.time.Instant;
/**
* @Author: cdf
* @CreateTime: 2025-10-28
* @Description:
*/
@Configuration
@EnableCaching
public class RedisConfig {
@Value("${spring.redis.host:localhost}")
private String host;
@Value("${spring.redis.port:6379}")
private int port;
@Value("${spring.redis.password:}")
private String password;
@Value("${spring.redis.database:0}")
private int database;
@Value("${spring.redis.timeout:5000}")
private int timeout;
@Bean
@Primary
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 为了开发方便,一般直接使用<String,object>
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域(field,get,set),访问修饰符(public,private,protected)
//解决Java 8 date/time type java.time.Instant not supported
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.registerModule(new SimpleModule().addDeserializer(Instant.class, new RedisInstantDateDeserializer()));
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// key采用string的序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// hash的key采用string的序列化方式
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// hash的value序列化方式采用jackson
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public JedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setDatabase(database);
if (StringUtils.hasText(password)) {
config.setPassword(RedisPassword.of(password));
}
JedisClientConfiguration.JedisClientConfigurationBuilder builder = JedisClientConfiguration.builder();
builder.connectTimeout(Duration.ofMillis(timeout));
builder.readTimeout(Duration.ofMillis(timeout));
// 使用连接池
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(20);
poolConfig.setMaxIdle(8);
poolConfig.setMinIdle(2);
poolConfig.setMaxWaitMillis(8000);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setTimeBetweenEvictionRunsMillis(30000);
builder.usePooling().poolConfig(poolConfig);
return new JedisConnectionFactory(config, builder.build());
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
}

View File

@@ -0,0 +1,38 @@
package com.njcn.product.event.config;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
/**
* @Author: cdf
* @CreateTime: 2025-07-25
* @Description:
*/
@Component
public class RedisInstantDateDeserializer extends StdDeserializer<Instant> {
public RedisInstantDateDeserializer() {
this(null);
}
protected RedisInstantDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String text = p.getValueAsString();
return DateUtil.parse(text, DatePattern.NORM_DATETIME_PATTERN).toInstant().plusMillis(TimeUnit.HOURS.toMillis(8));
}
}

View File

@@ -0,0 +1,208 @@
package com.njcn.product.event.config;
/**
* @Author: cdf
* @CreateTime: 2025-10-28
* @Description:
*/
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* Redis 工具类 - 基于 RedisTemplate
*/
@Component
@Slf4j
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// ==================== 通用操作 ====================
/**
* 设置缓存
*/
public void saveByKey(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
} catch (Exception e) {
log.error("Redis set操作失败 key: {}", key, e);
throw e;
}
}
/**
* 设置缓存带过期时间
*/
public void setex(String key, Object value, long time, TimeUnit timeUnit) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, timeUnit);
} else {
saveByKey(key, value);
}
} catch (Exception e) {
log.error("Redis setex操作失败 key: {}", key, e);
throw e;
}
}
/**
* 获取缓存
*/
public Object get(String key) {
try {
return key != null ? redisTemplate.opsForValue().get(key) : null;
} catch (Exception e) {
log.error("Redis get操作失败 key: {}", key, e);
throw e;
}
}
/**
* 获取对象 - 你在代码中使用的方法
*/
public Object getObjectByKey(String key) {
return get(key);
}
/**
* 获取value为字符串的
* @param key
* @return
*/
public String getRawValue(String key) {
return redisTemplate.execute((RedisCallback<String>) connection -> {
byte[] data = connection.get(key.getBytes());
return data == null ? null : new String(data, StandardCharsets.UTF_8);
});
}
/**
* 删除缓存
*/
public void deleteKeysByString(String... keys) {
try {
if (keys != null && keys.length > 0) {
if (keys.length == 1) {
redisTemplate.delete(keys[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(keys));
}
}
} catch (Exception e) {
log.error("Redis del操作失败", e);
throw e;
}
}
/**
* 设置过期时间
*/
public boolean expire(String key, long time, TimeUnit timeUnit) {
try {
if (time > 0) {
redisTemplate.expire(key, time, timeUnit);
return true;
}
return false;
} catch (Exception e) {
log.error("Redis expire操作失败 key: {}", key, e);
throw e;
}
}
/**
* 获取过期时间
*/
public long getExpire(String key, TimeUnit timeUnit) {
try {
return redisTemplate.getExpire(key, timeUnit);
} catch (Exception e) {
log.error("Redis getExpire操作失败 key: {}", key, e);
throw e;
}
}
/**
* 判断key是否存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
log.error("Redis hasKey操作失败 key: {}", key, e);
throw e;
}
}
// ==================== Hash 操作 ====================
public void hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
} catch (Exception e) {
log.error("Redis hset操作失败 key: {}, item: {}", key, item, e);
throw e;
}
}
public Object hget(String key, String item) {
try {
return redisTemplate.opsForHash().get(key, item);
} catch (Exception e) {
log.error("Redis hget操作失败 key: {}, item: {}", key, item, e);
throw e;
}
}
public Map<Object, Object> hgetall(String key) {
try {
return redisTemplate.opsForHash().entries(key);
} catch (Exception e) {
log.error("Redis hgetall操作失败 key: {}", key, e);
throw e;
}
}
// ==================== 其他常用操作 ====================
/**
* 递增
*/
public long incr(String key, long delta) {
try {
return redisTemplate.opsForValue().increment(key, delta);
} catch (Exception e) {
log.error("Redis incr操作失败 key: {}", key, e);
throw e;
}
}
/**
* 递减
*/
public long decr(String key, long delta) {
try {
return redisTemplate.opsForValue().increment(key, -delta);
} catch (Exception e) {
log.error("Redis decr操作失败 key: {}", key, e);
throw e;
}
}
}

View File

@@ -0,0 +1,39 @@
package com.njcn.product.event.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @Author: cdf
* @CreateTime: 2025-10-23
* @Description: 线程池配置
*/
@Configuration
public class ThreadPoolConfig {
@Bean("smsTaskExecutor")
public ThreadPoolTaskExecutor smsTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(100); // 队列容量
executor.setKeepAliveSeconds(30); // 空闲线程存活时间
executor.setThreadNamePrefix("sms-sender-"); // 线程名前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略
executor.initialize();
return executor;
}
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(); // 基础配置
}
}
}

View File

@@ -0,0 +1,551 @@
package com.njcn.product.event.dataTransmit;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njcn.product.event.devcie.mapper.PqGdCompanyMapper;
import com.njcn.product.event.devcie.mapper.PqLineMapper;
import com.njcn.product.event.devcie.mapper.PqLinedetailMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqGdCompany;
import com.njcn.product.event.devcie.pojo.po.PqLinedetail;
import com.njcn.product.event.transientes.mapper.*;
import com.njcn.product.event.transientes.pojo.dto.UpLoadEvent;
import com.njcn.product.event.transientes.pojo.dto.UpLoadUserDTO;
import com.njcn.product.event.transientes.pojo.dto.UserLegerDTO;
import com.njcn.product.event.transientes.pojo.dto.UserLineAssDTO;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.PqsEventDetailStatusService;
import com.njcn.product.event.transientes.utils.OssFileStorageUtils;
import com.njcn.product.event.config.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Author: cdf
* @CreateTime: 2025-10-20
* @Description: 暂降事件同步
*/
@Service
@EnableScheduling
@Slf4j
@RequiredArgsConstructor
public class DataSynchronization {
private final PqsEventdetailMapper pqsEventdetailMapper;
private final PqsEventDetailStatusService pqsEventDetailStatusService;
private final OssFileStorageUtils ossFileStorageUtils;
private final PqLinedetailMapper pqLinedetailMapper;
private final PqLineMapper pqLineMapper;
private final PqUserLineAssMapper pqUserLineAssMapper;
private final PqUserLedgerMapper pqUserLedgerMapper;
private final PqsDicTreeMapper pqsDicTreeMapper;
private final PqGdCompanyMapper pqGdCompanyMapper;
private final RedisUtil redisUtil;
// 文件配置
@Value("${business.wavePath}")
private String sourceWaveDir;
@Value("${business.targetPath}")
private String targetPath;
@Value("${business.syncinterval}")
private Integer syncinterval;
@Value("${business.failsyncinterval}")
private Integer failsyncinterval;
private volatile boolean syncEventFlag = false;
private volatile boolean syncFailFlag = false;
private final static String NAME_KEY = "LineCache:";
/**
* 定时执行的同步任务
*/
@Scheduled(cron = "${business.eventCronExpression}")
@Transactional
public void syncPqsEventdetails() {
// 防止任务并发执行
if (syncEventFlag) {
log.warn("同步任务正在执行中,跳过本次调度");
return;
}
try {
syncEventFlag = true;
log.info("=== 开始暂降事件波形文件同步任务 ===");
// 同步最近N天的事件,因为存在事件补招,延迟的原因,采用大范围扫描
LocalDateTime end = LocalDateTime.now();
LocalDateTime start = end.minusMinutes(syncinterval);
syncEvents(start, end);
log.info("=== 同步任务完成 ===");
} catch (Exception e) {
log.error("同步任务执行失败", e);
} finally {
syncEventFlag = false;
}
}
@Scheduled(cron = "${business.failCronExpression}")
@Transactional
public void syncFail() {
// 防止任务并发执行
if (syncFailFlag) {
log.warn("同步任务正在执行中,跳过本次调度");
return;
}
try {
syncFailFlag = true;
log.info("=== 开始暂降事件波形文件同步任务 ===");
// 同步最近N天的事件,因为存在事件补招,延迟的原因,采用大范围扫描
LocalDateTime end = LocalDateTime.now();
LocalDateTime start = end.minusMinutes(failsyncinterval);
synFailEvents(start, end);
log.info("=== 同步任务完成 ===");
} catch (Exception e) {
log.error("同步任务执行失败", e);
} finally {
syncFailFlag = false;
}
}
@Scheduled(cron = "${business.userCronExpression}")
@Transactional
public void syncUser() throws Exception {
log.info("=== 开始重要敏感用户同步任务 ===");
String exportDirName = "/pq_user/pq_user.json";
UpLoadUserDTO result = new UpLoadUserDTO();
QueryWrapper<PqUserLedgerPO> pqUserLedgerPOQueryWrapper = new QueryWrapper<>();
// pqUserLedgerPOQueryWrapper.lambda().eq(PqUserLedgerPO::getIsShow,1);
List<PqUserLedgerPO> pqUserLedgerPOS = pqUserLedgerMapper.selectList(null);
if(!CollectionUtils.isEmpty(pqUserLedgerPOS)){
List<String> showIds =new ArrayList<>();
List<UserLegerDTO> userLegerDTOList =new ArrayList<>();
List<PqsDicTreePO> pqsDicTreePOS = pqsDicTreeMapper.selectList(new LambdaQueryWrapper<>());
Map<String, PqsDicTreePO> pqsDicTreePOMap = pqsDicTreePOS.stream().collect(Collectors.toMap(PqsDicTreePO::getId, Function.identity()));
List<PqGdCompany> pqGdCompanyList = pqGdCompanyMapper.selectList(null);
Map<Long, PqGdCompany> gdMap = pqGdCompanyList.stream().collect(Collectors.toMap(PqGdCompany::getGdIndex, Function.identity()));
pqUserLedgerPOS.forEach(temp->{
showIds.add(temp.getId());
UserLegerDTO userLegerDTO = new UserLegerDTO();
userLegerDTO.setId(temp.getId());
userLegerDTO.setPowerSupplyArea(gdMap.get(Long.valueOf(temp.getPowerSupplyArea())).getName());
userLegerDTO.setCustomerName(temp.getCustomerName());
userLegerDTO.setElectricityAddress(temp.getElectricityAddress());
userLegerDTO.setBigObjType(pqsDicTreePOMap.get(temp.getBigObjType()).getName());
userLegerDTO.setSmallObjType(pqsDicTreePOMap.get(temp.getSmallObjType()).getName());
userLegerDTO.setCustomerNo("");
userLegerDTO.setIsShow(temp.getIsShow());
userLegerDTOList.add(userLegerDTO);
});
QueryWrapper<PqUserLineAssPO> userLineAssPOQueryWrapper = new QueryWrapper<>();
// userLineAssPOQueryWrapper.lambda().in(PqUserLineAssPO::getUserIndex,showIds);
if (showIds.size() > 1000) {
List<List<String>> splitList = CollUtil.split(showIds, 1000);
userLineAssPOQueryWrapper.lambda().and(ew -> {
for (int i = 0; i < splitList.size(); i++) {
List<String> batch = splitList.get(i);
if (i == 0) {
ew.in(PqUserLineAssPO::getUserIndex, batch); // 第一个条件不加 or
} else {
ew.or().in(PqUserLineAssPO::getUserIndex, batch); // 后续条件加 or
}
}
});
} else {
userLineAssPOQueryWrapper.lambda().in(PqUserLineAssPO::getUserIndex, showIds);
}
List<PqUserLineAssPO> pqUserLineAssPOS = pqUserLineAssMapper.selectList(userLineAssPOQueryWrapper);
List<UserLineAssDTO> userLineAssDTOS = pqUserLineAssPOS.stream().map(temp -> {
UserLineAssDTO userLineAssDTO = new UserLineAssDTO();
BeanUtils.copyProperties(temp, userLineAssDTO);
return userLineAssDTO;
}).collect(Collectors.toList());
result.setUserList(userLegerDTOList);
result.setAssList(userLineAssDTOS);
ossFileStorageUtils.uploadObjectAsJsonStream(result,exportDirName);
log.info("=== 结束重要敏感用户同步任务 ===");
}else {
log.info("=== 暂无重要敏感用户 ===");
}
}
private void synFailEvents(LocalDateTime start, LocalDateTime end) throws Exception {
log.info("=== 开始同步同步失败事件任务 ===");
// 创建导出目录
String filePath = start.toLocalDate().format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
String fileName = end.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String exportDirName = String.format("%s/%s/%s.json","/event", filePath,"bz_"+fileName);
// 查询失败的暂降事件
LambdaQueryWrapper<PqsEventDetailStatusPO> statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>();
statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getSyncTime,start,end);
List<PqsEventDetailStatusPO> hasList = pqsEventDetailStatusService.list(statusPOLambdaQueryWrapper);
Map<String, PqsEventDetailStatusPO> pqsEventDetailStatusPOMap = hasList.stream().collect(Collectors.toMap(PqsEventDetailStatusPO::getEventDetailId, Function.identity()));
// 查询事件
LambdaQueryWrapper<PqsEventdetail> pqsEventdetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
pqsEventdetailLambdaQueryWrapper.between(PqsEventdetail::getCreateTime,start.minusMinutes(6*10),end);
List<PqsEventdetail> unsyncedEvents = pqsEventdetailMapper.selectList(pqsEventdetailLambdaQueryWrapper);
List<String> tempEvetIds = unsyncedEvents.stream().map(PqsEventdetail::getEventdetailIndex).collect(Collectors.toList());
//查询日志
List<String> allEventIds = hasList.stream().map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
List<String> unSyncIds = tempEvetIds.stream().filter(temp -> !allEventIds.contains(temp)).collect(Collectors.toList());
List<String> failIds = hasList.stream().filter(temp -> temp.getRetryCount() <= 5 && temp.getSyncStatus() == 0).map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
unSyncIds.addAll(failIds);
List<UpLoadEvent> result = new ArrayList<>();
if(!CollectionUtils.isEmpty(unSyncIds)){
List<String> eventIds = unSyncIds.stream().distinct().collect(Collectors.toList());
LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if (eventIds.size() > 1000) {
List<List<String>> splitList = CollUtil.split(eventIds, 1000);
lambdaQueryWrapper.and(ew -> {
for (int i = 0; i < splitList.size(); i++) {
List<String> batch = splitList.get(i);
if (i == 0) {
ew.in(PqsEventdetail::getEventdetailIndex, batch); // 第一个条件不加 or
} else {
ew.or().in(PqsEventdetail::getEventdetailIndex, batch); // 后续条件加 or
}
}
});
} else {
lambdaQueryWrapper.in(PqsEventdetail::getEventdetailIndex, eventIds);
}
List<PqsEventdetail> pqsEventdetails = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
Map<String, PqsEventdetail> pqsEventdetailMap = pqsEventdetails.stream().collect(Collectors.toMap(PqsEventdetail::getEventdetailIndex, Function.identity()));
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
Map<Integer, LedgerBaseInfoDTO> LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));
List<PqLinedetail> pqLinedetails = pqLinedetailMapper.selectList(null);
Map<Integer, PqLinedetail> lineDetailMap = pqLinedetails.stream().collect(Collectors.toMap(PqLinedetail::getLineIndex, Function.identity()));
eventIds.forEach(temp->{
PqsEventdetail pqsEventdetail = pqsEventdetailMap.get(temp);
if(pqsEventDetailStatusPOMap.containsKey(temp)){
PqsEventDetailStatusPO pqsEventDetailStatusPO = pqsEventDetailStatusPOMap.get(temp);
pqsEventDetailStatusPO.setRetryCount(pqsEventDetailStatusPO.getRetryCount()+1);
if(Objects.nonNull(pqsEventdetail.getWavename())||pqsEventDetailStatusPO.getRetryCount()>5){
pqsEventDetailStatusPO.setSyncStatus(1);
pqsEventDetailStatusPO.setWaveFlag(0);
UpLoadEvent upLoadEvent = new UpLoadEvent();
upLoadEvent.setEventdetail_index(pqsEventdetail.getEventdetailIndex());
upLoadEvent.setLineid(pqsEventdetail.getLineid());
upLoadEvent.setTimeid(LocalDateTimeUtil.format(pqsEventdetail.getTimeid(),DatePattern.NORM_DATETIME_PATTERN));
upLoadEvent.setMs(pqsEventdetail.getMs());
upLoadEvent.setDescribe(pqsEventdetail.getDescribe());
upLoadEvent.setWavetype(pqsEventdetail.getWavetype());
upLoadEvent.setPersisttime( pqsEventdetail.getPersisttime()/ 1000);
upLoadEvent.setEventvalue(pqsEventdetail.getEventvalue());
upLoadEvent.setEventreason(pqsEventdetail.getEventreason());
upLoadEvent.setEventtype(pqsEventdetail.getEventtype());
LedgerBaseInfoDTO ledgerBaseInfoDTO = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid());
if(Objects.isNull(ledgerBaseInfoDTO)){
List<LedgerBaseInfoDTO> baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetail.getLineid()).collect(Collectors.toList()));
ledgerBaseInfoDTO = baseLineInfo.get(0);
}
upLoadEvent.setGdname(ledgerBaseInfoDTO.getGdName());
upLoadEvent.setBdname(ledgerBaseInfoDTO.getStationName());
upLoadEvent.setBusname(ledgerBaseInfoDTO.getBusBarName());
upLoadEvent.setPointname(ledgerBaseInfoDTO.getLineName());
upLoadEvent.setIp(ledgerBaseInfoDTO.getIp());
upLoadEvent.setPt(ledgerBaseInfoDTO.getPt());
upLoadEvent.setCt(ledgerBaseInfoDTO.getCt());
upLoadEvent.setPtType(lineDetailMap.get(pqsEventdetail.getLineid()).getPttype());
upLoadEvent.setIp(ledgerBaseInfoDTO.getIp());
if(Objects.nonNull(pqsEventdetail.getWavename())){
pqsEventDetailStatusPO.setWaveFlag(1);
upLoadEvent.setWavePath(ledgerBaseInfoDTO.getIp()+"/"+pqsEventdetail.getWavename());
}
result.add(upLoadEvent);
}
pqsEventDetailStatusService.saveOrUpdate(pqsEventDetailStatusPO);
}else{
PqsEventDetailStatusPO pqsEventDetailStatusPO = new PqsEventDetailStatusPO();
pqsEventDetailStatusPO.setEventDetailId(pqsEventdetail.getEventdetailIndex());
pqsEventDetailStatusPO.setEventTime(pqsEventdetail.getTimeid());
pqsEventDetailStatusPO.setSyncTime(LocalDateTime.now());
pqsEventDetailStatusPO.setRemark("");
pqsEventDetailStatusPO.setRetryCount(0);
if(StringUtils.isEmpty(pqsEventdetail.getWavename())){
pqsEventDetailStatusPO.setSyncStatus(0);
pqsEventDetailStatusPO.setWaveFlag(0);
}else {
UpLoadEvent upLoadEvent = new UpLoadEvent();
upLoadEvent.setEventdetail_index(pqsEventdetail.getEventdetailIndex());
upLoadEvent.setLineid(pqsEventdetail.getLineid());
upLoadEvent.setTimeid(LocalDateTimeUtil.format(pqsEventdetail.getTimeid(),DatePattern.NORM_DATETIME_PATTERN));
upLoadEvent.setMs(pqsEventdetail.getMs());
upLoadEvent.setDescribe(pqsEventdetail.getDescribe());
upLoadEvent.setWavetype(pqsEventdetail.getWavetype());
upLoadEvent.setPersisttime(pqsEventdetail.getPersisttime()/ 1000);
upLoadEvent.setEventvalue(pqsEventdetail.getEventvalue());
upLoadEvent.setEventreason(pqsEventdetail.getEventreason());
upLoadEvent.setEventtype(pqsEventdetail.getEventtype());
LedgerBaseInfoDTO ledgerBaseInfoDTO = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid());
if(Objects.isNull(ledgerBaseInfoDTO)){
List<LedgerBaseInfoDTO> baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetail.getLineid()).collect(Collectors.toList()));
ledgerBaseInfoDTO = baseLineInfo.get(0);
}
upLoadEvent.setGdname(ledgerBaseInfoDTO.getGdName());
upLoadEvent.setBdname(ledgerBaseInfoDTO.getStationName());
upLoadEvent.setBusname(ledgerBaseInfoDTO.getBusBarName());
upLoadEvent.setPointname(ledgerBaseInfoDTO.getLineName());
upLoadEvent.setIp(ledgerBaseInfoDTO.getIp());
upLoadEvent.setPt(ledgerBaseInfoDTO.getPt());
upLoadEvent.setCt(ledgerBaseInfoDTO.getCt());
upLoadEvent.setPtType(lineDetailMap.get(pqsEventdetail.getLineid()).getPttype());
upLoadEvent.setWavePath(ledgerBaseInfoDTO.getIp()+"/"+pqsEventdetail.getWavename());
result.add(upLoadEvent);
pqsEventDetailStatusPO.setSyncStatus(1);
pqsEventDetailStatusPO.setWaveFlag(1);
}
pqsEventDetailStatusService.saveOrUpdate(pqsEventDetailStatusPO);
}
});
}
if(!CollectionUtils.isEmpty(result)){
//上传Json
ossFileStorageUtils.uploadObjectAsJsonStream(result,exportDirName);
//上传波形文件
result.forEach(temp->{
if(Objects.nonNull(temp.getWavePath())){
// String uploadLocalFile1 =sourceWaveDir+"/"+temp.getWavePath()+".dat";
String uploadLocalFile2 =sourceWaveDir+"/"+temp.getWavePath()+".DAT";
// String uploadLocalFile3 =sourceWaveDir+"/"+temp.getWavePath()+".cfg";
String uploadLocalFile4 =sourceWaveDir+"/"+temp.getWavePath()+".CFG";
String uploadLocalFile5 =sourceWaveDir+"/"+temp.getWavePath()+".HDR";
// String uploadLocalFile6 =sourceWaveDir+"/"+temp.getWavePath()+".hdr";
// ossFileStorageUtils.uploadLocalFile(uploadLocalFile1, targetPath+"/"+temp.getIp());
ossFileStorageUtils.uploadLocalFile(uploadLocalFile2, targetPath+"/"+temp.getIp());
// ossFileStorageUtils.uploadLocalFile(uploadLocalFile3, targetPath+"/"+temp.getIp());
ossFileStorageUtils.uploadLocalFile(uploadLocalFile4, targetPath+"/"+temp.getIp());
ossFileStorageUtils.uploadLocalFile(uploadLocalFile5, targetPath+"/"+temp.getIp());
// ossFileStorageUtils.uploadLocalFile(uploadLocalFile6, targetPath+"/"+temp.getIp());
}
});
}
}
/**
* 同步指定时间范围内的事件
*/
public void syncEvents(LocalDateTime startTime, LocalDateTime endTime) throws Exception {
// 创建导出目录
String filePath = endTime.toLocalDate().format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
String fileName = startTime.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String exportDirName = String.format("%s/%s/%s.json","/event", filePath,fileName);
// 查询未同步的事件
LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.between(PqsEventdetail::getCreateTime,startTime,endTime);
List<PqsEventdetail> unsyncedEvents = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
log.info("查询到 " + unsyncedEvents.size() + " 个暂降事件");
if(CollUtil.isEmpty(unsyncedEvents)){
return ;
}
// // 查询已经存在记录的暂降事件
// LambdaQueryWrapper<PqsEventDetailStatusPO> statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>();
// statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getEventTime,startTime,endTime);
// List<PqsEventDetailStatusPO> hasList = pqsEventDetailStatusMapper.selectList(statusPOLambdaQueryWrapper);
// log.info("查询到 " + hasList.size() + "条已存在记录事件");
// //成功或者重试超过2次的时间id
// List<String> successEventDetailIds = hasList.stream().filter(it->it.getWaveFlag() == 1||it.getRetryCount()>2).map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
//
//
// //排除已经成功的事件
// if(CollUtil.isNotEmpty(successEventDetailIds)){
// unsyncedEvents = unsyncedEvents.stream().filter(it->!successEventDetailIds.contains(it.getEventdetailIndex())).collect(Collectors.toList());
// }
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
Map<Integer, LedgerBaseInfoDTO> LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));
List<PqLinedetail> pqLinedetails = pqLinedetailMapper.selectList(null);
Map<Integer, PqLinedetail> lineDetailMap = pqLinedetails.stream().collect(Collectors.toMap(PqLinedetail::getLineIndex, Function.identity()));
List<UpLoadEvent> result = new ArrayList<>();
List<PqsEventDetailStatusPO> logs = new ArrayList<>();
for (PqsEventdetail unsyncedEvent : unsyncedEvents) {
PqsEventDetailStatusPO pqsEventDetailStatusPO = new PqsEventDetailStatusPO();
pqsEventDetailStatusPO.setEventDetailId(unsyncedEvent.getEventdetailIndex());
pqsEventDetailStatusPO.setEventTime(unsyncedEvent.getTimeid());
pqsEventDetailStatusPO.setSyncTime(LocalDateTime.now());
pqsEventDetailStatusPO.setRemark("");
pqsEventDetailStatusPO.setRetryCount(0);
if(StringUtils.isEmpty(unsyncedEvent.getWavename())){
pqsEventDetailStatusPO.setSyncStatus(0);
pqsEventDetailStatusPO.setWaveFlag(0);
}else {
UpLoadEvent upLoadEvent = new UpLoadEvent();
upLoadEvent.setEventdetail_index(unsyncedEvent.getEventdetailIndex());
upLoadEvent.setLineid(unsyncedEvent.getLineid());
upLoadEvent.setTimeid(LocalDateTimeUtil.format(unsyncedEvent.getTimeid(),DatePattern.NORM_DATETIME_PATTERN));
upLoadEvent.setMs(unsyncedEvent.getMs());
upLoadEvent.setDescribe(unsyncedEvent.getDescribe());
upLoadEvent.setWavetype(unsyncedEvent.getWavetype());
upLoadEvent.setPersisttime(unsyncedEvent.getPersisttime()/ 1000);
upLoadEvent.setEventvalue(unsyncedEvent.getEventvalue());
upLoadEvent.setEventreason(unsyncedEvent.getEventreason());
upLoadEvent.setEventtype(unsyncedEvent.getEventtype());
LedgerBaseInfoDTO ledgerBaseInfoDTO = LedgerBaseInfoDTOMap.get(unsyncedEvent.getLineid());
if(Objects.isNull(ledgerBaseInfoDTO)){
List<LedgerBaseInfoDTO> baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(unsyncedEvent.getLineid()).collect(Collectors.toList()));
ledgerBaseInfoDTO = baseLineInfo.get(0);
}
upLoadEvent.setGdname(ledgerBaseInfoDTO.getGdName());
upLoadEvent.setBdname(ledgerBaseInfoDTO.getStationName());
upLoadEvent.setBusname(ledgerBaseInfoDTO.getBusBarName());
upLoadEvent.setPointname(ledgerBaseInfoDTO.getLineName());
upLoadEvent.setIp(ledgerBaseInfoDTO.getIp());
upLoadEvent.setPt(ledgerBaseInfoDTO.getPt());
upLoadEvent.setCt(ledgerBaseInfoDTO.getCt());
upLoadEvent.setPtType(lineDetailMap.get(unsyncedEvent.getLineid()).getPttype());
upLoadEvent.setWavePath(ledgerBaseInfoDTO.getIp()+"/"+unsyncedEvent.getWavename());
result.add(upLoadEvent);
pqsEventDetailStatusPO.setSyncStatus(1);
pqsEventDetailStatusPO.setWaveFlag(1);
}
pqsEventDetailStatusService.saveOrUpdate(pqsEventDetailStatusPO);
logs.add(pqsEventDetailStatusPO);
}
if(!CollectionUtils.isEmpty(result)){
//上传Json
ossFileStorageUtils.uploadObjectAsJsonStream(result,exportDirName);
//上传波形文件
result.forEach(temp->{
// String uploadLocalFile1 =sourceWaveDir+"/"+temp.getWavePath()+".dat";
String uploadLocalFile2 =sourceWaveDir+"/"+temp.getWavePath()+".DAT";
// String uploadLocalFile3 =sourceWaveDir+"/"+temp.getWavePath()+".cfg";
String uploadLocalFile4 =sourceWaveDir+"/"+temp.getWavePath()+".CFG";
String uploadLocalFile5 =sourceWaveDir+"/"+temp.getWavePath()+".HDR";
// String uploadLocalFile6 =sourceWaveDir+"/"+temp.getWavePath()+".hdr";
// ossFileStorageUtils.uploadLocalFile(uploadLocalFile1, targetPath+"/"+temp.getIp());
ossFileStorageUtils.uploadLocalFile(uploadLocalFile2, targetPath+"/"+temp.getIp());
// ossFileStorageUtils.uploadLocalFile(uploadLocalFile3, targetPath+"/"+temp.getIp());
ossFileStorageUtils.uploadLocalFile(uploadLocalFile4, targetPath+"/"+temp.getIp());
ossFileStorageUtils.uploadLocalFile(uploadLocalFile5, targetPath+"/"+temp.getIp());
// ossFileStorageUtils.uploadLocalFile(uploadLocalFile6, targetPath+"/"+temp.getIp());
});
}
}
/**
* 获取波形类型描述
*/
private String getWaveTypeDesc(Integer waveType) {
if (waveType == null) return "未知";
switch (waveType) {
case 1: return "电压暂降";
case 2: return "电压暂升";
case 3: return "电压中断";
case 4: return "电压波动";
default: return "未知类型(" + waveType + ")";
}
}
public static void main(String[] args) {
double a =3.00;
System.out.println(a/1000);
}
}

View File

@@ -1,224 +0,0 @@
package com.njcn.product.event.dataTransmit;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.product.event.transientes.mapper.PqsEventDetailStatusMapper;
import com.njcn.product.event.transientes.mapper.PqsEventdetailMapper;
import com.njcn.product.event.transientes.pojo.po.PqsEventDetailStatusPO;
import com.njcn.product.event.transientes.pojo.po.PqsEventdetail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author: cdf
* @CreateTime: 2025-10-20
* @Description: 暂降事件同步
*/
@Service
@EnableScheduling
@Slf4j
@RequiredArgsConstructor
public class dataSynchronization {
private final PqsEventdetailMapper pqsEventdetailMapper;
private final PqsEventDetailStatusMapper pqsEventDetailStatusMapper;
// 文件配置
@Value("${business.wavePath}")
private String sourceWaveDir;
@Value("${business.exportBaseDir}")
private String exportBaseDir;
// 定时任务配置
// 默认每2小时执行一次
private String cronExpression = "0 0 */2 * * ?";
private volatile boolean isRunning = false;
/**
* 定时执行的同步任务
*/
@Scheduled(cron = "${sag.sync.cronExpression}")
@Transactional
public void syncPqsEventdetails() {
// 防止任务并发执行
if (isRunning) {
log.warn("同步任务正在执行中,跳过本次调度");
return;
}
try {
isRunning = true;
log.info("=== 开始暂降事件波形文件同步任务 ===");
// 初始化
initialize();
// 同步最近N天的事件,因为存在事件补招,延迟的原因,采用大范围扫描
LocalDateTime end = LocalDateTime.now();
LocalDateTime start = end.minusHours(24);
syncEvents(start, end);
log.info("=== 同步任务完成 ===");
} catch (Exception e) {
log.error("同步任务执行失败", e);
} finally {
isRunning = false;
}
}
/**
* 初始化操作
*/
private void initialize() throws Exception {
// 检查目录
checkDirectories();
// 检查同步状态表
checkSyncStatusTable();
}
/**
* 同步指定时间范围内的事件
*/
public void syncEvents(LocalDateTime startTime, LocalDateTime endTime) throws Exception {
// 创建导出目录
String startStr = startTime.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String endStr = startTime.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String exportDirName = String.format("%s_%s.json", startStr,endStr);
Path exportDir = Paths.get(exportBaseDir, exportDirName);
Files.createDirectories(exportDir);
log.info("创建导出目录: " + exportDir.toAbsolutePath());
// 查询未同步的事件
LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.between(PqsEventdetail::getTimeid,startTime,endTime);
List<PqsEventdetail> unsyncedEvents = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
log.info("查询到 " + unsyncedEvents.size() + " 个暂降事件");
if(CollUtil.isEmpty(unsyncedEvents)){
return ;
}
// 查询已经存在记录的暂降事件
LambdaQueryWrapper<PqsEventDetailStatusPO> statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>();
statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getEventTime,startTime,endTime);
List<PqsEventDetailStatusPO> hasList = pqsEventDetailStatusMapper.selectList(statusPOLambdaQueryWrapper);
log.info("查询到 " + hasList.size() + "条已存在记录事件");
//波形文件失败的事件id
List<String> waveFailEventDetailIds = hasList.stream().filter(it->it.getWaveFlag() == 0).map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
//排除已经成功的事件
if(CollUtil.isNotEmpty(hasList)){
List<String> hasIds = hasList.stream().map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
unsyncedEvents = unsyncedEvents.stream().filter(it->!hasIds.contains(it.getEventdetailIndex())).collect(Collectors.toList());
}
//对为上传的事件进行上传操作
}
/**
* 检查必要的目录是否存在
*/
private void checkDirectories() throws IOException {
// 检查源目录
Path sourceDir = Paths.get(sourceWaveDir);
if (!Files.exists(sourceDir)) {
throw new IOException("源波形文件目录不存在: " + sourceDir);
}
// 检查导出基础目录
Path exportDir = Paths.get(exportBaseDir);
if (!Files.exists(exportDir)) {
Files.createDirectories(exportDir);
log.info("创建导出基础目录: " + exportDir);
}
}
/**
* 检查同步状态表是否存在
*/
private void checkSyncStatusTable() {
}
/**
* 导出单个事件
*/
private void exportSingleEvent(Path exportDir, PqsEventdetail event) throws Exception {
}
/**
* 生成事件信息文件
*/
private void generateEventInfoFile(Path eventDir, PqsEventdetail event) throws Exception {
}
/**
* 生成同步报告
*/
private void generateSyncReport(Path exportDir, int totalEvents, int successCount, int failureCount) throws Exception {
}
/**
* 更新事件同步状态
*/
private void updateSyncStatus(PqsEventdetail event, int status, String errorMessage) {
}
/**
* 获取波形类型描述
*/
private String getWaveTypeDesc(Integer waveType) {
if (waveType == null) return "未知";
switch (waveType) {
case 1: return "电压暂降";
case 2: return "电压暂升";
case 3: return "电压中断";
case 4: return "电压波动";
default: return "未知类型(" + waveType + ")";
}
}
/**
* 获取任务运行状态
*/
public boolean isRunning() {
return isRunning;
}
}

View File

@@ -3,12 +3,13 @@ package com.njcn.product.event.devcie.config;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.product.event.devcie.mapper.PqLineMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqLine;
import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.pojo.po.PqsDepts;
import com.njcn.product.event.transientes.service.PqsDeptsService;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.product.event.config.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -44,7 +45,7 @@ public class PqlineCache {
private String sysTypeZt;
@PostConstruct
public void init() {
log.info("系统启动中。。。加载pqline");
log.info("初始化刷新redis缓存----------------------");
List<PqLine> pqLines = pqLineMapper.selectList(null);
redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"pqLineList",pqLines);
List<PqsDepts> list = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState, 1).list();
@@ -70,6 +71,20 @@ public class PqlineCache {
List<PqsDepts> deptsList = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState,1).list();
redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"AllDept",deptsList);
List<Integer> collect = pqLines.stream().map(PqLine::getLineIndex).collect(Collectors.toList());
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = new ArrayList<>();
if(collect.size()>1000){
List<List<Integer>> listIds = CollUtil.split(collect,1000);
for(List<Integer> itemIds : listIds){
List<LedgerBaseInfoDTO> temp =pqLineMapper.getBaseLineInfo(itemIds);
ledgerBaseInfoDTOS.addAll(temp);
}
}else {
List<LedgerBaseInfoDTO> temp =pqLineMapper.getBaseLineInfo(collect);
ledgerBaseInfoDTOS.addAll(temp);
}
redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO",ledgerBaseInfoDTOS);
}
@PreDestroy

View File

@@ -4,12 +4,13 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.njcn.product.event.devcie.mapper.PqDeviceMapper;
import com.njcn.product.event.devcie.mapper.PqLineMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqLine;
import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.pojo.po.PqsDepts;
import com.njcn.product.event.transientes.service.PqsDeptsService;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.product.event.config.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
@@ -74,6 +75,20 @@ public class LineCacheJob {
List<PqsDepts> deptsList = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState,1).list();
redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"AllDept",deptsList);
List<Integer> collect = pqLines.stream().map(PqLine::getLineIndex).collect(Collectors.toList());
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = new ArrayList<>();
if(collect.size()>1000){
List<List<Integer>> listIds = CollUtil.split(collect,1000);
for(List<Integer> itemIds : listIds){
List<LedgerBaseInfoDTO> temp =pqLineMapper.getBaseLineInfo(itemIds);
ledgerBaseInfoDTOS.addAll(temp);
}
}else {
List<LedgerBaseInfoDTO> temp =pqLineMapper.getBaseLineInfo(collect);
ledgerBaseInfoDTOS.addAll(temp);
}
redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO",ledgerBaseInfoDTOS);
}
}

View File

@@ -44,6 +44,9 @@
PQ_SUBVOLTAGE.SCALE,
pq_device.dev_index devId,
pq_device.name devName,
pq_device.ip ip,
pq_line.pt1/pq_line.pt2 pt,
pq_line.ct1/pq_line.ct2 ct,
pq_device.Status runFlag,
PQ_SUBSTATION.sub_index stationId,
PQ_SUBSTATION.name stationName,
@@ -74,6 +77,9 @@ where 1=1
PQ_SUBVOLTAGE.SCALE,
pq_device.dev_index devId,
pq_device.name devName,
pq_device.ip ip,
pq_line.pt1/pq_line.pt2 pt,
pq_line.ct1/pq_line.ct2 ct,
pq_device.Status runFlag,
PQ_SUBSTATION.sub_index stationId,
PQ_SUBSTATION.name stationName

View File

@@ -35,7 +35,9 @@ public class LedgerBaseInfoDTO {
private Integer runFlag=0;
private Integer eventCount;
private String ip;
private int pt;
private int ct;
}

View File

@@ -0,0 +1,41 @@
package com.njcn.product.event.devcie.pojo.dto;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
/**
* Description:
* Date: 2025/10/23 上午 10:58【需求编号】
*
* @author clam
* @version V1.0.0
*/
@Data
public class LedgerExcelDTO {
@Excel(name = "供电公司", width = 20)
private String gdName;
@Excel(name = "变电站", width = 20)
private String stationName;
@Excel(name = "装置", width = 20)
private String devName;
@Excel(name = "母线", width = 20)
private String busBarName;
@Excel(name = "监测点", width = 20)
private String lineName;
@Excel(name = "用户", width = 50)
private String objName;
}

View File

@@ -10,6 +10,7 @@ import com.njcn.product.event.report.utils.WordTemplate;
import com.njcn.product.event.transientes.pojo.param.LargeScreenCountParam;
import com.njcn.product.event.transientes.pojo.po.PqsDepts;
import com.njcn.product.event.transientes.service.PqsDeptsService;
import com.njcn.product.event.config.RedisUtil;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.HttpResultUtil;
import io.swagger.annotations.Api;

View File

@@ -25,6 +25,7 @@ import com.njcn.product.event.transientes.pojo.param.LargeScreenCountParam;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.CommGeneralService;
import com.njcn.product.event.transientes.service.MsgEventConfigService;
import com.njcn.product.event.config.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
@@ -40,6 +41,7 @@ import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;
@@ -73,6 +75,8 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService {
private final ObjectMapper mapper = new ObjectMapper();
// @Value("${business.wordTemplatePath}")
// private String wordTemplatePath;
private final RedisUtil redisUtil;
private final static String NAME_KEY = "LineCache:";
@Override
public void exportWordReport(HttpServletResponse response, ReportExportParam param) {
@@ -115,20 +119,23 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService {
List<PqsEventdetail> pqsEventdetailList = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
if(CollUtil.isNotEmpty(pqsEventdetailList)) {
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
Map<Integer, LedgerBaseInfoDTO> LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));
List<Map<String, Object>> eventTemplateList = new ArrayList<>();
for (int i = 0; i < pqsEventdetailList.size(); i++) {
PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i);
EventTemplate eventTemplate = new EventTemplate();
eventTemplate.setSno(i + 1);
eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER) + "." + pqsEventdetail.getMs());
List<LedgerBaseInfoDTO> baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetailList.get(i).getLineid()).collect(Collectors.toList()));
eventTemplate.setOrgName(baseLineInfo.get(0).getGdName());
eventTemplate.setSubName(baseLineInfo.get(0).getStationName());
eventTemplate.setBusName(baseLineInfo.get(0).getBusBarName());
eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.get(0).getScale()).getDicName());
LedgerBaseInfoDTO baseLineInfo = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid());
eventTemplate.setOrgName(baseLineInfo.getGdName());
eventTemplate.setSubName(baseLineInfo.getStationName());
eventTemplate.setBusName(baseLineInfo.getBusBarName());
eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.getScale()).getDicName());
eventTemplate.setDuration(String.format("%.3f", pqsEventdetail.getPersisttime() / 1000));
eventTemplate.setResidualVoltage(String.format("%.2f", pqsEventdetail.getEventvalue() * 100));
eventTemplate.setUserName(baseLineInfo.get(0).getObjName());
eventTemplate.setUserName(baseLineInfo.getObjName());
Map<String, Object> eventMap = mapper.convertValue(eventTemplate, Map.class);
eventTemplateList.add(eventMap);
@@ -177,10 +184,15 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService {
bjReportDTO.setObjTypeList(treeStr);
bjReportDTO.setAffectedUserCount(pqUserLedgerPOList.size());
log.info(LocalDateTime.now()+"组装公共参数结束");
areaAssemble(bjReportDTO, param, pqsDicDataMap);
log.info(LocalDateTime.now()+"组装特别参数结束");
}
Map<String,Object> map = mapper.convertValue(bjReportDTO,Map.class);
log.info(LocalDateTime.now()+"开始组装word模版");
WordTemplate.generateWordDownload("template/bj_report.docx", response, bjReportDTO.getDateFormat()+"重要敏感用户电压暂降事件监测情况.docx", map);
log.info(LocalDateTime.now()+"结束导出word报告");
@@ -200,6 +212,10 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService {
List<String> areaContentList = new ArrayList<>();
List<Map<String,Object>> eventTemplateList = new ArrayList<>();
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
Map<Integer, LedgerBaseInfoDTO> LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));
List<Map<String, Object>> finalEventTemplateList = eventTemplateList;
param.getDeptList().forEach(deptId->{
String deptName = deptMap.get(deptId);
@@ -253,85 +269,90 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService {
if(!CollectionUtils.isEmpty(lineIds)){
List<PqUserLineAssPO> pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getLineIndex,lineIds));
List<String> userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
LambdaQueryWrapper<PqUserLedgerPO> queryWrapper = new LambdaQueryWrapper<>();
if (userIds.size() > 1000) {
List<List<String>> listUserIds = CollUtil.split(userIds, 1000);
queryWrapper.eq(PqUserLedgerPO::getIsShow,1).and(w -> {
for (List<String> ids : listUserIds) {
w.or(wIn -> wIn.in(PqUserLedgerPO::getId, ids));
}
});
} else {
queryWrapper.eq(PqUserLedgerPO::getIsShow,1).in(PqUserLedgerPO::getId, userIds);
}
List<PqUserLedgerPO> pqUserLedgerPOList = pqUserLedgerMapper.selectList(queryWrapper);
if(CollectionUtils.isEmpty(pqUserLedgerPOList)){
if(CollectionUtils.isEmpty(pqUserLineAssPOS)){
userContext ="不涉及半导体及重点关注用户。";
}else {
String companyName = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining("", "", ""));
userContext="涉及"+pqUserLedgerPOList.size()+"家半导体及重点关注用户"+companyName+"";
//逆推监测点,过滤发生暂降事件
List<String> companyId = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList());
List<PqUserLineAssPO> pqUserLineAssPOS1 = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getUserIndex, companyId));
List<String> companyNameList = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList());
List<Integer> companyLineId= pqUserLineAssPOS1.stream().map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList());
List<PqsEventdetail> companyevent = pqsEventdetailList.stream().filter(pqsEventdetail -> companyLineId.contains(pqsEventdetail.getLineid())).collect(Collectors.toList());
if(CollectionUtils.isEmpty(companyevent)){
userContext =userContext+"暂未发生暂态事件。";
}else {
List<String> userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
for (int i = 0; i < pqsEventdetailList.size(); i++) {
PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i);
List<LedgerBaseInfoDTO> baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetailList.get(i).getLineid()).collect(Collectors.toList()));
if(Objects.isNull(baseLineInfo.get(0).getObjName())){
continue;
LambdaQueryWrapper<PqUserLedgerPO> queryWrapper = new LambdaQueryWrapper<>();
if (userIds.size() > 1000) {
List<List<String>> listUserIds = CollUtil.split(userIds, 1000);
queryWrapper.eq(PqUserLedgerPO::getIsShow,1).and(w -> {
for (List<String> ids : listUserIds) {
w.or(wIn -> wIn.in(PqUserLedgerPO::getId, ids));
}
String[] split = baseLineInfo.get(0).getObjName().split(";");
for (int i1 = 0; i1 < split.length; i1++) {
if(companyNameList.contains(split[i1])){
EventTemplate eventTemplate = new EventTemplate();
eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER)+"."+pqsEventdetail.getMs());
eventTemplate.setOrgName(baseLineInfo.get(0).getGdName());
eventTemplate.setSubName(baseLineInfo.get(0).getStationName());
eventTemplate.setBusName(baseLineInfo.get(0).getBusBarName());
eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.get(0).getScale()).getDicName());
eventTemplate.setDuration(String.format("%.3f",pqsEventdetail.getPersisttime()/1000));
eventTemplate.setResidualVoltage(String.format("%.2f",pqsEventdetail.getEventvalue()*100));
eventTemplate.setUserName(split[i1]);
Map<String,Object> eventMap = mapper.convertValue(eventTemplate,Map.class);
finalEventTemplateList.add(eventMap);
});
} else {
queryWrapper.eq(PqUserLedgerPO::getIsShow,1).in(PqUserLedgerPO::getId, userIds);
}
List<PqUserLedgerPO> pqUserLedgerPOList = pqUserLedgerMapper.selectList(queryWrapper);
if(CollectionUtils.isEmpty(pqUserLedgerPOList)){
userContext ="不涉及半导体及重点关注用户。";
}else {
String companyName = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining("", "", ""));
userContext="涉及"+pqUserLedgerPOList.size()+"家半导体及重点关注用户"+companyName+"";
//逆推监测点,过滤发生暂降事件
List<String> companyId = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList());
List<PqUserLineAssPO> pqUserLineAssPOS1 = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getUserIndex, companyId));
List<String> companyNameList = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList());
List<Integer> companyLineId= pqUserLineAssPOS1.stream().map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList());
List<PqsEventdetail> companyevent = pqsEventdetailList.stream().filter(pqsEventdetail -> companyLineId.contains(pqsEventdetail.getLineid())).collect(Collectors.toList());
if(CollectionUtils.isEmpty(companyevent)){
userContext =userContext+"暂未发生暂态事件。";
}else {
for (int i = 0; i < pqsEventdetailList.size(); i++) {
PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i);
LedgerBaseInfoDTO baseLineInfo = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid());
if(Objects.isNull(baseLineInfo.getObjName())){
continue;
}
String[] split = baseLineInfo.getObjName().split(";");
for (int i1 = 0; i1 < split.length; i1++) {
if(companyNameList.contains(split[i1])){
EventTemplate eventTemplate = new EventTemplate();
eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER)+"."+pqsEventdetail.getMs());
eventTemplate.setOrgName(baseLineInfo.getGdName());
eventTemplate.setSubName(baseLineInfo.getStationName());
eventTemplate.setBusName(baseLineInfo.getBusBarName());
eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.getScale()).getDicName());
eventTemplate.setDuration(String.format("%.3f",pqsEventdetail.getPersisttime()/1000));
eventTemplate.setResidualVoltage(String.format("%.2f",pqsEventdetail.getEventvalue()*100));
eventTemplate.setUserName(split[i1]);
Map<String,Object> eventMap = mapper.convertValue(eventTemplate,Map.class);
finalEventTemplateList.add(eventMap);
}
}
}
Integer companyEveCount = companyevent.size();
List<Integer> companyLineIds = companyevent.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList());
List<LedgerBaseInfoDTO> companyLedgerBaseInfoDTOList = pqLineMapper.getBaseLedger(companyLineIds,null);
long companyStationCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
long companyBusCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();
String companyStationStr = stationVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap);
String companyAreabusVoltageDeal = areabusVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap);
String companyMin =String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01) ;
String companyMax = String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01) ;
String companyResidualVoltage = companyMin+"%-"+companyMax+"%";
double companyMinPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000;
double companyMaxPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()/1000;
String companyDuration = companyMinPersisTime+"s-"+companyMaxPersisTime+"s";
String companyTemp ="电压暂降事件%s条变电站%s座母线%s条其中%s造成%s发生电压暂降残余电压范围为%s持续时间范围为%s。";
userContext = userContext+String.format(companyTemp,companyEveCount,companyStationCount,companyBusCount,companyStationStr,companyAreabusVoltageDeal,companyResidualVoltage,companyDuration);
}
Integer companyEveCount = companyevent.size();
List<Integer> companyLineIds = companyevent.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList());
List<LedgerBaseInfoDTO> companyLedgerBaseInfoDTOList = pqLineMapper.getBaseLedger(companyLineIds,null);
long companyStationCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
long companyBusCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();
String companyStationStr = stationVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap);
String companyAreabusVoltageDeal = areabusVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap);
String companyMin =String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01) ;
String companyMax = String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01) ;
String companyResidualVoltage = companyMin+"%-"+companyMax+"%";
double companyMinPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000;
double companyMaxPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()/1000;
String companyDuration = companyMinPersisTime+"s-"+companyMaxPersisTime+"s";
String companyTemp ="电压暂降事件%s条变电站%s座母线%s条其中%s造成%s发生电压暂降残余电压范围为%s持续时间范围为%s。";
userContext = userContext+String.format(companyTemp,companyEveCount,companyStationCount,companyBusCount,companyStationStr,companyAreabusVoltageDeal,companyResidualVoltage,companyDuration);
}
}
}else {
userContext ="不涉及半导体及重点关注用户。";
}

View File

@@ -3,9 +3,10 @@ package com.njcn.product.event.transientes.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.annotation.OperateInfo;
@@ -13,6 +14,8 @@ import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.event.file.pojo.dto.WaveDataDTO;
import com.njcn.product.event.devcie.config.PqlineCache;
import com.njcn.product.event.devcie.job.LineCacheJob;
import com.njcn.product.event.devcie.mapper.PqLineMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqLine;
@@ -20,17 +23,16 @@ import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.mapper.PqUserLedgerMapper;
import com.njcn.product.event.transientes.mapper.PqUserLineAssMapper;
import com.njcn.product.event.transientes.pojo.dto.MsgDTO;
import com.njcn.product.event.transientes.mapper.PqsEventdetailMapper;
import com.njcn.product.event.transientes.pojo.dto.SmsResponseDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsSendDTO;
import com.njcn.product.event.transientes.pojo.dto.UpLoadEvent;
import com.njcn.product.event.transientes.pojo.param.MonitorTerminalParam;
import com.njcn.product.event.transientes.pojo.param.SimulationMsgParam;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.*;
import com.njcn.product.event.transientes.service.impl.MsgEventInfoServiceImpl;
import com.njcn.product.event.transientes.utils.SmsUtils;
import com.njcn.product.event.transientes.websocket.WebSocketServer;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.product.event.config.RedisUtil;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.HttpResultUtil;
import io.swagger.annotations.Api;
@@ -39,15 +41,12 @@ import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -66,9 +65,9 @@ import static com.njcn.product.event.transientes.pojo.constant.RedisConstant.RED
@RequiredArgsConstructor
@Slf4j
public class EventGateController extends BaseController {
private final MsgEventInfoServiceImpl msgEventInfoServiceImpl;
private final PqUserLineAssMapper pqUserLineAssMapper;
private final PqUserLedgerMapper pqUserLedgerMapper;
private final PqsEventdetailMapper pqsEventdetailMapper;
@Value("${SYS_TYPE_ZT}")
private String sysTypeZt;
@@ -95,6 +94,8 @@ public class EventGateController extends BaseController {
private final SmsUtils smsUtils;
private final ThreadPoolTaskExecutor smsTaskExecutor;
private final PqlineCache pqlineCache;
@OperateInfo
@GetMapping("/eventMsg")
@@ -102,7 +103,7 @@ public class EventGateController extends BaseController {
@ApiImplicitParam(name = "eventMsg", value = "暂态事件json字符", required = true)
public HttpResult<Object> eventMsg(@RequestParam("msg") String msg) {
String methodDescribe = getMethodDescribe("eventMsg");
log.info("收到前置推送暂降事件"+msg);
log.info("收到前置推送暂降事件,事件详情:" + msg);
JSONObject jsonObject;
try {
@@ -113,28 +114,37 @@ public class EventGateController extends BaseController {
if (msgEventConfigService.getEventType().contains(jsonObject.get("wavetype").toString())
&& Float.parseFloat(jsonObject.get("eventvalue").toString()) <= msgEventConfigService.getEventValue()
&& (Float.parseFloat(jsonObject.get("persisttime").toString())*1000) >= msgEventConfigService.getEventDuration()) {
&& (Float.parseFloat(jsonObject.get("persisttime").toString()) * 1000) >= msgEventConfigService.getEventDuration()) {
//过滤重要暂降事件
Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().eq(PqUserLineAssPO::getLineIndex,lineId));
String str ="/";
if(CollUtil.isNotEmpty(assList)){
List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().select(PqUserLedgerPO::getId,PqUserLedgerPO::getCustomerName).in(PqUserLedgerPO::getId,userIds));
str = poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining(StrUtil.COMMA));
jsonObject.set("persisttime",new BigDecimal(jsonObject.get("persisttime").toString()).setScale(3,RoundingMode.HALF_UP).toString());
Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().eq(PqUserLineAssPO::getLineIndex, lineId));
String str;
if (CollUtil.isNotEmpty(assList)) {
List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().select(PqUserLedgerPO::getId, PqUserLedgerPO::getCustomerName).in(PqUserLedgerPO::getId, userIds));
str = poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining(";"));
} else {
str = "/";
}
List<PqsDepts> deptsList = (List<PqsDepts>)redisUtil.getObjectByKey(REDIS_DEPT_INDEX+ StrUtil.DASHED+"AllDept");
Map<String,PqsDepts> deptsMap = deptsList.stream().collect(Collectors.toMap(PqsDepts::getDeptsIndex,dept->dept));
List<PqsDepts> deptsList = (List<PqsDepts>) redisUtil.getObjectByKey(REDIS_DEPT_INDEX + StrUtil.DASHED + "AllDept");
Map<String, PqsDepts> deptsMap = deptsList.stream().collect(Collectors.toMap(PqsDepts::getDeptsIndex, dept -> dept));
List<PqsDeptsline> deptslineList = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex,lineId).list();
List<PqsDeptsline> deptslineList = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).list();
List<String> deptIds = deptslineList.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toList());
Set<String> set =getAllParentIdsWithChildrenBatch(deptIds,deptsMap);
jsonObject.putOpt("objName",str);
Set<String> set = getAllParentIdsWithChildrenBatch(deptIds, deptsMap);
jsonObject.putOpt("objName", str);
jsonObject.putOpt("dept", String.join(StrUtil.COMMA, set));
webSocketServer.sendMessageToAll(jsonObject.toString());
//针对前置推送的暂降事件进行短信发送功能
smsTaskExecutor.execute(() -> {
sendMessage(jsonObject, str);
});
}
} catch (Exception e) {
@@ -178,15 +188,15 @@ public class EventGateController extends BaseController {
//下面一行代码正式环境需要放开
jsonObject = test();
if (msgEventConfigService.getEventType().contains(jsonObject.get("wavetype").toString()) &&Float.parseFloat(jsonObject.get("eventvalue").toString()) <= msgEventConfigService.getEventValue()) {
if (msgEventConfigService.getEventType().contains(jsonObject.get("wavetype").toString()) && Float.parseFloat(jsonObject.get("eventvalue").toString()) <= msgEventConfigService.getEventValue()) {
webSocketServer.sendMessageToAll(jsonObject.toString());
//开始发送短信
try {
sendMessage(jsonObject);
}catch (Exception e){
sendMessage(jsonObject, "/");
} catch (Exception e) {
e.printStackTrace();
log.error("短信组装发送失败!失败原因{}",e.getMessage());
log.error("短信组装发送失败!失败原因{}", e.getMessage());
}
}
@@ -197,6 +207,8 @@ public class EventGateController extends BaseController {
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
}
private static final int MAX_RETRY_COUNT = 3; // 最大重试次数
//测试模拟,正式环境删除
private PqsEventdetail createEvent(JSONObject jsonObject, LocalDateTime now) {
@@ -235,7 +247,7 @@ public class EventGateController extends BaseController {
Integer wave = random.nextInt(2);
Double per = (double)random.nextInt(5000);
Double per = (double) random.nextInt(5000);
double minV = 0.1;
double maxV = 0.9;
@@ -279,72 +291,126 @@ public class EventGateController extends BaseController {
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@PostMapping("/simulationSend")
@GetMapping("/phoneSend")
@ApiOperation("模拟发送短信")
public HttpResult<WaveDataDTO> simulationSend(@RequestBody @Validated SimulationMsgParam param) {
public HttpResult<String> simulationSend(@RequestParam("id") String id) {
String methodDescribe = getMethodDescribe("simulationSend");
PqsEventdetail pqsEventdetail = pqsEventdetailMapper.selectOne(new LambdaQueryWrapper<PqsEventdetail>().eq(PqsEventdetail::getEventdetailIndex, id));
UpLoadEvent upLoadEvent = new UpLoadEvent();
upLoadEvent.setEventdetail_index(pqsEventdetail.getEventdetailIndex());
upLoadEvent.setMs(pqsEventdetail.getMs());
upLoadEvent.setBdname("测试电站");
upLoadEvent.setLineid(pqsEventdetail.getLineid());
upLoadEvent.setTimeid(LocalDateTimeUtil.format(pqsEventdetail.getTimeid(), DatePattern.NORM_DATETIME_PATTERN));
upLoadEvent.setWavetype(pqsEventdetail.getWavetype());
upLoadEvent.setPersisttime(pqsEventdetail.getPersisttime());
upLoadEvent.setEventvalue(pqsEventdetail.getEventvalue());
upLoadEvent.setEventreason("");
upLoadEvent.setEventtype(pqsEventdetail.getEventtype());
upLoadEvent.setPointname("测试监测点");
upLoadEvent.setGdname("测试供电公司");
JSONObject jsonObject = new JSONObject(upLoadEvent);
sendMessage(jsonObject, "/");
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
}
private void sendMessage(JSONObject jsonObject){
Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list();
Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet());
Set<String> resultIds = getAllParentDeptIds(deptIds);
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@GetMapping("/simpleTest")
@ApiOperation("模拟发送简单测试短信")
public HttpResult<Object> simpleTest() {
String methodDescribe = getMethodDescribe("simulationSend");
List<SmsSendDTO.ItemInner> msgDTOList = new ArrayList<>();
SmsSendDTO.ItemInner msgDTO = new SmsSendDTO.ItemInner();
msgDTO.setCustomMsgID(IdUtil.simpleUUID());
msgDTO.setContent("test");
msgDTO.setTo("18815508963");
msgDTOList.add(msgDTO);
List<SmsResponseDTO.SmsItem> result = smsUtils.sendSmSToUser(msgDTOList);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
List<PqsUserSet> pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list();
if (CollUtil.isEmpty(pqsUserSetList)) {
//当前事件未找到用户信息,判断为不需要发送短信用户
return;
}
List<PqsUser> pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex,PqsUser::getPhone,PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list();
List<String> userIds = pqsUserList.stream().map(PqsUser::getUserIndex).collect(Collectors.toList());
List<PqsUserSet> poList = pqsUserSetList.stream().filter(it -> userIds.contains(it.getUserIndex())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(poList)) {
StringBuilder stringBuilder = new StringBuilder(jsonObject.get("timeid").toString());
List<LedgerBaseInfoDTO> list = pqLineMapper.getBaseLineInfo(Stream.of(lineId).collect(Collectors.toList()));
LedgerBaseInfoDTO ledgerBaseInfoDTO = list.get(0);
BigDecimal bigDecimal = new BigDecimal(jsonObject.get("eventvalue").toString()).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
stringBuilder.append(".").append(jsonObject.get("ms").toString()).append(", ").append(ledgerBaseInfoDTO.getStationName()).append(ledgerBaseInfoDTO.getLineName())
.append("发生暂降事件,事件特征幅值").append(bigDecimal).append("%,持续时间:").append(jsonObject.get("persisttime").toString()).append("S");
//TODO 发送短信
// System.out.println(stringBuilder);
List<MsgEventInfo> resultList = new ArrayList<>();
List<MsgDTO> msgDTOList = new ArrayList<>();
for (PqsUser user : pqsUserList) {
String msgId = IdUtil.simpleUUID();
private void sendMessage(JSONObject jsonObject, String objStr) {
try {
if (!"/".equals(objStr)) {
log.info("-------------------------开始执行短信发送逻辑{}", System.currentTimeMillis());
TimeInterval timeInterval = new TimeInterval();
Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list();
Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet());
Set<String> resultIds = getAllParentDeptIds(deptIds);
MsgDTO dto = new MsgDTO();
dto.setMessage(stringBuilder.toString());
dto.setPhone(user.getPhone());
dto.setCustomMsgID(msgId);
msgDTOList.add(dto);
MsgEventInfo msgEventInfo = new MsgEventInfo();
msgEventInfo.setMsgIndex(msgId);
msgEventInfo.setMsgContent(stringBuilder.toString());
msgEventInfo.setPhone(user.getPhone());
msgEventInfo.setUserId(user.getUserIndex());
msgEventInfo.setUserName(user.getName());
msgEventInfo.setIsHandle(0);
msgEventInfo.setSendResult(0);
msgEventInfo.setSendTime(LocalDateTime.now());
msgEventInfo.setEventIndex(jsonObject.get("eventdetail_index").toString());
resultList.add(msgEventInfo);
}
List<SmsResponseDTO.SmsItem> result = smsUtils.sendSmSToUser(msgDTOList);
Map<String,SmsResponseDTO.SmsItem> stringSmsItemMap = result.stream().collect(Collectors.toMap(SmsResponseDTO.SmsItem::getCustomMsgID,Function.identity()));
resultList.forEach(item->{
if(stringSmsItemMap.containsKey(item.getMsgIndex())){
SmsResponseDTO.SmsItem smsItem = stringSmsItemMap.get(item.getMsgIndex());
item.setSendResult(Objects.equals(smsItem.getCode(),"0")?1:0);
List<PqsUserSet> pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list();
if (CollUtil.isEmpty(pqsUserSetList)) {
//当前事件未找到用户信息,判断为不需要发送短信用户
return;
}
});
msgEventInfoService.saveBatch(resultList);
List<PqsUser> pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex, PqsUser::getPhone, PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list();
List<String> userIds = pqsUserList.stream().map(PqsUser::getUserIndex).collect(Collectors.toList());
List<PqsUserSet> poList = pqsUserSetList.stream().filter(it -> userIds.contains(it.getUserIndex())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(poList)) {
StringBuilder stringBuilder = new StringBuilder(jsonObject.get("timeid").toString());
BigDecimal bigDecimal = new BigDecimal(jsonObject.get("eventvalue").toString()).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
stringBuilder.append(".").append(jsonObject.get("ms").toString()).append(",").append(jsonObject.get("bdname").toString()).append("_").append(jsonObject.get("busname").toString()).append("_").append(jsonObject.get("pointname").toString())
.append("发生电压暂降事件,事件残余电压").append(bigDecimal).append("%,持续时间:").append(jsonObject.get("persisttime").toString()).append("S;影响用户:");
stringBuilder.append(objStr);
//TODO 临时处理,后面需要用上
String message;
if (stringBuilder.length() > 500) {
message = stringBuilder.substring(0, 490).concat(";详情请登录电压暂降监测平台查看。");
} else {
message = stringBuilder.toString();
}
List<MsgEventInfo> resultList = new ArrayList<>();
List<SmsSendDTO.ItemInner> msgDTOList = new ArrayList<>();
for (PqsUser user : pqsUserList) {
String msgId = IdUtil.simpleUUID();
SmsSendDTO.ItemInner dto = new SmsSendDTO.ItemInner();
dto.setContent(message);
dto.setTo(user.getPhone());
dto.setCustomMsgID(msgId);
msgDTOList.add(dto);
MsgEventInfo msgEventInfo = new MsgEventInfo();
msgEventInfo.setMsgIndex(msgId);
msgEventInfo.setMsgContent(message);
msgEventInfo.setPhone(user.getPhone());
msgEventInfo.setUserId(user.getUserIndex());
msgEventInfo.setUserName(user.getName());
msgEventInfo.setIsHandle(0);
msgEventInfo.setSendResult(0);
msgEventInfo.setSendTime(LocalDateTime.now());
msgEventInfo.setEventIndex(jsonObject.get("eventdetail_index").toString());
resultList.add(msgEventInfo);
}
List<SmsResponseDTO.SmsItem> result = smsUtils.sendSmSToUser(msgDTOList);
Map<String, SmsResponseDTO.SmsItem> stringSmsItemMap = result.stream().collect(Collectors.toMap(SmsResponseDTO.SmsItem::getCustomMsgID, Function.identity()));
resultList.forEach(item -> {
if (stringSmsItemMap.containsKey(item.getMsgIndex())) {
SmsResponseDTO.SmsItem smsItem = stringSmsItemMap.get(item.getMsgIndex());
item.setSendResult(Objects.equals(smsItem.getCode(), "0") ? 1 : 0);
}
});
msgEventInfoService.saveBatch(resultList);
}
log.info("{}-------------短信发送执行结束,执行时长{}s", System.currentTimeMillis(), timeInterval.intervalSecond());
}
} catch (Exception e) {
e.printStackTrace();
log.error("---------短信发送异常,异常信息", e);
}
}
@@ -356,9 +422,7 @@ public class EventGateController extends BaseController {
return "token";
}
private boolean apiSend(){
private boolean apiSend() {
return false;
@@ -395,6 +459,11 @@ public class EventGateController extends BaseController {
}
return result;
}
@GetMapping("/refreshIdCache")
@ApiOperation("刷新缓存")
public Boolean refreshIdCache() {
pqlineCache.init();
return true;// HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, true, "数据同步");
}
}

View File

@@ -1,10 +1,14 @@
package com.njcn.product.event.transientes.controller;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.constant.OperateType;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.product.event.dataTransmit.DataSynchronization;
import com.njcn.product.event.devcie.pojo.dto.DeviceDTO;
import com.njcn.product.event.transientes.pojo.param.LargeScreenCountParam;
import com.njcn.product.event.transientes.pojo.param.MessageEventFeedbackParam;
@@ -18,6 +22,7 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -274,5 +279,27 @@ public class LargeScreenCountController extends BaseController {
Page<EventDetailVO> result = largeScreenCountService.userEventList(largeScreenCountParam);
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@PostMapping("/exportLineData")
@ApiOperation("导出台账数据数据")
public void exportEventData() {
largeScreenCountService.exportLineData();
}
@Autowired
private DataSynchronization synchronization;
@GetMapping("sycnEvent")
public boolean sycnEvent(@RequestParam("startDateTime") String startDateTime,@RequestParam("endDateTime") String endDateTime) throws Exception {
synchronization.syncEvents(LocalDateTimeUtil.parse(startDateTime, DatePattern.NORM_DATETIME_PATTERN),LocalDateTimeUtil.parse(endDateTime, DatePattern.NORM_DATETIME_PATTERN));
return true;
}
@GetMapping("sycnUser")
public boolean sycnUser() throws Exception {
synchronization.syncUser();
return true;
}
}

View File

@@ -22,6 +22,8 @@ public class PqUserLedgerController {
@Autowired
private PqUserLedgerService pqUserLedgerService;
// 添加记录
@PostMapping("addLedger")
public boolean addLedger(@RequestBody PqUserLedgerParam ledgerParam) {

View File

@@ -28,8 +28,8 @@ import java.util.zip.ZipOutputStream;
@RequiredArgsConstructor
public class ScheduledEvent implements SchedulingConfigurer {
@Value("${}")
private final String cronStr = "";
// @Value("${}")
private final String cronStr = "0 0 */2 * * ?";
// 源文件夹路径
private final String sourceFolderPath = "D:\\";

View File

@@ -0,0 +1,58 @@
package com.njcn.product.event.transientes.pojo.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* Description:
* Date: 2025/10/22 上午 10:37【需求编号】
*
* @author clam
* @version V1.0.0
*/
@Data
public class UpLoadEvent {
/**
* eventdetail_index : d4963f8f-201f-443f-b293-dda8ef870ee6
* lineid : 1591
* timeid : 2025-10-09 13:25:14
* ms : 509
* describe :
* wavetype : 1
* persisttime : 23.000
* eventvalue : 0.6
* eventreason :
* eventtype :
* gdname :
* bdname : 110kV皇后店变
* pointname : 232待用
* wavePath : 192.168.1.102/3_20240515_163022_349
*/
private String eventdetail_index;
private Integer lineid;
private String timeid;
private BigDecimal ms;
private String describe;
private Integer wavetype;
private Double persisttime;
private Double eventvalue;
private String eventreason;
private String eventtype;
private String gdname;
private String bdname;
private String busname;
private String pointname;
private String wavePath;
private String ip;
private int pt;
private int ct;
private int ptType;
}

View File

@@ -0,0 +1,21 @@
package com.njcn.product.event.transientes.pojo.dto;
import com.njcn.product.event.transientes.pojo.po.PqUserLedgerPO;
import com.njcn.product.event.transientes.pojo.po.PqUserLineAssPO;
import lombok.Data;
import java.util.List;
/**
* Description:
* Date: 2025/10/28 下午 2:32【需求编号】
*
* @author clam
* @version V1.0.0
*/
@Data
public class UpLoadUserDTO {
private List<UserLegerDTO> userList;
private List<UserLineAssDTO> assList;
}

View File

@@ -0,0 +1,34 @@
package com.njcn.product.event.transientes.pojo.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
/**
* Description:
* Date: 2025/10/28 下午 2:47【需求编号】
*
* @author clam
* @version V1.0.0
*/
@Data
public class UserLegerDTO {
private String id;
private String powerSupplyArea;
private String customerNo;
private String customerName;
private String electricityAddress;
private String bigObjType;
private String smallObjType;
private Integer isShow;
}

View File

@@ -0,0 +1,19 @@
package com.njcn.product.event.transientes.pojo.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
/**
* Description:
* Date: 2025/10/28 下午 2:49【需求编号】
*
* @author clam
* @version V1.0.0
*/
@Data
public class UserLineAssDTO {
private String userIndex;
private Integer lineIndex;
}

View File

@@ -2,6 +2,7 @@ package com.njcn.product.event.transientes.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@@ -13,18 +14,19 @@ import java.util.Date;
* @Description: 暂降事件同步记录
*/
@Data
@TableName(value = "PQS_EVENTDETAIL_STATUS")
public class PqsEventDetailStatusPO {
@TableId(value = "EVENT_DETAIL_ID")
private String eventDetailId;
@TableField(value = "EVENT_TIME")
private Date eventTime;
private LocalDateTime eventTime;
@TableField(value = "WAVE_FLAG")
private int waveFlag;
@TableField(value = "SYNC_STATUE")
@TableField(value = "SYNC_STATUS")
private int syncStatus;
@TableField(value = "SYNC_TIME")

View File

@@ -96,6 +96,10 @@ public class PqsEventdetail {
@TableField(value = "NOTICE_FLAG")
private Integer noticeFlag;
@TableField(value = "CREATE_TIME")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@TableField(exist = false)
private Integer eventSeverity;

View File

@@ -3,7 +3,7 @@ package com.njcn.product.event.transientes.security;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.product.event.transientes.utils.JwtUtil;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.product.event.config.RedisUtil;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.HttpResultUtil;
import io.swagger.annotations.ApiOperation;
@@ -47,6 +47,8 @@ public class AuthController extends BaseController {
//针对系统推送的认证特殊处理
if ("system_event".equals(authRequest.getUsername())) {
pass = authRequest.getPassword();
} else if ("cn_test_a".equals(authRequest.getUsername())) {
pass = authRequest.getPassword();
} else {
hasFlag = redisUtil.hasKey(eventRedisKey + authRequest.getUsername());
if (hasFlag) {

View File

@@ -5,7 +5,7 @@ import com.njcn.product.event.transientes.mapper.PqsUserMapper;
import com.njcn.product.event.transientes.mapper.PqsUserSetMapper;
import com.njcn.product.event.transientes.pojo.po.PqsUser;
import com.njcn.product.event.transientes.pojo.po.PqsUserSet;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.product.event.config.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -39,6 +39,13 @@ public class MyUserDetailsService implements UserDetailsService {
new ArrayList<>());
}
if("cn_test_a".equals(username)){
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode("@#001njcnpqs");
return new MyUserDetails("12345678910","system_event",encodedPassword,"10001",
new ArrayList<>());
}
if(redisUtil.hasKey("event_smart_"+username)){
String password = redisUtil.getRawValue("event_smart_"+username);

View File

@@ -34,8 +34,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
// .antMatchers("/cn_authenticate","/ws/**","/accept/testEvent","/accept/eventMsg").permitAll() // 允许访问认证接口
.antMatchers("/**").permitAll() // 允许访问认证接口
.antMatchers("/cn_authenticate","/ws/**","/accept/testEvent","/accept/eventMsg","/accept/simpleTest","/accept/phoneSend","/accept/refreshIdCache","/largescreen/sycnUser").permitAll() // 允许访问认证接口
// .antMatchers("/**").permitAll() // 允许访问认证接口
.anyRequest().authenticated()
.and()
.sessionManagement()

View File

@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.pojo.param.LargeScreenCountParam;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.product.event.config.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

View File

@@ -64,4 +64,6 @@ public interface LargeScreenCountService {
Page<DeviceDTO> devicePage(LargeScreenCountParam largeScreenCountParam);
Page<EventDetailVO> userEventList(LargeScreenCountParam largeScreenCountParam);
void exportLineData();
}

View File

@@ -0,0 +1,13 @@
package com.njcn.product.event.transientes.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.njcn.product.event.transientes.pojo.po.PqsEventDetailStatusPO;
/**
* CN_Product
*
* @author cdf
* @date 2025/10/24
*/
public interface PqsEventDetailStatusService extends IService<PqsEventDetailStatusPO> {
}

View File

@@ -2,6 +2,7 @@ package com.njcn.product.event.transientes.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.*;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -14,6 +15,7 @@ import com.beust.ah.A;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.product.event.config.RedisUtil;
import com.njcn.product.event.devcie.mapper.*;
import com.njcn.product.event.devcie.pojo.dto.*;
import com.njcn.product.event.devcie.pojo.po.*;
@@ -31,10 +33,11 @@ import com.njcn.product.event.transientes.pojo.vo.*;
import com.njcn.product.event.devcie.service.*;
import com.njcn.product.event.transientes.service.*;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.ExcelUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -697,6 +700,9 @@ public class LargeScreenCountServiceImpl implements LargeScreenCountService {
LambdaQueryWrapper<MsgEventInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(!StringUtils.isEmpty(largeScreenCountParam.getSendResult()), MsgEventInfo::getSendResult, largeScreenCountParam.getSendResult());
lambdaQueryWrapper.orderByDesc(MsgEventInfo::getSendTime).between(MsgEventInfo::getSendTime, start, end);
if(StrUtil.isNotBlank(largeScreenCountParam.getSearchValue())){
lambdaQueryWrapper.and(w->w.like(MsgEventInfo::getUserName,largeScreenCountParam.getSearchValue()).or().like(MsgEventInfo::getPhone,largeScreenCountParam.getSearchValue()));
}
return msgEventInfoService.page(new Page<>(PageFactory.getPageNum(largeScreenCountParam), PageFactory.getPageSize(largeScreenCountParam)), lambdaQueryWrapper);
}
@@ -1670,5 +1676,22 @@ public class LargeScreenCountServiceImpl implements LargeScreenCountService {
return result;
}
@Override
public void exportLineData() {
List<LedgerExcelDTO> ledgerExcelDTOList;
List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
ledgerExcelDTOList = ledgerBaseInfoDTOS.stream().map(temp->{
LedgerExcelDTO ledgerExcelDTO = new LedgerExcelDTO();
BeanUtils.copyProperties(temp,ledgerExcelDTO);
return ledgerExcelDTO;
}).collect(Collectors.toList());
if (CollectionUtil.isEmpty(ledgerExcelDTOList)) {
ExcelUtil.exportExcel("台账数据.xls", "台账数据", LedgerExcelDTO.class, new ArrayList<>());
} else {
ExcelUtil.exportExcel("台账数据.xls", "台账数据", LedgerExcelDTO.class, ledgerExcelDTOList);
}
}
}

View File

@@ -0,0 +1,19 @@
package com.njcn.product.event.transientes.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.product.event.transientes.mapper.PqsEventDetailStatusMapper;
import com.njcn.product.event.transientes.pojo.po.PqsEventDetailStatusPO;
import com.njcn.product.event.transientes.service.PqsEventDetailStatusService;
import org.springframework.stereotype.Service;
/**
* CN_Product
*PqsEventDetailStatusPO
* @author cdf
* @date 2025/10/24
*/
@Service
public class PqsEventDetailStatusServiceImpl extends ServiceImpl<PqsEventDetailStatusMapper, PqsEventDetailStatusPO> implements PqsEventDetailStatusService {
}

View File

@@ -0,0 +1,483 @@
package com.njcn.product.event.transientes.utils;
import cn.hutool.core.lang.UUID;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
/**
* @Author: cdf
* @CreateTime: 2025-10-21
* @Description:
*/
@Component
@Slf4j
public class OssFileStorageUtils {
@Value("${aliyun.oss.endpoint}")
private String endpoint="oss-cn-beijing.aliyuncs.com";
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId="LTAI5tQYuyu1PpiCdeM74PT6";
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret="vTGHcQOCF9u7w9FL3HAHJO1oufVWru";
@Value("${aliyun.oss.bucketName}")
private String bucketName= "cn-comtrade";
@Value("${aliyun.oss.basePath:pqmm}")
private String basePath;
private OSS ossClient;
@PostConstruct
public void init() {
// 初始化 OSS 客户端
this.ossClient = new OSSClientBuilder().build(
endpoint,
accessKeyId,
accessKeySecret
);
}
/**
* 将对象直接以JSON流的形式上传到OSS
*
* @param object 要上传的Java对象
* @param objectName 在OSS上保存的路径和文件名 (例如: "data/user001.json")
* @throws IOException
*/
public void uploadObjectAsJsonStream(Object object, String objectName) throws IOException {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 使用try-with-resources确保ByteArrayInputStream被关闭
ByteArrayInputStream inputStream = convertObjectToJsonStream(object);
try {
// 创建上传请求。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, basePath+objectName, inputStream);
// 可选设置对象元信息如Content-Type
// ObjectMetadata metadata = new ObjectMetadata();
// metadata.setContentType("application/json");
// putObjectRequest.setMetadata(metadata);
// 执行上传。
ossClient.putObject(putObjectRequest);
System.out.println("JSON对象已直接上传至OSS: " + objectName);
} finally {
inputStream.close();
}
}
/**
* 上传本地文件到阿里云OSS
*
* @param localFilePath 本地文件的完整路径
* @return 文件在OSS上的访问URL
*/
public String uploadLocalFile(String localFilePath,String targetPath) {
File file = new File(localFilePath);
if (!file.exists()) {
log.info("本地波形文件不存在"+localFilePath );
return null;
}
// 生成唯一的文件名,防止覆盖:cite[5]:cite[8]
String originalFileName = file.getName();
originalFileName = basePath+targetPath+"/"+originalFileName;
try {
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, originalFileName, file);
// 执行上传
ossClient.putObject(putObjectRequest);
// 生成文件的访问URL:cite[7]:cite[8]
String fileUrl = "https://" + bucketName + "." + endpoint + "/" + originalFileName;
log.info("文件上传成功,访问地址: {}", fileUrl);
return fileUrl;
} catch (OSSException oe) {
log.error("OSS服务异常: {}", oe.getErrorMessage());
} catch (Exception e) {
log.error("文件上传失败: ", e);
}
// 在实际项目中,可以考虑抛出自定义异常
return null;
}
/**
* 将Java对象序列化为JSON字节流
*
* @param object Java对象
* @return 包含JSON数据的ByteArrayInputStream
* @throws IOException
*/
private ByteArrayInputStream convertObjectToJsonStream(Object object) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
// 将对象序列化为JSON字节数组
byte[] jsonBytes = objectMapper.writeValueAsBytes(object);
// 返回字节数组输入流
return new ByteArrayInputStream(jsonBytes);
}
/**
* 上传文件流到OSS
*
* @param inputStream 文件输入流
* @param fileName 文件名
* @param contentType 文件类型
* @return 文件访问URL
*/
public String uploadFileStream(InputStream inputStream, String fileName, String contentType) {
if (inputStream == null) {
throw new IllegalArgumentException("文件输入流不能为空");
}
if (fileName == null || fileName.trim().isEmpty()) {
throw new IllegalArgumentException("文件名不能为空");
}
try {
// 生成唯一文件名
String fileExtension = getFileExtension(fileName);
String uniqueFileName = UUID.randomUUID().toString() + fileExtension;
// 构建文件路径
String filePath = basePath + "/" + uniqueFileName;
// 上传文件
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream);
// 设置文件元数据
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(contentType);
putObjectRequest.setMetadata(metadata);
// 执行上传
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 关闭输入流
inputStream.close();
// 返回文件访问URL
return getFileUrl(filePath);
} catch (IOException e) {
throw new RuntimeException("文件上传失败", e);
}
}
/**
* 上传文件到OSS
*
* @param file 上传的文件
* @return 文件访问URL
*/
public String uploadFile(MultipartFile file) {
if (file == null || file.isEmpty()) {
throw new IllegalArgumentException("上传文件不能为空");
}
try {
// 生成唯一文件名
String originalFilename = file.getOriginalFilename();
String fileExtension = getFileExtension(originalFilename);
String uniqueFileName = UUID.randomUUID() + fileExtension;
// 构建文件路径
String filePath = basePath + "/" + uniqueFileName;
// 上传文件
InputStream inputStream = file.getInputStream();
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream);
// 设置文件元数据
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());
metadata.setContentType(file.getContentType());
putObjectRequest.setMetadata(metadata);
// 执行上传
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 关闭输入流
inputStream.close();
// 返回文件访问URL
return getFileUrl(filePath);
} catch (IOException e) {
throw new RuntimeException("文件上传失败", e);
}
}
/**
* 上传文件到指定目录
*
* @param file 上传的文件
* @param directory 目录路径
* @return 文件访问URL
*/
public String uploadFileToDirectory(MultipartFile file, String directory) {
if (file == null || file.isEmpty()) {
throw new IllegalArgumentException("上传文件不能为空");
}
if (directory == null || directory.trim().isEmpty()) {
throw new IllegalArgumentException("目录路径不能为空");
}
try {
// 生成唯一文件名
String originalFilename = file.getOriginalFilename();
String fileExtension = getFileExtension(originalFilename);
String uniqueFileName = UUID.randomUUID().toString() + fileExtension;
// 构建文件路径
String filePath = directory + "/" + uniqueFileName;
// 上传文件
InputStream inputStream = file.getInputStream();
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, inputStream);
// 设置文件元数据
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());
metadata.setContentType(file.getContentType());
putObjectRequest.setMetadata(metadata);
// 执行上传
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 关闭输入流
inputStream.close();
// 返回文件访问URL
return getFileUrl(filePath);
} catch (IOException e) {
throw new RuntimeException("文件上传失败", e);
}
}
/**
* 删除OSS上的文件
*
* @param fileUrl 文件URL
* @return 是否删除成功
*/
public boolean deleteFile(String fileUrl) {
if (fileUrl == null || fileUrl.trim().isEmpty()) {
throw new IllegalArgumentException("文件URL不能为空");
}
try {
// 从URL中提取文件路径
String filePath = extractFilePathFromUrl(fileUrl);
// 检查文件是否存在
if (ossClient.doesObjectExist(bucketName, filePath)) {
// 删除文件
ossClient.deleteObject(bucketName, filePath);
return true;
}
return false;
} catch (Exception e) {
throw new RuntimeException("文件删除失败", e);
}
}
/**
* 获取文件访问URL
*
* @param filePath 文件路径
* @return 文件访问URL
*/
public String getFileUrl(String filePath) {
if (filePath == null || filePath.trim().isEmpty()) {
throw new IllegalArgumentException("文件路径不能为空");
}
// 构建文件URL
return "https://" + bucketName + "." + endpoint + "/" + filePath;
}
/**
* 获取带签名的临时URL默认1小时有效期
*
* @param filePath 文件路径
* @return 带签名的临时URL
*/
public String getSignedUrl(String filePath) {
return getSignedUrl(filePath, 3600);
}
/**
* 获取带签名的临时URL
*
* @param filePath 文件路径
* @param expirationSeconds 过期时间(秒)
* @return 带签名的临时URL
*/
public String getSignedUrl(String filePath, int expirationSeconds) {
if (filePath == null || filePath.trim().isEmpty()) {
throw new IllegalArgumentException("文件路径不能为空");
}
if (expirationSeconds <= 0) {
throw new IllegalArgumentException("过期时间必须大于0");
}
try {
// 设置URL过期时间
Date expiration = new Date(System.currentTimeMillis() + expirationSeconds * 1000L);
// 生成签名URL
URL url = ossClient.generatePresignedUrl(bucketName, filePath, expiration);
return url.toString();
} catch (Exception e) {
throw new RuntimeException("生成签名URL失败", e);
}
}
/**
* 获取文件信息
*
* @param filePath 文件路径
* @return 文件信息
*/
public ObjectMetadata getFileMetadata(String filePath) {
if (filePath == null || filePath.trim().isEmpty()) {
throw new IllegalArgumentException("文件路径不能为空");
}
try {
return ossClient.getObjectMetadata(bucketName, filePath);
} catch (Exception e) {
throw new RuntimeException("获取文件信息失败", e);
}
}
/**
* 检查文件是否存在
*
* @param filePath 文件路径
* @return 是否存在
*/
public boolean doesFileExist(String filePath) {
if (filePath == null || filePath.trim().isEmpty()) {
return false;
}
try {
return ossClient.doesObjectExist(bucketName, filePath);
} catch (Exception e) {
return false;
}
}
/**
* 下载文件
*
* @param filePath 文件路径
* @return 文件输入流
*/
public InputStream downloadFile(String filePath) {
if (filePath == null || filePath.trim().isEmpty()) {
throw new IllegalArgumentException("文件路径不能为空");
}
try {
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, filePath);
OSSObject ossObject = ossClient.getObject(getObjectRequest);
return ossObject.getObjectContent();
} catch (Exception e) {
throw new RuntimeException("文件下载失败", e);
}
}
/**
* 创建目录
*
* @param directoryPath 目录路径
*/
public void createDirectory(String directoryPath) {
if (directoryPath == null || directoryPath.trim().isEmpty()) {
throw new IllegalArgumentException("目录路径不能为空");
}
try {
// 目录必须以"/"结尾
String normalizedPath = directoryPath.endsWith("/") ? directoryPath : directoryPath + "/";
// 创建目录
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(0);
InputStream emptyContent = new ByteArrayInputStream(new byte[0]);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, normalizedPath, emptyContent, metadata);
ossClient.putObject(putObjectRequest);
} catch (Exception e) {
throw new RuntimeException("创建目录失败", e);
}
}
/**
* 获取文件扩展名
*
* @param fileName 文件名
* @return 文件扩展名
*/
private String getFileExtension(String fileName) {
if (fileName == null || fileName.isEmpty()) {
return "";
}
int lastIndexOfDot = fileName.lastIndexOf(".");
if (lastIndexOfDot == -1) {
return "";
}
return fileName.substring(lastIndexOfDot);
}
/**
* 从URL中提取文件路径
*
* @param fileUrl 文件URL
* @return 文件路径
*/
private String extractFilePathFromUrl(String fileUrl) {
String prefix = "https://" + bucketName + "." + endpoint + "/";
if (fileUrl.startsWith(prefix)) {
return fileUrl.substring(prefix.length());
}
return fileUrl;
}
}

View File

@@ -1,13 +1,17 @@
package com.njcn.product.event.transientes.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.json.JSONObject;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.product.event.transientes.pojo.dto.MsgDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsResponseDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsSendDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -18,8 +22,8 @@ import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author: cdf
@@ -28,10 +32,16 @@ import java.util.List;
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class SmsUtils {
@Autowired
private RestTemplate restTemplate;
private final RestTemplate restTemplate;
// 最大重试次数
private static final int MAX_RETRY_COUNT = 2;
//短信平台成功返回码
private static final String SUCCESS_CODE = "0";
//短信平台业务码
private static final String SERVICE_CODE = "01001101";
@Value("${smsServer.info}")
private String smsServer;
@@ -43,26 +53,237 @@ public class SmsUtils {
private String password;
public List<SmsResponseDTO.SmsItem> sendSmSToUser(List<MsgDTO> msgDTOList) {
/**
* 发送短信给用户
*
* @param itemList 短信内容列表
* @return 发送结果列表
*/
public List<SmsResponseDTO.SmsItem> sendSmSToUser(List<SmsSendDTO.ItemInner> itemList) {
if (CollUtil.isEmpty(itemList)) {
log.info("短信发送列表为空");
return Collections.emptyList();
}
return sendSmSToUserWithRetry(itemList, MAX_RETRY_COUNT);
}
/**
* 带重试机制的短信发送
*
* @param itemList 短信内容列表
* @param retryCount 剩余重试次数
* @return 发送结果列表
*/
private List<SmsResponseDTO.SmsItem> sendSmSToUserWithRetry(List<SmsSendDTO.ItemInner> itemList, int retryCount) {
if (retryCount <= 0) {
log.error("短信发送重试次数耗尽,剩余{}条短信发送失败", itemList.size());
return buildFailedResponse(itemList);
}
try {
SmsSendDTO smsSendDTO = buildSmsRequest(itemList);
ResponseEntity<SmsResponseDTO> response = executeSmsRequest(smsSendDTO);
return processSmsResponse(response, itemList, retryCount);
} catch (RestClientException e) {
log.error("第{}次短信发送网络异常,剩余重试次数: {}",
MAX_RETRY_COUNT - retryCount + 1, retryCount - 1, e);
return sendSmSToUserWithRetry(itemList, retryCount - 1);
} catch (Exception e) {
log.error("第{}次短信发送系统异常,剩余重试次数: {}",
MAX_RETRY_COUNT - retryCount + 1, retryCount - 1, e);
return sendSmSToUserWithRetry(itemList, retryCount - 1);
}
}
/**
* 构建短信请求参数
*/
private SmsSendDTO buildSmsRequest(List<SmsSendDTO.ItemInner> itemList) {
String nowTime = LocalDateTime.now().format(
DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String sm3Hash = new SM3().digestHex(account + password + nowTime);
SmsSendDTO smsSendDTO = new SmsSendDTO();
smsSendDTO.setServiceCode("101001101");
smsSendDTO.setServiceCode(SERVICE_CODE);
smsSendDTO.setAccount(account);
smsSendDTO.setToken(sm3Hash);
smsSendDTO.setTs(nowTime);
smsSendDTO.setItems(itemList);
log.info("短信请求实体{}", smsSendDTO);
return smsSendDTO;
}
/**
* 执行短信请求
*/
private ResponseEntity<SmsResponseDTO> executeSmsRequest(SmsSendDTO smsSendDTO) {
String url = smsServer + "/sms/msg";
log.info("调用短信接口: {}", url);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
String requestBody = new JSONObject(smsSendDTO).toString();
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
return restTemplate.exchange(url, HttpMethod.POST, requestEntity, SmsResponseDTO.class);
}
/**
* 处理短信响应
*/
private List<SmsResponseDTO.SmsItem> processSmsResponse(
ResponseEntity<SmsResponseDTO> response,
List<SmsSendDTO.ItemInner> originalList,
int retryCount) {
// 检查HTTP状态码
if (response.getStatusCode() != HttpStatus.OK) {
log.error("短信接口HTTP状态码异常: {}", response.getStatusCode());
return sendSmSToUserWithRetry(originalList, retryCount - 1);
}
// 检查响应体
SmsResponseDTO smsResponse = response.getBody();
if (smsResponse == null) {
log.error("短信接口返回体为空");
return sendSmSToUserWithRetry(originalList, retryCount - 1);
}
// 检查业务状态码
if (!SUCCESS_CODE.equals(smsResponse.getCode())) {
log.error("短信发送业务失败: {} - {}", smsResponse.getCode(), smsResponse.getMessage());
return sendSmSToUserWithRetry(originalList, retryCount - 1);
}
log.info("短信发送接口调用成功batchId: {}, 发送条数: {}",
smsResponse.getBatchId(), smsResponse.getItems().size());
// 处理部分失败的情况
return handlePartialFailures(smsResponse, originalList);
}
/**
* 处理部分短信发送失败的情况
*/
private List<SmsResponseDTO.SmsItem> handlePartialFailures(
SmsResponseDTO smsResponse,
List<SmsSendDTO.ItemInner> originalList) {
List<SmsResponseDTO.SmsItem> allItems = smsResponse.getItems();
// 找出发送失败的短信ID
List<String> failedIds = allItems.stream()
.filter(item -> !SUCCESS_CODE.equals(item.getCode()))
.map(SmsResponseDTO.SmsItem::getCustomMsgID)
.filter(StrUtil::isNotBlank)
.collect(Collectors.toList());
if (CollUtil.isEmpty(failedIds)) {
log.info("所有短信发送成功!");
return allItems;
}
log.info("发现{}条短信发送失败,尝试重新发送", failedIds.size());
// 找出需要重发的短信内容
List<SmsSendDTO.ItemInner> failedItems = originalList.stream()
.filter(item -> failedIds.contains(item.getCustomMsgID()))
.collect(Collectors.toList());
if (CollUtil.isEmpty(failedItems)) {
log.info("未找到对应的失败短信内容,直接返回原始结果");
return allItems;
}
// 对失败的消息重新发送
List<SmsResponseDTO.SmsItem> retryResults = sendSmSToUserWithRetry(failedItems, MAX_RETRY_COUNT);
// 合并结果:用重试结果替换原有的失败结果
return mergeSmsResults(allItems, retryResults, failedIds);
}
/**
* 合并短信发送结果
*/
private List<SmsResponseDTO.SmsItem> mergeSmsResults(
List<SmsResponseDTO.SmsItem> originalResults,
List<SmsResponseDTO.SmsItem> retryResults,
List<String> originalFailedIds) {
// 创建结果副本
List<SmsResponseDTO.SmsItem> mergedResults = new ArrayList<>(originalResults);
// 构建重试结果的映射,便于查找
Map<String, SmsResponseDTO.SmsItem> retryResultMap = retryResults.stream()
.collect(Collectors.toMap(
SmsResponseDTO.SmsItem::getCustomMsgID,
item -> item,
(existing, replacement) -> replacement
));
// 用重试结果替换原有的失败结果
for (int i = 0; i < mergedResults.size(); i++) {
SmsResponseDTO.SmsItem originalItem = mergedResults.get(i);
String msgId = originalItem.getCustomMsgID();
if (originalFailedIds.contains(msgId)) {
SmsResponseDTO.SmsItem retryItem = retryResultMap.get(msgId);
if (retryItem != null) {
mergedResults.set(i, retryItem);
}
// 如果重试结果中没有找到对应的消息,保持原失败结果
}
}
log.info("结果合并完成,原始结果数: {}, 重试结果数: {}, 合并后结果数: {}",
originalResults.size(), retryResults.size(), mergedResults.size());
return mergedResults;
}
/**
* 构建失败响应
*/
private List<SmsResponseDTO.SmsItem> buildFailedResponse(List<SmsSendDTO.ItemInner> itemList) {
return itemList.stream()
.map(item -> {
SmsResponseDTO.SmsItem failedItem = new SmsResponseDTO.SmsItem();
failedItem.setCustomMsgID(item.getCustomMsgID());
failedItem.setCode("-1");
failedItem.setMsg("短信发送失败,重试次数耗尽");
return failedItem;
})
.collect(Collectors.toList());
}
/* public List<SmsResponseDTO.SmsItem> sendSmSToUser(List<SmsSendDTO.ItemInner> temList,Boolean failFlag) {
if (CollUtil.isEmpty(temList)) {
log.error("短信发送列表为空");
return Collections.emptyList();
}
SmsSendDTO smsSendDTO = new SmsSendDTO();
smsSendDTO.setServiceCode("01001101");
smsSendDTO.setAccount(account);
String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String sm3Hash = new SM3().digestHex(account + password + nowTime);
smsSendDTO.setToken(sm3Hash);
smsSendDTO.setTs(nowTime);
List<SmsSendDTO.ItemInner> temList = new ArrayList<>();
for (MsgDTO dto : msgDTOList) {
SmsSendDTO.ItemInner inner = new SmsSendDTO.ItemInner();
inner.setTo(dto.getPhone());
inner.setContent(dto.getMessage());
temList.add(inner);
}
smsSendDTO.setItems(temList);
log.info("短信请求实体{}", smsSendDTO);
String url = smsServer + "/sms/msg";
System.out.println(url);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
@@ -75,28 +296,46 @@ public class SmsUtils {
SmsResponseDTO.class
);
// 处理响应
return handleSmsResponse(response);
} catch (RestClientException e) {
return handleSmsResponse(response,failFlag,temList);
} catch (Exception e) {
log.error("短信接口调用失败", e);
throw new RuntimeException("短信发送异常", e);
return new ArrayList<>();
}
}
private List<SmsResponseDTO.SmsItem> handleSmsResponse(ResponseEntity<SmsResponseDTO> response) {
private List<SmsResponseDTO.SmsItem> handleSmsResponse(ResponseEntity<SmsResponseDTO> response,Boolean failFlag,List<SmsSendDTO.ItemInner> msgList) {
if (response.getStatusCode() == HttpStatus.OK) {
SmsResponseDTO smsResponse = response.getBody();
List<SmsSendDTO.ItemInner> failList = new ArrayList<>();
if (smsResponse != null && "0".equals(smsResponse.getCode())) {
log.info("短信发送成功batchId: {}", smsResponse.getBatchId());
return smsResponse.getItems();
log.info("短信发送成功batchId: {},发送条数{}", smsResponse.getBatchId(),smsResponse.getItems().size());
List<String> ids = smsResponse.getItems().stream().filter(it->!"0".equals(it.getCode())).map(SmsResponseDTO.SmsItem::getCustomMsgID).collect(Collectors.toList());
if(CollUtil.isNotEmpty(ids)){
//调用成功的情况下,依然会存在个别短信发送失败
List<SmsSendDTO.ItemInner> faliList = msgList.stream().filter(it->ids.contains(it.getCustomMsgID())).collect(Collectors.toList());
sendSmSToUser(faliList,false);
}
return smsResponse.getItems();
} else {
log.error("短信发送失败: {}", (smsResponse != null ? smsResponse.getMessage() : "API 返回异常"));
throw new BusinessException("调用短信服务失败");
//全部失败重新发送一次
if(failFlag){
//失败重新发送
sendSmSToUser(msgList,false);
}
return new ArrayList<>();
}
} else {
log.error("HTTP 请求失败,状态码: {}", response.getStatusCode());
throw new BusinessException("调用短信服务失败");
if(failFlag){
//全部失败重新发送一次
sendSmSToUser(msgList,false);
}
return new ArrayList<>();
}
}
*/
}

View File

@@ -43,16 +43,24 @@ spring:
host: localhost
port: 6379
timeout: 5000
lettuce:
jedis:
pool:
max-active: 8
max-active: 20
max-wait: 8000
max-idle: 8
min-idle: 0
min-idle: 2
test-on-borrow: true # 借出连接时验证
test-on-return: true # 归还连接时验证
test-while-idle: true # 空闲时验证
smsServer:
info: http://22.33.194.50:18096
netInfo: http://22.33.191.206:18096
account: sms
password: aaa
account: xbjbpt
password: WLv8w071
aliyun:
oss:
endpoint: oss-cn-beijing.aliyuncs.com
accessKeyId: LTAI5tQYuyu1PpiCdeM74PT6
accessKeySecret: vTGHcQOCF9u7w9FL3HAHJO1oufVWru
bucketName: cn-comtrade

View File

@@ -44,17 +44,27 @@ spring:
host: localhost
port: 16379
password: "Pqsadmin@#1qaz"
timeout: 5000
lettuce:
timeout: 5000
jedis:
pool:
max-active: 20
max-wait: 8000
max-idle: 8
min-idle: 0
min-idle: 2
test-on-borrow: true # 借出连接时验证
test-on-return: true # 归还连接时验证
test-while-idle: true # 空闲时验证
smsServer:
info: http://22.33.194.49:18095
netInfo: http://20.33.234.143:18095
account: sms
password: aaa
account: xbjbpt
password: ihS2b73v
aliyun:
oss:
endpoint: http://oss-bj-yz-a.ops.sgmc.sgcc.com.cn/
accessKeyId: LKIyxAYe0yI8EqL8
accessKeySecret: H2UgWI6RdacGGGJAxLsTNj8Qa4oX2e
bucketName: sjzt-fjghsjcc-pro

View File

@@ -8,7 +8,7 @@ spring:
application:
name: event_smart
profiles:
active: dev
active: prod
#mybatis配置信息
@@ -38,9 +38,13 @@ db:
business:
#处理波形数据位置
wavePath: D://Comtrade
targetPath: /pqmonitor
exportBaseDir: D://exportComtrade
cronExpression:
eventCronExpression: 0 0/10 * * * ?
failCronExpression: 0 5/10 * * * ?
userCronExpression: 0 5 1 * * ?
syncinterval: 10
failsyncinterval: 1440
#wavePath: /usr/local/comtrade
#处理临时数据
tempPath: D://file

View File

@@ -14,8 +14,7 @@
<!--日志输出格式-->
<property name="log.pattern"
value="|-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%level} ${log.projectName} -- %t %logger{100}.%M ==> %m%n${Log_EXCEPTION_CONVERSION_WORD:-%ec}}}"/>
<property name="log.pattern" value="|-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%level} ${log.projectName} -- %t %logger{100}.%M ==> %m%n${Log_EXCEPTION_CONVERSION_WORD:-%ec}}"/>
<property name="log.maxHistory" value="30"/>
<!-- 控制台输出(可选) -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">