ruoyi-admin/pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ReportController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-system/pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-system/src/main/java/com/ruoyi/system/utils/ExcelPoiUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-system/src/main/java/com/ruoyi/system/vo/system/LocationTypeListByProjectVO.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-system/src/main/java/com/ruoyi/system/vo/system/ProjectDeptDetailsChildVO.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-system/src/main/java/com/ruoyi/system/vo/system/ProjectDeptDetailsVO.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
ruoyi-system/src/main/java/com/ruoyi/system/vo/system/TaskSummaryVO.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
ruoyi-admin/pom.xml
@@ -148,16 +148,16 @@ <!-- excel工具 --> <!-- Apache POI核心依赖 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <!-- <dependency>--> <!-- <groupId>org.apache.poi</groupId>--> <!-- <artifactId>poi</artifactId>--> <!-- <version>3.17</version>--> <!-- </dependency>--> <!-- <dependency>--> <!-- <groupId>org.apache.poi</groupId>--> <!-- <artifactId>poi-ooxml</artifactId>--> <!-- <version>3.17</version>--> <!-- </dependency>--> <dependency> <groupId>net.coobird</groupId> ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/ReportController.java
@@ -16,6 +16,7 @@ import com.ruoyi.system.model.*; import com.ruoyi.system.query.*; import com.ruoyi.system.service.*; import com.ruoyi.system.utils.ExcelPoiUtils; import com.ruoyi.system.vo.system.*; import com.ruoyi.web.util.OssUploadUtil; import io.swagger.annotations.Api; @@ -479,7 +480,6 @@ locationTypeListByProjectVOS1.add(temp); } projectDeptDetailsChildVO.setLocationTypeList(locationTypeListByProjectVOS1); projectDeptDetailsChildVO.setCleanerCount(0); } @@ -631,7 +631,6 @@ @ApiOperation(value = "巡检人员报表") @PostMapping(value = "/patrolInspectorList") public R<List<PatrolInspectorVO>> patrolInspectorList(@RequestBody PatrolInspectorQuery query) { List<SysUser> sysUsers = sysUserService.selectAllList(); LambdaQueryWrapper<TLeave> tLeaveLambdaQueryWrapper = new LambdaQueryWrapper<>(); @@ -1075,5 +1074,140 @@ } } } @ApiOperation(value = "任务报表导出模板") @PostMapping(value = "/exportExcel") public void exportExcel(@RequestBody TaskDetailsQuery query,HttpServletResponse response) throws Exception{ // 动态标头名称字段 final String headerName = "locationTypeName"; // 动态标头值字段 final String headerValue = "locationNum"; List<TLocationType> locationTypeList = locationTypeService.list(); List<TLocation> locations = locationService.list(); LambdaQueryWrapper<TTask> tTaskLambdaQueryWrapper = new LambdaQueryWrapper<>(); if (StringUtils.hasLength(query.getStartTime()) && StringUtils.hasLength(query.getEndTime())) { tTaskLambdaQueryWrapper.ge(TTask::getImplementTime, query.getStartTime()); tTaskLambdaQueryWrapper.le(TTask::getImplementTime, query.getEndTime()); } List<ProjectDeptDetailsVO> res = new ArrayList<>(); List<TTask> tasks = taskCleanerService.list(tTaskLambdaQueryWrapper); List<TTaskDetail> taskDetails = taskDetailService.lambdaQuery().orderByDesc(BaseModel::getCreateTime).list(); List<String> collect = tasks.stream().map(TTask::getProjectId).distinct().collect(Collectors.toList()); List<TProjectDept> projectDepts = projectDeptService.list(); List<String> strings = new ArrayList<>(); // 片区ids 反查项目部 List<TProjectDept> list1 = projectDeptService.lambdaQuery().in(TProjectDept::getId, collect).list(); for (TProjectDept tProjectDept : list1) { TProjectDept tProjectDept1 = projectDepts.stream().filter(e -> e.getId().equals(tProjectDept.getParentId())).findFirst().orElse(null); if (tProjectDept1 != null && !strings.contains(tProjectDept1.getId())) { ProjectDeptDetailsVO projectDeptDetailsVO = new ProjectDeptDetailsVO(); projectDeptDetailsVO.setProjectName(tProjectDept1.getProjectName()); List<TProjectDept> collect1 = list1.stream().filter(e -> e.getParentId().equals(tProjectDept1.getId())).collect(Collectors.toList()); List<ProjectDeptDetailsChildVO> projectDeptDetailsChildVOS = new ArrayList<>(); for (TProjectDept projectDept : collect1) { ProjectDeptDetailsChildVO projectDeptDetailsChildVO = new ProjectDeptDetailsChildVO(); projectDeptDetailsChildVO.setProjectChildName(projectDept.getProjectName()); projectDeptDetailsChildVO.setProjectId(projectDept.getId()); projectDeptDetailsChildVOS.add(projectDeptDetailsChildVO); } projectDeptDetailsVO.setProjectChild(projectDeptDetailsChildVOS); res.add(projectDeptDetailsVO); strings.add(tProjectDept1.getId()); } } List<LocationTypeListByProjectVO> locationTypeListByProjectVOS = new ArrayList<>(); for (TLocationType tLocationType : locationTypeList) { LocationTypeListByProjectVO locationTypeListByProjectVO = new LocationTypeListByProjectVO(); locationTypeListByProjectVO.setLocationTypeName(tLocationType.getLocationName()); locationTypeListByProjectVO.setLocationNum(0); locationTypeListByProjectVO.setId(tLocationType.getId()); locationTypeListByProjectVOS.add(locationTypeListByProjectVO); } for (ProjectDeptDetailsVO re : res) { List<ProjectDeptDetailsChildVO> projectChild = re.getProjectChild(); for (ProjectDeptDetailsChildVO projectDeptDetailsChildVO : projectChild) { int cleanerCount = cleanerService.lambdaQuery().eq(TCleaner::getProjectId, projectDeptDetailsChildVO.getProjectId()).list().size(); projectDeptDetailsChildVO.setCleanerCount(cleanerCount); for (LocationTypeListByProjectVO locationTypeListByProjectVO : locationTypeListByProjectVOS) { List<TaskSummaryVO> taskSummaryVOS = new ArrayList<>(); List<String> locationIds = locations.stream().filter(e -> e.getLocationType().equals(locationTypeListByProjectVO.getId())).map(TLocation::getId).collect(Collectors.toList()); if (locationIds.isEmpty()) { locationTypeListByProjectVO.setLocationNum(0); } else { List<TTask> taskList = tasks.stream().filter(e -> e.getProjectId().equals(projectDeptDetailsChildVO.getProjectId()) && locationIds.contains(e.getLocationId())).collect(Collectors.toList()); Integer count = taskList.size(); locationTypeListByProjectVO.setLocationNum(count); int total = taskList.size(); int num1 = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; TaskSummaryVO taskSummaryVO = new TaskSummaryVO(); for (TTask tTask : taskList) { TTaskDetail tTaskDetail = taskDetails.stream().filter(e -> e.getTaskId().equals(tTask.getId()) && e.getClearStatus() != null).findFirst().orElse(null); if (tTaskDetail!=null){ switch (tTaskDetail.getClearStatus()) { case 1: num1++; break; case 2: num2++; break; } } // 任务状态:1未执行、2超时、3待确认、4待整改、5整改完成、6已完成 switch (tTask.getStatus()) { case 1: if (tTaskDetail == null) { num3++; } break; case 2: num6++; break; case 3: break; case 4: num4++; break; case 5: num7++; break; case 6: num5++; break; } } taskSummaryVO.setTotal(total); taskSummaryVO.setNum1(num1); taskSummaryVO.setNum2(num2); taskSummaryVO.setNum3(num3); taskSummaryVO.setNum4(num4); taskSummaryVO.setNum5(num5); taskSummaryVO.setNum6(num6); taskSummaryVO.setNum7(num7); taskSummaryVOS.add(taskSummaryVO); } projectDeptDetailsChildVO.setTaskSummaryVOS(taskSummaryVOS); } projectDeptDetailsChildVO.setLocationTypeList(locationTypeListByProjectVOS); } } try { String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss")); ExcelPoiUtils.exportExcel(response, "任务报表_"+time, "任务报表导出模板", "sheet", res, headerName, headerValue); } catch (Exception e) { System.out.println("导出错误,"+e.getMessage()); throw new RuntimeException(e.getMessage()); } } } ruoyi-system/pom.xml
@@ -41,17 +41,17 @@ <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.0.3</version> <version>4.4.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.0.3</version> <version>4.4.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.0.3</version> <version>4.4.0</version> </dependency> <!--mybatis-plus--> @@ -93,6 +93,12 @@ <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83_noneautotype</version> <scope>compile</scope> </dependency> </dependencies> </project> ruoyi-system/src/main/java/com/ruoyi/system/utils/ExcelPoiUtils.java
New file @@ -0,0 +1,333 @@ package com.ruoyi.system.utils; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelCollection; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.hutool.core.annotation.AnnotationUtil; import cn.hutool.core.util.ReflectUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.BufferedOutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * @Author: 一杯美式 * @version: V1.0 * @Date: 2024-04-23 10:38 * @Package: com.victory.jfe.pdm.srm.config */ @Slf4j @Service public class ExcelPoiUtils { /** * 动态列导出 * @param response 响应 * @param fileName 文件名 * @param title 标题 * @param sheetName sheet名称 * @param dataList 导出数据 * @param headerName 动态列标题 * @param headerValue 动态列值 * @param <T> * @throws Exception */ public static <T> void exportExcel(HttpServletResponse response, String fileName, String title, String sheetName, List<T> dataList, String headerName, String headerValue) throws Exception { if (CollectionUtils.isNotEmpty(dataList)) { T dataInstance = dataList.get(0); List<ExcelExportEntity> entityList = buildExcelExportEntityList(dataInstance, headerName, ""); List<Object> objList = convertDataListToObjList(dataList, headerName,headerValue); downloadExcelEntityDynamic(response, entityList, objList, fileName, title, sheetName); } } public static <T> void exportExcel(HttpServletResponse response, String fileName, String title, String sheetName, List<T> dataList, String headerName, String headerValue, String ignoreCol) throws Exception { if (CollectionUtils.isNotEmpty(dataList)) { T dataInstance = dataList.get(0); List<ExcelExportEntity> entityList = buildExcelExportEntityList(dataInstance, headerName, ignoreCol); List<Object> objList = convertDataListToObjList(dataList, headerName,headerValue); downloadExcelEntityDynamic(response, entityList, objList, fileName, title, sheetName); } } /** * 构建Excel导出实体列表 * * @param t 取数据集第一条数据 做实体列表构建 * @param headerName 动态列标题 * @param <T> 数据类型 * @return Excel导出实体列表 * @throws IllegalAccessException 如果无法访问字段 */ private static <T> List<ExcelExportEntity> buildExcelExportEntityList(T t, String headerName, String ignoreCol) throws IllegalAccessException { List<ExcelExportEntity> entityList = new ArrayList<>(); Field[] fields = t.getClass().getDeclaredFields(); int index = 0; for (Field field : fields) { field.setAccessible(true); Optional<Excel> excelOpt = Optional.ofNullable(field.getAnnotation(Excel.class)); Optional<ExcelCollection> excelCollectionOpt = Optional.ofNullable(field.getAnnotation(ExcelCollection.class)); if (excelOpt.isPresent()) { // 处理固定导出列 if (ignoreCol.contains(field.getName())) { index++; } else { index = handleFixedExportColumn(entityList, field, excelOpt.get(), index); } } else if (excelCollectionOpt.isPresent() && List.class.isAssignableFrom(field.getType())) { // 处理自定义导出列 index = handleCustomExportColumn(t, entityList, field, headerName, index); } } return entityList; } /** * 处理固定导出列 * * @param entityList 实体列表 * @param field 字段 * @param excel Excel注解 * @param index 索引 * @return 更新后的索引 */ private static int handleFixedExportColumn(List<ExcelExportEntity> entityList, Field field, Excel excel, int index) { Object name = AnnotationUtil.getAnnotationValue(field, Excel.class, "name"); ExcelExportEntity entity = createExcelExportEntity(field, name.toString(), field.getName(), index); entityList.add(entity); return index + 1; } /** * 处理自定义导出列 * * @param t 数据对象 * @param entityList 实体列表 * @param field 字段 * @param headerName 动态列标题 * @param index 索引 * @param <T> 数据类型 * @return 更新后的索引 * @throws IllegalAccessException 如果无法访问字段 */ private static <T> int handleCustomExportColumn(T t, List<ExcelExportEntity> entityList, Field field, String headerName, int index) throws IllegalAccessException { List<?> dynamicColl = (List<?>) field.get(t); for (Object arr : dynamicColl) { Field[] typeFields = arr.getClass().getDeclaredFields(); for (Field typeField : typeFields) { typeField.setAccessible(true); Excel excelItem = typeField.getAnnotation(Excel.class); if (excelItem != null && headerName.equals(typeField.getName())) { Object value = typeField.get(arr); ExcelExportEntity entity = createExcelExportEntity(typeField, value.toString(), value.toString(), index); entityList.add(entity); index++; } } } return index; } /** * 将数据对象列表转换为对象列表,通过异步处理每个项。 * * @param dataList 需要处理的数据对象列表。 * @param headerName 用于从对象中提取特定值的标题名称。 * @param headerValue 用于从对象中提取特定值的标题值。 * @param <T> 数据对象列表中的对象类型。 * @return 表示处理过的数据对象的映射列表。 */ public static <T> List<Object> convertDataListToObjList(List<T> dataList, String headerName, String headerValue) { // 创建一个固定大小的线程池 =处理器数量 ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); long start = System.currentTimeMillis(); List<CompletableFuture<Object>> futures = new ArrayList<>(); // 提交每个数据对象进行异步处理 for (T data : dataList) { futures.add(CompletableFuture.supplyAsync(() -> processData(data, headerName, headerValue), executorService)); } // 收集处理结果 List<Object> objList = futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList()); // 关闭线程池 executorService.shutdown(); try { if (!executorService.awaitTermination(2, TimeUnit.MINUTES)) { executorService.shutdownNow(); } } catch (InterruptedException e) { executorService.shutdownNow(); Thread.currentThread().interrupt(); } log.info("数据处理时间:" + (System.currentTimeMillis() - start) + "ms"); return objList; } /** * 处理单个数据对象以提取相关字段及其值。 * * @param data 要处理的数据对象。 * @param headerName 用于从对象中提取特定值的标题名称。 * @param headerValue 用于从对象中提取特定值的标题值。 * @param <T> 数据对象的类型。 * @return 表示数据对象的映射。 */ private static <T> Object processData(T data, String headerName, String headerValue) { Map<String, Object> dataMap = new HashMap<>(); Field[] fields = ReflectUtil.getFields(data.getClass()); for (Field field : fields) { field.setAccessible(true); try { // 将字段名和值放入dataMap中 dataMap.put(field.getName(), field.get(data)); ExcelCollection excelCollection = field.getAnnotation(ExcelCollection.class); // 如果字段是ExcelCollection并且是List类型,进一步处理 if (excelCollection != null && field.getType().getName().equals(List.class.getName())) { List<?> dynamicColl = (List<?>) field.get(data); for (Object arr : dynamicColl) { String key = null; String val = null; Field[] typeFields = arr.getClass().getDeclaredFields(); for (Field typeField : typeFields) { typeField.setAccessible(true); Excel excelItem = typeField.getAnnotation(Excel.class); // 根据注解提取key和value if (excelItem != null) { if (headerName.equals(typeField.getName())) { key = String.valueOf(typeField.get(arr)); } else if (headerValue.equals(typeField.getName())) { val = String.valueOf(typeField.get(arr)); } } } dataMap.put(key, val); } } } catch (IllegalAccessException e) { log.error("无法访问字段值:", e.getMessage()); return null; } } return dataMap; } /** * 动态生成并下载Excel文件。 * * @param response HttpServletResponse对象,用于发送响应。 * @param entityList Excel导出实体列表。 * @param list 数据列表。 * @param fileName 文件名。 * @param title 标题。 * @param sheetName 工作表名称。 * @throws Exception 可能抛出的异常。 */ public static void downloadExcelEntityDynamic(HttpServletResponse response, List<ExcelExportEntity> entityList, List<Object> list, String fileName, String title, String sheetName) throws Exception { setResponseHeadersForDownload1(response, fileName); ExportParams exportParams = StringUtils.hasText(title) ? new ExportParams(title, sheetName) : new ExportParams(); if (!StringUtils.hasText(title)) { exportParams.setSheetName(sheetName); } int pageSize = 12000; int totalPages = (list.size() + pageSize - 1) / pageSize; Workbook workbook = ExcelExportUtil.exportBigExcel(exportParams, entityList, (obj, page) -> { if (((int) obj) < page) { return null; } log.info("当前查询第{}页数据", page); int fromIndex = (page - 1) * pageSize; int toIndex = Math.min(page * pageSize, list.size()); return list.subList(fromIndex, toIndex); }, totalPages); try (ServletOutputStream output = response.getOutputStream(); BufferedOutputStream bufferedOutPut = new BufferedOutputStream(output)) { workbook.write(bufferedOutPut); bufferedOutPut.flush(); } } private static void setResponseHeadersForDownload1(HttpServletResponse response, String fileName) throws UnsupportedEncodingException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls"); } public static void setResponseHeadersForDownload(HttpServletResponse response, String fileName) throws UnsupportedEncodingException { response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "utf-8")); response.setContentType("application/octet-stream;charset=utf-8"); } /** * 将@Excel或者@ExcelCollection修饰的字段转为ExcelExportEntity */ private static ExcelExportEntity createExcelExportEntity(Field typeField, String name, String key, int index) { Map<String, Object> annotationValueMap = AnnotationUtil.getAnnotationValueMap(typeField, Excel.class); ExcelExportEntity entity = JSONObject.parseObject(JSONObject.toJSONBytes(annotationValueMap), ExcelExportEntity.class); // 字段名和@Excel的name一致,视为动态表头列 entity.setName(name); entity.setKey(key); entity.setOrderNum(index); return entity; } private static ExcelExportEntity createExcelExportEntity1(Field typeField, String name, String key, int index) { ExcelExportEntity entity = new ExcelExportEntity(); // 设置基本信息 entity.setName(name); entity.setKey(key); entity.setOrderNum(index); // 设置注解中的属性 Excel excel = typeField.getAnnotation(Excel.class); if (excel != null) { try { BeanUtils.copyProperties(entity, excel); // 复制注解中的属性到ExcelExportEntity对象 } catch (Exception e) { log.error(e.getMessage()); throw new RuntimeException("无法从Excel注解复制属性:", e); } } return entity; } } ruoyi-system/src/main/java/com/ruoyi/system/vo/system/LocationTypeListByProjectVO.java
@@ -1,5 +1,6 @@ package com.ruoyi.system.vo.system; import cn.afterturn.easypoi.excel.annotation.Excel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,8 +12,10 @@ public class LocationTypeListByProjectVO { @ApiModelProperty("类型名称") @Excel(name = "locationTypeName", width = 20) private String locationTypeName; @ApiModelProperty("数量") @Excel(name = "locationNum", width = 20) private Integer locationNum; @ApiModelProperty("类型id") private String id; ruoyi-system/src/main/java/com/ruoyi/system/vo/system/ProjectDeptDetailsChildVO.java
@@ -1,5 +1,7 @@ package com.ruoyi.system.vo.system; import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelCollection; import com.ruoyi.system.model.TProjectDept; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -12,14 +14,20 @@ @ApiModel(value = "片区VO") public class ProjectDeptDetailsChildVO { @ApiModelProperty("作业类型分类") private List<LocationTypeListByProjectVO> locationTypeList; @ApiModelProperty("片区名称") @Excel(name = "片区名称", width = 20) private String projectChildName; @ApiModelProperty("保洁员数量") @Excel(name = "巡检保洁员数", width = 20) private Integer cleanerCount; @ApiModelProperty("作业类型分类") @ExcelCollection(name = "作业类型分类") private List<LocationTypeListByProjectVO> locationTypeList; @ApiModelProperty("任务情况汇总") @ExcelCollection(name = "任务情况汇总") private List<TaskSummaryVO> taskSummaryVOS; @ApiModelProperty("片区id") private String projectId; @ApiModelProperty("保洁员数量") private Integer cleanerCount; @ApiModelProperty("总数") private Integer total; @ApiModelProperty("清洁合格") ruoyi-system/src/main/java/com/ruoyi/system/vo/system/ProjectDeptDetailsVO.java
@@ -1,5 +1,7 @@ package com.ruoyi.system.vo.system; import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.annotation.ExcelCollection; import com.ruoyi.system.model.TProjectDept; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -11,9 +13,11 @@ @ApiModel(value = "任务报表VO") public class ProjectDeptDetailsVO { @ApiModelProperty("片区") private List<ProjectDeptDetailsChildVO> projectChild; @ApiModelProperty("项目名称") @ApiModelProperty("项目") @Excel(name = "项目", width = 20,needMerge = true) private String projectName; @ApiModelProperty("片区") @ExcelCollection(name = "片区") private List<ProjectDeptDetailsChildVO> projectChild; } ruoyi-system/src/main/java/com/ruoyi/system/vo/system/TaskSummaryVO.java
New file @@ -0,0 +1,39 @@ package com.ruoyi.system.vo.system; import cn.afterturn.easypoi.excel.annotation.Excel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @Data @ApiModel(value = "任务情况汇总VO") public class TaskSummaryVO implements Serializable { @ApiModelProperty("总数") @Excel(name = "总数") private Integer total; @ApiModelProperty("清洁合格") @Excel(name = "清洁合格") private Integer num1; @ApiModelProperty("清洁不合格") @Excel(name = "清洁不合格") private Integer num2; @ApiModelProperty("未执行任务") @Excel(name = "未执行任务") private Integer num3; @ApiModelProperty("待整改任务") @Excel(name = "待整改任务") private Integer num4; @ApiModelProperty("审核通过任务") @Excel(name = "审核通过任务") private Integer num5; @ApiModelProperty("超时未执行任务") @Excel(name = "超时未执行任务") private Integer num6; @ApiModelProperty("整改完成任务") @Excel(name = "整改完成任务") private Integer num7; }