Merge branch 'develop-business-css' of http://121.37.111.42:3000/ThbTech/JavaProjectRepo into develop-business-css
This commit is contained in:
commit
bd7292ccbe
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
@ -7,13 +7,16 @@
|
|||||||
"hostName": "localhost",
|
"hostName": "localhost",
|
||||||
"port": "5005"
|
"port": "5005"
|
||||||
},
|
},
|
||||||
java
|
|
||||||
{
|
{
|
||||||
"type": "java",
|
"type": "java",
|
||||||
"name": "CriticalScenarioApplication",
|
"name": "CriticalScenarioApplication",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
"mainClass": "com.yfd.business.css.CriticalScenarioApplication",
|
"mainClass": "com.yfd.business.css.CriticalScenarioApplication",
|
||||||
"projectName": "business-css"
|
"projectName": "business-css",
|
||||||
|
"args": "",
|
||||||
|
"envFile": "${workspaceFolder}/.env"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "java",
|
"type": "java",
|
||||||
|
|||||||
@ -51,6 +51,23 @@
|
|||||||
4. 增加 OpenAPI 文档与前端集成接口规范。
|
4. 增加 OpenAPI 文档与前端集成接口规范。
|
||||||
5. 引入结果持久化与查询报表。
|
5. 引入结果持久化与查询报表。
|
||||||
|
|
||||||
|
## 调试与开发指南
|
||||||
|
|
||||||
|
### Maven 命令行启动 + 远程调试
|
||||||
|
|
||||||
|
如果您偏好使用命令行启动,或者需要模拟特定的 Maven 环境,可采用以下方式:
|
||||||
|
|
||||||
|
1. **启动应用**:
|
||||||
|
在终端中运行以下命令,该命令会以调试模式启动应用并监听 `5005` 端口(`suspend=n` 表示不等待调试器连接直接启动,如需等待可改为 `y`)。
|
||||||
|
> 注意:PowerShell 中需要使用单引号包裹 JVM 参数,防止解析错误。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn -DskipTests spring-boot:run -pl business-css '-Dspring-boot.run.jvmArguments=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **附加调试器**:
|
||||||
|
应用启动后,转到 IDE 的 "运行和调试" (Run and Debug) 面板,选择 **"Attach to Remote Program(5005)"** 配置(需确保 `.vscode/launch.json` 中已存在相应配置),然后点击运行。IDE 将连接到正在运行的 Maven 进程,即可开始断点调试。
|
||||||
|
|
||||||
## 运维与配置
|
## 运维与配置
|
||||||
- 端口默认 `8082`,环境覆盖通过 `application.yml` 与外部化配置。
|
- 端口默认 `8082`,环境覆盖通过 `application.yml` 与外部化配置。
|
||||||
- 数据库连接按环境注入(dev/test/prod)。
|
- 数据库连接按环境注入(dev/test/prod)。
|
||||||
|
|||||||
@ -66,6 +66,13 @@
|
|||||||
<classifier>plain</classifier>
|
<classifier>plain</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 显式添加 MyBatis-Plus 依赖,确保测试环境类加载正确 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.5.6</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Lombok -->
|
<!-- Lombok -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
package com.yfd.business.css.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ComponentScan(basePackages = {
|
|
||||||
"com.yfd.business.css.controller"
|
|
||||||
})
|
|
||||||
@Import(OpenApiConfig.class)
|
|
||||||
public class BusinessCssAutoConfiguration {
|
|
||||||
}
|
|
||||||
@ -14,9 +14,6 @@ import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilde
|
|||||||
import org.springdoc.core.models.GroupedOpenApi;
|
import org.springdoc.core.models.GroupedOpenApi;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
|
||||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -41,9 +38,6 @@ public class OpenApiConfig {
|
|||||||
builder.deserializers(new LocalDateTimeDeserializer(fmt));
|
builder.deserializers(new LocalDateTimeDeserializer(fmt));
|
||||||
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
builder.serializationInclusion(JsonInclude.Include.ALWAYS);
|
builder.serializationInclusion(JsonInclude.Include.ALWAYS);
|
||||||
builder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.NONE);
|
|
||||||
builder.visibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.PUBLIC_ONLY);
|
|
||||||
builder.propertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE);
|
|
||||||
SimpleModule module = new SimpleModule();
|
SimpleModule module = new SimpleModule();
|
||||||
module.setSerializerModifier(new BeanSerializerModifier() {
|
module.setSerializerModifier(new BeanSerializerModifier() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -11,11 +11,15 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/algorithms")
|
@RequestMapping("/algorithms")
|
||||||
|
@Tag(name = "算法接口", description = "算法字典的增删改查与搜索")
|
||||||
public class AlgorithmController {
|
public class AlgorithmController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -25,11 +29,13 @@ public class AlgorithmController {
|
|||||||
|
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
@Operation(summary = "根据算法ID获取算法", description = "路径参数传入算法ID,返回算法对象")
|
||||||
public Algorithm getAlgorithmById(@PathVariable String id) {
|
public Algorithm getAlgorithmById(@PathVariable String id) {
|
||||||
return algorithmService.getById(id);
|
return algorithmService.getById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@Operation(summary = "新增算法", description = "请求体传入算法对象,返回是否新增成功")
|
||||||
public boolean createAlgorithm(@RequestBody Algorithm algorithm) {
|
public boolean createAlgorithm(@RequestBody Algorithm algorithm) {
|
||||||
algorithm.setModifier(currentUsername());
|
algorithm.setModifier(currentUsername());
|
||||||
algorithm.setCreatedAt(LocalDateTime.now());
|
algorithm.setCreatedAt(LocalDateTime.now());
|
||||||
@ -38,6 +44,7 @@ public class AlgorithmController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
|
@Operation(summary = "修改算法", description = "请求体传入算法对象(需包含主键),返回是否修改成功")
|
||||||
public boolean updateAlgorithm(@RequestBody Algorithm algorithm) {
|
public boolean updateAlgorithm(@RequestBody Algorithm algorithm) {
|
||||||
algorithm.setModifier(currentUsername());
|
algorithm.setModifier(currentUsername());
|
||||||
algorithm.setUpdatedAt(LocalDateTime.now());
|
algorithm.setUpdatedAt(LocalDateTime.now());
|
||||||
@ -45,15 +52,57 @@ public class AlgorithmController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@Operation(summary = "删除算法(单条)", description = "根据算法ID删除算法")
|
||||||
public boolean deleteAlgorithm(@PathVariable String id) {
|
public boolean deleteAlgorithm(@PathVariable String id) {
|
||||||
return algorithmService.removeById(id);
|
return algorithmService.removeById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@Operation(summary = "删除算法(批量)", description = "请求体传入算法ID列表,批量删除算法")
|
||||||
public boolean deleteAlgorithms(@RequestBody List<String> ids) {
|
public boolean deleteAlgorithms(@RequestBody List<String> ids) {
|
||||||
return algorithmService.removeByIds(ids);
|
return algorithmService.removeByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//算法类型激活
|
||||||
|
@PostMapping("/activate")
|
||||||
|
@Operation(summary = "激活算法", description = "激活当前算法类型")
|
||||||
|
public boolean activate(@RequestParam String algorithmId) {
|
||||||
|
Algorithm algorithm = algorithmService.getById(algorithmId);
|
||||||
|
if (algorithm == null) return false;
|
||||||
|
// 先将当前算法类型激活
|
||||||
|
algorithm.setStatus("1");
|
||||||
|
algorithm.setModifier(currentUsername());
|
||||||
|
algorithm.setUpdatedAt(LocalDateTime.now());
|
||||||
|
return algorithmService.updateById(algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//算法类型关闭
|
||||||
|
@PostMapping("/unactivate")
|
||||||
|
@Operation(summary = "关闭算法", description = "关闭当前算法类型")
|
||||||
|
public boolean unactivate(@RequestParam String algorithmId) {
|
||||||
|
Algorithm algorithm = algorithmService.getById(algorithmId);
|
||||||
|
if (algorithm == null) return false;
|
||||||
|
// 先将当前算法类型激活
|
||||||
|
algorithm.setStatus("0");
|
||||||
|
algorithm.setModifier(currentUsername());
|
||||||
|
algorithm.setUpdatedAt(LocalDateTime.now());
|
||||||
|
return algorithmService.updateById(algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取激活的算法类型
|
||||||
|
/**
|
||||||
|
* 获取所有激活的算法类型
|
||||||
|
* 输出参数:激活的算法类型列表
|
||||||
|
* @return 激活的算法类型列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/getActiveAlgorithms")
|
||||||
|
@Operation(summary = "获取激活的算法类型", description = "返回所有激活的算法类型")
|
||||||
|
public List<Algorithm> getActiveAlgorithms() {
|
||||||
|
QueryWrapper<Algorithm> qw = new QueryWrapper<>();
|
||||||
|
qw.eq("status", "1");
|
||||||
|
return algorithmService.list(qw);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据算法名称搜索并分页返回
|
* 根据算法名称搜索并分页返回
|
||||||
* 输入参数:查询参数 name(算法名称关键词,可为空),pageNum(页码,默认1),pageSize(每页条数,默认10)
|
* 输入参数:查询参数 name(算法名称关键词,可为空),pageNum(页码,默认1),pageSize(每页条数,默认10)
|
||||||
@ -64,6 +113,7 @@ public class AlgorithmController {
|
|||||||
* @return 算法分页列表
|
* @return 算法分页列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/search")
|
@GetMapping("/search")
|
||||||
|
@Operation(summary = "搜索算法并分页返回", description = "按名称关键词模糊查询,返回分页结果")
|
||||||
public Page<Algorithm> searchAlgorithms(@RequestParam(required = false) String name,
|
public Page<Algorithm> searchAlgorithms(@RequestParam(required = false) String name,
|
||||||
@RequestParam(defaultValue = "1") long pageNum,
|
@RequestParam(defaultValue = "1") long pageNum,
|
||||||
@RequestParam(defaultValue = "20") long pageSize) {
|
@RequestParam(defaultValue = "20") long pageSize) {
|
||||||
|
|||||||
@ -3,7 +3,9 @@ package com.yfd.business.css.controller;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.yfd.business.css.domain.AlgorithmModel;
|
import com.yfd.business.css.domain.AlgorithmModel;
|
||||||
|
import com.yfd.business.css.domain.Algorithm;
|
||||||
import com.yfd.business.css.service.AlgorithmModelService;
|
import com.yfd.business.css.service.AlgorithmModelService;
|
||||||
|
import com.yfd.business.css.service.AlgorithmService;
|
||||||
import com.yfd.platform.system.service.IUserService;
|
import com.yfd.platform.system.service.IUserService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -11,24 +13,46 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/algorithm-models")
|
@RequestMapping("/algorithm-models")
|
||||||
|
@Tag(name = "算法模型接口", description = "算法模型版本的增删改查、查询当前版本与在线训练")
|
||||||
public class AlgorithmModelController {
|
public class AlgorithmModelController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AlgorithmModelService algorithmModelService;
|
private AlgorithmModelService algorithmModelService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IUserService userService;
|
private IUserService userService;
|
||||||
|
@Autowired
|
||||||
|
private AlgorithmService algorithmService;
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
@Operation(summary = "根据模型ID获取模型版本", description = "路径参数传入模型ID,返回模型版本对象")
|
||||||
public AlgorithmModel getById(@PathVariable String id) {
|
public AlgorithmModel getById(@PathVariable String id) {
|
||||||
return algorithmModelService.getById(id);
|
return algorithmModelService.getById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@Operation(summary = "新增模型版本", description = "请求体传入模型版本对象,返回是否新增成功")
|
||||||
public boolean create(@RequestBody AlgorithmModel model) {
|
public boolean create(@RequestBody AlgorithmModel model) {
|
||||||
model.setModifier(currentUsername());
|
model.setModifier(currentUsername());
|
||||||
model.setCreatedAt(LocalDateTime.now());
|
model.setCreatedAt(LocalDateTime.now());
|
||||||
@ -37,6 +61,7 @@ public class AlgorithmModelController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
|
@Operation(summary = "修改模型版本", description = "请求体传入模型版本对象(需包含主键),返回是否修改成功")
|
||||||
public boolean update(@RequestBody AlgorithmModel model) {
|
public boolean update(@RequestBody AlgorithmModel model) {
|
||||||
model.setModifier(currentUsername());
|
model.setModifier(currentUsername());
|
||||||
model.setUpdatedAt(LocalDateTime.now());
|
model.setUpdatedAt(LocalDateTime.now());
|
||||||
@ -44,24 +69,31 @@ public class AlgorithmModelController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@Operation(summary = "删除模型版本(单条)", description = "根据模型ID删除模型版本")
|
||||||
public boolean delete(@PathVariable String id) {
|
public boolean delete(@PathVariable String id) {
|
||||||
return algorithmModelService.removeById(id);
|
return algorithmModelService.removeById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
@Operation(summary = "删除模型版本(批量)", description = "请求体传入模型ID列表,批量删除模型版本")
|
||||||
public boolean deleteBatch(@RequestBody List<String> ids) {
|
public boolean deleteBatch(@RequestBody List<String> ids) {
|
||||||
return algorithmModelService.removeByIds(ids);
|
return algorithmModelService.removeByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回:该算法+设备类型的版本列表
|
//返回:该算法+设备类型的版本列表
|
||||||
@GetMapping("/search")
|
@GetMapping("/search")
|
||||||
|
@Operation(summary = "查询模型版本列表", description = "按算法类型与设备类型过滤并分页返回模型版本")
|
||||||
public Page<AlgorithmModel> search(@RequestParam(required = false) String algorithmType,
|
public Page<AlgorithmModel> search(@RequestParam(required = false) String algorithmType,
|
||||||
@RequestParam(required = false) String deviceType,
|
@RequestParam(required = false) String deviceType,
|
||||||
|
@RequestParam(required = false) String versionTag,
|
||||||
|
@RequestParam(required = false) String isCurrent,
|
||||||
@RequestParam(defaultValue = "1") long pageNum,
|
@RequestParam(defaultValue = "1") long pageNum,
|
||||||
@RequestParam(defaultValue = "20") long pageSize) {
|
@RequestParam(defaultValue = "20") long pageSize) {
|
||||||
QueryWrapper<AlgorithmModel> qw = new QueryWrapper<>();
|
QueryWrapper<AlgorithmModel> qw = new QueryWrapper<>();
|
||||||
if (algorithmType != null && !algorithmType.isEmpty()) qw.eq("algorithm_type", algorithmType);
|
if (algorithmType != null && !algorithmType.isEmpty()) qw.eq("algorithm_type", algorithmType);
|
||||||
if (deviceType != null && !deviceType.isEmpty()) qw.eq("device_type", deviceType);
|
if (deviceType != null && !deviceType.isEmpty()) qw.eq("device_type", deviceType);
|
||||||
|
if (versionTag != null && !versionTag.isEmpty()) qw.eq("version_tag", versionTag);
|
||||||
|
if (isCurrent != null && !isCurrent.isEmpty()) qw.eq("is_current", isCurrent);
|
||||||
qw.orderByDesc("updated_at");
|
qw.orderByDesc("updated_at");
|
||||||
Page<AlgorithmModel> page = new Page<>(pageNum, pageSize, true);
|
Page<AlgorithmModel> page = new Page<>(pageNum, pageSize, true);
|
||||||
return algorithmModelService.page(page, qw);
|
return algorithmModelService.page(page, qw);
|
||||||
@ -69,6 +101,7 @@ public class AlgorithmModelController {
|
|||||||
|
|
||||||
//返回:该算法+设备类型的当前激活版本
|
//返回:该算法+设备类型的当前激活版本
|
||||||
@GetMapping("/current")
|
@GetMapping("/current")
|
||||||
|
@Operation(summary = "获取当前激活版本", description = "根据算法类型与设备类型,返回 is_current=1 的模型版本")
|
||||||
public AlgorithmModel getCurrent(@RequestParam String algorithmType,
|
public AlgorithmModel getCurrent(@RequestParam String algorithmType,
|
||||||
@RequestParam String deviceType) {
|
@RequestParam String deviceType) {
|
||||||
QueryWrapper<AlgorithmModel> qw = new QueryWrapper<>();
|
QueryWrapper<AlgorithmModel> qw = new QueryWrapper<>();
|
||||||
@ -81,6 +114,7 @@ public class AlgorithmModelController {
|
|||||||
|
|
||||||
//版本激活
|
//版本激活
|
||||||
@PostMapping("/activate")
|
@PostMapping("/activate")
|
||||||
|
@Operation(summary = "激活模型版本", description = "将目标模型版本设为当前,并将同组其他版本设为非当前")
|
||||||
public boolean activate(@RequestParam String algorithmModelId) {
|
public boolean activate(@RequestParam String algorithmModelId) {
|
||||||
AlgorithmModel model = algorithmModelService.getById(algorithmModelId);
|
AlgorithmModel model = algorithmModelService.getById(algorithmModelId);
|
||||||
if (model == null) return false;
|
if (model == null) return false;
|
||||||
@ -98,15 +132,122 @@ public class AlgorithmModelController {
|
|||||||
return algorithmModelService.updateById(model);
|
return algorithmModelService.updateById(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
//在线训练
|
// 在线训练(Excel 数据集)
|
||||||
|
@PostMapping("/train/excel")
|
||||||
|
@Operation(summary = "在线训练(Excel)", description = "传入算法类型、设备类型与Excel路径,训练完成新增模型版本记录,可选激活")
|
||||||
|
public Map<String, Object> trainExcel(@RequestBody Map<String, Object> body) {
|
||||||
|
String algorithmType = str(body.get("algorithm_type"));
|
||||||
|
String deviceType = str(body.get("device_type"));
|
||||||
|
String datasetPath = str(body.get("dataset_path"));
|
||||||
|
String modelDir = str(body.getOrDefault("model_dir", ""));
|
||||||
|
boolean activate = bool(body.getOrDefault("activate", false));
|
||||||
|
String featureMapSnapshot = toJson(body.get("feature_map_snapshot"));
|
||||||
|
if (isBlank(algorithmType) || isBlank(deviceType) || isBlank(datasetPath)) {
|
||||||
|
return Map.of("code", 1, "msg", "algorithm_type/device_type/dataset_path 必填");
|
||||||
|
}
|
||||||
|
Algorithm algo = getAlgorithmByType(algorithmType);
|
||||||
|
if (algo == null || isBlank(algo.getTrainBaseUrl())) {
|
||||||
|
return Map.of("code", 1, "msg", "算法或训练URL未配置");
|
||||||
|
}
|
||||||
|
String baseUrl = algo.getTrainBaseUrl();
|
||||||
|
if (baseUrl != null && baseUrl.endsWith("/")) {
|
||||||
|
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
|
||||||
|
}
|
||||||
|
String url = baseUrl + "/v1/train/" + deviceType;
|
||||||
|
Map<String, Object> payload = new HashMap<>();
|
||||||
|
payload.put("dataset_path", datasetPath);
|
||||||
|
if (!isBlank(modelDir)) payload.put("model_dir", modelDir);
|
||||||
|
Map<String, Object> resp = httpPostJson(url, payload);
|
||||||
|
if (resp == null) return Map.of("code", 1, "msg", "训练接口无响应");
|
||||||
|
int code = 0;
|
||||||
|
Object codeObj = resp.get("code");
|
||||||
|
if (codeObj instanceof Number) {
|
||||||
|
code = ((Number) codeObj).intValue();
|
||||||
|
} else if (codeObj instanceof String) {
|
||||||
|
try {
|
||||||
|
code = Integer.parseInt((String) codeObj);
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
code = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (code != 0) return Map.of("code", 1, "msg", "训练失败: " + str(resp.get("msg")));
|
||||||
|
Map<String, Object> data = castMap(resp.get("data"));
|
||||||
|
String modelPath = str(data.get("model_path"));
|
||||||
|
String metrics = toJson(data.get("metrics"));
|
||||||
|
AlgorithmModel model = new AlgorithmModel();
|
||||||
|
model.setAlgorithmModelId(UUID.randomUUID().toString());
|
||||||
|
model.setAlgorithmType(algorithmType);
|
||||||
|
model.setDeviceType(deviceType);
|
||||||
|
model.setVersionTag(genVersionTag());
|
||||||
|
model.setModelPath(modelPath);
|
||||||
|
model.setFeatureMapSnapshot(isBlank(featureMapSnapshot) ? "{}" : featureMapSnapshot);
|
||||||
|
model.setMetrics(metrics);
|
||||||
|
model.setTrainedAt(LocalDateTime.now());
|
||||||
|
model.setIsCurrent(activate ? 1 : 0);
|
||||||
|
model.setCreatedAt(LocalDateTime.now());
|
||||||
|
model.setUpdatedAt(LocalDateTime.now());
|
||||||
|
model.setModifier(currentUsername());
|
||||||
|
if (activate) {
|
||||||
|
QueryWrapper<AlgorithmModel> qw = new QueryWrapper<>();
|
||||||
|
qw.eq("algorithm_type", algorithmType).eq("device_type", deviceType);
|
||||||
|
AlgorithmModel upd = new AlgorithmModel();
|
||||||
|
upd.setIsCurrent(0);
|
||||||
|
algorithmModelService.update(upd, qw);
|
||||||
|
}
|
||||||
|
algorithmModelService.save(model);
|
||||||
|
return Map.of("code", 0, "msg", "训练成功", "data", model);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/train")
|
// 在线训练(样本集合)
|
||||||
public boolean train(@RequestParam String algorithmModelId) {
|
@PostMapping("/train/samples")
|
||||||
AlgorithmModel model = algorithmModelService.getById(algorithmModelId);
|
@Operation(summary = "在线训练(样本集合)", description = "传入算法类型、设备类型与样本集,训练完成新增模型版本记录,可选激活")
|
||||||
if (model == null) return false;
|
public Map<String, Object> trainSamples(@RequestBody Map<String, Object> body) {
|
||||||
// 调用训练接口
|
String algorithmType = str(body.get("algorithm_type"));
|
||||||
// ...
|
String deviceType = str(body.get("device_type"));
|
||||||
return true;
|
Object samples = body.get("samples"); // 期望为 List<Map>,由前端提供
|
||||||
|
String modelDir = str(body.getOrDefault("model_dir", ""));
|
||||||
|
boolean activate = bool(body.getOrDefault("activate", false));
|
||||||
|
String featureMapSnapshot = toJson(body.get("feature_map_snapshot"));
|
||||||
|
if (isBlank(algorithmType) || isBlank(deviceType) || samples == null) {
|
||||||
|
return Map.of("code", 1, "msg", "algorithm_type/device_type/samples 必填");
|
||||||
|
}
|
||||||
|
Algorithm algo = getAlgorithmByType(algorithmType);
|
||||||
|
if (algo == null || isBlank(algo.getTrainBaseUrl())) {
|
||||||
|
return Map.of("code", 1, "msg", "算法或训练URL未配置");
|
||||||
|
}
|
||||||
|
String url = "";//trimSlash(algo.getTrainBaseUrl()) + "/v1/train/" + deviceType + "/from-samples";
|
||||||
|
Map<String, Object> payload = new HashMap<>();
|
||||||
|
payload.put("samples", samples);
|
||||||
|
if (!isBlank(modelDir)) payload.put("model_dir", modelDir);
|
||||||
|
Map<String, Object> resp = httpPostJson(url, payload);
|
||||||
|
if (resp == null) return Map.of("code", 1, "msg", "训练接口无响应");
|
||||||
|
int code = 0;//intVal(resp.get("code"));
|
||||||
|
if (code != 0) return Map.of("code", 1, "msg", "训练失败: " + str(resp.get("msg")));
|
||||||
|
Map<String, Object> data = castMap(resp.get("data"));
|
||||||
|
String modelPath = str(data.get("model_path"));
|
||||||
|
String metrics = toJson(data.get("metrics"));
|
||||||
|
AlgorithmModel model = new AlgorithmModel();
|
||||||
|
model.setAlgorithmModelId(UUID.randomUUID().toString());
|
||||||
|
model.setAlgorithmType(algorithmType);
|
||||||
|
model.setDeviceType(deviceType);
|
||||||
|
model.setVersionTag(genVersionTag());
|
||||||
|
model.setModelPath(modelPath);
|
||||||
|
model.setFeatureMapSnapshot(isBlank(featureMapSnapshot) ? "{}" : featureMapSnapshot);
|
||||||
|
model.setMetrics(metrics);
|
||||||
|
model.setTrainedAt(LocalDateTime.now());
|
||||||
|
model.setIsCurrent(activate ? 1 : 0);
|
||||||
|
model.setCreatedAt(LocalDateTime.now());
|
||||||
|
model.setUpdatedAt(LocalDateTime.now());
|
||||||
|
model.setModifier(currentUsername());
|
||||||
|
if (activate) {
|
||||||
|
QueryWrapper<AlgorithmModel> qw = new QueryWrapper<>();
|
||||||
|
qw.eq("algorithm_type", algorithmType).eq("device_type", deviceType);
|
||||||
|
AlgorithmModel upd = new AlgorithmModel();
|
||||||
|
upd.setIsCurrent(0);
|
||||||
|
algorithmModelService.update(upd, qw);
|
||||||
|
}
|
||||||
|
algorithmModelService.save(model);
|
||||||
|
return Map.of("code", 0, "msg", "训练成功", "data", model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -121,4 +262,55 @@ public class AlgorithmModelController {
|
|||||||
return "anonymous";
|
return "anonymous";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Algorithm getAlgorithmByType(String algorithmType) {
|
||||||
|
QueryWrapper<Algorithm> qw = new QueryWrapper<>();
|
||||||
|
qw.eq("algorithm_type", algorithmType);
|
||||||
|
return algorithmService.getOne(qw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> httpPostJson(String url, Object payload) {
|
||||||
|
try {
|
||||||
|
String json = objectMapper.writeValueAsString(payload);
|
||||||
|
HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
|
||||||
|
HttpRequest req = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(url))
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.timeout(Duration.ofSeconds(30))
|
||||||
|
.POST(HttpRequest.BodyPublishers.ofString(json, StandardCharsets.UTF_8))
|
||||||
|
.build();
|
||||||
|
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
|
||||||
|
if (res.statusCode() >= 200 && res.statusCode() < 300) {
|
||||||
|
return objectMapper.readValue(res.body(), new TypeReference<Map<String, Object>>() {});
|
||||||
|
}
|
||||||
|
return Map.of("code", 1, "msg", "HTTP " + res.statusCode());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Map.of("code", 1, "msg", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String genVersionTag() {
|
||||||
|
return "v" + LocalDateTime.now().toString().replace(":", "-");
|
||||||
|
}
|
||||||
|
private String str(Object v) { return v == null ? "" : String.valueOf(v); }
|
||||||
|
private boolean isBlank(String s) { return s == null || s.trim().isEmpty(); }
|
||||||
|
private boolean bool(Object v) {
|
||||||
|
if (v instanceof Boolean) return (Boolean) v;
|
||||||
|
String s = str(v).toLowerCase();
|
||||||
|
return "true".equals(s) || "1".equals(s) || "yes".equals(s);
|
||||||
|
}
|
||||||
|
private String toJson(Object v) {
|
||||||
|
try {
|
||||||
|
if (v == null) return null;
|
||||||
|
if (v instanceof String) return (String) v;
|
||||||
|
return objectMapper.writeValueAsString(v);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, Object> castMap(Object v) {
|
||||||
|
if (v instanceof Map) return (Map<String, Object>) v;
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -285,6 +285,21 @@ public class ProjectController {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//输入模拟数据,调用推理接口,得到推理结果并写入结果表
|
||||||
|
@PostMapping("/simulation/run")
|
||||||
|
@Operation(summary = "运行项目模拟", description = "输入模拟数据,调用推理接口,得到推理结果并写入结果表")
|
||||||
|
public ResponseEntity<Map<String, Object>> runSimulation(@RequestParam @Parameter(description = "项目ID", required = true) String projectId,
|
||||||
|
@RequestParam @Parameter(description = "情景ID", required = true) String scenarioId,
|
||||||
|
@RequestBody(required = false) Map<String, Object> params) {
|
||||||
|
var res = projectService.runSimulation(projectId, scenarioId, params == null ? Map.of() : params);
|
||||||
|
return ResponseEntity.ok(Map.of(
|
||||||
|
"code", 0,
|
||||||
|
"msg", "运行完成",
|
||||||
|
"data", res
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,57 +9,80 @@ import lombok.Data;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 算法配置信息表
|
||||||
|
* 存储算法的基本配置、参数和状态信息
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("algorithm")
|
@TableName("algorithm")
|
||||||
public class Algorithm implements Serializable {
|
public class Algorithm implements Serializable {
|
||||||
|
|
||||||
|
/** 序列化版本号 */
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 算法ID - 主键,UUID生成 */
|
||||||
@TableId(value = "algorithm_id", type = IdType.ASSIGN_UUID)
|
@TableId(value = "algorithm_id", type = IdType.ASSIGN_UUID)
|
||||||
private String algorithmId;
|
private String algorithmId;
|
||||||
|
|
||||||
|
/** 算法类型 */
|
||||||
@TableField("algorithm_type")
|
@TableField("algorithm_type")
|
||||||
private String algorithmType;
|
private String algorithmType;
|
||||||
|
|
||||||
|
/** 算法名称 */
|
||||||
@TableField("name")
|
@TableField("name")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
/** 算法描述 */
|
||||||
@TableField("description")
|
@TableField("description")
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
/** 算法版本 - 版本号,例如v1.0 */
|
||||||
@TableField("version")
|
@TableField("version")
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
|
/** 算法原理说明 */
|
||||||
@TableField("principle")
|
@TableField("principle")
|
||||||
private String principle;
|
private String principle;
|
||||||
|
|
||||||
|
/** 调用参数 - 以JSON存储参数名称、类型、默认值等 */
|
||||||
@TableField("input_params")
|
@TableField("input_params")
|
||||||
private String inputParams;
|
private String inputParams;
|
||||||
|
|
||||||
|
/** 输出参数 - 以JSON存储参数名称、类型、说明等 */
|
||||||
@TableField("output_params")
|
@TableField("output_params")
|
||||||
private String outputParams;
|
private String outputParams;
|
||||||
|
|
||||||
|
/** 推理URL */
|
||||||
@TableField("infer_base_url")
|
@TableField("infer_base_url")
|
||||||
private String inferBaseUrl;
|
private String inferBaseUrl;
|
||||||
|
|
||||||
|
/** 训练URL */
|
||||||
@TableField("train_base_url")
|
@TableField("train_base_url")
|
||||||
private String trainBaseUrl;
|
private String trainBaseUrl;
|
||||||
|
|
||||||
|
/** 支持设备类型 - JSON格式 */
|
||||||
@TableField("supported_device_types")
|
@TableField("supported_device_types")
|
||||||
private String supportedDeviceTypes;
|
private String supportedDeviceTypes;
|
||||||
|
|
||||||
|
/** 默认超参 - JSON格式 */
|
||||||
@TableField("default_hyper_params")
|
@TableField("default_hyper_params")
|
||||||
private String defaultHyperParams;
|
private String defaultHyperParams;
|
||||||
|
|
||||||
|
/** 激活状态 - 1:激活;0:关闭 */
|
||||||
@TableField("status")
|
@TableField("status")
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
@TableField("updated_at")
|
@TableField("updated_at")
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
@TableField("created_at")
|
@TableField("created_at")
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
/** 最后修改人 */
|
||||||
@TableField("modifier")
|
@TableField("modifier")
|
||||||
private String modifier;
|
private String modifier;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,45 +7,65 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备临界数据表
|
||||||
|
* 存储设备的临界数据信息,包括几何参数、材料特性和k_eff值
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("critical_data")
|
@TableName("critical_data")
|
||||||
public class CriticalData implements Serializable {
|
public class CriticalData implements Serializable {
|
||||||
|
|
||||||
|
/** 序列化版本号 */
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 临界数据主键 */
|
||||||
@TableId(value = "critical_id", type = IdType.ASSIGN_UUID)
|
@TableId(value = "critical_id", type = IdType.ASSIGN_UUID)
|
||||||
private String criticalId;
|
private String criticalId;
|
||||||
|
|
||||||
|
/** 设备类型 */
|
||||||
@TableField("device_type")
|
@TableField("device_type")
|
||||||
private String deviceType;
|
private String deviceType;
|
||||||
|
|
||||||
|
/** 等效直径 */
|
||||||
@TableField("diameter")
|
@TableField("diameter")
|
||||||
private BigDecimal diameter;
|
private BigDecimal diameter;
|
||||||
|
|
||||||
|
/** 等效高度 */
|
||||||
@TableField("height")
|
@TableField("height")
|
||||||
private BigDecimal height;
|
private BigDecimal height;
|
||||||
|
|
||||||
|
/** 核材料浓度(U 或 Pu) */
|
||||||
@TableField("fissile_concentration")
|
@TableField("fissile_concentration")
|
||||||
private BigDecimal fissileConcentration;
|
private BigDecimal fissileConcentration;
|
||||||
|
|
||||||
|
/** 同位素丰度(铀富集度 或 Pu-240 占比) */
|
||||||
@TableField("isotopic_abundance")
|
@TableField("isotopic_abundance")
|
||||||
private BigDecimal isotopicAbundance;
|
private BigDecimal isotopicAbundance;
|
||||||
|
|
||||||
|
/** 扩展物理/算法特征 - JSON格式 */
|
||||||
@TableField("extra_features")
|
@TableField("extra_features")
|
||||||
private String extraFeatures;
|
private String extraFeatures;
|
||||||
|
|
||||||
|
/** 对应 k_eff 值 */
|
||||||
@TableField("keff_value")
|
@TableField("keff_value")
|
||||||
private BigDecimal keffValue;
|
private BigDecimal keffValue;
|
||||||
|
|
||||||
|
/** 属性状态 - JSON格式 */
|
||||||
|
@TableField("attr_state")
|
||||||
|
private String attrState;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
@TableField("created_at")
|
@TableField("created_at")
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
/** 最后更新时间 */
|
||||||
@TableField("updated_at")
|
@TableField("updated_at")
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
/** 最后修改人 */
|
||||||
@TableField("modifier")
|
@TableField("modifier")
|
||||||
private String modifier;
|
private String modifier;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -32,11 +31,9 @@ public class Project implements Serializable {
|
|||||||
private String topology;
|
private String topology;
|
||||||
|
|
||||||
@TableField("created_at")
|
@TableField("created_at")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
@TableField("updated_at")
|
@TableField("updated_at")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
@TableField("modifier")
|
@TableField("modifier")
|
||||||
|
|||||||
@ -11,6 +11,6 @@ public class EventAttrParseResult {
|
|||||||
private Map<String, String> target;
|
private Map<String, String> target;
|
||||||
private String unit;
|
private String unit;
|
||||||
private List<EventAttrSegment> segments;
|
private List<EventAttrSegment> segments;
|
||||||
private List<Map<String, Object>> schedule; // optional derived ramp/step
|
private List<Map<String, Object>> schedule;
|
||||||
private List<String> issues;
|
private List<String> issues;
|
||||||
}
|
}
|
||||||
@ -10,6 +10,6 @@ public class TopoEdge {
|
|||||||
private String toEntityType;
|
private String toEntityType;
|
||||||
private String toEntityId;
|
private String toEntityId;
|
||||||
private String toProperty;
|
private String toProperty;
|
||||||
private Double coefficient;
|
private double coefficient;
|
||||||
private Long delayMs;
|
private long delayMs;
|
||||||
}
|
}
|
||||||
@ -8,11 +8,11 @@ import java.util.Map;
|
|||||||
@Data
|
@Data
|
||||||
public class TopologyParseResult {
|
public class TopologyParseResult {
|
||||||
private String projectId;
|
private String projectId;
|
||||||
private Integer deviceCount;
|
|
||||||
private Integer nodeCount;
|
|
||||||
private Integer edgeCount;
|
|
||||||
private List<TopoNode> nodes;
|
private List<TopoNode> nodes;
|
||||||
private List<TopoEdge> edges;
|
private List<TopoEdge> edges;
|
||||||
private List<Map<String, Object>> plans;
|
private List<Map<String, Object>> plans;
|
||||||
private List<String> issues;
|
private List<String> issues;
|
||||||
|
private int deviceCount;
|
||||||
|
private int nodeCount;
|
||||||
|
private int edgeCount;
|
||||||
}
|
}
|
||||||
@ -2,8 +2,7 @@ package com.yfd.business.css.mapper;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.yfd.business.css.domain.AlgorithmModel;
|
import com.yfd.business.css.domain.AlgorithmModel;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface AlgorithmModelMapper extends BaseMapper<AlgorithmModel> {
|
public interface AlgorithmModelMapper extends BaseMapper<AlgorithmModel> {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.yfd.business.css.model;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DeviceStepInfo {
|
||||||
|
private String deviceId;
|
||||||
|
private String deviceType;
|
||||||
|
private Map<String, Object> properties;
|
||||||
|
private int step;
|
||||||
|
private int time;
|
||||||
|
|
||||||
|
public DeviceStepInfo() {}
|
||||||
|
|
||||||
|
public DeviceStepInfo(String deviceId, String deviceType, Map<String, Object> properties,int step,int time) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
this.properties = properties;
|
||||||
|
this.step = step;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter和Setter方法
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getDeviceType() {
|
||||||
|
return deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceType(String deviceType) {
|
||||||
|
this.deviceType = deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperties(Map<String, Object> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStep() {
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStep(int step) {
|
||||||
|
this.step = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(int time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DeviceStepInfo{" +
|
||||||
|
"deviceId='" + deviceId + '\'' +
|
||||||
|
", deviceType='" + deviceType + '\'' +
|
||||||
|
", properties=" + properties +
|
||||||
|
", step=" + step +
|
||||||
|
", time=" + time +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.yfd.business.css.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class InferRequest {
|
||||||
|
private String modelDir;
|
||||||
|
private String deviceType;
|
||||||
|
private List<Map<String, Object>> batch;
|
||||||
|
private Map<String, Object> features;
|
||||||
|
private Map<String, Object> meta;
|
||||||
|
|
||||||
|
public InferRequest() {}
|
||||||
|
|
||||||
|
// Getter和Setter方法
|
||||||
|
public String getModelDir() { return modelDir; }
|
||||||
|
public void setModelDir(String modelDir) { this.modelDir = modelDir; }
|
||||||
|
public String getDeviceType() { return deviceType; }
|
||||||
|
public void setDeviceType(String deviceType) { this.deviceType = deviceType; }
|
||||||
|
public List<Map<String, Object>> getBatch() { return batch; }
|
||||||
|
public void setBatch(List<Map<String, Object>> batch) { this.batch = batch; }
|
||||||
|
public Map<String, Object> getFeatures() { return features; }
|
||||||
|
public void setFeatures(Map<String, Object> features) { this.features = features; }
|
||||||
|
public Map<String, Object> getMeta() { return meta; }
|
||||||
|
public void setMeta(Map<String, Object> meta) { this.meta = meta; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "InferRequest{" +
|
||||||
|
"modelDir='" + modelDir + '\'' +
|
||||||
|
", deviceType='" + deviceType + '\'' +
|
||||||
|
", batch=" + batch +
|
||||||
|
", features=" + features +
|
||||||
|
", meta=" + meta +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
package com.yfd.business.css.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public class InferResponse {
|
||||||
|
private int code;
|
||||||
|
private String msg;
|
||||||
|
private InferData data;
|
||||||
|
|
||||||
|
public static class InferData {
|
||||||
|
private List<InferItem> items;
|
||||||
|
private Map<String, Object> meta;
|
||||||
|
private Map<String, Object> features;
|
||||||
|
private BigDecimal keff;
|
||||||
|
|
||||||
|
// Getter和Setter方法
|
||||||
|
public List<InferItem> getItems() { return items; }
|
||||||
|
public void setItems(List<InferItem> items) { this.items = items; }
|
||||||
|
public Map<String, Object> getMeta() { return meta; }
|
||||||
|
public void setMeta(Map<String, Object> meta) { this.meta = meta; }
|
||||||
|
public Map<String, Object> getFeatures() { return features; }
|
||||||
|
public void setFeatures(Map<String, Object> features) { this.features = features; }
|
||||||
|
public BigDecimal getKeff() { return keff; }
|
||||||
|
public void setKeff(BigDecimal keff) { this.keff = keff; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "InferData{" +
|
||||||
|
"items=" + items +
|
||||||
|
", meta=" + meta +
|
||||||
|
", features=" + features +
|
||||||
|
", keff=" + keff +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InferItem {
|
||||||
|
private Map<String, Object> meta;
|
||||||
|
private Map<String, Object> features;
|
||||||
|
private BigDecimal keff;
|
||||||
|
|
||||||
|
// Getter和Setter方法
|
||||||
|
public Map<String, Object> getMeta() { return meta; }
|
||||||
|
public void setMeta(Map<String, Object> meta) { this.meta = meta; }
|
||||||
|
public Map<String, Object> getFeatures() { return features; }
|
||||||
|
public void setFeatures(Map<String, Object> features) { this.features = features; }
|
||||||
|
public BigDecimal getKeff() { return keff; }
|
||||||
|
public void setKeff(BigDecimal keff) { this.keff = keff; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "InferItem{" +
|
||||||
|
"meta=" + meta +
|
||||||
|
", features=" + features +
|
||||||
|
", keff=" + keff +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter和Setter方法
|
||||||
|
public int getCode() { return code; }
|
||||||
|
public void setCode(int code) { this.code = code; }
|
||||||
|
public String getMsg() { return msg; }
|
||||||
|
public void setMsg(String msg) { this.msg = msg; }
|
||||||
|
public InferData getData() { return data; }
|
||||||
|
public void setData(InferData data) { this.data = data; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "InferResponse{" +
|
||||||
|
"code=" + code +
|
||||||
|
", msg='" + msg + '\'' +
|
||||||
|
", data=" + data +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,4 +4,14 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.yfd.business.css.domain.AlgorithmModel;
|
import com.yfd.business.css.domain.AlgorithmModel;
|
||||||
|
|
||||||
public interface AlgorithmModelService extends IService<AlgorithmModel> {
|
public interface AlgorithmModelService extends IService<AlgorithmModel> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据算法类型、设备类型,获取当前激活的模型路径
|
||||||
|
*
|
||||||
|
* @param algorithmType 算法类型(如GPR/MLP/FastRBF)
|
||||||
|
* @param deviceType 设备类型(如CylindricalTank/AnnularTank)
|
||||||
|
* @return 激活版本的模型文件路径,如果不存在则返回null
|
||||||
|
*/
|
||||||
|
String getCurrentModelPath(String algorithmType, String deviceType) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,175 @@
|
|||||||
|
package com.yfd.business.css.service;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.yfd.business.css.domain.ScenarioResult;
|
||||||
|
import com.yfd.business.css.model.DeviceStepInfo;
|
||||||
|
import com.yfd.business.css.model.InferRequest;
|
||||||
|
import com.yfd.business.css.model.InferResponse;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
@Service
|
||||||
|
public class DeviceInferService {
|
||||||
|
@Value("${python.api.url:http://localhost:8000}")
|
||||||
|
private String pythonInferUrl;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ScenarioService scenarioService;
|
||||||
|
@Resource
|
||||||
|
private AlgorithmModelService algorithmModelService;
|
||||||
|
@Resource
|
||||||
|
private ScenarioResultService scenarioResultService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public void processDeviceInference(String projectId, String scenarioId,
|
||||||
|
Map<String, List<DeviceStepInfo>> groupedDevices) {
|
||||||
|
// 遍历每个设备类型,调用对应的模型进行推理
|
||||||
|
for (Map.Entry<String, List<DeviceStepInfo>> entry : groupedDevices.entrySet()) {
|
||||||
|
String deviceType = entry.getKey();
|
||||||
|
// algorithmType通过scenarioId获取
|
||||||
|
String algorithmType = scenarioService.getAlgorithmType(scenarioId);
|
||||||
|
if (algorithmType == null) {
|
||||||
|
throw new IllegalArgumentException("场景 " + scenarioId + " 未配置算法类型");
|
||||||
|
}
|
||||||
|
|
||||||
|
//modelPath根据模型类型、设备类型,从algorithm_model获取活动的model_path
|
||||||
|
String modelPath = algorithmModelService.getCurrentModelPath(algorithmType, deviceType);
|
||||||
|
System.out.println("modelPath="+modelPath);
|
||||||
|
if (modelPath == null) {
|
||||||
|
throw new IllegalArgumentException("未配置 " + algorithmType + " 模型路径");
|
||||||
|
}
|
||||||
|
List<DeviceStepInfo> devices = entry.getValue();
|
||||||
|
System.out.println("devices="+devices);
|
||||||
|
// 校验设备数据是否完整
|
||||||
|
if (devices == null || devices.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("设备数据为空,无法进行模拟");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 封装推理请求
|
||||||
|
InferRequest request = buildInferenceRequest(deviceType,devices,modelPath);
|
||||||
|
System.out.println("request="+request);
|
||||||
|
|
||||||
|
// 调用Python推理服务
|
||||||
|
InferResponse response = infer(request);
|
||||||
|
System.out.println("推理服务返回结果: " + response);
|
||||||
|
|
||||||
|
// 处理推理结果
|
||||||
|
if (response != null && response.getCode() == 0) {
|
||||||
|
// 重新构建InferResponse对象示例
|
||||||
|
// 1. 从response获取数据
|
||||||
|
int code = response.getCode();
|
||||||
|
String msg = response.getMsg();
|
||||||
|
InferResponse.InferData originalData = response.getData();
|
||||||
|
|
||||||
|
// 2. 重新构建InferData
|
||||||
|
InferResponse.InferData newData = new InferResponse.InferData();
|
||||||
|
newData.setItems(originalData.getItems());
|
||||||
|
newData.setMeta(originalData.getMeta());
|
||||||
|
newData.setFeatures(originalData.getFeatures());
|
||||||
|
newData.setKeff(originalData.getKeff());
|
||||||
|
|
||||||
|
// 3. 构建新的InferResponse
|
||||||
|
InferResponse reconstructedResponse = new InferResponse();
|
||||||
|
reconstructedResponse.setCode(code);
|
||||||
|
reconstructedResponse.setMsg(msg);
|
||||||
|
reconstructedResponse.setData(newData);
|
||||||
|
|
||||||
|
System.out.println("重新构建的response: " + reconstructedResponse);
|
||||||
|
|
||||||
|
// 使用重新构建的response处理结果
|
||||||
|
processInferenceResults(projectId, scenarioId, deviceType, devices, reconstructedResponse);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("推理服务调用失败: " + (response != null ? response.getMsg() : "未知错误"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InferRequest buildInferenceRequest(String deviceType,List<DeviceStepInfo> devices,String modelPath) {
|
||||||
|
InferRequest request = new InferRequest();
|
||||||
|
request.setModelDir(modelPath); // 设置模型路径
|
||||||
|
request.setDeviceType(deviceType);
|
||||||
|
|
||||||
|
// 构建批量推理数据
|
||||||
|
List<Map<String, Object>> batchData = new ArrayList<>();
|
||||||
|
for (DeviceStepInfo device : devices) {
|
||||||
|
Map<String, Object> deviceData = new HashMap<>();
|
||||||
|
deviceData.put("features", device.getProperties());
|
||||||
|
deviceData.put("meta", buildDeviceMeta(device));
|
||||||
|
batchData.add(deviceData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置批量数据到请求中
|
||||||
|
request.setBatch(batchData);
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> buildDeviceMeta(DeviceStepInfo device) {
|
||||||
|
Map<String, Object> meta = new HashMap<>();
|
||||||
|
meta.put("deviceId", device.getDeviceId());
|
||||||
|
meta.put("deviceType", device.getDeviceType());
|
||||||
|
meta.put("step", device.getStep());
|
||||||
|
meta.put("time", device.getTime());
|
||||||
|
return meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processInferenceResults(String projectId, String scenarioId, String deviceType,
|
||||||
|
List<DeviceStepInfo> devices, InferResponse response) {
|
||||||
|
// 处理推理结果,例如写入数据库
|
||||||
|
List<InferResponse.InferItem> items = response.getData().getItems();
|
||||||
|
List<ScenarioResult> inferenceResults = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
InferResponse.InferItem item = items.get(i);
|
||||||
|
//DeviceStepInfo device = devices.get(i);
|
||||||
|
|
||||||
|
ScenarioResult result = new ScenarioResult();
|
||||||
|
//result.put("projectId", projectId);
|
||||||
|
result.setScenarioId(scenarioId);
|
||||||
|
//result.put("deviceType", deviceType);
|
||||||
|
result.setDeviceId((String) item.getMeta().get("deviceId"));
|
||||||
|
result.setKeffValue(item.getKeff());
|
||||||
|
// 将 Map<String,Object> 转为 JSON 字符串后再设置
|
||||||
|
try {
|
||||||
|
Map<String, Object> features = item.getFeatures();
|
||||||
|
String featuresJson = objectMapper.writeValueAsString(features);
|
||||||
|
result.setAttrState(featuresJson);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.setAttrState("{}");
|
||||||
|
}
|
||||||
|
//result.put("meta", item.getMeta());
|
||||||
|
result.setStep((Integer) item.getMeta().get("time"));
|
||||||
|
|
||||||
|
inferenceResults.add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
scenarioResultService.saveBatch(inferenceResults);
|
||||||
|
System.out.println("保存推理结果: " + inferenceResults.size() + " 条记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并的Python推理调用方法
|
||||||
|
public InferResponse infer(InferRequest request) {
|
||||||
|
String url = pythonInferUrl + "/v1/infer" ;
|
||||||
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
HttpEntity<InferRequest> entity = new HttpEntity<>(request, headers);
|
||||||
|
ResponseEntity<InferResponse> response = restTemplate.postForEntity(url, entity, InferResponse.class);
|
||||||
|
return response.getBody();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,4 +35,13 @@ public interface ProjectService extends IService<Project> {
|
|||||||
|
|
||||||
java.util.List<java.util.Map<String, Object>> parseDeviceOrderWithMaterials(String projectId);
|
java.util.List<java.util.Map<String, Object>> parseDeviceOrderWithMaterials(String projectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行项目模拟
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @param scenarioId 情景ID
|
||||||
|
* @param params 模拟参数
|
||||||
|
* @return 模拟结果
|
||||||
|
*/
|
||||||
|
java.util.Map<String, Object> runSimulation(String projectId, String scenarioId, java.util.Map<String, Object> params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,4 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.yfd.business.css.domain.Scenario;
|
import com.yfd.business.css.domain.Scenario;
|
||||||
|
|
||||||
public interface ScenarioService extends IService<Scenario> {
|
public interface ScenarioService extends IService<Scenario> {
|
||||||
|
//根据场景id,获取算法类型
|
||||||
|
String getAlgorithmType(String scenarioId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.yfd.business.css.service.impl;
|
package com.yfd.business.css.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.yfd.business.css.domain.AlgorithmModel;
|
import com.yfd.business.css.domain.AlgorithmModel;
|
||||||
import com.yfd.business.css.mapper.AlgorithmModelMapper;
|
import com.yfd.business.css.mapper.AlgorithmModelMapper;
|
||||||
@ -8,4 +9,14 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AlgorithmModelServiceImpl extends ServiceImpl<AlgorithmModelMapper, AlgorithmModel> implements AlgorithmModelService {
|
public class AlgorithmModelServiceImpl extends ServiceImpl<AlgorithmModelMapper, AlgorithmModel> implements AlgorithmModelService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrentModelPath(String algorithmType, String deviceType) {
|
||||||
|
QueryWrapper<AlgorithmModel> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("algorithm_type", algorithmType)
|
||||||
|
.eq("device_type", deviceType)
|
||||||
|
.eq("is_current", 1); // 当前激活版本
|
||||||
|
AlgorithmModel model = getOne(queryWrapper);
|
||||||
|
return model != null ? model.getModelPath() : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.yfd.business.css.domain.Device;
|
import com.yfd.business.css.domain.Device;
|
||||||
import com.yfd.business.css.domain.Material;
|
import com.yfd.business.css.domain.Material;
|
||||||
@ -17,6 +19,9 @@ import com.yfd.business.css.domain.ScenarioResult;
|
|||||||
import com.yfd.business.css.service.DeviceService;
|
import com.yfd.business.css.service.DeviceService;
|
||||||
import com.yfd.business.css.service.MaterialService;
|
import com.yfd.business.css.service.MaterialService;
|
||||||
import com.yfd.business.css.service.ScenarioService;
|
import com.yfd.business.css.service.ScenarioService;
|
||||||
|
import com.yfd.business.css.service.DeviceInferService;
|
||||||
|
import com.yfd.business.css.utils.DeviceDataParser;
|
||||||
|
import com.yfd.business.css.model.DeviceStepInfo;
|
||||||
import com.yfd.business.css.service.EventService;
|
import com.yfd.business.css.service.EventService;
|
||||||
import com.yfd.business.css.service.ScenarioResultService;
|
import com.yfd.business.css.service.ScenarioResultService;
|
||||||
import com.yfd.business.css.dto.TopologyParseResult;
|
import com.yfd.business.css.dto.TopologyParseResult;
|
||||||
@ -31,8 +36,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
@ -55,6 +59,15 @@ public class ProjectServiceImpl
|
|||||||
private EventService eventService;
|
private EventService eventService;
|
||||||
@Resource
|
@Resource
|
||||||
private ScenarioResultService scenarioResultService;
|
private ScenarioResultService scenarioResultService;
|
||||||
|
@Resource
|
||||||
|
private DeviceInferService deviceInferService;
|
||||||
|
// 通过构造函数注入DeviceDataParser
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final DeviceDataParser deviceDataParser;
|
||||||
|
|
||||||
|
public ProjectServiceImpl(DeviceDataParser deviceDataParser) {
|
||||||
|
this.deviceDataParser = deviceDataParser;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] exportAllProjectsExcel() {
|
public byte[] exportAllProjectsExcel() {
|
||||||
@ -1221,4 +1234,59 @@ public class ProjectServiceImpl
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//运行项目模拟
|
||||||
|
@Override
|
||||||
|
public java.util.Map<String, Object> runSimulation(String projectId, String scenarioId, java.util.Map<String, Object> params) {
|
||||||
|
//1. 校验项目是否存在
|
||||||
|
Project project = this.getOne(new LambdaQueryWrapper<Project>().eq(Project::getProjectId, projectId));
|
||||||
|
if (project == null) throw new IllegalArgumentException("项目不存在");
|
||||||
|
//2. 校验情景是否存在
|
||||||
|
Scenario scenario = scenarioService.getOne(new LambdaQueryWrapper<Scenario>().eq(Scenario::getScenarioId, scenarioId));
|
||||||
|
if (scenario == null) throw new IllegalArgumentException("情景不存在");
|
||||||
|
//获取该情景对应的算法类型
|
||||||
|
String algorithmType = scenario.getAlgorithmType();
|
||||||
|
if (algorithmType == null) throw new IllegalArgumentException("情景未指定算法类型");
|
||||||
|
//3. 校验模拟参数是否完整
|
||||||
|
if (params == null || params.isEmpty()) throw new IllegalArgumentException("模拟参数不能为空");
|
||||||
|
//4. 解析模拟参数,生成模拟数据
|
||||||
|
// 使用 Jackson 将 Map 转为 JSON 字符串
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
String jsonParams;
|
||||||
|
try {
|
||||||
|
jsonParams = objectMapper.writeValueAsString(params);
|
||||||
|
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
|
||||||
|
throw new RuntimeException("模拟参数序列化失败", e);
|
||||||
}
|
}
|
||||||
|
// 解析并按设备类型分组,后续批量推理将依赖此结果
|
||||||
|
System.out.println("projectId="+projectId);
|
||||||
|
System.out.println("scenarioId="+scenarioId);
|
||||||
|
System.out.println("params="+params);
|
||||||
|
System.out.println("jsonParams="+jsonParams);
|
||||||
|
|
||||||
|
jsonParams ="{\"data\":{\"frames\":[{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":160.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":160.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":20.0,\"u_enrichment\":0.01,\"height\":20.0,\"u_concentration\":20.0}},\"step\":0,\"time\":0},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":170.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":170.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":50.0,\"u_enrichment\":0.01,\"height\":50.0,\"u_concentration\":20.0}},\"step\":1,\"time\":2},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":180.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":180.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":70.0,\"u_enrichment\":0.01,\"height\":70.0,\"u_concentration\":20.0}},\"step\":2,\"time\":4},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":190.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":190.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":100.0,\"u_enrichment\":0.01,\"height\":100.0,\"u_concentration\":20.0}},\"step\":3,\"time\":6},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":200.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":200.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":120.0,\"u_enrichment\":0.01,\"height\":120.0,\"u_concentration\":20.0}},\"step\":4,\"time\":8},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":210.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":210.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":150.0,\"u_enrichment\":0.01,\"height\":150.0,\"u_concentration\":20.0}},\"step\":5,\"time\":10},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":220.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":220.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":200.0,\"u_enrichment\":0.01,\"height\":200.0,\"u_concentration\":20.0}},\"step\":6,\"time\":12},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":230.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":230.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":220.0,\"u_enrichment\":0.01,\"height\":220.0,\"u_concentration\":20.0}},\"step\":7,\"time\":14},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":240.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":240.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":250.0,\"u_enrichment\":0.01,\"height\":250.0,\"u_concentration\":20.0}},\"step\":8,\"time\":16},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":250.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":250.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":300.0,\"u_enrichment\":0.01,\"height\":300.0,\"u_concentration\":20.0}},\"step\":9,\"time\":18}],\"generated\":{\"snapshots\":20,\"events\":2},\"projectId\":\"proj-0001-uuid\",\"scenarioId\":\"scen-001-uuid\",\"issues\":[]}}";
|
||||||
|
|
||||||
|
Map<String, List<DeviceStepInfo>> groupedDevices = DeviceDataParser.parseAndGroupDeviceData(jsonParams);
|
||||||
|
if (groupedDevices == null || groupedDevices.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("解析后的设备数据为空,无法进行模拟");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出结果
|
||||||
|
for (Map.Entry<String, List<DeviceStepInfo>> entry : groupedDevices.entrySet()) {
|
||||||
|
System.out.println("Device Type: " + entry.getKey());
|
||||||
|
for (DeviceStepInfo device : entry.getValue()) {
|
||||||
|
System.out.println(" " + device);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
//6. 调用模型进行推理
|
||||||
|
deviceInferService.processDeviceInference(projectId, scenarioId, groupedDevices);
|
||||||
|
|
||||||
|
|
||||||
|
//var res = inferenceService.runInference(projectId, scenarioId, params);
|
||||||
|
//5. 写入结果表
|
||||||
|
//scenarioResultMapper.insertBatch(res);
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,4 +10,12 @@ import org.springframework.stereotype.Service;
|
|||||||
public class ScenarioServiceImpl
|
public class ScenarioServiceImpl
|
||||||
extends ServiceImpl<ScenarioMapper, Scenario>
|
extends ServiceImpl<ScenarioMapper, Scenario>
|
||||||
implements ScenarioService {
|
implements ScenarioService {
|
||||||
|
@Override
|
||||||
|
public String getAlgorithmType(String scenarioId) {
|
||||||
|
Scenario scenario = baseMapper.selectById(scenarioId);
|
||||||
|
if (scenario == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return scenario.getAlgorithmType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,150 @@
|
|||||||
|
package com.yfd.business.css.utils;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.yfd.business.css.model.DeviceStepInfo;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
@Component // 添加注解
|
||||||
|
public class DeviceDataParser {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Map<String, List<DeviceStepInfo>> parseAndGroupDeviceData(String jsonData) {
|
||||||
|
try {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(jsonData);
|
||||||
|
JsonNode framesNode = rootNode.get("data").get("frames");
|
||||||
|
|
||||||
|
List<DeviceStepInfo> allDevices = new ArrayList<>();
|
||||||
|
|
||||||
|
for (JsonNode frameNode : framesNode) {
|
||||||
|
int step = frameNode.get("step").asInt();
|
||||||
|
int time = frameNode.get("time").asInt();
|
||||||
|
JsonNode devicesNode = frameNode.get("devices");
|
||||||
|
|
||||||
|
Iterator<Map.Entry<String, JsonNode>> devices = devicesNode.fields();
|
||||||
|
while (devices.hasNext()) {
|
||||||
|
Map.Entry<String, JsonNode> deviceEntry = devices.next();
|
||||||
|
String deviceId = deviceEntry.getKey();
|
||||||
|
JsonNode deviceInfo = deviceEntry.getValue();
|
||||||
|
|
||||||
|
String deviceType = deviceInfo.get("deviceType").asText();
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
|
||||||
|
Iterator<Map.Entry<String, JsonNode>> fields = deviceInfo.fields();
|
||||||
|
while (fields.hasNext()) {
|
||||||
|
Map.Entry<String, JsonNode> field = fields.next();
|
||||||
|
String fieldName = field.getKey();
|
||||||
|
JsonNode fieldValue = field.getValue();
|
||||||
|
|
||||||
|
if (!"deviceType".equals(fieldName)) {
|
||||||
|
if (fieldValue.isDouble() || fieldValue.isFloat()) {
|
||||||
|
properties.put(fieldName, fieldValue.asDouble());
|
||||||
|
} else if (fieldValue.isInt()) {
|
||||||
|
properties.put(fieldName, fieldValue.asInt());
|
||||||
|
} else {
|
||||||
|
properties.put(fieldName, fieldValue.asText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allDevices.add(new DeviceStepInfo(deviceId, deviceType, properties, step, time));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按设备类型分组
|
||||||
|
return allDevices.stream()
|
||||||
|
.collect(Collectors.groupingBy(DeviceStepInfo::getDeviceType));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// String jsonData = "{\n" +
|
||||||
|
// " \"data\": {\n" +
|
||||||
|
// " \"frames\": [\n" +
|
||||||
|
// " {\n" +
|
||||||
|
// " \"devices\": {\n" +
|
||||||
|
// " \"dev-003-uuid\": {\n" +
|
||||||
|
// " \"deviceType\": \"AnnularTank\",\n" +
|
||||||
|
// " \"diameter\": 160.0,\n" +
|
||||||
|
// " \"pu_isotope\": 0.13,\n" +
|
||||||
|
// " \"pu_concentration\": 20.0,\n" +
|
||||||
|
// " \"height\": 160.0\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " \"dev-002-uuid\": {\n" +
|
||||||
|
// " \"deviceType\": \"CylindricalTank\",\n" +
|
||||||
|
// " \"diameter\": 20.0,\n" +
|
||||||
|
// " \"u_enrichment\": 0.01,\n" +
|
||||||
|
// " \"height\": 20.0,\n" +
|
||||||
|
// " \"u_concentration\": 20.0\n" +
|
||||||
|
// " }\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " \"step\": 0,\n" +
|
||||||
|
// " \"time\": 0\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " {\n" +
|
||||||
|
// " \"devices\": {\n" +
|
||||||
|
// " \"dev-003-uuid\": {\n" +
|
||||||
|
// " \"deviceType\": \"AnnularTank\",\n" +
|
||||||
|
// " \"diameter\": 170.0,\n" +
|
||||||
|
// " \"pu_isotope\": 0.13,\n" +
|
||||||
|
// " \"pu_concentration\": 20.0,\n" +
|
||||||
|
// " \"height\": 170.0\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " \"dev-002-uuid\": {\n" +
|
||||||
|
// " \"deviceType\": \"CylindricalTank\",\n" +
|
||||||
|
// " \"diameter\": 50.0,\n" +
|
||||||
|
// " \"u_enrichment\": 0.01,\n" +
|
||||||
|
// " \"height\": 50.0,\n" +
|
||||||
|
// " \"u_concentration\": 20.0\n" +
|
||||||
|
// " }\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " \"step\": 1,\n" +
|
||||||
|
// " \"time\": 2\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " {\n" +
|
||||||
|
// " \"devices\": {\n" +
|
||||||
|
// " \"dev-003-uuid\": {\n" +
|
||||||
|
// " \"deviceType\": \"AnnularTank\",\n" +
|
||||||
|
// " \"diameter\": 180.0,\n" +
|
||||||
|
// " \"pu_isotope\": 0.13,\n" +
|
||||||
|
// " \"pu_concentration\": 20.0,\n" +
|
||||||
|
// " \"height\": 180.0\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " \"dev-002-uuid\": {\n" +
|
||||||
|
// " \"deviceType\": \"CylindricalTank\",\n" +
|
||||||
|
// " \"diameter\": 70.0,\n" +
|
||||||
|
// " \"u_enrichment\": 0.01,\n" +
|
||||||
|
// " \"height\": 70.0,\n" +
|
||||||
|
// " \"u_concentration\": 20.0\n" +
|
||||||
|
// " }\n" +
|
||||||
|
// " },\n" +
|
||||||
|
// " \"step\": 2,\n" +
|
||||||
|
// " \"time\": 4\n" +
|
||||||
|
// " }\n" +
|
||||||
|
// " ]\n" +
|
||||||
|
// " }\n" +
|
||||||
|
// "}";
|
||||||
|
// String jsonData = "{\"data\":{\"frames\":[{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":160.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":160.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":20.0,\"u_enrichment\":0.01,\"height\":20.0,\"u_concentration\":20.0}},\"step\":0,\"time\":0},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":170.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":170.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":50.0,\"u_enrichment\":0.01,\"height\":50.0,\"u_concentration\":20.0}},\"step\":1,\"time\":2},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":180.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":180.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":70.0,\"u_enrichment\":0.01,\"height\":70.0,\"u_concentration\":20.0}},\"step\":2,\"time\":4},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":190.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":190.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":100.0,\"u_enrichment\":0.01,\"height\":100.0,\"u_concentration\":20.0}},\"step\":3,\"time\":6},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":200.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":200.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":120.0,\"u_enrichment\":0.01,\"height\":120.0,\"u_concentration\":20.0}},\"step\":4,\"time\":8},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":210.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":210.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":150.0,\"u_enrichment\":0.01,\"height\":150.0,\"u_concentration\":20.0}},\"step\":5,\"time\":10},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":220.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":220.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":200.0,\"u_enrichment\":0.01,\"height\":200.0,\"u_concentration\":20.0}},\"step\":6,\"time\":12},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":230.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":230.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":220.0,\"u_enrichment\":0.01,\"height\":220.0,\"u_concentration\":20.0}},\"step\":7,\"time\":14},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":240.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":240.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":250.0,\"u_enrichment\":0.01,\"height\":250.0,\"u_concentration\":20.0}},\"step\":8,\"time\":16},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":250.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":250.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":300.0,\"u_enrichment\":0.01,\"height\":300.0,\"u_concentration\":20.0}},\"step\":9,\"time\":18}],\"generated\":{\"snapshots\":20,\"events\":2},\"projectId\":\"proj-0001-uuid\",\"scenarioId\":\"scen-001-uuid\",\"issues\":[]}}";
|
||||||
|
String jsonData = "{\"data\":{\"frames\":[{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":160.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":160.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":20.0,\"u_enrichment\":0.01,\"height\":20.0,\"u_concentration\":20.0}},\"step\":0,\"time\":0},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":170.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":170.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":50.0,\"u_enrichment\":0.01,\"height\":50.0,\"u_concentration\":20.0}},\"step\":1,\"time\":2},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":180.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":180.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":70.0,\"u_enrichment\":0.01,\"height\":70.0,\"u_concentration\":20.0}},\"step\":2,\"time\":4},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":190.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":190.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":100.0,\"u_enrichment\":0.01,\"height\":100.0,\"u_concentration\":20.0}},\"step\":3,\"time\":6},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":200.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":200.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":120.0,\"u_enrichment\":0.01,\"height\":120.0,\"u_concentration\":20.0}},\"step\":4,\"time\":8},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":210.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":210.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":150.0,\"u_enrichment\":0.01,\"height\":150.0,\"u_concentration\":20.0}},\"step\":5,\"time\":10},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":220.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":220.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":200.0,\"u_enrichment\":0.01,\"height\":200.0,\"u_concentration\":20.0}},\"step\":6,\"time\":12},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":230.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":230.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":220.0,\"u_enrichment\":0.01,\"height\":220.0,\"u_concentration\":20.0}},\"step\":7,\"time\":14},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":240.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":240.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":250.0,\"u_enrichment\":0.01,\"height\":250.0,\"u_concentration\":20.0}},\"step\":8,\"time\":16},{\"devices\":{\"dev-003-uuid\":{\"deviceType\":\"AnnularTank\",\"diameter\":250.0,\"pu_isotope\":0.13,\"pu_concentration\":20.0,\"height\":250.0},\"dev-002-uuid\":{\"deviceType\":\"CylindricalTank\",\"diameter\":300.0,\"u_enrichment\":0.01,\"height\":300.0,\"u_concentration\":20.0}},\"step\":9,\"time\":18}],\"generated\":{\"snapshots\":20,\"events\":2},\"projectId\":\"proj-0001-uuid\",\"scenarioId\":\"scen-001-uuid\",\"issues\":[]}} ";
|
||||||
|
System.out.println("jsonData="+jsonData);
|
||||||
|
Map<String, List<DeviceStepInfo>> groupedDevices = parseAndGroupDeviceData(jsonData);
|
||||||
|
|
||||||
|
// 输出结果
|
||||||
|
for (Map.Entry<String, List<DeviceStepInfo>> entry : groupedDevices.entrySet()) {
|
||||||
|
System.out.println("Device Type: " + entry.getKey());
|
||||||
|
for (DeviceStepInfo device : entry.getValue()) {
|
||||||
|
System.out.println(" " + device);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
com.yfd.business.css.config.BusinessCssAutoConfiguration
|
|
||||||
@ -27,3 +27,6 @@ logging:
|
|||||||
level:
|
level:
|
||||||
root: INFO
|
root: INFO
|
||||||
|
|
||||||
|
python:
|
||||||
|
api:
|
||||||
|
url: http://localhost:8000
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
server:
|
|
||||||
port: 8091
|
|
||||||
spring:
|
|
||||||
application:
|
|
||||||
name: business-css
|
|
||||||
datasource:
|
|
||||||
driver-class-name: org.h2.Driver
|
|
||||||
url: jdbc:h2:mem:cssdb;MODE=MySQL;DB_CLOSE_DELAY=-1
|
|
||||||
username: sa
|
|
||||||
password:
|
|
||||||
sql:
|
|
||||||
init:
|
|
||||||
mode: never
|
|
||||||
mybatis-plus:
|
|
||||||
configuration:
|
|
||||||
map-underscore-to-camel-case: true
|
|
||||||
cache-enabled: false
|
|
||||||
global-config:
|
|
||||||
db-config:
|
|
||||||
id-type: assign_uuid
|
|
||||||
@ -69,9 +69,7 @@ public class SimulationInitTest {
|
|||||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||||
|
|
||||||
String initBody = "{\"startTime\":0,\"endTime\":18,\"step\":2}";
|
String initBody = "{\"startTime\":0,\"endTime\":18,\"step\":2}";
|
||||||
String initResp = mockMvc.perform(MockMvcRequestBuilders.post("/projects/simulation/init")
|
String initResp = mockMvc.perform(MockMvcRequestBuilders.post("/projects/" + projectId + "/scenarios/" + scenarioId + "/simulation/init")
|
||||||
.param("projectId", projectId)
|
|
||||||
.param("scenarioId", scenarioId)
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(initBody))
|
.content(initBody))
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||||
@ -97,9 +95,7 @@ public class SimulationInitTest {
|
|||||||
String projectId = "proj-0001-uuid";
|
String projectId = "proj-0001-uuid";
|
||||||
String scenarioId = "scen-001-uuid";
|
String scenarioId = "scen-001-uuid";
|
||||||
String initBody = "{\"startTime\":0,\"endTime\":10,\"step\":2}";
|
String initBody = "{\"startTime\":0,\"endTime\":10,\"step\":2}";
|
||||||
String initResp = mockMvc.perform(MockMvcRequestBuilders.post("/projects/simulation/init")
|
String initResp = mockMvc.perform(MockMvcRequestBuilders.post("/projects/" + projectId + "/scenarios/" + scenarioId + "/simulation/init")
|
||||||
.param("projectId", projectId)
|
|
||||||
.param("scenarioId", scenarioId)
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.content(initBody))
|
.content(initBody))
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||||
@ -118,35 +114,4 @@ public class SimulationInitTest {
|
|||||||
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0))
|
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0))
|
||||||
.andExpect(MockMvcResultMatchers.jsonPath("$.data.records").isArray());
|
.andExpect(MockMvcResultMatchers.jsonPath("$.data.records").isArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void initSimulation_returnData() throws Exception {
|
|
||||||
String projectId = "proj-0001-uuid";
|
|
||||||
String scenarioId = "scen-001-uuid";
|
|
||||||
String initBody = "{\"startTime\":0,\"endTime\":12,\"step\":3}";
|
|
||||||
String initResp = mockMvc.perform(MockMvcRequestBuilders.post("/projects/simulation/init")
|
|
||||||
.param("projectId", projectId)
|
|
||||||
.param("scenarioId", scenarioId)
|
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
|
||||||
.content(initBody))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0))
|
|
||||||
.andReturn().getResponse().getContentAsString();
|
|
||||||
System.out.println("initResp=" + initResp);
|
|
||||||
JsonNode initNode = objectMapper.readTree(initResp).path("data");
|
|
||||||
int eventsCount = initNode.path("generated").path("events").asInt();
|
|
||||||
int snapshotsCount = initNode.path("generated").path("snapshots").asInt();
|
|
||||||
System.out.println("eventsCount=" + eventsCount + ", snapshotsCount=" + snapshotsCount);
|
|
||||||
String resultResp = mockMvc.perform(MockMvcRequestBuilders.get("/scenario-results/by-scenario")
|
|
||||||
.param("scenarioId", scenarioId)
|
|
||||||
.param("pageNum", "1")
|
|
||||||
.param("pageSize", "20"))
|
|
||||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
|
||||||
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value(0))
|
|
||||||
.andReturn().getResponse().getContentAsString();
|
|
||||||
System.out.println("resultResp=" + resultResp);
|
|
||||||
JsonNode resultNode = objectMapper.readTree(resultResp).path("data").path("records");
|
|
||||||
Assertions.assertTrue(resultNode.isArray());
|
|
||||||
System.out.println("recordsSize=" + resultNode.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import com.yfd.platform.config.bean.LoginProperties;
|
|||||||
import com.yfd.platform.exception.AccessDeniedHandExcetion;
|
import com.yfd.platform.exception.AccessDeniedHandExcetion;
|
||||||
import com.yfd.platform.exception.AuthenticationException;
|
import com.yfd.platform.exception.AuthenticationException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -19,6 +20,9 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
|
// 1. 注入配置项,默认为 false
|
||||||
|
@Value("${security.dev.permit:false}")
|
||||||
|
private boolean devPermit;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
@ -50,8 +54,12 @@ public class SecurityConfig {
|
|||||||
http
|
http
|
||||||
.csrf(csrf -> csrf.disable())
|
.csrf(csrf -> csrf.disable())
|
||||||
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> {
|
||||||
.requestMatchers("/user/login").anonymous()
|
// 如果配置为 true,则允许所有请求
|
||||||
|
if (devPermit) {
|
||||||
|
auth.anyRequest().permitAll();
|
||||||
|
} else {
|
||||||
|
auth.requestMatchers("/user/login").anonymous()
|
||||||
.requestMatchers("/user/code").permitAll()
|
.requestMatchers("/user/code").permitAll()
|
||||||
.requestMatchers(HttpMethod.GET,
|
.requestMatchers(HttpMethod.GET,
|
||||||
"/*.html",
|
"/*.html",
|
||||||
@ -73,8 +81,9 @@ public class SecurityConfig {
|
|||||||
"/avatar/**",
|
"/avatar/**",
|
||||||
"/systemurl/**",
|
"/systemurl/**",
|
||||||
"/api/imageserver/upload").permitAll()
|
"/api/imageserver/upload").permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated();
|
||||||
)
|
}
|
||||||
|
})
|
||||||
.cors(cors -> {});
|
.cors(cors -> {});
|
||||||
|
|
||||||
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|||||||
@ -31,3 +31,4 @@ springdoc:
|
|||||||
swagger-ui:
|
swagger-ui:
|
||||||
enabled: true
|
enabled: true
|
||||||
path: /swagger-ui.html
|
path: /swagger-ui.html
|
||||||
|
|
||||||
|
|||||||
335
logs/business-css.log
Normal file
335
logs/business-css.log
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
2026-01-05T15:20:12.027+08:00 INFO 2372 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 2372 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:20:12.029+08:00 INFO 2372 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:20:14.178+08:00 INFO 2372 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:20:14.194+08:00 INFO 2372 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:20:14.195+08:00 INFO 2372 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:20:14.331+08:00 INFO 2372 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:20:14.331+08:00 INFO 2372 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2255 ms
|
||||||
|
2026-01-05T15:20:14.623+08:00 WARN 2372 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mybatisConfig': Injection of resource dependencies failed
|
||||||
|
2026-01-05T15:20:14.628+08:00 INFO 2372 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:20:14.682+08:00 INFO 2372 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:20:14.708+08:00 ERROR 2372 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
A component required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T15:23:04.333+08:00 INFO 11384 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 11384 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:23:04.336+08:00 INFO 11384 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:23:06.304+08:00 INFO 11384 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:23:06.321+08:00 INFO 11384 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:23:06.321+08:00 INFO 11384 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:23:06.436+08:00 INFO 11384 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:23:06.437+08:00 INFO 11384 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2056 ms
|
||||||
|
2026-01-05T15:23:06.709+08:00 WARN 11384 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'algorithmController' defined in file [E:\projectJava\JavaProjectRepo\business-css\target\classes\com\yfd\business\css\controller\AlgorithmController.class]: Post-processing of merged bean definition failed
|
||||||
|
2026-01-05T15:23:06.713+08:00 INFO 11384 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:23:06.758+08:00 INFO 11384 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:23:06.779+08:00 ERROR 11384 --- [business-css] [main] o.s.boot.SpringApplication : Application run failed
|
||||||
|
|
||||||
|
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'algorithmController' defined in file [E:\projectJava\JavaProjectRepo\business-css\target\classes\com\yfd\business\css\controller\AlgorithmController.class]: Post-processing of merged bean definition failed
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:577) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at com.yfd.business.css.CriticalScenarioApplication.main(CriticalScenarioApplication.java:27) ~[classes/:na]
|
||||||
|
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.yfd.business.css.controller.AlgorithmController] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@5e481248]
|
||||||
|
at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:757) ~[spring-core-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:689) ~[spring-core-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.buildResourceMetadata(CommonAnnotationBeanPostProcessor.java:431) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:412) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:312) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1085) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:574) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
... 15 common frames omitted
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: com/yfd/platform/system/service/IUserService
|
||||||
|
at java.base/java.lang.Class.getDeclaredFields0(Native Method) ~[na:na]
|
||||||
|
at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3299) ~[na:na]
|
||||||
|
at java.base/java.lang.Class.getDeclaredFields(Class.java:2373) ~[na:na]
|
||||||
|
at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:752) ~[spring-core-6.1.8.jar:6.1.8]
|
||||||
|
... 21 common frames omitted
|
||||||
|
Caused by: java.lang.ClassNotFoundException: com.yfd.platform.system.service.IUserService
|
||||||
|
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
|
||||||
|
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
|
||||||
|
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[na:na]
|
||||||
|
... 25 common frames omitted
|
||||||
|
|
||||||
|
2026-01-05T15:23:25.835+08:00 INFO 10632 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 10632 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:23:25.837+08:00 INFO 10632 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:23:27.674+08:00 INFO 10632 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:23:27.693+08:00 INFO 10632 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:23:27.694+08:00 INFO 10632 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:23:27.807+08:00 INFO 10632 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:23:27.808+08:00 INFO 10632 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1929 ms
|
||||||
|
2026-01-05T15:23:28.080+08:00 WARN 10632 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'algorithmController' defined in file [E:\projectJava\JavaProjectRepo\business-css\target\classes\com\yfd\business\css\controller\AlgorithmController.class]: Post-processing of merged bean definition failed
|
||||||
|
2026-01-05T15:23:28.084+08:00 INFO 10632 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:23:28.130+08:00 INFO 10632 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:23:28.150+08:00 ERROR 10632 --- [business-css] [main] o.s.boot.SpringApplication : Application run failed
|
||||||
|
|
||||||
|
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'algorithmController' defined in file [E:\projectJava\JavaProjectRepo\business-css\target\classes\com\yfd\business\css\controller\AlgorithmController.class]: Post-processing of merged bean definition failed
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:577) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.0.jar:3.3.0]
|
||||||
|
at com.yfd.business.css.CriticalScenarioApplication.main(CriticalScenarioApplication.java:27) ~[classes/:na]
|
||||||
|
Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.yfd.business.css.controller.AlgorithmController] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@5e481248]
|
||||||
|
at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:757) ~[spring-core-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:689) ~[spring-core-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.buildResourceMetadata(CommonAnnotationBeanPostProcessor.java:431) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:412) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:312) ~[spring-context-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1085) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:574) ~[spring-beans-6.1.8.jar:6.1.8]
|
||||||
|
... 15 common frames omitted
|
||||||
|
Caused by: java.lang.NoClassDefFoundError: com/yfd/platform/system/service/IUserService
|
||||||
|
at java.base/java.lang.Class.getDeclaredFields0(Native Method) ~[na:na]
|
||||||
|
at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3299) ~[na:na]
|
||||||
|
at java.base/java.lang.Class.getDeclaredFields(Class.java:2373) ~[na:na]
|
||||||
|
at org.springframework.util.ReflectionUtils.getDeclaredFields(ReflectionUtils.java:752) ~[spring-core-6.1.8.jar:6.1.8]
|
||||||
|
... 21 common frames omitted
|
||||||
|
Caused by: java.lang.ClassNotFoundException: com.yfd.platform.system.service.IUserService
|
||||||
|
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
|
||||||
|
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
|
||||||
|
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[na:na]
|
||||||
|
... 25 common frames omitted
|
||||||
|
|
||||||
|
2026-01-05T15:29:34.916+08:00 INFO 30416 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 30416 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:29:34.919+08:00 INFO 30416 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:29:36.946+08:00 INFO 30416 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:29:36.976+08:00 INFO 30416 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:29:36.976+08:00 INFO 30416 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:29:37.100+08:00 INFO 30416 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:29:37.101+08:00 INFO 30416 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2130 ms
|
||||||
|
2026-01-05T15:29:37.366+08:00 WARN 30416 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mybatisConfig': Unsatisfied dependency expressed through field 'mybatisPlusInterceptor': No qualifying bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
|
||||||
|
2026-01-05T15:29:37.370+08:00 INFO 30416 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:29:37.410+08:00 INFO 30416 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:29:37.431+08:00 ERROR 30416 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Field mybatisPlusInterceptor in com.yfd.business.css.config.MybatisConfig required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
The injection point has the following annotations:
|
||||||
|
- @org.springframework.beans.factory.annotation.Autowired(required=true)
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T15:29:50.820+08:00 INFO 6636 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 6636 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:29:50.823+08:00 INFO 6636 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:29:52.756+08:00 INFO 6636 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:29:52.771+08:00 INFO 6636 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:29:52.771+08:00 INFO 6636 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:29:52.914+08:00 INFO 6636 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:29:52.915+08:00 INFO 6636 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2049 ms
|
||||||
|
2026-01-05T15:29:53.173+08:00 WARN 6636 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mybatisConfig': Unsatisfied dependency expressed through field 'mybatisPlusInterceptor': No qualifying bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
|
||||||
|
2026-01-05T15:29:53.177+08:00 INFO 6636 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:29:53.222+08:00 INFO 6636 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:29:53.244+08:00 ERROR 6636 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Field mybatisPlusInterceptor in com.yfd.business.css.config.MybatisConfig required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
The injection point has the following annotations:
|
||||||
|
- @org.springframework.beans.factory.annotation.Autowired(required=true)
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T15:30:03.576+08:00 INFO 22176 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 22176 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:30:03.579+08:00 INFO 22176 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:30:05.318+08:00 INFO 22176 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:30:05.330+08:00 INFO 22176 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:30:05.330+08:00 INFO 22176 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:30:05.460+08:00 INFO 22176 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:30:05.461+08:00 INFO 22176 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1836 ms
|
||||||
|
2026-01-05T15:30:05.727+08:00 WARN 22176 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mybatisConfig': Unsatisfied dependency expressed through field 'mybatisPlusInterceptor': No qualifying bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
|
||||||
|
2026-01-05T15:30:05.730+08:00 INFO 22176 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:30:05.764+08:00 INFO 22176 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:30:05.782+08:00 ERROR 22176 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Field mybatisPlusInterceptor in com.yfd.business.css.config.MybatisConfig required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
The injection point has the following annotations:
|
||||||
|
- @org.springframework.beans.factory.annotation.Autowired(required=true)
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T15:32:03.378+08:00 INFO 9616 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 9616 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:32:03.381+08:00 INFO 9616 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:32:05.424+08:00 INFO 9616 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:32:05.445+08:00 INFO 9616 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:32:05.446+08:00 INFO 9616 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:32:05.578+08:00 INFO 9616 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:32:05.579+08:00 INFO 9616 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2158 ms
|
||||||
|
2026-01-05T15:32:05.864+08:00 WARN 9616 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mybatisConfig': Unsatisfied dependency expressed through field 'mybatisPlusInterceptor': No qualifying bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
|
||||||
|
2026-01-05T15:32:05.868+08:00 INFO 9616 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:32:05.918+08:00 INFO 9616 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:32:05.943+08:00 ERROR 9616 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Field mybatisPlusInterceptor in com.yfd.business.css.config.MybatisConfig required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
The injection point has the following annotations:
|
||||||
|
- @org.springframework.beans.factory.annotation.Autowired(required=true)
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T15:34:01.386+08:00 INFO 18712 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 18712 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T15:34:01.389+08:00 INFO 18712 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T15:34:03.377+08:00 INFO 18712 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T15:34:03.392+08:00 INFO 18712 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T15:34:03.393+08:00 INFO 18712 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T15:34:03.536+08:00 INFO 18712 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T15:34:03.537+08:00 INFO 18712 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2109 ms
|
||||||
|
2026-01-05T15:34:03.793+08:00 WARN 18712 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mybatisConfig': Unsatisfied dependency expressed through field 'mybatisPlusInterceptor': No qualifying bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
|
||||||
|
2026-01-05T15:34:03.797+08:00 INFO 18712 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T15:34:03.838+08:00 INFO 18712 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T15:34:03.860+08:00 ERROR 18712 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Field mybatisPlusInterceptor in com.yfd.business.css.config.MybatisConfig required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
The injection point has the following annotations:
|
||||||
|
- @org.springframework.beans.factory.annotation.Autowired(required=true)
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T17:30:52.702+08:00 INFO 27432 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 27432 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T17:30:52.705+08:00 INFO 27432 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T17:30:54.802+08:00 INFO 27432 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T17:30:54.815+08:00 INFO 27432 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T17:30:54.816+08:00 INFO 27432 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T17:30:54.951+08:00 INFO 27432 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T17:30:54.952+08:00 INFO 27432 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2206 ms
|
||||||
|
2026-01-05T17:30:55.307+08:00 WARN 27432 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mybatisConfig': Injection of resource dependencies failed
|
||||||
|
2026-01-05T17:30:55.310+08:00 INFO 27432 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T17:30:55.353+08:00 INFO 27432 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T17:30:55.377+08:00 ERROR 27432 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
A component required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
|
2026-01-05T17:31:24.083+08:00 INFO 24748 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : Starting CriticalScenarioApplication using Java 17.0.17 with PID 24748 (E:\projectJava\JavaProjectRepo\business-css\target\classes started by Admin in E:\projectJava\JavaProjectRepo)
|
||||||
|
2026-01-05T17:31:24.086+08:00 INFO 24748 --- [business-css] [main] c.y.b.css.CriticalScenarioApplication : The following 2 profiles are active: "framework", "business"
|
||||||
|
2026-01-05T17:31:25.999+08:00 INFO 24748 --- [business-css] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8090 (http)
|
||||||
|
2026-01-05T17:31:26.013+08:00 INFO 24748 --- [business-css] [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
|
||||||
|
2026-01-05T17:31:26.013+08:00 INFO 24748 --- [business-css] [main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.24]
|
||||||
|
2026-01-05T17:31:26.151+08:00 INFO 24748 --- [business-css] [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
|
||||||
|
2026-01-05T17:31:26.152+08:00 INFO 24748 --- [business-css] [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2022 ms
|
||||||
|
2026-01-05T17:31:26.407+08:00 WARN 24748 --- [business-css] [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mybatisConfig': Injection of resource dependencies failed
|
||||||
|
2026-01-05T17:31:26.410+08:00 INFO 24748 --- [business-css] [main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
|
||||||
|
2026-01-05T17:31:26.452+08:00 INFO 24748 --- [business-css] [main] .s.b.a.l.ConditionEvaluationReportLogger :
|
||||||
|
|
||||||
|
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
|
||||||
|
2026-01-05T17:31:26.480+08:00 ERROR 24748 --- [business-css] [main] o.s.b.d.LoggingFailureAnalysisReporter :
|
||||||
|
|
||||||
|
***************************
|
||||||
|
APPLICATION FAILED TO START
|
||||||
|
***************************
|
||||||
|
|
||||||
|
Description:
|
||||||
|
|
||||||
|
A component required a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' that could not be found.
|
||||||
|
|
||||||
|
|
||||||
|
Action:
|
||||||
|
|
||||||
|
Consider defining a bean of type 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor' in your configuration.
|
||||||
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
|
|
||||||
<mirrors>
|
|
||||||
<mirror>
|
|
||||||
<id>aliyunmaven</id>
|
|
||||||
<name>Aliyun Maven</name>
|
|
||||||
<mirrorOf>central</mirrorOf>
|
|
||||||
<url>https://maven.aliyun.com/repository/public</url>
|
|
||||||
</mirror>
|
|
||||||
</mirrors>
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>aliyun</id>
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>central</id>
|
|
||||||
<url>https://repo.maven.apache.org/maven2</url>
|
|
||||||
<releases>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</releases>
|
|
||||||
<snapshots>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</snapshots>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
<pluginRepositories>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>central</id>
|
|
||||||
<url>https://repo.maven.apache.org/maven2</url>
|
|
||||||
<releases>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</releases>
|
|
||||||
<snapshots>
|
|
||||||
<enabled>true</enabled>
|
|
||||||
</snapshots>
|
|
||||||
</pluginRepository>
|
|
||||||
</pluginRepositories>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
<activeProfiles>
|
|
||||||
<activeProfile>aliyun</activeProfile>
|
|
||||||
</activeProfiles>
|
|
||||||
</settings>
|
|
||||||
1
python-ml/__init__.py
Normal file
1
python-ml/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
72
python-ml/app.py
Normal file
72
python-ml/app.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from flask import Flask, request, jsonify
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
from .service import train_one_type, infer_one, infer_batch, train_one_type_from_samples
|
||||||
|
except ImportError:
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.path.dirname(__file__))
|
||||||
|
from service import train_one_type, infer_one, infer_batch, train_one_type_from_samples
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
def ensure_model_dir(device_type, model_dir):
|
||||||
|
root = model_dir if model_dir else os.path.join("models", device_type)
|
||||||
|
return root
|
||||||
|
|
||||||
|
@app.post("/v1/train/<device_type>")
|
||||||
|
def train(device_type):
|
||||||
|
data = request.get_json(force=True)
|
||||||
|
dataset_path = data.get("dataset_path")
|
||||||
|
model_dir = data.get("model_dir")
|
||||||
|
if not dataset_path or not os.path.exists(dataset_path):
|
||||||
|
return jsonify({"code": 1, "msg": "dataset_path not found"}), 400
|
||||||
|
out_dir = ensure_model_dir(device_type, model_dir)
|
||||||
|
res = train_one_type(device_type, dataset_path, out_dir)
|
||||||
|
return jsonify({"code": 0, "msg": "ok", "data": res})
|
||||||
|
|
||||||
|
@app.post("/v1/train/<device_type>/from-samples")
|
||||||
|
def train_from_samples(device_type):
|
||||||
|
data = request.get_json(force=True)
|
||||||
|
samples = data.get("samples")
|
||||||
|
model_dir = data.get("model_dir")
|
||||||
|
if not samples or len(samples) == 0:
|
||||||
|
return jsonify({"code": 1, "msg": "samples required"}), 400
|
||||||
|
feats = []
|
||||||
|
labels = []
|
||||||
|
for s in samples:
|
||||||
|
feats.append(s.get("features"))
|
||||||
|
labels.append(s.get("label"))
|
||||||
|
out_dir = ensure_model_dir(device_type, model_dir)
|
||||||
|
res = train_one_type_from_samples(device_type, feats, labels, out_dir)
|
||||||
|
return jsonify({"code": 0, "msg": "ok", "data": res})
|
||||||
|
|
||||||
|
@app.post("/v1/infer/<device_type>/keff")
|
||||||
|
def infer(device_type):
|
||||||
|
data = request.get_json(force=True)
|
||||||
|
model_dir = data.get("model_dir")
|
||||||
|
out_dir = ensure_model_dir(device_type, model_dir)
|
||||||
|
batch = data.get("batch")
|
||||||
|
features = data.get("features")
|
||||||
|
meta = data.get("meta") or {}
|
||||||
|
if batch and len(batch) > 0:
|
||||||
|
feats_list = []
|
||||||
|
metas = []
|
||||||
|
for s in batch:
|
||||||
|
if isinstance(s, dict) and "features" in s:
|
||||||
|
feats_list.append(s["features"])
|
||||||
|
metas.append(s.get("meta") or {})
|
||||||
|
else:
|
||||||
|
feats_list.append(s)
|
||||||
|
metas.append({})
|
||||||
|
ys = infer_batch(device_type, feats_list, out_dir)
|
||||||
|
items = []
|
||||||
|
for i, y in enumerate(ys):
|
||||||
|
items.append({"meta": metas[i], "features": feats_list[i], "keff": y})
|
||||||
|
return jsonify({"code": 0, "msg": "ok", "data": {"items": items}})
|
||||||
|
if not features:
|
||||||
|
return jsonify({"code": 1, "msg": "features required"}), 400
|
||||||
|
y = infer_one(device_type, features, out_dir)
|
||||||
|
return jsonify({"code": 0, "msg": "ok", "data": {"meta": meta, "features": features, "keff": y}})
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host="0.0.0.0", port=8000, debug=True)
|
||||||
149
python-ml/service.py
Normal file
149
python-ml/service.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
import pickle
|
||||||
|
import numpy as np
|
||||||
|
from sklearn.pipeline import Pipeline
|
||||||
|
from sklearn.preprocessing import StandardScaler
|
||||||
|
from sklearn.gaussian_process import GaussianProcessRegressor
|
||||||
|
from sklearn.gaussian_process.kernels import RBF, RationalQuadratic, ConstantKernel, WhiteKernel
|
||||||
|
from sklearn.model_selection import train_test_split
|
||||||
|
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score, max_error
|
||||||
|
try:
|
||||||
|
from .type_config import load_from_excel, features_to_vector
|
||||||
|
except ImportError:
|
||||||
|
from type_config import load_from_excel, features_to_vector
|
||||||
|
|
||||||
|
"""
|
||||||
|
训练与推理服务方法
|
||||||
|
- build_gpr_model: 构建 GPR 模型
|
||||||
|
- build_pipeline: 构建包含标准化与模型的 Pipeline
|
||||||
|
- compute_metrics: 计算评估指标
|
||||||
|
- train_one_type: 按设备类型训练并保存模型
|
||||||
|
- infer_one: 单条推理
|
||||||
|
- infer_batch: 批量推理
|
||||||
|
"""
|
||||||
|
|
||||||
|
RANDOM_STATE = 42
|
||||||
|
TEST_SIZE = 0.2
|
||||||
|
|
||||||
|
def build_gpr_model():
|
||||||
|
"""构建高斯过程回归模型,含复合核与输出中心化"""
|
||||||
|
kernel = ConstantKernel(1.0) * (0.7 * RBF(1.0) + 0.3 * RationalQuadratic(1.0, 1.0)) + WhiteKernel(1e-5)
|
||||||
|
return GaussianProcessRegressor(kernel=kernel, alpha=0.0, n_restarts_optimizer=5, normalize_y=True, random_state=RANDOM_STATE)
|
||||||
|
|
||||||
|
def build_pipeline():
|
||||||
|
"""构建训练/推理管线:输入标准化 + 模型"""
|
||||||
|
return Pipeline([("scaler", StandardScaler()), ("model", build_gpr_model())])
|
||||||
|
|
||||||
|
def compute_metrics(y_true, y_pred):
|
||||||
|
"""计算回归误差指标:RMSE/MAE/R2/maxe"""
|
||||||
|
return {
|
||||||
|
"rmse": float(np.sqrt(mean_squared_error(y_true, y_pred))),
|
||||||
|
"mae": float(mean_absolute_error(y_true, y_pred)),
|
||||||
|
"r2": float(r2_score(y_true, y_pred)),
|
||||||
|
"maxe": float(max_error(y_true, y_pred))
|
||||||
|
}
|
||||||
|
|
||||||
|
def train_one_type(device_type, dataset_path, model_dir):
|
||||||
|
"""按设备类型训练模型并保存 Pipeline,返回指标与耗时"""
|
||||||
|
X, y = load_from_excel(device_type, dataset_path)
|
||||||
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=TEST_SIZE, random_state=RANDOM_STATE)
|
||||||
|
pipe = build_pipeline()
|
||||||
|
pipe.fit(X_train, y_train)
|
||||||
|
X_all = np.vstack([X_train, X_test])
|
||||||
|
y_all = np.concatenate([y_train, y_test])
|
||||||
|
t0 = time.time()
|
||||||
|
pred_all = pipe.predict(X_all)
|
||||||
|
t1 = time.time()
|
||||||
|
os.makedirs(model_dir, exist_ok=True)
|
||||||
|
model_path = os.path.join(model_dir, "pipeline.pkl")
|
||||||
|
with open(model_path, "wb") as f:
|
||||||
|
pickle.dump(pipe, f)
|
||||||
|
return {"metrics": compute_metrics(y_all, pred_all), "infer_batch_time_sec": float(t1 - t0), "model_path": model_path}
|
||||||
|
|
||||||
|
def infer_one(device_type, features, model_dir):
|
||||||
|
"""加载 Pipeline,按设备类型将特征映射为向量并进行单条推理"""
|
||||||
|
model_path = os.path.join(model_dir, "pipeline.pkl")
|
||||||
|
with open(model_path, "rb") as f:
|
||||||
|
pipe = pickle.load(f)
|
||||||
|
X = features_to_vector(device_type, features)
|
||||||
|
y = pipe.predict(X)
|
||||||
|
return float(y[0])
|
||||||
|
|
||||||
|
def infer_batch(device_type, features_list, model_dir):
|
||||||
|
"""加载 Pipeline,批量将特征映射为向量并进行推理"""
|
||||||
|
model_path = os.path.join(model_dir, "pipeline.pkl")
|
||||||
|
with open(model_path, "rb") as f:
|
||||||
|
pipe = pickle.load(f)
|
||||||
|
Xs = []
|
||||||
|
for feat in features_list:
|
||||||
|
Xs.append(features_to_vector(device_type, feat))
|
||||||
|
X = np.vstack(Xs)
|
||||||
|
ys = pipe.predict(X)
|
||||||
|
return [float(v) for v in ys]
|
||||||
|
|
||||||
|
def train_one_type_from_samples(device_type, features_list, labels, model_dir):
|
||||||
|
"""按设备类型基于样本集合训练模型并保存 Pipeline"""
|
||||||
|
Xs = []
|
||||||
|
for feat in features_list:
|
||||||
|
Xs.append(features_to_vector(device_type, feat))
|
||||||
|
X = np.vstack(Xs)
|
||||||
|
y = np.array(labels, dtype=float)
|
||||||
|
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=TEST_SIZE, random_state=RANDOM_STATE)
|
||||||
|
pipe = build_pipeline()
|
||||||
|
pipe.fit(X_train, y_train)
|
||||||
|
X_all = np.vstack([X_train, X_test])
|
||||||
|
y_all = np.concatenate([y_train, y_test])
|
||||||
|
t0 = time.time()
|
||||||
|
pred_all = pipe.predict(X_all)
|
||||||
|
t1 = time.time()
|
||||||
|
os.makedirs(model_dir, exist_ok=True)
|
||||||
|
model_path = os.path.join(model_dir, "pipeline.pkl")
|
||||||
|
with open(model_path, "wb") as f:
|
||||||
|
pickle.dump(pipe, f)
|
||||||
|
return {"metrics": compute_metrics(y_all, pred_all), "infer_batch_time_sec": float(t1 - t0), "model_path": model_path}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = os.getcwd()
|
||||||
|
tasks = [
|
||||||
|
("cylindrical_tank", os.path.join(root, "circle.xlsx"), os.path.join(root, "models", "cylindrical_tank")),
|
||||||
|
("ring_tank", os.path.join(root, "ring.xlsx"), os.path.join(root, "models", "ring_tank"))
|
||||||
|
]
|
||||||
|
results = {}
|
||||||
|
for dt, ds, md in tasks:
|
||||||
|
if not os.path.exists(ds):
|
||||||
|
print(f"[skip] dataset not found: {ds}")
|
||||||
|
continue
|
||||||
|
res = train_one_type(dt, ds, md)
|
||||||
|
results[dt] = res
|
||||||
|
print(f"[train] {dt} -> {res}")
|
||||||
|
sample_cyl = {"直径": 160, "高度": 160, "铀浓度": 20, "铀富集度": 0.01}
|
||||||
|
cyl_dir = os.path.join(root, "models", "cylindrical_tank")
|
||||||
|
if os.path.exists(os.path.join(cyl_dir, "pipeline.pkl")):
|
||||||
|
y_cyl = infer_one("cylindrical_tank", sample_cyl, cyl_dir)
|
||||||
|
print(f"[infer] cylindrical_tank keff={y_cyl}")
|
||||||
|
sample_ring = {"外径": 70, "高度": 70, "Pu浓度": 40, "Pu240占比": 0.05}
|
||||||
|
ring_dir = os.path.join(root, "models", "ring_tank")
|
||||||
|
if os.path.exists(os.path.join(ring_dir, "pipeline.pkl")):
|
||||||
|
y_ring = infer_one("ring_tank", sample_ring, ring_dir)
|
||||||
|
print(f"[infer] ring_tank keff={y_ring}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tasks = [
|
||||||
|
("cylindrical_tank", "circle.xlsx", os.path.join("models", "cylindrical_tank")),
|
||||||
|
("ring_tank", "ring.xlsx", os.path.join("models", "ring_tank"))
|
||||||
|
]
|
||||||
|
results = {}
|
||||||
|
for t, path, out in tasks:
|
||||||
|
res = train_one_type(t, path, out)
|
||||||
|
results[t] = res
|
||||||
|
print({"train_results": results})
|
||||||
|
sample_cyl = {"直径": 160, "高度": 160, "铀浓度": 20, "铀富集度": 0.01}
|
||||||
|
y_cyl = infer_one("cylindrical_tank", sample_cyl, os.path.join("models", "cylindrical_tank"))
|
||||||
|
sample_ring = {"外径": 70, "高度": 70, "Pu浓度": 40, "Pu240占比": 0.05}
|
||||||
|
y_ring = infer_one("ring_tank", sample_ring, os.path.join("models", "ring_tank"))
|
||||||
|
print({"infer_examples": {"cylindrical_tank": {"features": sample_cyl, "keff": y_cyl},
|
||||||
|
"ring_tank": {"features": sample_ring, "keff": y_ring}}})
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
90
python-ml/type_config.py
Normal file
90
python-ml/type_config.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
def cfg_cylindrical():
|
||||||
|
return {
|
||||||
|
"cols": ["diameter", "height", "fissile_concentration", "isotopic_abundance"],
|
||||||
|
"label": "keff",
|
||||||
|
"aliases": {
|
||||||
|
"直径": "diameter",
|
||||||
|
"高度": "height",
|
||||||
|
"铀浓度": "fissile_concentration",
|
||||||
|
"U浓度": "fissile_concentration",
|
||||||
|
"铀富集度": "isotopic_abundance",
|
||||||
|
"U富集度": "isotopic_abundance",
|
||||||
|
# 兼容旧英文键
|
||||||
|
"u_concentration": "fissile_concentration",
|
||||||
|
"u_enrichment": "isotopic_abundance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def cfg_ring():
|
||||||
|
return {
|
||||||
|
"cols": ["diameter", "height", "fissile_concentration", "isotopic_abundance"],
|
||||||
|
"label": "keff",
|
||||||
|
"aliases": {
|
||||||
|
"外径": "diameter",
|
||||||
|
"高度": "height",
|
||||||
|
"Pu浓度": "fissile_concentration",
|
||||||
|
"Pu240占比": "isotopic_abundance",
|
||||||
|
# 兼容旧英文键
|
||||||
|
"pu_concentration": "fissile_concentration",
|
||||||
|
"pu_isotope": "isotopic_abundance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_CONFIG = {
|
||||||
|
"CylindricalTank": cfg_cylindrical(),
|
||||||
|
"AnnularTank": cfg_ring()
|
||||||
|
}
|
||||||
|
|
||||||
|
def feature_names(device_type):
|
||||||
|
cfg = TYPE_CONFIG[device_type]
|
||||||
|
base = cfg["cols"]
|
||||||
|
if device_type in ("CylindricalTank", "AnnularTank"):
|
||||||
|
derived = [f"{base[0]}*{base[1]}", f"{base[2]}*{base[3]}"]
|
||||||
|
return base + derived
|
||||||
|
return base
|
||||||
|
|
||||||
|
def derive_features(device_type, X):
|
||||||
|
if device_type in ("CylindricalTank", "AnnularTank"):
|
||||||
|
return np.hstack([X, (X[:, 0] * X[:, 1]).reshape(-1, 1), (X[:, 2] * X[:, 3]).reshape(-1, 1)])
|
||||||
|
return X
|
||||||
|
|
||||||
|
def _resolve_col(df, key, aliases):
|
||||||
|
if key in df.columns:
|
||||||
|
return df[key].values
|
||||||
|
for a, k in aliases.items():
|
||||||
|
if k == key and a in df.columns:
|
||||||
|
return df[a].values
|
||||||
|
raise KeyError(key)
|
||||||
|
|
||||||
|
def load_from_excel(device_type, path):
|
||||||
|
cfg = TYPE_CONFIG[device_type]
|
||||||
|
df = pd.read_excel(path)
|
||||||
|
cols = cfg["cols"]
|
||||||
|
aliases = cfg.get("aliases", {})
|
||||||
|
arrs = []
|
||||||
|
for k in cols:
|
||||||
|
v = _resolve_col(df, k, aliases)
|
||||||
|
arrs.append(v.astype(float))
|
||||||
|
X = np.vstack(arrs).T
|
||||||
|
y = df[cfg["label"]].values.astype(float) if cfg["label"] in df.columns else df[cfg["label"]].values.astype(float)
|
||||||
|
Xd = derive_features(device_type, X)
|
||||||
|
return Xd, y
|
||||||
|
|
||||||
|
def features_to_vector(device_type, features):
|
||||||
|
cfg = TYPE_CONFIG[device_type]
|
||||||
|
aliases = cfg.get("aliases", {})
|
||||||
|
vals = []
|
||||||
|
for k in cfg["cols"]:
|
||||||
|
v = features.get(k)
|
||||||
|
if v is None:
|
||||||
|
for a, ck in aliases.items():
|
||||||
|
if ck == k and a in features:
|
||||||
|
v = features[a]
|
||||||
|
break
|
||||||
|
vals.append(float(v))
|
||||||
|
X = np.array(vals, dtype=float).reshape(1, -1)
|
||||||
|
Xd = derive_features(device_type, X)
|
||||||
|
return Xd
|
||||||
52
python_ml/type_config.py
Normal file
52
python_ml/type_config.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
"""
|
||||||
|
类型配置与特征管线
|
||||||
|
职责:
|
||||||
|
- 为不同 device_type 定义输入列与 label 名称
|
||||||
|
- 提供特征衍生(原始列→模型向量)
|
||||||
|
- 支持从 Excel 加载与将字典特征映射为向量
|
||||||
|
"""
|
||||||
|
|
||||||
|
def cfg_cylindrical():
|
||||||
|
return {
|
||||||
|
"cols": ["直径", "高度", "铀浓度", "铀富集度"],
|
||||||
|
"label": "keff"
|
||||||
|
}
|
||||||
|
|
||||||
|
def cfg_ring():
|
||||||
|
return {
|
||||||
|
"cols": ["外径", "高度", "Pu浓度", "Pu240占比"],
|
||||||
|
"label": "keff"
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_CONFIG = {
|
||||||
|
"cylindrical_tank": cfg_cylindrical(),
|
||||||
|
"ring_tank": cfg_ring()
|
||||||
|
}
|
||||||
|
|
||||||
|
def derive_features(device_type, X):
|
||||||
|
if device_type == "cylindrical_tank":
|
||||||
|
return np.hstack([X, (X[:, 0] * X[:, 1]).reshape(-1, 1), (X[:, 2] * X[:, 3]).reshape(-1, 1)])
|
||||||
|
if device_type == "ring_tank":
|
||||||
|
return np.hstack([X, (X[:, 0] * X[:, 1]).reshape(-1, 1), (X[:, 2] * X[:, 3]).reshape(-1, 1)])
|
||||||
|
return X
|
||||||
|
|
||||||
|
def load_from_excel(device_type, path):
|
||||||
|
cfg = TYPE_CONFIG[device_type]
|
||||||
|
df = pd.read_excel(path)
|
||||||
|
X = df[cfg["cols"]].values.astype(float)
|
||||||
|
y = df[cfg["label"]].values.astype(float)
|
||||||
|
Xd = derive_features(device_type, X)
|
||||||
|
return Xd, y
|
||||||
|
|
||||||
|
def features_to_vector(device_type, features):
|
||||||
|
cfg = TYPE_CONFIG[device_type]
|
||||||
|
vals = []
|
||||||
|
for k in cfg["cols"]:
|
||||||
|
v = features.get(k)
|
||||||
|
vals.append(float(v))
|
||||||
|
X = np.array(vals, dtype=float).reshape(1, -1)
|
||||||
|
Xd = derive_features(device_type, X)
|
||||||
|
return Xd
|
||||||
@ -1,4 +0,0 @@
|
|||||||
@echo off
|
|
||||||
set "JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-17.0.17.10-hotspot"
|
|
||||||
set "PATH=%JAVA_HOME%\bin;%PATH%"
|
|
||||||
mvn %*
|
|
||||||
Loading…
Reference in New Issue
Block a user