补全 api 缺失的方法

This commit is contained in:
chenbowen
2025-09-15 00:31:25 +08:00
parent 2ffed7cc9e
commit bea39f9b57
47 changed files with 1620 additions and 46 deletions

View File

@@ -1,14 +1,18 @@
package cn.iocoder.yudao.module.infra.api.businessfile;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.api.businessfile.dto.BusinessFilePageReqDTO;
import cn.iocoder.yudao.module.infra.api.businessfile.dto.BusinessFileRespDTO;
import cn.iocoder.yudao.module.infra.api.businessfile.dto.BusinessFileSaveReqDTO;
import cn.iocoder.yudao.module.infra.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
/**
@@ -20,8 +24,42 @@ public interface BusinessFileApi {
String PREFIX = ApiConstants.PREFIX + "/business-file";
@PostMapping(PREFIX + "/create")
@Operation(summary = "创建业务附件关联")
CommonResult<Long> createBusinessFile(@Valid @RequestBody BusinessFileSaveReqDTO createReqDTO);
@PostMapping(PREFIX + "/batch-create")
@Operation(summary = "批量新增业务附件关联")
CommonResult<List<Long>> batchCreateBusinessFile(@RequestBody List<BusinessFileSaveReqDTO> createReqDTOList);
@PutMapping(PREFIX + "/update")
@Operation(summary = "更新业务附件关联")
CommonResult<Boolean> updateBusinessFile(@Valid @RequestBody BusinessFileSaveReqDTO updateReqDTO);
@DeleteMapping(PREFIX + "/delete")
@Operation(summary = "删除业务附件关联")
@Parameter(name = "id", description = "编号", required = true)
CommonResult<Boolean> deleteBusinessFile(@RequestParam("id") Long id);
@DeleteMapping(PREFIX + "/delete-list")
@Operation(summary = "批量删除业务附件关联")
@Parameter(name = "ids", description = "编号列表", required = true)
CommonResult<Boolean> deleteBusinessFileList(@RequestParam("ids") List<Long> ids);
@GetMapping(PREFIX + "/get")
@Operation(summary = "获得业务附件关联")
@Parameter(name = "id", description = "编号", required = true)
CommonResult<BusinessFileRespDTO> getBusinessFile(@RequestParam("id") Long id);
@GetMapping(PREFIX + "/page")
@Operation(summary = "获得业务附件关联分页")
CommonResult<PageResult<BusinessFileRespDTO>> getBusinessFilePage(@Valid BusinessFilePageReqDTO pageReqDTO);
@DeleteMapping(PREFIX + "/delete-by-business")
@Operation(summary = "根据业务Id和来源删除业务附件关联")
@Parameter(name = "businessId", description = "业务Id", required = true)
@Parameter(name = "source", description = "业务来源", required = true)
CommonResult<Boolean> deleteBusinessFileByBusinessIdAndSource(@RequestParam("businessId") Long businessId,
@RequestParam("source") String source);
}

View File

@@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.infra.api.businessfile.dto;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 业务附件关联分页查询 DTO
*
* @author 后台管理
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BusinessFilePageReqDTO extends PageParam implements Serializable {
/**
* 业务Id
*/
private Long businessId;
/**
* 业务编码
*/
private String businessCode;
/**
* 文件名
*/
private String fileName;
/**
* 业务来源
*/
private String source;
/**
* 创建时间
*/
private LocalDateTime[] createTime;
}

View File

