فهرست منبع

接线组线路列表,计算推演平台运行优化方案

Sunlit 2 هفته پیش
والد
کامیت
f0619a8da1
15فایلهای تغییر یافته به همراه365 افزوده شده و 52 حذف شده
  1. 34 0
      api/load-transfer-bf-api/src/main/java/com/hdkj/fhzg/optimization/response/FeederLineVO.java
  2. 10 7
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/ISimulationPlatformApiClient.java
  3. 13 5
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/fallback/SimulationPlatformApiClientFallBack.java
  4. 21 0
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/EacFeederDTO.java
  5. 29 0
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/OperationModeStartDTO.java
  6. 19 0
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/QueryOperationModeDTO.java
  7. 20 0
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/SwitchFeederDTO.java
  8. 3 0
      api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/po/FhzgReconResult.java
  9. 34 0
      services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/application/FeederGroupApplication.java
  10. 14 0
      services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/controller/optimization/FeederGroupController.java
  11. 20 7
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/controller/simulation/SimulationController.java
  12. 8 0
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/recon/ReconResultService.java
  13. 34 23
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/recon/impl/ReconResultServiceImpl.java
  14. 15 5
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/simulation/ISimulationService.java
  15. 91 5
      services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/simulation/impl/SimulationServiceImpl.java

+ 34 - 0
api/load-transfer-bf-api/src/main/java/com/hdkj/fhzg/optimization/response/FeederLineVO.java

@@ -0,0 +1,34 @@
+package com.hdkj.fhzg.optimization.response;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author rj
+ * @date 2026/7/25
+ * @description 接线组线路信息
+ */
+@Data
+@Accessors(chain = true)
+public class FeederLineVO {
+
+    /**
+     * 线路ID
+     */
+    private String feederId;
+
+    /**
+     * 线路名称
+     */
+    private String feederName;
+
+    /**
+     * 出线开关ID
+     */
+    private String startSwitchId;
+
+    /**
+     * 出线开关名称
+     */
+    private String startSwitchName;
+}

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

@@ -2,15 +2,11 @@ package com.hdkj.lt.feign;
 
 import com.hdkj.lt.base.constants.SystemGlobalConstant;
 import com.hdkj.lt.feign.fallback.SimulationPlatformApiClientFallBack;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelRequest;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelResponse;
-import com.hdkj.lt.modle.dto.simulation.FaultTransferSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.OperationSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.PlanTransferSchemeDTO;
+import com.hdkj.lt.modle.dto.simulation.*;
+import com.hdkj.hussar.ApiResponse;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.*;
 
 /**
  * @author rj
@@ -35,4 +31,11 @@ public interface ISimulationPlatformApiClient {
     @PostMapping("/getElectricalModel")
     String getElectricalModel(@RequestBody ElectricalModelRequest request);
 
+    @ApiOperation(value = "执行调优算法计算,启动网络重构")
+    @PostMapping("/operationMode/startOperationCalTask")
+    ApiResponse<String> startOperationCalTask(@RequestBody OperationModeStartDTO dto);
+
+    @ApiOperation(value = "查询调优计算结果")
+    @GetMapping("/operationMode/queryOperationResult")
+    ApiResponse<QueryOperationModeDTO> queryOperationResult(@RequestParam("id") String taskId);
 }

+ 13 - 5
api/load-transfer-si-api/src/main/java/com/hdkj/lt/feign/fallback/SimulationPlatformApiClientFallBack.java

@@ -1,11 +1,7 @@
 package com.hdkj.lt.feign.fallback;
 
 import com.hdkj.lt.feign.ISimulationPlatformApiClient;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelRequest;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelResponse;
-import com.hdkj.lt.modle.dto.simulation.FaultTransferSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.OperationSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.PlanTransferSchemeDTO;
+import com.hdkj.lt.modle.dto.simulation.*;
 import com.hdkj.hussar.ApiResponse;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.cloud.openfeign.FallbackFactory;
@@ -43,6 +39,18 @@ public class SimulationPlatformApiClientFallBack implements FallbackFactory<ISim
                 log.error("配网电气模型接口-远程调用服务异常, 参数:{},异常:{}", request, cause.getMessage());
                 return null;
             }
+
+            @Override
+            public ApiResponse<String> startOperationCalTask(OperationModeStartDTO dto) {
+                log.error("执行调优算法计算-远程调用服务异常, 参数:{},异常:{}", dto, cause.getMessage());
+                return ApiResponse.fail("执行调优算法计算服务异常");
+            }
+
+            @Override
+            public ApiResponse<QueryOperationModeDTO> queryOperationResult(String taskId) {
+                log.error("查询调优计算结果-远程调用服务异常, taskId:{},异常:{}", taskId, cause.getMessage());
+                return ApiResponse.fail("查询调优计算结果服务异常");
+            }
         };
     }
 }

+ 21 - 0
api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/EacFeederDTO.java

@@ -0,0 +1,21 @@
+package com.hdkj.lt.modle.dto.simulation;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 单条线路参数.
+ */
+@Data
+@NoArgsConstructor
+public class EacFeederDTO {
+
+    /** 线路名称 */
+    private String name;
+
+    /** 组织ID */
+    private String orgId;
+
+    /** 线路资源ID */
+    private String psrId;
+}

