用户数据存储配置

This commit is contained in:
2025-12-04 14:26:35 +08:00
parent 5313f94c94
commit 22b0eb2fde
10 changed files with 263 additions and 51 deletions

View File

@@ -0,0 +1,27 @@
package com.sdm.common.entity.req.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class SimulationPoolInfo {
/**
* 所属工况库id
*/
@Schema(description = "所属工况库id")
private Integer simulationPoolId;
/**
* 工况库版本
*/
@Schema(description = "工况库版本")
private String simulationPoolVersion;
/**
* 关联工况
*/
@Schema(description = "关联工况")
private List<String> simulationPoolTaskIds;
}

View File

@@ -73,26 +73,8 @@ public class UploadFilesReq {
@Schema(description = "关联项目id")
private String projectId;
/**
* 所属工况库id
*/
@Schema(description = "所属工况库id")
private Integer simulationPoolId;
/**
* 工况库版本
*/
@Schema(description = "工况库版本")
private String simulationPoolVersion;
/**
* 关联工况
*/
@Schema(description = "关联工况")
private List<String> simulationPoolTaskIds;
@Schema(description = "删除文件和工况库关联")
private List<Long> deleteFileSimulationMappingIds;
@Schema(description = "关联工况库信息")
private List<SimulationPoolInfo> simulationPoolInfoList;
/**
* 关联分析项目id

View File

@@ -2,7 +2,6 @@ package com.sdm.common.entity.req.system;
import com.sdm.common.entity.BaseReq;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "用户列表查询请求参数")
@@ -14,9 +13,12 @@ public class UserListReq extends BaseReq {
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "用户名")
@Schema(description = "CID userName是手机号")
private String userName;
@Schema(description = "昵称")
private String nickname;
@Schema(description = "手机号")
private String phone;
}

View File

@@ -20,9 +20,12 @@ public class UserQueryReq {
@NotNull(message = "用户ID不能为空")
private Long userId;
@Schema(description = "用户名")
@Schema(description = "CID userName是手机号")
private String userName;
@Schema(description = "昵称")
private String nickName;
@Schema(description = "用户IDS")
private List<Long> userIds;

View File

@@ -65,5 +65,71 @@ public class FileSizeUtils {
DecimalFormat df = new DecimalFormat("0.00000000");
return df.format(gbValue);
}
/**
* 将指定单位的文件大小转换为字节大小
*
* @param size 文件大小
* @param unit 文件大小单位 (B, KB, MB, GB, TB)
* @return 字节大小
*/
public static Long convertToBytes(Long size, String unit) {
if (size == null || unit == null) {
return null;
}
switch (unit.toUpperCase()) {
case "B":
return size;
case "KB":
return size * 1024L;
case "MB":
return size * 1024L * 1024L;
case "GB":
return size * 1024L * 1024L * 1024L;
case "TB":
return size * 1024L * 1024L * 1024L * 1024L;
default:
return size; // 默认认为是字节
}
}
/**
* 将字节大小转换为指定单位的文件大小
*
* @param bytes 字节大小
* @param unit 文件大小单位 (B, KB, MB, GB, TB)
* @return 文件大小
*/
public static BigDecimal convertToUnit(Long bytes, String unit) {
if (bytes == null || unit == null) {
return null;
}
BigDecimal byteValue = new BigDecimal(bytes);
BigDecimal result;
switch (unit.toUpperCase()) {
case "B":
result = byteValue;
break;
case "KB":
result = byteValue.divide(new BigDecimal(1024L), 8, RoundingMode.HALF_UP);
break;
case "MB":
result = byteValue.divide(new BigDecimal(1024L * 1024L), 8, RoundingMode.HALF_UP);
break;
case "GB":
result = byteValue.divide(new BigDecimal(1024L * 1024L * 1024L), 8, RoundingMode.HALF_UP);
break;
case "TB":
result = byteValue.divide(new BigDecimal(1024L * 1024L * 1024L * 1024L), 8, RoundingMode.HALF_UP);
break;
default:
result = byteValue; // 默认认为是字节
}
return result;
}
}

View File