@@ -0,0 +1,62 @@
package cn.iocoder.yudao.module.infra.api.businessfile.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 业务附件关联响应 DTO
*
* @author 后台管理
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BusinessFileRespDTO implements Serializable {
/**
* 编号
*/
private Long id;
/**
* 业务Id
*/
private Long businessId;
/**
* 业务编码
*/
private String businessCode;
/**
* 文件名
*/
private String fileName;
/**
* 文件Id
*/
private Long fileId;
/**
* 业务来源
*/
private String source;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@@ -1,9 +1,14 @@
package cn.iocoder.yudao.module.infra.api.businessfile;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.api.businessfile.dto.BusinessFilePageReqDTO;
import cn.iocoder.yudao.module.infra.api.businessfile.dto.BusinessFileRespDTO;
import cn.iocoder.yudao.module.infra.api.businessfile.dto.BusinessFileSaveReqDTO;
import cn.iocoder.yudao.module.infra.controller.admin.businessfile.vo.BusinessFilePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.businessfile.vo.BusinessFileSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.businessfile.BusinessFileDO;
import cn.iocoder.yudao.module.infra.service.businessfile.BusinessFileService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@@ -24,10 +29,51 @@ public class BusinessFileApiImpl implements BusinessFileApi {
@Resource
private BusinessFileService businessFileService;
@Override
public CommonResult<Long> createBusinessFile(BusinessFileSaveReqDTO createReqDTO) {
return success(businessFileService.createBusinessFile(BeanUtils.toBean(createReqDTO, BusinessFileSaveReqVO.class)));
}
@Override
public CommonResult<List<Long>> batchCreateBusinessFile(List<BusinessFileSaveReqDTO> createReqDTOList) {
List<BusinessFileSaveReqVO> createReqVOList = BeanUtils.toBean(createReqDTOList, BusinessFileSaveReqVO.class);
List<Long> ids = businessFileService.batchCreateBusinessFile(createReqVOList);
return success(ids);
}
@Override
public CommonResult<Boolean> updateBusinessFile(BusinessFileSaveReqDTO updateReqDTO) {
businessFileService.updateBusinessFile(BeanUtils.toBean(updateReqDTO, BusinessFileSaveReqVO.class));
return success(true);
}
@Override
public CommonResult<Boolean> deleteBusinessFile(Long id) {
businessFileService.deleteBusinessFile(id);
return success(true);
}
@Override
public CommonResult<Boolean> deleteBusinessFileList(List<Long> ids) {
businessFileService.deleteBusinessFileListByIds(ids);
return success(true);
}
@Override
public CommonResult<BusinessFileRespDTO> getBusinessFile(Long id) {
BusinessFileDO businessFile = businessFileService.getBusinessFile(id);
return success(BeanUtils.toBean(businessFile, BusinessFileRespDTO.class));
}
@Override
public CommonResult<PageResult<BusinessFileRespDTO>> getBusinessFilePage(BusinessFilePageReqDTO pageReqDTO) {
PageResult<BusinessFileDO> pageResult = businessFileService.getBusinessFilePage(BeanUtils.toBean(pageReqDTO, BusinessFilePageReqVO.class));
return success(BeanUtils.toBean(pageResult, BusinessFileRespDTO.class));
}
@Override
public CommonResult<Boolean> deleteBusinessFileByBusinessIdAndSource(Long businessId, String source) {
businessFileService.deleteBusinessFileByBusinessIdAndSource(businessId, source);
return success(true);
}
}

View File

@@ -27,7 +27,9 @@ import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.iocoder.yudao.module.infra.controller.admin.businessfile.vo.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.businessfile.BusinessFileDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.service.businessfile.BusinessFileService;
import cn.iocoder.yudao.module.infra.service.file.FileService;
@Tag(name = "管理后台 - 业务附件关联")
@RestController
@@ -38,6 +40,9 @@ public class BusinessFileController {
@Resource
private BusinessFileService businessFileService;
@Resource
private FileService fileService;
@PostMapping("/create")
@Operation(summary = "创建业务附件关联")
@PreAuthorize("@ss.hasPermission('infra:business-file:create')")
@@ -95,6 +100,46 @@ public class BusinessFileController {
return success(BeanUtils.toBean(pageResult, BusinessFileRespVO.class));
}
@GetMapping("/page-with-url")
@Operation(summary = "获得业务附件关联分页带URL")
@PreAuthorize("@ss.hasPermission('infra:business-file:query')")
public CommonResult<PageResult<BusinessFileWithUrlRespVO>> getBusinessFilePageWithUrl(@Valid BusinessFilePageReqVO pageReqVO) {
PageResult<BusinessFileDO> pageResult = businessFileService.getBusinessFilePage(pageReqVO);
PageResult<BusinessFileWithUrlRespVO> result = BeanUtils.toBean(pageResult, BusinessFileWithUrlRespVO.class);
// 批量获取文件信息并设置URL
List<Long> fileIds = result.getList().stream()
.map(BusinessFileWithUrlRespVO::getFileId)
.filter(Objects::nonNull)
.distinct()
.toList();
// 批量查询文件信息
Map<Long, FileDO> fileMap = new HashMap<>();
for (Long fileId : fileIds) {
FileDO fileDO = fileService.getActiveFileById(fileId);
if (fileDO != null) {
fileMap.put(fileId, fileDO);
}
}
// 设置文件相关信息
for (BusinessFileWithUrlRespVO vo : result.getList()) {
if (vo.getFileId() != null) {
FileDO fileDO = fileMap.get(vo.getFileId());
if (fileDO != null) {
vo.setFilePath(fileDO.getPath());
vo.setFileUrl(fileDO.getUrl());
vo.setIsEncrypted(fileDO.getIsEncrypted());
vo.setFileType(fileDO.getType());
vo.setFileSize(fileDO.getSize());
}
}
}
return success(result);
}
@GetMapping("/export-excel")
@Operation(summary = "导出业务附件关联 Excel")
@PreAuthorize("@ss.hasPermission('infra:business-file:export')")
@@ -108,4 +153,15 @@ public class BusinessFileController {
BeanUtils.toBean(list, BusinessFileRespVO.class));
}
@DeleteMapping("/delete-by-business")
@Operation(summary = "根据业务Id和来源删除业务附件关联")
@Parameter(name = "businessId", description = "业务Id", required = true)
@Parameter(name = "source", description = "业务来源", required = true)
@PreAuthorize("@ss.hasPermission('infra:business-file:delete')")
public CommonResult<Boolean> deleteBusinessFileByBusinessIdAndSource(@RequestParam("businessId") Long businessId,
@RequestParam("source") String source) {
businessFileService.deleteBusinessFileByBusinessIdAndSource(businessId, source);
return success(true);
}
}