+ 29 - 0
api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/OperationModeStartDTO.java

@@ -0,0 +1,29 @@
+package com.hdkj.lt.modle.dto.simulation;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 执行调优算法计算 — 请求参数.
+ */
+@Data
+@NoArgsConstructor
+public class OperationModeStartDTO {
+
+    /** 线路列表(必填) */
+    private List<EacFeederDTO> feeders;
+
+    /** 请求ID(幂等去重) */
+    private String requestId;
+
+    /** 量测断面时间,格式 yyyy-MM-dd HH:mm:ss */
+    private String sectionTime;
+
+    /** 不可操作的开关ID列表 */
+    private List<String> switchOutControl;
+
+    /** 联络开关线路关系 */
+    private List<SwitchFeederDTO> switchFeeders;
+}

+ 19 - 0
api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/QueryOperationModeDTO.java

@@ -0,0 +1,19 @@
+package com.hdkj.lt.modle.dto.simulation;
+
+import com.hdkj.lt.modle.dto.recon.RawResultDTO;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 调优任务结果承载对象.
+ */
+@Data
+@NoArgsConstructor
+public class QueryOperationModeDTO {
+
+    /** 调优任务ID */
+    private String id;
+
+    /** 调优计算结果详情,结构与 DNR 重构结果一致 */
+    private RawResultDTO result;
+}

+ 20 - 0
api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/dto/simulation/SwitchFeederDTO.java

@@ -0,0 +1,20 @@
+package com.hdkj.lt.modle.dto.simulation;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 联络开关线路关系.
+ */
+@Data
+@NoArgsConstructor
+public class SwitchFeederDTO {
+
+    /** 开关设备的psrId */
+    private String switchPsrId;
+
+    /** 线路列表 */
+    private List<EacFeederDTO> feeders;
+}

+ 3 - 0
api/load-transfer-si-api/src/main/java/com/hdkj/lt/modle/po/FhzgReconResult.java

@@ -62,6 +62,9 @@ public class FhzgReconResult {
     /** 快照时间(运行时间) */
     private LocalDateTime snapshotTime;
 
+    /** 原始结果JSON(raw_result节点) */
+    private String rawResult;
+
     /** 入库时间 */
     private LocalDateTime createTime;
 }

+ 34 - 0
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/application/FeederGroupApplication.java

@@ -3,6 +3,7 @@ package com.hdkj.lt.bf.application;
 import cn.hutool.core.map.MapUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.hdkj.fhzg.optimization.response.FeederGroupTreeNode;
+import com.hdkj.fhzg.optimization.response.FeederLineVO;
 import com.hdkj.lt.base.constants.DictConstants;
 import com.hdkj.lt.bf.constants.OptimizationConstants;
 import com.hdkj.lt.bf.entity.TJxz;
