From 7499a6e29583ed49744c0c84d9c38a72a631df17 Mon Sep 17 00:00:00 2001 From: wanxiaoli Date: Thu, 18 Dec 2025 17:16:24 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=86=E5=8C=96=E6=8E=A5=E5=8F=A3=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E3=80=81=E6=B3=A8=E9=87=8A=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- business-css/pom.xml | 14 +- .../controller/CriticalDataController.java | 36 +++- .../css/controller/DeviceController.java | 52 ++++- .../css/controller/EventController.java | 41 ++++ .../css/controller/MaterialController.java | 28 ++- .../css/controller/ProjectController.java | 79 +++++++ .../css/controller/ScenarioController.java | 50 ++++- .../controller/ScenarioResultController.java | 21 ++ .../yfd/business/css/domain/CriticalData.java | 19 +- .../com/yfd/business/css/domain/Material.java | 21 +- .../business/css/domain/ScenarioResult.java | 3 +- .../css/service/CriticalDataService.java | 5 +- .../business/css/service/DeviceService.java | 6 - .../service/impl/CriticalDataServiceImpl.java | 186 ++++++++++++++++- .../css/service/impl/DeviceServiceImpl.java | 167 ++++++++++++++- .../css/service/impl/MaterialServiceImpl.java | 197 +++++++++++++++++- .../css/service/impl/ProjectServiceImpl.java | 97 ++++++++- 17 files changed, 959 insertions(+), 63 deletions(-) diff --git a/business-css/pom.xml b/business-css/pom.xml index 37db454..8763eea 100644 --- a/business-css/pom.xml +++ b/business-css/pom.xml @@ -23,7 +23,7 @@ UTF-8 - + org.springframework.boot @@ -66,6 +66,18 @@ plain + + + org.apache.poi + poi + 4.1.2 + + + org.apache.poi + poi-ooxml + 4.1.2 + + 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 d5e1700..d3c39c4 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 @@ -18,6 +18,10 @@ public class CriticalDataController { /** * 1. 新增临界数据 + * 输入参数:请求体中的临界数据对象 + * 输出参数:布尔值,表示是否新增成功 + * @param data 临界数据对象 + * @return 是否新增成功 */ @PostMapping public boolean create(@RequestBody CriticalData data) { @@ -26,6 +30,10 @@ public class CriticalDataController { /** * 2. 修改临界数据 + * 输入参数:请求体中的临界数据对象(需包含主键) + * 输出参数:布尔值,表示是否修改成功 + * @param data 临界数据对象 + * @return 是否修改成功 */ @PutMapping public boolean update(@RequestBody CriticalData data) { @@ -34,6 +42,10 @@ public class CriticalDataController { /** * 3.1 删除临界数据(单条) + * 输入参数:路径参数临界数据ID + * 输出参数:布尔值,表示是否删除成功 + * @param id 临界数据ID + * @return 是否删除成功 */ @DeleteMapping("/{id}") public boolean delete(@PathVariable String id) { @@ -42,6 +54,10 @@ public class CriticalDataController { /** * 3.2 删除临界数据(多条) + * 输入参数:请求体中的临界数据ID列表 + * 输出参数:布尔值,表示是否删除成功 + * @param ids 临界数据ID列表 + * @return 是否删除成功 */ @DeleteMapping public boolean deleteBatch(@RequestBody List ids) { @@ -49,23 +65,27 @@ public class CriticalDataController { } /** - * 4. 导入临界数据 + * 4. 导入临界数据(Excel/CSV) + * 输入参数:表单文件字段 file + * 模板表头:device_type, diameter, height, fissile_concentration, isotopic_abundance, keff_value, extra_features + * 采集规则:仅采集上述字段,表头中多余字段不予采集;extra_features 校验为合法 JSON,非法或占位符将置为 null + * 输出参数:布尔值,表示是否导入成功 + * @param file Excel/CSV 文件 + * @return 是否导入成功 */ @PostMapping("/import") public boolean importCriticalData(@RequestParam("file") MultipartFile file) { return criticalDataService.importCriticalData(file); } - /** - * 5. 获取设备类型列表(去重) - */ - @GetMapping("/device-types") - public List listDeviceTypes() { - return criticalDataService.listDeviceTypes(); - } + /** * 6. 根据设备类型获取临界数据列表 + * 输入参数:查询参数 deviceType(设备类型) + * 输出参数:临界数据列表(按创建时间倒序) + * @param deviceType 设备类型 + * @return 临界数据列表 */ @GetMapping("/by-device-type") public List listByDeviceType(@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 7c83348..5c28783 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 @@ -18,6 +18,10 @@ public class DeviceController { /** * 1. 新增设备 + * 输入参数:请求体中的设备对象 + * 输出参数:布尔值,表示是否新增成功 + * @param device 设备对象 + * @return 是否新增成功 */ @PostMapping public boolean create(@RequestBody Device device) { @@ -26,6 +30,10 @@ public class DeviceController { /** * 2. 编辑设备 + * 输入参数:请求体中的设备对象(需包含主键) + * 输出参数:布尔值,表示是否修改成功 + * @param device 设备对象 + * @return 是否修改成功 */ @PutMapping public boolean update(@RequestBody Device device) { @@ -34,6 +42,10 @@ public class DeviceController { /** * 3.1 删除设备(单条) + * 输入参数:路径参数设备ID + * 输出参数:布尔值,表示是否删除成功 + * @param id 设备ID + * @return 是否删除成功 */ @DeleteMapping("/{id}") public boolean delete(@PathVariable String id) { @@ -42,6 +54,10 @@ public class DeviceController { /** * 3.2 删除设备(多条) + * 输入参数:请求体中的设备ID列表 + * 输出参数:布尔值,表示是否删除成功 + * @param ids 设备ID列表 + * @return 是否删除成功 */ @DeleteMapping public boolean deleteBatch(@RequestBody List ids) { @@ -49,24 +65,43 @@ public class DeviceController { } /** - * 4. 导入设备 - * (Excel / CSV,具体解析逻辑在 Service) + * 4. 导入设备(Excel/CSV) + * 输入参数:表单文件字段 file + * 模板表头:type, code, name, size, volume, flow_rate, pulse_velocity + * 采集规则:仅采集上述字段,表头中多余字段不予采集;size 校验为合法 JSON,非法或占位符将置为 null;导入记录的 project_id 统一写入 -1 + * 输出参数:布尔值,表示是否导入成功 + * @param file Excel/CSV 文件 + * @return 是否导入成功 */ @PostMapping("/import") public boolean importDevices(@RequestParam("file") MultipartFile file) { return deviceService.importDevices(file); } + /** - * 5. 获取设备类型列表(去重) + * 5. 根据项目ID获取设备列表 + * 输入参数:查询参数 projectId(项目ID) + * 输出参数:设备列表(按创建时间倒序) + * @param projectId 项目ID + * @return 设备列表 */ - @GetMapping("/types") - public List listDeviceTypes() { - return deviceService.listDeviceTypes(); + @GetMapping("/by-project") + public List listByProject(@RequestParam String projectId) { + return deviceService.list( + new QueryWrapper() + .eq("project_id", projectId) + .orderByDesc("created_at") + ); } + /** * 6. 根据设备类型获取设备列表 + * 输入参数:查询参数 type(设备类型) + * 输出参数:设备列表(按创建时间倒序) + * @param type 设备类型 + * @return 设备列表 */ @GetMapping("/by-type") public List listByType(@RequestParam String type) { @@ -79,6 +114,11 @@ public class DeviceController { /** * 7. 设备查询(类型 + 名称) + * 输入参数:查询参数 type(可选),name(可选) + * 输出参数:设备列表(按创建时间倒序) + * @param type 设备类型(可选) + * @param name 设备名称关键词(可选) + * @return 设备列表 */ @GetMapping("/search") public List search(@RequestParam(required = false) String type, 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 f6d9fb3..8b6e990 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 @@ -5,7 +5,9 @@ import com.yfd.business.css.service.EventService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import java.util.Map; +import java.util.List; @RestController @RequestMapping("/events") @@ -57,4 +59,43 @@ public class EventController { "data", updatedEvent )); } + + /** + * 根据情景ID获取始发事件列表 + * 输入参数:查询参数 scenarioId(情景ID) + * 输出参数:事件列表(按创建时间倒序) + * @param scenarioId 情景ID + * @return 始发事件列表 + */ + @GetMapping("/by-scenario") + public List listByScenario(@RequestParam String scenarioId) { + return eventService.list( + new QueryWrapper() + .eq("scenario_id", scenarioId) + .orderByDesc("created_at") + ); + } + + /** + * 删除始发事件 + * 输入参数:路径参数 eventId(事件ID) + * 输出参数:标准响应结构,表示删除结果 + * @param eventId 事件ID + * @return 删除结果 + */ + @DeleteMapping("/{eventId}") + public ResponseEntity> deleteEvent(@PathVariable String eventId) { + boolean ok = eventService.removeById(eventId); + if (ok) { + return ResponseEntity.ok(Map.of( + "code", 0, + "msg", "删除成功" + )); + } else { + return ResponseEntity.badRequest().body(Map.of( + "code", 1, + "msg", "删除失败" + )); + } + } } 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 3445f9b..f8fc9ff 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 @@ -18,6 +18,10 @@ public class MaterialController { /** * 1. 新增物料 + * 输入参数:请求体中的物料对象 + * 输出参数:布尔值,表示是否新增成功 + * @param material 物料对象 + * @return 是否新增成功 */ @PostMapping public boolean create(@RequestBody Material material) { @@ -26,6 +30,10 @@ public class MaterialController { /** * 2. 编辑物料 + * 输入参数:请求体中的物料对象(需包含主键) + * 输出参数:布尔值,表示是否修改成功 + * @param material 物料对象 + * @return 是否修改成功 */ @PutMapping public boolean update(@RequestBody Material material) { @@ -34,6 +42,10 @@ public class MaterialController { /** * 3.1 删除物料(单条) + * 输入参数:路径参数物料ID + * 输出参数:布尔值,表示是否删除成功 + * @param id 物料ID + * @return 是否删除成功 */ @DeleteMapping("/{id}") public boolean delete(@PathVariable String id) { @@ -42,6 +54,10 @@ public class MaterialController { /** * 3.2 删除物料(多条) + * 输入参数:请求体中的物料ID列表 + * 输出参数:布尔值,表示是否删除成功 + * @param ids 物料ID列表 + * @return 是否删除成功 */ @DeleteMapping public boolean deleteBatch(@RequestBody List ids) { @@ -49,7 +65,13 @@ public class MaterialController { } /** - * 4. 导入物料 + * 4. 导入物料(Excel/CSV) + * 输入参数:表单文件字段 file + * 模板表头:name, u_concentration, uo2_density, u_enrichment, pu_concentration, puo2_density, pu_isotope, hno3_acidity, h2c2o4_concentration, organic_ratio, moisture_content, custom_attrs + * 采集规则:仅采集上述字段,表头中多余字段不予采集;custom_attrs 校验为合法 JSON,非法或占位符(-、—、/、/)将置为 null;导入记录的 project_id 统一写入 -1 + * 输出参数:布尔值,表示是否导入成功 + * @param file Excel/CSV 文件 + * @return 是否导入成功 */ @PostMapping("/import") public boolean importMaterials(@RequestParam("file") MultipartFile file) { @@ -58,6 +80,10 @@ public class MaterialController { /** * 5. 根据物料名称搜索 + * 输入参数:查询参数 name(物料名称关键词) + * 输出参数:物料列表(按创建时间倒序) + * @param name 物料名称关键词 + * @return 物料列表 */ @GetMapping("/search") public List search(@RequestParam String name) { 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 9bc298b..324b5d1 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 @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; import java.util.List; +import java.util.Map; @RestController @RequestMapping("/projects") @@ -20,6 +21,10 @@ public class ProjectController { /** * 1. 新增项目 + * 输入参数:请求体中的项目对象 + * 输出参数:布尔值,表示是否新增成功 + * @param project 项目对象 + * @return 是否新增成功 */ @PostMapping public boolean create(@RequestBody Project project) { @@ -28,6 +33,10 @@ public class ProjectController { /** * 2. 修改项目 + * 输入参数:请求体中的项目对象(需包含主键) + * 输出参数:布尔值,表示是否修改成功 + * @param project 项目对象 + * @return 是否修改成功 */ @PutMapping public boolean update(@RequestBody Project project) { @@ -36,6 +45,10 @@ public class ProjectController { /** * 3.1 删除项目(单条) + * 输入参数:路径参数项目ID + * 输出参数:布尔值,表示是否删除成功 + * @param id 项目ID + * @return 是否删除成功 */ @DeleteMapping("/{id}") public boolean delete(@PathVariable String id) { @@ -44,6 +57,10 @@ public class ProjectController { /** * 3.2 删除项目(多条) + * 输入参数:请求体中的项目ID列表 + * 输出参数:布尔值,表示是否删除成功 + * @param ids 项目ID列表 + * @return 是否删除成功 */ @DeleteMapping public boolean deleteBatch(@RequestBody List ids) { @@ -52,6 +69,10 @@ public class ProjectController { /** * 4. 导出所有项目 + * 输入参数:无 + * 导出描述:返回所有项目的 JSON 数组,作为附件 `projects.json` + * 输出参数:附件字节流(application/octet-stream) + * @return 附件响应,文件名为 projects.json */ @GetMapping("/export/all") public ResponseEntity exportAll() { @@ -66,6 +87,17 @@ public class ProjectController { /** * 5. 导出项目工程 + * 输入参数:路径参数项目ID + * 导出描述:返回 ZIP 附件 `project_{id}.zip`,包含以下 JSON 文件: + * - project.json:项目对象 + * - devices.json:设备列表 + * - materials.json:物料列表 + * - scenarios.json:情景列表 + * - events.json:事件列表 + * - scenario-results.json:情景结果列表 + * 输出参数:附件字节流(application/octet-stream) + * @param id 项目ID + * @return 附件响应,文件名为 project_{id}.zip */ @GetMapping("/{id}/export") public ResponseEntity exportProject(@PathVariable String id) { @@ -80,6 +112,10 @@ public class ProjectController { /** * 6. 根据项目名称搜索 + * 输入参数:查询参数 name(项目名称关键词) + * 输出参数:项目列表 + * @param name 项目名称关键词 + * @return 匹配的项目列表 */ @GetMapping("/search") public List searchByName(@RequestParam String name) { @@ -89,4 +125,47 @@ public class ProjectController { .orderByDesc("created_at") ); } + + /** + * 7. 根据项目ID获取项目信息 + * 输入参数:路径参数项目ID + * 输出参数:项目对象(不存在时为空) + * @param id 项目ID + * @return 项目对象 + */ + @GetMapping("/{id}") + public Project getById(@PathVariable String id) { + return projectService.getById(id); + } + + /** + * 8. 更新指定项目的拓扑结构 + * 输入参数:路径参数项目ID;请求体 Map 中的 topology 字段 + * 输出参数:标准响应结构,包含更新后的项目主键与拓扑字段 + * @param id 项目ID + * @param requestBody 请求体,需包含 topology 字段 + * @return 标准响应结构 + */ + @PutMapping("/{id}/topology") + public ResponseEntity> updateTopology(@PathVariable String id, + @RequestBody Map requestBody) { + Object topology = requestBody.get("topology"); + if (topology == null) { + return ResponseEntity.badRequest().body(Map.of( + "code", 1, + "msg", "topology不能为空" + )); + } + Project updated = new Project(); + updated.setProjectId(id); + updated.setTopology(String.valueOf(topology)); + projectService.updateById(updated); + return ResponseEntity.ok(Map.of( + "code", 0, + "msg", "修改成功", + "data", updated + )); + } + + } 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 9b12279..a1b08e1 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 @@ -17,6 +17,10 @@ public class ScenarioController { /** * 1. 新增情景 + * 输入参数:请求体中的情景对象 + * 输出参数:布尔值,表示是否新增成功 + * @param scenario 情景对象 + * @return 是否新增成功 */ @PostMapping public boolean create(@RequestBody Scenario scenario) { @@ -25,6 +29,10 @@ public class ScenarioController { /** * 2. 修改情景 + * 输入参数:请求体中的情景对象(需包含主键) + * 输出参数:布尔值,表示是否修改成功 + * @param scenario 情景对象 + * @return 是否修改成功 */ @PutMapping public boolean update(@RequestBody Scenario scenario) { @@ -32,7 +40,11 @@ public class ScenarioController { } /** - * 3. 删除情景 + * 3.1 删除情景(单条) + * 输入参数:路径参数情景ID + * 输出参数:布尔值,表示是否删除成功 + * @param id 情景ID + * @return 是否删除成功 */ @DeleteMapping("/{id}") public boolean delete(@PathVariable String id) { @@ -41,6 +53,10 @@ public class ScenarioController { /** * 3.2 删除情景(多条) + * 输入参数:请求体中的情景ID列表 + * 输出参数:布尔值,表示是否删除成功 + * @param ids 情景ID列表 + * @return 是否删除成功 */ @DeleteMapping public boolean deleteBatch(@RequestBody List ids) { @@ -49,6 +65,10 @@ public class ScenarioController { /** * 4. 根据情景名称搜索 + * 输入参数:查询参数 name(情景名称关键词) + * 输出参数:情景列表(按创建时间倒序) + * @param name 情景名称关键词 + * @return 情景列表 */ @GetMapping("/search") public List searchByName(@RequestParam String name) { @@ -58,4 +78,32 @@ public class ScenarioController { .orderByDesc("created_at") ); } + + /** + * 5. 根据情景ID获取情景记录 + * 输入参数:路径参数情景ID + * 输出参数:情景对象(不存在时为空) + * @param id 情景ID + * @return 情景对象 + */ + @GetMapping("/{id}") + public Scenario getById(@PathVariable String id) { + return scenarioService.getById(id); + } + + /** + * 6. 根据项目ID查询情景列表 + * 输入参数:查询参数 projectId(项目ID) + * 输出参数:情景列表(按创建时间倒序) + * @param projectId 项目ID + * @return 情景列表 + */ + @GetMapping("/by-project") + public List listByProject(@RequestParam String projectId) { + return scenarioService.list( + new QueryWrapper() + .eq("project_id", projectId) + .orderByDesc("created_at") + ); + } } diff --git a/business-css/src/main/java/com/yfd/business/css/controller/ScenarioResultController.java b/business-css/src/main/java/com/yfd/business/css/controller/ScenarioResultController.java index 8bcebd1..0548466 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/ScenarioResultController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/ScenarioResultController.java @@ -5,6 +5,8 @@ import com.yfd.business.css.service.ScenarioResultService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import java.util.List; import java.util.Map; @RestController @@ -30,4 +32,23 @@ public class ScenarioResultController { "data", savedResult )); } + + /** + * 根据情景ID与设备ID获取情景结果列表 + * 输入参数:查询参数 scenarioId(情景ID)、deviceId(设备ID) + * 输出参数:情景结果列表(按时间点 step 排序) + * @param scenarioId 情景ID + * @param deviceId 设备ID + * @return 情景结果列表 + */ + @GetMapping("/by-scenario") + public List listByScenario(@RequestParam String scenarioId, + @RequestParam String deviceId) { + return scenarioResultService.list( + new QueryWrapper() + .eq("scenario_id", scenarioId) + .eq("device_id", deviceId) + .orderByAsc("step") + ); + } } diff --git a/business-css/src/main/java/com/yfd/business/css/domain/CriticalData.java b/business-css/src/main/java/com/yfd/business/css/domain/CriticalData.java index ef5d4c0..f5bf6cc 100644 --- a/business-css/src/main/java/com/yfd/business/css/domain/CriticalData.java +++ b/business-css/src/main/java/com/yfd/business/css/domain/CriticalData.java @@ -8,6 +8,7 @@ import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; +import java.math.BigDecimal; @Data @TableName("critical_data") @@ -21,11 +22,23 @@ public class CriticalData implements Serializable { @TableField("device_type") private String deviceType; - @TableField("attr_state") - private String attrState; // JSON + @TableField("diameter") + private BigDecimal diameter; + + @TableField("height") + private BigDecimal height; + + @TableField("fissile_concentration") + private BigDecimal fissileConcentration; + + @TableField("isotopic_abundance") + private BigDecimal isotopicAbundance; + + @TableField("extra_features") + private String extraFeatures; @TableField("keff_value") - private Double keffValue; + private BigDecimal keffValue; @TableField("created_at") private LocalDateTime createdAt; diff --git a/business-css/src/main/java/com/yfd/business/css/domain/Material.java b/business-css/src/main/java/com/yfd/business/css/domain/Material.java index 8a9720c..e1f8169 100644 --- a/business-css/src/main/java/com/yfd/business/css/domain/Material.java +++ b/business-css/src/main/java/com/yfd/business/css/domain/Material.java @@ -8,6 +8,7 @@ import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; +import java.math.BigDecimal; @Data @TableName("material") @@ -25,34 +26,34 @@ public class Material implements Serializable { private String name; @TableField("u_concentration") - private Double uConcentration; + private BigDecimal uConcentration; @TableField("uo2_density") - private Double uo2Density; + private BigDecimal uo2Density; @TableField("u_enrichment") - private Double uEnrichment; + private BigDecimal uEnrichment; @TableField("pu_concentration") - private Double puConcentration; + private BigDecimal puConcentration; @TableField("puo2_density") - private Double puo2Density; + private BigDecimal puo2Density; @TableField("pu_isotope") - private Double puIsotope; + private BigDecimal puIsotope; @TableField("hno3_acidity") - private Double hno3Acidity; + private BigDecimal hno3Acidity; @TableField("h2c2o4_concentration") - private Double h2c2o4Concentration; + private BigDecimal h2c2o4Concentration; @TableField("organic_ratio") - private Double organicRatio; + private BigDecimal organicRatio; @TableField("moisture_content") - private Double moistureContent; + private BigDecimal moistureContent; @TableField("custom_attrs") private String customAttrs; // JSON diff --git a/business-css/src/main/java/com/yfd/business/css/domain/ScenarioResult.java b/business-css/src/main/java/com/yfd/business/css/domain/ScenarioResult.java index b6e8a34..9c804e6 100644 --- a/business-css/src/main/java/com/yfd/business/css/domain/ScenarioResult.java +++ b/business-css/src/main/java/com/yfd/business/css/domain/ScenarioResult.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; +import java.math.BigDecimal; @Data @TableName("scenario_result") @@ -25,5 +26,5 @@ public class ScenarioResult implements Serializable { private String attrState; // JSON @TableField("keff_value") - private Double keffValue; + private BigDecimal keffValue; } diff --git a/business-css/src/main/java/com/yfd/business/css/service/CriticalDataService.java b/business-css/src/main/java/com/yfd/business/css/service/CriticalDataService.java index cac40a9..e4ac9b1 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/CriticalDataService.java +++ b/business-css/src/main/java/com/yfd/business/css/service/CriticalDataService.java @@ -11,8 +11,5 @@ public interface CriticalDataService extends IService { */ boolean importCriticalData(MultipartFile file); - /** - * 获取设备类型列表(去重) - */ - List listDeviceTypes(); + } diff --git a/business-css/src/main/java/com/yfd/business/css/service/DeviceService.java b/business-css/src/main/java/com/yfd/business/css/service/DeviceService.java index 8880bd8..8d20810 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/DeviceService.java +++ b/business-css/src/main/java/com/yfd/business/css/service/DeviceService.java @@ -3,15 +3,9 @@ package com.yfd.business.css.service; import com.baomidou.mybatisplus.extension.service.IService; import com.yfd.business.css.domain.Device; import org.springframework.web.multipart.MultipartFile; -import java.util.List; public interface DeviceService extends IService { /** * 导入设备 */ boolean importDevices(MultipartFile file); - - /** - * 获取设备类型列表(去重) - */ - List listDeviceTypes(); } diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/CriticalDataServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/CriticalDataServiceImpl.java index 9fd49d2..14fc953 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/CriticalDataServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/CriticalDataServiceImpl.java @@ -7,25 +7,193 @@ import com.yfd.business.css.service.CriticalDataService; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.annotation.Resource; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.math.BigDecimal; import java.util.List; import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; @Service public class CriticalDataServiceImpl extends ServiceImpl implements CriticalDataService { + @Resource + private ObjectMapper objectMapper; @Override public boolean importCriticalData(MultipartFile file) { - return false; + try { + String name = file.getOriginalFilename(); + if (name == null) return false; + String lower = name.toLowerCase(); + if (lower.endsWith(".xlsx")) { + return importExcel(new XSSFWorkbook(file.getInputStream())); + } else if (lower.endsWith(".xls")) { + return importExcel(new HSSFWorkbook(file.getInputStream())); + } else if (lower.endsWith(".csv")) { + return importCsv(file.getInputStream()); + } else { + return false; + } + } catch (Exception e) { + return false; + } } - @Override - public List listDeviceTypes() { - return this.list() - .stream() - .map(CriticalData::getDeviceType) - .filter(s -> s != null && !s.isEmpty()) - .distinct() - .collect(Collectors.toList()); + private boolean importExcel(Workbook workbook) { + try (Workbook wb = workbook) { + Sheet sheet = wb.getSheetAt(0); + if (sheet == null) return false; + Row headerRow = sheet.getRow(0); + if (headerRow == null) return false; + Map idx = new HashMap<>(); + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell c = headerRow.getCell(i); + if (c == null) continue; + String key = c.getStringCellValue(); + if (key != null) idx.put(key.trim().toLowerCase(), i); + } + String[] keys = new String[]{ + "device_type","diameter","height", + "fissile_concentration","isotopic_abundance", + "keff_value","extra_features" + }; + for (String k : keys) if (!idx.containsKey(k)) return false; + List list = new ArrayList<>(); + for (int r = 1; r <= sheet.getLastRowNum(); r++) { + Row row = sheet.getRow(r); + if (row == null) continue; + CriticalData cd = new CriticalData(); + cd.setDeviceType(cleanString(getString(row, idx.get("device_type")))); + cd.setDiameter(cleanDecimal(getDecimal(row, idx.get("diameter")))); + cd.setHeight(cleanDecimal(getDecimal(row, idx.get("height")))); + cd.setFissileConcentration(cleanDecimal(getDecimal(row, idx.get("fissile_concentration")))); + cd.setIsotopicAbundance(cleanDecimal(getDecimal(row, idx.get("isotopic_abundance")))); + cd.setKeffValue(cleanDecimal(getDecimal(row, idx.get("keff_value")))); + cd.setExtraFeatures(validateJson(cleanString(getString(row, idx.get("extra_features"))))); + cd.setCreatedAt(LocalDateTime.now()); + cd.setUpdatedAt(LocalDateTime.now()); + if (isEmpty(cd)) continue; + list.add(cd); + } + if (list.isEmpty()) return false; + return this.saveBatch(list); + } catch (Exception e) { + return false; + } } + + private boolean importCsv(InputStream is) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + String header = br.readLine(); + if (header == null) return false; + String[] hs = header.split(","); + Map idx = new HashMap<>(); + for (int i = 0; i < hs.length; i++) idx.put(hs[i].trim().toLowerCase(), i); + String[] keys = new String[]{ + "device_type","diameter","height", + "fissile_concentration","isotopic_abundance", + "keff_value","extra_features" + }; + for (String k : keys) if (!idx.containsKey(k)) return false; + List list = new ArrayList<>(); + String line; + while ((line = br.readLine()) != null) { + String[] cols = line.split(","); + CriticalData cd = new CriticalData(); + cd.setDeviceType(cleanString(get(cols, idx.get("device_type")))); + cd.setDiameter(cleanDecimal(parseDecimal(get(cols, idx.get("diameter"))))); + cd.setHeight(cleanDecimal(parseDecimal(get(cols, idx.get("height"))))); + cd.setFissileConcentration(cleanDecimal(parseDecimal(get(cols, idx.get("fissile_concentration"))))); + cd.setIsotopicAbundance(cleanDecimal(parseDecimal(get(cols, idx.get("isotopic_abundance"))))); + cd.setKeffValue(cleanDecimal(parseDecimal(get(cols, idx.get("keff_value"))))); + cd.setExtraFeatures(validateJson(cleanString(get(cols, idx.get("extra_features"))))); + cd.setCreatedAt(LocalDateTime.now()); + cd.setUpdatedAt(LocalDateTime.now()); + if (isEmpty(cd)) continue; + list.add(cd); + } + if (list.isEmpty()) return false; + return this.saveBatch(list); + } catch (Exception e) { + return false; + } + } + + private String getString(Row row, int i) { + Cell c = row.getCell(i); + if (c == null) return null; + switch (c.getCellType()) { + case STRING: return c.getStringCellValue(); + case NUMERIC: return String.valueOf(c.getNumericCellValue()); + case BOOLEAN: return String.valueOf(c.getBooleanCellValue()); + default: return null; + } + } + + private BigDecimal getDecimal(Row row, int i) { + Cell c = row.getCell(i); + if (c == null) return null; + switch (c.getCellType()) { + case NUMERIC: return BigDecimal.valueOf(c.getNumericCellValue()); + case STRING: + try { return new BigDecimal(c.getStringCellValue().trim()); } catch (Exception e) { return null; } + default: return null; + } + } + + private String get(String[] cols, int i) { + if (i < 0 || i >= cols.length) return null; + String v = cols[i]; + if (v == null) return null; + return v.trim(); + } + + private BigDecimal parseDecimal(String s) { + if (s == null || s.isEmpty()) return null; + try { return new BigDecimal(s.trim()); } catch (Exception e) { return null; } + } + + private boolean isPlaceholder(String s) { + if (s == null) return false; + String t = s.trim(); + return "-".equals(t) || "—".equals(t) || "/".equals(t) || "/".equals(t); + } + + private String cleanString(String s) { + return isPlaceholder(s) ? null : s; + } + + private BigDecimal cleanDecimal(BigDecimal d) { + return d; + } + + private boolean isEmpty(CriticalData cd) { + return cd.getDeviceType() == null || cd.getDeviceType().isEmpty(); + } + + private String validateJson(String s) { + if (s == null || s.isEmpty()) return null; + try { + JsonNode node = objectMapper.readTree(s); + return objectMapper.writeValueAsString(node); + } catch (Exception e) { + return null; + } + } + } 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 6fc2105..28300cc 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 @@ -7,25 +7,172 @@ import com.yfd.business.css.service.DeviceService; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.annotation.Resource; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; import java.util.List; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; @Service public class DeviceServiceImpl extends ServiceImpl implements DeviceService { + @Resource + private ObjectMapper objectMapper; @Override public boolean importDevices(MultipartFile file) { - return false; + try { + String name = file.getOriginalFilename(); + if (name == null) return false; + String lower = name.toLowerCase(); + if (lower.endsWith(".xlsx")) { + return importExcel(new XSSFWorkbook(file.getInputStream())); + } else if (lower.endsWith(".xls")) { + return importExcel(new HSSFWorkbook(file.getInputStream())); + } else if (lower.endsWith(".csv")) { + return importCsv(file.getInputStream()); + } else { + return false; + } + } catch (Exception e) { + return false; + } } - @Override - public List listDeviceTypes() { - return this.list() - .stream() - .map(Device::getType) - .filter(s -> s != null && !s.isEmpty()) - .distinct() - .collect(Collectors.toList()); + private boolean importExcel(Workbook workbook) { + try (Workbook wb = workbook) { + Sheet sheet = wb.getSheetAt(0); + if (sheet == null) return false; + Row headerRow = sheet.getRow(0); + if (headerRow == null) return false; + Map idx = new HashMap<>(); + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell c = headerRow.getCell(i); + if (c == null) continue; + String key = c.getStringCellValue(); + if (key != null) idx.put(key.trim().toLowerCase(), i); + } + String[] keys = new String[]{"type","code","name","size","volume","flow_rate","pulse_velocity"}; + for (String k : keys) { + if (!idx.containsKey(k)) return false; + } + List devices = new ArrayList<>(); + for (int r = 1; r <= sheet.getLastRowNum(); r++) { + Row row = sheet.getRow(r); + if (row == null) continue; + Device d = new Device(); + d.setType(getString(row, idx.get("type"))); + d.setCode(getString(row, idx.get("code"))); + d.setName(getString(row, idx.get("name"))); + d.setSize(validateJson(getString(row, idx.get("size")))); + d.setVolume(getDouble(row, idx.get("volume"))); + d.setFlowRate(getDouble(row, idx.get("flow_rate"))); + d.setPulseVelocity(getDouble(row, idx.get("pulse_velocity"))); + d.setProjectId("-1"); + d.setCreatedAt(LocalDateTime.now()); + d.setUpdatedAt(LocalDateTime.now()); + if (isEmpty(d)) continue; + devices.add(d); + } + if (devices.isEmpty()) return false; + return this.saveBatch(devices); + } catch (Exception e) { + return false; + } + } + + private boolean importCsv(InputStream is) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + String header = br.readLine(); + if (header == null) return false; + String[] hs = header.split(","); + Map idx = new HashMap<>(); + for (int i = 0; i < hs.length; i++) idx.put(hs[i].trim().toLowerCase(), i); + String[] keys = new String[]{"type","code","name","size","volume","flow_rate","pulse_velocity"}; + for (String k : keys) if (!idx.containsKey(k)) return false; + List devices = new ArrayList<>(); + String line; + while ((line = br.readLine()) != null) { + String[] cols = line.split(","); + Device d = new Device(); + d.setType(get(cols, idx.get("type"))); + d.setCode(get(cols, idx.get("code"))); + d.setName(get(cols, idx.get("name"))); + d.setSize(validateJson(get(cols, idx.get("size")))); + d.setVolume(parseDouble(get(cols, idx.get("volume")))); + d.setFlowRate(parseDouble(get(cols, idx.get("flow_rate")))); + d.setPulseVelocity(parseDouble(get(cols, idx.get("pulse_velocity")))); + d.setProjectId("-1"); + d.setCreatedAt(LocalDateTime.now()); + d.setUpdatedAt(LocalDateTime.now()); + if (isEmpty(d)) continue; + devices.add(d); + } + if (devices.isEmpty()) return false; + return this.saveBatch(devices); + } catch (Exception e) { + return false; + } + } + + private String getString(Row row, int i) { + Cell c = row.getCell(i); + if (c == null) return null; + switch (c.getCellType()) { + case STRING: return c.getStringCellValue(); + case NUMERIC: return String.valueOf(c.getNumericCellValue()); + case BOOLEAN: return String.valueOf(c.getBooleanCellValue()); + default: return null; + } + } + + private Double getDouble(Row row, int i) { + Cell c = row.getCell(i); + if (c == null) return null; + switch (c.getCellType()) { + case NUMERIC: return c.getNumericCellValue(); + case STRING: + try { return Double.parseDouble(c.getStringCellValue()); } catch (Exception e) { return null; } + default: return null; + } + } + + private String get(String[] cols, int i) { + if (i < 0 || i >= cols.length) return null; + String v = cols[i]; + if (v == null) return null; + return v.trim(); + } + + private Double parseDouble(String s) { + if (s == null || s.isEmpty()) return null; + try { return Double.parseDouble(s); } catch (Exception e) { return null; } + } + + private boolean isEmpty(Device d) { + return (d.getCode() == null || d.getCode().isEmpty()) && (d.getName() == null || d.getName().isEmpty()); + } + + private String validateJson(String s) { + if (s == null || s.isEmpty()) return null; + try { + JsonNode node = objectMapper.readTree(s); + return objectMapper.writeValueAsString(node); + } catch (Exception e) { + return null; + } } } 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 b5dc374..5d63789 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 @@ -7,12 +7,207 @@ import com.yfd.business.css.service.MaterialService; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.annotation.Resource; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Service public class MaterialServiceImpl extends ServiceImpl implements MaterialService { + @Resource + private ObjectMapper objectMapper; @Override public boolean importMaterials(MultipartFile file) { - return false; + try { + String name = file.getOriginalFilename(); + if (name == null) return false; + String lower = name.toLowerCase(); + if (lower.endsWith(".xlsx")) { + return importExcel(new XSSFWorkbook(file.getInputStream())); + } else if (lower.endsWith(".xls")) { + return importExcel(new HSSFWorkbook(file.getInputStream())); + } else if (lower.endsWith(".csv")) { + return importCsv(file.getInputStream()); + } else { + return false; + } + } catch (Exception e) { + return false; + } + } + + private boolean importExcel(Workbook workbook) { + try (Workbook wb = workbook) { + Sheet sheet = wb.getSheetAt(0); + if (sheet == null) return false; + Row headerRow = sheet.getRow(0); + if (headerRow == null) return false; + Map idx = new HashMap<>(); + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell c = headerRow.getCell(i); + if (c == null) continue; + String key = c.getStringCellValue(); + if (key != null) idx.put(key.trim().toLowerCase(), i); + } + 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" + }; + for (String k : keys) { + if (!idx.containsKey(k)) return false; + } + List list = new ArrayList<>(); + for (int r = 1; r <= sheet.getLastRowNum(); r++) { + Row row = sheet.getRow(r); + if (row == null) continue; + Material m = new Material(); + m.setName(cleanString(getString(row, idx.get("name")))); + m.setUConcentration(cleanDecimal(getDecimal(row, idx.get("u_concentration")))); + m.setUo2Density(cleanDecimal(getDecimal(row, idx.get("uo2_density")))); + m.setUEnrichment(cleanDecimal(getDecimal(row, idx.get("u_enrichment")))); + m.setPuConcentration(cleanDecimal(getDecimal(row, idx.get("pu_concentration")))); + m.setPuo2Density(cleanDecimal(getDecimal(row, idx.get("puo2_density")))); + m.setPuIsotope(cleanDecimal(getDecimal(row, idx.get("pu_isotope")))); + m.setHno3Acidity(cleanDecimal(getDecimal(row, idx.get("hno3_acidity")))); + m.setH2c2o4Concentration(cleanDecimal(getDecimal(row, idx.get("h2c2o4_concentration")))); + m.setOrganicRatio(cleanDecimal(getDecimal(row, idx.get("organic_ratio")))); + m.setMoistureContent(cleanDecimal(getDecimal(row, idx.get("moisture_content")))); + m.setCustomAttrs(validateJson(cleanString(getString(row, idx.get("custom_attrs"))))); + m.setProjectId("-1"); + m.setCreatedAt(LocalDateTime.now()); + m.setUpdatedAt(LocalDateTime.now()); + if (isEmpty(m)) continue; + list.add(m); + } + if (list.isEmpty()) return false; + return this.saveBatch(list); + } catch (Exception e) { + return false; + } + } + + private boolean importCsv(InputStream is) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + String header = br.readLine(); + if (header == null) return false; + String[] hs = header.split(","); + Map idx = new HashMap<>(); + for (int i = 0; i < hs.length; i++) idx.put(hs[i].trim().toLowerCase(), i); + 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" + }; + for (String k : keys) if (!idx.containsKey(k)) return false; + List list = new ArrayList<>(); + String line; + while ((line = br.readLine()) != null) { + String[] cols = line.split(","); + Material m = new Material(); + m.setName(cleanString(get(cols, idx.get("name")))); + m.setUConcentration(cleanDecimal(parseDecimal(get(cols, idx.get("u_concentration"))))); + m.setUo2Density(cleanDecimal(parseDecimal(get(cols, idx.get("uo2_density"))))); + m.setUEnrichment(cleanDecimal(parseDecimal(get(cols, idx.get("u_enrichment"))))); + m.setPuConcentration(cleanDecimal(parseDecimal(get(cols, idx.get("pu_concentration"))))); + m.setPuo2Density(cleanDecimal(parseDecimal(get(cols, idx.get("puo2_density"))))); + m.setPuIsotope(cleanDecimal(parseDecimal(get(cols, idx.get("pu_isotope"))))); + m.setHno3Acidity(cleanDecimal(parseDecimal(get(cols, idx.get("hno3_acidity"))))); + m.setH2c2o4Concentration(cleanDecimal(parseDecimal(get(cols, idx.get("h2c2o4_concentration"))))); + m.setOrganicRatio(cleanDecimal(parseDecimal(get(cols, idx.get("organic_ratio"))))); + m.setMoistureContent(cleanDecimal(parseDecimal(get(cols, idx.get("moisture_content"))))); + m.setCustomAttrs(validateJson(cleanString(get(cols, idx.get("custom_attrs"))))); + m.setProjectId("-1"); + m.setCreatedAt(LocalDateTime.now()); + m.setUpdatedAt(LocalDateTime.now()); + if (isEmpty(m)) continue; + list.add(m); + } + if (list.isEmpty()) return false; + return this.saveBatch(list); + } catch (Exception e) { + return false; + } + } + + private String getString(Row row, int i) { + Cell c = row.getCell(i); + if (c == null) return null; + switch (c.getCellType()) { + case STRING: return c.getStringCellValue(); + case NUMERIC: return String.valueOf(c.getNumericCellValue()); + case BOOLEAN: return String.valueOf(c.getBooleanCellValue()); + default: return null; + } + } + + private BigDecimal getDecimal(Row row, int i) { + Cell c = row.getCell(i); + if (c == null) return null; + switch (c.getCellType()) { + case NUMERIC: return BigDecimal.valueOf(c.getNumericCellValue()); + case STRING: + try { return new BigDecimal(c.getStringCellValue().trim()); } catch (Exception e) { return null; } + default: return null; + } + } + + private String get(String[] cols, int i) { + if (i < 0 || i >= cols.length) return null; + String v = cols[i]; + if (v == null) return null; + return v.trim(); + } + + private BigDecimal parseDecimal(String s) { + if (s == null || s.isEmpty()) return null; + try { return new BigDecimal(s.trim()); } catch (Exception e) { return null; } + } + + private boolean isEmpty(Material m) { + return m.getName() == null || m.getName().isEmpty(); + } + + private boolean isPlaceholder(String s) { + if (s == null) return false; + String t = s.trim(); + return "-".equals(t) || "—".equals(t) || "/".equals(t) || "/".equals(t); + } + + private String cleanString(String s) { + return isPlaceholder(s) ? null : s; + } + + private BigDecimal cleanDecimal(BigDecimal d) { + return d; + } + + private String validateJson(String s) { + if (s == null || s.isEmpty()) return null; + try { + JsonNode node = objectMapper.readTree(s); + return objectMapper.writeValueAsString(node); + } catch (Exception e) { + return null; + } } } diff --git a/business-css/src/main/java/com/yfd/business/css/service/impl/ProjectServiceImpl.java b/business-css/src/main/java/com/yfd/business/css/service/impl/ProjectServiceImpl.java index f38e756..f83f9a9 100644 --- a/business-css/src/main/java/com/yfd/business/css/service/impl/ProjectServiceImpl.java +++ b/business-css/src/main/java/com/yfd/business/css/service/impl/ProjectServiceImpl.java @@ -5,18 +5,111 @@ import com.yfd.business.css.domain.Project; import com.yfd.business.css.mapper.ProjectMapper; import com.yfd.business.css.service.ProjectService; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Resource; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.yfd.business.css.domain.Device; +import com.yfd.business.css.domain.Material; +import com.yfd.business.css.domain.Scenario; +import com.yfd.business.css.domain.Event; +import com.yfd.business.css.domain.ScenarioResult; +import com.yfd.business.css.service.DeviceService; +import com.yfd.business.css.service.MaterialService; +import com.yfd.business.css.service.ScenarioService; +import com.yfd.business.css.service.EventService; +import com.yfd.business.css.service.ScenarioResultService; +import java.util.List; +import java.util.zip.ZipOutputStream; +import java.util.zip.ZipEntry; +import java.io.ByteArrayOutputStream; @Service public class ProjectServiceImpl extends ServiceImpl implements ProjectService { + @Resource + private ObjectMapper objectMapper; + @Resource + private DeviceService deviceService; + @Resource + private MaterialService materialService; + @Resource + private ScenarioService scenarioService; + @Resource + private EventService eventService; + @Resource + private ScenarioResultService scenarioResultService; @Override public byte[] exportAllProjects() { - return new byte[0]; + try { + List projects = this.list(); + return objectMapper.writeValueAsBytes(projects); + } catch (Exception e) { + throw new RuntimeException(e); + } } @Override public byte[] exportProjectEngineering(String projectId) { - return new byte[0]; + try { + Project project = this.getById(projectId); + if (project == null) { + throw new IllegalArgumentException("项目不存在: " + projectId); + } + + List devices = deviceService.list( + new QueryWrapper().eq("project_id", projectId) + ); + List materials = materialService.list( + new QueryWrapper().eq("project_id", projectId) + ); + List scenarios = scenarioService.list( + new QueryWrapper().eq("project_id", projectId) + ); + List scenarioIds = scenarios.stream().map(Scenario::getScenarioId).toList(); + + List events = scenarioIds.isEmpty() + ? List.of() + : eventService.list(new QueryWrapper().in("scenario_id", scenarioIds)); + List results = scenarioIds.isEmpty() + ? List.of() + : scenarioResultService.list(new QueryWrapper().in("scenario_id", scenarioIds)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zos = new ZipOutputStream(baos)) { + // 项目信息 + zos.putNextEntry(new ZipEntry("project.json")); + zos.write(objectMapper.writeValueAsBytes(project)); + zos.closeEntry(); + + // 设备 + zos.putNextEntry(new ZipEntry("devices.json")); + zos.write(objectMapper.writeValueAsBytes(devices)); + zos.closeEntry(); + + // 物料 + zos.putNextEntry(new ZipEntry("materials.json")); + zos.write(objectMapper.writeValueAsBytes(materials)); + zos.closeEntry(); + + // 情景 + zos.putNextEntry(new ZipEntry("scenarios.json")); + zos.write(objectMapper.writeValueAsBytes(scenarios)); + zos.closeEntry(); + + // 事件 + zos.putNextEntry(new ZipEntry("events.json")); + zos.write(objectMapper.writeValueAsBytes(events)); + zos.closeEntry(); + + // 结果 + zos.putNextEntry(new ZipEntry("scenario-results.json")); + zos.write(objectMapper.writeValueAsBytes(results)); + zos.closeEntry(); + } + return baos.toByteArray(); + } catch (Exception e) { + throw new RuntimeException(e); + } } }