raojiang před 6 měsíci
rodič
revize
1c80ad3e93
54 změnil soubory, kde provedl 1583 přidání a 63 odebrání
  1. 2 2
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IApiTestClient.java
  2. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ICityFeederTopoApiClient.java
  3. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ILineSvgFileApiClient.java
  4. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IMeasurementApiClient.java
  5. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IPsrDeviceApiClient.java
  6. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IRefreshCacheApiClient.java
  7. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ISimulationPlatformApiClient.java
  8. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IStateEstimationApiClient.java
  9. 1 1
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ISvgGenerationApiClient.java
  10. 6 6
      common/common-core/src/main/resources/mapper/SysDictMapper.xml
  11. 1 1
      services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/entity/vo/NoticeListVO.java
  12. 5 3
      services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/FhzgNoticeServiceImpl.java
  13. 3 3
      services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/FhzgPlanStrategyServiceImpl.java
  14. 6 5
      services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/FhzgProblemFeedbackServiceImpl.java
  15. 0 0
      services/load-transfer-bf/src/main/resources/config/dev/bootstrap-dev.yaml
  16. 0 0
      services/load-transfer-bf/src/main/resources/config/local/bootstrap-local.yaml
  17. 0 0
      services/load-transfer-bf/src/main/resources/config/uat/bootstrap-uat.yaml
  18. 1 1
      services/load-transfer-bf/src/main/resources/mapper/DwdShbDsSwitchBaseMapper.xml
  19. 37 0
      services/load-transfer-io/pom.xml
  20. 28 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/LoadTransferIOApplication.java
  21. 131 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/aop/FileTypeCheckAop.java
  22. 31 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/AliyunOSSConfigProperties.java
  23. 36 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/AliyunOSSConfiguration.java
  24. 20 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/FileCheckProperties.java
  25. 29 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/MinioOSSConfigProperties.java
  26. 36 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/MinioOSSConfiguration.java
  27. 130 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/controller/FileController.java
  28. 19 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/dao/DistSVGFileMapper.java
  29. 9 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/dao/mapping/DistSVGFileMapper.xml
  30. 104 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/feign/FileApiClient.java
  31. 39 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/IFileService.java
  32. 38 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/IObjectStorageService.java
  33. 112 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/impl/AliyunIObjectStorageServiceImpl.java
  34. 160 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/impl/FileServiceImpl.java
  35. 119 0
      services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/impl/MinioIObjectStorageServiceImpl.java
  36. 3 0
      services/load-transfer-io/src/main/resources/bootstrap.yaml
  37. 41 0
      services/load-transfer-io/src/main/resources/config/dev/bootstrap-dev.yml
  38. 1 0
      services/load-transfer-io/src/main/resources/config/dev/vol.properties
  39. 38 0
      services/load-transfer-io/src/main/resources/config/local/bootstrap-local.yml
  40. 1 0
      services/load-transfer-io/src/main/resources/config/local/vol.properties
  41. 36 0
      services/load-transfer-io/src/main/resources/config/prod/bootstrap-prod.yml
  42. 41 0
      services/load-transfer-io/src/main/resources/config/test/bootstrap-test.yml
  43. 1 0
      services/load-transfer-io/src/main/resources/config/test/vol.properties
  44. 35 0
      services/load-transfer-io/src/main/resources/config/uat/bootstrap-uat.yml
  45. 33 0
      services/load-transfer-io/src/main/resources/kaptcha.properties
  46. 209 0
      services/load-transfer-io/src/main/resources/log4j2.xml
  47. 1 0
      services/load-transfer-io/src/main/resources/sentinel.properties
  48. 3 3
      services/load-transfer-mq/src/main/java/com/hdkj/lt/mq/mapper/fault/mapping/FhzgFaultAnalyzeCalculateDecudeMapper.xml
  49. 4 4
      services/load-transfer-mq/src/main/java/com/hdkj/lt/mq/mapper/plan/mapping/FhzgPlanAnalyzeCalculateDecudeMapper.xml
  50. 4 4
      services/load-transfer-mq/src/main/java/com/hdkj/lt/mq/mapper/voltageLimitViolation/mapping/FhzgInfoLimitTransferSchemeSwitchingSequenceMapper.xml
  51. 0 2
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/LoadTransferSIApplication.java
  52. 3 3
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/dao/mapping/CityFeederTopoMapper.xml
  53. 18 18
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/dao/mapping/DistMappingFileMapper.xml
  54. 1 0
      services/pom.xml

+ 2 - 2
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IApiTestClient.java

@@ -1,8 +1,8 @@
 package com.hdkj.lt.feign;
 
+import com.hdkj.hussar.ApiResponse;
 import com.hdkj.lt.base.constants.SystemGlobalConstant;
 import com.hdkj.lt.feign.fallback.ApiTestFallBack;
