后端更新

This commit is contained in:
wanxiaoli 2026-03-19 15:09:03 +08:00
parent 666248b402
commit d82e34d803
30 changed files with 344 additions and 80 deletions

View File

@ -15,6 +15,7 @@ import org.springframework.boot.web.servlet.ServletComponentScan;
"com.yfd.platform.system",
"com.yfd.platform.utils",
"com.yfd.platform.component",
"com.yfd.platform.aspect",
"com.yfd.business.css"
},
exclude = {DataSourceAutoConfiguration.class, RedisAutoConfiguration.class}

View File

@ -9,6 +9,7 @@ import com.yfd.business.css.domain.Material;
import com.yfd.business.css.domain.Project;
import com.yfd.business.css.model.*;
import com.yfd.business.css.service.MaterialService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
@ -17,6 +18,7 @@ import java.util.*;
* 仿真模型构建器
* 负责将原始的 Project (Topology) Event 数据解析转换为 SimUnit, SimEvent, SimInfluenceNode
*/
@Slf4j
@Component
public class SimBuilder {
@ -99,6 +101,7 @@ public class SimBuilder {
}
}
} catch (Exception e) {
log.error("Build units failed: {}", e.getMessage(), e);
throw new RuntimeException("Build units failed", e);
}
return units;
@ -175,7 +178,7 @@ public class SimBuilder {
parseCommonSize(sizeNode, staticProps);
}
} catch (Exception e) {
System.err.println("解析Device.size失败" + e.getMessage());
log.warn("解析Device.size失败{}", e.getMessage());
}
}
@ -257,7 +260,7 @@ public class SimBuilder {
}
}
} catch (Exception e) {
// log error
log.error("解析事件失败: {}", e.getMessage(), e);
}
}
return simEvents;
@ -292,6 +295,7 @@ public class SimBuilder {
}
}
} catch (Exception e) {
log.error("Build influence nodes failed: {}", e.getMessage(), e);
throw new RuntimeException("Build influence nodes failed", e);
}
return nodes;

View File

