From 02375f3b0333d45f48ea5dcbe87ebe4743659f36 Mon Sep 17 00:00:00 2001 From: wanxiaoli Date: Wed, 24 Dec 2025 15:46:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=9B=E5=BB=BA=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 8 + .../css/controller/AlgorithmController.java | 22 ++ .../controller/CriticalDataController.java | 3 +- .../css/controller/DeviceController.java | 24 ++- .../css/controller/EventController.java | 24 ++- .../css/controller/MaterialController.java | 22 +- .../css/controller/ProjectController.java | 24 +++ .../css/controller/ScenarioController.java | 22 ++ .../service/impl/CriticalDataServiceImpl.java | 191 +++++++++++------- .../css/service/impl/DeviceServiceImpl.java | 71 ++----- .../css/service/impl/MaterialServiceImpl.java | 77 ++----- .../main/resources/application-business.yml | 11 +- 系统代码结构框架规划.md | 3 + 13 files changed, 310 insertions(+), 192 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index b2cf7c3..014e576 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,5 +1,13 @@ { "configurations": [ + { + "type": "java", + "name": "Attach to Remote Program(5005)", + "request": "attach", + "hostName": "localhost", + "port": "5005" + }, + java { "type": "java", "name": "CriticalScenarioApplication", diff --git a/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java b/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java index 0c05ddc..9fe11ad 100644 --- a/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java +++ b/business-css/src/main/java/com/yfd/business/css/controller/AlgorithmController.java @@ -4,10 +4,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.business.css.domain.Algorithm; import com.yfd.business.css.service.AlgorithmService; +import com.yfd.platform.system.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import java.util.List; +import java.time.LocalDateTime; @RestController @RequestMapping("/api/algorithms") @@ -15,6 +20,8 @@ public class AlgorithmController { @Autowired private AlgorithmService algorithmService; + @Autowired + private IUserService userService; @GetMapping("/{id}") @@ -24,12 +31,15 @@ public class AlgorithmController { @PostMapping public boolean createAlgorithm(@RequestBody Algorithm algorithm) { + algorithm.setModifier(currentUsername()); return algorithmService.save(algorithm); } @PutMapping("/{id}") public boolean updateAlgorithm(@PathVariable String id, @RequestBody Algorithm algorithm) { algorithm.setAlgorithmId(id); + algorithm.setModifier(currentUsername()); + algorithm.setUpdatedAt(LocalDateTime.now()); return algorithmService.updateById(algorithm); } @@ -63,4 +73,16 @@ public class AlgorithmController { Page page = new Page<>(pageNum, pageSize); return algorithmService.page(page, queryWrapper); } + + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 14b3695..251412e 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 @@ -66,9 +66,10 @@ public class CriticalDataController { } /** - * 4. 导入临界数据(Excel/CSV) + * 4. 导入临界数据(Excel) * 输入参数:表单文件字段 file * 模板表头:device_type, diameter, height, fissile_concentration, isotopic_abundance, keff_value, extra_features + * excel文件中,diameter,height,fissile_concentration, isotopic_abundance支持数值型,公式型 * 采集规则:仅采集上述字段,表头中多余字段不予采集;extra_features 校验为合法 JSON,非法或占位符将置为 null * 输出参数:布尔值,表示是否导入成功 * @param file Excel/CSV 文件 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 0381e34..9395d64 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 @@ -4,11 +4,16 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.business.css.domain.Device; import com.yfd.business.css.service.DeviceService; +import com.yfd.platform.system.service.IUserService; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import jakarta.annotation.Resource; import java.util.List; +import java.time.LocalDateTime; @RestController @RequestMapping("/devices") @@ -16,6 +21,8 @@ public class DeviceController { @Resource private DeviceService deviceService; + @Resource + private IUserService userService; /** * 1. 新增设备 @@ -26,6 +33,7 @@ public class DeviceController { */ @PostMapping public boolean create(@RequestBody Device device) { + device.setModifier(currentUsername()); return deviceService.save(device); } @@ -38,6 +46,8 @@ public class DeviceController { */ @PutMapping public boolean update(@RequestBody Device device) { + device.setModifier(currentUsername()); + device.setUpdatedAt(LocalDateTime.now()); return deviceService.updateById(device); } @@ -66,7 +76,7 @@ public class DeviceController { } /** - * 4. 导入设备(Excel/CSV) + * 4. 导入设备(Excel) * 输入参数:表单文件字段 file * 模板表头:type, code, name, size, volume, flow_rate, pulse_velocity * 采集规则:仅采集上述字段,表头中多余字段不予采集;size 校验为合法 JSON,非法或占位符将置为 null;导入记录的 project_id 统一写入 -1 @@ -126,4 +136,16 @@ public class DeviceController { return deviceService.page(page, wrapper.orderByDesc("created_at")); } + + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 8dc0412..1042be0 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 @@ -2,12 +2,17 @@ package com.yfd.business.css.controller; import com.yfd.business.css.domain.Event; import com.yfd.business.css.service.EventService; +import com.yfd.platform.system.service.IUserService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import java.util.Map; import java.util.List; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashMap; @@ -23,10 +28,12 @@ public class EventController { private final EventService eventService; private final ObjectMapper objectMapper; + private final IUserService userService; - public EventController(EventService eventService, ObjectMapper objectMapper) { + public EventController(EventService eventService, ObjectMapper objectMapper, IUserService userService) { this.eventService = eventService; this.objectMapper = objectMapper; + this.userService = userService; } /** @@ -55,6 +62,8 @@ public class EventController { public ResponseEntity> updateEvent(@PathVariable String eventId, @RequestBody Event event) { event.setEventId(eventId); + event.setModifier(currentUsername()); + event.setUpdatedAt(LocalDateTime.now()); boolean ok = eventService.updateById(event); if (!ok) { return ResponseEntity.badRequest().body(Map.of( @@ -96,6 +105,7 @@ public class EventController { Event updatedEvent = new Event(); updatedEvent.setEventId(eventId); updatedEvent.setAttrChanges(String.valueOf(attrChanges)); + updatedEvent.setModifier(currentUsername()); eventService.updateById(updatedEvent); return ResponseEntity.ok(Map.of( "code", 0, @@ -268,4 +278,16 @@ public class EventController { return 0.0; } } + + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 2fd637d..bae544b 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 @@ -4,11 +4,16 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.business.css.domain.Material; import com.yfd.business.css.service.MaterialService; +import com.yfd.platform.system.service.IUserService; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import jakarta.annotation.Resource; import java.util.List; +import java.time.LocalDateTime; @RestController @RequestMapping("/materials") @@ -16,6 +21,8 @@ public class MaterialController { @Resource private MaterialService materialService; + @Resource + private IUserService userService; /** * 1. 新增物料 @@ -26,6 +33,7 @@ public class MaterialController { */ @PostMapping public boolean create(@RequestBody Material material) { + material.setModifier(currentUsername()); return materialService.save(material); } @@ -38,6 +46,8 @@ public class MaterialController { */ @PutMapping public boolean update(@RequestBody Material material) { + material.setModifier(currentUsername()); + material.setUpdatedAt(LocalDateTime.now()); return materialService.updateById(material); } @@ -111,5 +121,15 @@ public class MaterialController { return materialService.page(page, wrapper); } - + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 17e68d9..3a8e8d2 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 @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.business.css.domain.Project; import com.yfd.business.css.service.ProjectService; +import com.yfd.platform.system.service.IUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -11,6 +12,9 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import jakarta.annotation.Resource; import java.util.List; @@ -21,6 +25,7 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.time.format.DateTimeFormatter; +import java.time.LocalDateTime; @RestController @RequestMapping("/projects") @@ -31,6 +36,8 @@ public class ProjectController { private ProjectService projectService; @Resource private com.fasterxml.jackson.databind.ObjectMapper objectMapper; + @Resource + private IUserService userService; /** * 1. 新增项目 @@ -42,6 +49,7 @@ public class ProjectController { @PostMapping @Operation(summary = "新增项目", description = "请求体传入项目对象,返回是否新增成功") public boolean create(@RequestBody Project project) { + project.setModifier(currentUsername()); return projectService.save(project); } @@ -55,9 +63,23 @@ public class ProjectController { @PutMapping @Operation(summary = "修改项目", description = "请求体传入项目对象(需包含主键),返回是否修改成功") public boolean update(@RequestBody Project project) { + project.setModifier(currentUsername()); + project.setUpdatedAt(LocalDateTime.now()); return projectService.updateById(project); } + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } + /** * 3.1 删除项目(单条) * 输入参数:路径参数项目ID @@ -198,6 +220,8 @@ public class ProjectController { Project updated = new Project(); updated.setProjectId(id); updated.setTopology(json); + updated.setModifier(currentUsername()); + updated.setUpdatedAt(LocalDateTime.now()); projectService.updateById(updated); return ResponseEntity.ok(Map.of( "code", 0, 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 b3d7589..c7d7141 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 @@ -4,10 +4,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.business.css.domain.Scenario; import com.yfd.business.css.service.ScenarioService; +import com.yfd.platform.system.service.IUserService; import org.springframework.web.bind.annotation.*; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import jakarta.annotation.Resource; import java.util.List; +import java.time.LocalDateTime; @RestController @RequestMapping("/scenarios") @@ -15,6 +20,8 @@ public class ScenarioController { @Resource private ScenarioService scenarioService; + @Resource + private IUserService userService; /** * 1. 新增情景 @@ -25,6 +32,7 @@ public class ScenarioController { */ @PostMapping public boolean create(@RequestBody Scenario scenario) { + scenario.setModifier(currentUsername()); return scenarioService.save(scenario); } @@ -37,6 +45,8 @@ public class ScenarioController { */ @PutMapping public boolean update(@RequestBody Scenario scenario) { + scenario.setModifier(currentUsername()); + scenario.setUpdatedAt(LocalDateTime.now()); return scenarioService.updateById(scenario); } @@ -100,4 +110,16 @@ public class ScenarioController { } return scenarioService.page(page, wrapper.orderByDesc("created_at")); } + + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 14fc953..488547d 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 @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.business.css.domain.CriticalData; import com.yfd.business.css.mapper.CriticalDataMapper; import com.yfd.business.css.service.CriticalDataService; +import com.yfd.platform.system.service.IUserService; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -11,55 +12,71 @@ 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.ss.usermodel.DataFormatter; +import org.apache.poi.ss.usermodel.FormulaEvaluator; 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 org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; 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; +import lombok.extern.slf4j.Slf4j; @Service +@Slf4j public class CriticalDataServiceImpl extends ServiceImpl implements CriticalDataService { @Resource private ObjectMapper objectMapper; + @Resource + private IUserService userService; @Override public boolean importCriticalData(MultipartFile file) { try { String name = file.getOriginalFilename(); + log.info("critical-data import start name={} size={} contentType={}", name, file.getSize(), file.getContentType()); if (name == null) return false; String lower = name.toLowerCase(); if (lower.endsWith(".xlsx")) { + log.info("critical-data detected type=xlsx"); return importExcel(new XSSFWorkbook(file.getInputStream())); } else if (lower.endsWith(".xls")) { + log.info("critical-data detected type=xls"); return importExcel(new HSSFWorkbook(file.getInputStream())); - } else if (lower.endsWith(".csv")) { - return importCsv(file.getInputStream()); } else { + log.warn("critical-data unsupported file type name={}", name); return false; } } catch (Exception e) { + log.error("critical-data import failed", e); return false; } } private boolean importExcel(Workbook workbook) { try (Workbook wb = workbook) { + FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + evaluator.evaluateAll(); + DataFormatter formatter = new DataFormatter(); Sheet sheet = wb.getSheetAt(0); - if (sheet == null) return false; + if (sheet == null) { + log.warn("critical-data excel sheet null"); + return false; + } Row headerRow = sheet.getRow(0); - if (headerRow == null) return false; + if (headerRow == null) { + log.warn("critical-data excel header row null"); + return false; + } Map idx = new HashMap<>(); for (int i = 0; i < headerRow.getLastCellNum(); i++) { Cell c = headerRow.getCell(i); @@ -67,69 +84,59 @@ public class CriticalDataServiceImpl String key = c.getStringCellValue(); if (key != null) idx.put(key.trim().toLowerCase(), i); } + log.info("critical-data excel header keys={}", idx.keySet()); 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 missing = new ArrayList<>(); + for (String k : keys) if (!idx.containsKey(k)) missing.add(k); + if (!missing.isEmpty()) { + log.warn("critical-data excel missing headers={}", missing); + 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.setDiameter(cleanDecimal(getDecimalFlexible(row, idx.get("diameter"), evaluator, formatter))); + cd.setHeight(cleanDecimal(getDecimalFlexible(row, idx.get("height"), evaluator, formatter))); + cd.setFissileConcentration(cleanDecimal(getDecimalFlexible(row, idx.get("fissile_concentration"), evaluator, formatter))); + cd.setIsotopicAbundance(cleanDecimal(getDecimalFlexible(row, idx.get("isotopic_abundance"), evaluator, formatter))); + cd.setKeffValue(cleanDecimal(getDecimalFlexible(row, idx.get("keff_value"), evaluator, formatter))); + String extraRaw = cleanString(getString(row, idx.get("extra_features"))); + String extra = validateJson(extraRaw); + if (extraRaw != null && extra == null) { + log.warn("critical-data excel invalid JSON at row={} raw={}", r, extraRaw); + } + cd.setExtraFeatures(extra); cd.setCreatedAt(LocalDateTime.now()); cd.setUpdatedAt(LocalDateTime.now()); - if (isEmpty(cd)) continue; + cd.setModifier(currentUsername()); + List miss = missingRequired(cd); + if (!miss.isEmpty()) { + log.warn("critical-data excel skip row={} missing={}", r, miss); + continue; + } + if (isOutOfRange(cd.getFissileConcentration(), 7, 3)) { + log.warn("critical-data excel skip row={} out_of_range field=fissile_concentration value={}", r, cd.getFissileConcentration()); + 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); + log.info("critical-data excel parsed rows={} valid={}", sheet.getLastRowNum(), list.size()); + if (list.isEmpty()) { + log.warn("critical-data excel parsed list empty"); + return false; } - if (list.isEmpty()) return false; - return this.saveBatch(list); + boolean ok = this.saveBatch(list, 500); + log.info("critical-data excel saveBatch result={}", ok); + return ok; } catch (Exception e) { + log.error("critical-data excel import failed", e); return false; } } @@ -145,27 +152,40 @@ public class CriticalDataServiceImpl } } - private BigDecimal getDecimal(Row row, int i) { + private BigDecimal getDecimalFlexible(Row row, int i, FormulaEvaluator evaluator, DataFormatter formatter) { 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(); + String txt = formatter.formatCellValue(c, evaluator); + return parseDecimal(txt); } private BigDecimal parseDecimal(String s) { if (s == null || s.isEmpty()) return null; - try { return new BigDecimal(s.trim()); } catch (Exception e) { return null; } + String t = s.trim().replace(",", ""); + try { return new BigDecimal(t); } catch (Exception e) { + StringBuilder sb = new StringBuilder(); + boolean started = false; + for (int idx = 0; idx < t.length(); idx++) { + char ch = t.charAt(idx); + if (!started) { + if (ch == '+' || ch == '-' || Character.isDigit(ch)) { + sb.append(ch); + started = true; + } else if (ch == '.') { + sb.append(ch); + started = true; + } + } else { + if (Character.isDigit(ch) || ch == '.') { + sb.append(ch); + } else { + break; + } + } + } + if (sb.length() == 0) return null; + try { return new BigDecimal(sb.toString()); } catch (Exception ex) { return null; } + } } private boolean isPlaceholder(String s) { @@ -182,8 +202,22 @@ public class CriticalDataServiceImpl return d; } - private boolean isEmpty(CriticalData cd) { - return cd.getDeviceType() == null || cd.getDeviceType().isEmpty(); + private List missingRequired(CriticalData cd) { + List miss = new ArrayList<>(); + if (cd.getDeviceType() == null || cd.getDeviceType().isEmpty()) miss.add("device_type"); + if (cd.getHeight() == null) miss.add("height"); + if (cd.getDiameter() == null) miss.add("diameter"); + if (cd.getFissileConcentration() == null) miss.add("fissile_concentration"); + if (cd.getIsotopicAbundance() == null) miss.add("isotopic_abundance"); + if (cd.getKeffValue() == null) miss.add("keff_value"); + return miss; + } + + private boolean isOutOfRange(BigDecimal v, int maxIntegerDigits, int maxScale) { + if (v == null) return false; + int scale = Math.max(v.scale(), 0); + int intDigits = v.precision() - scale; + return intDigits > maxIntegerDigits || scale > maxScale; } private String validateJson(String s) { @@ -195,5 +229,16 @@ public class CriticalDataServiceImpl return null; } } - + + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 28300cc..be2e44b 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 @@ -4,8 +4,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.business.css.domain.Device; import com.yfd.business.css.mapper.DeviceMapper; import com.yfd.business.css.service.DeviceService; +import com.yfd.platform.system.service.IUserService; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; @@ -16,10 +20,6 @@ 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.ArrayList; @@ -32,6 +32,8 @@ public class DeviceServiceImpl implements DeviceService { @Resource private ObjectMapper objectMapper; + @Resource + private IUserService userService; @Override public boolean importDevices(MultipartFile file) { try { @@ -42,8 +44,6 @@ public class DeviceServiceImpl 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; } @@ -84,40 +84,7 @@ public class DeviceServiceImpl 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()); + d.setModifier(currentUsername()); if (isEmpty(d)) continue; devices.add(d); } @@ -150,18 +117,6 @@ public class DeviceServiceImpl } } - 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()); } @@ -175,4 +130,16 @@ public class DeviceServiceImpl return null; } } + + private String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } + } } 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 5d63789..74fa171 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 @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.business.css.domain.Material; import com.yfd.business.css.mapper.MaterialMapper; import com.yfd.business.css.service.MaterialService; +import com.yfd.platform.system.service.IUserService; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -16,10 +17,9 @@ 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 org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AnonymousAuthenticationToken; import java.time.LocalDateTime; import java.math.BigDecimal; import java.util.ArrayList; @@ -33,6 +33,8 @@ public class MaterialServiceImpl implements MaterialService { @Resource private ObjectMapper objectMapper; + @Resource + private IUserService userService; @Override public boolean importMaterials(MultipartFile file) { try { @@ -43,8 +45,6 @@ public class MaterialServiceImpl 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; } @@ -95,50 +95,7 @@ public class MaterialServiceImpl 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()); + m.setModifier(currentUsername()); if (isEmpty(m)) continue; list.add(m); } @@ -171,16 +128,16 @@ public class MaterialServiceImpl } } - 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 String currentUsername() { + try { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth == null || auth instanceof AnonymousAuthenticationToken) { + return "anonymous"; + } + return userService.getUsername(); + } catch (Exception e) { + return "anonymous"; + } } private boolean isEmpty(Material m) { diff --git a/business-css/src/main/resources/application-business.yml b/business-css/src/main/resources/application-business.yml index e40891d..0beb7ad 100644 --- a/business-css/src/main/resources/application-business.yml +++ b/business-css/src/main/resources/application-business.yml @@ -15,10 +15,15 @@ spring: username: root password: ylfw20230626@ -file-space: #项目文档空间 - files: D:\css\files\ #单独上传的文件附件 - system: D:\css\system\ #单独上传的文件 +file-space: + files: D:\css\files\ + system: D:\css\system\ security: dev: permit: true +logging: + file: + name: logs/business-css.log + level: + root: INFO diff --git a/系统代码结构框架规划.md b/系统代码结构框架规划.md index b3addde..4a77d58 100644 --- a/系统代码结构框架规划.md +++ b/系统代码结构框架规划.md @@ -228,6 +228,9 @@ scripts\mvn17.cmd -s mvn-settings.xml -DskipTests -pl framework -am install scripts\mvn17.cmd -s mvn-settings.xml -DskipTests -f business-css\pom.xml spring-boot:run -Dspring-boot.run.profiles=business +- debug方式启动 +scripts\mvn17-debug.cmd -s mvn-settings.xml -DskipTests -f business-css\pom.xml spring-boot:run -Dspring-boot.run.profiles=business + ## 在工具内终端验证并调整到 17: - 验证: mvn -version 、 where java 、 where mvn - 临时修正当前终端(一次性手动):