From 005f73e19d36e7e589af1967ced2f24b91009e72 Mon Sep 17 00:00:00 2001 From: hzj <826100833@qq.com> Date: Mon, 3 Nov 2025 09:02:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8C=97=E4=BA=AC=E6=9A=82=E9=99=8D10=E6=9C=88?= =?UTF-8?q?=E5=87=BA=E5=B7=AE=E5=BC=80=E5=8F=91=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/event/config/RedisConfig.java | 130 +++++ .../config/RedisInstantDateDeserializer.java | 38 ++ .../njcn/product/event/config/RedisUtil.java | 208 +++++++ .../event/config/ThreadPoolConfig.java | 39 ++ .../dataTransmit/DataSynchronization.java | 510 ++++++++++++++++++ .../dataTransmit/dataSynchronization.java | 224 -------- .../event/devcie/config/PqlineCache.java | 17 +- .../event/devcie/job/LineCacheJob.java | 17 +- .../devcie/mapper/mapping/PqLineMapper.xml | 6 + .../devcie/pojo/dto/LedgerBaseInfoDTO.java | 4 +- .../event/devcie/pojo/dto/LedgerExcelDTO.java | 41 ++ .../EasyPoiWordExportController.java | 1 + .../impl/EasyPoiWordExportServiceImpl.java | 163 +++--- .../controller/EventGateController.java | 233 +++++--- .../LargeScreenCountController.java | 27 + .../controller/PqUserLedgerController.java | 3 + .../event/transientes/job/ScheduledEvent.java | 4 +- .../transientes/pojo/dto/UpLoadEvent.java | 57 ++ .../transientes/pojo/dto/UpLoadUserDTO.java | 21 + .../transientes/pojo/dto/UserLegerDTO.java | 30 ++ .../transientes/pojo/dto/UserLineAssDTO.java | 19 + .../pojo/po/PqsEventDetailStatusPO.java | 6 +- .../transientes/pojo/po/PqsEventdetail.java | 4 + .../transientes/security/AuthController.java | 2 +- .../security/MyUserDetailsService.java | 2 +- .../service/CommGeneralService.java | 2 +- .../service/LargeScreenCountService.java | 2 + .../service/PqsEventDetailStatusService.java | 13 + .../impl/LargeScreenCountServiceImpl.java | 22 +- .../impl/PqsEventDetailStatusServiceImpl.java | 19 + .../utils/OssFileStorageUtils.java | 483 +++++++++++++++++ .../event/transientes/utils/SmsUtils.java | 34 +- .../src/main/resources/application-dev.yml | 20 +- .../src/main/resources/application-prod.yml | 24 +- .../src/main/resources/application.yml | 10 +- event_smart/src/main/resources/logback.xml | 3 +- 36 files changed, 2010 insertions(+), 428 deletions(-) create mode 100644 event_smart/src/main/java/com/njcn/product/event/config/RedisConfig.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/config/RedisInstantDateDeserializer.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/config/RedisUtil.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/config/ThreadPoolConfig.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/dataTransmit/DataSynchronization.java delete mode 100644 event_smart/src/main/java/com/njcn/product/event/dataTransmit/dataSynchronization.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerExcelDTO.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadEvent.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadUserDTO.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLegerDTO.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLineAssDTO.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/service/PqsEventDetailStatusService.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/PqsEventDetailStatusServiceImpl.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/utils/OssFileStorageUtils.java diff --git a/event_smart/src/main/java/com/njcn/product/event/config/RedisConfig.java b/event_smart/src/main/java/com/njcn/product/event/config/RedisConfig.java new file mode 100644 index 0000000..beb62b4 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/config/RedisConfig.java @@ -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 redisTemplate(RedisConnectionFactory redisConnectionFactory) { + + + // 为了开发方便,一般直接使用 + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory); + // 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 + Jackson2JsonRedisSerializer 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(); + } +} diff --git a/event_smart/src/main/java/com/njcn/product/event/config/RedisInstantDateDeserializer.java b/event_smart/src/main/java/com/njcn/product/event/config/RedisInstantDateDeserializer.java new file mode 100644 index 0000000..de727b5 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/config/RedisInstantDateDeserializer.java @@ -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 { + + 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)); + } +} diff --git a/event_smart/src/main/java/com/njcn/product/event/config/RedisUtil.java b/event_smart/src/main/java/com/njcn/product/event/config/RedisUtil.java new file mode 100644 index 0000000..394b2c0 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/config/RedisUtil.java @@ -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 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) 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 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; + } + } + + +} diff --git a/event_smart/src/main/java/com/njcn/product/event/config/ThreadPoolConfig.java b/event_smart/src/main/java/com/njcn/product/event/config/ThreadPoolConfig.java new file mode 100644 index 0000000..f0b0d62 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/config/ThreadPoolConfig.java @@ -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(); // 基础配置 + } + } +} diff --git a/event_smart/src/main/java/com/njcn/product/event/dataTransmit/DataSynchronization.java b/event_smart/src/main/java/com/njcn/product/event/dataTransmit/DataSynchronization.java new file mode 100644 index 0000000..624d836 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/dataTransmit/DataSynchronization.java @@ -0,0 +1,510 @@ +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.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.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; + + +/** + * @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 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 pqUserLedgerPOQueryWrapper = new QueryWrapper<>(); + pqUserLedgerPOQueryWrapper.lambda().eq(PqUserLedgerPO::getIsShow,1); + List pqUserLedgerPOS = pqUserLedgerMapper.selectList(pqUserLedgerPOQueryWrapper); + if(!CollectionUtils.isEmpty(pqUserLedgerPOS)){ + List showIds =new ArrayList<>(); + List userLegerDTOList =new ArrayList<>(); + List pqsDicTreePOS = pqsDicTreeMapper.selectList(new LambdaQueryWrapper<>()); + Map pqsDicTreePOMap = pqsDicTreePOS.stream().collect(Collectors.toMap(PqsDicTreePO::getId, Function.identity())); + List pqGdCompanyList = pqGdCompanyMapper.selectList(null); + Map 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()); + + userLegerDTOList.add(userLegerDTO); + }); + + QueryWrapper userLineAssPOQueryWrapper = new QueryWrapper<>(); + userLineAssPOQueryWrapper.lambda().in(PqUserLineAssPO::getUserIndex,showIds); + List pqUserLineAssPOS = pqUserLineAssMapper.selectList(userLineAssPOQueryWrapper); + List 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 statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>(); + statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getEventTime,start,end); + List hasList = pqsEventDetailStatusService.list(statusPOLambdaQueryWrapper); + Map pqsEventDetailStatusPOMap = hasList.stream().collect(Collectors.toMap(PqsEventDetailStatusPO::getEventDetailId, Function.identity())); + // 查询事件 + LambdaQueryWrapper pqsEventdetailLambdaQueryWrapper = new LambdaQueryWrapper<>(); + pqsEventdetailLambdaQueryWrapper.between(PqsEventdetail::getCreateTime,start,end); + List unsyncedEvents = pqsEventdetailMapper.selectList(pqsEventdetailLambdaQueryWrapper); + List tempEvetIds = unsyncedEvents.stream().map(PqsEventdetail::getEventdetailIndex).collect(Collectors.toList()); + //查询日志 + List allEventIds = hasList.stream().map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList()); + List unSyncIds = tempEvetIds.stream().filter(temp -> !allEventIds.contains(temp)).collect(Collectors.toList()); + + List failIds = hasList.stream().filter(temp -> temp.getRetryCount() <= 2 && temp.getSyncStatus() == 0).map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList()); + unSyncIds.addAll(failIds); + List result = new ArrayList<>(); + + if(!CollectionUtils.isEmpty(unSyncIds)){ + List eventIds = unSyncIds.stream().distinct().collect(Collectors.toList()); + + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + + if (eventIds.size() > 1000) { + List> splitList = CollUtil.split(eventIds, 1000); + lambdaQueryWrapper.and(ew -> { + for (int i = 0; i < splitList.size(); i++) { + List 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 pqsEventdetails = pqsEventdetailMapper.selectList(lambdaQueryWrapper); + Map pqsEventdetailMap = pqsEventdetails.stream().collect(Collectors.toMap(PqsEventdetail::getEventdetailIndex, Function.identity())); + + List ledgerBaseInfoDTOS = (List)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO"); + Map LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity())); + List pqLinedetails = pqLinedetailMapper.selectList(null); + Map lineDetailMap = pqLinedetails.stream().collect(Collectors.toMap(PqLinedetail::getLineIndex, Function.identity())); + + unSyncIds.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()>2){ + 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()); + upLoadEvent.setEventvalue(pqsEventdetail.getEventvalue()); + upLoadEvent.setEventreason(pqsEventdetail.getEventreason()); + upLoadEvent.setEventtype(pqsEventdetail.getEventtype()); + LedgerBaseInfoDTO ledgerBaseInfoDTO = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid()); + upLoadEvent.setGdname(ledgerBaseInfoDTO.getGdName()); + upLoadEvent.setBdname(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()); + upLoadEvent.setEventvalue(pqsEventdetail.getEventvalue()); + upLoadEvent.setEventreason(pqsEventdetail.getEventreason()); + upLoadEvent.setEventtype(pqsEventdetail.getEventtype()); + LedgerBaseInfoDTO ledgerBaseInfoDTO = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid()); + upLoadEvent.setGdname(ledgerBaseInfoDTO.getGdName()); + upLoadEvent.setBdname(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 lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.between(PqsEventdetail::getCreateTime,startTime,endTime); + List unsyncedEvents = pqsEventdetailMapper.selectList(lambdaQueryWrapper); + log.info("查询到 " + unsyncedEvents.size() + " 个暂降事件"); + if(CollUtil.isEmpty(unsyncedEvents)){ + return ; + } + +// // 查询已经存在记录的暂降事件 +// LambdaQueryWrapper statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>(); +// statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getEventTime,startTime,endTime); +// List hasList = pqsEventDetailStatusMapper.selectList(statusPOLambdaQueryWrapper); + +// log.info("查询到 " + hasList.size() + "条已存在记录事件"); +// //成功或者重试超过2次的时间id +// List 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 ledgerBaseInfoDTOS = (List)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO"); + Map LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity())); + + List pqLinedetails = pqLinedetailMapper.selectList(null); + Map lineDetailMap = pqLinedetails.stream().collect(Collectors.toMap(PqLinedetail::getLineIndex, Function.identity())); + List result = new ArrayList<>(); + List 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()); + upLoadEvent.setEventvalue(unsyncedEvent.getEventvalue()); + upLoadEvent.setEventreason(unsyncedEvent.getEventreason()); + upLoadEvent.setEventtype(unsyncedEvent.getEventtype()); + LedgerBaseInfoDTO ledgerBaseInfoDTO = LedgerBaseInfoDTOMap.get(unsyncedEvent.getLineid()); + upLoadEvent.setGdname(ledgerBaseInfoDTO.getGdName()); + upLoadEvent.setBdname(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 + ")"; + } + } + + + +} + diff --git a/event_smart/src/main/java/com/njcn/product/event/dataTransmit/dataSynchronization.java b/event_smart/src/main/java/com/njcn/product/event/dataTransmit/dataSynchronization.java deleted file mode 100644 index d2038a5..0000000 --- a/event_smart/src/main/java/com/njcn/product/event/dataTransmit/dataSynchronization.java +++ /dev/null @@ -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 lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.between(PqsEventdetail::getTimeid,startTime,endTime); - List unsyncedEvents = pqsEventdetailMapper.selectList(lambdaQueryWrapper); - log.info("查询到 " + unsyncedEvents.size() + " 个暂降事件"); - if(CollUtil.isEmpty(unsyncedEvents)){ - return ; - } - - // 查询已经存在记录的暂降事件 - LambdaQueryWrapper statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>(); - statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getEventTime,startTime,endTime); - List hasList = pqsEventDetailStatusMapper.selectList(statusPOLambdaQueryWrapper); - log.info("查询到 " + hasList.size() + "条已存在记录事件"); - //波形文件失败的事件id - List waveFailEventDetailIds = hasList.stream().filter(it->it.getWaveFlag() == 0).map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList()); - - - //排除已经成功的事件 - if(CollUtil.isNotEmpty(hasList)){ - List 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; - } - -} diff --git a/event_smart/src/main/java/com/njcn/product/event/devcie/config/PqlineCache.java b/event_smart/src/main/java/com/njcn/product/event/devcie/config/PqlineCache.java index fdc8aeb..94978d4 100644 --- a/event_smart/src/main/java/com/njcn/product/event/devcie/config/PqlineCache.java +++ b/event_smart/src/main/java/com/njcn/product/event/devcie/config/PqlineCache.java @@ -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; @@ -70,6 +71,20 @@ public class PqlineCache { List deptsList = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState,1).list(); redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"AllDept",deptsList); + List collect = pqLines.stream().map(PqLine::getLineIndex).collect(Collectors.toList()); + List ledgerBaseInfoDTOS = new ArrayList<>(); + + if(collect.size()>1000){ + List> listIds = CollUtil.split(collect,1000); + for(List itemIds : listIds){ + List temp =pqLineMapper.getBaseLineInfo(itemIds); + ledgerBaseInfoDTOS.addAll(temp); + } + }else { + List temp =pqLineMapper.getBaseLineInfo(collect); + ledgerBaseInfoDTOS.addAll(temp); + } + redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO",ledgerBaseInfoDTOS); } @PreDestroy diff --git a/event_smart/src/main/java/com/njcn/product/event/devcie/job/LineCacheJob.java b/event_smart/src/main/java/com/njcn/product/event/devcie/job/LineCacheJob.java index 0504e6f..62fd7c4 100644 --- a/event_smart/src/main/java/com/njcn/product/event/devcie/job/LineCacheJob.java +++ b/event_smart/src/main/java/com/njcn/product/event/devcie/job/LineCacheJob.java @@ -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 deptsList = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState,1).list(); redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"AllDept",deptsList); + List collect = pqLines.stream().map(PqLine::getLineIndex).collect(Collectors.toList()); + List ledgerBaseInfoDTOS = new ArrayList<>(); + + if(collect.size()>1000){ + List> listIds = CollUtil.split(collect,1000); + for(List itemIds : listIds){ + List temp =pqLineMapper.getBaseLineInfo(itemIds); + ledgerBaseInfoDTOS.addAll(temp); + } + }else { + List temp =pqLineMapper.getBaseLineInfo(collect); + ledgerBaseInfoDTOS.addAll(temp); + } + redisUtil.saveByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO",ledgerBaseInfoDTOS); } } diff --git a/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml b/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml index 9949399..6eb43db 100644 --- a/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml +++ b/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml @@ -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 diff --git a/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerBaseInfoDTO.java b/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerBaseInfoDTO.java index 6a25a34..442d547 100644 --- a/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerBaseInfoDTO.java +++ b/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerBaseInfoDTO.java @@ -35,7 +35,9 @@ public class LedgerBaseInfoDTO { private Integer runFlag=0; private Integer eventCount; + private String ip; - + private int pt; + private int ct; } diff --git a/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerExcelDTO.java b/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerExcelDTO.java new file mode 100644 index 0000000..7a6305f --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/devcie/pojo/dto/LedgerExcelDTO.java @@ -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; + + + +} diff --git a/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java b/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java index 2736f80..6039014 100644 --- a/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java +++ b/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java @@ -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; diff --git a/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java b/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java index c36504f..dc9ad7d 100644 --- a/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java +++ b/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java @@ -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 pqsEventdetailList = pqsEventdetailMapper.selectList(lambdaQueryWrapper); if(CollUtil.isNotEmpty(pqsEventdetailList)) { + List ledgerBaseInfoDTOS = (List)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO"); + Map LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity())); + List> 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 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 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 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 areaContentList = new ArrayList<>(); List> eventTemplateList = new ArrayList<>(); + List ledgerBaseInfoDTOS = (List)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO"); + Map LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity())); + + List> 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 pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().in(PqUserLineAssPO::getLineIndex,lineIds)); - List userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList()); - - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - if (userIds.size() > 1000) { - List> listUserIds = CollUtil.split(userIds, 1000); - queryWrapper.eq(PqUserLedgerPO::getIsShow,1).and(w -> { - for (List ids : listUserIds) { - w.or(wIn -> wIn.in(PqUserLedgerPO::getId, ids)); - } - }); - } else { - queryWrapper.eq(PqUserLedgerPO::getIsShow,1).in(PqUserLedgerPO::getId, userIds); - } - List 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 companyId = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList()); - List pqUserLineAssPOS1 = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().in(PqUserLineAssPO::getUserIndex, companyId)); - List companyNameList = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList()); - List companyLineId= pqUserLineAssPOS1.stream().map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList()); - List companyevent = pqsEventdetailList.stream().filter(pqsEventdetail -> companyLineId.contains(pqsEventdetail.getLineid())).collect(Collectors.toList()); - if(CollectionUtils.isEmpty(companyevent)){ - userContext =userContext+"暂未发生暂态事件。"; - }else { + List userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList()); - for (int i = 0; i < pqsEventdetailList.size(); i++) { - PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i); - - List baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetailList.get(i).getLineid()).collect(Collectors.toList())); - if(Objects.isNull(baseLineInfo.get(0).getObjName())){ - continue; + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (userIds.size() > 1000) { + List> listUserIds = CollUtil.split(userIds, 1000); + queryWrapper.eq(PqUserLedgerPO::getIsShow,1).and(w -> { + for (List 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 eventMap = mapper.convertValue(eventTemplate,Map.class); - finalEventTemplateList.add(eventMap); + }); + } else { + queryWrapper.eq(PqUserLedgerPO::getIsShow,1).in(PqUserLedgerPO::getId, userIds); + } + List 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 companyId = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList()); + List pqUserLineAssPOS1 = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().in(PqUserLineAssPO::getUserIndex, companyId)); + List companyNameList = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList()); + List companyLineId= pqUserLineAssPOS1.stream().map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList()); + List 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 eventMap = mapper.convertValue(eventTemplate,Map.class); + finalEventTemplateList.add(eventMap); + } + } + + } + Integer companyEveCount = companyevent.size(); + List companyLineIds = companyevent.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList()); + List 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 companyLineIds = companyevent.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList()); - List 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 ="不涉及半导体及重点关注用户。"; } diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java index 56b83db..682b94a 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java @@ -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; @@ -20,17 +21,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 +39,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 +63,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 +92,8 @@ public class EventGateController extends BaseController { private final SmsUtils smsUtils; + private final ThreadPoolTaskExecutor smsTaskExecutor; + @OperateInfo @GetMapping("/eventMsg") @@ -102,7 +101,7 @@ public class EventGateController extends BaseController { @ApiImplicitParam(name = "eventMsg", value = "暂态事件json字符", required = true) public HttpResult eventMsg(@RequestParam("msg") String msg) { String methodDescribe = getMethodDescribe("eventMsg"); - log.info("收到前置推送暂降事件:"+msg); + log.info("收到前置推送暂降事件,事件详情:" + msg); JSONObject jsonObject; try { @@ -113,28 +112,34 @@ 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 assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().eq(PqUserLineAssPO::getLineIndex,lineId)); + List assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().eq(PqUserLineAssPO::getLineIndex, lineId)); - String str ="/"; - if(CollUtil.isNotEmpty(assList)){ - List userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList()); - List poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper().select(PqUserLedgerPO::getId,PqUserLedgerPO::getCustomerName).in(PqUserLedgerPO::getId,userIds)); - str = poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining(StrUtil.COMMA)); + String str; + if (CollUtil.isNotEmpty(assList)) { + List userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList()); + List poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper().select(PqUserLedgerPO::getId, PqUserLedgerPO::getCustomerName).in(PqUserLedgerPO::getId, userIds)); + str = poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining(";")); + } else { + str = "/"; } - List deptsList = (List)redisUtil.getObjectByKey(REDIS_DEPT_INDEX+ StrUtil.DASHED+"AllDept"); - Map deptsMap = deptsList.stream().collect(Collectors.toMap(PqsDepts::getDeptsIndex,dept->dept)); + List deptsList = (List) redisUtil.getObjectByKey(REDIS_DEPT_INDEX + StrUtil.DASHED + "AllDept"); + Map deptsMap = deptsList.stream().collect(Collectors.toMap(PqsDepts::getDeptsIndex, dept -> dept)); - List deptslineList = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex,lineId).list(); + List deptslineList = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).list(); List deptIds = deptslineList.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toList()); - Set set =getAllParentIdsWithChildrenBatch(deptIds,deptsMap); - jsonObject.putOpt("objName",str); + Set 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 +183,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()); } } @@ -235,7 +240,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 +284,132 @@ public class EventGateController extends BaseController { @OperateInfo(info = LogEnum.BUSINESS_COMMON) - @PostMapping("/simulationSend") + @GetMapping("/phoneSend") @ApiOperation("模拟发送短信") - public HttpResult simulationSend(@RequestBody @Validated SimulationMsgParam param) { + public HttpResult simulationSend(@RequestParam("id") String id) { + String methodDescribe = getMethodDescribe("simulationSend"); + + PqsEventdetail pqsEventdetail = pqsEventdetailMapper.selectOne(new LambdaQueryWrapper().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 pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list(); - Set deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet()); - Set resultIds = getAllParentDeptIds(deptIds); + @OperateInfo(info = LogEnum.BUSINESS_COMMON) + @GetMapping("/simpleTest") + @ApiOperation("模拟发送简单测试短信") + public HttpResult simpleTest() { + String methodDescribe = getMethodDescribe("simulationSend"); + List msgDTOList = new ArrayList<>(); + SmsSendDTO.ItemInner msgDTO = new SmsSendDTO.ItemInner(); + msgDTO.setCustomMsgID(IdUtil.simpleUUID()); + msgDTO.setContent("test"); + msgDTO.setTo("18815508963"); + msgDTOList.add(msgDTO); + List result = smsUtils.sendSmSToUser(msgDTOList); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe); + } - List pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list(); - if (CollUtil.isEmpty(pqsUserSetList)) { - //当前事件未找到用户信息,判断为不需要发送短信用户 - return; - } - List pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex,PqsUser::getPhone,PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list(); - List userIds = pqsUserList.stream().map(PqsUser::getUserIndex).collect(Collectors.toList()); - List 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 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 resultList = new ArrayList<>(); - List msgDTOList = new ArrayList<>(); - for (PqsUser user : pqsUserList) { - String msgId = IdUtil.simpleUUID(); + private void sendMessage(JSONObject jsonObject, String objStr) { - MsgDTO dto = new MsgDTO(); - dto.setMessage(stringBuilder.toString()); - dto.setPhone(user.getPhone()); - dto.setCustomMsgID(msgId); - msgDTOList.add(dto); + try { - 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); + + TimeInterval timeInterval = new TimeInterval(); + log.info("-------------------------开始执行短信发送逻辑{}",System.currentTimeMillis()); + + Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString()); + List pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list(); + Set deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet()); + Set resultIds = getAllParentDeptIds(deptIds); + + List pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list(); + if (CollUtil.isEmpty(pqsUserSetList)) { + //当前事件未找到用户信息,判断为不需要发送短信用户 + return; + } + List pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex, PqsUser::getPhone, PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list(); + List userIds = pqsUserList.stream().map(PqsUser::getUserIndex).collect(Collectors.toList()); + List 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 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;影响用户:"); + + + if ("/".equals(objStr)) { + stringBuilder.append("/"); + } else { + stringBuilder.append(objStr); + } + + String message; + if (stringBuilder.length() > 500) { + message = stringBuilder.substring(0, 490).concat(";详情请登录电压暂降监测平台查看。"); + } else { + message = stringBuilder.toString(); + } + + List resultList = new ArrayList<>(); + List 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 result = smsUtils.sendSmSToUser(msgDTOList); + Map 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); } - List result = smsUtils.sendSmSToUser(msgDTOList); - Map 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 +421,7 @@ public class EventGateController extends BaseController { return "token"; } - private boolean apiSend(){ - - + private boolean apiSend() { return false; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/LargeScreenCountController.java b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/LargeScreenCountController.java index b0a4992..7dceaf3 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/LargeScreenCountController.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/LargeScreenCountController.java @@ -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 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; + } + } diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/PqUserLedgerController.java b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/PqUserLedgerController.java index 4f87727..f7a67fc 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/PqUserLedgerController.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/PqUserLedgerController.java @@ -2,6 +2,7 @@ package com.njcn.product.event.transientes.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.njcn.product.event.dataTransmit.DataSynchronization; import com.njcn.product.event.transientes.pojo.param.PqUserLedgerParam; import com.njcn.product.event.transientes.pojo.po.PqUserLedgerPO; import com.njcn.product.event.transientes.service.PqUserLedgerService; @@ -22,6 +23,8 @@ public class PqUserLedgerController { @Autowired private PqUserLedgerService pqUserLedgerService; + + // 添加记录 @PostMapping("addLedger") public boolean addLedger(@RequestBody PqUserLedgerParam ledgerParam) { diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/job/ScheduledEvent.java b/event_smart/src/main/java/com/njcn/product/event/transientes/job/ScheduledEvent.java index ccdbf98..3fb8691 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/job/ScheduledEvent.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/job/ScheduledEvent.java @@ -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:\\"; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadEvent.java b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadEvent.java new file mode 100644 index 0000000..b1df9a7 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadEvent.java @@ -0,0 +1,57 @@ +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 pointname; + private String wavePath; + private String ip; + + private int pt; + private int ct; + private int ptType; + + + +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadUserDTO.java b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadUserDTO.java new file mode 100644 index 0000000..b55f27e --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UpLoadUserDTO.java @@ -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 userList; + private List assList; + +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLegerDTO.java b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLegerDTO.java new file mode 100644 index 0000000..f68a3e0 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLegerDTO.java @@ -0,0 +1,30 @@ +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 customerName; + + private String electricityAddress; + + private String bigObjType; + + private String smallObjType; + +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLineAssDTO.java b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLineAssDTO.java new file mode 100644 index 0000000..9a11bc5 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/dto/UserLineAssDTO.java @@ -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; +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventDetailStatusPO.java b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventDetailStatusPO.java index 5cf4d0c..b2f6884 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventDetailStatusPO.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventDetailStatusPO.java @@ -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") diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventdetail.java b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventdetail.java index eab2338..56bd7c5 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventdetail.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/pojo/po/PqsEventdetail.java @@ -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; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/security/AuthController.java b/event_smart/src/main/java/com/njcn/product/event/transientes/security/AuthController.java index a8b1a59..ddf286d 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/security/AuthController.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/security/AuthController.java @@ -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; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/security/MyUserDetailsService.java b/event_smart/src/main/java/com/njcn/product/event/transientes/security/MyUserDetailsService.java index 915a64f..59318c0 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/security/MyUserDetailsService.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/security/MyUserDetailsService.java @@ -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; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/CommGeneralService.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/CommGeneralService.java index aa557ae..c54aeb5 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/service/CommGeneralService.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/CommGeneralService.java @@ -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; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/LargeScreenCountService.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/LargeScreenCountService.java index eccad7d..c9b2b23 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/service/LargeScreenCountService.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/LargeScreenCountService.java @@ -64,4 +64,6 @@ public interface LargeScreenCountService { Page devicePage(LargeScreenCountParam largeScreenCountParam); Page userEventList(LargeScreenCountParam largeScreenCountParam); + + void exportLineData(); } diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/PqsEventDetailStatusService.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/PqsEventDetailStatusService.java new file mode 100644 index 0000000..b71f032 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/PqsEventDetailStatusService.java @@ -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 { +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java index 737b64d..20fcd26 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java @@ -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; @@ -1670,5 +1673,22 @@ public class LargeScreenCountServiceImpl implements LargeScreenCountService { return result; } + @Override + public void exportLineData() { + List ledgerExcelDTOList; + List ledgerBaseInfoDTOS = (List)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); + } + } + } diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/PqsEventDetailStatusServiceImpl.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/PqsEventDetailStatusServiceImpl.java new file mode 100644 index 0000000..bfd014c --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/PqsEventDetailStatusServiceImpl.java @@ -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 implements PqsEventDetailStatusService { + +} + diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/utils/OssFileStorageUtils.java b/event_smart/src/main/java/com/njcn/product/event/transientes/utils/OssFileStorageUtils.java new file mode 100644 index 0000000..9efcedf --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/utils/OssFileStorageUtils.java @@ -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; + } + + +} + + diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/utils/SmsUtils.java b/event_smart/src/main/java/com/njcn/product/event/transientes/utils/SmsUtils.java index e217d95..e623a1f 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/utils/SmsUtils.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/utils/SmsUtils.java @@ -4,10 +4,12 @@ import cn.hutool.core.date.DatePattern; import cn.hutool.core.util.IdUtil; 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; @@ -28,10 +30,11 @@ import java.util.List; */ @Component @Slf4j +@RequiredArgsConstructor public class SmsUtils { - @Autowired - private RestTemplate restTemplate; + + private final RestTemplate restTemplate; @Value("${smsServer.info}") private String smsServer; @@ -43,25 +46,19 @@ public class SmsUtils { private String password; - public List sendSmSToUser(List msgDTOList) { + public List sendSmSToUser(List temList) { SmsSendDTO smsSendDTO = new SmsSendDTO(); - smsSendDTO.setServiceCode("101001101"); + 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 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"; try { HttpHeaders headers = new HttpHeaders(); @@ -76,26 +73,25 @@ public class SmsUtils { ); // 处理响应 return handleSmsResponse(response); - } catch (RestClientException e) { + } catch (Exception e) { log.error("短信接口调用失败", e); - throw new RuntimeException("短信发送异常", e); + return new ArrayList<>(); } - } private List handleSmsResponse(ResponseEntity response) { if (response.getStatusCode() == HttpStatus.OK) { SmsResponseDTO smsResponse = response.getBody(); if (smsResponse != null && "0".equals(smsResponse.getCode())) { - log.info("短信发送成功,batchId: {}", smsResponse.getBatchId()); - return smsResponse.getItems(); + log.info("短信发送成功,batchId: {},发送条数{}", smsResponse.getBatchId(),smsResponse.getItems().size()); + return smsResponse.getItems(); } else { log.error("短信发送失败: {}", (smsResponse != null ? smsResponse.getMessage() : "API 返回异常")); - throw new BusinessException("调用短信服务失败"); + return new ArrayList<>(); } } else { log.error("HTTP 请求失败,状态码: {}", response.getStatusCode()); - throw new BusinessException("调用短信服务失败"); + return new ArrayList<>(); } } diff --git a/event_smart/src/main/resources/application-dev.yml b/event_smart/src/main/resources/application-dev.yml index 31bddbf..9a1feba 100644 --- a/event_smart/src/main/resources/application-dev.yml +++ b/event_smart/src/main/resources/application-dev.yml @@ -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 diff --git a/event_smart/src/main/resources/application-prod.yml b/event_smart/src/main/resources/application-prod.yml index 00c5061..235ac9e 100644 --- a/event_smart/src/main/resources/application-prod.yml +++ b/event_smart/src/main/resources/application-prod.yml @@ -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 + info: http://22.33.194.50:18096 + netInfo: http://22.33.191.206:18096 + account: xbjbpt + password: WLv8w071 + +aliyun: + oss: + endpoint: http://oss-bj-yz-a.ops.sgmc.sgcc.com.cn/ + accessKeyId: LKIyxAYe0yI8EqL8 + accessKeySecret: H2UgWI6RdacGGGJAxLsTNj8Qa4oX2e + bucketName: sjzt-fjghsjcc-pro diff --git a/event_smart/src/main/resources/application.yml b/event_smart/src/main/resources/application.yml index 12f13a6..f979340 100644 --- a/event_smart/src/main/resources/application.yml +++ b/event_smart/src/main/resources/application.yml @@ -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 9 0/1 * * ? + failCronExpression: 0 16 0/1 * * ? + userCronExpression: 0 5 0/1 * * ? + syncinterval: 60 + failsyncinterval: 1440 #wavePath: /usr/local/comtrade #处理临时数据 tempPath: D://file diff --git a/event_smart/src/main/resources/logback.xml b/event_smart/src/main/resources/logback.xml index e972d91..8e713c7 100644 --- a/event_smart/src/main/resources/logback.xml +++ b/event_smart/src/main/resources/logback.xml @@ -14,8 +14,7 @@ - +