细化接口方法、注释等
This commit is contained in:
parent
719f02becd
commit
7499a6e295
@ -66,6 +66,18 @@
|
||||
<classifier>plain</classifier>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache POI 用于 Excel 导入 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
|
||||
@ -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<String> 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<String> listDeviceTypes() {
|
||||
return criticalDataService.listDeviceTypes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 6. 根据设备类型获取临界数据列表
|
||||
* 输入参数:查询参数 deviceType(设备类型)
|
||||
* 输出参数:临界数据列表(按创建时间倒序)
|
||||
* @param deviceType 设备类型
|
||||
* @return 临界数据列表
|
||||
*/
|
||||
@GetMapping("/by-device-type")
|
||||
public List<CriticalData> listByDeviceType(@RequestParam String deviceType) {
|
||||
|
||||
@ -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<String> 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<String> listDeviceTypes() {
|
||||
return deviceService.listDeviceTypes();
|
||||
@GetMapping("/by-project")
|
||||
public List<Device> listByProject(@RequestParam String projectId) {
|
||||
return deviceService.list(
|
||||
new QueryWrapper<Device>()
|
||||
.eq("project_id", projectId)
|
||||
.orderByDesc("created_at")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 6. 根据设备类型获取设备列表
|
||||
* 输入参数:查询参数 type(设备类型)
|
||||
* 输出参数:设备列表(按创建时间倒序)
|
||||
* @param type 设备类型
|
||||
* @return 设备列表
|
||||
*/
|
||||
@GetMapping("/by-type")
|
||||
public List<Device> listByType(@RequestParam String type) {
|
||||
@ -79,6 +114,11 @@ public class DeviceController {
|
||||
|
||||
/**
|
||||
* 7. 设备查询(类型 + 名称)
|
||||
* 输入参数:查询参数 type(可选),name(可选)
|
||||
* 输出参数:设备列表(按创建时间倒序)
|
||||
* @param type 设备类型(可选)
|
||||
* @param name 设备名称关键词(可选)
|
||||
* @return 设备列表
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
public List<Device> search(@RequestParam(required = false) String type,
|
||||
|
||||
@ -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<Event> listByScenario(@RequestParam String scenarioId) {
|
||||
return eventService.list(
|
||||
new QueryWrapper<Event>()
|
||||
.eq("scenario_id", scenarioId)
|
||||
.orderByDesc("created_at")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除始发事件
|
||||
* 输入参数:路径参数 eventId(事件ID)
|
||||
* 输出参数:标准响应结构,表示删除结果
|
||||
* @param eventId 事件ID
|
||||
* @return 删除结果
|
||||
*/
|
||||
@DeleteMapping("/{eventId}")
|
||||
public ResponseEntity<Map<String, Object>> 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", "删除失败"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<String> 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<Material> search(@RequestParam String name) {
|
||||
|
||||
@ -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<String> ids) {
|
||||
@ -52,6 +69,10 @@ public class ProjectController {
|
||||
|
||||
/**
|
||||
* 4. 导出所有项目
|
||||
* 输入参数:无
|
||||
* 导出描述:返回所有项目的 JSON 数组,作为附件 `projects.json`
|
||||
* 输出参数:附件字节流(application/octet-stream)
|
||||
* @return 附件响应,文件名为 projects.json
|
||||
*/
|
||||
@GetMapping("/export/all")
|
||||
public ResponseEntity<byte[]> 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<byte[]> exportProject(@PathVariable String id) {
|
||||
@ -80,6 +112,10 @@ public class ProjectController {
|
||||
|
||||
/**
|
||||
* 6. 根据项目名称搜索
|
||||
* 输入参数:查询参数 name(项目名称关键词)
|
||||
* 输出参数:项目列表
|
||||
* @param name 项目名称关键词
|
||||
* @return 匹配的项目列表
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
public List<Project> 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<Map<String, Object>> updateTopology(@PathVariable String id,
|
||||
@RequestBody Map<String, Object> 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
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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<String> ids) {
|
||||
@ -49,6 +65,10 @@ public class ScenarioController {
|
||||
|
||||
/**
|
||||
* 4. 根据情景名称搜索
|
||||
* 输入参数:查询参数 name(情景名称关键词)
|
||||
* 输出参数:情景列表(按创建时间倒序)
|
||||
* @param name 情景名称关键词
|
||||
* @return 情景列表
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
public List<Scenario> 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<Scenario> listByProject(@RequestParam String projectId) {
|
||||
return scenarioService.list(
|
||||
new QueryWrapper<Scenario>()
|
||||
.eq("project_id", projectId)
|
||||
.orderByDesc("created_at")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<ScenarioResult> listByScenario(@RequestParam String scenarioId,
|
||||
@RequestParam String deviceId) {
|
||||
return scenarioResultService.list(
|
||||
new QueryWrapper<ScenarioResult>()
|
||||
.eq("scenario_id", scenarioId)
|
||||
.eq("device_id", deviceId)
|
||||
.orderByAsc("step")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -11,8 +11,5 @@ public interface CriticalDataService extends IService<CriticalData> {
|
||||
*/
|
||||
boolean importCriticalData(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 获取设备类型列表(去重)
|
||||
*/
|
||||
List<String> listDeviceTypes();
|
||||
|
||||
}
|
||||
|
||||
@ -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<Device> {
|
||||
/**
|
||||
* 导入设备
|
||||
*/
|
||||
boolean importDevices(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 获取设备类型列表(去重)
|
||||
*/
|
||||
List<String> listDeviceTypes();
|
||||
}
|
||||
|
||||
@ -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<CriticalDataMapper, CriticalData>
|
||||
implements CriticalDataService {
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
@Override
|
||||
public boolean importCriticalData(MultipartFile file) {
|
||||
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<String> 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<String, Integer> 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<CriticalData> 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<String, Integer> 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<CriticalData> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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<DeviceMapper, Device>
|
||||
implements DeviceService {
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
@Override
|
||||
public boolean importDevices(MultipartFile file) {
|
||||
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<String> 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<String, Integer> 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<Device> 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<String, Integer> 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<Device> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<MaterialMapper, Material>
|
||||
implements MaterialService {
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
@Override
|
||||
public boolean importMaterials(MultipartFile file) {
|
||||
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<String, Integer> 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<Material> 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<String, Integer> 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<Material> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<ProjectMapper, Project>
|
||||
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<Project> 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<Device> devices = deviceService.list(
|
||||
new QueryWrapper<Device>().eq("project_id", projectId)
|
||||
);
|
||||
List<Material> materials = materialService.list(
|
||||
new QueryWrapper<Material>().eq("project_id", projectId)
|
||||
);
|
||||
List<Scenario> scenarios = scenarioService.list(
|
||||
new QueryWrapper<Scenario>().eq("project_id", projectId)
|
||||
);
|
||||
List<String> scenarioIds = scenarios.stream().map(Scenario::getScenarioId).toList();
|
||||
|
||||
List<Event> events = scenarioIds.isEmpty()
|
||||
? List.of()
|
||||
: eventService.list(new QueryWrapper<Event>().in("scenario_id", scenarioIds));
|
||||
List<ScenarioResult> results = scenarioIds.isEmpty()
|
||||
? List.of()
|
||||
: scenarioResultService.list(new QueryWrapper<ScenarioResult>().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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user