数据存储

This commit is contained in:
cwchen 2025-12-24 14:59:26 +08:00
parent ae226ebda6
commit bb381a7569
16 changed files with 847 additions and 0 deletions

View File

@ -0,0 +1,46 @@
package com.bonus.web.controller.data;
import com.bonus.common.annotation.RequiresPermissions;
import com.bonus.common.annotation.SysLog;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.enums.OperaType;
import com.bonus.web.service.data.StorageService;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @className:StorageController
* @author:cwchen
* @date:2025-12-24-14:17
* @version:1.0
* @description:数据存储-web层
*/
@RestController
@RequestMapping("/data/storage/")
public class StorageController {
@Resource(name = "StorageService")
private StorageService storageService;
@ApiOperation(notes = "查询数据存储",value = "查询数据存储")
@RequiresPermissions("devops:storage:info")
@GetMapping("/getStorageInfo")
@SysLog(title = "系统信息", businessType = OperaType.QUERY, logType = 1, module = "设备运维->数据存储", details = "查询数据存储")
public AjaxResult getStorageInfo(ParamsDto dto) {
return storageService.getStorageInfo(dto);
}
@ApiOperation(notes = "格式化存储",value = "格式化存储")
@RequiresPermissions("devops:storage:formatStorage")
@PostMapping("/formatStorage")
@SysLog(title = "系统信息", businessType = OperaType.QUERY, logType = 1, module = "设备运维->数据存储", details = "格式化存储")
public AjaxResult formatStorage(ParamsDto dto) {
return storageService.formatStorage(dto);
}
}

View File

@ -0,0 +1,51 @@
package com.bonus.web.controller.data;
import com.bonus.common.annotation.RequiresPermissions;
import com.bonus.common.annotation.SysLog;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.enums.OperaType;
import com.bonus.web.service.data.SystemInfoService;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @className:SystemInfoController
* @author:cwchen
* @date:2025-12-24-11:11
* @version:1.0
* @description:系统信息-web层
*/
@RestController
@RequestMapping("/data/device/")
public class SystemInfoController {
@Resource(name = "SystemInfoService")
private SystemInfoService systemInfoService;
@ApiOperation(notes = "查询系统信息",value = "查询系统信息")
@RequiresPermissions("devops:info:list")
@GetMapping("/getDeviceInfo")
@SysLog(title = "系统信息", businessType = OperaType.QUERY, logType = 1, module = "设备运维->系统信息", details = "查询系统信息")
public AjaxResult getDeviceInfo(ParamsDto dto) {
return systemInfoService.getDeviceInfo(dto);
}
@ApiOperation(notes = "修改设备信息",value = "修改设备信息")
@RequiresPermissions("devops:info:edit")
@PostMapping("/updateDevice")
@SysLog(title = "系统信息", businessType = OperaType.UPDATE, logType = 1, module = "设备运维->系统信息", details = "修改设备信息")
public AjaxResult updateDevice(@RequestBody ParamsDto dto) {
return systemInfoService.updateDevice(dto);
}
@ApiOperation(notes = "修改告警状态",value = "修改告警状态")
@RequiresPermissions("devops:info:edit")
@PostMapping("/updateAlarmStatus")
@SysLog(title = "系统信息", businessType = OperaType.UPDATE, logType = 1, module = "设备运维->系统信息", details = "修改告警状态")
public AjaxResult updateAlarmStatus(@RequestBody ParamsDto dto) {
return systemInfoService.updateAlarmStatus(dto);
}
}

View File

