huliguo
3 天以前 b21549bfd07dd43525d453d9a0282e25260c092c
导出增加筛选条件
导出根据任务名称分sheet
添加索引
5个文件已修改
1个文件已添加
266 ■■■■■ 已修改文件
guns-admin/src/main/java/com/stylefeng/guns/modular/api/PatrolTaskController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailServiceImpl.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
增加索引.sql 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
guns-admin/src/main/java/com/stylefeng/guns/modular/api/PatrolTaskController.java
@@ -221,9 +221,11 @@
            @ApiImplicitParam(value = "列表数据id,多个逗号分隔", name = "ids", dataType = "String"),
            @ApiImplicitParam(value = "状态(1=待执行,2=进行中,3=成功,4=失败)", name = "status", dataType = "String"),
            @ApiImplicitParam(value = "规则编号", name = "code", dataType = "String"),
            @ApiImplicitParam(value = "任务类型", name = "type", dataType = "int"),
            @ApiImplicitParam(value = "任务名称", name = "name", dataType = "String"),
            @ApiImplicitParam(value = "系统审核状态(1=未执行,2=正常,3=异常)", name = "sysStatus", dataType = "int"),
    })
    public void downloadTaskRecord(String ids, String code, String status,Integer sysStatus, HttpServletResponse response){
    public void downloadTaskRecord(String ids, String code, String status,Integer type, String name, Integer sysStatus,HttpServletResponse response){
        List<String> id = null;
        if(ToolUtil.isNotEmpty(ids)){
            String[] split = ids.split(",");
@@ -237,7 +239,7 @@
                    .collect(Collectors.toList());
        }
        taskDetailService.downloadTaskRecord(id, code, statusList,sysStatus, response);
        taskDetailService.downloadTaskRecord(id, code, statusList,sysStatus,type,name, response);
    }
    
    
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/TaskDetailMapper.java
@@ -42,5 +42,5 @@
     * @param status
     * @return
     */
    List<Map<String, Object>> getDownloadTaskRecord(@Param("ids") List<String> ids, @Param("code") String code, @Param("status") List<Integer> status,@Param("sysStatus") Integer sysStatus);
    List<Map<String, Object>> getDownloadTaskRecord(@Param("ids") List<String> ids, @Param("code") String code, @Param("status") List<Integer> status,@Param("sysStatus") Integer sysStatus,@Param("type") Integer type,@Param("typeName") String typeName);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/dao/mapping/TaskDetailMapper.xml
@@ -90,6 +90,7 @@
    
    <select id="getDownloadTaskRecord" resultType="map">
        select
        c.id,
        c.`name`,
        if(c.type = 1, '定时任务', '实时任务') as taskType,
        DATE_FORMAT(b.execution_time, '%Y-%m-%d %H:%i:%s') as executionTime,
@@ -128,6 +129,12 @@
        <if test="null != sysStatus">
            and d.sys_status = #{sysStatus}
        </if>
        <if test="null != type">
            and c.type = #{type}
        </if>
        <if test="null != typeName and '' != typeName">
            and c.name like CONCAT('%', #{typeName}, '%')
        </if>
        order by b.execution_time desc
    </select>
</mapper>
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/ITaskDetailService.java
@@ -77,6 +77,6 @@
     * @param status
     * @param response
     */
    void downloadTaskRecord(List<String> ids, String code,List<Integer>   status,Integer sysStatus, HttpServletResponse response);
    void downloadTaskRecord(List<String> ids, String code,List<Integer>   status,Integer sysStatus,Integer type,String typeName, HttpServletResponse response);
}
guns-admin/src/main/java/com/stylefeng/guns/modular/system/service/impl/TaskDetailServiceImpl.java
@@ -28,6 +28,7 @@
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
@@ -300,9 +301,9 @@
     * @param status
     * @param response
     */
    @Override
    public void downloadTaskRecord(List<String> ids, String code, List<Integer> status,Integer sysStatus, HttpServletResponse response) {
        List<Map<String, Object>> mapList = this.baseMapper.getDownloadTaskRecord(ids, code, status,sysStatus);
    /*@Override
    public void downloadTaskRecord(List<String> ids, String code, List<Integer> status,Integer sysStatus, Integer type,String typeName,HttpServletResponse response) {
        List<Map<String, Object>> mapList = this.baseMapper.getDownloadTaskRecord(ids, code, status,sysStatus,type,typeName);
        try {
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
            HSSFSheet hssfSheet = hssfWorkbook.createSheet();
@@ -528,4 +529,236 @@
            e.printStackTrace();
        }
    }
    */
    @Override
    public void downloadTaskRecord(List<String> ids, String code, List<Integer> status,Integer sysStatus, Integer type,String typeName,HttpServletResponse response){
        List<Map<String, Object>> mapList = this.baseMapper.getDownloadTaskRecord(ids, code, status, sysStatus, type, typeName);
        try {
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook();
            // 1. 按 name 分组(先获取所有唯一 name)
            Set<Object> nameSet = new HashSet<>();
            for (Map<String, Object> map : mapList) {
                nameSet.add(map.get("name")); // 收集所有不重复的 name
            }
            // 2. 创建单元格样式(提取为公共方法,避免重复代码)
            HSSFCellStyle titleStyle = createTitleStyle(hssfWorkbook);
            HSSFCellStyle contentStyle = createContentStyle(hssfWorkbook);
            List<Icon> icons = iconService.selectList(null);
            // 3. 为每个 name 创建一个 Sheet
            for (Object name : nameSet) {
                if (name == null) continue; // 跳过 name 为 null 的情况
                // 创建 Sheet(以 name 为 Sheet 名称,可根据需求自定义)
                HSSFSheet sheet = hssfWorkbook.createSheet(name.toString());
                sheet.setDefaultColumnWidth(20);
                sheet.setDefaultRowHeight((short) 800);
                // 设置表头(与原逻辑一致)
                initSheetHeader(sheet, hssfWorkbook, titleStyle);
                // 筛选当前 name 的数据
                List<Map<String, Object>> groupData = mapList.stream()
                        .filter(map -> name.equals(map.get("name")))
                        .collect(Collectors.toList());
                // 填充当前 Sheet 的数据
                fillSheetData(sheet, hssfWorkbook, groupData, contentStyle, icons);
            }
            // 4. 输出 Excel 到响应
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("任务记录(" + sdf.format(new Date()) + ").xls", "utf-8"));
            response.setContentType("application/vnd.ms-excel");
            ServletOutputStream out = response.getOutputStream();
            hssfWorkbook.write(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // -------------------- 以下是抽取的工具方法 --------------------
    /**
     * 创建标题样式(加粗、居中)
     */
    private HSSFCellStyle createTitleStyle(HSSFWorkbook workbook) {
        HSSFCellStyle style = workbook.createCellStyle();
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setAlignment(HorizontalAlignment.CENTER);
        HSSFFont font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }
    /**
     * 创建内容样式(居中,不加粗)
     */
    private HSSFCellStyle createContentStyle(HSSFWorkbook workbook) {
        HSSFCellStyle style = workbook.createCellStyle();
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setAlignment(HorizontalAlignment.CENTER);
        return style;
    }
    /**
     * 初始化 Sheet 表头(合并单元格 + 标题)
     */
    private void initSheetHeader(HSSFSheet sheet, HSSFWorkbook workbook, HSSFCellStyle titleStyle) {
        // 合并单元格
        for (int i = 0; i < 10; i++) {
            CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 1, i, i);
            sheet.addMergedRegion(cellRangeAddress);
        }
        CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 10, 16);
        sheet.addMergedRegion(cellRangeAddress);
        // 第一行标题
        HSSFRow row0 = sheet.createRow(0);
        List<String> titles0 = Arrays.asList("序号", "任务名称", "任务类型", "执行时间", "执行状态", "车牌号", "运输公司", "年审有效期", "巡检状态", "车辆轨迹图片", "货箱通道");
        for (int i = 0; i < titles0.size(); i++) {
            HSSFCell cell = row0.createCell(i);
            cell.setCellType(CellType.STRING);
            cell.setCellStyle(titleStyle);
            cell.setCellValue(titles0.get(i));
        }
        // 第二行标题
        HSSFRow row1 = sheet.createRow(1);
        List<String> titles1 = Arrays.asList("图片", "系统审核", "系统审核时间", "人工审核", "审核意见", "审核人", "审核时间");
        for (int i = 0; i < titles1.size(); i++) {
            HSSFCell cell = row1.createCell(i + 10);
            cell.setCellType(CellType.STRING);
            cell.setCellStyle(titleStyle);
            cell.setCellValue(titles1.get(i));
        }
    }
    /**
     * 填充 Sheet 数据(根据分组数据填充行)
     */
    private void fillSheetData(HSSFSheet sheet, HSSFWorkbook workbook, List<Map<String, Object>> dataList, HSSFCellStyle contentStyle, List<Icon> icons) {
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); // 用于插入图片
        for (int i = 0; i < dataList.size(); i++) {
            HSSFRow row = sheet.createRow(i + 2); // 从第3行开始(索引2)
            Map<String, Object> map = dataList.get(i);
            // 1. 序号
            setCellValue(row, 0, (i + 1) + "", contentStyle);
            // 2. 任务名称
            setCellValue(row, 1, map.get("name"), contentStyle);
            // 3. 任务类型
            setCellValue(row, 2, map.get("taskType"), contentStyle);
            // 4. 执行时间
            setCellValue(row, 3, map.get("executionTime"), contentStyle);
            // 5. 执行状态(带状态转换逻辑)
            Object statusObj = map.get("status");
            String statusValue = "";
            if (statusObj != null) {
                Integer status = Integer.valueOf(statusObj.toString());
                statusValue = status == 1 ? "待执行" : status == 2 ? "进行中" : status == 3 ? "成功" : "失败";
                // 处理图片逻辑(根据状态设置默认图片)
                if (status == 5) {
                    map.put("imageUrl", icons.stream().filter(s -> s.getType() == 2).findFirst().orElse(null).getUrl());
                } else if (ToolUtil.isEmpty(map.get("imageUrl"))) {
                    map.put("imageUrl", icons.stream().filter(s -> s.getType() == 3).findFirst().orElse(null).getUrl());
                }
                if (status == 4) {
                    map.put("imageUrl", icons.stream().filter(s -> s.getType() == 1).findFirst().orElse(null).getUrl());
                }
            }
            setCellValue(row, 4, statusValue, contentStyle);
            // 6. 车牌号
            setCellValue(row, 5, map.get("vehicleNum"), contentStyle);
            // 7. 运输公司
            setCellValue(row, 6, map.get("companyName"), contentStyle);
            // 8. 年审有效期
            setCellValue(row, 7, map.get("inspectPeriodEnd"), contentStyle);
            // 9. 巡检状态
            Object vehiclesStatusObj = map.get("vehiclesStatus");
            String vehiclesStatusValue = "";
            if (vehiclesStatusObj != null) {
                Integer vehiclesStatus = Integer.valueOf(vehiclesStatusObj.toString());
                vehiclesStatusValue = vehiclesStatus == 1 ? "未执行" : vehiclesStatus == 2 ? "正常" : "异常";
            }
            setCellValue(row, 8, vehiclesStatusValue, contentStyle);
            // 10. 车辆轨迹图片(占位,实际图片在第10列插入)
            setCellValue(row, 9, "", contentStyle);
            // 11. 图片(插入图片到第10列)
            Object imageUrlObj = map.get("imageUrl");
            if (imageUrlObj != null) {
                try {
                    URL url = new URL(imageUrlObj.toString());
                    URLConnection conn = url.openConnection();
                    conn.connect();
                    InputStream is = conn.getInputStream();
                    byte[] bytes = IOUtils.toByteArray(is);
                    int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
                    is.close();
                    // 图片位置:第10列(索引10),当前行(i+2)
                    HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) 10, i + 2, (short) 11, i + 3);
                    patriarch.createPicture(anchor, pictureIdx);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 12. 系统审核
            Object sysStatusObj = map.get("sysStatus");
            String sysStatusValue = "";
            if (sysStatusObj != null) {
                Integer sysStatus = Integer.valueOf(sysStatusObj.toString());
                sysStatusValue = sysStatus == 1 ? "未执行" : sysStatus == 2 ? "正常" : "异常";
            }
            setCellValue(row, 11, sysStatusValue, contentStyle);
            // 13. 系统审核时间
            setCellValue(row, 12, map.get("sysCreateTime"), contentStyle);
            // 14. 人工审核
            Object artificialStatusObj = map.get("artificialStatus");
            String artificialStatusValue = "";
            if (artificialStatusObj != null) {
                Integer artificialStatus = Integer.valueOf(artificialStatusObj.toString());
                artificialStatusValue = artificialStatus == 1 ? "未执行" : artificialStatus == 2 ? "正常" : "异常";
            }
            setCellValue(row, 13, artificialStatusValue, contentStyle);
            // 15. 审核意见
            setCellValue(row, 14, map.get("remark"), contentStyle);
            // 16. 审核人
            setCellValue(row, 15, map.get("artificialUser"), contentStyle);
            // 17. 审核时间
            setCellValue(row, 16, map.get("artificialCreateTime"), contentStyle);
        }
    }
    /**
     * 通用单元格赋值方法(处理 null 情况)
     */
    private void setCellValue(HSSFRow row, int cellIndex, Object value, HSSFCellStyle style) {
        HSSFCell cell = row.createCell(cellIndex);
        cell.setCellType(CellType.STRING);
        cell.setCellStyle(style);
        cell.setCellValue(value != null ? value.toString() : "");
    }
}
增加索引.sql
New file
@@ -0,0 +1,10 @@
CREATE INDEX idx_b_del_flag_id_status_execution_time
ON t_task_detail (del_flag, id, status, execution_time);
CREATE INDEX idx_a_task_detail_id ON t_task_detail_vehicles (task_detail_id);
CREATE INDEX idx_a_patrol_task_id ON t_task_detail_vehicles (patrol_task_id);
CREATE INDEX idx_d_task_detail_vehicles_id ON t_task_detail_vehicles_channel (task_detail_vehicles_id);
CREATE INDEX idx_d_artificial_user_id ON t_task_detail_vehicles_channel (artificial_user_id);