@@ -93,7 +93,7 @@ public class DataStorageAnalysisController {
// 查询用户配额
@PostMapping("/listUserQuota")
@Operation(summary = "查询用户配额")
public SdmResponse listUserQuota(ListUserQuotaReq listUserQuotaReq){
public SdmResponse listUserQuota(@RequestBody ListUserQuotaReq listUserQuotaReq){
return dataStorageAnalysis.listUserQuota(listUserQuotaReq);
}
//批量修改用户配额

View File

@@ -0,0 +1,16 @@
package com.sdm.data.model.enums;
public enum FileStorageQuotaStatusEnum {
// 配额状态枚举NORMAL-正常/WARNING-临界/EXCEED-超限)
NORMAL("正常"),
WARNING("临界"),
EXCEED("超限");
private String description;
FileStorageQuotaStatusEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}

View File

@@ -0,0 +1,29 @@
package com.sdm.data.model.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class FileStorageQuotaResp {
@Schema(description = "用户id")
private String userId;
@Schema(description = "用户昵称")
private String nickName;
@Schema(description = "用户工号")
private String jobNumber;
@Schema(description = "用户部门")
private String department;
@Schema(description = "存储阈值显示单位TB/GB/MB/KB")
private String quotaValueString;
@Schema(description = "已使用存储单位TB/GB/MB/KB")
private String usedValueString;
@Schema(description = "配额状态枚举NORMAL-正常/WARNING-临界/EXCEED-超限)")
private String status;
}

View File

@@ -19,14 +19,15 @@ import com.sdm.data.model.dto.UserTotalFileSizeDTO;
import com.sdm.data.model.entity.FileMetadataInfo;
import com.sdm.data.model.entity.FileStorage;
import com.sdm.data.model.entity.FileStorageQuota;
import com.sdm.data.model.enums.FileStorageQuotaStatusEnum;
import com.sdm.data.model.req.AddUserQuotaEntity;
import com.sdm.common.entity.req.data.DelFileReq;
import com.sdm.data.model.req.ListUserQuotaReq;
import com.sdm.data.model.req.QueryBigFileReq;
import com.sdm.data.model.resp.FileStorageQuotaResp;
import com.sdm.data.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -34,10 +35,10 @@ import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@@ -229,48 +230,131 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis {
@Override
public SdmResponse addUserQuota(AddUserQuotaEntity addUserQuota) {
Long quotaValue = convertToBytes(addUserQuota.getQuotaValue(), addUserQuota.getQuotaUnit());
if(ObjectUtils.isEmpty(addUserQuota.getUserId()) || ObjectUtils.isEmpty(addUserQuota.getQuotaValue()) || ObjectUtils.isEmpty(addUserQuota.getQuotaUnit())){
return SdmResponse.failed("配置参数不能为空");
}
FileStorageQuota existFileStorageQuota = fileStorageQuotaService.lambdaQuery().eq(FileStorageQuota::getUserId, addUserQuota.getUserId()).one();
if (existFileStorageQuota != null){
return SdmResponse.failed("该用户已存在存储配额");
}
FileStorageQuota fileStorageQuota = new FileStorageQuota();
fileStorageQuota.setUserId(addUserQuota.getUserId());
fileStorageQuota.setQuotaValue(quotaValue);
fileStorageQuota.setQuotaValue(addUserQuota.getQuotaValue());
fileStorageQuota.setQuotaUnit(addUserQuota.getQuotaUnit());
fileStorageQuota.setStatus("NORMAL");
fileStorageQuotaService.save(fileStorageQuota);
return null;
return SdmResponse.success("新增用户存储配额成功");
}
@Override
public SdmResponse listUserQuota(ListUserQuotaReq listUserQuotaReq) {
UserListReq req = new UserListReq();
req.setUserName(listUserQuotaReq.getUserName());
req.setNickname(listUserQuotaReq.getUserName());
req.setCurrent(listUserQuotaReq.getCurrent());
req.setSize(listUserQuotaReq.getSize());
SdmResponse<PageDataResp<List<CIDUserResp>>> pageDataRespSdmResponse = sysUserFeignClient.listUser(req);
if (!pageDataRespSdmResponse.isSuccess()) {
return SdmResponse.success();
}
List<Long> userIds = pageDataRespSdmResponse.getData().getData().stream().map(CIDUserResp::getUserId).toList();
PageHelper.startPage(listUserQuotaReq.getCurrent(), listUserQuotaReq.getSize());
List<FileStorageQuota> list = fileStorageQuotaService.lambdaQuery().in(ObjectUtils.isNotEmpty(userIds), FileStorageQuota::getUserId, userIds).list();
PageInfo<FileStorageQuota> page = new PageInfo<>(list);
return PageUtils.getJsonObjectSdmResponse(list, page);
Map<Long, CIDUserResp> userIdToNicknameMap = pageDataRespSdmResponse.getData().getData().stream().collect(Collectors.toMap(CIDUserResp::getUserId,Function.identity()));
// 查询这些 userId 的配额信息,创建 userId -> quota 的映射
Map<Long, FileStorageQuota> quotaMap = fileStorageQuotaService.lambdaQuery()
.in(ObjectUtils.isNotEmpty(userIds), FileStorageQuota::getUserId, userIds)
.list().stream()
.collect(Collectors.toMap(FileStorageQuota::getUserId, Function.identity()));
// fileStorageService 查询用户已使用的存储空间
Map<Long,UserTotalFileSizeDTO> usedStorageMap = fileStorageService.getTotalFileSizeByCreator(userIds, null).stream()
.collect(Collectors.toMap(UserTotalFileSizeDTO::getUserId, Function.identity()));
// 构造最终结果,对于没有配额信息的用户添加默认值,并根据已使用存储量设置状态
List<FileStorageQuota> fullList = userIds.stream().map(userId -> {
FileStorageQuota quota = quotaMap.getOrDefault(userId, createDefaultFileStorageQuota(userId));
// 设置已使用值
UserTotalFileSizeDTO usedStorage = usedStorageMap.get(userId);
if (usedStorage != null) {
quota.setUsedValue(usedStorage.getTotalSize());
}
// 根据配额和已使用量设置状态
if (quota.getQuotaValue() != null && quota.getUsedValue() != null) {
// 将配额值转换为与已使用值相同的单位(字节)进行比较
long quotaInBytes = convertToBytes(quota.getQuotaValue(), quota.getQuotaUnit());
if (quotaInBytes <= quota.getUsedValue()) {
quota.setStatus("EXCEED");
} else if (quotaInBytes * 0.8 <= quota.getUsedValue()) {
quota.setStatus("WARNING");
} else {
quota.setStatus("NORMAL");
}
}
return quota;
}).toList();
List<FileStorageQuotaResp> result = new ArrayList<>();
for (FileStorageQuota quota : fullList) {
FileStorageQuotaResp resp = new FileStorageQuotaResp();
resp.setUserId(quota.getUserId().toString());
CIDUserResp cidUserResp = userIdToNicknameMap.get(quota.getUserId());
resp.setNickName(cidUserResp.getNickname());
resp.setQuotaValueString(quota.getQuotaValue() + " " + quota.getQuotaUnit());
BigDecimal usedValue = FileSizeUtils.convertToUnit(quota.getUsedValue(), quota.getQuotaUnit());
resp.setUsedValueString(usedValue.toPlainString() + " " + quota.getQuotaUnit());
// 设置状态为中文
resp.setStatus(FileStorageQuotaStatusEnum.valueOf(quota.getStatus()).getDescription());
result.add(resp);
}
// 使用 PageDataResp 中的数据构造 PageInfo
PageInfo<FileStorageQuota> page = new PageInfo<>();
page.setTotal(pageDataRespSdmResponse.getData().getTotal()); // 设置总记录数
page.setPageNum(pageDataRespSdmResponse.getData().getCurrentPage()); // 设置当前页码
page.setPageSize(pageDataRespSdmResponse.getData().getPageSize()); // 设置每页记录数
return PageUtils.getJsonObjectSdmResponse(result, page);
}
// 辅助方法:创建默认的 FileStorageQuota 实例
private FileStorageQuota createDefaultFileStorageQuota(Long userId) {
FileStorageQuota defaultQuota = new FileStorageQuota();
defaultQuota.setUserId(userId);
defaultQuota.setQuotaValue(2L); // 默认存储阈值
defaultQuota.setQuotaUnit("GB"); // 默认单位
defaultQuota.setUsedValue(0L); // 默认已使用值
defaultQuota.setStatus("NORMAL"); // 默认状态
return defaultQuota;
}
@Override
public SdmResponse batchUpdateUserQuota(List<AddUserQuotaEntity> addUserQuota) {
if (CollectionUtils.isEmpty(addUserQuota)) {
return SdmResponse.success();
return SdmResponse.failed("配置参数不能为空");
}
List<FileStorageQuota> fileStorageQuotas = new ArrayList<>();
for (AddUserQuotaEntity addUserQuotaEntity : addUserQuota) {
Long quotaValue = convertToBytes(addUserQuotaEntity.getQuotaValue(), addUserQuotaEntity.getQuotaUnit());
FileStorageQuota fileStorageQuota = new FileStorageQuota();
fileStorageQuota.setUserId(addUserQuotaEntity.getUserId());
fileStorageQuota.setQuotaValue(quotaValue);
fileStorageQuota.setQuotaUnit(addUserQuotaEntity.getQuotaUnit());
fileStorageQuotas.add(fileStorageQuota);
}
if(ObjectUtils.isEmpty(addUserQuotaEntity.getUserId()) || ObjectUtils.isEmpty(addUserQuotaEntity.getQuotaValue()) || ObjectUtils.isEmpty(addUserQuotaEntity.getQuotaUnit())){
return SdmResponse.failed("配置参数不能为空");
}
fileStorageQuotaService.saveBatch(fileStorageQuotas);
return SdmResponse.success();
// 判断用户是否存在存储配额,如果不存在则新增
FileStorageQuota existFileStorageQuota = fileStorageQuotaService.lambdaQuery().eq(FileStorageQuota::getUserId, addUserQuotaEntity.getUserId()).one();
if (ObjectUtils.isEmpty(existFileStorageQuota)) {
FileStorageQuota fileStorageQuota = new FileStorageQuota();
fileStorageQuota.setUserId(addUserQuotaEntity.getUserId());
fileStorageQuota.setQuotaValue(addUserQuotaEntity.getQuotaValue());
fileStorageQuota.setQuotaUnit(addUserQuotaEntity.getQuotaUnit());
fileStorageQuotaService.save(fileStorageQuota);
}
// 更新用户存储配额
fileStorageQuotaService.lambdaUpdate()
.eq(FileStorageQuota::getUserId, addUserQuotaEntity.getUserId())
.set(FileStorageQuota::getQuotaValue, addUserQuotaEntity.getQuotaValue())
.set(FileStorageQuota::getQuotaUnit, addUserQuotaEntity.getQuotaUnit())
.update();
}
return SdmResponse.success("更新成功");
}
/*

View File

@@ -401,8 +401,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
fileMetadataExtensionService.saveBatch(fileMetadataExtensionList);
//绑定文件和工况库的关系
if(ObjectUtils.isNotEmpty(req.getSimulationPoolId()) && Objects.nonNull(req.getSimulationPoolVersion()) && CollectionUtils.isNotEmpty(req.getSimulationPoolTaskIds())){
fileSimulationMappingService.saveFileSimulationMapping(fileInfo.getId(),req.getSimulationPoolId(),req.getSimulationPoolVersion(),req.getSimulationPoolTaskIds());
if(CollectionUtils.isNotEmpty(req.getSimulationPoolInfoList())){
for (SimulationPoolInfo simulationPoolInfo : req.getSimulationPoolInfoList()) {
fileSimulationMappingService.saveFileSimulationMapping(fileInfo.getId(),simulationPoolInfo.getSimulationPoolId(),simulationPoolInfo.getSimulationPoolVersion(),simulationPoolInfo.getSimulationPoolTaskIds());
}
}
// 创建默认权限记录
@@ -1353,11 +1355,12 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
fileMetadataExtensionService.saveBatch(fileMetadataExtensionList);
//绑定文件和工况库的关系
if(ObjectUtils.isNotEmpty(req.getSimulationPoolId()) && Objects.nonNull(req.getSimulationPoolVersion()) && CollectionUtils.isNotEmpty(req.getSimulationPoolTaskIds())){
fileSimulationMappingService.saveFileSimulationMapping(fileInfo.getId(),req.getSimulationPoolId(),req.getSimulationPoolVersion(),req.getSimulationPoolTaskIds());
if(CollectionUtils.isNotEmpty(req.getSimulationPoolInfoList())){
for (SimulationPoolInfo simulationPoolInfo : req.getSimulationPoolInfoList()) {
fileSimulationMappingService.saveFileSimulationMapping(fileInfo.getId(),simulationPoolInfo.getSimulationPoolId(),simulationPoolInfo.getSimulationPoolVersion(),simulationPoolInfo.getSimulationPoolTaskIds());
}
}
// 创建默认权限记录
createFilePermission(fileInfo.getId());