@ -0,0 +1,73 @@
package com.bonus.web.service.data;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
import com.bonus.common.utils.StorageScanner;
import com.bonus.data.service.DIStorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
/**
* @className:StorageService
* @author:cwchen
* @date:2025-12-24-14:18
* @version:1.0
* @description:数据存储-业务逻辑层
*/
@Service(value = "StorageService")
@Slf4j
public class StorageService {
@Resource(name = "DIStorageService")
private DIStorageService diStorageService;
/**
* 查询数据存储
*
* @param dto
* @return AjaxResult
* @author cwchen
* @date 2025/12/24 14:23
*/
public AjaxResult getStorageInfo(ParamsDto dto) {
StorageVo vo = null;
try {
List<StorageVo> results = StorageScanner.scanAllStorages(1L);
StorageVo totalVo = StorageScanner.mergeStorageData(results, 1L, "TOTAL_SYSTEM_STORAGE");
if (Objects.nonNull(totalVo)) {
// 保存存储信息
try {
totalVo.setSystemStorageId(1L);
diStorageService.saveStorageInfo(totalVo);
} catch (Exception e) {
log.error(e.toString(), e);
}
vo = totalVo;
} else {
// 查询
vo = diStorageService.getStorageInfo(dto);
}
} catch (Exception e) {
log.error(e.toString(), e);
vo = new StorageVo();
}
return AjaxResult.success(vo);
}
/**
* 格式化存储
* @param dto
* @return AjaxResult
* @author cwchen
* @date 2025/12/24 14:56
*/
public AjaxResult formatStorage(ParamsDto dto) {
return AjaxResult.success();
}
}

View File

