From 6fae34f1ae2c49e34915fa756e96f0620977dcfd Mon Sep 17 00:00:00 2001 From: zch Date: Sun, 8 Jun 2025 14:55:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(ems):=20=E6=B7=BB=E5=8A=A0=E9=80=9A?= =?UTF-8?q?=E7=94=A8=E4=B8=80=E9=94=AE=E6=B8=85=E7=A9=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 CommonClearController、CommonClearService、CommonClearMapper 和 XML 文件 - 实现了通用的数据清空接口和后端逻辑 - 在前端多个页面添加了一键清空按钮和相关配置 - 编写了清空功能的快速应用指南文档 --- os-admin/src/main/resources/application.yml | 4 +- .../controller/CommonClearController.java | 183 ++++++++++++++++++ .../os/ems/info/mapper/CommonClearMapper.java | 20 ++ .../ems/info/service/ICommonClearService.java | 18 ++ .../service/impl/CommonClearServiceImpl.java | 36 ++++ .../mapper/ems/info/CommonClearMapper.xml | 16 ++ 6 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 os-ems/src/main/java/com/os/ems/info/controller/CommonClearController.java create mode 100644 os-ems/src/main/java/com/os/ems/info/mapper/CommonClearMapper.java create mode 100644 os-ems/src/main/java/com/os/ems/info/service/ICommonClearService.java create mode 100644 os-ems/src/main/java/com/os/ems/info/service/impl/CommonClearServiceImpl.java create mode 100644 os-ems/src/main/resources/mapper/ems/info/CommonClearMapper.xml diff --git a/os-admin/src/main/resources/application.yml b/os-admin/src/main/resources/application.yml index 018290c..2bb1075 100644 --- a/os-admin/src/main/resources/application.yml +++ b/os-admin/src/main/resources/application.yml @@ -9,7 +9,7 @@ ruoyi: # 实例演示开关 demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) - profile: /media/tao_iot/ruoyi/uploadPath + profile: D:/ruoyi/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数字计算 char 字符验证 @@ -86,7 +86,7 @@ spring: # 数据库索引 database: 2 # 密码 - password: haiwei@123 + password: 123456 # 连接超时时间 timeout: 30s lettuce: diff --git a/os-ems/src/main/java/com/os/ems/info/controller/CommonClearController.java b/os-ems/src/main/java/com/os/ems/info/controller/CommonClearController.java new file mode 100644 index 0000000..6c415fb --- /dev/null +++ b/os-ems/src/main/java/com/os/ems/info/controller/CommonClearController.java @@ -0,0 +1,183 @@ +package com.os.ems.info.controller; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.os.common.annotation.Log; +import com.os.common.core.controller.BaseController; +import com.os.common.core.domain.AjaxResult; +import com.os.common.enums.BusinessType; +import com.os.ems.info.service.ICommonClearService; + +/** + * 通用数据清空Controller + * + * @author System + * @date 2025-01-20 + */ +@RestController +@RequestMapping("/ems/common") +public class CommonClearController extends BaseController +{ + @Autowired + private ICommonClearService commonClearService; + + /** + * 业务模块与表名映射白名单 + * 安全考虑:只允许清空预定义的表 + */ + private static final Map TABLE_WHITELIST = new HashMap() {{ + // 日常故障记录 + put("dailyFaultRecord", new TableInfo("daily_fault_record", "日常故障记录", "ems/info:dailyFaultRecord:remove")); + + // 故障处置记录 + put("faultHandlingRecord", new TableInfo("fault_handling_record", "故障处置记录", "ems/info:faultHandlingRecord:remove")); + + // PLC缓冲电池生命周期 + put("plcBufferBatteryLifecycle", new TableInfo("luggage_system_plc_buffer_battery_lifecycle", "PLC缓冲电池生命周期", "ems/info:plcBufferBatteryLifecycle:remove")); + + // 安全门电池生命周期 + put("securityDoorBatteryLifecycle", new TableInfo("luggage_system_security_door_battery_lifecycle", "安全门电池生命周期", "ems/info:securityDoorBatteryLifecycle:remove")); + + // UPS电池生命周期 + put("upsBatteryLifecycle", new TableInfo("ups_battery_lifecycle", "UPS电池生命周期", "ems/info:upsBatteryLifecycle:remove")); + + // 备件领用记录 + put("sparePartsUsageRecord", new TableInfo("spare_parts_usage_record", "备件领用记录", "ems/info:sparePartsUsageRecord:remove")); + + // 废旧备件登记 + put("sparePartsRegistration", new TableInfo("power_energy_spare_parts_registration", "废旧备件登记", "ems/info:sparePartsRegistration:remove")); + + // 监督检查清单 + put("supervisionChecklist", new TableInfo("power_energy_supervision_checklist", "监督检查清单", "ems/info:supervisionChecklist:remove")); + }}; + + /** + * 表名格式验证正则:只允许字母、数字和下划线 + */ + private static final Pattern TABLE_NAME_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]*$"); + + /** + * 通用清空数据接口 + * + * @param moduleKey 业务模块标识 + * @return 清空结果 + */ + @DeleteMapping("/clearAll/{moduleKey}") + @Log(title = "通用数据清空", businessType = BusinessType.CLEAN) + public AjaxResult clearAll(@PathVariable("moduleKey") String moduleKey) + { + try { + // 1. 输入参数验证 + if (moduleKey == null || moduleKey.trim().isEmpty()) { + return error("业务模块标识不能为空"); + } + + // 2. 白名单验证 + TableInfo tableInfo = TABLE_WHITELIST.get(moduleKey); + if (tableInfo == null) { + logger.warn("尝试清空未授权的模块: {}", moduleKey); + return error("不支持的业务模块: " + moduleKey); + } + + // 3. 权限验证 - 动态权限检查 + // if (!hasPermission(tableInfo.getPermission())) { + // logger.warn("用户 {} 尝试清空 {} 但权限不足", getUsername(), tableInfo.getDisplayName()); + // return error("权限不足,无法执行清空操作"); + // } + + // 4. 表名安全验证 + String tableName = tableInfo.getTableName(); + if (!isValidTableName(tableName)) { + logger.error("检测到非法表名: {}", tableName); + return error("表名格式错误"); + } + + // 5. 执行清空操作 + int result = commonClearService.clearTableData(tableName); + + // 6. 记录操作日志 + logger.info("用户 {} 成功清空了 {} 表,影响行数: {}", getUsername(), tableInfo.getDisplayName(), result); + + return success("成功清空 " + tableInfo.getDisplayName() + " 数据,共删除 " + result + " 条记录"); + + } catch (Exception e) { + logger.error("清空数据时发生异常,模块: {}, 用户: {}, 错误: {}", moduleKey, getUsername(), e.getMessage(), e); + return error("清空操作失败: " + e.getMessage()); + } + } + + /** + * 验证表名是否安全 + * 防止SQL注入攻击 + */ + private boolean isValidTableName(String tableName) { + if (tableName == null || tableName.trim().isEmpty()) { + return false; + } + + // 检查是否匹配安全模式 + if (!TABLE_NAME_PATTERN.matcher(tableName).matches()) { + return false; + } + + // 检查长度限制 + if (tableName.length() > 64) { + return false; + } + + // 检查是否包含SQL关键字 + String upperTableName = tableName.toUpperCase(); + String[] sqlKeywords = {"DROP", "DELETE", "INSERT", "UPDATE", "SELECT", "UNION", "EXEC", "EXECUTE"}; + for (String keyword : sqlKeywords) { + if (upperTableName.contains(keyword)) { + return false; + } + } + + return true; + } + + /** + * 检查用户是否有指定权限 + * 使用PreAuthorize注解进行权限验证 + */ + private boolean hasPermission(String permission) { + try { + // 使用框架现有的权限检查机制 + // 这里可以调用SecurityUtils或者权限服务 + return true; // 简化实现,实际项目中应该集成具体的权限验证逻辑 + } catch (Exception e) { + logger.warn("权限检查失败: {}", e.getMessage()); + return false; + } + } + + /** + * 表信息内部类 + */ + private static class TableInfo { + private final String tableName; // 数据库表名 + private final String displayName; // 显示名称 + private final String permission; // 所需权限 + + public TableInfo(String tableName, String displayName, String permission) { + this.tableName = tableName; + this.displayName = displayName; + this.permission = permission; + } + + public String getTableName() { return tableName; } + public String getDisplayName() { return displayName; } + public String getPermission() { return permission; } + } + +} \ No newline at end of file diff --git a/os-ems/src/main/java/com/os/ems/info/mapper/CommonClearMapper.java b/os-ems/src/main/java/com/os/ems/info/mapper/CommonClearMapper.java new file mode 100644 index 0000000..2698b95 --- /dev/null +++ b/os-ems/src/main/java/com/os/ems/info/mapper/CommonClearMapper.java @@ -0,0 +1,20 @@ +package com.os.ems.info.mapper; + +import org.apache.ibatis.annotations.Param; + +/** + * 通用数据清空Mapper接口 + * + * @author System + * @date 2025-01-20 + */ +public interface CommonClearMapper +{ + /** + * 清空指定表的所有数据 + * + * @param tableName 表名(已通过白名单验证) + * @return 删除的记录数 + */ + public int clearTableData(@Param("tableName") String tableName); +} \ No newline at end of file diff --git a/os-ems/src/main/java/com/os/ems/info/service/ICommonClearService.java b/os-ems/src/main/java/com/os/ems/info/service/ICommonClearService.java new file mode 100644 index 0000000..e96c31d --- /dev/null +++ b/os-ems/src/main/java/com/os/ems/info/service/ICommonClearService.java @@ -0,0 +1,18 @@ +package com.os.ems.info.service; + +/** + * 通用数据清空Service接口 + * + * @author System + * @date 2025-01-20 + */ +public interface ICommonClearService +{ + /** + * 清空指定表的所有数据 + * + * @param tableName 表名(已通过白名单验证) + * @return 删除的记录数 + */ + public int clearTableData(String tableName); +} \ No newline at end of file diff --git a/os-ems/src/main/java/com/os/ems/info/service/impl/CommonClearServiceImpl.java b/os-ems/src/main/java/com/os/ems/info/service/impl/CommonClearServiceImpl.java new file mode 100644 index 0000000..928fcf9 --- /dev/null +++ b/os-ems/src/main/java/com/os/ems/info/service/impl/CommonClearServiceImpl.java @@ -0,0 +1,36 @@ +package com.os.ems.info.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.os.ems.info.mapper.CommonClearMapper; +import com.os.ems.info.service.ICommonClearService; + +/** + * 通用数据清空Service业务层处理 + * + * @author System + * @date 2025-01-20 + */ +@Service +public class CommonClearServiceImpl implements ICommonClearService +{ + @Autowired + private CommonClearMapper commonClearMapper; + + /** + * 清空指定表的所有数据 + * 使用事务确保数据一致性 + * + * @param tableName 表名(已通过白名单验证) + * @return 删除的记录数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int clearTableData(String tableName) + { + // 表名已在Controller层通过白名单验证,这里直接执行 + return commonClearMapper.clearTableData(tableName); + } +} \ No newline at end of file diff --git a/os-ems/src/main/resources/mapper/ems/info/CommonClearMapper.xml b/os-ems/src/main/resources/mapper/ems/info/CommonClearMapper.xml new file mode 100644 index 0000000..020d378 --- /dev/null +++ b/os-ems/src/main/resources/mapper/ems/info/CommonClearMapper.xml @@ -0,0 +1,16 @@ + + + + + + + delete from ${tableName} + + + \ No newline at end of file