@@ -11,12 +12,14 @@ import com.hdkj.lt.bf.entity.convert.EntityToVOConvertor;
 import com.hdkj.lt.bf.entity.vo.BreakerAreaVO;
 import com.hdkj.lt.bf.entity.vo.FeederDeviceVO;
 import com.hdkj.lt.bf.entity.vo.XlRelVO;
+import com.hdkj.lt.bf.mapper.FeederTopoMapper;
 import com.hdkj.lt.bf.mapper.FhzgGridOperationAbnormalityMapper;
 import com.hdkj.lt.bf.mapper.TJxzXlMapper;
 import com.hdkj.lt.bf.service.TJxzService;
 import com.hdkj.lt.bf.service.TJxzXlService;
 import com.hdkj.lt.bf.service.impl.XlRelServiceImpl;
 import com.hdkj.lt.core.bizms.modle.po.DwdShbDsFeederBase;
+import com.hdkj.lt.core.bizms.modle.po.FeederTopo;
 import com.hdkj.lt.core.bizms.modle.po.XlRel;
 import com.hdkj.lt.core.sys.dao.FhzgDistMappingFileMapper;
 import com.hdkj.lt.core.sys.model.dto.FhzgDistMappingFileDTO;
@@ -52,6 +55,7 @@ public class FeederGroupApplication {
     private final RedisRepository redisRepository;
     private final DwdShbDsFeederBaseService dwdShbDsFeederBaseService;
     private final FhzgGridOperationAbnormalityMapper fhzgGridOperationAbnormalityMapper;
+    private final FeederTopoMapper feederTopoMapper;
 
 
     public List<FeederGroupTreeNode> getFeederGroupTree() {
@@ -205,4 +209,34 @@ public class FeederGroupApplication {
         }
         return Lists.newArrayList();
     }
+
+    /**
+     * 根据接线组ID获取线路列表
+     * @param jxzId 接线组ID
+     * @return 线路列表
+     */
+    public List<FeederLineVO> getFeederLinesByJxzId(String jxzId) {
+        List<TJxzXl> jxzXlList = jxzXlService.list(new LambdaQueryWrapper<TJxzXl>().eq(TJxzXl::getJxzId, jxzId));
+        if (CollectionUtils.isEmpty(jxzXlList)) {
+            return Lists.newArrayList();
+        }
+        List<String> xlIds = jxzXlList.stream().map(TJxzXl::getXlid).collect(Collectors.toList());
+        List<DwdShbDsFeederBase> feederList = dwdShbDsFeederBaseService.list(new LambdaQueryWrapper<DwdShbDsFeederBase>().in(DwdShbDsFeederBase::getPsrId, xlIds));
+        // 从topo表批量查询每个线路的出线开关
+        List<FeederTopo> topoList = feederTopoMapper.selectList(new LambdaQueryWrapper<FeederTopo>()
+                .in(FeederTopo::getFeeder, xlIds)
+                .eq(FeederTopo::getIsStartKg, "1"));
+        Map<String, FeederTopo> topoMap = topoList.stream()
+                .collect(Collectors.toMap(FeederTopo::getFeeder, t -> t, (a, b) -> a));
+        return feederList.stream()
+                .map(f -> {
+                    FeederLineVO vo = new FeederLineVO().setFeederId(f.getPsrId()).setFeederName(f.getName());
+                    FeederTopo topo = topoMap.get(f.getPsrId());
+                    if (topo != null) {
+                        vo.setStartSwitchId(topo.getPsrId()).setStartSwitchName(topo.getName());
+                    }
+                    return vo;
+                })
+                .collect(Collectors.toList());
+    }
 }

+ 14 - 0
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/controller/optimization/FeederGroupController.java

@@ -2,6 +2,7 @@ package com.hdkj.lt.bf.controller.optimization;
 
 import com.hdkj.fhzg.optimization.request.FeederRequest;
 import com.hdkj.fhzg.optimization.response.FeederGroupTreeNode;
+import com.hdkj.fhzg.optimization.response.FeederLineVO;
 import com.hdkj.hussar.ApiResponse;
 import com.hdkj.lt.bf.application.FeederGroupApplication;
 import com.hdkj.lt.bf.entity.vo.BreakerAreaVO;
