From c761a94c4362c00211ae2b2168fa1b8b03773463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=93=B2=E8=B4=A4?= <1037512352@qq.com> Date: Tue, 16 Apr 2024 22:41:51 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ooxml-schemas=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=EF=BC=8C=E5=AE=9E=E7=8E=B0=E5=AF=BC=E5=87=BA=E5=B8=A6?= =?UTF-8?q?=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- smart-admin-api/pom.xml | 7 +++++++ smart-admin-api/sa-base/pom.xml | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/smart-admin-api/pom.xml b/smart-admin-api/pom.xml index e77cdd42..df769e82 100644 --- a/smart-admin-api/pom.xml +++ b/smart-admin-api/pom.xml @@ -282,6 +282,13 @@ ${poi.version} + + + org.apache.poi + ooxml-schemas + 1.4 + + org.apache.poi poi-scratchpad diff --git a/smart-admin-api/sa-base/pom.xml b/smart-admin-api/sa-base/pom.xml index a2fd27f7..0b3cc4d1 100644 --- a/smart-admin-api/sa-base/pom.xml +++ b/smart-admin-api/sa-base/pom.xml @@ -243,6 +243,11 @@ poi-ooxml + + org.apache.poi + ooxml-schemas + + org.apache.poi poi-scratchpad From 44938b34a555b6402233484b223b7b5c239a1aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=93=B2=E8=B4=A4?= <1037512352@qq.com> Date: Tue, 16 Apr 2024 22:42:20 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=B8=A6=E6=B0=B4=E5=8D=B0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E9=BB=98=E8=AE=A4=E4=B8=BA=E5=B8=A6=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sa-base/src/main/resources/dev/sa-base.yaml | 7 +++++-- .../sa-base/src/main/resources/pre/sa-base.yaml | 5 ++++- .../sa-base/src/main/resources/prod/sa-base.yaml | 5 ++++- .../sa-base/src/main/resources/test/sa-base.yaml | 5 ++++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/smart-admin-api/sa-base/src/main/resources/dev/sa-base.yaml b/smart-admin-api/sa-base/src/main/resources/dev/sa-base.yaml index b563a4d1..088769c5 100644 --- a/smart-admin-api/sa-base/src/main/resources/dev/sa-base.yaml +++ b/smart-admin-api/sa-base/src/main/resources/dev/sa-base.yaml @@ -3,7 +3,7 @@ spring: datasource: url: jdbc:p6spy:mysql://127.0.0.1:3306/smart_admin_v3?autoReconnect=true&useServerPreparedStmts=false&rewriteBatchedStatements=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai username: root - password: Zhuoda.123 + password: 123456 initial-size: 2 min-idle: 2 max-active: 10 @@ -141,4 +141,7 @@ sa-token: # 启动时的字符画打印 is-print: false # 是否从cookie读取token - is-read-cookie: false \ No newline at end of file + is-read-cookie: false + +export: + show-watermark: true \ No newline at end of file diff --git a/smart-admin-api/sa-base/src/main/resources/pre/sa-base.yaml b/smart-admin-api/sa-base/src/main/resources/pre/sa-base.yaml index ee6cb459..259ad438 100644 --- a/smart-admin-api/sa-base/src/main/resources/pre/sa-base.yaml +++ b/smart-admin-api/sa-base/src/main/resources/pre/sa-base.yaml @@ -143,4 +143,7 @@ sa-token: # 启动时的字符画打印 is-print: false # 是否从cookie读取token - is-read-cookie: false \ No newline at end of file + is-read-cookie: false + +export: + show-watermark: true \ No newline at end of file diff --git a/smart-admin-api/sa-base/src/main/resources/prod/sa-base.yaml b/smart-admin-api/sa-base/src/main/resources/prod/sa-base.yaml index 3307563c..9e24374c 100644 --- a/smart-admin-api/sa-base/src/main/resources/prod/sa-base.yaml +++ b/smart-admin-api/sa-base/src/main/resources/prod/sa-base.yaml @@ -143,4 +143,7 @@ sa-token: # 启动时的字符画打印 is-print: false # 是否从cookie读取token - is-read-cookie: false \ No newline at end of file + is-read-cookie: false + +export: + show-watermark: true \ No newline at end of file diff --git a/smart-admin-api/sa-base/src/main/resources/test/sa-base.yaml b/smart-admin-api/sa-base/src/main/resources/test/sa-base.yaml index 9021ea9b..47995b34 100644 --- a/smart-admin-api/sa-base/src/main/resources/test/sa-base.yaml +++ b/smart-admin-api/sa-base/src/main/resources/test/sa-base.yaml @@ -143,4 +143,7 @@ sa-token: # 启动时的字符画打印 is-print: false # 是否从cookie读取token - is-read-cookie: false \ No newline at end of file + is-read-cookie: false + +export: + show-watermark: true \ No newline at end of file From ce8db0389eaaac78d35456644185fdadd428db00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=93=B2=E8=B4=A4?= <1037512352@qq.com> Date: Tue, 16 Apr 2024 22:42:57 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=B0=B4=E5=8D=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sa/admin/util/excel/Watermark.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/Watermark.java diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/Watermark.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/Watermark.java new file mode 100644 index 00000000..8e80dd23 --- /dev/null +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/Watermark.java @@ -0,0 +1,95 @@ +package net.lab1024.sa.admin.util.excel; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.date.DateUtil; +import lombok.Data; + +import javax.swing.*; +import java.awt.*; +import java.util.Date; + + +/** + * @author liuzhexian + * @since 2024-04-16 + * @email 1037512352@qq.com + */ +@Data +public class Watermark { + + public Watermark(String content) { + this.content = content; + init(); + } + + public Watermark(String content, Color color, Font font, double angle) { + this.content = content; + this.color = color; + this.font = font; + this.angle = angle; + init(); + } + + /** + * 根据水印内容长度自适应水印图片大小,简单的三角函数 + */ + private void init() { + FontMetrics fontMetrics = new JLabel().getFontMetrics(this.font); + int stringWidth = fontMetrics.stringWidth(this.content); + int charWidth = fontMetrics.charWidth('A'); + this.width = (int) Math.abs(stringWidth * Math.cos(Math.toRadians(this.angle))) + 2 * charWidth; + this.height = (int) Math.abs(stringWidth * Math.sin(Math.toRadians(this.angle))) + 2 * charWidth; + this.yAxis = this.height; + this.xAxis = charWidth; + } + + /** + * 水印内容 + */ + private String content; + + /** + * 画笔颜色 + */ + private Color color = new Color(239,239,239); + + /** + * 字体样式 + */ + private Font font = new Font("Microsoft YaHei", Font.BOLD, 15); + + /** + * 水印宽度 + */ + private int width; + + /** + * 水印高度 + */ + private int height; + + /** + * 倾斜角度,非弧度制 + */ + private double angle = 25; + + /** + * 字体的y轴位置 + */ + private int yAxis = 50; + + /** + * 字体的X轴位置 + */ + private int xAxis; + + /** + * 水平倾斜度 + */ + private double shearX = 0.1; + + /** + * 垂直倾斜度 + */ + private double shearY = -0.26; +} From 48d108d4e6992a2ff63e3d305f99f4d740a31bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=93=B2=E8=B4=A4?= <1037512352@qq.com> Date: Tue, 16 Apr 2024 22:43:43 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=AE=9E=E7=8E=B0easyexcel=E4=B8=AD?= =?UTF-8?q?=E7=9A=84SheetWriteHandler=EF=BC=8C=E5=9C=A8afterSheetCreate?= =?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/excel/CustomWaterMarkHandler.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/CustomWaterMarkHandler.java diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/CustomWaterMarkHandler.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/CustomWaterMarkHandler.java new file mode 100644 index 00000000..11b6fda9 --- /dev/null +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/CustomWaterMarkHandler.java @@ -0,0 +1,105 @@ +package net.lab1024.sa.admin.util.excel; + + +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.xssf.usermodel.XSSFPictureData; +import org.apache.poi.xssf.usermodel.XSSFRelation; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; + +/** + * + * @author liuzhexian + * @since 2024-04-16 + * @email 1037512352@qq.com + */ +@Slf4j +public class CustomWaterMarkHandler implements SheetWriteHandler { + + private final Watermark watermark; + + public CustomWaterMarkHandler(Watermark watermark) { + this.watermark = watermark; + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + BufferedImage bufferedImage = createWatermarkImage(); + XSSFWorkbook workbook = (XSSFWorkbook) writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook(); + try { + // 添加水印的具体操作 + addWatermarkToSheet(workbook, bufferedImage); + } catch (Exception e) { + log.error("添加水印出错:", e); + } + + } + + /** + * 创建水印图片 + * + * @return + */ + private BufferedImage createWatermarkImage() { + // 获取水印相关参数 + Font font = watermark.getFont(); + int width = watermark.getWidth(); + int height = watermark.getHeight(); + Color color = watermark.getColor(); + String text = watermark.getContent(); + + // 创建带有透明背景的 BufferedImage + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + + // 设置画笔字体、平滑、颜色 + g.setFont(font); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(color); + + // 计算水印位置和角度 + int y = watermark.getYAxis(); + int x = watermark.getXAxis(); + AffineTransform transform = AffineTransform.getRotateInstance(Math.toRadians(-watermark.getAngle()), 0, y); + g.setTransform(transform); + // 绘制水印文字 + g.drawString(text, x, y); + + // 释放资源 + g.dispose(); + + return image; + } + + private void addWatermarkToSheet(XSSFWorkbook workbook, BufferedImage watermarkImage) { + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + ImageIO.write(watermarkImage, "png", os); + int pictureIdx = workbook.addPicture(os.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG); + XSSFPictureData pictureData = workbook.getAllPictures().get(pictureIdx); + for (int i = 0; i < workbook.getNumberOfSheets(); i++) { + // 获取每个Sheet表 + XSSFSheet sheet = workbook.getSheetAt(i); + PackagePartName ppn = pictureData.getPackagePart().getPartName(); + String relType = XSSFRelation.IMAGES.getRelation(); + PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null); + sheet.getCTWorksheet().addNewPicture().setId(pr.getId()); + } + } catch (Exception e) { + // 处理ImageIO.write可能抛出的异常 + log.error("添加水印图片时发生错误", e); + } + } +} + From 18cd04c33a0fc188197ac757cac4db628ca4a4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=93=B2=E8=B4=A4?= <1037512352@qq.com> Date: Tue, 16 Apr 2024 22:46:13 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E5=B0=81=E8=A3=85excel=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E7=B1=BB=EF=BC=8C=E7=AE=80=E5=8C=96Controller=E4=B8=AD?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../goods/controller/GoodsController.java | 18 +--- .../oa/enterprise/EnterpriseController.java | 16 +--- .../sa/admin/util/excel/ExcelUtils.java | 96 +++++++++++++++++++ 3 files changed, 104 insertions(+), 26 deletions(-) create mode 100644 smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/ExcelUtils.java diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java index e9b938a4..d3b36a33 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java @@ -1,7 +1,6 @@ package net.lab1024.sa.admin.module.business.goods.controller; import cn.dev33.satoken.annotation.SaCheckPermission; -import com.alibaba.excel.EasyExcel; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; @@ -11,17 +10,16 @@ import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm; import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO; import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO; import net.lab1024.sa.admin.module.business.goods.service.GoodsService; +import net.lab1024.sa.admin.util.excel.ExcelUtils; import net.lab1024.sa.base.common.domain.PageResult; import net.lab1024.sa.base.common.domain.ResponseDTO; import net.lab1024.sa.base.common.domain.ValidateList; -import net.lab1024.sa.base.common.util.SmartResponseUtil; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.io.IOException; import java.util.List; /** @@ -87,18 +85,10 @@ public class GoodsController { @Operation(summary = "导出 @author 卓大") @GetMapping("/goods/exportGoods") @SaCheckPermission("goods:exportGoods") - public void exportGoods(HttpServletResponse response) throws IOException { - + public void exportGoods(HttpServletResponse response) { List goodsList = goodsService.getAllGoods(); - - // 设置下载消息头 - SmartResponseUtil.setDownloadFileHeader(response, "商品列表.xls", null); - - // 下载 - EasyExcel.write(response.getOutputStream(), GoodsExcelVO.class) - .autoCloseStream(Boolean.FALSE) - .sheet("商品") - .doWrite(goodsList); + ExcelUtils utils = new ExcelUtils<>(GoodsExcelVO.class); + utils.exportData(response,goodsList,"商品列表"); } } diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java index 7b3d3f4a..6055eddf 100644 --- a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java @@ -1,7 +1,6 @@ package net.lab1024.sa.admin.module.business.oa.enterprise; import cn.dev33.satoken.annotation.SaCheckPermission; -import com.alibaba.excel.EasyExcel; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -11,6 +10,7 @@ import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEm import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO; import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO; import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO; +import net.lab1024.sa.admin.util.excel.ExcelUtils; import net.lab1024.sa.base.common.domain.PageResult; import net.lab1024.sa.base.common.domain.RequestUser; import net.lab1024.sa.base.common.domain.ResponseDTO; @@ -23,7 +23,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.io.IOException; import java.util.List; /** @@ -53,21 +52,14 @@ public class EnterpriseController { @Operation(summary = "导出企业信息 @author 卓大") @PostMapping("/oa/enterprise/exportExcel") - public void exportExcel(@RequestBody @Valid EnterpriseQueryForm queryForm, HttpServletResponse response) throws IOException { + public void exportExcel(@RequestBody @Valid EnterpriseQueryForm queryForm, HttpServletResponse response) { List data = enterpriseService.getExcelExportData(queryForm); if (CollectionUtils.isEmpty(data)) { SmartResponseUtil.write(response, ResponseDTO.userErrorParam("暂无数据")); return; } - - // 设置下载消息头 - SmartResponseUtil.setDownloadFileHeader(response, "企业基本信息.xls", null); - - // 下载 - EasyExcel.write(response.getOutputStream(), EnterpriseExcelVO.class) - .autoCloseStream(Boolean.FALSE) - .sheet("企业信息") - .doWrite(data); + ExcelUtils utils = new ExcelUtils<>(EnterpriseExcelVO.class); + utils.exportData(response,data,"企业基本信息"); } @Operation(summary = "查询企业详情 @author 开云") diff --git a/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/ExcelUtils.java b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/ExcelUtils.java new file mode 100644 index 00000000..faab0509 --- /dev/null +++ b/smart-admin-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/excel/ExcelUtils.java @@ -0,0 +1,96 @@ +package net.lab1024.sa.admin.util.excel; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.extra.spring.SpringUtil; +import com.alibaba.excel.EasyExcel; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.system.login.domain.LoginResultVO; +import net.lab1024.sa.admin.module.system.login.service.LoginService; +import net.lab1024.sa.admin.util.AdminRequestUtil; +import net.lab1024.sa.base.common.util.SmartResponseUtil; +import org.springframework.core.env.Environment; + +import javax.servlet.http.HttpServletResponse; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @author liuzhexian + * @since 2024-04-16 + * @email 1037512352@qq.com + */ +@Slf4j +public class ExcelUtils implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** + * 导出文件后缀 + */ + public static final String XLSX = ".xlsx"; + + /** + * 实体对象 + */ + public Class clazz; + + public ExcelUtils(Class clazz) { + this.clazz = clazz; + } + + /** + * 通用导出方法 + * + * @param response response + * @param list 导出的列表 + * @param title 导出的名称 + */ + public void exportData(HttpServletResponse response, List list, String title) { + // 设置下载消息头 + SmartResponseUtil.setDownloadFileHeader(response, title + XLSX, null); + // 根据配置文件中的参数判断导出是否带水印 + String show = SpringUtil.getBean(Environment.class).getProperty("export.show-watermark"); + if(Boolean.parseBoolean(show)) { + exportSheetWithWatermark(response, list, title); + } else { + exportSheet(response, list, title); + } + } + + /** + * 通用导出方法(不带水印) + * + * @param response response + * @param list 导出的列表 + * @param title 导出的名称 + */ + public void exportSheet(HttpServletResponse response, List list, String title) { + try { + EasyExcel.write(response.getOutputStream(), this.clazz).sheet(title).doWrite(list); + } catch (Exception e) { + log.error("{}导出异常", title, e); + } + } + + /** + * 通用导出方法(带水印) + * + * @param response response + * @param exportList 导出的列表 + * @param title 导出的名称 + */ + public void exportSheetWithWatermark(HttpServletResponse response, List exportList, String title) { + try { + LoginResultVO loginResult = SpringUtil.getBean(LoginService.class).getLoginResult(AdminRequestUtil.getRequestUser()); + // 注册水印处理器 水印 员工昵称 + 日期 + Watermark watermark = new Watermark(String.format("%s %s",loginResult.getActualName(), DateUtil.formatDate(new Date()))); + // 一定要inMemory + EasyExcel.write(response.getOutputStream(), this.clazz) + .inMemory(true).sheet(title).registerWriteHandler(new CustomWaterMarkHandler(watermark)).doWrite(exportList); + } catch (Exception e) { + log.error("{}导出异常", title, e); + } + } +}