package com.tievd.jyz.service.impl; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ZipUtil; import cn.hutool.http.HttpUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.tievd.cube.commons.easyexcel.EasyExcel; import com.tievd.cube.commons.utils.SystemContextUtil; import com.tievd.cube.commons.utils.web.HttpServletUtil; import com.tievd.jyz.cache.AlgorithmCache; import com.tievd.jyz.constants.SystemConstant; import com.tievd.jyz.entity.OiloutEvent; import com.tievd.jyz.entity.vo.OiloutRecordVo; import com.tievd.jyz.mapper.OiloutEventMapper; import com.tievd.jyz.service.IOiloutEventService; import fr.opensagres.xdocreport.document.IXDocReport; import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; import fr.opensagres.xdocreport.template.IContext; import fr.opensagres.xdocreport.template.TemplateEngineKind; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; import java.beans.PropertyDescriptor; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * OiloutEvent * @author cube * @since 2023-02-27 * @version V2.0.0 */ @Service @Slf4j public class OiloutEventServiceImpl extends ServiceImpl implements IOiloutEventService { @Autowired OiloutEventMapper oiloutEventMapper; @Autowired EasyExcel easyExcel; @Value("${cube.resources.download-path:/app/jyz/download/}") String filePath; @Value("${cube.resources.templete-path:/app/jyz/templete/}") String templetePath; public static ConcurrentHashMap fileMap = new ConcurrentHashMap(); @Override public List oilOutStatis(Map map) { return oiloutEventMapper.oilOutStatis(map); } @Override @SneakyThrows public void exportWord(OiloutRecordVo recordVo, HttpServletResponse response) { //获取卸油流程数据 LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(OiloutEvent::getRecordId, recordVo.getId()); List recordEvents = this.list(wrapper); try { recordEvents.sort(Comparator.comparingInt(o -> AlgorithmCache.algorithmMap().get(o.getAlgorithmCode()).getSort())); } catch (Exception e) { log.error("", e); } HttpServletUtil.addDownloadHeader(response, "卸油记录.docx"); String tempPath = templetePath + "recordTemp" + recordEvents.size() + SystemConstant.WORD_SUFFIX; try(InputStream in = new FileInputStream(new File(tempPath))) { IXDocReport docReport = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker); IContext context = docReport.createContext(); context.put("recordTime", DateUtil.formatDateTime(recordVo.getStartTime())); context.put("spandTime", recordVo.getSpandTime()); context.put("complete", recordVo.getComplete()); //创建字段元数据,需要表格才加下面这两行,否则不用 FieldsMetadata fm = docReport.createFieldsMetadata(); //待删除文件 List fileList = new ArrayList<>(); //填充word数据 for (int i = 0; i < recordEvents.size(); i++) { OiloutEvent event = recordEvents.get(i); int num = i + 1; String fileStr = filePath + event.getId() + SystemConstant.IMG_SUFFIX; fileList.add(fileStr); context.put("algorithmName" + num, event.getAlgorithmName()); context.put("eventTime" + num, DateUtil.formatDateTime(event.getEventTime())); context.put("eventType" + num, event.getEventType() == 1 ? "规范" : "异常"); //增加图片 try { File img = HttpUtil.downloadFileFromUrl(event.getImgPath(), fileStr); context.put("img" + num, new FileInputStream(img)); fm.addFieldAsImage("img" + num); } catch (Exception e) { log.info("导出word图片获取失败--{}", event.getImgPath()); } } //// //Word模板中的表格数据对应的集合类型 // fm.load("event", OiloutEvent.class, true); //处理word文档并输出 docReport.process(context, response.getOutputStream()); } catch (Exception e) { log.error("", e); throw new RuntimeException("导出word失败" + e.getMessage()); } } /** * 鉴于第一种不太灵活,增加第二种导出方法 * 未完待续 */ @SneakyThrows public void exportWord2(OiloutRecordVo recordVo, HttpServletResponse response) { //获取卸油流程数据 LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); wrapper.eq(OiloutEvent::getRecordId, recordVo.getId()); List recordEvents = this.list(wrapper); HttpServletUtil.addDownloadHeader(response, "卸油记录.docx"); try (InputStream in = new FileInputStream(new File("d:/recordTemp.docx"))) { IXDocReport docReport = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker); IContext context = docReport.createContext(); context.put("recordTime", recordVo.getStartTime()); context.put("spandTime", recordVo.getSpandTime()); context.put("complete", recordVo.getComplete()); context.put("event",recordEvents); //创建字段元数据,需要表格才加下面这两行,否则不用 FieldsMetadata fm = docReport.createFieldsMetadata(); //Word模板中的表格数据对应的集合类型 fm.load("event", OiloutEvent.class, true); //处理word文档并输出 docReport.process(context, response.getOutputStream()); } catch (Exception e) { log.error("导出word异常", e); } } /** * * @param dataList 数据 * @param fileName filemap存储的key,用以异步下载 */ @Override @SneakyThrows @Async public void exportZip(List dataList, String fileName) { String dirPath = filePath + fileName + "/"; FileUtil.mkdir(dirPath); String excel = dirPath + fileName + SystemConstant.EXCEL_SUFFIX; String mediaPath = "media/"; FileUtil.mkdir(mediaPath); //获取文件 for (Object o : dataList) { try { Class clazz = o.getClass(); PropertyDescriptor uidField = BeanUtils.getPropertyDescriptor(clazz, "imgUid"); String imgUid = (String) uidField.getReadMethod().invoke(o); PropertyDescriptor imgField = BeanUtils.getPropertyDescriptor(clazz, "imgPath"); String relativePath = mediaPath + imgUid + SystemConstant.IMG_SUFFIX; reSetField(o, imgField, relativePath, dirPath); PropertyDescriptor vdoField = BeanUtils.getPropertyDescriptor(clazz, "videoPath"); relativePath = mediaPath + imgUid + SystemConstant.VIDEO_SUFFIX; reSetField(o, vdoField, relativePath, dirPath); } catch (Exception e) { log.error("文件或图片下载失败", e); } } //excel try(OutputStream out = new FileOutputStream(new File(excel))) { easyExcel.export(dataList, out, SystemContextUtil.dictTranslator()); } catch (IOException e) { log.error("导出失败", e); throw new RuntimeException("excel生成失败" + e.getMessage()); } File zip = ZipUtil.zip(dirPath); fileMap.put(fileName, zip.getAbsolutePath()); FileUtil.del(dirPath); } //重新设置文件字段值 public void reSetField(Object obj, PropertyDescriptor field, String relativePath, String dirPath) throws InvocationTargetException, IllegalAccessException { String url = (String) field.getReadMethod().invoke(obj); if (StringUtils.isBlank(url)) { return; } File file = new File(dirPath + relativePath); HttpUtil.downloadFile(url, file); field.getWriteMethod().invoke(obj, relativePath); } public Map getFileMap() { return fileMap; } }