@@ -67,5 +68,18 @@ public class FeederGroupController {
         return ApiResponse.success(FeederGroupApplication.getOverviewSwitchByFeederGroupId(request.getFeederId()));
     }
 
+    /**
+     * 根据接线组ID获取线路列表
+     * @param request 接线组ID
+     * @return 线路列表(线路ID + 线路名称)
+     */
+    @PostMapping("/getFeederLinesByJxzId")
+    @ApiOperation(value = "根据接线组ID获取线路列表")
+    public ApiResponse<List<FeederLineVO>> getFeederLinesByJxzId(@RequestBody FeederRequest request) {
+        boolean assertFlag = ObjectUtils.isNotEmpty(request) && StringUtils.isNotEmpty(request.getFeederId());
+        Assert.isTrue(assertFlag, "接线组ID不允许为空!");
+        return ApiResponse.success(FeederGroupApplication.getFeederLinesByJxzId(request.getFeederId()));
+    }
+
 
 }

+ 20 - 7
services/load-transfer-si/src/main/java/com/hdkj/lt/si/controller/simulation/SimulationController.java

@@ -2,17 +2,12 @@ package com.hdkj.lt.si.controller.simulation;
 
 import com.alibaba.fastjson.JSONObject;
 import com.hdkj.lt.feign.ISimulationPlatformApiClient;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelRequest;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelResponse;
-import com.hdkj.lt.modle.dto.simulation.FaultTransferSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.OperationSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.PlanTransferSchemeDTO;
+import com.hdkj.lt.modle.dto.simulation.*;
 import com.hdkj.lt.si.service.simulation.ISimulationService;
 import com.hdkj.hussar.ApiResponse;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 /**
  * @author rj
@@ -48,4 +43,22 @@ public class SimulationController implements ISimulationPlatformApiClient {
     public String getElectricalModel(ElectricalModelRequest request) {
         return simulationService.getElectricalModel(request);
     }
+
+    /**
+     * 执行调优算法计算,启动网络重构计算任务.
+     */
+    @Override
+    @PostMapping("/operationMode/startOperationCalTask")
+    public ApiResponse<String> startOperationCalTask(@RequestBody OperationModeStartDTO dto) {
+        return simulationService.startOperationCalTask(dto);
+    }
+
+    /**
+     * 查询调优结果.
+     */
+    @Override
+    @GetMapping("/operationMode/queryOperationResult")
+    public ApiResponse<QueryOperationModeDTO> queryOperationResult(@RequestParam("id") String taskId) {
+        return simulationService.queryOperationResult(taskId);
+    }
 }

+ 8 - 0
services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/recon/ReconResultService.java

@@ -17,4 +17,12 @@ public interface ReconResultService {
      * @param params county_sid,county_name,problem_feeder_ids
      */
     ReconSaveResultVO saveReconResult(String eventId, Map<String, Object> params);
+
+    /**
+     * 反序列化 raw_result JSON 并入库(主表 + 7子表),单事务.
+     * @param rawResultJson 算法响应中 raw_result 节点的原始JSON字符串
+     * @param eventId 事件ID
+     * @return 入库结果概要
+     */
+    ReconSaveResultVO parseAndSaveReconResult(String rawResultJson, String eventId);
 }

+ 34 - 23
services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/recon/impl/ReconResultServiceImpl.java

@@ -1,7 +1,6 @@
 package com.hdkj.lt.si.service.recon.impl;
 
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -17,16 +16,13 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.Charsets;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.ClassPathResource;
 import org.springframework.http.*;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.StreamUtils;
 import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.Resource;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
 import java.time.OffsetDateTime;
 import java.time.format.DateTimeFormatter;
