diff --git a/xinnengyuan/pom.xml b/xinnengyuan/pom.xml index 6cfadc39..4499b51c 100644 --- a/xinnengyuan/pom.xml +++ b/xinnengyuan/pom.xml @@ -331,7 +331,7 @@ commons-io commons-io - 2.15.0 + 2.16.1 diff --git a/xinnengyuan/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java b/xinnengyuan/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java index b22e6f98..0e73e4d3 100644 --- a/xinnengyuan/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java +++ b/xinnengyuan/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java @@ -19,12 +19,14 @@ import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.core.*; import org.dromara.common.excel.handler.DataWriteHandler; +import org.springframework.http.HttpHeaders; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -203,6 +205,60 @@ public class ExcelUtil { builder.doWrite(list); } + /** + * 导出多sheet excel(增强版,解决XML安全问题) + * + * @param sheetData 多个sheet的数据 + * @param sheetNames 多个sheet的名称 + * @param clazz 实体类 + * @param optionsList 级联下拉选内容列表 + */ + public static void exportMultiSheetExcelEnhanced(List> sheetData, List sheetNames, Class clazz, List> optionsList,HttpServletResponse response) throws IOException { + resetResponse("file", response); + ExcelWriter excelWriter = null; + ServletOutputStream os = response.getOutputStream(); + + try { + // 使用SXSSFWorkbook避免内存问题,并减少XML处理复杂度 + excelWriter = EasyExcel.write(os) + .head(clazz) + .autoCloseStream(false) + .registerConverter(new ExcelBigNumberConvert()) + .build(); + + + // 为每个sheet写入数据 + for (int i = 0; i < sheetData.size(); i++) { + // 创建基本sheet配置 + WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetNames.get(i)) + .head(clazz) + .build(); + + // 添加下拉选项(如果存在) + if (optionsList != null && optionsList.size() > i && optionsList.get(i) != null) { + ExcelDownHandler handler = new ExcelDownHandler(optionsList.get(i)); + writeSheet.setCustomWriteHandlerList( + Collections.singletonList(handler)); + } + + // 写入数据 + excelWriter.write(sheetData.get(i), writeSheet); + } + + } finally { + // 确保资源正确释放 + if (excelWriter != null) { + try { + excelWriter.finish(); + } catch (Exception e) { + // 记录日志但不中断主流程 + e.printStackTrace(); + } + } + } + } + + /** * 单表多数据模板导出 模板格式为 {.属性} * @@ -436,4 +492,7 @@ public class ExcelUtil { return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; } + + + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsProgressCategoryController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsProgressCategoryController.java index b2d50cc6..2b348e12 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsProgressCategoryController.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsProgressCategoryController.java @@ -1,16 +1,28 @@ package org.dromara.progress.controller; import cn.dev33.satoken.annotation.SaCheckPermission; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelReader; +import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder; +import com.alibaba.excel.read.metadata.ReadSheet; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import jakarta.annotation.Resource; +import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.R; +import org.dromara.common.excel.core.DefaultExcelListener; +import org.dromara.common.excel.core.ExcelResult; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.web.core.BaseController; +import org.dromara.design.domain.BusBillofquantities; +import org.dromara.facility.service.IFacMatrixService; +import org.dromara.progress.domain.PgsProgressCategory; import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq; import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq; import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq; @@ -20,10 +32,15 @@ import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryLastTi import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryProjectVo; import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo; import org.dromara.progress.service.IPgsProgressCategoryService; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; -import java.util.List; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.stream.Collectors; /** * 进度类别 @@ -31,6 +48,7 @@ import java.util.List; * @author lilemy * @date 2025-05-26 */ +@Slf4j @Validated @RestController @RequestMapping("/progress/progressCategory") @@ -38,6 +56,8 @@ public class PgsProgressCategoryController extends BaseController { @Resource private IPgsProgressCategoryService pgsProgressCategoryService; + @Resource + private IFacMatrixService matrixService; /** * 查询进度类别列表 @@ -54,10 +74,102 @@ public class PgsProgressCategoryController extends BaseController { */ @SaCheckPermission("progress:progressCategory:export") @Log(title = "进度类别", businessType = BusinessType.EXPORT) + @Transactional @PostMapping("/export") - public void export(PgsProgressCategoryQueryReq req, HttpServletResponse response) { - List list = pgsProgressCategoryService.queryList(req); - ExcelUtil.exportExcel(list, "进度类别", PgsProgressCategoryVo.class, response); + public void export(@RequestBody Map>ids, HttpServletResponse response) throws IOException { + List> voList = new ArrayList<>(); + List sheetNames = new ArrayList<>(); + List idss = new ArrayList<>(); + + + + List idStrings = ids.get("ids"); + for (String idString : idStrings) { + idss.add(Long.valueOf(idString)); + } + + for (Long id : idss) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(PgsProgressCategory::getMatrixId,id); + List voList1 = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper)); + voList.add(voList1); + sheetNames.add(matrixService.getById(voList1.getFirst().getMatrixId()).getMatrixName()); + } + + ExcelUtil.exportMultiSheetExcelEnhanced(voList,sheetNames,PgsProgressCategoryVo.class,null,response); + } + + /*** + * 导入 + */ + @SaCheckPermission("progress:progressCategory:import") + @Log(title = "进度类别导入", businessType = BusinessType.IMPORT) + @PostMapping("/import") + public R importData(@RequestParam("file") MultipartFile file) throws Exception { + + // 检查文件是否为空 + if (file == null || file.isEmpty()) { + return R.fail("上传文件不能为空"); + } + // 检查文件大小 + if (file.getSize() == 0) { + return R.fail("上传文件不能为空文件"); + } + // 检查文件名 + if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) { + return R.fail("文件名不能为空"); + } + + try { + // 使用EasyExcel读取所有sheet + List allData = new ArrayList<>(); + + // 创建Excel读取监听器 + DefaultExcelListener listener = new DefaultExcelListener<>(false); + + // 读取Excel文件 + ExcelReader excelReader = EasyExcel.read(file.getInputStream(), PgsProgressCategoryVo.class, listener).build(); + + // 获取所有sheet + List sheetList = excelReader.excelExecutor().sheetList(); + + // 遍历所有sheet + for (ReadSheet readSheet : sheetList) { + // 为每个sheet创建新的监听器实例 + DefaultExcelListener sheetListener = new DefaultExcelListener<>(false); + + // 读取当前sheet数据 + EasyExcel.read(file.getInputStream(), PgsProgressCategoryVo.class, sheetListener) + .sheet(readSheet.getSheetNo()) + .doRead(); + + // 将当前sheet的数据添加到总数据中 + allData.addAll(sheetListener.getExcelResult().getList()); + } + + // 关闭读取器 + excelReader.finish(); + + if (allData.isEmpty()) { + return R.fail("未读取到有效数据"); + } + // 处理导入的数据 + // TODO: 添加你的业务逻辑 + List list = new ArrayList<>(); + for (PgsProgressCategoryVo vo : allData) { + list.add(pgsProgressCategoryService.convertVoToEntity(vo)); + } + + boolean b = pgsProgressCategoryService.updateBatchById(list); + if (!b){ + return R.fail("更新失败"); + } + + return R.ok("导入成功,共更新 " + list.size() + " 条数据"); + } catch (Exception e) { + log.error("导入Excel文件失败", e); + return R.fail("导入失败: " + e.getMessage()); + } } /** @@ -153,4 +265,12 @@ public class PgsProgressCategoryController extends BaseController { @PathVariable Long[] ids) { return toAjax(pgsProgressCategoryService.deleteWithValidByIds(List.of(ids), true)); } + + /*** + * 分项工程方阵导出 + */ +// @SaCheckPermission("progress:progressCategory:export") +// @Log(title = "分项工程方阵导出", businessType = BusinessType.EXPORT) +// @GetMapping("/export") + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/mapper/PgsProgressCategoryMapper.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/mapper/PgsProgressCategoryMapper.java index 8a01aa84..48dc909e 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/mapper/PgsProgressCategoryMapper.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/mapper/PgsProgressCategoryMapper.java @@ -1,9 +1,13 @@ package org.dromara.progress.mapper; +import org.apache.ibatis.annotations.Select; import org.dromara.progress.domain.PgsProgressCategory; import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import java.util.List; +import java.util.Map; + /** * 进度类别Mapper接口 * @@ -12,4 +16,8 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; */ public interface PgsProgressCategoryMapper extends BaseMapperPlus { + @Select(""" + select count(id),project_id,matrix_id from pgs_progress_category GROUP BY matrix_id,project_id HAVING project_id = #{projectId} + """) + List> getMatrixIdAndNumber(Long projectId); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/IPgsProgressCategoryService.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/IPgsProgressCategoryService.java index 5beb4f18..37923e38 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/IPgsProgressCategoryService.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/IPgsProgressCategoryService.java @@ -15,6 +15,7 @@ import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo; import java.util.Collection; import java.util.List; +import java.util.Map; /** * 进度类别Service接口 @@ -137,4 +138,12 @@ public interface IPgsProgressCategoryService extends IService queryListByProjectIds(List projectIds); + + /*** + * 获取方阵id及对应数量 + */ + List> getMatrixIdAndNumber(Long projectId); + + + public PgsProgressCategory convertVoToEntity(PgsProgressCategoryVo vo); } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/impl/PgsProgressCategoryServiceImpl.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/impl/PgsProgressCategoryServiceImpl.java index 55a0a87b..4f4a8c5f 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/impl/PgsProgressCategoryServiceImpl.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/service/impl/PgsProgressCategoryServiceImpl.java @@ -935,4 +935,21 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl> getMatrixIdAndNumber(Long projectId){ + return baseMapper.getMatrixIdAndNumber(projectId); + } + + @Override + public PgsProgressCategory convertVoToEntity(PgsProgressCategoryVo vo){ + if (vo == null) { + return null; + } + + PgsProgressCategory entity = new PgsProgressCategory(); + org.springframework.beans.BeanUtils.copyProperties(vo, entity); + return entity; + } + } diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/tender/util/LunchDataListenerMultiSheet.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/tender/util/LunchDataListenerMultiSheet.java new file mode 100644 index 00000000..caeba48a --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/tender/util/LunchDataListenerMultiSheet.java @@ -0,0 +1,51 @@ +package org.dromara.tender.util; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +@Slf4j +@Data +public class LunchDataListenerMultiSheet extends AnalysisEventListener> { + + private List> dataList; + + public LunchDataListenerMultiSheet() { + this.dataList = new ArrayList<>(); + } + + + /** + * 每读到一行数据都调用invoke方法 + * + * @param integerObjectMap + * @param context + */ + @Override + public void invoke(Map integerObjectMap, AnalysisContext context) { + Integer rowIndex = context.readRowHolder().getRowIndex(); + System.out.println("rowIndex = " + rowIndex); + // key为列号,value为单元格的内容 + log.info("解析到数据:{}", integerObjectMap); + // 把数据放到dataList里面,便于统一处理 + LinkedList strings = new LinkedList<>(); + integerObjectMap.forEach((k,v) -> { + strings.add(v); + }); + this.dataList.add(strings); + } + + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + // 读完所有数据,做统一处理。 + // 当然还可以拿到listener之外处理 + log.info("数据读取完成"); + } +}