From d82e34d803db994a0fbd762c162be65a689bb07a Mon Sep 17 00:00:00 2001 From: wanxiaoli Date: Thu, 19 Mar 2026 15:09:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../css/CriticalScenarioApplication.java | 1 + .../yfd/business/css/build/SimBuilder.java | 8 +- .../css/controller/AlgorithmController.java | 7 ++ .../controller/AlgorithmModelController.java | 8 ++ .../controller/CriticalDataController.java | 6 ++ .../css/controller/DeviceController.java | 7 ++ .../css/controller/EventController.java | 6 ++ .../css/controller/MaterialController.java | 7 ++ .../css/controller/ModelTrainController.java | 5 ++ .../css/controller/ProjectController.java | 8 ++ .../css/controller/ScenarioController.java | 6 ++ .../css/controller/SimController.java | 2 + .../css/service/AlgorithmModelService.java | 10 +++ .../css/service/DeviceInferService.java | 75 +++++++++++++------ .../business/css/service/SimInferService.java | 10 ++- .../yfd/business/css/service/SimService.java | 5 ++ .../impl/AlgorithmModelServiceImpl.java | 28 ++++++- .../service/impl/AlgorithmServiceImpl.java | 2 + .../css/service/impl/DeviceServiceImpl.java | 41 ++++++++-- .../css/service/impl/EventServiceImpl.java | 2 + .../css/service/impl/MaterialServiceImpl.java | 41 ++++++++-- .../service/impl/ModelTrainServiceImpl.java | 16 ++-- .../css/service/impl/ProjectServiceImpl.java | 28 +++++-- .../impl/ScenarioResultServiceImpl.java | 2 + .../css/service/impl/ScenarioServiceImpl.java | 4 + .../service/impl/SimulationServiceImpl.java | 4 + framework/pom.xml | 3 + .../com/yfd/platform/aspect/LogAspect.java | 18 ++++- .../system/service/impl/UserServiceImpl.java | 57 +++++++++----- .../src/main/resources/logback-spring.xml | 7 +- 30 files changed, 344 insertions(+), 80 deletions(-) diff --git a/business-css/src/main/java/com/yfd/business/css/CriticalScenarioApplication.java b/business-css/src/main/java/com/yfd/business/css/CriticalScenarioApplication.java index b536a10..fa78bca 100644 --- a/business-css/src/main/java/com/yfd/business/css/CriticalScenarioApplication.java +++ b/business-css/src/main/java/com/yfd/business/css/CriticalScenarioApplication.java @@ -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} diff --git a/business-css/src/main/java/com/yfd/business/css/build/SimBuilder.java b/business-css/src/main/java/com/yfd/business/css/build/SimBuilder.java index 779abbe..3c8477d 100644 --- a/business-css/src/main/java/com/yfd/business/css/build/SimBuilder.java +++ b/business-css/src/main/java/com/yfd/business/css/build/SimBuilder.java @@ -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; diff --git a/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java b/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java index 4865fb8..1af3fb7 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java @@ -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 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 = "关闭当前算法类型") diff --git a/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmModelController.java b/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmModelController.java index 31bbb73..fd38b78 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmModelController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmModelController.java @@ -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 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 = "传入算法类型、设备类型与样本集,训练完成新增模型版本记录,可选激活") diff --git a/business-css/src/main/java/com/yfd/business/css/controller/CriticalDataController.java b/business-css/src/main/java/com/yfd/business/css/controller/CriticalDataController.java index e11a5d2..0a1cf2f 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/CriticalDataController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/CriticalDataController.java @@ -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 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) { diff --git a/business-css/src/main/java/com/yfd/business/css/controller/DeviceController.java b/business-css/src/main/java/com/yfd/business/css/controller/DeviceController.java index 44ee2d6..1af1b1c 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/DeviceController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/DeviceController.java @@ -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 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) { diff --git a/business-css/src/main/java/com/yfd/business/css/controller/EventController.java b/business-css/src/main/java/com/yfd/business/css/controller/EventController.java index bd4197c..550ad41 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/EventController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/EventController.java @@ -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> 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> batchSaveOrUpdateEvents(@RequestBody List events) { @@ -112,6 +116,7 @@ public class EventController { /** * 修改 Event 的 attr_changes */ + @Log(value = "修改事件属性变更配置", module = "事件管理") @PutMapping("/{eventId}/attr-changes") public ResponseEntity> updateAttrChanges( @PathVariable String eventId, @@ -169,6 +174,7 @@ public class EventController { * @param eventId 事件ID * @return 删除结果 */ + @Log(value = "删除始发事件", module = "事件管理") @DeleteMapping("/{eventId}") public ResponseEntity> deleteEvent(@PathVariable String eventId) { boolean ok = eventService.removeById(eventId); diff --git a/business-css/src/main/java/com/yfd/business/css/controller/MaterialController.java b/business-css/src/main/java/com/yfd/business/css/controller/MaterialController.java index 6b70f45..906d2ad 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/MaterialController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/MaterialController.java @@ -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 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); diff --git a/business-css/src/main/java/com/yfd/business/css/controller/ModelTrainController.java b/business-css/src/main/java/com/yfd/business/css/controller/ModelTrainController.java index dc4e24e..3944edd 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/ModelTrainController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/ModelTrainController.java @@ -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 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); diff --git a/business-css/src/main/java/com/yfd/business/css/controller/ProjectController.java b/business-css/src/main/java/com/yfd/business/css/controller/ProjectController.java index 98b27a9..64df1e1 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/ProjectController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/ProjectController.java @@ -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 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 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 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> updateTopology(@PathVariable @Parameter(description = "项目ID", required = true) String id, diff --git a/business-css/src/main/java/com/yfd/business/css/controller/ScenarioController.java b/business-css/src/main/java/com/yfd/business/css/controller/ScenarioController.java index 03b908c..3c8f9e5 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/ScenarioController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/ScenarioController.java @@ -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 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 ids) { return scenarioService.removeByIds(ids); diff --git a/business-css/src/main/java/com/yfd/business/css/controller/SimController.java b/business-css/src/main/java/com/yfd/business/css/controller/SimController.java index f03c1d0..ee5da1b 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/SimController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/SimController.java @@ -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 req) { String projectId = (String) req.get("projectId"); diff --git a/business-css/src/main/java/com/yfd/business/css/service/AlgorithmModelService.java b/business-css/src/main/java/com/yfd/business/css/service/AlgorithmModelService.java index be82b7a..de243d2 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/AlgorithmModelService.java +++ b/business-css/src/main/java/com/yfd/business/css/service/AlgorithmModelService.java @@ -26,6 +26,16 @@ public interface AlgorithmModelService extends IService { */ 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 ids); } diff --git a/business-css/src/main/java/com/yfd/business/css/service/DeviceInferService.java b/business-css/src/main/java/com/yfd/business/css/service/DeviceInferService.java index c69b333..317af6e 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/DeviceInferService.java +++ b/business-css/src/main/java/com/yfd/business/css/service/DeviceInferService.java @@ -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>() {}); } 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 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 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 devices,String modelPath) { + private InferRequest buildInferenceRequest(String deviceType,List devices,String modelPath, List requiredFeatures) { InferRequest request = new InferRequest(); request.setModelDir(modelPath); // 设置模型路径 request.setDeviceType(deviceType); @@ -176,7 +194,22 @@ public class DeviceInferService { List> batchData = new ArrayList<>(); for (DeviceStepInfo device : devices) { Map deviceData = new HashMap<>(); - deviceData.put("features", device.getProperties()); + + // 特征过滤逻辑 + Map allProps = device.getProperties(); + Map 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推理调用方法 diff --git a/business-css/src/main/java/com/yfd/business/css/service/SimInferService.java b/business-css/src/main/java/com/yfd/business/css/service/SimInferService.java index 75756a0..bf4f638 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/SimInferService.java +++ b/business-css/src/main/java/com/yfd/business/css/service/SimInferService.java @@ -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); } } } diff --git a/business-css/src/main/java/com/yfd/business/css/service/SimService.java b/business-css/src/main/java/com/yfd/business/css/service/SimService.java index f93ddee..123dc4c 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/SimService.java +++ b/business-css/src/main/java/com/yfd/business/css/service/SimService.java @@ -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; } diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmModelServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmModelServiceImpl.java index d1e343e..5d04994 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmModelServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmModelServiceImpl.java @@ -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 implements AlgorithmModelService { @@ -21,7 +23,7 @@ public class AlgorithmModelServiceImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("algorithm_type", algorithmType) .eq("device_type", deviceType) @@ -39,10 +41,30 @@ public class AlgorithmModelServiceImpl extends ServiceImpl 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 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 models = list(queryWrapper); + if (models != null && !models.isEmpty()) { + return models.get(0); + } else { return null; } } diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmServiceImpl.java index 6c01adb..b58fd6b 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/AlgorithmServiceImpl.java @@ -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 implements AlgorithmService { } \ No newline at end of file diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/DeviceServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/DeviceServiceImpl.java index 921fe5e..c467946 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/DeviceServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/DeviceServiceImpl.java @@ -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 @@ -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 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 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 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; } } diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/EventServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/EventServiceImpl.java index 6261a7e..868f7a7 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/EventServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/EventServiceImpl.java @@ -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 diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/MaterialServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/MaterialServiceImpl.java index 141dc0c..a59b359 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/MaterialServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/MaterialServiceImpl.java @@ -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 @@ -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 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 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 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; } } diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/ModelTrainServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/ModelTrainServiceImpl.java index c1c9b53..22f19fc 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/ModelTrainServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/ModelTrainServiceImpl.java @@ -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 implements ModelTrainService { @@ -144,7 +146,7 @@ public class ModelTrainServiceImpl extends ServiceImpl params = objectMapper.readValue(task.getTrainParams(), new TypeReference>() {}); 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 @@ -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 list = this.list(new QueryWrapper().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 parseDeviceOrder(String projectId) { + log.info("parseDeviceOrder start projectId={}", projectId); try { Project p = this.getById(projectId); List 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 parseCanvasView(String projectId) { + log.info("parseCanvasView start projectId={}", projectId); try { Project p = this.getById(projectId); Map 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> parseDeviceOrderWithMaterials(String projectId) { + log.info("parseDeviceOrderWithMaterials start projectId={}", projectId); try { Project p = this.getById(projectId); List> 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 initSimulation(String projectId, String scenarioId, Map 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 runSimulation(String projectId, String scenarioId, java.util.Map params) { + log.info("runSimulation start projectId={} scenarioId={}", projectId, scenarioId); //1. 校验项目是否存在 Project project = this.getOne(new LambdaQueryWrapper().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> 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); diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioResultServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioResultServiceImpl.java index 61fe0e3..5871fb8 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioResultServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioResultServiceImpl.java @@ -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 diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioServiceImpl.java index dcef204..3b0b1e7 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/ScenarioServiceImpl.java @@ -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 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(); diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/SimulationServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/SimulationServiceImpl.java index ae1c91a..808cd84 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/SimulationServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/SimulationServiceImpl.java @@ -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; } } \ No newline at end of file diff --git a/framework/pom.xml b/framework/pom.xml index 17b245b..cac16d5 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -353,6 +353,9 @@ repackage + + exec + diff --git a/framework/src/main/java/com/yfd/platform/aspect/LogAspect.java b/framework/src/main/java/com/yfd/platform/aspect/LogAspect.java index 0c52a21..80221b6 100644 --- a/framework/src/main/java/com/yfd/platform/aspect/LogAspect.java +++ b/framework/src/main/java/com/yfd/platform/aspect/LogAspect.java @@ -75,9 +75,21 @@ public class LogAspect { SysLog log = new SysLog("INFO"); currentTime.remove(); HttpServletRequest request = RequestHolder.getHttpServletRequest(); - Map nameInfo = userService.getNameInfo(); - String nickname = nameInfo.get("nickname"); - String username = nameInfo.get("username"); + + // 修复:不直接依赖 userService.getNameInfo(),防止匿名用户转换异常 + String nickname = "匿名用户"; + String username = getUsername(); // 调用本类包装好的获取用户名方法 + if (StringUtils.isNotBlank(username)) { + try { + Map nameInfo = userService.getNameInfo(); + 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; diff --git a/framework/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java b/framework/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java index 566d608..673d998 100644 --- a/framework/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java +++ b/framework/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java @@ -69,34 +69,55 @@ public class UserServiceImpl extends ServiceImpl impleme ***********************************/ @Override public String getUsername() { - UsernamePasswordAuthenticationToken authentication = - (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); - LoginUser loginuser = (LoginUser) authentication.getPrincipal(); - String acountname = - loginuser.getUser().getNickname(); - return acountname; - //return "admin"; + try { + Object auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth instanceof UsernamePasswordAuthenticationToken) { + UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) auth; + LoginUser loginuser = (LoginUser) authentication.getPrincipal(); + return loginuser.getUser().getNickname(); + } + } catch (Exception e) { + // ignore + } + return "anonymous"; } @Override public Map getNameInfo() { - UsernamePasswordAuthenticationToken authentication = - (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); - LoginUser loginuser = (LoginUser) authentication.getPrincipal(); - String nickname = loginuser.getUser().getNickname(); - String username = loginuser.getUser().getUsername(); Map map = new HashMap<>(); - map.put("nickname", nickname); - map.put("username", username); + 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.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(); - LoginUser loginuser = (LoginUser) authentication.getPrincipal(); - return loginuser.getUser(); + 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 diff --git a/framework/src/main/resources/logback-spring.xml b/framework/src/main/resources/logback-spring.xml index 31a0ed8..5d2067d 100644 --- a/framework/src/main/resources/logback-spring.xml +++ b/framework/src/main/resources/logback-spring.xml @@ -2,7 +2,8 @@ - + + @@ -15,13 +16,13 @@ - ${LOG_PATH}/${LOG_FILE}.log + ${LOG_PATH}/${APP_NAME}.log UTF-8 ${LOG_PATTERN} - ${LOG_PATH}/${LOG_FILE}.%d{yyyy-MM-dd}.log + ${LOG_PATH}/${APP_NAME}.%d{yyyy-MM-dd}.log 30