-import com.hdkj.hussar.ApiResponse;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestParam;
  * @Date 2025/4/24 17:58
  * @Version 1.0
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = ApiTestFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, contextId = "IApiTestClient", fallbackFactory = ApiTestFallBack.class)
 public interface IApiTestClient {
     // api远程调用前缀
     String API_PREFIX = "/feign/";

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ICityFeederTopoApiClient.java

@@ -15,7 +15,7 @@ import java.util.List;
 /**
  * @author Annie
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = CityFeederTopoApiClientFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI,contextId = "ICityFeederTopoApiClient", fallbackFactory = CityFeederTopoApiClientFallBack.class)
 public interface ICityFeederTopoApiClient {
     // 处理拓扑数据
     String API_MAPPING_SERVICE_TOPO_GET = "feign/topo/doCityFeederTopo";

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ILineSvgFileApiClient.java

@@ -20,7 +20,7 @@ import java.util.List;
  * @Date 2025/6/3 10:12
  * @Version 1.0
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = LineSvgFileApiClientFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI,contextId = "ILineSvgFileApiClient", fallbackFactory = LineSvgFileApiClientFallBack.class)
 public interface ILineSvgFileApiClient {
     // 获取异动线路信息
     String API_MAPPING_SERVICE_LINE_GET = "feign/mapping/getLineByVersion";

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IMeasurementApiClient.java

@@ -20,7 +20,7 @@ import java.util.Map;
  * @date 2025/5/24 下午3:23
  * @description
  */
-@FeignClient(path = "/measurement", value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = MeasurementApiClientFallBack.class)
+@FeignClient(path = "/measurement", value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI,contextId = "IMeasurementApiClient", fallbackFactory = MeasurementApiClientFallBack.class)
 public interface IMeasurementApiClient {
 
     @ApiOperation(value = "获取token")

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IPsrDeviceApiClient.java

@@ -18,7 +18,7 @@ import java.util.List;
  * @Date 2025/6/3 10:12
  * @Version 1.0
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = PsrDeviceApiClientFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI,contextId = "IPsrDeviceApiClient", fallbackFactory = PsrDeviceApiClientFallBack.class)
 public interface IPsrDeviceApiClient {
     // 获取异动线路信息
     String API_SERVICE_DEVICE_COMMON_GET = "feign/getPsrDeviceByCommonInterface";

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IRefreshCacheApiClient.java

@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestParam;
  * @Date 2025/7/10 20:46
  * @Version 1.0
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_BF, fallbackFactory = RefreshCacheApiClientFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_BF,contextId = "IRefreshCacheApiClient", fallbackFactory = RefreshCacheApiClientFallBack.class)
 public interface IRefreshCacheApiClient {
 
     // 获取异动线路信息

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ISimulationPlatformApiClient.java

@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody;
  * @date 2025/5/26 下午2:22
  * @description
  */
-@FeignClient(path = "/simulation", value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = SimulationPlatformApiClientFallBack.class)
+@FeignClient(path = "/simulation", value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI,contextId = "ISimulationPlatformApiClient", fallbackFactory = SimulationPlatformApiClientFallBack.class)
 public interface ISimulationPlatformApiClient {
     @ApiOperation(value = "获取计划停电转供")
     @PostMapping("/getPlanTransferScheme")

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/IStateEstimationApiClient.java

@@ -20,7 +20,7 @@ import java.util.List;
  * @Date 2025/5/28 16:37
  * @Version 1.0
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI, fallbackFactory = StateEstimationApiClientFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_LOAD_TRANSFER_SI,contextId = "IStateEstimationApiClient", fallbackFactory = StateEstimationApiClientFallBack.class)
 public interface IStateEstimationApiClient {
 
     @PostMapping("feign/stateEstimation/queryPeriodByEquip")

+ 1 - 1
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ISvgGenerationApiClient.java

@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.PostMapping;
  * @Date 2025/6/30 11:09
  * @Version 1.0
  */
-@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_SVG_GENERATION, fallbackFactory = SvgGenerationApiClientFallBack.class)
+@FeignClient(value = SystemGlobalConstant.SERVICE_NAME_SVG_GENERATION,contextId = "ISvgGenerationApiClient", fallbackFactory = SvgGenerationApiClientFallBack.class)
 public interface ISvgGenerationApiClient {
 
     // 根据线路保存文件信息

+ 6 - 6
common/common-core/src/main/resources/mapper/SysDictMapper.xml

@@ -4,12 +4,12 @@
 
     <select id="getDictSingleByTypeName" resultType="com.hdkj.lt.core.sys.model.po.DicSingle">
         SELECT
-            sds.LABEL,
-            sds.VALUE,
-            sds.SORT
-        FROM SYS_DICT_TYPE sdt
-        INNER JOIN SYS_DICT_SINGLE sds ON sdt.TYPE_ID = sds.TYPE_ID AND sdt.TYPE_NAME = #{typeName,jdbcType=VARCHAR}
-        ORDER BY sds.SORT
+            sdd.dict_label as label,
+            sdd.dict_value as value,
+            sdd.dict_sort as sort
+        FROM sys_dict_type sdt
+        INNER JOIN sys_dict_data sdd ON sdt.dict_type = sdd.dict_type AND sdt.dict_type = #{typeName,jdbcType=VARCHAR}
+        ORDER BY sdd.dict_sort
     </select>
 
 </mapper>

+ 1 - 1
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/entity/vo/NoticeListVO.java

@@ -15,7 +15,7 @@ import java.util.List;
 @Data
 public class NoticeListVO {
 
-    private Long id;
+    private String id;
 
     /**
      * 标题

+ 5 - 3
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/FhzgNoticeServiceImpl.java

@@ -18,6 +18,7 @@ import com.hdkj.lt.bf.service.FhzgNoticeAttachmentService;
 import com.hdkj.lt.bf.service.FhzgNoticeReceiveRecordService;
 import com.hdkj.lt.bf.service.FhzgNoticeService;
 import com.ruoyi.common.security.utils.SecurityUtils;
+import com.ruoyi.system.api.model.LoginUser;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -106,7 +107,7 @@ public class FhzgNoticeServiceImpl extends ServiceImpl<FhzgNoticeMapper, FhzgNot
         List<NoticeListVO> noticeListVOList = new ArrayList<>();
         page.getRecords().forEach(i -> {
             NoticeListVO noticeListVO = new NoticeListVO();
-            noticeListVO.setId(i.getId());
+            noticeListVO.setId(String.valueOf(i.getId()));
             noticeListVO.setTitle(i.getTitle());
             noticeListVO.setType(i.getType());
             noticeListVO.setStatus(i.getStatus());
@@ -150,6 +151,7 @@ public class FhzgNoticeServiceImpl extends ServiceImpl<FhzgNoticeMapper, FhzgNot
                 throw new BusinessException("文档标题重复");
             }
         }
+        LoginUser loginUser = SecurityUtils.getLoginUser();
         FhzgNotice fhzgNotice = new FhzgNotice();
         fhzgNotice.setId(noticeAddDTO.getId());
         fhzgNotice.setTitle(noticeAddDTO.getTitle());
@@ -157,8 +159,8 @@ public class FhzgNoticeServiceImpl extends ServiceImpl<FhzgNoticeMapper, FhzgNot
         fhzgNotice.setType(noticeAddDTO.getType());
         fhzgNotice.setStatus(noticeAddDTO.getStatus());
         fhzgNotice.setCreateTime(new Date());
-        fhzgNotice.setUserId(SecurityUtils.getUserId());
-        fhzgNotice.setUserName(SecurityUtils.getUsername());
+        fhzgNotice.setUserId(loginUser.getUserid());
+        fhzgNotice.setUserName(loginUser.getUsername());
         this.saveOrUpdate(fhzgNotice);
         if (noticeAddDTO.getAttachments() != null && !noticeAddDTO.getAttachments().isEmpty()) {
             Long id = fhzgNotice.getId();

+ 3 - 3
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/FhzgPlanStrategyServiceImpl.java

@@ -89,9 +89,9 @@ public class FhzgPlanStrategyServiceImpl implements FhzgPlanStrategyService {
         strategyConfigDTO.setStatus(1);
         LoginUser loginUser = SecurityUtils.getLoginUser();
         if (null != loginUser) {
-            strategyConfigDTO.setCreateName(SecurityUtils.getUsername());
-            strategyConfigDTO.setCreator(SecurityUtils.getUserId());
-            strategyConfigDTO.setLastEditor(SecurityUtils.getUserId());
+            strategyConfigDTO.setCreateName(loginUser.getUsername());
+            strategyConfigDTO.setCreator(loginUser.getUserid());
+            strategyConfigDTO.setLastEditor(loginUser.getUserid());
         }
         strategyConfigDTO.setCreateTime(LocalDateTime.now());
         strategyConfigDTO.setLastTime(LocalDateTime.now());

+ 6 - 5
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/FhzgProblemFeedbackServiceImpl.java

@@ -42,9 +42,10 @@ public class FhzgProblemFeedbackServiceImpl extends ServiceImpl<FhzgProblemFeedb
 
     @Override
     public void save(ProblemFeedbackDTO problemFeedbackDTO) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
         FhzgProblemFeedback fhzgProblemFeedback = new FhzgProblemFeedback();
-        fhzgProblemFeedback.setUserId(SecurityUtils.getUserId());
-        fhzgProblemFeedback.setUserName(SecurityUtils.getUsername());
+        fhzgProblemFeedback.setUserId(loginUser.getUserid());
+        fhzgProblemFeedback.setUserName(loginUser.getUsername());
         fhzgProblemFeedback.setProblemType(problemFeedbackDTO.getProblemType());
         fhzgProblemFeedback.setProblemDetail(problemFeedbackDTO.getProblemDetail());
         fhzgProblemFeedback.setDeleted(0);
@@ -73,10 +74,10 @@ public class FhzgProblemFeedbackServiceImpl extends ServiceImpl<FhzgProblemFeedb
             //非管理员权限只能查自己的问题
             queryWrapper.eq(FhzgProblemFeedback::getUserId, SecurityUtils.getUserId());
         }
-        if(problemFeedbackListDTO.getCreateTime() != null){
+        if (problemFeedbackListDTO.getCreateTime() != null) {
             LocalDateTime start = problemFeedbackListDTO.getCreateTime().atStartOfDay();
-            LocalDateTime end = problemFeedbackListDTO.getCreateTime().atTime(23,59,59,999999999);
-            queryWrapper.between(FhzgProblemFeedback::getCreateTime,start,end);
+            LocalDateTime end = problemFeedbackListDTO.getCreateTime().atTime(23, 59, 59, 999999999);
+            queryWrapper.between(FhzgProblemFeedback::getCreateTime, start, end);
         }
         queryWrapper.eq(!problemFeedbackListDTO.getUserName().isEmpty(), FhzgProblemFeedback::getUserName, problemFeedbackListDTO.getUserName());
         queryWrapper.eq(problemFeedbackListDTO.getProblemType() != null, FhzgProblemFeedback::getProblemType, problemFeedbackListDTO.getProblemType());

+ 0 - 0
services/load-transfer-bf/src/main/resources/bootstrap-dev.yaml → services/load-transfer-bf/src/main/resources/config/dev/bootstrap-dev.yaml


+ 0 - 0
services/load-transfer-bf/src/main/resources/bootstrap-local.yaml → services/load-transfer-bf/src/main/resources/config/local/bootstrap-local.yaml


+ 0 - 0
services/load-transfer-bf/src/main/resources/bootstrap-uat.yaml → services/load-transfer-bf/src/main/resources/config/uat/bootstrap-uat.yaml


+ 1 - 1
services/load-transfer-bf/src/main/resources/mapper/DwdShbDsSwitchBaseMapper.xml

@@ -38,7 +38,7 @@
         from dwd_shb_ds_switch_base a
         left join fhzg_switch_protection_settings c on a.psr_id = c.device_prs_id
         left join t_disable_llkg_config d on a.psr_id= d.llsb_id
-        left join SYS_STRU s on a.maint_org = s.ISC_ORG_ID
+        left join sys_dept s on a.maint_org = s.isc_org_id
         <where>
             a.pub_priv_flag = '0' and a.psr_state = '20'
             <if test="params.feederName != null and params.feederName != ''">

+ 37 - 0
services/load-transfer-io/pom.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.hdkj</groupId>
+        <artifactId>services</artifactId>
+        <version>${revision}</version>
+    </parent>
+
+    <artifactId>load-transfer-io</artifactId><!-- 文件操作 Input Output -->
+
+    <properties>
+        <minio.oss.version>8.0.3</minio.oss.version>
+        <aliyun.oss.version>3.8.0</aliyun.oss.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.hdkj.components</groupId>
+            <artifactId>attachments-api</artifactId>
+            <version>1.0.0.080423_Alpha</version>
+        </dependency>
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>${minio.oss.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>${aliyun.oss.version}</version>
+        </dependency>
+    </dependencies>
+</project>

+ 28 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/LoadTransferIOApplication.java

@@ -0,0 +1,28 @@
+package com.hdkj.lt.io;
+
+import com.hdkj.lt.base.constants.SystemGlobalConstant;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ * @Description:
+ * @Author: wenhao
+ * @Create: 2024/05/23 10:18
+ * @Version: 1.0
+ */
+@EnableFeignClients(basePackages = {SystemGlobalConstant.HUSSAR_ROOT_PACKAGE, SystemGlobalConstant.BIZMS_BASE_PACKAGE})
+@EnableDiscoveryClient
+@SpringBootApplication(scanBasePackages = {SystemGlobalConstant.HUSSAR_BASE_PACKAGE, SystemGlobalConstant.BIZMS_BASE_PACKAGE})
+@MapperScan(basePackages = {SystemGlobalConstant.HUSSAR_DAO_PACKAGE, SystemGlobalConstant.BIZMS_DAO_PACKAGE})
+@EnableCaching
+public class LoadTransferIOApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(LoadTransferIOApplication.class, args);
+    }
+
+}

+ 131 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/aop/FileTypeCheckAop.java

@@ -0,0 +1,131 @@
+package com.hdkj.lt.io.aop;
+
+import com.hdkj.lt.utils.file.FileExtUtils;
+import com.hdkj.lt.utils.file.FileUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.util.WebUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Component
+@RefreshScope
+public class FileTypeCheckAop {
+
+    private static final Map<String, String> FILE_MAP = new HashMap<>();
+
+    @Value("${lt.file.check.file-types}")
+    private List<String> fileTypes;
+
+    static {
+        FILE_MAP.put("image/png", "png");
+        FILE_MAP.put("image/jpeg", "jpg");
+        FILE_MAP.put("image/gif", "gif");
+        FILE_MAP.put("image/svg+xml", "svg");
+        FILE_MAP.put("image/x-icon", "ico");
+        FILE_MAP.put("image/bmp", "bmp");
+        FILE_MAP.put("application/msword", "doc");
+        FILE_MAP.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx");
+        FILE_MAP.put("application/vnd.ms-excel", "xls");
+        FILE_MAP.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx");
+        FILE_MAP.put("application/pdf", "pdf");
+        FILE_MAP.put("application/xml", "xml");
+        FILE_MAP.put("application/vnd.ms-powerpoint", "ppt");
+        FILE_MAP.put("text/plain", "txt");
+        FILE_MAP.put("audio/wav", "wav");
+        FILE_MAP.put("audio/mpeg", "mp3");
+        FILE_MAP.put("audio/x-mpeg", "mp3");
+        FILE_MAP.put("audio/mp4", "m4a");
+        FILE_MAP.put("application/octet-stream", "");
+    }
+
+    @Pointcut("execution(* com.jxdinfo.hussar.support.*.controller.AttachmentManagerController.*(..))")
+    public void poincut() {
+        //Do nothing because of X and Y.
+    }
+
+    @Before("poincut()")
+    public void doBeforeGame(JoinPoint joinPoint) {
+        try {
+            Object[] args = joinPoint.getArgs();
+            for (Object arg : args) {
+                if (arg instanceof HttpServletRequest) {
+                    HttpServletRequest request = (HttpServletRequest) arg;
+                    MultipartHttpServletRequest multipartRequest =
+                            WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
+                    if (multipartRequest == null) {
+                        continue;
+                    }
+                    check(multipartRequest);
+                } else if (arg instanceof MultipartHttpServletRequest) {
+                    check((MultipartHttpServletRequest) arg);
+                } else if (arg instanceof MultipartFile) {
+                    check((MultipartFile) arg);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void check(MultipartHttpServletRequest multipartRequest) throws IOException {
+        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
+        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
+            MultipartFile mf = entity.getValue();
+            check(mf);
+        }
+    }
+
+    public void check(MultipartFile mf) throws IOException {
+
+        byte[] bytes = mf.getBytes();
+        String suffix = "";
+        try {
+            File f = FileExtUtils.multipartFileToFile(mf);
+            suffix = FileExtUtils.getFileType(f);
+            FileUtils.delete(f);
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+        String extend = FileExtUtils.getExtend(mf.getOriginalFilename(), suffix);
+        log.info("文件后缀extend[{}]", extend);
+        log.info("文件原文件类型[{}]", suffix);
+        log.info("文件大小size[{}]", mf.getSize());
+        if (StringUtils.isNotBlank(extend)) {
+            boolean b = FileExtUtils.checkRealExtend(bytes, extend);
+            if (!b && !StringUtils.equalsAny(extend, (CharSequence) fileTypes)) {
+                throw new RuntimeException("文件格式错误");
+            }
+        }
+    }
+
+
+    public void checkFile(MultipartFile mf) throws IOException {
+        byte[] bytes = mf.getBytes();
+        String extend = FileExtUtils.getExtend(mf.getOriginalFilename());
+        log.info("文件后缀extend[{}]", extend);
+        log.info("文件大小size[{}]", mf.getSize());
+        if (StringUtils.isNotBlank(extend)) {
+            boolean b = FileExtUtils.checkRealExtend(bytes, extend);
+            if (!b && !fileTypes.contains(extend.toLowerCase())) {
+                throw new RuntimeException("文件格式错误");
+            }
+        }
+    }
+
+}

+ 31 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/AliyunOSSConfigProperties.java

@@ -0,0 +1,31 @@
+package com.hdkj.lt.io.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/18 16:19
+ * @Version 1.0
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "lt.oss")
+public class AliyunOSSConfigProperties {
+
+    private String endpoint;
+
+    private String showPoint;
+
+    private String accessKeyId;
+
+    private String accessKeySecret;
+
+    private String bucketName;
+
+    private String region;
+
+    private Integer maxKeys;
+}

+ 36 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/AliyunOSSConfiguration.java

@@ -0,0 +1,36 @@
+package com.hdkj.lt.io.config;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.hdkj.lt.io.dao.DistSVGFileMapper;
+import com.hdkj.lt.io.service.impl.AliyunIObjectStorageServiceImpl;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/18 16:19
+ * @Version 1.0
+ */
+@Configuration
+@EnableConfigurationProperties({AliyunOSSConfigProperties.class})
+@ConditionalOnProperty(prefix = "lt.storage", name = "type", havingValue = "oss")
+public class AliyunOSSConfiguration {
+
+    @Bean
+    public OSS ossClient(AliyunOSSConfigProperties aliyunOSSConfigProperties) {
+        return new OSSClientBuilder().build(
+                aliyunOSSConfigProperties.getEndpoint(),
+                aliyunOSSConfigProperties.getAccessKeyId(),
+                aliyunOSSConfigProperties.getAccessKeySecret());
+    }
+
+    @Bean
+    public AliyunIObjectStorageServiceImpl objectStorageService(OSS ossClient, DistSVGFileMapper distSVGFileMapper, AliyunOSSConfigProperties aliyunOSSConfigProperties) {
+        return new AliyunIObjectStorageServiceImpl(ossClient, distSVGFileMapper, aliyunOSSConfigProperties);
+    }
+
+}

+ 20 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/FileCheckProperties.java

@@ -0,0 +1,20 @@
+package com.hdkj.lt.io.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.List;
+
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "lt.file.check")
+public class FileCheckProperties {
+
+    // 可以上传的文件类型
+    private List<String> fileTypes;
+
+    // 是否开启文件上传类型校验
+    private boolean enabled = false;
+
+}

+ 29 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/MinioOSSConfigProperties.java

@@ -0,0 +1,29 @@
+package com.hdkj.lt.io.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/18 16:19
+ * @Version 1.0
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "lt.minio")
+public class MinioOSSConfigProperties {
+
+    private String endpoint;
+
+    private String showPoint;
+
+    private String accessKey;
+
+    private String secretKey;
+
+    private String bucketName;
+
+    private Integer maxKeys;
+}

+ 36 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/config/MinioOSSConfiguration.java

@@ -0,0 +1,36 @@
+package com.hdkj.lt.io.config;
+
+import com.hdkj.lt.io.dao.DistSVGFileMapper;
+import com.hdkj.lt.io.service.impl.MinioIObjectStorageServiceImpl;
+import io.minio.MinioClient;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/18 16:19
+ * @Version 1.0
+ */
+@Configuration
+@EnableConfigurationProperties({MinioOSSConfigProperties.class})
+@ConditionalOnProperty(prefix = "lt.storage", name = "type", havingValue = "minio")
+public class MinioOSSConfiguration {
+
+    @Bean
+    public MinioClient minioClient(MinioOSSConfigProperties minioOSSConfigProperties) {
+        return MinioClient.builder()
+                .endpoint(minioOSSConfigProperties.getEndpoint())
+                .credentials(minioOSSConfigProperties.getAccessKey(), minioOSSConfigProperties.getSecretKey())
+                .build();
+    }
+
+
+    @Bean
+    public MinioIObjectStorageServiceImpl objectStorageService(MinioClient minioClient, DistSVGFileMapper distSVGFileMapper, MinioOSSConfigProperties minioOSSConfigProperties) {
+        return new MinioIObjectStorageServiceImpl(minioClient, distSVGFileMapper, minioOSSConfigProperties);
+    }
+
+}

+ 130 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/controller/FileController.java

@@ -0,0 +1,130 @@
+package com.hdkj.lt.io.controller;
+
+import com.hdkj.attachments.client.entity.Attachment;
+import com.hdkj.attachments.client.entity.AttachmentsParam;
+import com.hdkj.attachments.client.response.ResponseData;
+import com.hdkj.lt.io.service.IFileService;
+import com.hdkj.lt.io.service.IObjectStorageService;
+import com.hdkj.lt.modle.FileIdRequestDTO;
+import com.hdkj.lt.modle.FileUploadDTO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+@Api(tags = "附件相关")
+@RestController
+@RequiredArgsConstructor
+@Validated
+public class FileController {
+
+    private final IFileService fileService;
+    private final IObjectStorageService objectStorageService;
+
+    /**
+     * 附件下载
+     */
+    @GetMapping("/download")
+    @ApiOperation(value = "附件下载")
+    public void download(@Valid @NotNull(message = "附件ID不能为空") Long id, HttpServletResponse response) throws Exception {
+        fileService.download(id, response);
+    }
+
+    /**
+     * 附件批量下载
+     */
+    @PostMapping("/downloadZip")
+    @ApiOperation(value = "附件批量下载")
+    public void downloadZip(@Valid @RequestBody FileIdRequestDTO fileIdRequest, HttpServletResponse response) throws Exception {
+        fileService.downloadZip(fileIdRequest.getIds(), response);
+    }
+
+    /**
+     * 查询附件列表
+     */
+    @PostMapping("/list")
+    @ApiOperation(value = "查询附件列表")
+    public ResponseData<List<Attachment>> list(@RequestBody AttachmentsParam attachmentsParam) throws Exception {
+        return fileService.list(attachmentsParam);
+    }
+
+    /**
+     * 附件信息详情
+     */
+    @GetMapping("/detail")
+    @ApiOperation(value = "附件信息详情")
+    public ResponseData<Attachment> detail(@Valid @NotNull(message = "附件ID不能为空") Long id) throws Exception {
+        return fileService.detail(id);
+    }
+
+    /**
+     * 多文件上传附件上传
+     */
+    @PostMapping("/uploads")
+    @ApiOperation(value = "多文件上传附件上传")
+    public ResponseData<List<Attachment>> uploads(@RequestParam("files") MultipartFile[] multipartFiles) throws Exception {
+        return fileService.uploads(multipartFiles);
+    }
+
+    /**
+     * 单附件上传
+     */
+    @PostMapping("/upload")
+    @ApiOperation(value = "附件上传")
+    public ResponseData<Attachment> upload(@RequestParam("file") MultipartFile multipartFile) throws Exception {
+        return fileService.upload(multipartFile);
+    }
+
+    /**
+     * 附件删除
+     */
+    @GetMapping("/delete")
+    @ApiOperation(value = "附件删除")
+    public ResponseData<String> delete(@Valid @NotNull(message = "附件ID不能为空") Long id) throws Exception {
+        fileService.delete(id);
+        return ResponseData.success("附件删除成功");
+    }
+
+    /**
+     * 配电云主站附件查询
+     */
+    @GetMapping("/listObject")
+    @ApiOperation(value = "附件查询")
+    public ResponseData<List<FileUploadDTO>> listObject(@Valid @NotNull(message = "附件文件夹名不能为空") String fileDir) {
+        return ResponseData.success(objectStorageService.listObject(fileDir));
+    }
+
+    /**
+     * 配电云主站附件下载
+     */
+    @GetMapping("/getObject")
+    @ApiOperation(value = "附件下载")
+    public ResponseData<String> getObject(@Valid @NotNull(message = "附件全路径名不能为空") String objectName) {
+        return ResponseData.success(new String(objectStorageService.getObject(objectName), StandardCharsets.UTF_8));
+    }
+
+    /**
+     * 配电云主站附件删除
+     */
+    @GetMapping("/removeObject")
+    @ApiOperation(value = "附件删除")
+    public ResponseData<String> removeObject(@Valid @NotNull(message = "附件全路径名不能为空") String objectName) {
+        objectStorageService.removeObject(objectName);
+        return ResponseData.success("云主站附件删除成功");
+    }
+
+    @GetMapping("/feign/topo/getById")
+    @ApiOperation(value = "附件信息详情")
+    public byte[] getById(@Valid @NotNull(message = "附件ID不能为空") Long id) throws Exception {
+        return fileService.getFileById(id).getData();
+    }
+
+}

+ 19 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/dao/DistSVGFileMapper.java

@@ -0,0 +1,19 @@
+package com.hdkj.lt.io.dao;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import java.time.LocalDateTime;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/7/11 15:03
+ * @Version 1.0
+ */
+@Mapper
+public interface DistSVGFileMapper {
+    /**
+     * 获取配置的更新文件时间
+     */
+    LocalDateTime getConfigFileChangeTime();
+}

+ 9 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/dao/mapping/DistSVGFileMapper.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.hdkj.lt.io.dao.DistSVGFileMapper">
+
+    <select id="getConfigFileChangeTime" resultType="java.time.LocalDateTime">
+        SELECT max(LAST_TIME) conf_time from SYS_BASE_CONFIG where CONFIG_KEY = 'ds_svg_file_config' group by CONFIG_KEY
+    </select>
+
+</mapper>

+ 104 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/feign/FileApiClient.java

@@ -0,0 +1,104 @@
+package com.hdkj.lt.io.feign;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.io.FileUtil;
+import com.hdkj.attachments.client.entity.Attachment;
+import com.hdkj.attachments.client.response.ResponseData;
+import com.hdkj.hussar.ApiResponse;
+import com.hdkj.lt.feign.IFileApiClient;
+import com.hdkj.lt.io.service.IFileService;
+import com.hdkj.lt.io.service.IObjectStorageService;
+import com.hdkj.lt.modle.FileInfoDTO;
+import com.hdkj.lt.modle.FileRequest;
+import com.hdkj.lt.modle.FileUploadDTO;
+import com.hdkj.lt.utils.file.FileExtUtils;
+import com.hdkj.lt.utils.file.FileUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import springfox.documentation.annotations.ApiIgnore;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/3 17:58
+ * @Version 1.0
+ */
+@ApiIgnore
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+public class FileApiClient implements IFileApiClient {
+
+    private final IFileService fileService;
+    private final IObjectStorageService objectStorageService;
+
+    @PostMapping(IFileApiClient.API_IO_SERVICE_FILE_UPLOAD)
+    public ApiResponse<FileInfoDTO> upload(@RequestBody FileRequest request) {
+        Assert.isTrue(!StringUtils.isAnyEmpty(request.getFileContent(), request.getFileName()), "附件内容和附件名称不允许为空!");
+        // 上传临时文件信息, 成图服务文件名防止不加后缀时处理方式,配电云主站不存在
+        String fileName = request.getFileName();
+        if (!StringUtils.endsWithAny(fileName.toLowerCase(), ".svg", ".xml")) {
+            fileName = String.format("%s.svg", request.getFileName());
+        }
+        File file = FileUtils.customFileByPath(fileName);
+        try {
+            // 生成本地SVG或者XML临时文件
+            FileUtil.writeBytes(request.getFileContent().getBytes(StandardCharsets.UTF_8), file);
+            // 上传文件
+            MultipartFile multipartFile = FileUtils.file2MultipartFile(file);
+            ResponseData<Attachment> upload = fileService.upload(multipartFile); // 文件上传
+            if (Integer.compare(upload.getCode(), ResponseData.DEFAULT_SUCCESS_CODE) == 0) { // 上传成功转换输出
+                FileInfoDTO fileInfoDTO = BeanUtil.copyProperties(upload.getData(), FileInfoDTO.class);
+                return ApiResponse.success(fileInfoDTO);
+            } else { // 上传失败提示错误
+                return ApiResponse.fail(upload.getMessage());
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            return ApiResponse.fail(ex.getMessage());
+        } finally {
+            FileExtUtils.deleteTempFile(file);
+        }
+    }
+
+    @PostMapping(IFileApiClient.API_IO_SERVICE_FILE_GET)
+    public ApiResponse<byte[]> getFileById(@RequestBody FileRequest request) {
+        Assert.isTrue(ObjectUtils.isNotEmpty(request.getFileId()), "附件ID不允许为空!");
+        try {
+            ResponseData<byte[]> fileDate = fileService.getFileById(request.getFileId());
+            return ApiResponse.success(fileDate.getData());
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            return ApiResponse.fail(ex.getMessage());
+        }
+    }
+
+    @GetMapping(IFileApiClient.API_IO_SERVICE_LIST_OBJECT)
+    public ApiResponse<List<FileUploadDTO>> listObject(@RequestParam("fileDir") String fileDir) {
+        Assert.isTrue(StringUtils.isNotEmpty(fileDir), "文件夹名称不允许为空!");
+        return ApiResponse.success(objectStorageService.listObject(fileDir));
+    }
+
+    @GetMapping(IFileApiClient.API_IO_SERVICE_GET_OBJECT)
+    public ApiResponse<byte[]> getObject(@RequestParam("objectName") String objectName) {
+        Assert.isTrue(StringUtils.isNotEmpty(objectName), "附件全路径名称不允许为空!");
+        return ApiResponse.success(objectStorageService.getObject(objectName));
+    }
+
+    @GetMapping(IFileApiClient.API_IO_SERVICE_REMOVE_OBJECT)
+    public ApiResponse<String> removeObject(@RequestParam("objectName") String objectName) {
+        Assert.isTrue(StringUtils.isNotEmpty(objectName), "附件全路径名称不允许为空!");
+        objectStorageService.removeObject(objectName);
+        return ApiResponse.success("配电云主站异动附件删除成功");
+    }
+
+}

+ 39 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/IFileService.java

@@ -0,0 +1,39 @@
+package com.hdkj.lt.io.service;
+
+import com.hdkj.attachments.client.entity.Attachment;
+import com.hdkj.attachments.client.entity.AttachmentsParam;
+import com.hdkj.attachments.client.response.ResponseData;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/4 8:47
+ * @Version 1.0
+ */
+public interface IFileService {
+
+    void download(Long id, HttpServletResponse response) throws Exception;
+
+    void downloadZip(List<Long> ids, HttpServletResponse response) throws Exception;
+
+    ResponseData<List<Attachment>> list(AttachmentsParam attachmentsParam) throws Exception;
+
+    ResponseData<Attachment> detail(Long id) throws Exception;
+
+    ResponseData<List<Attachment>> uploads(MultipartFile[] multipartFiles) throws Exception;
+
+    ResponseData<Attachment> upload(MultipartFile multipartFile) throws Exception;
+
+    ResponseData<Void> delete(Long id) throws Exception;
+
+    ResponseData<byte[]> getFileById(Long id) throws Exception;
+
+}

+ 38 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/IObjectStorageService.java

@@ -0,0 +1,38 @@
+package com.hdkj.lt.io.service;
+
+import com.hdkj.lt.modle.FileUploadDTO;
+
+import java.util.List;
+
+/**
+ * @Description 对象存储服务
+ * @Author wcx
+ * @Date 2025/6/18 15:59
+ * @Version 1.0
+ */
+public interface IObjectStorageService {
+
+    /**
+     * 获取文件流
+     *
+     * @param objectName 文件存储的全路径,如:tb/2024-08-21/xxx.xls
+     * @return 文件流
+     */
+    byte[] getObject(String objectName);
+
+    /**
+     * 获取文件夹下文件信息
+     *
+     * @param fileDir
+     * @return
+     */
+    List<FileUploadDTO> listObject(String fileDir);
+
+    /**
+     * 删除文件
+     *
+     * @param objectName 文件全路径,如:tb/2024-08-21/xxx.xls
+     * @return
+     */
+    void removeObject(String objectName);
+}

+ 112 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/impl/AliyunIObjectStorageServiceImpl.java

@@ -0,0 +1,112 @@
+package com.hdkj.lt.io.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.model.*;
+import com.hdkj.lt.base.constants.CommonConstant;
+import com.hdkj.lt.base.constants.SymbolConstants;
+import com.hdkj.lt.io.config.AliyunOSSConfigProperties;
+import com.hdkj.lt.io.dao.DistSVGFileMapper;
+import com.hdkj.lt.io.service.IObjectStorageService;
+import com.hdkj.lt.modle.FileUploadDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.compress.utils.Lists;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import java.time.LocalDateTime;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.ZoneId;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/18 16:16
+ * @Version 1.0
+ */
+@Slf4j
+public class AliyunIObjectStorageServiceImpl implements IObjectStorageService {
+
+    private final OSS ossClient;
+
+    private final DistSVGFileMapper distSVGFileMapper;
+
+    private final AliyunOSSConfigProperties aliyunOssConfigProperties;
+
+    public AliyunIObjectStorageServiceImpl(OSS ossClient, DistSVGFileMapper distSVGFileMapper, AliyunOSSConfigProperties aliyunOssConfigProperties) {
+        this.ossClient = ossClient;
+        this.distSVGFileMapper = distSVGFileMapper;
+        this.aliyunOssConfigProperties = aliyunOssConfigProperties;
+    }
+
+    @Override
+    public byte[] getObject(String objectName) {
+        GetObjectRequest request = new GetObjectRequest(aliyunOssConfigProperties.getBucketName(), objectName);
+        OSSObject response = ossClient.getObject(request);
+        try (InputStream inputStream = response.getObjectContent();) {
+            return IOUtils.toByteArray(inputStream);
+        } catch (IOException e) {
+            log.error("下载文件失败:{}", e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    @Override
+    public List<FileUploadDTO> listObject(String fileDir) {
+        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(aliyunOssConfigProperties.getBucketName(),
+                String.format("%s/", fileDir), null, SymbolConstants.FORWARD_SLASH, aliyunOssConfigProperties.getMaxKeys());
+        List<FileUploadDTO> fileNameList = Lists.newArrayList();
+        // 配置变更生效时间
+        LocalDateTime configTime = distSVGFileMapper.getConfigFileChangeTime();
+        // 分页文件对象
+        ObjectListing response;
+        do {
+            response = ossClient.listObjects(listObjectsRequest);
+            fileNameList.addAll(response.getObjectSummaries()
+                    .stream()
+                    .filter(e -> this.isChangeFile(e, configTime))
+                    .map(e -> FileUploadDTO.builder().fileName(e.getKey()).uploadTime(DateUtil.toLocalDateTime(e.getLastModified())).build())
+                    .collect(Collectors.toList()));
+
+            // 设置获取下一页的文件数据
+            listObjectsRequest.setMarker(response.getNextMarker());
+        } while (response.isTruncated());
+        return fileNameList;
+    }
+
+    @Override
+    public void removeObject(String objectName) {
+        GenericRequest request = new GenericRequest(aliyunOssConfigProperties.getBucketName(), objectName);
+        ossClient.deleteObject(request);
+    }
+
+
+    /**
+     * 判断是否异动文件
+     */
+    private Boolean isChangeFile(OSSObjectSummary objectSummary, LocalDateTime configTime) {
+        // 大于配置文件时、非文件夹、是svg和xml后缀
+        if (!this.isFolder(objectSummary)) {
+            // 文件最后修改时间设置时区
+            LocalDateTime dateAsLocal = objectSummary.getLastModified()
+                    .toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+            // 配置时间设置时区时间
+            LocalDateTime configTimeAsLocal = configTime.atZone(ZoneId.systemDefault()).toLocalDateTime();
+            // 取配置时间之后且 后缀为.xml和.svg的异动文件及.txt终结文件
+            return configTimeAsLocal.isBefore(dateAsLocal) &&
+                    StringUtils.endsWithAny(objectSummary.getKey().toLowerCase(), ".xml", ".svg", ".txt");
+        }
+        return Boolean.FALSE;
+    }
+
+    /**
+     * 判断OSS对象是否为文件夹
+     */
+    private Boolean isFolder(OSSObjectSummary objectSummary) {
+        return StringUtils.endsWithIgnoreCase(objectSummary.getKey(), SymbolConstants.FORWARD_SLASH)
+                && Long.compare(objectSummary.getSize(), Long.valueOf(CommonConstant.ZERO)) == 0;
+    }
+}

+ 160 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/impl/FileServiceImpl.java

@@ -0,0 +1,160 @@
+package com.hdkj.lt.io.service.impl;
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import com.hdkj.attachments.client.entity.Attachment;
+import com.hdkj.attachments.client.entity.AttachmentsParam;
+import com.hdkj.attachments.client.facade.IAttachmentFacadeClient;
+import com.hdkj.attachments.client.response.ResponseData;
+import com.hdkj.lt.io.aop.FileTypeCheckAop;
+import com.hdkj.lt.io.config.FileCheckProperties;
+import com.hdkj.lt.io.service.IFileService;
+import com.ruoyi.common.third.constants.StringPool;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.codec.Charsets;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.util.UriUtils;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/4 8:48
+ * @Version 1.0
+ */
+@Service
+@RequiredArgsConstructor
+public class FileServiceImpl implements IFileService {
+
+    private final IAttachmentFacadeClient attachmentFacadeClient;
+
+    private final FileCheckProperties fileCheckProperties;
+
+    private final FileTypeCheckAop fileTypeCheckAop;
+
+
+    @Override
+    public void download(Long id, HttpServletResponse response) throws Exception {
+        ResponseData<Attachment> detail = attachmentFacadeClient.detail(id);
+        String fileName = detail.getData().getOriginName();
+        byte[] data = attachmentFacadeClient.download(id).getData();
+        try (BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream())) {
+            // 转码,免得文件名中文乱码
+            fileName = UriUtils.encode(fileName, StringPool.UTF_8);
+            // 清空response
+            response.reset();
+            // 设置文件下载头
+            response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
+            // 设置文件ContentType类型,这样设置,会自动判断下载文件类型(svg文件前端需要指定特殊类型)
+            if (StringUtils.endsWithIgnoreCase(fileName, ".svg")) {
+                response.setContentType("image/svg+xml");
+            } else {
+                response.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
+            }
+            out.write(data);
+            out.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void downloadZip(List<Long> ids, HttpServletResponse response) throws Exception {
+        try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
+            // 文件名(暂时以时间命名)
+            String fileName = DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN);
+            // 清空response
+            response.reset();
+            response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
+            response.setHeader(HttpHeaders.CONTENT_TYPE, "application/zip");
+            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment;filename=%s.zip", fileName));
+            response.setCharacterEncoding(Charsets.UTF_8.toString());
+            for (Long id : ids) {
+                ResponseData<Attachment> detail = attachmentFacadeClient.detail(id);
+                byte[] data = attachmentFacadeClient.download(id).getData();
+                if (ObjectUtils.isNotEmpty(data)) {
+                    zos.putNextEntry(new ZipEntry(detail.getData().getOriginName()));
+                    Integer offset = 0; // 起始读取位置
+                    Integer bufferSize = 10240; // 10KB缓冲区
+                    while (offset < data.length) {
+                        Integer chunkSize = Math.min(bufferSize, data.length - offset);
+                        zos.write(data, offset, chunkSize);
+                        offset += chunkSize;
+                    }
+                    zos.closeEntry();
+                }
+                data = null; // 快速回收防止内存溢出
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public ResponseData<List<Attachment>> list(AttachmentsParam attachmentsParam) throws Exception {
+        return attachmentFacadeClient.list(attachmentsParam);
+    }
+
+    @Override
+    public ResponseData<Attachment> detail(Long id) throws Exception {
+        return attachmentFacadeClient.detail(id);
+    }
+
+    @Override
+    public ResponseData<List<Attachment>> uploads(MultipartFile[] multipartFiles) throws Exception {
+        // 文件上传安全校验开
+        if (fileCheckProperties.isEnabled()) {
+            for (MultipartFile multipartFile : multipartFiles) {
+                try {
+                    fileTypeCheckAop.checkFile(multipartFile);
+                } catch (RuntimeException runtimeException) {
+                    return ResponseData.error(runtimeException.getMessage());
+                }
+            }
+        }
+        // 文件上传安全校验结束
+        List<Attachment> attachments = new ArrayList<>();
+        for (MultipartFile multipartFile : multipartFiles) {
+            attachments.add(attachmentFacadeClient.upload(multipartFile).getData());
+        }
+        return ResponseData.success(attachments);
+    }
+
+    @Override
+    public ResponseData<Attachment> upload(MultipartFile multipartFile) throws Exception {
+        // 文件上传安全校验开始
+        if (fileCheckProperties.isEnabled()) {
+            try {
+                fileTypeCheckAop.checkFile(multipartFile);
+            } catch (RuntimeException runtimeException) {
+                return ResponseData.error(runtimeException.getMessage());
+            }
+        }
+        // 文件上传安全校验结束
+        return attachmentFacadeClient.upload(multipartFile);
+    }
+
+    @Override
+    public ResponseData<Void> delete(Long id) throws Exception {
+        return attachmentFacadeClient.delete(id);
+    }
+
+    @Override
+    public ResponseData<byte[]> getFileById(Long id) throws Exception {
+        byte[] fileData = attachmentFacadeClient.download(id).getData();
+        return ResponseData.success(fileData);
+    }
+}

+ 119 - 0
services/load-transfer-io/src/main/java/com/hdkj/lt/io/service/impl/MinioIObjectStorageServiceImpl.java

@@ -0,0 +1,119 @@
+package com.hdkj.lt.io.service.impl;
+
+import com.google.common.collect.Lists;
+import com.hdkj.lt.base.constants.SymbolConstants;
+import com.hdkj.lt.io.config.MinioOSSConfigProperties;
+import com.hdkj.lt.io.dao.DistSVGFileMapper;
+import com.hdkj.lt.io.service.IObjectStorageService;
+import com.hdkj.lt.modle.FileUploadDTO;
+import io.minio.*;
+import io.minio.messages.Item;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.InputStream;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.List;
+
+/**
+ * @Description
+ * @Author wcx
+ * @Date 2025/6/18 16:15
+ * @Version 1.0
+ */
+@Slf4j
+public class MinioIObjectStorageServiceImpl implements IObjectStorageService {
+
+    private final MinioClient minioClient;
+
+    private final DistSVGFileMapper distSVGFileMapper;
+
+    private final MinioOSSConfigProperties minioOssConfigProperties;
+
+    public MinioIObjectStorageServiceImpl(MinioClient minioClient, DistSVGFileMapper distSVGFileMapper, MinioOSSConfigProperties minioConfigProperties) {
+        this.minioClient = minioClient;
+        this.distSVGFileMapper = distSVGFileMapper;
+        this.minioOssConfigProperties = minioConfigProperties;
+    }
+
+    @Override
+    public byte[] getObject(String objectName) {
+        GetObjectArgs args = GetObjectArgs.builder()
+                .bucket(minioOssConfigProperties.getBucketName())
+                .object(objectName).build();
+        try (InputStream inputStream = minioClient.getObject(args)) {
+            return IOUtils.toByteArray(inputStream);
+        } catch (Exception e) {
+            log.error("下载文件失败:{}", e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    @Override
+    public List<FileUploadDTO> listObject(String fileDir) {
+        try {
+            List<FileUploadDTO> fileNameList = Lists.newArrayList();
+            // 配置变更生效时间
+            LocalDateTime configTime = distSVGFileMapper.getConfigFileChangeTime();
+            List<Result<Item>> fileList;
+            String keyMarker = null;
+            do {
+                ListObjectsArgs args = ListObjectsArgs.builder()
+                        .bucket(minioOssConfigProperties.getBucketName())
+                        .prefix(String.format("%s/", fileDir))
+                        .delimiter(SymbolConstants.FORWARD_SLASH)
+                        .maxKeys(minioOssConfigProperties.getMaxKeys())
+                        .marker(keyMarker)
+                        .build();
+
+                // 迭代器转成集合
+                fileList = Lists.newArrayList(minioClient.listObjects(args));
+                // 查看本次查询是否还存在文件
+                for (Result<Item> result : fileList) {
+                    Item item = result.get();
+                    if (!item.isDir() && this.isChangeFile(item, configTime)) {
+                        LocalDateTime uploadTime = item.lastModified().withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
+                        fileNameList.add(FileUploadDTO.builder().fileName(item.objectName()).uploadTime(uploadTime).build());
+                    }
+                }
+                keyMarker = fileList.get(fileList.size() - 1).get().objectName();
+            } while (CollectionUtils.size(fileList) == minioOssConfigProperties.getMaxKeys());
+            return fileNameList;
+        } catch (Exception e) {
+            log.error("批量获取失败:{}", e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    @Override
+    public void removeObject(String objectName) {
+        try {
+            RemoveObjectArgs args = RemoveObjectArgs.builder()
+                    .bucket(minioOssConfigProperties.getBucketName())
+                    .object(objectName)
+                    .build();
+            minioClient.removeObject(args);
+        } catch (Exception e) {
+            log.error("删除文件失败:{}", e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 判断是否异动文件
+     */
+    private Boolean isChangeFile(Item item, LocalDateTime configTime) {
+        // 文件最后修改时间设置时区
+        LocalDateTime dateAsLocal = item.lastModified()
+                .withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
+        // 配置时间设置时区时间
+        LocalDateTime configTimeAsLocal = configTime.atZone(ZoneId.systemDefault()).toLocalDateTime();
+        // 取配置时间之后且 后缀为.xml和.svg的异动文件及.txt终结文件
+        return configTimeAsLocal.isBefore(dateAsLocal) &&
+                StringUtils.endsWithAny(item.objectName().toLowerCase(), ".xml", ".svg", ".txt");
+
+    }
+}

+ 3 - 0
services/load-transfer-io/src/main/resources/bootstrap.yaml

@@ -0,0 +1,3 @@
+spring:
+  profiles:
+    active: @environment@

+ 41 - 0
services/load-transfer-io/src/main/resources/config/dev/bootstrap-dev.yml

@@ -0,0 +1,41 @@
+# 开发环境配置文件(27.54.100.167)
+NACOS_HOST: 192.168.10.176
+NACOS_PORT: 18848
+NACOS_PWD: FHZG@nacos2025
+NAMESPACE: 682eb787-7279-47d8-8516-79b521f96690
+
+server:
+  servlet:
+    context-path: /
+  port: 19003
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    static-path-pattern: /static/**         # 静态资源路径
+    view:
+      prefix: /WEB-INF/view
+  application:
+    name: load-transfer-io
+  cloud:
+    nacos:
+      discovery:
+        username: nacos
+        password: ${NACOS_PWD}
+        server-addr: ${NACOS_HOST}:${NACOS_PORT}
+        namespace: ${NAMESPACE}
+        metadata:
+          formdesign: true
+      config:
+        server-addr: ${spring.cloud.nacos.discovery.server-addr}
+        username: ${spring.cloud.nacos.discovery.username}
+        password: ${spring.cloud.nacos.discovery.password}
+        namespace: ${spring.cloud.nacos.discovery.namespace}
+        file-extension: yml
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #公共配置
+          - datasource-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}  #数据源配置
+          - hussar-common-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #轻骑兵框架配置
+          - hussar-cloud-oss-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+          - load-transfer-custom-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #负荷转供系统自定义配置

+ 1 - 0
services/load-transfer-io/src/main/resources/config/dev/vol.properties

@@ -0,0 +1 @@
+hussar.vol.server=http://192.168.10.93:18090

+ 38 - 0
services/load-transfer-io/src/main/resources/config/local/bootstrap-local.yml

@@ -0,0 +1,38 @@
+# 本地环境配置文件(研发网终端)
+NACOS_HOST: 27.54.100.176
+NACOS_PORT: 18848
+NACOS_PWD: FHZG@nacos2025
+NAMESPACE: 88b0baca-b7b1-496c-8ebd-bbfea7959c49
+
+server:
+  servlet:
+    context-path: /
+  port: 19003
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    static-path-pattern: /static/**         # 静态资源路径
+    view:
+      prefix: /WEB-INF/view
+  application:
+    name: load-transfer-io
+  cloud:
+    nacos:
+      discovery:
+        username: nacos
+        password: ${NACOS_PWD}
+        server-addr: ${NACOS_HOST}:${NACOS_PORT}
+        namespace: ${NAMESPACE}
+        metadata:
+          formdesign: true
+      config:
+        server-addr: ${spring.cloud.nacos.discovery.server-addr}
+        username: ${spring.cloud.nacos.discovery.username}
+        password: ${spring.cloud.nacos.discovery.password}
+        namespace: ${spring.cloud.nacos.discovery.namespace}
+        file-extension: yaml
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #公共配置
+          - datasource.${spring.cloud.nacos.config.file-extension}  #数据源配置

+ 1 - 0
services/load-transfer-io/src/main/resources/config/local/vol.properties

@@ -0,0 +1 @@
+hussar.vol.server=http://27.54.100.93:18090

+ 36 - 0
services/load-transfer-io/src/main/resources/config/prod/bootstrap-prod.yml

@@ -0,0 +1,36 @@
+# 生产环境配置文件(25.91.75.XXX)
+NACOS_HOST: 192.168.10.176
+NACOS_PORT: 18848
+NAMESPACE: 986c37cf-7d33-41ff-ae5d-c5fc62b83ade
+
+server:
+  servlet:
+    context-path: /
+  port: 19003
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    static-path-pattern: /static/**         # 静态资源路径
+    view:
+      prefix: /WEB-INF/view
+  application:
+    name: load-transfer-io
+  cloud:
+    nacos:
+      discovery:
+        server-addr: ${NACOS_HOST}:${NACOS_PORT}
+        namespace: ${NAMESPACE}
+        metadata:
+          formdesign: true
+      config:
+        server-addr: ${spring.cloud.nacos.discovery.server-addr}
+        namespace: ${spring.cloud.nacos.discovery.namespace}
+        file-extension: yml
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #公共配置
+          - datasource-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}  #数据源配置
+          - hussar-common-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #轻骑兵框架配置
+          - hussar-cloud-oss-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+          - load-transfer-custom-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #负荷转供系统自定义配置

+ 41 - 0
services/load-transfer-io/src/main/resources/config/test/bootstrap-test.yml

@@ -0,0 +1,41 @@
+# 测试环境配置文件(27.54.100.168)
+NACOS_HOST: 192.168.10.176
+NACOS_PORT: 18848
+NACOS_PWD: FHZG@nacos2025
+NAMESPACE: b0a462af-0f3b-4b67-b181-3de6f4b5d07d
+
+server:
+  servlet:
+    context-path: /
+  port: 19003
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    static-path-pattern: /static/**         # 静态资源路径
+    view:
+      prefix: /WEB-INF/view
+  application:
+    name: load-transfer-io
+  cloud:
+    nacos:
+      discovery:
+        username: nacos
+        password: ${NACOS_PWD}
+        server-addr: ${NACOS_HOST}:${NACOS_PORT}
+        namespace: ${NAMESPACE}
+        metadata:
+          formdesign: true
+      config:
+        server-addr: ${spring.cloud.nacos.discovery.server-addr}
+        username: ${spring.cloud.nacos.discovery.username}
+        password: ${spring.cloud.nacos.discovery.password}
+        namespace: ${spring.cloud.nacos.discovery.namespace}
+        file-extension: yml
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #公共配置
+          - datasource-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}  #数据源配置
+          - hussar-common-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #轻骑兵框架配置
+          - hussar-cloud-oss-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+          - load-transfer-custom-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #负荷转供系统自定义配置

+ 1 - 0
services/load-transfer-io/src/main/resources/config/test/vol.properties

@@ -0,0 +1 @@
+hussar.vol.server=http://192.168.10.93:18090

+ 35 - 0
services/load-transfer-io/src/main/resources/config/uat/bootstrap-uat.yml

@@ -0,0 +1,35 @@
+NACOS_HOST: http://jmenv-dncs.hb-2-am301-a.res.sgmc.sgcc.com.cn
+NACOS_PORT: 8848
+NAMESPACE: 74226456-1d37-4a89-bbb3-08d24fb54126
+
+server:
+  servlet:
+    context-path: /
+  port: 19003
+
+spring:
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    static-path-pattern: /static/**         # 静态资源路径
+    view:
+      prefix: /WEB-INF/view
+  application:
+    name: load-transfer-io
+  cloud:
+    nacos:
+      discovery:
+        server-addr: ${NACOS_HOST}:${NACOS_PORT}
+        namespace: ${NAMESPACE}
+        metadata:
+          formdesign: true
+      config:
+        server-addr: ${spring.cloud.nacos.discovery.server-addr}
+        namespace: ${spring.cloud.nacos.discovery.namespace}
+        file-extension: yml
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #公共配置
+          - datasource-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}  #数据源配置
+          - hussar-common-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #轻骑兵框架配置
+          - hussar-cloud-oss-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+          - load-transfer-custom-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} #负荷转供系统自定义配置

+ 33 - 0
services/load-transfer-io/src/main/resources/kaptcha.properties

@@ -0,0 +1,33 @@
+#============================验证码相关配置=====================
+#是否加边框<yes,no>
+kaptcha.border=no
+#边框颜色<RGB>
+kaptcha.border.color=105,179,90
+#字体颜色
+kaptcha.textproducer.font.color=black
+#字体大小
+kaptcha.textproducer.font.size=40
+#字体类型
+kaptcha.textproducer.font.names=NexaBlack
+#验证码字符个数
+kaptcha.textproducer.char.length=4
+#验证码字符间距
+kaptcha.textproducer.char.space=3
+#文本集合,验证码值从此集合中获取,不包含易混字符1、l、0、o等
+kaptcha.textproducer.char.string=ABCDEFGHGKMNPQRSTUVWXYZ23456789
+#验证码图片宽度
+kaptcha.image.width=120
+#验证码图片高度
+kaptcha.image.height=46
+#session key
+kaptcha.session.key=code
+#背景颜色渐变开始颜色
+kaptcha.background.clear.from=247,247,247
+#背景颜色渐变结束颜色
+kaptcha.background.clear.to=247,247,247
+#验证码干扰实现类<默认不加干扰线>
+kaptcha.noise.impl=com.google.code.kaptcha.impl.NoNoise
+#验证码阴影干扰
+kaptcha.obscurificator.impl=com.google.code.kaptcha.impl.ShadowGimpy
+#验证码随机数生成器,排除0、1、2、o、O、i、I等易混字符,且随机值必须包含大小写和数字
+kaptcha.textproducer.impl=com.jxdinfo.hussar.authorization.kaptcha.KaptchaRandom

+ 209 - 0
services/load-transfer-io/src/main/resources/log4j2.xml

@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出 monitorInterval 
+	: Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。 注:本配置文件的目标是将不同级别的日志输出到不同文件,最大2MB一个文件, 
+	文件数据达到最大值时,旧数据会被压缩并放进指定文件夹 -->
+<Configuration status="WARN" monitorInterval="30">
+    <Properties>
+        <!-- 配置日志文件输出目录,此配置将日志输出到目录下的指定文件夹,防止目录遍历,末级文件夹必须为logs -->
+        <Property name="LOG.PATH">.logs/${project.artifactId}</Property>
+        <!-- 控制台输出日志级别 -->
+        <Property name="LOG.LEVEL.CONSOLE.PRINT">warn</Property>
+        <Property name="LOG.LEVEL.CONSOLE.ERROR">error</Property>
+        <!-- 日志输出格式 -->
+        <Property name="PROJECT.NAME">${project.artifactId}</Property>
+        <Property name="PID">????</Property>
+        <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
+        <Property name="LOG_LEVEL_PATTERN">%5p</Property>
+        <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
+        <Property name="CONSOLE_LOG_PATTERN_COLOR">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}}
+            %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint}
+            %clr{%-c{4}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}
+        </Property>
+        <Property name="CONSOLE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%15.15t]
+            %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}
+        </Property>
+        <Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t]
+            %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}
+        </Property>
+    </Properties>
+
+    <Appenders>
+
+        <!-- 优先级从高到低分别是 OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
+        <!-- 单词解释: Match:匹配 DENY:拒绝 Mismatch:不匹配 ACCEPT:接受 -->
+        <!-- DENY,日志将立即被抛弃不再经过其他过滤器; NEUTRAL,有序列表里的下个过滤器过接着处理日志; ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
+        <!--输出日志的格式 %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间 %p : 日志输出格式 %c : logger的名称
+            %m : 日志内容,即 logger.info("message") %n : 换行符 %C : Java类名 %L : 日志输出所在行数 %M
+            : 日志输出所在方法名 -->
+
+        <!--这个输出控制台的配置,这里输出除了warn和error级别的信息到System.out -->
+        <Console name="console_out_appender" target="SYSTEM_OUT" follow="true">
+            <!-- 输出日志的格式 -->
+            <PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN_COLOR}"/>
+            <Filters>
+                <!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
+                <ThresholdFilter level="${LOG.LEVEL.CONSOLE.PRINT}" onMatch="deny" onMismatch="neutral"/>
+                <!-- 控制台拒绝包含 (Preparing:|Parameters:|Total:|Row:) 内容 -->
+                <RegexFilter regex=".*(Preparing:|Parameters:|Total:|Row:).*" onMatch="deny" onMismatch="neutral"/>
+            </Filters>
+        </Console>
+        <!--这个输出控制台的配置,这里输出warn和error级别的信息到System.err,在eclipse控制台上看到的是红色文字 -->
+        <Console name="console_err_appender" target="system_err">
+            <!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
+            <ThresholdFilter level="${LOG.LEVEL.CONSOLE.ERROR}"
+                             onMatch="accept" onMismatch="deny"/>
+            <!-- 输出日志的格式 -->
+            <PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN_COLOR}"/>
+        </Console>
+
+        <!-- TRACE级别日志 -->
+        <!-- 设置日志格式并配置日志压缩格式,压缩文件独立放在一个文件夹内, 日期格式不能为冒号,否则无法生成,因为文件名不允许有冒号,此appender只输出trace级别的数据到trace.log -->
+        <RollingRandomAccessFile name="trace_appender"
+                                 immediateFlush="true"
+                                 fileName="${LOG.PATH}/${PROJECT.NAME}-trace.log"
+                                 filePattern="${LOG.PATH}/${PROJECT.NAME}/trace/${PROJECT.NAME}-trace - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
+            <PatternLayout>
+                <pattern>${sys:FILE_LOG_PATTERN}</pattern>
+            </PatternLayout>
+            <Policies>
+                <!-- 每个日志文件最大2MB -->
+                <SizeBasedTriggeringPolicy size="2MB"/>
+            </Policies>
+            <Filters>
+                <!-- 此Filter意思是,只输出debug级别的数据 -->
+                <!-- DENY,日志将立即被抛弃不再经过其他过滤器; NEUTRAL,有序列表里的下个过滤器过接着处理日志; ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
+                <ThresholdFilter level="debug" onMatch="deny"
+                                 onMismatch="neutral"/>
+                <ThresholdFilter level="trace" onMatch="accept"
+                                 onMismatch="deny"/>
+            </Filters>
+        </RollingRandomAccessFile>
+
+        <!-- DEBUG级别日志 -->
+        <!-- 设置日志格式并配置日志压缩格式,压缩文件独立放在一个文件夹内, 日期格式不能为冒号,否则无法生成,因为文件名不允许有冒号,此appender只输出debug级别的数据到debug.log -->
+        <RollingRandomAccessFile name="debug_appender"
+                                 immediateFlush="true"
+                                 fileName="${LOG.PATH}/${PROJECT.NAME}-debug.log"
+                                 filePattern="${LOG.PATH}/${PROJECT.NAME}/debug/${PROJECT.NAME}-debug - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
+            <PatternLayout>
+                <pattern>${sys:FILE_LOG_PATTERN}</pattern>
+            </PatternLayout>
+            <Policies>
+                <!-- 每个日志文件最大2MB -->
+                <SizeBasedTriggeringPolicy size="2MB"/>
+
+                <!-- 如果启用此配置,则日志会按文件名生成新压缩文件, 即如果filePattern配置的日期格式为 %d{yyyy-MM-dd HH}
+                    ,则每小时生成一个压缩文件, 如果filePattern配置的日期格式为 %d{yyyy-MM-dd} ,则天生成一个压缩文件 -->
+                <!--<TimeBasedTriggeringPolicy interval="1" modulate="true" /> -->
+            </Policies>
+            <Filters>
+                <!-- 此Filter意思是,只输出debug级别的数据 -->
+                <!-- DENY,日志将立即被抛弃不再经过其他过滤器; NEUTRAL,有序列表里的下个过滤器过接着处理日志; ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
+                <ThresholdFilter level="info" onMatch="deny"
+                                 onMismatch="neutral"/>
+                <ThresholdFilter level="debug" onMatch="accept"
+                                 onMismatch="deny"/>
+            </Filters>
+        </RollingRandomAccessFile>
+
+        <!-- INFO级别日志 -->
+        <RollingRandomAccessFile name="info_appender"
+                                 immediateFlush="true" fileName="${LOG.PATH}/${PROJECT.NAME}-info.log"
+                                 filePattern="${LOG.PATH}/${PROJECT.NAME}/info/${PROJECT.NAME}-info - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
+            <PatternLayout>
+                <pattern>${sys:FILE_LOG_PATTERN}</pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="20MB"/>
+            </Policies>
+            <Filters>
+                <ThresholdFilter level="warn" onMatch="deny"
+                                 onMismatch="neutral"/>
+                <ThresholdFilter level="info" onMatch="accept"
+                                 onMismatch="deny"/>
+            </Filters>
+        </RollingRandomAccessFile>
+
+        <!-- WARN级别日志 -->
+        <RollingRandomAccessFile name="warn_appender"
+                                 immediateFlush="true" fileName="${LOG.PATH}/${PROJECT.NAME}-warn.log"
+                                 filePattern="${LOG.PATH}/${PROJECT.NAME}/warn/${PROJECT.NAME}-warn - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
+            <PatternLayout>
+                <pattern>${sys:FILE_LOG_PATTERN}</pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="10MB"/>
+            </Policies>
+            <Filters>
+                <ThresholdFilter level="error" onMatch="deny"
+                                 onMismatch="neutral"/>
+                <ThresholdFilter level="warn" onMatch="accept"
+                                 onMismatch="deny"/>
+            </Filters>
+        </RollingRandomAccessFile>
+
+        <!-- ERROR级别日志 -->
+        <RollingRandomAccessFile name="error_appender"
+                                 immediateFlush="true"
+                                 fileName="${LOG.PATH}/${PROJECT.NAME}-error.log"
+                                 filePattern="${LOG.PATH}/${PROJECT.NAME}/error/${PROJECT.NAME}-error - %d{yyyy-MM-dd HH_mm_ss}.log.gz">
+            <PatternLayout>
+                <pattern>${sys:FILE_LOG_PATTERN}</pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="2MB"/>
+            </Policies>
+            <Filters>
+                <ThresholdFilter level="error" onMatch="accept"
+                                 onMismatch="deny"/>
+            </Filters>
+        </RollingRandomAccessFile>
+
+    </Appenders>
+
+    <Loggers>
+        <!-- 配置日志的根节点 -->
+        <Root level="ALL">
+            <AppenderRef ref="console_out_appender"/>
+            <AppenderRef ref="console_err_appender"/>
+            <AppenderRef ref="trace_appender"/>
+            <AppenderRef ref="debug_appender"/>
+            <AppenderRef ref="info_appender"/>
+            <AppenderRef ref="warn_appender"/>
+            <AppenderRef ref="error_appender"/>
+        </Root>
+
+        <!-- 禁用类路径打印 -->
+        <Logger name="org.springframework.boot.context.logging.ClasspathLoggingApplicationListener" level="off"/>
+        <!-- 关闭Mybatis的Mapper 解析日志 -->
+        <Logger name="org.apache.ibatis.binding.MapperRegistry" level="warn"/>
+        <Logger name="org.mybatis.spring.mapper.MapperScannerConfigurer" level="warn"/>
+
+        <!-- 第三方日志系统 -->
+        <Logger name="org.springframework.core" level="info"/>
+        <Logger name="org.springframework.beans" level="info"/>
+        <Logger name="org.springframework.context" level="info"/>
+        <Logger name="org.springframework.web" level="info"/>
+        <Logger name="org.jboss.netty" level="warn"/>
+        <Logger name="org.apache.http" level="warn"/>
+        <Logger name="com.sgcc" level="debug"/>
+        <Logger name="com.sgcc.isc" level="debug"/>
+        <Logger name="org.jasig" level="debug"/>
+        <Logger name="org.hibernate" level="error"/>
+        <Logger name="org.springframework.boot.autoconfigure" level="warn"/>
+        <Logger name="org.springframework.boot.context.config" level="warn"/>
+        <Logger name="org.springframework.cloud" level="warn"/>
+
+        <Logger name="org.activiti.engine.impl.db" level="DEBUG">
+            <AppenderRef ref="debug_appender"/>
+        </Logger>
+
+        <Logger name="com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder" level="OFF"/>
+
+        <!--屏蔽nacos心跳-->
+        <Logger name="com.alibaba.nacos" level="OFF">
+            <appender-ref ref="error_appender"/>
+        </Logger>
+    </Loggers>
+
+</Configuration>

+ 1 - 0
services/load-transfer-io/src/main/resources/sentinel.properties

@@ -0,0 +1 @@
+csp.sentinel.heartbeat.api.path=/nacos/registry/machine

+ 3 - 3
services/load-transfer-mq/src/main/java/com/hdkj/lt/mq/mapper/fault/mapping/FhzgFaultAnalyzeCalculateDecudeMapper.xml

@@ -69,9 +69,9 @@
     <select id="getLineVoltageByLineId" resultType="com.hdkj.lt.mq.entity.vo.FeederDeviceVO">
         select t.psr_id,t.name,t.feeder_rate_capacity,s.LABEL volt_value
           from dwd_shb_ds_feeder_base t
-          join SYS_DICT_SINGLE s on t.voltage_level=s.VALUE
-          join SYS_DICT_TYPE d on d.TYPE_ID = s.TYPE_ID
-         where d.TYPE_NAME = 'voltage_level_map'
+          join sys_dict_data s on t.voltage_level=s.dict_value
+          join sys_dict_type d on d.dict_type = s.dict_type
+         where d.dict_type = 'voltage_level_map'
            and t.psr_id in
         <foreach collection = 'lineIds' item = 'item' open = '(' separator = ',' close = ')'>#{item}</foreach>
     </select>

+ 4 - 4
services/load-transfer-mq/src/main/java/com/hdkj/lt/mq/mapper/plan/mapping/FhzgPlanAnalyzeCalculateDecudeMapper.xml

@@ -69,9 +69,9 @@
     <select id="getLineVoltageByLineId" resultType="com.hdkj.lt.mq.entity.vo.FeederDeviceVO">
         select t.psr_id,t.name,t.feeder_rate_capacity,s.LABEL volt_value
           from dwd_shb_ds_feeder_base t
-          join SYS_DICT_SINGLE s on t.voltage_level=s.VALUE
-          join SYS_DICT_TYPE d on d.TYPE_ID = s.TYPE_ID
-         where d.TYPE_NAME = 'voltage_level_map'
+          join sys_dict_data s on t.voltage_level=s.dict_value
+          join sys_dict_type d on d.dict_type = s.dict_type
+         where d.dict_type = 'voltage_level_map'
            and t.psr_id in
         <foreach collection = 'lineIds' item = 'item' open = '(' separator = ',' close = ')'>#{item}</foreach>
     </select>
@@ -83,7 +83,7 @@
     </update>
 
     <update id="updateSwitchingSequenceIsConnect">
-        update fhzg_plan_transfer_scheme_switching_sequence a  set switch_type = "1"
+        update fhzg_plan_transfer_scheme_switching_sequence a  set switch_type = '1'
         where exists (select 1 from fhzg_plan_transfer_scheme_path_detail b where b.switch_id = a.switch_id and b.scheme_id = a.scheme_id)
           and a.scheme_id in (select id from fhzg_plan_transfer_scheme where plan_id = #{planId})
     </update>

+ 4 - 4
services/load-transfer-mq/src/main/java/com/hdkj/lt/mq/mapper/voltageLimitViolation/mapping/FhzgInfoLimitTransferSchemeSwitchingSequenceMapper.xml

@@ -102,11 +102,11 @@
         </foreach>
     </select>
     <select id="getLineVoltageByLineId" resultType="com.hdkj.lt.mq.entity.vo.FeederDeviceVO">
-        select t.psr_id,t.name,t.feeder_rate_capacity,s.LABEL volt_value
+        select t.psr_id,t.name,t.feeder_rate_capacity,s.dict_label volt_value
         from dwd_shb_ds_feeder_base t
-        join SYS_DICT_SINGLE s on t.voltage_level=s.VALUE
-        join SYS_DICT_TYPE d on d.TYPE_ID = s.TYPE_ID
-        where d.TYPE_NAME = 'voltage_level_map'
+        join sys_dict_data s on t.voltage_level=s.dict_value
+        join sys_dict_type d on d.dict_type = s.dict_type
+        where d.dict_type = 'voltage_level_map'
         and t.psr_id in
         <foreach collection='lineIds' item='item' open='(' separator=',' close=')'>#{item}</foreach>
     </select>

+ 0 - 2
services/load-transfer-si/src/main/java/com/hdkj/lt/si/LoadTransferSIApplication.java

@@ -5,7 +5,6 @@ import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 
@@ -20,7 +19,6 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
 @SpringBootApplication(scanBasePackages = {SystemGlobalConstant.HUSSAR_BASE_PACKAGE, SystemGlobalConstant.BIZMS_BASE_PACKAGE})
 @MapperScan(basePackages = {SystemGlobalConstant.HUSSAR_DAO_PACKAGE, SystemGlobalConstant.BIZMS_DAO_PACKAGE})
 @EnableCaching
-@EnableCircuitBreaker
 public class LoadTransferSIApplication {
 
     public static void main(String[] args) {

+ 3 - 3
services/load-transfer-si/src/main/java/com/hdkj/lt/si/dao/mapping/CityFeederTopoMapper.xml

@@ -5,10 +5,10 @@
 
     <select id="getCityCodeByLine" resultType="com.hdkj.lt.modle.dto.svg.CityFeederInfo">
         select
-        ifnull(s.LABEL,f.city) city,f.psr_id lineId
+        ifnull(s.dict_label,f.city) city,f.psr_id lineId
         from dwd_shb_ds_feeder_base f
-        left join SYS_DICT_SINGLE s on f.city = s.VALUE
-        left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+        left join sys_dict_data s on f.city = s.dict_value
+        left join sys_dict_type t on s. = t.dict_type and t.dict_type = 'custom_storage'
         where f.psr_id in
         <foreach item="item" collection="lineIds" open="(" separator="," close=")">
             #{item, jdbcType=BIGINT}

+ 18 - 18
services/load-transfer-si/src/main/java/com/hdkj/lt/si/dao/mapping/DistMappingFileMapper.xml

@@ -62,13 +62,13 @@
     </delete>
 
     <select id="getDeviceInfoById" resultType="com.hdkj.lt.modle.vo.svg.FeederBaseVO">
-        select f.psr_id, f.name, ifnull(s.LABEL,f.city) city, ifnull(s.BAK_2,f.city_name) city_name
+        select f.psr_id, f.name, ifnull(s.dict_label,f.city) city, ifnull(s.,f.city_name) city_name
         from dwd_shb_ds_feeder_base f
         inner join (select a.feeder, a.feeder_name from t_feeder_topo a
             join t_feeder_topo b on a.psr_id=b.psr_id where b.normal_open='true' and b.feeder=#{feederId}
             union select psr_id, `name` from dwd_shb_ds_feeder_base t where psr_id = #{feederId}
-        ) p on f.psr_id = p.feeder left join SYS_DICT_SINGLE s on f.city = s.VALUE
-        left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+        ) p on f.psr_id = p.feeder left join sys_dict_data s on f.city = s.dict_value
+        left join sys_dict_type t on s.dict_type = t.dict_type and t.dict_type = 'custom_storage'
     </select>
 
     <select id="getSwitchInfoById" resultType="com.hdkj.lt.modle.dto.svg.AppendSwitchDTO">
@@ -118,37 +118,37 @@
         <choose>
             <!-- objType:5-调优事件,6-调优方案 -->
             <when test='objType == "5"'>
-                SELECT f.psr_id, f.name, ifnull(s.LABEL,f.city) city, ifnull(s.BAK_2,f.city_name) city_name
+                SELECT f.psr_id, f.name, ifnull(s.dict_label,f.city) city, ifnull(s.bak2,f.city_name) city_name
                 from dwd_shb_ds_feeder_base f
                 join fhzg_operation_abnormality_line_loadfactor_loss x on f.psr_id = x.psr_id
-                left join SYS_DICT_SINGLE s on f.city = s.VALUE
-                left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+                left join sys_dict_data s on f.city = s.dict_value
+                left join sys_dict_type t on s.dict_type = t.dict_type and t.dict_type = 'custom_storage'
                 where x.oa_id = #{objId}
             </when>
             <when test='objType == "7"'>
-                SELECT distinct f.psr_id, f.name, ifnull(s.LABEL,f.city) city, ifnull(s.BAK_2,f.city_name) city_name
+                SELECT distinct f.psr_id, f.name, ifnull(s.dict_label,f.city) city, ifnull(s.bak2,f.city_name) city_name
                 from dwd_shb_ds_feeder_base f
                 join fhzg_voltage_limit_violation_transfer_scheme_detail x on f.psr_id = x.line_id
-                left join SYS_DICT_SINGLE s on f.city = s.VALUE
-                left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+                left join sys_dict_data s on f.city = s.dict_value
+                left join sys_dict_type t on s.dict_type = t.dict_type and t.dict_type = 'custom_storage'
                 where x.limit_id = #{objId} and (x.line_tag = 1 or x.line_tag = 0)
             </when>
             <when test='objType == "8"'>
-                SELECT distinct f.psr_id, f.name, ifnull(s.LABEL,f.city) city, ifnull(s.BAK_2,f.city_name) city_name
+                SELECT distinct f.psr_id, f.name, ifnull(s.dict_label,f.city) city, ifnull(s.bak2,f.city_name) city_name
                 from dwd_shb_ds_feeder_base f
                 join fhzg_voltage_limit_violation_transfer_scheme_detail x on f.psr_id = x.line_id
                 join fhzg_info_limit_transfer_scheme y on x.limit_id = y.limit_id
-                left join SYS_DICT_SINGLE s on f.city = s.VALUE
-                left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+                left join sys_dict_data s on f.city = s.dict_value
+                left join sys_dict_type t on s.dict_type = t.dict_type and t.dict_type = 'custom_storage'
                 where y.id = #{objId} and (x.line_tag = 1 or x.line_tag = 0)
             </when>
             <otherwise>
-                SELECT f.psr_id, f.name, ifnull(s.LABEL,f.city) city, ifnull(s.BAK_2,f.city_name) city_name
+                SELECT f.psr_id, f.name, ifnull(s.dict_label,f.city) city, ifnull(s.bak2,f.city_name) city_name
                 from dwd_shb_ds_feeder_base f
                 join fhzg_operation_abnormality_line_loadfactor_loss x on f.psr_id = x.psr_id
                 join fhzg_operation_abnormality_transfer_scheme y on x.oa_id = y.oa_id
-                left join SYS_DICT_SINGLE s on f.city = s.VALUE
-                left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+                left join sys_dict_data s on f.city = s.dict_value
+                left join sys_dict_type t on s.dict_type = t.dict_type and t.dict_type = 'custom_storage'
                 where y.id = #{objId}
             </otherwise>
         </choose>
@@ -203,11 +203,11 @@
         with station_feeder as (
             select f.start_station station, f.start_station_name station_name, f.ctime,
                    f.psr_id feeder, f.`name` feeder_name, tft.psr_id, tft.name psr_name,
-                   ifnull(s.LABEL,f.city) city, ifnull(s.BAK_2,f.city_name) city_name
+                   ifnull(s.dict_label,f.city) city, ifnull(s.bak2,f.city_name) city_name
             from dwd_shb_ds_feeder_base f left join (select distinct feeder,psr_id,`name`
                 from t_feeder_topo where normal_open = 'true') tft on f.psr_id = tft.feeder
-            left join SYS_DICT_SINGLE s on f.city = s.VALUE
-            left join SYS_DICT_TYPE t on s.TYPE_ID = t.TYPE_ID and t.TYPE_NAME = 'custom_storage'
+                left join sys_dict_data s on f.city = s.dict_value
+                left join sys_dict_type t on s.dict_type = t.dict_type and t.dict_type = 'custom_storage'
             where f.psr_state = '20' and f.pub_priv_flag = '0'
             and f.start_station in <foreach collection="stationIds" open="(" item="station" separator="," close=")">#{station}</foreach>
         ) select station,station_name,feeder,feeder_name,psr_id,psr_name,switch_state,city,city_name,station_type

+ 1 - 0
services/pom.xml

@@ -17,6 +17,7 @@
         <module>load-transfer-bf</module>
         <module>load-transfer-mq</module>
         <module>load-transfer-si</module>
+        <module>load-transfer-io</module>
     </modules>
 
     <dependencies>