View File

@@ -0,0 +1,97 @@
package cn.iocoder.yudao.module.infra.controller.admin.businessfile.vo;
import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.framework.file.core.client.FileClient;
import cn.iocoder.yudao.module.infra.framework.file.core.client.s3.S3FileClient;
import cn.iocoder.yudao.module.infra.service.file.FileConfigService;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.Date;
/**
* @author 后台管理
*/
@Schema(description = "管理后台 - 业务附件关联带URL Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class BusinessFileWithUrlRespVO extends BusinessFileRespVO {
@Schema(description = "文件路径", example = "yudao.jpg")
private String filePath;
@Schema(description = "文件 URL", example = "https://www.iocoder.cn/yudao.jpg")
private String fileUrl;
@Schema(description = "附件预览地址", example = "https://www.iocoder.cn/yudao.jpg")
private String previewUrl;
@Schema(description = "是否加密", example = "false")
private Boolean isEncrypted;
@Schema(description = "文件MIME类型", example = "application/octet-stream")
private String fileType;
@Schema(description = "文件大小", example = "2048")
private Integer fileSize;
/**
* 获取文件 URL参考 FileRespVO 的实现)
*/
public String getFileUrl() {
// 加密附件不返回 url
if (Boolean.TRUE.equals(this.isEncrypted)) {
return null;
}
// 如果 url 已经是临时下载地址(如预签名 URL直接返回
if (fileUrl != null && (fileUrl.contains("X-Amz-Signature") || fileUrl.contains("?sign="))) {
return fileUrl;
}
FileConfigService fileConfigService = SpringUtils.getBean(FileConfigService.class);
FileClient fileClient = fileConfigService.getMasterFileClient();
if (fileClient instanceof S3FileClient s3FileClient) {
String presignedDownloadUrl = s3FileClient.getPresignedDownloadUrl(this.filePath, null);
if (presignedDownloadUrl != null && !presignedDownloadUrl.isEmpty()) {
return presignedDownloadUrl;
}
}
return fileUrl;
}
/**
* 获取附件预览地址(参考 FileRespVO 的实现)
*/
public String getPreviewUrl() {
// 加密附件不返回 previewUrl
if (Boolean.TRUE.equals(this.isEncrypted)) {
return null;
}
// 仅当 url 不为空时生成
if (this.fileUrl == null || this.fileUrl.isEmpty()) {
return null;
}
// 这里的 onlinePreview 通过 SpringUtils 获取
String onlinePreview = SpringUtils.getProperty("yudao.kkfile");
if (onlinePreview == null || onlinePreview.isEmpty()) {
return null;
}
String presignedUrl = this.getFileUrl();
if (presignedUrl == null || presignedUrl.isEmpty()) {
return null;
}
String base64PresignedUrl = Base64.getEncoder().encodeToString(presignedUrl.getBytes(StandardCharsets.UTF_8));
String timestamp = String.valueOf(System.currentTimeMillis());
String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname();
String format = DateUtil.format(new Date(), "yyyy-MM-dd");
String watermark = SpringUtils.getProperty("aj.captcha.water-mark", loginUserNickname+" "+ format);
return onlinePreview + base64PresignedUrl + "&t=" + timestamp + "&watermarkTxt=" + watermark;
}
}

View File

@@ -61,4 +61,12 @@ public interface BusinessFileService {
PageResult<BusinessFileDO> getBusinessFilePage(BusinessFilePageReqVO pageReqVO);
List<Long> batchCreateBusinessFile(List<BusinessFileSaveReqVO> createReqVOList);
/**
* 根据业务Id和来源删除业务附件关联
*
* @param businessId 业务Id
* @param source 业务来源
*/
void deleteBusinessFileByBusinessIdAndSource(Long businessId, String source);
}

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.service.businessfile;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.controller.admin.businessfile.vo.BusinessFilePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.businessfile.vo.BusinessFileSaveReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.businessfile.BusinessFileDO;
@@ -96,4 +97,11 @@ public class BusinessFileServiceImpl implements BusinessFileService {
}
return ids;
}
@Override
public void deleteBusinessFileByBusinessIdAndSource(Long businessId, String source) {
businessFileMapper.delete(new LambdaQueryWrapperX<BusinessFileDO>()
.eq(BusinessFileDO::getBusinessId, businessId)
.eq(BusinessFileDO::getSource, source));
}
}