@ -0,0 +1,84 @@
package com.bonus.web.service.data;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.SystemInfoVo;
import com.bonus.data.service.DISystemInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
/**
* @className:SystemInfoService
* @author:cwchen
* @date:2025-12-24-11:11
* @version:1.0
* @description:系统信息-业务层
*/
@Slf4j
@Service(value = "SystemInfoService")
public class SystemInfoService {
@Resource(name = "DISystemInfoService")
private DISystemInfoService systemInfoService;
/**
* 查询系统信息
* @param dto
* @return AjaxResult
* @author cwchen
* @date 2025/12/24 11:24
*/
public AjaxResult getDeviceInfo(ParamsDto dto) {
SystemInfoVo vo = null;
try {
vo = systemInfoService.getDeviceInfo(dto);
return AjaxResult.success(vo == null ? new SystemInfoVo() : vo);
} catch (Exception e) {
log.error(e.toString(),e);
vo = new SystemInfoVo();
}
return AjaxResult.success(vo);
}
/**
* 修改设备信息
* @param dto
* @return AjaxResult
* @author cwchen
* @date 2025/12/24 13:12
*/
@Transactional(rollbackFor = Exception.class)
public AjaxResult updateDevice(ParamsDto dto) {
try {
systemInfoService.updateDevice(dto);
return AjaxResult.success();
} catch (Exception e) {
log.error(e.toString(),e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return AjaxResult.error();
}
}
/**
* 修改告警状态
* @param dto
* @return AjaxResult
* @author cwchen
* @date 2025/12/24 13:18
*/
public AjaxResult updateAlarmStatus(ParamsDto dto) {
try {
// 1.是否调用第三方接口
systemInfoService.updateAlarmStatus(dto);
return AjaxResult.success();
} catch (Exception e) {
log.error(e.toString(),e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return AjaxResult.error();
}
}
}

View File

@ -26,4 +26,13 @@ public class ParamsDto {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**设备名称*/
private String equipmentName;
/**设备ID*/
private Long systemId;
/**告警状态*/
private String alarmStatus;
}

View File

@ -0,0 +1,46 @@
package com.bonus.common.domain.data.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* @className:StorageVo
* @author:cwchen
* @date:2025-12-24-14:25
* @version:1.0
* @description:系统存储-vo
*/
@Data
public class StorageVo {
/**
* 系统存储id
*/
private Long systemStorageId;
/**
* 系统id
*/
private Long systemId;
/**
* 存储类型 1.TF
*/
private String storageType;
/**
* 容量大小 GB为单位
*/
private BigDecimal capacity;
/**
* 可用容量 GB为单位
*/
private BigDecimal availableCapacity;
/**
* 已用容量 GB为单位
*/
private BigDecimal usedCapacity;
}

View File

@ -0,0 +1,128 @@
package com.bonus.common.domain.data.vo;
import lombok.Data;
import java.util.Date;
/**
* @className:SystemInfoVo
* @author:cwchen
* @date:2025-12-24-11:08
* @version:1.0
* @description:系统信息-vo
*/
@Data
public class SystemInfoVo {
/**
* 系统id
*/
private Long systemId;
/**
* 设备名称
*/
private String equipmentName;
/**
* 设备型号
*/
private String equipmentModel;
/**
* 固件版本
*/
private String firmwareVersion;
/**
* 软件版本
*/
private String softwareVersion;
/**
* 运行内存
*/
private String ram;
/**
* 硬盘大小
*/
private String hardDriveSize;
/**
* NPU
*/
private String npu;
/**
* 电池容量
*/
private String batteryCapacity;
/**
* TF存储
*/
private String tfStorage;
/**
* 序列号
*/
private String serialNumber;
/**
* 设备状态
设备状态 1.在线/0.离线/2.待机/3.升级中
*/
private String equipmentStatus;
/**
* 供电方式 1.外接电源/2.电池供电
*/
private String powerSupplyMethod;
/**
* 电池电量
*/
private String batteryPower;
/**
* 网络连接方式 4G/5G/以太网
*/
private String networkConnectionMethod;
/**
* 设备运行温度
*/
private String equipmentOperatingTemperature;
/**
* 告警状态 1.设置告警 0.设置告警
*/
private String alarmStatus;
/**
* 创建时间
*/
private Date createTime;
/**
* 创建人
*/
private Long createUserId;
/**
* 修改时间
*/
private Date updateTime;
/**
* 修改人
*/
private Long updateUserId;
/**
* 是否删除 0.未删除 1,已删除
*/
private String delFlag;
}

View File

@ -0,0 +1,117 @@
package com.bonus.common.utils;
import com.bonus.common.domain.data.vo.StorageVo;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.FileStore;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.List;
/**
* @className:StorageScanner
* @author:cwchen
* @date:2025-12-24-14:37
* @version:1.0
* @description:磁盘扫描
*/
public class StorageScanner {
private static final BigDecimal GB_FACTOR = new BigDecimal(1024 * 1024 * 1024);
/**
* 自动扫描并获取系统中所有存储设备的状态
* @param systemId 关联的系统ID
* @return 存储信息列表
*/
public static List<StorageVo> scanAllStorages(Long systemId) {
List<StorageVo> storageList = new ArrayList<>();
// 获取当前文件系统的所有存储卷Windows的C/D盘Linux的//mnt等
Iterable<FileStore> fileStores = FileSystems.getDefault().getFileStores();
for (FileStore store : fileStores) {
try {
// 过滤一些虚拟文件系统 Linux 下的内存盘内核文件系统等
// 通常只保留物理存储排除总空间为 0 的设备
if (store.getTotalSpace() <= 0) {
continue;
}
StorageVo vo = new StorageVo();
vo.setSystemId(systemId);
// 设置存储类型根据名称或挂载路径判断
// 1.TF 是你的约定值这里可以加入逻辑判断或者默认设为磁盘名
String storeName = store.name();
String storeDescription = store.toString(); // 例如 "/ (/dev/sda1)" "(C:)"
vo.setStorageType(identifyStorageType(storeName, storeDescription));
// 核心数据计算
long totalSpace = store.getTotalSpace();
long usableSpace = store.getUsableSpace();
long usedSpace = totalSpace - usableSpace;
vo.setCapacity(byteToGb(totalSpace));
vo.setAvailableCapacity(byteToGb(usableSpace));
vo.setUsedCapacity(byteToGb(usedSpace));
storageList.add(vo);
} catch (IOException e) {
// 某些系统分区可能因为权限无法读取跳过即可
System.err.println("无法读取存储设备: " + store + " - " + e.getMessage());
}
}
return storageList;
}
/**
* 将多个存储节点的数据累加合并为一个
* @param results 扫描到的存储列表
* @param systemId 合并后的系统ID
* @param combinedType 合并后的存储类型描述 "Total"
* @return 累加后的 StorageVo
*/
public static StorageVo mergeStorageData(List<StorageVo> results, Long systemId, String combinedType) {
if (results == null || results.isEmpty()) {
return null;
}
// 使用 Stream 进行累加计算
BigDecimal totalCapacity = results.stream()
.map(StorageVo::getCapacity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalAvailable = results.stream()
.map(StorageVo::getAvailableCapacity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalUsed = results.stream()
.map(StorageVo::getUsedCapacity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 创建合并后的实体类
StorageVo summary = new StorageVo();
summary.setSystemId(systemId);
summary.setStorageType(combinedType); // 例如设置为 "ALL" "TOTAL"
summary.setCapacity(totalCapacity);
summary.setAvailableCapacity(totalAvailable);
summary.setUsedCapacity(totalUsed);
return summary;
}
/**
* 简单的存储类型识别逻辑
*/
private static String identifyStorageType(String name, String description) {
String lowerDesc = description.toLowerCase();
// 如果挂载点包含 sdcard, mmcblk, tf 等关键字标记为 TF卡 (类型 1)
if (lowerDesc.contains("mmcblk") || lowerDesc.contains("sdcard") || lowerDesc.contains("tf")) {
return "1"; // TF卡
}
return "Disk: " + name; // 其他普通磁盘
}
private static BigDecimal byteToGb(long bytes) {
if (bytes <= 0) return BigDecimal.ZERO;
return new BigDecimal(bytes)
.divide(GB_FACTOR, 2, RoundingMode.HALF_UP);
}
}

View File

@ -0,0 +1,34 @@
package com.bonus.data.mapper;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
import org.springframework.stereotype.Repository;
/**
* @className:DIStorageMapper
* @author:cwchen
* @date:2025-12-24-14:20
* @version:1.0
* @description:数据存储-数据层
*/
@Repository(value = "DIStorageMapper")
public interface DIStorageMapper {
/**
* 查询数据存储
* @param dto
* @return StorageVo
* @author cwchen
* @date 2025/12/24 14:29
*/
StorageVo getStorageInfo(ParamsDto dto);
/**
* 保存存储信息
* @param vo
* @return void
* @author cwchen
* @date 2025/12/24 14:46
*/
void saveStorageInfo(StorageVo vo);
}

View File

@ -0,0 +1,42 @@
package com.bonus.data.mapper;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.SystemInfoVo;
import org.springframework.stereotype.Repository;
/**
* @className:DISystemInfoMapper
* @author:cwchen
* @date:2025-12-24-11:15
* @version:1.0
* @description:系统信息-数据层
*/
@Repository(value = "DISystemInfoMapper")
public interface DISystemInfoMapper {
/**
* 查询系统信息
* @param dto
* @return SystemInfoVo
* @author cwchen
* @date 2025/12/24 11:29
*/
SystemInfoVo getDeviceInfo(ParamsDto dto);
/**
* 修改设备信息
* @param dto
* @return void
* @author cwchen
* @date 2025/12/24 13:15
*/
void updateDevice(ParamsDto dto);
/**
* 修改告警状态
* @param dto
* @return void
* @author cwchen
* @date 2025/12/24 13:20
*/
void updateAlarmStatus(ParamsDto dto);
}

View File

@ -0,0 +1,31 @@
package com.bonus.data.service;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
/**
* @className:DIStorageService
* @author:cwchen
* @date:2025-12-24-14:19
* @version:1.0
* @description:数据存储-业务层
*/
public interface DIStorageService {
/**
* 查询数据存储
* @param dto
* @return StorageVo
* @author cwchen
* @date 2025/12/24 14:28
*/
StorageVo getStorageInfo(ParamsDto dto);
/**
* 保存存储信息
* @param vo
* @return void
* @author cwchen
* @date 2025/12/24 14:46
*/
void saveStorageInfo(StorageVo vo);
}

View File

@ -0,0 +1,40 @@
package com.bonus.data.service;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.SystemInfoVo;
/**
* @className:DISystemInfoService
* @author:cwchen
* @date:2025-12-24-11:12
* @version:1.0
* @description:系统信息-业务层
*/
public interface DISystemInfoService {
/**
* 查询系统信息
* @param dto
* @return SystemInfoVo
* @author cwchen
* @date 2025/12/24 11:28
*/
SystemInfoVo getDeviceInfo(ParamsDto dto);
/**
* 修改设备信息
* @param dto
* @return void
* @author cwchen
* @date 2025/12/24 13:15
*/
void updateDevice(ParamsDto dto);
/**
* 修改告警状态
* @param dto
* @return void
* @author cwchen
* @date 2025/12/24 13:20
*/
void updateAlarmStatus(ParamsDto dto);
}

View File

@ -0,0 +1,33 @@
package com.bonus.data.service.impl;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.StorageVo;
import com.bonus.data.mapper.DIStorageMapper;
import com.bonus.data.service.DIStorageService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @className:DStorageServiceImpl
* @author:cwchen
* @date:2025-12-24-14:19
* @version:1.0
* @description:数据存储-业务逻辑层
*/
@Service(value = "DIStorageService")
public class DStorageServiceImpl implements DIStorageService {
@Resource(name = "DIStorageMapper")
private DIStorageMapper diStorageMapper;
@Override
public StorageVo getStorageInfo(ParamsDto dto) {
return diStorageMapper.getStorageInfo(dto);
}
@Override
public void saveStorageInfo(StorageVo vo) {
diStorageMapper.saveStorageInfo(vo);
}
}

View File

@ -0,0 +1,38 @@
package com.bonus.data.service.impl;
import com.bonus.common.domain.data.dto.ParamsDto;
import com.bonus.common.domain.data.vo.SystemInfoVo;
import com.bonus.data.mapper.DISystemInfoMapper;
import com.bonus.data.service.DISystemInfoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @className:DSystemInfoServiceImpl
* @author:cwchen
* @date:2025-12-24-11:13
* @version:1.0
* @description:系统信息-业务逻辑层
*/
@Service(value = "DISystemInfoService")
public class DSystemInfoServiceImpl implements DISystemInfoService {
@Resource(name = "DISystemInfoMapper")
private DISystemInfoMapper diSystemInfoMapper;
@Override
public SystemInfoVo getDeviceInfo(ParamsDto dto) {
return diSystemInfoMapper.getDeviceInfo(dto);
}
@Override
public void updateDevice(ParamsDto dto) {
diSystemInfoMapper.updateDevice(dto);
}
@Override
public void updateAlarmStatus(ParamsDto dto) {
diSystemInfoMapper.updateAlarmStatus(dto);
}
}

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.data.mapper.DIStorageMapper">
<!--查询数据存储-->
<select id="getStorageInfo" resultType="com.bonus.common.domain.data.vo.StorageVo">
SELECT capacity,
available_capacity AS availableCapacity,
used_capacity AS usedCapacity
FROM tb_system_storage
WHERE storage_type = '1'
LIMIT 1
</select>
<!--保存存储信息-->
<insert id="saveStorageInfo">
REPLACE INTO tb_system_storage
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="systemId != null">system_id,</if>
<if test="storageType != null and storageType!=''">storage_type,</if>
<if test="capacity != null">capacity,</if>
<if test="availableCapacity != null">available_capacity,</if>
<if test="usedCapacity != null">used_capacity,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="systemId != null">#{systemId},</if>
<if test="storageType != null and storageType!=''">#{storageType},</if>
<if test="capacity != null">#{capacity},</if>
<if test="availableCapacity != null">#{availableCapacity},</if>
<if test="usedCapacity != null">#{usedCapacity},</if>
</trim>
</insert>
</mapper>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.data.mapper.DISystemInfoMapper">
<!--查询系统信息-->
<select id="getDeviceInfo" resultType="com.bonus.common.domain.data.vo.SystemInfoVo">
SELECT system_id AS systemId,
equipment_name AS equipmentName,
equipment_model AS equipmentModel,
firmware_version AS firmwareVersion,
software_version AS softwareVersion,
ram AS ram,
hard_drive_size AS hardDriveSize,
npu AS npu,
battery_capacity AS batteryCapacity,
tf_storage AS tfStorage,
serial_number AS serialNumber,
equipment_status AS equipmentStatus,
power_supply_method AS powerSupplyMethod,
battery_power AS batteryPower,
network_connection_method AS networkConnectionMethod,
equipment_operating_temperature AS equipmentOperatingTemperature,
alarm_status AS alarmStatus
FROM tb_system_info WHERE del_flag = '0'
ORDER BY create_time DESC
LIMIT 1
</select>
<!--修改设备信息-->
<update id="updateDevice">
UPDATE tb_system_info SET equipment_name = #{equipmentName} WHERE system_id = #{systemId}
</update>
<!--修改告警状态-->
<update id="updateAlarmStatus">
UPDATE tb_system_info SET alarm_status = #{alarmStatus} WHERE system_id = #{systemId}
</update>
</mapper>