@ -11,6 +11,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import com.yfd.platform.annotation.Log;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -43,6 +44,7 @@ public class AlgorithmController {
return algorithmService.getOne(qw);
}
@Log(value = "新增算法", module = "算法管理")
@PostMapping
@Operation(summary = "新增算法", description = "请求体传入算法对象,返回是否新增成功")
public boolean createAlgorithm(@RequestBody Algorithm algorithm) {
@ -52,6 +54,7 @@ public class AlgorithmController {
return algorithmService.save(algorithm);
}
@Log(value = "修改算法", module = "算法管理")
@PutMapping
@Operation(summary = "修改算法", description = "请求体传入算法对象(需包含主键),返回是否修改成功")
public boolean updateAlgorithm(@RequestBody Algorithm algorithm) {
@ -60,18 +63,21 @@ public class AlgorithmController {
return algorithmService.updateById(algorithm);
}
@Log(value = "删除算法", module = "算法管理")
@DeleteMapping("/{id}")
@Operation(summary = "删除算法(单条)", description = "根据算法ID删除算法")
public boolean deleteAlgorithm(@PathVariable String id) {
return algorithmService.removeById(id);
}
@Log(value = "批量删除算法", module = "算法管理")
@DeleteMapping
@Operation(summary = "删除算法(批量)", description = "请求体传入算法ID列表批量删除算法")
public boolean deleteAlgorithms(@RequestBody List<String> ids) {
return algorithmService.removeByIds(ids);
}
@Log(value = "激活算法", module = "算法管理")
//算法类型激活
@PostMapping("/activate")
@Operation(summary = "激活算法", description = "激活当前算法类型")
@ -85,6 +91,7 @@ public class AlgorithmController {
return algorithmService.updateById(algorithm);
}
@Log(value = "关闭算法", module = "算法管理")
//算法类型关闭
@PostMapping("/unactivate")
@Operation(summary = "关闭算法", description = "关闭当前算法类型")

View File

@ -13,6 +13,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import com.yfd.platform.annotation.Log;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -51,6 +52,7 @@ public class AlgorithmModelController {
return algorithmModelService.getById(id);
}
@Log(value = "新增模型版本", module = "算法模型管理")
@PostMapping
@Operation(summary = "新增模型版本", description = "请求体传入模型版本对象,返回是否新增成功")
public boolean create(@RequestBody AlgorithmModel model) {
@ -60,6 +62,7 @@ public class AlgorithmModelController {
return algorithmModelService.save(model);
}
@Log(value = "修改模型版本", module = "算法模型管理")
@PutMapping
@Operation(summary = "修改模型版本", description = "请求体传入模型版本对象(需包含主键),返回是否修改成功")
public boolean update(@RequestBody AlgorithmModel model) {
@ -68,12 +71,14 @@ public class AlgorithmModelController {
return algorithmModelService.updateById(model);
}
@Log(value = "删除模型版本", module = "算法模型管理")
@DeleteMapping("/{id}")
@Operation(summary = "删除模型版本(单条)", description = "根据模型ID删除模型版本")
public boolean delete(@PathVariable String id) {
return algorithmModelService.removeById(id);
}
@Log(value = "批量删除模型版本", module = "算法模型管理")
@DeleteMapping
@Operation(summary = "删除模型版本(批量)", description = "请求体传入模型ID列表批量删除模型版本")
public boolean deleteBatch(@RequestBody List<String> ids) {
@ -118,6 +123,7 @@ public class AlgorithmModelController {
return algorithmModelService.getOne(qw, false); // 使用 false 避免多条结果时抛出异常虽然正常不应该有多条
}
@Log(value = "激活模型版本", module = "算法模型管理")
//版本激活
@PostMapping("/activate")
@Operation(summary = "激活模型版本", description = "将目标模型版本设为当前,并将同组(算法+设备+材料)其他版本设为非当前")
@ -143,6 +149,7 @@ public class AlgorithmModelController {
return algorithmModelService.updateById(model);
}
@Log(value = "在线训练(Excel)", module = "算法模型管理")
// 在线训练Excel 数据集
@PostMapping("/train/excel")
@Operation(summary = "在线训练Excel", description = "传入算法类型、设备类型与Excel路径训练完成新增模型版本记录可选激活")
@ -216,6 +223,7 @@ public class AlgorithmModelController {
return Map.of("code", 0, "msg", "训练成功", "data", model);
}
@Log(value = "在线训练(样本)", module = "算法模型管理")
// 在线训练样本集合
@PostMapping("/train/samples")
@Operation(summary = "在线训练(样本集合)", description = "传入算法类型、设备类型与样本集,训练完成新增模型版本记录,可选激活")

View File

@ -7,6 +7,7 @@ import com.yfd.business.css.service.CriticalDataService;
import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.annotation.Log;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@ -34,6 +35,7 @@ public class CriticalDataController {
* @param data 临界数据对象
* @return 是否新增成功
*/
@Log(value = "新增临界数据", module = "临界数据管理")
@PostMapping
public boolean create(@RequestBody CriticalData data) {
data.setModifier(currentUsername());
@ -59,6 +61,7 @@ public class CriticalDataController {
* @param data 临界数据对象
* @return 是否修改成功
*/
@Log(value = "修改临界数据", module = "临界数据管理")
@PutMapping
public boolean update(@RequestBody CriticalData data) {
data.setModifier(currentUsername());
@ -73,6 +76,7 @@ public class CriticalDataController {
* @param id 临界数据ID
* @return 是否删除成功
*/
@Log(value = "删除临界数据", module = "临界数据管理")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable String id) {
return criticalDataService.removeById(id);
@ -85,6 +89,7 @@ public class CriticalDataController {
* @param ids 临界数据ID列表
* @return 是否删除成功
*/
@Log(value = "批量删除临界数据", module = "临界数据管理")
@DeleteMapping
public boolean deleteBatch(@RequestBody List<String> ids) {
return criticalDataService.removeByIds(ids);
@ -100,6 +105,7 @@ public class CriticalDataController {
* @param file Excel/CSV 文件
* @return 是否导入成功
*/
@Log(value = "导入临界数据", module = "临界数据管理")
@PostMapping("/import")
public boolean importCriticalData(@RequestParam("file") MultipartFile file,
@RequestParam String deviceType) {

View File

@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import com.yfd.platform.annotation.Log;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import jakarta.annotation.Resource;
@ -31,12 +32,14 @@ public class DeviceController {
* @param device 设备对象
* @return 是否新增成功
*/
@Log(value = "新增设备", module = "设备管理")
@PostMapping
public boolean create(@RequestBody Device device) {
device.setModifier(currentUsername());
return deviceService.createDevice(device);
}
@Log(value = "保存或更新设备", module = "设备管理")
@PostMapping("/saveOrUpdate")
public boolean saveOrUpdate(@RequestBody Device device) {
device.setModifier(currentUsername());
@ -50,6 +53,7 @@ public class DeviceController {
* @param device 设备对象
* @return 是否修改成功
*/
@Log(value = "编辑设备", module = "设备管理")
@PutMapping
public boolean update(@RequestBody Device device) {
device.setModifier(currentUsername());
@ -64,6 +68,7 @@ public class DeviceController {
* @param id 设备ID
* @return 是否删除成功
*/
@Log(value = "删除设备", module = "设备管理")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable String id) {
return deviceService.removeById(id);
@ -76,6 +81,7 @@ public class DeviceController {
* @param ids 设备ID列表
* @return 是否删除成功
*/
@Log(value = "批量删除设备", module = "设备管理")
@DeleteMapping
public boolean deleteBatch(@RequestBody List<String> ids) {
return deviceService.removeByIds(ids);
@ -90,6 +96,7 @@ public class DeviceController {
* @param file Excel/CSV 文件
* @return 是否导入成功
*/
@Log(value = "导入设备", module = "设备管理")
@PostMapping("/import")
public boolean importDevices(@RequestParam("file") MultipartFile file,
@RequestParam String deviceType) {

View File

@ -10,6 +10,7 @@ import jakarta.annotation.Resource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.security.core.Authentication;
import com.yfd.platform.annotation.Log;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -44,6 +45,7 @@ public class EventController {
/**
* 新增始发事件
*/
@Log(value = "新增始发事件", module = "事件管理")
@PostMapping
public ResponseEntity<Map<String, Object>> addEvent(@RequestBody Event event) {
event.setModifier(currentUsername());
@ -64,6 +66,7 @@ public class EventController {
* @param event 事件对象
* @return 修改结果
*/
@Log(value = "修改始发事件", module = "事件管理")
@PutMapping
public boolean update(@RequestBody Event event) {
event.setModifier(currentUsername());
@ -76,6 +79,7 @@ public class EventController {
* @param events
* @return
*/
@Log(value = "批量保存或更新事件", module = "事件管理")
@PostMapping("/batchSave")
@Transactional
public ResponseEntity<Map<String, Object>> batchSaveOrUpdateEvents(@RequestBody List<Event> events) {
@ -112,6 +116,7 @@ public class EventController {
/**
* 修改 Event attr_changes
*/
@Log(value = "修改事件属性变更配置", module = "事件管理")
@PutMapping("/{eventId}/attr-changes")
public ResponseEntity<Map<String, Object>> updateAttrChanges(
@PathVariable String eventId,
@ -169,6 +174,7 @@ public class EventController {
* @param eventId 事件ID
* @return 删除结果
*/
@Log(value = "删除始发事件", module = "事件管理")
@DeleteMapping("/{eventId}")
public ResponseEntity<Map<String, Object>> deleteEvent(@PathVariable String eventId) {
boolean ok = eventService.removeById(eventId);

View File

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import com.yfd.platform.annotation.Log;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import jakarta.annotation.Resource;
@ -32,12 +33,14 @@ public class MaterialController {
* @param material 物料对象
* @return 是否新增成功
*/
@Log(value = "新增物料", module = "物料管理")
@PostMapping
public boolean create(@RequestBody Material material) {
material.setModifier(currentUsername());
return materialService.saveMaterial(material);
}
@Log(value = "保存或更新物料", module = "物料管理")
@PostMapping("/saveOrUpdate")
public boolean saveOrUpdate(@RequestBody Material material) {
material.setModifier(currentUsername());
@ -51,6 +54,7 @@ public class MaterialController {
* @param material 物料对象
* @return 是否修改成功
*/
@Log(value = "编辑物料", module = "物料管理")
@PutMapping
public boolean update(@RequestBody Material material) {
material.setModifier(currentUsername());
@ -65,6 +69,7 @@ public class MaterialController {
* @param id 物料ID
* @return 是否删除成功
*/
@Log(value = "删除物料", module = "物料管理")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable String id) {
return materialService.removeById(id);
@ -77,6 +82,7 @@ public class MaterialController {
* @param ids 物料ID列表
* @return 是否删除成功
*/
@Log(value = "批量删除物料", module = "物料管理")
@DeleteMapping
public boolean deleteBatch(@RequestBody List<String> ids) {
return materialService.removeByIds(ids);
@ -91,6 +97,7 @@ public class MaterialController {
* @param file Excel/CSV 文件
* @return 是否导入成功
*/
@Log(value = "导入物料", module = "物料管理")
@PostMapping("/import")
public boolean importMaterials(@RequestParam("file") MultipartFile file) {
return materialService.importMaterials(file);

View File

@ -9,6 +9,7 @@ import com.yfd.business.css.service.ModelTrainService;
import com.yfd.platform.config.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.yfd.platform.annotation.Log;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
@ -26,6 +27,7 @@ public class ModelTrainController {
/**
* 上传数据集
*/
@Log(value = "上传训练数据集", module = "模型训练")
@PostMapping("/upload")
public ResponseResult upload(@RequestParam("file") MultipartFile file) {
String path = modelTrainService.uploadDataset(file);
@ -35,6 +37,7 @@ public class ModelTrainController {
/**
* 提交训练任务 (支持文件上传和 JSON 参数)
*/
@Log(value = "提交训练任务", module = "模型训练")
@PostMapping("/submit")
public ResponseResult submit(@RequestPart("task") String taskJson,
@RequestPart(value = "file", required = false) MultipartFile file) {
@ -107,6 +110,7 @@ public class ModelTrainController {
/**
* 发布模型
*/
@Log(value = "发布训练模型", module = "模型训练")
@PostMapping("/publish")
public ResponseResult publish(@RequestBody Map<String, String> body) {
String taskId = body.get("taskId");
@ -118,6 +122,7 @@ public class ModelTrainController {
/**
* 删除训练任务
*/
@Log(value = "删除训练任务", module = "模型训练")
@DeleteMapping("/{taskId}")
public ResponseResult delete(@PathVariable String taskId) {
boolean success = modelTrainService.removeById(taskId);

View File

@ -14,6 +14,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import com.yfd.platform.annotation.Log;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import jakarta.annotation.Resource;
@ -40,6 +41,7 @@ public class ProjectController {
* @param project 项目对象
* @return 是否新增成功
*/
@Log(value = "新增项目", module = "项目管理")
@PostMapping
@Operation(summary = "新增项目", description = "请求体传入项目对象,返回是否新增成功")
public boolean create(@RequestBody Project project) {
@ -54,6 +56,7 @@ public class ProjectController {
* @param project 项目对象
* @return 是否修改成功
*/
@Log(value = "修改项目", module = "项目管理")
@PutMapping
@Operation(summary = "修改项目", description = "请求体传入项目对象(需包含主键),返回是否修改成功")
public boolean update(@RequestBody Project project) {
@ -81,6 +84,7 @@ public class ProjectController {
* @param id 项目ID
* @return 是否删除成功
*/
@Log(value = "删除项目", module = "项目管理")
@DeleteMapping("/{id}")
@Operation(summary = "删除项目(单条)", description = "根据项目ID删除项目")
public boolean delete(@PathVariable @Parameter(description = "项目ID", required = true) String id) {
@ -94,6 +98,7 @@ public class ProjectController {
* @param ids 项目ID列表
* @return 是否删除成功
*/
@Log(value = "批量删除项目", module = "项目管理")
@DeleteMapping
@Operation(summary = "删除项目(批量)", description = "请求体传入项目ID列表批量删除项目")
public boolean deleteBatch(@RequestBody List<String> ids) {
@ -108,6 +113,7 @@ public class ProjectController {
* 导出列project_id, code, name, description, topology,created_at, updated_at,modifier
* @return 附件响应文件名为 projects.xlsx
*/
@Log(value = "导出所有项目", module = "项目管理")
@GetMapping("/exportAllExports")
@Operation(summary = "导出所有项目Excel", description = "返回所有项目的 Excel 附件 projects.xlsx")
public ResponseEntity<byte[]> exportAllExports() {
@ -132,6 +138,7 @@ public class ProjectController {
* @param id 项目ID
* @return 附件响应文件名为 project_{id}.xlsx
*/
@Log(value = "导出项目工程", module = "项目管理")
@GetMapping("/{id}/exportProject")
@Operation(summary = "导出项目工程多Sheet", description = "根据项目ID导出工程数据返回 Excel 附件 project_{id}.xlsx")
public ResponseEntity<byte[]> exportProjectExcel(@PathVariable @Parameter(description = "项目ID", required = true) String id) {
@ -185,6 +192,7 @@ public class ProjectController {
* @param requestBody 请求体需包含 topology 字段
* @return 标准响应结构
*/
@Log(value = "更新项目拓扑", module = "项目管理")
@PutMapping("/{id}/topology")
@Operation(summary = "更新项目拓扑结构", description = "请求体需包含合法的 topology JSON对象或字符串")
public ResponseEntity<Map<String, Object>> updateTopology(@PathVariable @Parameter(description = "项目ID", required = true) String id,

View File

@ -8,6 +8,7 @@ import com.yfd.platform.system.service.IUserService;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import com.yfd.platform.annotation.Log;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import jakarta.annotation.Resource;
@ -30,6 +31,7 @@ public class ScenarioController {
* @param scenario 情景对象
* @return 是否新增成功
*/
@Log(value = "新增情景", module = "情景管理")
@PostMapping
public boolean create(@RequestBody Scenario scenario) {
scenario.setModifier(currentUsername());
@ -46,6 +48,7 @@ public class ScenarioController {
* @param scenario 情景对象
* @return 标准响应结构
*/
@Log(value = "新增情景并返回", module = "情景管理")
@PostMapping("/createAndReturn")
public java.util.Map<String, Object> createAndReturn(@RequestBody Scenario scenario) {
scenario.setModifier(currentUsername());
@ -66,6 +69,7 @@ public class ScenarioController {
* @param scenario 情景对象
* @return 是否修改成功
*/
@Log(value = "修改情景", module = "情景管理")
@PutMapping
public boolean update(@RequestBody Scenario scenario) {
scenario.setModifier(currentUsername());
@ -80,6 +84,7 @@ public class ScenarioController {
* @param id 情景ID
* @return 是否删除成功
*/
@Log(value = "删除情景", module = "情景管理")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable String id) {
return scenarioService.removeById(id);
@ -92,6 +97,7 @@ public class ScenarioController {
* @param ids 情景ID列表
* @return 是否删除成功
*/
@Log(value = "批量删除情景", module = "情景管理")
@DeleteMapping
public boolean deleteBatch(@RequestBody List<String> ids) {
return scenarioService.removeByIds(ids);

View File

@ -10,6 +10,7 @@ import com.yfd.business.css.service.SimService;
import com.yfd.business.css.service.SimInferService;
import com.yfd.platform.config.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import com.yfd.platform.annotation.Log;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
@ -37,6 +38,7 @@ public class SimController {
* @param req 请求参数包含 projectId, scenarioId, steps
* @return 仿真结果包含 code, msg, data (data.frames)
*/
@Log(value = "执行仿真计算", module = "仿真计算")
@PostMapping("/run")
public ResponseResult run(@RequestBody Map<String, Object> req) {
String projectId = (String) req.get("projectId");

View File

@ -26,6 +26,16 @@ public interface AlgorithmModelService extends IService<AlgorithmModel> {
*/
String getCurrentModelPath(String algorithmType, String deviceType, String materialType);
/**
* 根据算法类型设备类型材料类型获取当前激活的模型对象
*
* @param algorithmType 算法类型
* @param deviceType 设备类型
* @param materialType 材料类型如Pu/U
* @return 激活版本的模型对象
*/
AlgorithmModel getCurrentModel(String algorithmType, String deviceType, String materialType);
boolean deleteBatchWithCheck(List<String> ids);
}

View File

@ -10,6 +10,7 @@ import com.yfd.business.css.model.InferResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
@ -23,6 +24,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
@Slf4j
@Service
public class DeviceInferService {
@Value("${python.api.url:http://localhost:8000}")
@ -57,8 +59,9 @@ public class DeviceInferService {
// 全局算法类型
String globalAlgorithmType = scenario.getAlgorithmType();
if (globalAlgorithmType == null) {
throw new IllegalArgumentException("场景 " + scenarioId + " 未配置全局算法类型");
if (globalAlgorithmType == null || globalAlgorithmType.isBlank()) {
log.warn("场景 {} 未配置全局算法类型,将默认使用 GPR", scenarioId);
globalAlgorithmType = "GPR";
}
// 解析设备级算法配置
@ -67,7 +70,7 @@ public class DeviceInferService {
try {
deviceAlgoConfig = objectMapper.readValue(scenario.getDeviceAlgoConfig(), new TypeReference<Map<String, String>>() {});
} catch (Exception e) {
System.err.println("解析设备算法配置失败: " + e.getMessage());
log.error("解析设备算法配置失败: {}", e.getMessage(), e);
}
}
@ -105,31 +108,47 @@ public class DeviceInferService {
String currentMaterialType = matEntry.getKey();
List<DeviceStepInfo> batchDevices = matEntry.getValue();
// 获取模型路径根据算法类型设备类型材料类型
System.out.println("Processing inference for algorithmType: " + currentAlgoType +
", deviceType: " + deviceType + ", materialType: " + currentMaterialType);
String modelRelPath = algorithmModelService.getCurrentModelPath(currentAlgoType, deviceType, currentMaterialType);
System.out.println("modelRelPath=" + modelRelPath);
// 获取模型对象根据算法类型设备类型材料类型
log.info("Processing inference for algorithmType: {}, deviceType: {}, materialType: {}", currentAlgoType, deviceType, currentMaterialType);
AlgorithmModel model = algorithmModelService.getCurrentModel(currentAlgoType, deviceType, currentMaterialType);
if (modelRelPath == null) {
System.err.println("Model path not found for algorithmType: " + currentAlgoType +
", deviceType: " + deviceType + ", materialType: " + currentMaterialType);
if (model == null || model.getModelPath() == null) {
log.error("Model path not found for algorithmType: {}, deviceType: {}, materialType: {}", currentAlgoType, deviceType, currentMaterialType);
hasAnyError = true;
continue;
}
String modelRelPath = model.getModelPath();
log.debug("modelRelPath={}", modelRelPath);
// 解析模型的特征映射feature_map_snapshot以进行特征过滤
List<String> requiredFeatures = new ArrayList<>();
if (model.getFeatureMapSnapshot() != null && !model.getFeatureMapSnapshot().isBlank()) {
try {
// 解析 {"features": ["diameter", "height", ...]} 或者直接是一个 List
JsonNode fNode = objectMapper.readTree(model.getFeatureMapSnapshot());
if (fNode.isArray()) {
for (JsonNode node : fNode) requiredFeatures.add(node.asText());
} else if (fNode.has("features") && fNode.get("features").isArray()) {
for (JsonNode node : fNode.get("features")) requiredFeatures.add(node.asText());
}
} catch (Exception e) {
log.warn("解析特征映射快照失败: {}", e.getMessage());
}
}
// 将相对路径转换为绝对路径
String absoluteModelPath = Paths.get(modelRootPath).resolve(modelRelPath).toAbsolutePath().normalize().toString();
System.out.println("Absolute modelPath=" + absoluteModelPath);
log.debug("Absolute modelPath={}", absoluteModelPath);
// 封装推理请求
InferRequest request = buildInferenceRequest(deviceType, batchDevices, absoluteModelPath);
System.out.println("request=" + request);
InferRequest request = buildInferenceRequest(deviceType, batchDevices, absoluteModelPath, requiredFeatures);
log.debug("request={}", request);
try {
// 调用Python推理服务
InferResponse response = infer(request);
System.out.println("推理服务返回结果: code=" + (response != null ? response.getCode() : "null"));
log.info("推理服务返回结果: code={}", (response != null ? response.getCode() : "null"));
// 处理推理结果
if (response != null && response.getCode() == 0) {
@ -149,12 +168,11 @@ public class DeviceInferService {
processInferenceResults(projectId, scenarioId, deviceType, batchDevices, reconstructedResponse);
hasAnySuccess = true;
} else {
System.err.println("推理服务调用失败: " + (response != null ? response.getMsg() : "未知错误"));
log.error("推理服务调用失败: {}", (response != null ? response.getMsg() : "未知错误"));
hasAnyError = true;
}
} catch (Exception e) {
System.err.println("推理异常: " + e.getMessage());
e.printStackTrace();
log.error("推理异常: {}", e.getMessage(), e);
hasAnyError = true;
}
}
@ -167,7 +185,7 @@ public class DeviceInferService {
}
}
private InferRequest buildInferenceRequest(String deviceType,List<DeviceStepInfo> devices,String modelPath) {
private InferRequest buildInferenceRequest(String deviceType,List<DeviceStepInfo> devices,String modelPath, List<String> requiredFeatures) {
InferRequest request = new InferRequest();
request.setModelDir(modelPath); // 设置模型路径
request.setDeviceType(deviceType);
@ -176,7 +194,22 @@ public class DeviceInferService {
List<Map<String, Object>> batchData = new ArrayList<>();
for (DeviceStepInfo device : devices) {
Map<String, Object> deviceData = new HashMap<>();
deviceData.put("features", device.getProperties());
// 特征过滤逻辑
Map<String, Object> allProps = device.getProperties();
Map<String, Object> filteredProps = new HashMap<>();
if (requiredFeatures != null && !requiredFeatures.isEmpty()) {
for (String featureName : requiredFeatures) {
// 如果设备属性中包含模型需要的特征则提取否则填 0 或抛出异常这里选择填 0.0具体看业务要求
filteredProps.put(featureName, allProps.getOrDefault(featureName, 0.0));
}
} else {
// 如果模型没有保存特征快照退退回发送全部属性
filteredProps.putAll(allProps);
}
deviceData.put("features", filteredProps);
deviceData.put("meta", buildDeviceMeta(device));
batchData.add(deviceData);
}
@ -228,7 +261,7 @@ public class DeviceInferService {
scenarioResultService.saveBatch(inferenceResults);
System.out.println("保存推理结果: " + inferenceResults.size() + " 条记录");
log.info("保存推理结果: {} 条记录", inferenceResults.size());
}
// 合并的Python推理调用方法

View File

@ -2,6 +2,7 @@ package com.yfd.business.css.service;
import com.yfd.business.css.domain.Scenario;
import com.yfd.business.css.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@ -14,6 +15,7 @@ import java.util.stream.Collectors;
* 仿真推理服务
* 负责将仿真计算结果 (SimContext) 转换为推理请求并异步调用 Python 推理服务入库
*/
@Slf4j
@Service
public class SimInferService {
@ -79,7 +81,7 @@ public class SimInferService {
}
if (groupedDevices.isEmpty()) {
System.out.println("No device data found for inference.");
log.warn("No device data found for inference. scenarioId: {}", scenarioId);
// 即使没有数据也应该更新状态为完成或者视为正常结束
updateScenarioStatus(scenarioId, "2");
return;
@ -97,10 +99,10 @@ public class SimInferService {
// 简单改进如果 groupedDevices 非空但所有组都因为找不到模型而跳过应该视为失败吗
// 目前策略只要没有抛出未捕获异常就视为 Success
updateScenarioStatus(scenarioId, "2");
log.info("Async inference completed successfully. scenarioId: {}", scenarioId);
} catch (Exception e) {
System.err.println("Async inference failed: " + e.getMessage());
e.printStackTrace();
log.error("Async inference failed. scenarioId: {}, error: {}", scenarioId, e.getMessage(), e);
// 5. 更新状态为失败 (假设 3 代表失败)
updateScenarioStatus(scenarioId, "3");
}
@ -114,7 +116,7 @@ public class SimInferService {
scenario.setUpdatedAt(LocalDateTime.now());
scenarioService.updateById(scenario);
} catch (Exception e) {
System.err.println("Failed to update scenario status to " + status + ": " + e.getMessage());
log.error("Failed to update scenario status to {}. scenarioId: {}, error: {}", status, scenarioId, e.getMessage(), e);
}
}
}

View File

@ -1,6 +1,7 @@
package com.yfd.business.css.service;
import com.yfd.business.css.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@ -11,6 +12,7 @@ import java.util.Map;
* 仿真核心计算引擎
* 负责执行时间步推进处理静态属性事件输入影响传播和强制覆盖
*/
@Slf4j
@Service
public class SimService {
@ -30,6 +32,8 @@ public class SimService {
SimContext ctx = new SimContext();
log.info("Starting simulation... total steps: {}", steps);
// Step 1: 初始化静态基线 (t=0)
// 将所有单元的静态属性写入初始上下文
for (SimUnit unit : units) {
@ -56,6 +60,7 @@ public class SimService {
ctx.snapshot(step);
}
log.info("Simulation finished.");
return ctx;
}

View File

@ -6,11 +6,13 @@ import com.yfd.business.css.domain.AlgorithmModel;
import com.yfd.business.css.mapper.AlgorithmModelMapper;
import com.yfd.business.css.service.AlgorithmModelService;
import com.yfd.business.css.common.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AlgorithmModelServiceImpl extends ServiceImpl<AlgorithmModelMapper, AlgorithmModel> implements AlgorithmModelService {
@ -21,7 +23,7 @@ public class AlgorithmModelServiceImpl extends ServiceImpl<AlgorithmModelMapper,
@Override
public String getCurrentModelPath(String algorithmType, String deviceType, String materialType) {
System.out.println("Querying current model path for algorithmType: " + algorithmType + ", deviceType: " + deviceType + ", materialType: " + materialType);
log.debug("Querying current model path for algorithmType: {}, deviceType: {}, materialType: {}", algorithmType, deviceType, materialType);
QueryWrapper<AlgorithmModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("algorithm_type", algorithmType)
.eq("device_type", deviceType)
@ -39,10 +41,30 @@ public class AlgorithmModelServiceImpl extends ServiceImpl<AlgorithmModelMapper,
List<AlgorithmModel> models = list(queryWrapper);
if (models != null && !models.isEmpty()) {
AlgorithmModel model = models.get(0);
System.out.println("Found model: " + model.getModelPath());
log.debug("Found model: {}", model.getModelPath());
return model.getModelPath();
} else {
System.out.println("Model not found in database.");
log.warn("Model not found in database for algorithmType: {}, deviceType: {}, materialType: {}", algorithmType, deviceType, materialType);
return null;
}
}
@Override
public AlgorithmModel getCurrentModel(String algorithmType, String deviceType, String materialType) {
log.debug("Querying current model for algorithmType: {}, deviceType: {}, materialType: {}", algorithmType, deviceType, materialType);
QueryWrapper<AlgorithmModel> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("algorithm_type", algorithmType)
.eq("device_type", deviceType)
.eq("is_current", 1); // 当前激活版本
if (materialType != null && !materialType.isEmpty()) {
queryWrapper.eq("material_type", materialType);
}
List<AlgorithmModel> models = list(queryWrapper);
if (models != null && !models.isEmpty()) {
return models.get(0);
} else {
return null;
}
}

View File

@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.business.css.domain.Algorithm;
import com.yfd.business.css.mapper.AlgorithmMapper;
import com.yfd.business.css.service.AlgorithmService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class AlgorithmServiceImpl extends ServiceImpl<AlgorithmMapper, Algorithm> implements AlgorithmService {
}

View File

@ -9,6 +9,7 @@ import com.yfd.platform.system.service.IUserService;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.security.core.context.SecurityContextHolder;
@ -30,6 +31,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
public class DeviceServiceImpl
extends ServiceImpl<DeviceMapper, Device>
@ -42,16 +44,21 @@ public class DeviceServiceImpl
public boolean importDevices(MultipartFile file, String deviceType) {
try {
String name = file.getOriginalFilename();
log.info("device import start name={} size={} contentType={}", name, file.getSize(), file.getContentType());
if (name == null) return false;
String lower = name.toLowerCase();
if (lower.endsWith(".xlsx")) {
log.info("device detected type=xlsx");
return importExcel(new XSSFWorkbook(file.getInputStream()), deviceType);
} else if (lower.endsWith(".xls")) {
log.info("device detected type=xls");
return importExcel(new HSSFWorkbook(file.getInputStream()), deviceType);
} else {
log.warn("device unsupported file type name={}", name);
return false;
}
} catch (Exception e) {
log.error("device import failed", e);
return false;
}
}
@ -93,9 +100,15 @@ public class DeviceServiceImpl
private boolean importExcel(Workbook workbook, String deviceType) {
try (Workbook wb = workbook) {
Sheet sheet = wb.getSheetAt(0);
if (sheet == null) return false;
if (sheet == null) {
log.warn("device excel sheet null");
return false;
}
Row headerRow = sheet.getRow(0);
if (headerRow == null) return false;
if (headerRow == null) {
log.warn("device excel header row null");
return false;
}
Map<String, Integer> idx = new HashMap<>();
for (int i = 0; i < headerRow.getLastCellNum(); i++) {
Cell c = headerRow.getCell(i);
@ -103,9 +116,15 @@ public class DeviceServiceImpl
String key = c.getStringCellValue();
if (key != null) idx.put(key.trim().toLowerCase(), i);
}
log.info("device excel header keys={}", idx.keySet());
String[] keys = new String[]{"code","name","size","volume","flow_rate","pulse_velocity"};
List<String> missing = new ArrayList<>();
for (String k : keys) {
if (!idx.containsKey(k)) return false;
if (!idx.containsKey(k)) missing.add(k);
}
if (!missing.isEmpty()) {
log.warn("device excel missing headers={}", missing);
return false;
}
List<Device> devices = new ArrayList<>();
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
@ -123,12 +142,22 @@ public class DeviceServiceImpl
d.setCreatedAt(LocalDateTime.now());
d.setUpdatedAt(LocalDateTime.now());
d.setModifier(currentUsername());
if (isEmpty(d)) continue;
if (isEmpty(d)) {
log.warn("device excel skip empty row={}", r);
continue;
}
devices.add(d);
}
if (devices.isEmpty()) return false;
return this.saveBatch(devices);
log.info("device excel parsed rows={} valid={}", sheet.getLastRowNum(), devices.size());
if (devices.isEmpty()) {
log.warn("device excel parsed list empty");
return false;
}
boolean ok = this.saveBatch(devices);
log.info("device excel saveBatch result={}", ok);
return ok;
} catch (Exception e) {
log.error("device excel import failed", e);
return false;
}
}

View File

@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.business.css.domain.Event;
import com.yfd.business.css.mapper.EventMapper;
import com.yfd.business.css.service.EventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class EventServiceImpl
extends ServiceImpl<EventMapper, Event>

View File

@ -10,6 +10,7 @@ import com.yfd.platform.system.service.IUserService;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -32,6 +33,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class MaterialServiceImpl
extends ServiceImpl<MaterialMapper, Material>
@ -44,16 +46,21 @@ public class MaterialServiceImpl
public boolean importMaterials(MultipartFile file) {
try {
String name = file.getOriginalFilename();
log.info("material import start name={} size={} contentType={}", name, file.getSize(), file.getContentType());
if (name == null) return false;
String lower = name.toLowerCase();
if (lower.endsWith(".xlsx")) {
log.info("material detected type=xlsx");
return importExcel(new XSSFWorkbook(file.getInputStream()));
} else if (lower.endsWith(".xls")) {
log.info("material detected type=xls");
return importExcel(new HSSFWorkbook(file.getInputStream()));
} else {
log.warn("material unsupported file type name={}", name);
return false;
}
} catch (Exception e) {
log.error("material import failed", e);
return false;
}
}
@ -95,9 +102,15 @@ public class MaterialServiceImpl
private boolean importExcel(Workbook workbook) {
try (Workbook wb = workbook) {
Sheet sheet = wb.getSheetAt(0);
if (sheet == null) return false;
if (sheet == null) {
log.warn("material excel sheet null");
return false;
}
Row headerRow = sheet.getRow(0);
if (headerRow == null) return false;
if (headerRow == null) {
log.warn("material excel header row null");
return false;
}
Map<String, Integer> idx = new HashMap<>();
for (int i = 0; i < headerRow.getLastCellNum(); i++) {
Cell c = headerRow.getCell(i);
@ -105,14 +118,20 @@ public class MaterialServiceImpl
String key = c.getStringCellValue();
if (key != null) idx.put(key.trim().toLowerCase(), i);
}
log.info("material excel header keys={}", idx.keySet());
String[] keys = new String[]{
"name","u_concentration","uo2_density","u_enrichment",
"pu_concentration","puo2_density","pu_isotope",
"hno3_acidity","h2c2o4_concentration","organic_ratio",
"moisture_content","custom_attrs"
};
List<String> missing = new ArrayList<>();
for (String k : keys) {
if (!idx.containsKey(k)) return false;
if (!idx.containsKey(k)) missing.add(k);
}
if (!missing.isEmpty()) {
log.warn("material excel missing headers={}", missing);
return false;
}
List<Material> list = new ArrayList<>();
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
@ -135,12 +154,22 @@ public class MaterialServiceImpl
m.setCreatedAt(LocalDateTime.now());
m.setUpdatedAt(LocalDateTime.now());
m.setModifier(currentUsername());
if (isEmpty(m)) continue;
if (isEmpty(m)) {
log.warn("material excel skip empty row={}", r);
continue;
}
list.add(m);
}
if (list.isEmpty()) return false;
return this.saveBatch(list);
log.info("material excel parsed rows={} valid={}", sheet.getLastRowNum(), list.size());
if (list.isEmpty()) {
log.warn("material excel parsed list empty");
return false;
}
boolean ok = this.saveBatch(list);
log.info("material excel saveBatch result={}", ok);
return ok;
} catch (Exception e) {
log.error("material excel import failed", e);
return false;
}
}

View File

@ -11,6 +11,7 @@ import com.yfd.business.css.domain.ModelTrainTask;
import com.yfd.business.css.mapper.ModelTrainTaskMapper;
import com.yfd.business.css.service.AlgorithmModelService;
import com.yfd.business.css.service.ModelTrainService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
@ -36,6 +37,7 @@ import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;
@Slf4j
@Service
public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, ModelTrainTask> implements ModelTrainService {
@ -144,7 +146,7 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
Map<String, Object> params = objectMapper.readValue(task.getTrainParams(), new TypeReference<Map<String, Object>>() {});
request.put("hyperparameters", params);
} catch (Exception e) {
System.err.println("解析训练参数失败,将作为原始字符串发送: " + e.getMessage());
log.error("解析训练参数失败,将作为原始字符串发送: {}", e.getMessage());
request.put("hyperparameters", task.getTrainParams());
}
} else {
@ -162,9 +164,9 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
Map body = response.getBody();
if (body != null) {
try {
System.out.println("训练服务响应: " + objectMapper.writeValueAsString(body));
log.debug("训练服务响应: {}", objectMapper.writeValueAsString(body));
} catch (JsonProcessingException ignored) {
System.out.println("训练服务响应: " + body);
log.debug("训练服务响应: {}", body);
}
Object codeObj = body.get("code");
Integer code = null;
@ -183,7 +185,7 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
return;
}
}
System.out.println("训练任务提交成功: " + task.getTaskId());
log.info("训练任务提交成功: {}", task.getTaskId());
} else {
task.setStatus("Failed");
task.setErrorLog("提交训练任务失败: " + response.getStatusCode());
@ -194,7 +196,7 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
task.setStatus("Failed");
task.setErrorLog("调用 Python 服务异常: " + e.getMessage());
this.updateById(task);
e.printStackTrace();
log.error("调用 Python 训练服务异常: {}", e.getMessage(), e);
}
}
@ -285,7 +287,7 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
}
}
} catch (Exception e) {
System.err.println("同步任务状态失败: " + e.getMessage());
log.error("同步任务状态失败: {}", e.getMessage(), e);
}
}
@ -377,7 +379,7 @@ public class ModelTrainServiceImpl extends ServiceImpl<ModelTrainTaskMapper, Mod
}
} catch (Exception e) {
// 附加文件复制失败不应阻断发布主流程仅记录日志
System.err.println("复制附加训练文件失败: " + e.getMessage());
log.warn("复制附加训练文件失败: {}", e.getMessage());
}
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.business.css.domain.Project;
import com.yfd.business.css.mapper.ProjectMapper;
import com.yfd.business.css.service.ProjectService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
@ -45,6 +46,7 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.time.format.DateTimeFormatter;
@Slf4j
@Service
public class ProjectServiceImpl
extends ServiceImpl<ProjectMapper, Project>
@ -73,6 +75,7 @@ public class ProjectServiceImpl
@Override
public byte[] exportAllProjectsExcel() {
log.info("exportAllProjectsExcel start");
try (Workbook wb = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream()) {
List<Project> list = this.list(new QueryWrapper<Project>().orderByDesc("created_at"));
Sheet sheet = wb.createSheet("projects");
@ -96,6 +99,7 @@ public class ProjectServiceImpl
wb.write(out);
return out.toByteArray();
} catch (Exception e) {
log.error("exportAllProjectsExcel error", e);
throw new RuntimeException(e);
}
}
@ -107,6 +111,7 @@ public class ProjectServiceImpl
* @return TopologyParseResult
*/
public TopologyParseResult parseTopology(String projectId) {
log.info("parseTopology start projectId={}", projectId);
try {
Project p = this.getById(projectId);
TopologyParseResult r = new TopologyParseResult();
@ -253,6 +258,7 @@ public class ProjectServiceImpl
r.setEdgeCount(edges.size());
return r;
} catch (Exception e) {
log.error("parseTopology error projectId={}", projectId, e);
throw new RuntimeException(e);
}
}
@ -369,6 +375,7 @@ public class ProjectServiceImpl
@Override
public List<Device> parseDeviceOrder(String projectId) {
log.info("parseDeviceOrder start projectId={}", projectId);
try {
Project p = this.getById(projectId);
List<Device> devices = new ArrayList<>();
@ -394,6 +401,7 @@ public class ProjectServiceImpl
}
return devices;
} catch (Exception e) {
log.error("parseDeviceOrder error projectId={}", projectId, e);
throw new RuntimeException(e);
}
}
@ -405,6 +413,7 @@ public class ProjectServiceImpl
* @return Map 视图对象
*/
public Map<String, Object> parseCanvasView(String projectId) {
log.info("parseCanvasView start projectId={}", projectId);
try {
Project p = this.getById(projectId);
Map<String, Object> res = new HashMap<>();
@ -511,12 +520,14 @@ public class ProjectServiceImpl
}
return res;
} catch (Exception e) {
log.error("parseCanvasView error projectId={}", projectId, e);
throw new RuntimeException(e);
}
}
@Override
public List<Map<String, Object>> parseDeviceOrderWithMaterials(String projectId) {
log.info("parseDeviceOrderWithMaterials start projectId={}", projectId);
try {
Project p = this.getById(projectId);
List<Map<String, Object>> out = new ArrayList<>();
@ -607,12 +618,14 @@ public class ProjectServiceImpl
}
return out;
} catch (Exception e) {
log.error("parseDeviceOrderWithMaterials error projectId={}", projectId, e);
throw new RuntimeException(e);
}
}
@Override
public Map<String, Object> initSimulation(String projectId, String scenarioId, Map<String, Object> params) {
log.info("initSimulation start projectId={} scenarioId={}", projectId, scenarioId);
//改变场景状态
Scenario scenario = new Scenario();
scenario.setScenarioId(scenarioId);
@ -767,6 +780,7 @@ public class ProjectServiceImpl
out.put("frames", frames);
return out;
} catch (Exception ex) {
log.error("initSimulation error projectId={} scenarioId={}", projectId, scenarioId, ex);
issues.add("初始化失败:" + ex.getMessage());
out.put("generated", Map.of("events", 0, "snapshots", 0));
out.put("frames", frames);
@ -1297,6 +1311,7 @@ public class ProjectServiceImpl
//运行项目模拟
@Override
public java.util.Map<String, Object> runSimulation(String projectId, String scenarioId, java.util.Map<String, Object> params) {
log.info("runSimulation start projectId={} scenarioId={}", projectId, scenarioId);
//1. 校验项目是否存在
Project project = this.getOne(new LambdaQueryWrapper<Project>().eq(Project::getProjectId, projectId));
if (project == null) throw new IllegalArgumentException("项目不存在");
@ -1318,10 +1333,10 @@ public class ProjectServiceImpl
throw new RuntimeException("模拟参数序列化失败", e);
}
// 解析并按设备类型分组后续批量推理将依赖此结果
System.out.println("projectId="+projectId);
System.out.println("scenarioId="+scenarioId);
System.out.println("params="+params);
System.out.println("jsonParams="+jsonParams);
log.debug("projectId={}", projectId);
log.debug("scenarioId={}", scenarioId);
log.debug("params={}", params);
log.debug("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\":[]}}";
@ -1332,11 +1347,10 @@ public class ProjectServiceImpl
// 输出结果
for (Map.Entry<String, List<DeviceStepInfo>> entry : groupedDevices.entrySet()) {
System.out.println("Device Type: " + entry.getKey());
log.debug("Device Type: {}", entry.getKey());
for (DeviceStepInfo device : entry.getValue()) {
System.out.println(" " + device);
log.debug(" {}", device);
}
System.out.println();
}
//6. 调用模型进行推理,把结果写入推理结果表
deviceInferService.processDeviceInference(projectId, scenarioId, groupedDevices);

View File

@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.business.css.domain.ScenarioResult;
import com.yfd.business.css.mapper.ScenarioResultMapper;
import com.yfd.business.css.service.ScenarioResultService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class ScenarioResultServiceImpl
extends ServiceImpl<ScenarioResultMapper, ScenarioResult>

View File

@ -4,16 +4,20 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.business.css.domain.Scenario;
import com.yfd.business.css.mapper.ScenarioMapper;
import com.yfd.business.css.service.ScenarioService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class ScenarioServiceImpl
extends ServiceImpl<ScenarioMapper, Scenario>
implements ScenarioService {
@Override
public String getAlgorithmType(String scenarioId) {
log.debug("getAlgorithmType for scenarioId={}", scenarioId);
Scenario scenario = baseMapper.selectById(scenarioId);
if (scenario == null) {
log.warn("getAlgorithmType scenario not found id={}", scenarioId);
return null;
}
return scenario.getAlgorithmType();

View File

@ -3,20 +3,24 @@ package com.yfd.business.css.service.impl;
import com.yfd.business.css.model.SimulationRequest;
import com.yfd.business.css.model.SimulationResult;
import com.yfd.business.css.service.SimulationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.Instant;
@Slf4j
@Service
public class SimulationServiceImpl implements SimulationService {
@Override
public SimulationResult runSimulation(SimulationRequest request) {
log.info("SimulationServiceImpl runSimulation start request={}", request);
// TODO: 引入 framework 公共模块的算法与工具进行真实计算
SimulationResult result = new SimulationResult();
result.setScenarioName(request.getScenarioName());
result.setStartTime(Instant.now().toString());
result.setStatus("SUCCESS");
result.setSummary("占位结果:根据输入参数完成快速估算");
log.info("SimulationServiceImpl runSimulation finish status={}", result.getStatus());
return result;
}
}

View File

@ -353,6 +353,9 @@
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>

View File

@ -75,9 +75,21 @@ public class LogAspect {
SysLog log = new SysLog("INFO");
currentTime.remove();
HttpServletRequest request = RequestHolder.getHttpServletRequest();
// 修复不直接依赖 userService.getNameInfo()防止匿名用户转换异常
String nickname = "匿名用户";
String username = getUsername(); // 调用本类包装好的获取用户名方法
if (StringUtils.isNotBlank(username)) {
try {
Map<String, String> nameInfo = userService.getNameInfo();
String nickname = nameInfo.get("nickname");
String username = nameInfo.get("username");
nickname = nameInfo.get("nickname");
username = nameInfo.get("username");
} catch (Exception e) {
// 如果发生异常比如不是 UsernamePasswordAuthenticationToken则回退使用 username
nickname = username;
}
}
sysLogService.save(nickname, username, StringUtils.getBrowser(request),
StringUtils.getIp(request), joinPoint, log);
return result;

View File

@ -69,35 +69,56 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
***********************************/
@Override
public String getUsername() {
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
try {
Object auth = SecurityContextHolder.getContext().getAuthentication();
if (auth instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) auth;
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
String acountname =
loginuser.getUser().getNickname();
return acountname;
//return "admin";
return loginuser.getUser().getNickname();
}
} catch (Exception e) {
// ignore
}
return "anonymous";
}
@Override
public Map<String, String> getNameInfo() {
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
Map<String, String> map = new HashMap<>();
try {
Object auth = SecurityContextHolder.getContext().getAuthentication();
if (auth instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) auth;
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
String nickname = loginuser.getUser().getNickname();
String username = loginuser.getUser().getUsername();
Map<String, String> map = new HashMap<>();
map.put("nickname", nickname);
map.put("username", username);
} else {
map.put("nickname", "匿名用户");
map.put("username", "anonymous");
}
} catch (Exception e) {
map.put("nickname", "匿名用户");
map.put("username", "anonymous");
}
return map;
}
@Override
public SysUser getUserInfo() {
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
try {
Object auth = SecurityContextHolder.getContext().getAuthentication();
if (auth instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) auth;
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
return loginuser.getUser();
}
} catch (Exception e) {
// ignore
}
return null;
}
@Override
public ResponseResult getLoginUserInfo() {

View File

@ -2,7 +2,8 @@
<configuration scan="true" scanPeriod="60 seconds">
<!-- 通用变量 -->
<property name="LOG_PATH" value="logs"/>
<property name="LOG_FILE" value="platform"/>
<!-- 从 application.yml 读取 spring.application.name如果没有则默认叫 platform -->
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="platform"/>
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- 控制台输出:强制 UTF-8 编码 -->
@ -15,13 +16,13 @@
<!-- 文件输出滚动日志UTF-8 编码 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${LOG_FILE}.log</file>
<file>${LOG_PATH}/${APP_NAME}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>
<fileNamePattern>${LOG_PATH}/${APP_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>