add:第一版测试版本功能优化。1.F机器人修改调度上报异常信息,后端存储异常信息和异常处理,增加异常信息和异常处理方法excel导入功能。2.添加密码校验、修改密码功能。
This commit is contained in:
@@ -9,8 +9,8 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
public interface SettingAPI {
|
public interface SettingAPI {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据设置编号查询设置参数是否启用
|
* 根据设置编号查询
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
JSONObject querySttingParamIsActiveByCode(String setting_code);
|
JSONObject querySettingParamByCode(String setting_code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.nl.api.sys.anomalyInfo.api;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/30
|
||||||
|
*/
|
||||||
|
public interface ErrorInfoAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据异常码查询异常信息
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
JSONObject queryErrorInfoByCode(Integer code);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.nl.schedule.modular.init;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.nl.api.setting.api.SettingAPI;
|
||||||
|
import org.nl.util.URLConstant;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ScheduleInit {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SettingAPI settingAPI;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
URLConstant.SCHEDULE_IP_PORT = settingAPI.querySettingParamByCode("schedule_ip")
|
||||||
|
.getJSONObject("data")
|
||||||
|
.getString("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -55,7 +55,7 @@ public class ScheduleTaskServiceImpl implements ScheduleTaskService {
|
|||||||
|
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
// 到达时等待设置参数
|
// 到达时等待设置参数
|
||||||
JSONObject jsonObject = settingAPI.querySttingParamIsActiveByCode("call_arrival_waiting_time").getJSONObject("data");
|
JSONObject jsonObject = settingAPI.querySettingParamByCode("call_arrival_waiting_time").getJSONObject("data");
|
||||||
String is_active = jsonObject.getString("is_active");
|
String is_active = jsonObject.getString("is_active");
|
||||||
String arrive_waiting_time = jsonObject.getString("value");
|
String arrive_waiting_time = jsonObject.getString("value");
|
||||||
if (StrUtil.isNotBlank(is_active) && YesOrNoEnum.YES.getCode().equals(is_active)){
|
if (StrUtil.isNotBlank(is_active) && YesOrNoEnum.YES.getCode().equals(is_active)){
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.nl.schedule.modular.vehicle.dto;
|
package org.nl.schedule.modular.vehicle.dto;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.nl.schedule.modular.vehicle.entity.Location;
|
import org.nl.schedule.modular.vehicle.entity.Location;
|
||||||
|
|
||||||
@@ -54,9 +55,19 @@ public class VehicleInfoDto{
|
|||||||
private int signalStrength;
|
private int signalStrength;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异常信息集合
|
* 异常信息编码
|
||||||
*/
|
*/
|
||||||
private List<String> exceptions;
|
private Integer error_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息内容
|
||||||
|
*/
|
||||||
|
private String error_msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息
|
||||||
|
*/
|
||||||
|
private JSONObject error_info;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前位置
|
* 当前位置
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nl.api.sys.anomalyInfo.api.ErrorInfoAPI;
|
||||||
import org.nl.api.task.api.TaskAPI;
|
import org.nl.api.task.api.TaskAPI;
|
||||||
import org.nl.response.WebResponse;
|
import org.nl.response.WebResponse;
|
||||||
import org.nl.schedule.core.websocket.WebSocketVehicleInfoServer;
|
import org.nl.schedule.core.websocket.WebSocketVehicleInfoServer;
|
||||||
@@ -38,6 +39,9 @@ public class VehicleServiceImpl implements VehicleService {
|
|||||||
@Resource
|
@Resource
|
||||||
private TaskAPI taskAPI;
|
private TaskAPI taskAPI;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorInfoAPI errorInfoAPI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时更新车辆信息(每秒执行)
|
* 定时更新车辆信息(每秒执行)
|
||||||
*/
|
*/
|
||||||
@@ -52,6 +56,9 @@ public class VehicleServiceImpl implements VehicleService {
|
|||||||
|
|
||||||
// 更新缓存
|
// 更新缓存
|
||||||
for (VehicleInfoDto vehicle : vehicles) {
|
for (VehicleInfoDto vehicle : vehicles) {
|
||||||
|
if (vehicle.getError_code()!=0) {
|
||||||
|
vehicle.setError_info(errorInfoAPI.queryErrorInfoByCode(vehicle.getError_code()));
|
||||||
|
}
|
||||||
vehicleCache.put(vehicle.getVehicleNumber(), vehicle);
|
vehicleCache.put(vehicle.getVehicleNumber(), vehicle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +85,6 @@ public class VehicleServiceImpl implements VehicleService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<VehicleInfoDto> getAllVehicles() {
|
public List<VehicleInfoDto> getAllVehicles() {
|
||||||
String url = URLConstant.SCHEDULE_IP_PORT+"/vehicles";
|
|
||||||
List<VehicleInfoDto> vehicles = new ArrayList<>();
|
List<VehicleInfoDto> vehicles = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
try (HttpResponse response = HttpRequest.get(URLConstant.SCHEDULE_IP_PORT+"/vehicles")
|
try (HttpResponse response = HttpRequest.get(URLConstant.SCHEDULE_IP_PORT+"/vehicles")
|
||||||
|
|||||||
@@ -37,7 +37,12 @@ public enum SettingCodeEnum {
|
|||||||
/**
|
/**
|
||||||
* 充电时是否可呼叫
|
* 充电时是否可呼叫
|
||||||
*/
|
*/
|
||||||
CAN_IT_BE_CALLED_WHILE_CHARGING("6", "can_it_be_called_while_charging", "充电时是否可呼叫");
|
CAN_IT_BE_CALLED_WHILE_CHARGING("6", "can_it_be_called_while_charging", "充电时是否可呼叫"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示屏密码
|
||||||
|
*/
|
||||||
|
SCREEN_PASSWORD("7", "password", "显示屏密码");
|
||||||
|
|
||||||
private String code;
|
private String code;
|
||||||
private String name;
|
private String name;
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ public class SettingAPIProvider implements SettingAPI {
|
|||||||
private SettingService settingService;
|
private SettingService settingService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject querySttingParamIsActiveByCode(String setting_code) {
|
public JSONObject querySettingParamByCode(String setting_code) {
|
||||||
if (StrUtil.isBlank(setting_code)){
|
if (StrUtil.isBlank(setting_code)){
|
||||||
log.info("设置编号不能为空");
|
log.info("设置编号不能为空");
|
||||||
throw new BadRequestException("设置编号不能为空");
|
return null;
|
||||||
}
|
}
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("data",settingService.getOne(new LambdaQueryWrapper<>(Setting.class).eq(Setting::getSetting_code,setting_code)));
|
result.put("data",settingService.getOne(new LambdaQueryWrapper<>(Setting.class).eq(Setting::getSetting_code,setting_code)));
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.nl.setting.modular.service.impl;
|
package org.nl.setting.modular.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.secure.SaSecureUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@@ -20,6 +21,8 @@ import org.nl.setting.modular.enums.SettingCodeEnum;
|
|||||||
import org.nl.setting.modular.mapper.SettingMapper;
|
import org.nl.setting.modular.mapper.SettingMapper;
|
||||||
import org.nl.setting.modular.param.UpdateSettingParam;
|
import org.nl.setting.modular.param.UpdateSettingParam;
|
||||||
import org.nl.setting.modular.service.SettingService;
|
import org.nl.setting.modular.service.SettingService;
|
||||||
|
import org.nl.util.RsaUtils;
|
||||||
|
import org.nl.util.URLConstant;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -66,6 +69,7 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
|
|||||||
switch (settingCodeEnum){
|
switch (settingCodeEnum){
|
||||||
case SCHEDULE_IP:
|
case SCHEDULE_IP:
|
||||||
log.info("修改调度IP");
|
log.info("修改调度IP");
|
||||||
|
URLConstant.SCHEDULE_IP_PORT = setting_value;
|
||||||
break;
|
break;
|
||||||
case DELIVERY_SPEED:
|
case DELIVERY_SPEED:
|
||||||
log.info("修改配送速度");
|
log.info("修改配送速度");
|
||||||
@@ -120,6 +124,11 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
|
|||||||
throw new BadRequestException("设置调度可接任务阈值失败");
|
throw new BadRequestException("设置调度可接任务阈值失败");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SCREEN_PASSWORD:
|
||||||
|
log.info("修改显示屏密码");
|
||||||
|
String newPassword = RsaUtils.decryptByPrivateKey(RsaUtils.privateKey,setting_value);
|
||||||
|
setting_value = SaSecureUtil.md5BySalt(newPassword,"salt");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
settingMapper.update(new LambdaUpdateWrapper<>(Setting.class)
|
settingMapper.update(new LambdaUpdateWrapper<>(Setting.class)
|
||||||
|
|||||||
@@ -27,6 +27,19 @@
|
|||||||
<groupId>org.nl</groupId>
|
<groupId>org.nl</groupId>
|
||||||
<artifactId>nl-business-api</artifactId>
|
<artifactId>nl-business-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- easyexcel -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>easyexcel</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sa-token -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.controller;
|
||||||
|
|
||||||
|
import com.alibaba.excel.EasyExcel;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.nl.exception.BadRequestException;
|
||||||
|
import org.nl.logging.annotation.Log;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.listener.ErrorHandlingListener;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.listener.ErrorInfoListener;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.AnomalyInfoService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.ErrorHandlingService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.ErrorInfoService;
|
||||||
|
import org.nl.util.FileConstant;
|
||||||
|
import org.nl.util.ParseZip;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/anomalyInfo")
|
||||||
|
public class AnomalyInfoController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AnomalyInfoService anomalyInfoService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorInfoService errorInfoService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorHandlingService errorHandlingService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ParseZip parseZip;
|
||||||
|
|
||||||
|
@PostMapping("/queryErrorDataByCode")
|
||||||
|
@Log("根据异常编号查询异常数据")
|
||||||
|
public ResponseEntity<Object> queryErrorDataByCode(@RequestParam("code") String code) {
|
||||||
|
return new ResponseEntity<>(anomalyInfoService.queryErrorDataByCode(code), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/importErrorInfoExcel")
|
||||||
|
@Log("导入excel异常信息")
|
||||||
|
public ResponseEntity<Object> importErrorInfoExcel(@RequestParam("file") MultipartFile file) throws IOException {
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
throw new BadRequestException("请选择文件上传");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建监听器实例,传入所需的Service
|
||||||
|
ErrorInfoListener listener = new ErrorInfoListener(errorInfoService);
|
||||||
|
|
||||||
|
// 读取Excel文件
|
||||||
|
// withFile(file.getInputStream())... 也可以
|
||||||
|
|
||||||
|
EasyExcel.read(file.getInputStream(), ErrorInfo.class, listener)
|
||||||
|
.sheet() // 默认读取第一个sheet
|
||||||
|
.doRead();
|
||||||
|
return new ResponseEntity<>("操作成功",HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/importErrorHandlingExcel")
|
||||||
|
@Log("导入excel异常处理信息")
|
||||||
|
public ResponseEntity<Object> importErrorHandlingExcel(@RequestParam("file") MultipartFile file) throws IOException {
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
throw new BadRequestException("请选择文件上传");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建监听器实例,传入所需的Service
|
||||||
|
ErrorHandlingListener listener = new ErrorHandlingListener(errorHandlingService);
|
||||||
|
|
||||||
|
// 读取Excel文件
|
||||||
|
// withFile(file.getInputStream())... 也可以
|
||||||
|
|
||||||
|
EasyExcel.read(file.getInputStream(), ErrorHandling.class, listener)
|
||||||
|
.sheet() // 默认读取第一个sheet
|
||||||
|
.doRead();
|
||||||
|
return new ResponseEntity<>("操作成功",HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/importErrorImage")
|
||||||
|
@Log("导入异常图片")
|
||||||
|
public ResponseEntity<Object> importErrorImage(@RequestParam("file") MultipartFile file) throws IOException {
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
throw new BadRequestException("文件不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
if (originalFilename == null ||
|
||||||
|
(!originalFilename.toLowerCase().endsWith(".zip"))) {
|
||||||
|
throw new BadRequestException("目前只支持ZIP格式");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建上传目录
|
||||||
|
File uploadDir = new File(FileConstant.ERROR_IMAGE_PATH);
|
||||||
|
if (!uploadDir.exists()) {
|
||||||
|
uploadDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理压缩文件
|
||||||
|
parseZip.processCompressedFile(file);
|
||||||
|
|
||||||
|
|
||||||
|
return new ResponseEntity<>("上传成功!",HttpStatus.OK);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BadRequestException("处理文件失败:{}"+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.dao;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("error_handling")
|
||||||
|
public class ErrorHandling {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理标识
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
@ExcelProperty(index = 0,value = "标识")
|
||||||
|
private String error_handling_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息编码
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 1,value = "异常编码")
|
||||||
|
private String error_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理类型(1 图文说明 2视频说明)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 2,value = "异常处理类型(1图文说明2视频说明)")
|
||||||
|
private Integer error_handling_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理说明
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 3,value = "异常处理说明")
|
||||||
|
private String error_handling_title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中文异常处理说明
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 4,value = "异常处理说明(中文)")
|
||||||
|
private String zh_error_handling_title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 英文异常处理说明
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 5,value = "异常处理说明(英文)")
|
||||||
|
private String en_error_handling_title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理排序
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 6,value = "异常处理排序")
|
||||||
|
private Integer error_handling_seq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常处理地址(图片 或 视频地址)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 7,value = "异常处理地址(图片或视频地址)")
|
||||||
|
private String error_handling_addre;
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.dao;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("error_info")
|
||||||
|
public class ErrorInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息标识
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
@ExcelProperty(index = 0,value = "唯一标识")
|
||||||
|
private String error_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 1,value = "异常名称")
|
||||||
|
private String error_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中文异常信息名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 2,value = "异常名称(中文)")
|
||||||
|
private String zh_error_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 英文异常信息名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 3,value = "异常名称(英文)")
|
||||||
|
private String en_error_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息编码
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 4,value = "异常编号")
|
||||||
|
private String error_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息类别(1普通故障 2严重故障)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 5,value = "异常类别(1普通故障,2严重故障)")
|
||||||
|
private Integer error_category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常说明
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 6,value = "异常说明")
|
||||||
|
private String error_description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中文异常说明
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 7,value = "异常说明(中文)")
|
||||||
|
private String zh_error_description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 英文异常说明
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 8,value = "异常说明(英文)")
|
||||||
|
private String en_error_description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常信息类型(1电气 2导航)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(index = 9,value = "异常类型(1电气,2导航)")
|
||||||
|
private Integer error_type;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ErrorDataDto extends ErrorInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图文异常处理
|
||||||
|
*/
|
||||||
|
private List<ErrorHandling> graphicDescription;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频异常处理
|
||||||
|
*/
|
||||||
|
private List<ErrorHandling> videoDescription;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.listener;
|
||||||
|
|
||||||
|
import com.alibaba.excel.context.AnalysisContext;
|
||||||
|
import com.alibaba.excel.event.AnalysisEventListener;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nl.exception.BadRequestException;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ErrorHandlingListener extends AnalysisEventListener<ErrorHandling> {
|
||||||
|
/**
|
||||||
|
* 每隔 BATCH_COUNT 条存储数据库,然后清理list,方便内存回收
|
||||||
|
*/
|
||||||
|
private static final int BATCH_COUNT = 1000; // 批处理阈值:cite[2]:cite[5]
|
||||||
|
|
||||||
|
private List<ErrorHandling> cachedDataList = new ArrayList<>(BATCH_COUNT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 假设我们需要Service进行批量插入
|
||||||
|
* 也可以使用Mapper,但Service层封装批量操作更常见
|
||||||
|
*/
|
||||||
|
private IService<ErrorHandling> service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过构造器传入需要的Service或Mapper
|
||||||
|
*/
|
||||||
|
public ErrorHandlingListener(IService<ErrorHandling> service) {
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每读一行数据,都会调用此方法
|
||||||
|
* @param data 一行数据,类型是泛型T
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void invoke(ErrorHandling data, AnalysisContext context) {
|
||||||
|
cachedDataList.add(data);
|
||||||
|
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
|
||||||
|
if (cachedDataList.size() >= BATCH_COUNT) {
|
||||||
|
saveData();
|
||||||
|
// 存储完成清理 list
|
||||||
|
cachedDataList.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有数据解析完成后,会调用此方法
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||||
|
// 确保最后一批数据也持久化到数据库
|
||||||
|
if (!cachedDataList.isEmpty()) {
|
||||||
|
saveData();
|
||||||
|
cachedDataList.clear();
|
||||||
|
}
|
||||||
|
log.info("所有Excel数据解析并导入完成!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存数据到数据库
|
||||||
|
* 使用MyBatis-Plus的saveBatch方法
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveData() {
|
||||||
|
if (!cachedDataList.isEmpty()) {
|
||||||
|
// 清除所有异常信息 重新导入
|
||||||
|
service.remove(new QueryWrapper<ErrorHandling>());
|
||||||
|
// 第二个参数是批次大小
|
||||||
|
boolean saveResult = service.saveBatch(cachedDataList, BATCH_COUNT);
|
||||||
|
if (saveResult) {
|
||||||
|
log.info("成功批量插入 {} 条数据。", cachedDataList.size());
|
||||||
|
} else {
|
||||||
|
log.error("批量插入数据失败!");
|
||||||
|
throw new BadRequestException("操作失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.listener;
|
||||||
|
|
||||||
|
import com.alibaba.excel.context.AnalysisContext;
|
||||||
|
import com.alibaba.excel.event.AnalysisEventListener;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nl.exception.BadRequestException;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ErrorInfoListener extends AnalysisEventListener<ErrorInfo> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每隔 BATCH_COUNT 条存储数据库,然后清理list,方便内存回收
|
||||||
|
*/
|
||||||
|
private static final int BATCH_COUNT = 1000; // 批处理阈值:cite[2]:cite[5]
|
||||||
|
|
||||||
|
private List<ErrorInfo> cachedDataList = new ArrayList<>(BATCH_COUNT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 假设我们需要Service进行批量插入
|
||||||
|
* 也可以使用Mapper,但Service层封装批量操作更常见
|
||||||
|
*/
|
||||||
|
private IService<ErrorInfo> service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过构造器传入需要的Service或Mapper
|
||||||
|
*/
|
||||||
|
public ErrorInfoListener(IService<ErrorInfo> service) {
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每读一行数据,都会调用此方法
|
||||||
|
* @param data 一行数据,类型是泛型T
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void invoke(ErrorInfo data, AnalysisContext context) {
|
||||||
|
cachedDataList.add(data);
|
||||||
|
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
|
||||||
|
if (cachedDataList.size() >= BATCH_COUNT) {
|
||||||
|
saveData();
|
||||||
|
// 存储完成清理 list
|
||||||
|
cachedDataList.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有数据解析完成后,会调用此方法
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||||
|
// 确保最后一批数据也持久化到数据库
|
||||||
|
if (!cachedDataList.isEmpty()) {
|
||||||
|
saveData();
|
||||||
|
cachedDataList.clear();
|
||||||
|
}
|
||||||
|
log.info("所有Excel数据解析并导入完成!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量保存数据到数据库
|
||||||
|
* 使用MyBatis-Plus的saveBatch方法
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveData() {
|
||||||
|
if (!cachedDataList.isEmpty()) {
|
||||||
|
// 清除所有异常信息 重新导入
|
||||||
|
service.remove(new QueryWrapper<ErrorInfo>());
|
||||||
|
// 第二个参数是批次大小
|
||||||
|
boolean saveResult = service.saveBatch(cachedDataList, BATCH_COUNT);
|
||||||
|
if (saveResult) {
|
||||||
|
log.info("成功批量插入 {} 条数据。", cachedDataList.size());
|
||||||
|
} else {
|
||||||
|
log.error("批量插入数据失败!");
|
||||||
|
throw new BadRequestException("操作失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ErrorHandlingMapper extends BaseMapper<ErrorHandling> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ErrorInfoMapper extends BaseMapper<ErrorInfo> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.provider;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nl.api.sys.anomalyInfo.api.ErrorInfoAPI;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.ErrorInfoService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/30
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ErrorInfoAPIProvider implements ErrorInfoAPI {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorInfoService errorInfoService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject queryErrorInfoByCode(Integer code) {
|
||||||
|
if (ObjectUtil.isEmpty(code)){
|
||||||
|
log.info("异常码不能为空");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ErrorInfo errorInfo = errorInfoService.getOne(new LambdaQueryWrapper<>(ErrorInfo.class)
|
||||||
|
.eq(ErrorInfo::getError_code,code)
|
||||||
|
);
|
||||||
|
return errorInfo == null ? null : JSONObject.parseObject(JSONObject.toJSONString(errorInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.service;
|
||||||
|
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dto.ErrorDataDto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
public interface AnomalyInfoService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据异常编码查询处理方法
|
||||||
|
* @param code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ErrorDataDto queryErrorDataByCode(String code);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
public interface ErrorHandlingService extends IService<ErrorHandling> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
public interface ErrorInfoService extends IService<ErrorInfo> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dto.ErrorDataDto;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.AnomalyInfoService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.mapper.ErrorHandlingMapper;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.mapper.ErrorInfoMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class AnomalyInfoServiceImpl implements AnomalyInfoService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorHandlingMapper errorHandlingMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ErrorInfoMapper errorInfoMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ErrorDataDto queryErrorDataByCode(String code) {
|
||||||
|
|
||||||
|
ErrorDataDto errorDataDto = new ErrorDataDto();
|
||||||
|
// 异常信息
|
||||||
|
ErrorInfo errorInfo = errorInfoMapper.selectOne(new LambdaQueryWrapper<>(ErrorInfo.class).eq(ErrorInfo::getError_code,code));
|
||||||
|
BeanUtil.copyProperties(errorInfo,errorDataDto);
|
||||||
|
// 异常处理
|
||||||
|
List<ErrorHandling> errorHandlingList = errorHandlingMapper.selectList(new LambdaQueryWrapper<>(ErrorHandling.class).eq(ErrorHandling::getError_code,code));
|
||||||
|
// 图文说明
|
||||||
|
List<ErrorHandling> graphicDescription = errorHandlingList.stream().filter(errorHandling -> errorHandling.getError_handling_type() == 1).collect(Collectors.toList());
|
||||||
|
// 视频说明
|
||||||
|
List<ErrorHandling> videoDescription = errorHandlingList.stream().filter(errorHandling -> errorHandling.getError_handling_type() == 2).collect(Collectors.toList());
|
||||||
|
errorDataDto.setGraphicDescription(graphicDescription);
|
||||||
|
errorDataDto.setVideoDescription(videoDescription);
|
||||||
|
return errorDataDto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorHandling;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.ErrorHandlingService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.mapper.ErrorHandlingMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class ErrorHandlingServiceImpl extends ServiceImpl<ErrorHandlingMapper, ErrorHandling> implements ErrorHandlingService {
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.nl.sys.modular.anomalyInfo.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.dao.ErrorInfo;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.service.ErrorInfoService;
|
||||||
|
import org.nl.sys.modular.anomalyInfo.mapper.ErrorInfoMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class ErrorInfoServiceImpl extends ServiceImpl<ErrorInfoMapper, ErrorInfo> implements ErrorInfoService {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.nl.sys.modular.secutiry.controller;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.nl.logging.annotation.Log;
|
||||||
|
import org.nl.sys.modular.secutiry.param.SecurityParam;
|
||||||
|
import org.nl.sys.modular.secutiry.service.SecurityService;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/30
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/security")
|
||||||
|
public class SecurityController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SecurityService securityService;
|
||||||
|
|
||||||
|
@PostMapping("/verifyPasswords")
|
||||||
|
@Log("校验显示屏密码")
|
||||||
|
public ResponseEntity<Object> verifyPasswords(@RequestBody SecurityParam param){
|
||||||
|
return new ResponseEntity<>(securityService.verifyPasswords(param.getPassword()), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.nl.sys.modular.secutiry.param;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SecurityParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "密码不能为空")
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.nl.sys.modular.secutiry.service;
|
||||||
|
|
||||||
|
import org.nl.response.WebResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/30
|
||||||
|
*/
|
||||||
|
public interface SecurityService {
|
||||||
|
|
||||||
|
WebResponse verifyPasswords(String password);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package org.nl.sys.modular.secutiry.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.secure.SaSecureUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.nl.api.setting.api.SettingAPI;
|
||||||
|
import org.nl.exception.BadRequestException;
|
||||||
|
import org.nl.response.WebResponse;
|
||||||
|
import org.nl.sys.modular.secutiry.service.SecurityService;
|
||||||
|
import org.nl.util.RsaUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/30
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SecurityServiceImpl implements SecurityService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SettingAPI settingAPI;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public WebResponse verifyPasswords(String password) {
|
||||||
|
String new_password = RsaUtils.decryptByPrivateKey(RsaUtils.privateKey,password);
|
||||||
|
JSONObject setting = settingAPI.querySettingParamByCode("password").getJSONObject("data");
|
||||||
|
if (ObjectUtil.isEmpty(setting) || !setting.getString("value").equals(SaSecureUtil.md5BySalt(new_password,"salt"))) {
|
||||||
|
throw new BadRequestException("密码错误");
|
||||||
|
}
|
||||||
|
return WebResponse.requestOk();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,5 +71,11 @@
|
|||||||
<groupId>com.google.zxing</groupId>
|
<groupId>com.google.zxing</groupId>
|
||||||
<artifactId>javase</artifactId>
|
<artifactId>javase</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Sa-token -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.dev33</groupId>
|
||||||
|
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
23
nl-common/src/main/java/org/nl/util/FileConstant.java
Normal file
23
nl-common/src/main/java/org/nl/util/FileConstant.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package org.nl.util;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class FileConstant {
|
||||||
|
|
||||||
|
public static String ERROR_IMAGE_PATH = "";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FileProperties properties;
|
||||||
|
|
||||||
|
@Value("${customize.errorImage-dir}")
|
||||||
|
public void setErrorImagePath(String errorImagePath) {
|
||||||
|
FileConstant.ERROR_IMAGE_PATH = properties.getPath().getPath()+errorImagePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
128
nl-common/src/main/java/org/nl/util/ParseZip.java
Normal file
128
nl-common/src/main/java/org/nl/util/ParseZip.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package org.nl.util;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nl.exception.BadRequestException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author dsh
|
||||||
|
* 2025/12/29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ParseZip {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理上传的异常文件
|
||||||
|
* @param file
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void processCompressedFile(MultipartFile file) throws IOException {
|
||||||
|
List<String> skippedFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
String filename = file.getOriginalFilename();
|
||||||
|
String extension = filename.substring(filename.lastIndexOf("."));
|
||||||
|
|
||||||
|
try (InputStream inputStream = file.getInputStream()) {
|
||||||
|
if (extension.toLowerCase().equals(".zip")) {
|
||||||
|
extractZipFile(inputStream, skippedFiles);
|
||||||
|
} else {
|
||||||
|
throw new BadRequestException("不支持的压缩格式: " + extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解压上传异常图片压缩文件
|
||||||
|
* @param inputStream
|
||||||
|
* @param skippedFiles
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void extractZipFile(InputStream inputStream, List<String> skippedFiles)
|
||||||
|
throws IOException {
|
||||||
|
int processedCount = 0;
|
||||||
|
int skippedCount = 0;
|
||||||
|
|
||||||
|
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||||
|
if (!entry.isDirectory() && isImageFile(entry.getName())) {
|
||||||
|
String filename = new File(entry.getName()).getName();
|
||||||
|
|
||||||
|
if (isFileExists(filename)) {
|
||||||
|
skippedFiles.add(filename);
|
||||||
|
skippedCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveImageFile(zipInputStream, filename)) {
|
||||||
|
processedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zipInputStream.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("处理文件数:{},跳过文件数:{},跳过文件名称集合:{}",processedCount,skippedCount,skippedFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存图片文件到目录
|
||||||
|
* @param inputStream
|
||||||
|
* @param filename
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean saveImageFile(InputStream inputStream, String filename) {
|
||||||
|
try {
|
||||||
|
File outputFile = new File(FileConstant.ERROR_IMAGE_PATH + "/" + filename);
|
||||||
|
|
||||||
|
// 确保目录存在
|
||||||
|
File parentDir = outputFile.getParentFile();
|
||||||
|
if (!parentDir.exists()) {
|
||||||
|
parentDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
Files.copy(inputStream, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("保存文件失败: " + filename, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否是图片文件或者视频文件
|
||||||
|
* @param filename
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isImageFile(String filename) {
|
||||||
|
String lowerCaseFilename = filename.toLowerCase();
|
||||||
|
return lowerCaseFilename.endsWith(".jpg") ||
|
||||||
|
lowerCaseFilename.endsWith(".jpeg") ||
|
||||||
|
lowerCaseFilename.endsWith(".png") ||
|
||||||
|
lowerCaseFilename.endsWith(".gif") ||
|
||||||
|
lowerCaseFilename.endsWith(".bmp") ||
|
||||||
|
lowerCaseFilename.endsWith(".webp")||
|
||||||
|
lowerCaseFilename.endsWith(".mp4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看文件名是否有重名
|
||||||
|
* @param filename
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isFileExists(String filename) {
|
||||||
|
File targetFile = new File(FileConstant.ERROR_IMAGE_PATH+ "/" + filename);
|
||||||
|
return targetFile.exists();
|
||||||
|
}
|
||||||
|
}
|
||||||
90
nl-common/src/main/java/org/nl/util/RsaUtils.java
Normal file
90
nl-common/src/main/java/org/nl/util/RsaUtils.java
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package org.nl.util;
|
||||||
|
|
||||||
|
import org.apache.tomcat.util.codec.binary.Base64;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liejiu
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RsaUtils {
|
||||||
|
|
||||||
|
public static String privateKey;
|
||||||
|
|
||||||
|
@Value("${rsa.private_key}")
|
||||||
|
public void setPrivateKey(String privateKey) {
|
||||||
|
RsaUtils.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
System.out.println("\n");
|
||||||
|
RsaKeyPair keyPair = generateKeyPair();
|
||||||
|
System.out.println("公钥:" + keyPair.getPublicKey());
|
||||||
|
System.out.println("私钥:" + keyPair.getPrivateKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建RSA密钥对
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
* @throws NoSuchAlgorithmException /
|
||||||
|
*/
|
||||||
|
public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
|
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||||
|
keyPairGenerator.initialize(1024);
|
||||||
|
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||||
|
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
|
||||||
|
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
|
||||||
|
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
|
||||||
|
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
|
||||||
|
return new RsaKeyPair(publicKeyString, privateKeyString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA密钥对对象
|
||||||
|
*/
|
||||||
|
public static class RsaKeyPair {
|
||||||
|
|
||||||
|
private final String publicKey;
|
||||||
|
private final String privateKey;
|
||||||
|
|
||||||
|
public RsaKeyPair(String publicKey, String privateKey) {
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPublicKey() {
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateKey() {
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥解密
|
||||||
|
*
|
||||||
|
* @param privateKeyText 私钥
|
||||||
|
* @param text 待解密的文本
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
|
||||||
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
|
||||||
|
return new String(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user