ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetAdController.java
@@ -1,7 +1,7 @@ package com.ruoyi.web.controller.api; import cn.idev.excel.FastExcel; import cn.afterturn.easypoi.excel.ExcelImportUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.R; @@ -12,9 +12,9 @@ import com.ruoyi.system.query.AssetAdQuery; import com.ruoyi.system.service.AssetAdRentalRecordService; import com.ruoyi.system.service.AssetAdService; import com.ruoyi.system.utils.FastExcelUtil; import com.ruoyi.system.vo.asset.AssetAdDetailVO; import com.ruoyi.system.vo.asset.AssetAdVO; import com.ruoyi.web.controller.listener.AssetAdValidatorListener; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -36,9 +36,7 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.net.URLEncoder; import java.util.Collections; import java.util.List; /** * <p> @@ -90,18 +88,7 @@ @ApiOperation("下载导入模板") @GetMapping("/template") public void getTemplate(HttpServletResponse response){ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); String fileName = null; try { fileName = URLEncoder.encode("广告无形资产导入模板", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); FastExcel.write(response.getOutputStream(), AssetAdDTO.class) .sheet("广告无形资产") .doWrite(Collections.emptyList()); } catch (IOException e) { log.error("下载导入模板异常", e); } FastExcelUtil.exportData(response, "广告无形资产导入模板", "广告无形资产", AssetAdDTO.class, Collections.emptyList()); } @ApiOperation("导入") @@ -112,14 +99,15 @@ return R.fail("请选择一个文件上传!"); } try { List<AssetAdDTO> list = FastExcel.read(file.getInputStream(), AssetAdDTO.class, new AssetAdValidatorListener()) .sheet() .doReadSync(); assetAdService.importAssetAd(list); //List<AssetAdDTO> list = FastExcelUtil.readMultipartFile(file.getInputStream(), AssetAdDTO.class); //assetAdService.importAssetAd(list); ExcelImportUtil.importExcel(file.getInputStream(), AssetAdDTO.class, null); return R.ok(); } catch (IOException e) { log.error("文件处理失败", e); return R.fail("文件处理失败!"); } catch (Exception e) { throw new RuntimeException(e); } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetAdMaterialPriceController.java
@@ -1,6 +1,5 @@ package com.ruoyi.web.controller.api; import cn.idev.excel.FastExcel; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.R; @@ -8,6 +7,7 @@ import com.ruoyi.system.dto.asset.AssetAdMaterialPriceDTO; import com.ruoyi.system.query.AssetAdMaterialPriceQuery; import com.ruoyi.system.service.AssetAdMaterialPriceService; import com.ruoyi.system.utils.FastExcelUtil; import com.ruoyi.system.vo.asset.AssetAdMaterialPriceVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.net.URLEncoder; import java.util.Collections; import java.util.List; @@ -91,18 +90,7 @@ @ApiOperation("下载导入模板") @GetMapping("/template") public void getTemplate(HttpServletResponse response){ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); String fileName = null; try { fileName = URLEncoder.encode("广告物料单价导入模板", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); FastExcel.write(response.getOutputStream(), AssetAdMaterialPriceDTO.class) .sheet("广告物料单价") .doWrite(Collections.emptyList()); } catch (IOException e) { log.error("下载导入模板异常", e); } FastExcelUtil.exportData(response, "广告物料单价导入模板", "广告物料单价", AssetAdMaterialPriceDTO.class, Collections.emptyList()); } @ApiOperation("导入") @@ -113,10 +101,7 @@ return R.fail("请选择一个文件上传!"); } try { List<AssetAdMaterialPriceDTO> list = FastExcel.read(file.getInputStream()) .head(AssetAdMaterialPriceDTO.class) .sheet() .doReadSync(); List<AssetAdMaterialPriceDTO> list = FastExcelUtil.readMultipartFile(file.getInputStream(), AssetAdMaterialPriceDTO.class); assetAdMaterialPriceService.importAssetAdMaterialPrice(list); return R.ok(); } catch (IOException e) { ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetAdMaterialSporadicSettlementController.java
@@ -1,9 +1,32 @@ package com.ruoyi.web.controller.api; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import com.google.common.collect.Lists; import com.ruoyi.common.core.domain.R; import com.ruoyi.system.dto.asset.AssetAdMaterialSporadicSettlementDTO; import com.ruoyi.system.export.AssetAdMaterialSporadicSettlementImport; import com.ruoyi.system.service.AssetAdMaterialSporadicSettlementService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.context.annotation.Lazy; import org.springframework.validation.annotation.Validated; 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.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.net.URLEncoder; /** * <p> @@ -13,8 +36,46 @@ * @author mitao * @since 2025-10-17 */ @Slf4j @Validated @Api(tags = {"广告物料零星结算相关接口"}) @RestController @RequestMapping("/asset-ad-material-sporadic-settlement") @RequiredArgsConstructor(onConstructor_ = {@Lazy}) public class AssetAdMaterialSporadicSettlementController { private final AssetAdMaterialSporadicSettlementService assetAdMaterialSporadicSettlementService; @ApiOperation("下载导入模板") @GetMapping("/template") public void downloadTemplate(HttpServletResponse response) { Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), AssetAdMaterialSporadicSettlementImport.class, Lists.newArrayList(new AssetAdMaterialSporadicSettlementImport())); ServletOutputStream outputStream = null; try { String fileName = URLEncoder.encode("广告物料零星结算导入模板.xls", "utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName); response.setHeader("content-Type", "application/vnd.ms-excel"); response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); outputStream = response.getOutputStream(); workbook.write(outputStream); } catch (IOException e) { log.error("房屋巡检导入模板下载失败!", e); } finally { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } @ApiOperation("导入零星资产结算数据") @PostMapping("/import") public R<?> importData(@RequestPart("file") MultipartFile file, @Valid AssetAdMaterialSporadicSettlementDTO dto) { assetAdMaterialSporadicSettlementService.importData(file, dto); return R.ok(); } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetHouseInspectionItemController.java
@@ -6,7 +6,6 @@ import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.ImportParams; import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.basic.PageInfo; @@ -18,27 +17,40 @@ import com.ruoyi.common.utils.WebUtils; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.system.dto.AddAssetHouseInspection; import com.ruoyi.system.dto.AddAssetRepairRequestDTO; import com.ruoyi.system.export.AssetHouseInspectionImport; import com.ruoyi.system.model.*; import com.ruoyi.system.model.AssetHouseInspectionDetail; import com.ruoyi.system.model.AssetHouseInspectionItem; import com.ruoyi.system.model.AssetHouseInspectionRecord; import com.ruoyi.system.model.AssetMain; import com.ruoyi.system.model.AssetPropertyExt; import com.ruoyi.system.model.AssetType; import com.ruoyi.system.query.AssetHouseInspectionRecordListQuery; import com.ruoyi.system.query.AssetRepairRequestListQuery; import com.ruoyi.system.service.*; import com.ruoyi.system.service.AssetHouseInspectionDetailService; import com.ruoyi.system.service.AssetHouseInspectionItemService; import com.ruoyi.system.service.AssetHouseInspectionRecordService; import com.ruoyi.system.service.AssetMainService; import com.ruoyi.system.service.AssetPropertyExtService; import com.ruoyi.system.service.AssetTypeService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.TDeptService; import com.ruoyi.system.vo.AssetHouseInspectionVO; import com.ruoyi.system.vo.AssetRepairRequestVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiOperation; import io.swagger.models.auth.In; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Workbook; import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; 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.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; ruoyi-admin/src/main/java/com/ruoyi/web/controller/listener/AssetAdValidatorListener.java
File was deleted ruoyi-system/src/main/java/com/ruoyi/system/annotation/ExcelValid.java
New file @@ -0,0 +1,14 @@ package com.ruoyi.system.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * <p>Excel导入必填校验注解</p> */ @Target({ ElementType.FIELD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelValid { String message() default "导入有未填入的字段"; } ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetAdDTO.java
@@ -3,6 +3,7 @@ import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.write.style.ColumnWidth; import com.ruoyi.system.annotation.ExcelValid; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -24,6 +25,7 @@ @ApiModelProperty(value = "资产名称") @ExcelProperty("资产名称") @ColumnWidth(11) @ExcelValid(message = "名称不能为空") @NotBlank(message = "资产名称") private String assetName; ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetAdMaterialPriceDTO.java
@@ -3,6 +3,7 @@ import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.write.style.ColumnWidth; import com.ruoyi.system.annotation.ExcelValid; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -29,6 +30,7 @@ @ApiModelProperty(value = "物料名称") @ExcelProperty("物料名称") @ColumnWidth(15) @ExcelValid(message = "名称不能为空") @NotBlank(message = "物料名称不能为空") private String materialName; @@ -36,12 +38,14 @@ @ExcelProperty("单价") @ColumnWidth(10) @NotNull(message = "单价不能为空") @ExcelValid(message = "单价不能为空") @DecimalMin(value = "0.01", message = "单价必须大于0") private BigDecimal unitPrice; @ApiModelProperty(value = "单位(元、平方米等)") @ExcelProperty("单位") @ColumnWidth(8) @ExcelValid(message = "单位不能为空") @NotBlank(message = "单位不能为空") private String priceUnit; ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetAdMaterialSporadicSettlementDTO.java
New file @@ -0,0 +1,30 @@ package com.ruoyi.system.dto.asset; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; /** * @author mitao * @date 2025/10/22 */ @Data @ApiModel("广告物料零星结算表数据传输对象") public class AssetAdMaterialSporadicSettlementDTO { @ApiModelProperty(value = "主键") private Integer id; @ApiModelProperty(value = "标题") @NotBlank(message = "标题不能为空") private String title; @ApiModelProperty(value = "结算项目") @NotBlank(message = "结算项目不能为空") private String settlementProject; @ApiModelProperty(value = "结算单位") @NotBlank(message = "结算单位不能为空") private String settlementInstitution; } ruoyi-system/src/main/java/com/ruoyi/system/export/AssetAdMaterialSporadicSettlementImport.java
New file @@ -0,0 +1,72 @@ package com.ruoyi.system.export; import cn.afterturn.easypoi.excel.annotation.Excel; import io.swagger.annotations.ApiModel; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; /** * <p> * 广告物料零星结算表关联表 * </p> * * @author mitao * @since 2025-10-17 */ @Data @ApiModel(value="AssetAdMaterialSporadicSettlementInfo对象", description="广告物料零星结算表关联表") public class AssetAdMaterialSporadicSettlementImport { @Excel(name = "日期", width = 20) private LocalDate settlementDate; @Excel(name = "安装地点", width = 20) private String address; @Excel(name = "名称", width = 20) private String adName; @Excel(name = "材质工艺", width = 20) private String material; /** * 设计图例oss地址 */ private String designLegend; @Excel(name = "设计图例",type = 2, width = 20) private String designLegendTemp; /** * 安装图例oss地址 */ private String installationLegend; @Excel(name = "安装图例",type = 2, width = 20) private String installationLegendTemp; @Excel(name = "长(米)", width = 20) private Double length; @Excel(name = "高(米)", width = 20) private Double height; @Excel(name = "数量", width = 20) private Integer quantity; @Excel(name = "小计", width = 20) private String subtotal; @Excel(name = "单价(元)", width = 20) private BigDecimal unitPrice; @Excel(name = "金额(元)", width = 20) private BigDecimal totalAmount; @Excel(name = "备注", width = 20) private String remark; } ruoyi-system/src/main/java/com/ruoyi/system/model/AssetAdMaterialIntegralSettlement.java
@@ -35,6 +35,9 @@ @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value = "所属部门ID") private Integer deptId; @ApiModelProperty(value = "标题") private String title; ruoyi-system/src/main/java/com/ruoyi/system/model/AssetAdMaterialQuotation.java
@@ -34,6 +34,9 @@ @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value = "所属部门ID") private Integer deptId; @ApiModelProperty(value = "标题") private String title; ruoyi-system/src/main/java/com/ruoyi/system/model/AssetAdMaterialSporadicSettlement.java
@@ -34,6 +34,9 @@ @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty(value = "所属部门ID") private Integer deptId; @ApiModelProperty(value = "标题") private String title; ruoyi-system/src/main/java/com/ruoyi/system/service/AssetAdMaterialSporadicSettlementService.java
@@ -1,7 +1,9 @@ package com.ruoyi.system.service; import com.ruoyi.system.dto.asset.AssetAdMaterialSporadicSettlementDTO; import com.ruoyi.system.model.AssetAdMaterialSporadicSettlement; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.web.multipart.MultipartFile; /** * <p> @@ -13,4 +15,5 @@ */ public interface AssetAdMaterialSporadicSettlementService extends IService<AssetAdMaterialSporadicSettlement> { void importData(MultipartFile file, AssetAdMaterialSporadicSettlementDTO dto); } ruoyi-system/src/main/java/com/ruoyi/system/service/OssService.java
@@ -3,6 +3,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; /** * @author mitao @@ -25,4 +26,6 @@ * @return */ String upload(String storagePath, MultipartFile file) throws IOException; String uploadByInputStream(InputStream inputStream); } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetAdMaterialSporadicSettlementServiceImpl.java
@@ -1,10 +1,33 @@ package com.ruoyi.system.service.impl; import com.ruoyi.system.model.AssetAdMaterialSporadicSettlement; import com.ruoyi.system.mapper.AssetAdMaterialSporadicSettlementMapper; import com.ruoyi.system.service.AssetAdMaterialSporadicSettlementService; import cn.afterturn.easypoi.excel.ExcelImportUtil; import cn.afterturn.easypoi.excel.entity.ImportParams; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.system.dto.asset.AssetAdMaterialSporadicSettlementDTO; import com.ruoyi.system.export.AssetAdMaterialSporadicSettlementImport; import com.ruoyi.system.mapper.AssetAdMaterialSporadicSettlementMapper; import com.ruoyi.system.model.AssetAdMaterialSporadicSettlement; import com.ruoyi.system.model.AssetAdMaterialSporadicSettlementInfo; import com.ruoyi.system.service.AssetAdMaterialSporadicSettlementInfoService; import com.ruoyi.system.service.AssetAdMaterialSporadicSettlementService; import com.ruoyi.system.service.OssService; import lombok.Cleanup; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.List; import java.util.Objects; import java.util.Optional; /** * <p> @@ -15,6 +38,98 @@ * @since 2025-10-17 */ @Service @RequiredArgsConstructor(onConstructor_ = {@Lazy}) public class AssetAdMaterialSporadicSettlementServiceImpl extends ServiceImpl<AssetAdMaterialSporadicSettlementMapper, AssetAdMaterialSporadicSettlement> implements AssetAdMaterialSporadicSettlementService { private final OssService ossService; private final AssetAdMaterialSporadicSettlementInfoService assetAdMaterialSporadicSettlementInfoService; @Transactional(rollbackFor = Exception.class) @Override public void importData(MultipartFile file, AssetAdMaterialSporadicSettlementDTO dto) { try { ImportParams importParams = new ImportParams(); importParams.setTitleRows(0); importParams.setHeadRows(1); @Cleanup InputStream inputStream = file.getInputStream(); List<AssetAdMaterialSporadicSettlementImport> list = ExcelImportUtil.importExcel(inputStream, AssetAdMaterialSporadicSettlementImport.class, importParams); validateFields(list); uploadToOss(list); //保存 AssetAdMaterialSporadicSettlement assetAdMaterialSporadicSettlement = BeanUtil.copyProperties(dto, AssetAdMaterialSporadicSettlement.class); assetAdMaterialSporadicSettlement.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName()); assetAdMaterialSporadicSettlement.setDeptId(Integer.parseInt(SecurityUtils.getLoginUser().getUser().getDeptId())); save(assetAdMaterialSporadicSettlement); //保存明细 List<AssetAdMaterialSporadicSettlementInfo> assetAdMaterialSporadicSettlementInfos = BeanUtil.copyToList(list, AssetAdMaterialSporadicSettlementInfo.class); assetAdMaterialSporadicSettlementInfos.forEach(item -> item.setAdMaterialSporadicSettlementId(assetAdMaterialSporadicSettlement.getId())); assetAdMaterialSporadicSettlementInfoService.saveBatch(assetAdMaterialSporadicSettlementInfos); } catch (Exception e) { throw new RuntimeException(e); } } private void validateFields(List<AssetAdMaterialSporadicSettlementImport> list) { Optional<AssetAdMaterialSporadicSettlementImport> any = list.stream() .filter(item -> StringUtils.isBlank(item.getAdName())).findAny(); if (any.isPresent()) { throw new ServiceException("【名称】不能为空,请检查该列是否填写完整"); } Optional<AssetAdMaterialSporadicSettlementImport> quantityOpt = list.stream() .filter(item -> Objects.isNull(item.getQuantity())).findAny(); if (quantityOpt.isPresent()) { throw new ServiceException("【数量】不能为空,请检查该列是否填写完整"); } Optional<AssetAdMaterialSporadicSettlementImport> priceOpt = list.stream() .filter(item -> Objects.isNull(item.getUnitPrice())).findAny(); if (priceOpt.isPresent()) { throw new ServiceException("【单价】不能为空,请检查该列是否填写完整"); } } /** * 文件转存 * @param list */ private void uploadToOss(List<AssetAdMaterialSporadicSettlementImport> list) { //遍历每一条数据 for (AssetAdMaterialSporadicSettlementImport settlementImport : list) { if (StringUtils.isNotEmpty(settlementImport.getDesignLegendTemp())) { String ossUrl = getOssUrl(settlementImport.getDesignLegendTemp()); settlementImport.setDesignLegend(ossUrl); } if (StringUtils.isNotEmpty(settlementImport.getInstallationLegendTemp())) { String ossUrl = getOssUrl(settlementImport.getInstallationLegendTemp()); settlementImport.setInstallationLegend(ossUrl); } } //删除图片缓存 for (AssetAdMaterialSporadicSettlementImport settlementImport : list) { if (StringUtils.isNotEmpty(settlementImport.getDesignLegendTemp())) { deleteImageCache(settlementImport.getDesignLegendTemp()); } if (StringUtils.isNotEmpty(settlementImport.getInstallationLegendTemp())) { deleteImageCache(settlementImport.getInstallationLegendTemp()); } } } private String getOssUrl(String filePath) { try { //获取到暂存的文件 File tmpFile = new File(filePath); FileInputStream fileInputStream = new FileInputStream(tmpFile); //转换为 multipartFile 类 return ossService.uploadByInputStream(fileInputStream); } catch (Exception e) { e.printStackTrace(); } return null; } private void deleteImageCache(String filePath) { //获取到暂存的文件 File tmpFile = new File(filePath); if (tmpFile.exists() && tmpFile.isFile()) { tmpFile.delete(); } } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OssServiceImpl.java
@@ -93,7 +93,38 @@ ossClient.shutdown(); } } @Override public String uploadByInputStream(InputStream inputStream) { OSS ossClient = null; try { CredentialsProvider credentialsProvider = new DefaultCredentialProvider(OssConfig.ACCESS_KEY_ID, OssConfig.ACCESS_KEY_SECRET); String region = "cn-chengdu"; // 创建OSSClient实例。 ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); ossClient = OSSClientBuilder.create() .endpoint(OssConfig.UPLOAD_ENDPOINT) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); String fileExt = "png"; String fileName = UUID.randomUUID().toString(); // 设置文件名 String filePathName = generateRelativeStoragePath(OssConfig.FOLDER, fileExt, fileName); // 创建PutObjectRequest对象。 PutObjectRequest putObjectRequest = new PutObjectRequest(OssConfig.BUCKET_NAME, filePathName, inputStream); // 创建PutObject请求。 PutObjectResult result = ossClient.putObject(putObjectRequest); return OssConfig.DOWNLOAD_ENDPOINT + filePathName; } finally { ossClient.shutdown(); } } /** * <pre> * 获取存储的相对路径 ruoyi-system/src/main/java/com/ruoyi/system/utils/ExcelImportValid.java
New file @@ -0,0 +1,33 @@ package com.ruoyi.system.utils; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.system.annotation.ExcelValid; import java.lang.reflect.Field; import java.util.Objects; public class ExcelImportValid { /** * Excel导入字段非空校验 * * @param object 校验的JavaBean 其属性须有自定义注解 */ public static void valid(Object object) throws Exception { Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { // 设置可访问 field.setAccessible(true); // 属性的值 Object fieldValue = null; try { fieldValue = field.get(object); } catch (IllegalAccessException e) { throw new ServiceException("导入参数检查失败!"); } // 是否包含必填校验注解 boolean isRequiredValid = field.isAnnotationPresent(ExcelValid.class); if (isRequiredValid && Objects.isNull(fieldValue)) { throw new ServiceException(field.getAnnotation(ExcelValid.class).message()); } } } } ruoyi-system/src/main/java/com/ruoyi/system/utils/FastExcelUtil.java
New file @@ -0,0 +1,63 @@ package com.ruoyi.system.utils; import cn.idev.excel.FastExcel; import cn.idev.excel.context.AnalysisContext; import cn.idev.excel.event.AnalysisEventListener; import com.ruoyi.common.exception.ServiceException; import lombok.extern.slf4j.Slf4j; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import java.util.List; /** * @author mitao * @date 2025/10/22 */ @Slf4j public class FastExcelUtil { public static <T> void exportData(HttpServletResponse response, String fileName, String sheetName, Class<T> clazz, List<T> data) { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); try { fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); FastExcel.write(response.getOutputStream(), clazz) .sheet(sheetName) .doWrite(data); } catch (IOException e) { log.error("导出数据异常", e); throw new ServiceException("导出数据异常"); } } /** * 读取文件数据,并返回一个包含指定类型数据的列表。 * * @param inputStream 文件对象输入流 * @param clazz 数据对象的类型 * @param <T> 泛型类型,表示数据对象的类型 * @return 包含解析后数据对象的列表 */ public static <T> List<T> readMultipartFile(InputStream inputStream, Class<T> clazz) { return FastExcel.read(inputStream, clazz, new AnalysisEventListener<T>() { @Override public void invoke(Object o, AnalysisContext analysisContext) { Integer rowIndex = analysisContext.readRowHolder().getRowIndex(); rowIndex += 1; // 行号从0开始,需要加1 try { // 调用字段校验方法 ExcelImportValid.valid(o); } catch (Exception e) { throw new ServiceException(String.format("第%d行:%s", rowIndex, e.getMessage())); } } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }).sheet().doReadSync(); // 读取 Excel 文件中的第一个工作表 } }