@@ -68,18 +64,13 @@ public class ReconResultServiceImpl implements ReconResultService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public ReconSaveResultVO saveReconResult(String eventId, Map<String, Object> params) {
-        // 1. 构造请求参数
-//        Map<String, Object> params = new HashMap<>();
-//        params.put("county_sid", "honghu");
-//        params.put("county_name", "honghu");
-//        params.put("problem_feeder_ids", Collections.singletonList("15DKX-20690"));
+        // 1. 调用远程重构接口
         String requestUrl = requestUri.concat(reconUri);
         HttpHeaders headers = new HttpHeaders();
         headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
         headers.set(HttpHeaders.ACCEPT_CHARSET, Charsets.UTF_8.toString());
         HttpEntity<Object> httpEntity = new HttpEntity<>(params, headers);
         String str;
-        RawResultDTO dto;
         try {
             ResponseEntity<Object> restRespEntity = restTemplate.postForEntity(requestUrl, httpEntity, Object.class);
             if (!restRespEntity.getStatusCode().is2xxSuccessful() || Objects.isNull(restRespEntity.getBody())) {
@@ -88,51 +79,70 @@ public class ReconResultServiceImpl implements ReconResultService {
                 log.error(errorMsg);
                 ExceptionCast.cast(errorMsg);
             }
-
             Object body = restRespEntity.getBody();
             str = JSON.toJSONString(body);
-            log.info("调用重构方案接口成功, requestUrl: {}, result: {}",
-                    requestUrl, str);
-        // 2. 解析返回的JSON数据
-//            str = StreamUtils.copyToString(new ClassPathResource("1.txt").getInputStream(), StandardCharsets.UTF_8);
+            log.info("调用重构方案接口成功, requestUrl: {}, result: {}", requestUrl, str);
+        } catch (Exception e) {
+            throw new RuntimeException("调用重构方案接口异常", e);
+        }
 
+        // 2. 提取 raw_result 节点JSON字符串
+        String rawResultJson;
+        try {
             JsonNode root = OM.readTree(str);
             JsonNode rawNode = root.get("raw_result");
             if (rawNode == null || rawNode.isNull()) {
                 throw new RuntimeException("算法响应缺少 raw_result 节点");
             }
-            dto = OM.treeToValue(rawNode, RawResultDTO.class);
+            rawResultJson = OM.writeValueAsString(rawNode);
         } catch (IOException e) {
             throw new RuntimeException("解析算法响应 raw_result 失败", e);
         }
+
+        // 3. 反序列化并入库
+        return parseAndSaveReconResult(rawResultJson, eventId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public ReconSaveResultVO parseAndSaveReconResult(String rawResultJson, String eventId) {
+        // 1. 反序列化 raw_result JSON -> RawResultDTO
+        RawResultDTO dto;
+        try {
+            dto = OM.readValue(rawResultJson, RawResultDTO.class);
+        } catch (IOException e) {
+            throw new RuntimeException("反序列化 raw_result JSON 失败", e);
+        }
+
         Map<String, Integer> counts = new LinkedHashMap<>();
 
-        // 1. 主表
+        // 2. 主表
         FhzgReconResult main = buildMain(dto);
         main.setEventId(eventId);
+        main.setRawResult(rawResultJson);
         resultMapper.insert(main);
         Long resultId = main.getId();
         counts.put("result", 1);
 
-        // 2. 开关操作(简化版)
+        // 3. 开关操作(简化版)
         if (dto.getSwitchOp() != null) {
             int n = insertSwitchOp(dto.getSwitchOp(), resultId);
             counts.put("switch_op", n);
         }
 
-        // 3. 开关操作序列(详细)
+        // 4. 开关操作序列(详细)
         if (dto.getSwitchSeq() != null) {
             int n = insertSwitchSeq(dto.getSwitchSeq(), resultId);
             counts.put("switch_seq", n);
         }
 
-        // 4. 馈线结果
+        // 5. 馈线结果
         if (dto.getFeederResult() != null) {
             int n = insertFeederResult(dto.getFeederResult(), resultId);
             counts.put("feeder_result", n);
         }
 
-        // 5. 电压结果(汇总+详情)
+        // 6. 电压结果(汇总+详情)
         if (dto.getVolResult() != null) {
             if (dto.getVolResult().getSummary() != null) {
                 volResultMapper.insert(buildVolResult(dto.getVolResult().getSummary(), resultId));
@@ -144,17 +154,18 @@ public class ReconResultServiceImpl implements ReconResultService {
             }
         }
 
-        // 6. 开关状态详情(summary 折叠进主表)
+        // 7. 开关状态详情(summary 折叠进主表)
         if (dto.getSwitchResult() != null && dto.getSwitchResult().getDetails() != null) {
             int n = insertSwitchResultDetail(dto.getSwitchResult().getDetails(), resultId);
             counts.put("switch_result_detail", n);
         }
 
-        // 7. 运行指标
+        // 8. 运行指标
         if (dto.getMetrics() != null) {
             metricsMapper.insert(buildMetrics(dto.getMetrics(), resultId));
             counts.put("metrics", 1);
         }
+
         log.info("重构方案counts:{}", JSON.toJSONString(counts));
         ReconSaveResultVO vo = new ReconSaveResultVO();
         vo.setSuccess(true);

+ 15 - 5
services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/simulation/ISimulationService.java

@@ -1,10 +1,6 @@
 package com.hdkj.lt.si.service.simulation;
 
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelRequest;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelResponse;
-import com.hdkj.lt.modle.dto.simulation.FaultTransferSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.OperationSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.PlanTransferSchemeDTO;
+import com.hdkj.lt.modle.dto.simulation.*;
 import com.hdkj.hussar.ApiResponse;
 
 /**
@@ -25,4 +21,18 @@ public interface ISimulationService {
      * @return 原始JSON字符串
      */
     String getElectricalModel(ElectricalModelRequest request);
+
+    /**
+     * 执行调优算法计算,启动网络重构计算任务.
+     * @param dto 请求参数
+     * @return 任务ID
+     */
+    ApiResponse<String> startOperationCalTask(OperationModeStartDTO dto);
+
+    /**
+     * 查询调优结果.
+     * @param taskId 任务ID
+     * @return 调优计算结果
+     */
+    ApiResponse<QueryOperationModeDTO> queryOperationResult(String taskId);
 }

+ 91 - 5
services/load-transfer-si/src/main/java/com/hdkj/lt/si/service/simulation/impl/SimulationServiceImpl.java

@@ -3,7 +3,10 @@ package com.hdkj.lt.si.service.simulation.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.hdkj.lt.base.constants.ErrorLogConstant;
 import com.hdkj.lt.base.enums.EventTypeEnum;
 import com.hdkj.lt.base.enums.OperationStepEnum;
@@ -16,14 +19,15 @@ import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanPowerCutSwitch;
 import com.hdkj.lt.core.bizms.modle.po.plan.PlanAwaitTransferAreaResultPO;
 import com.hdkj.lt.core.log.exception.ExceptionErrorLogCast;
 import com.hdkj.lt.core.log.model.param.ErrorLogParam;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelRequest;
-import com.hdkj.lt.modle.dto.simulation.ElectricalModelResponse;
-import com.hdkj.lt.modle.dto.simulation.FaultTransferSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.OperationSchemeDTO;
-import com.hdkj.lt.modle.dto.simulation.PlanTransferSchemeDTO;
+import com.hdkj.lt.core.rest.config.HttpClientConfig;
+import com.hdkj.lt.modle.dto.recon.RawResultDTO;
+import com.hdkj.lt.modle.dto.simulation.*;
+import com.hdkj.lt.modle.po.FhzgReconResult;
 import com.hdkj.lt.si.dao.*;
+import com.hdkj.lt.si.service.recon.ReconResultService;
 import com.hdkj.lt.si.service.simulation.ISimulationService;
 import com.hdkj.lt.si.service.simulation.TyptResponseEntity;
+import com.hdkj.hussar.ApiResponse;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -36,7 +40,10 @@ import org.springframework.http.MediaType;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
+import javax.annotation.Resource;
+import java.io.IOException;
 import java.time.LocalDateTime;
+import java.util.UUID;
 
 /**
  * @author rj
@@ -54,15 +61,28 @@ public class SimulationServiceImpl implements ISimulationService {
     private final PlanAwaitTransferAreaResultMapper planAwaitTransferAreaResultMapper;
     private final FaultAwaitTransferAreaResultMapper faultAwaitTransferAreaResultMapper;
     private final FhzgOperationAbnormalityTransferAreaResultMapper operationAbnormalityTransferAreaResultMapper;
+    private final FhzgReconResultMapper fhzgReconResultMapper;
+    private final ReconResultService reconResultService;
     private final String BASE_URL = "http://25.91.83.252:28081";
 
+    private static final ObjectMapper OM = new ObjectMapper();
+
     @Value("${simulation.xToken}")
     private String xToken;
 
+    @Value("${remote.recon.request-uri}")
+    private String reconRequestUri;
+
+    @Value("${remote.recon.recon-uri}")
+    private String reconUri;
+
     @Autowired
     @Qualifier("simpleRestTemplate")
     private RestTemplate simpleRestTemplate;
 
+    @Resource(name = HttpClientConfig.CONN_POOL_REST_TEMPLATE)
+    private RestTemplate connPoolRestTemplate;
+
     @Override
     public String getPlanTransferScheme(PlanTransferSchemeDTO planTransferSchemeDTO) {
         String url = BASE_URL + "/api/power/power-transfer/plan-analysis";
@@ -251,4 +271,70 @@ public class SimulationServiceImpl implements ISimulationService {
         }
     }
 
+    @Override
+    public ApiResponse<String> startOperationCalTask(OperationModeStartDTO dto) {
+        // 1. 生成任务ID
+        String taskId = UUID.randomUUID().toString();
+        log.info("启动重构计算, taskId: {}, request: {}", taskId, JSON.toJSONString(dto));
+
+        // 2. 调用远程重构接口
+        String requestUrl = reconRequestUri.concat(reconUri);
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        HttpEntity<String> httpEntity = new HttpEntity<>(JSON.toJSONString(dto), headers);
+        String responseStr;
+        try {
+            responseStr = connPoolRestTemplate.postForObject(requestUrl, httpEntity, String.class);
+            log.info("重构计算接口返回, taskId: {}, response: {}", taskId, responseStr);
+        } catch (Exception e) {
+            log.error("调用重构算法接口失败, taskId: {}", taskId, e);
+            return ApiResponse.fail("调用重构算法接口失败: " + e.getMessage());
+        }
+
+        // 3. 提取 raw_result 节点并入库
+        try {
+            JsonNode root = OM.readTree(responseStr);
+            JsonNode rawNode = root.get("raw_result");
+            if (rawNode == null || rawNode.isNull()) {
+                log.error("算法响应缺少 raw_result 节点, taskId: {}", taskId);
+                return ApiResponse.fail("算法响应缺少 raw_result 节点");
+            }
+            String rawResultJson = OM.writeValueAsString(rawNode);
+            reconResultService.parseAndSaveReconResult(rawResultJson, taskId);
+        } catch (IOException e) {
+            log.error("解析算法响应失败, taskId: {}", taskId, e);
+            return ApiResponse.fail("解析算法响应失败: " + e.getMessage());
+        }
+
+        return ApiResponse.success(taskId);
+    }
+
+    @Override
+    public ApiResponse<QueryOperationModeDTO> queryOperationResult(String taskId) {
+        log.info("查询重构结果, taskId: {}", taskId);
+
+        // 查询主表
+        FhzgReconResult reconResult = fhzgReconResultMapper.selectOne(
+                new LambdaQueryWrapper<FhzgReconResult>().eq(FhzgReconResult::getEventId, taskId));
+        if (reconResult == null) {
+            return ApiResponse.fail("任务不存在或未完成: " + taskId);
+        }
+
+        // 反序列化 rawResult JSON -> RawResultDTO
+        RawResultDTO rawResultDTO = null;
+        String rawResultJson = reconResult.getRawResult();
+        if (rawResultJson != null && !rawResultJson.isEmpty()) {
+            try {
+                rawResultDTO = OM.readValue(rawResultJson, RawResultDTO.class);
+            } catch (IOException e) {
+                log.error("反序列化 rawResult 失败, taskId: {}", taskId, e);
+            }
+        }
+
+        QueryOperationModeDTO resultDTO = new QueryOperationModeDTO();
+        resultDTO.setId(taskId);
+        resultDTO.setResult(rawResultDTO);
+        return ApiResponse.success(resultDTO);
+    }
+
 }