From b7437f04131290f2bb5ac0186362302a727ded12 Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Sun, 10 Apr 2022 16:48:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=86=E5=9B=BE=E6=98=8E=E7=BB=86?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E6=94=AF=E6=8C=81=E9=99=84=E5=B8=A6=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E6=88=AA=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../panel/PanelGroupController.java | 11 ++ .../panel/PanelViewDetailsRequest.java | 28 +++++ .../service/panel/PanelGroupService.java | 108 +++++++++++++++--- frontend/src/api/panel/panel.js | 10 ++ .../custom-component/UserViewDialog.vue | 67 ++++++++--- 5 files changed, 194 insertions(+), 30 deletions(-) create mode 100644 backend/src/main/java/io/dataease/controller/request/panel/PanelViewDetailsRequest.java diff --git a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java index 39360d17aa..b71adceb39 100644 --- a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java +++ b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java @@ -10,6 +10,7 @@ import io.dataease.commons.constants.DePermissionType; import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.controller.handler.annotation.I18n; import io.dataease.controller.request.panel.PanelGroupRequest; +import io.dataease.controller.request.panel.PanelViewDetailsRequest; import io.dataease.dto.PermissionProxy; import io.dataease.dto.authModel.VAuthModelDTO; import io.dataease.dto.panel.PanelGroupDTO; @@ -22,6 +23,8 @@ import org.apache.shiro.authz.annotation.Logical; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -100,4 +103,12 @@ public class PanelGroupController { return panelGroupService.queryPanelComponents(id); } + @ApiOperation("导出仪表板视图明细") + @PostMapping("/exportDetails") + @I18n + public void exportDetails(@RequestBody PanelViewDetailsRequest request, HttpServletResponse response) throws IOException { + panelGroupService.exportPanelViewDetails(request,response); + } + + } diff --git a/backend/src/main/java/io/dataease/controller/request/panel/PanelViewDetailsRequest.java b/backend/src/main/java/io/dataease/controller/request/panel/PanelViewDetailsRequest.java new file mode 100644 index 0000000000..44fba1de45 --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/request/panel/PanelViewDetailsRequest.java @@ -0,0 +1,28 @@ +package io.dataease.controller.request.panel; + +import lombok.Data; + +import java.util.List; + +/** + * Author: wangjiahao + * Date: 2022/4/8 + * Description: + */ +@Data +public class PanelViewDetailsRequest { + + private String viewName; + + private String[] header; + + private List details; + + private String snapshot; + + private int snapshotWidth; + + private int snapshotHeight; + + +} diff --git a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java index f9f869f5fa..a72e2ef3c4 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java @@ -13,6 +13,7 @@ import io.dataease.commons.utils.TreeUtils; import io.dataease.controller.request.authModel.VAuthModelRequest; import io.dataease.controller.request.dataset.DataSetTableRequest; import io.dataease.controller.request.panel.PanelGroupRequest; +import io.dataease.controller.request.panel.PanelViewDetailsRequest; import io.dataease.dto.PanelGroupExtendDataDTO; import io.dataease.dto.authModel.VAuthModelDTO; import io.dataease.dto.chart.ChartViewDTO; @@ -20,6 +21,7 @@ import io.dataease.dto.dataset.DataSetTableDTO; import io.dataease.dto.panel.PanelGroupDTO; import io.dataease.dto.panel.linkJump.PanelLinkJumpBaseRequest; import io.dataease.dto.panel.po.PanelViewInsertDTO; +import io.dataease.excel.utils.EasyExcelExporter; import io.dataease.exception.DataEaseException; import io.dataease.i18n.Translator; import io.dataease.listener.util.CacheUtils; @@ -30,14 +32,24 @@ import io.swagger.annotations.ApiModelProperty; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.ss.usermodel.*; import org.pentaho.di.core.util.UUIDUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; import java.util.*; import java.util.stream.Collectors; @@ -51,6 +63,7 @@ public class PanelGroupService { private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + private final static String DATA_URL_TITLE = "data:image/jpeg;base64,"; @Resource private PanelGroupMapper panelGroupMapper; @Resource @@ -110,7 +123,7 @@ public class PanelGroupService { public PanelGroup saveOrUpdate(PanelGroupRequest request) { String userName = AuthUtils.getUser().getUsername(); String panelId = request.getId(); - if(StringUtils.isNotEmpty(panelId)){ + if (StringUtils.isNotEmpty(panelId)) { panelViewService.syncPanelViews(request); } if (StringUtils.isEmpty(panelId)) { // 新建 @@ -310,46 +323,46 @@ public class PanelGroupService { return newPanelId; } - public String newPanel(PanelGroupRequest request){ + public String newPanel(PanelGroupRequest request) { String newPanelId = UUIDUtil.getUUIDAsString(); String newFrom = request.getNewFrom(); String templateStyle = null; String templateData = null; String dynamicData = null; - if(PanelConstants.NEW_PANEL_FROM.NEW.equals(newFrom)){ + if (PanelConstants.NEW_PANEL_FROM.NEW.equals(newFrom)) { - }else{ + } else { //内部模板新建 - if(PanelConstants.NEW_PANEL_FROM.NEW_INNER_TEMPLATE.equals(newFrom)){ + if (PanelConstants.NEW_PANEL_FROM.NEW_INNER_TEMPLATE.equals(newFrom)) { PanelTemplateWithBLOBs panelTemplate = templateMapper.selectByPrimaryKey(request.getTemplateId()); templateStyle = panelTemplate.getTemplateStyle(); templateData = panelTemplate.getTemplateData(); dynamicData = panelTemplate.getDynamicData(); - }else if(PanelConstants.NEW_PANEL_FROM.NEW_OUTER_TEMPLATE.equals(newFrom)){ + } else if (PanelConstants.NEW_PANEL_FROM.NEW_OUTER_TEMPLATE.equals(newFrom)) { templateStyle = request.getPanelStyle(); templateData = request.getPanelData(); dynamicData = request.getDynamicData(); } - Map dynamicDataMap = JSON.parseObject(dynamicData,Map.class); + Map dynamicDataMap = JSON.parseObject(dynamicData, Map.class); List panelViews = new ArrayList<>(); List viewsData = new ArrayList<>(); - for(Map.Entry entry : dynamicDataMap.entrySet()){ + for (Map.Entry entry : dynamicDataMap.entrySet()) { String originViewId = entry.getKey(); String originViewData = entry.getValue(); - ChartViewDTO chartView = JSON.parseObject(originViewData,ChartViewDTO.class); + ChartViewDTO chartView = JSON.parseObject(originViewData, ChartViewDTO.class); String position = chartView.getPosition(); String newViewId = UUIDUtil.getUUIDAsString(); chartView.setId(newViewId); chartView.setSceneId(newPanelId); chartView.setDataFrom(CommonConstants.VIEW_DATA_FROM.TEMPLATE); //TODO 数据处理 1.替换viewId 2.加入panelView 数据(数据来源为template) 3.加入模板view data数据 - templateData = templateData.replaceAll(originViewId,newViewId); - panelViews.add(new PanelViewInsertDTO(newViewId,newPanelId,position)); - viewsData.add(new PanelGroupExtendDataDTO(newPanelId,newViewId,originViewData)); + templateData = templateData.replaceAll(originViewId, newViewId); + panelViews.add(new PanelViewInsertDTO(newViewId, newPanelId, position)); + viewsData.add(new PanelGroupExtendDataDTO(newPanelId, newViewId, originViewData)); chartViewMapper.insertSelective(chartView); extChartViewMapper.copyToCache(newViewId); } - if(CollectionUtils.isNotEmpty(panelViews)){ + if (CollectionUtils.isNotEmpty(panelViews)) { extPanelViewMapper.savePanelView(panelViews); extPanelGroupExtendDataMapper.savePanelExtendData(viewsData); } @@ -439,10 +452,77 @@ public class PanelGroupService { } return null; } - private void clearPermissionCache(){ + + private void clearPermissionCache() { CacheUtils.removeAll(AuthConstants.USER_PANEL_NAME); CacheUtils.removeAll(AuthConstants.ROLE_PANEL_NAME); CacheUtils.removeAll(AuthConstants.DEPT_PANEL_NAME); } + + public void exportPanelViewDetails(PanelViewDetailsRequest request, HttpServletResponse response) throws IOException { + OutputStream outputStream = response.getOutputStream(); + try { + String snapshot = request.getSnapshot(); + List details = request.getDetails(); + details.add(0,request.getHeader()); + HSSFWorkbook wb = new HSSFWorkbook(); + //明细sheet + HSSFSheet detailsSheet = wb.createSheet("视图明细"); + + //给单元格设置样式 + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + //设置字体大小 + font.setFontHeightInPoints((short) 12); + //设置字体加粗 + font.setBold(true); + //给字体设置样式 + cellStyle.setFont(font); + //设置单元格背景颜色 + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + //设置单元格填充样式(使用纯色背景颜色填充) + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + if (CollectionUtils.isNotEmpty(details)) { + for (int i = 0; i < details.size(); i++) { + HSSFRow row = detailsSheet.createRow(i); + String[] rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.length; j++) { + HSSFCell cell = row.createCell(j); + cell.setCellValue(rowData[j]); + if(i==0){// 头部 + cell.setCellStyle(cellStyle); + //设置列的宽度 + detailsSheet.setColumnWidth(j, 255*20); + } + } + } + } + } + if(StringUtils.isNotEmpty(snapshot)){ + //截图sheet 1px ≈ 2.33dx ≈ 0.48 dy 8*24 个单元格 + HSSFSheet snapshotSheet = wb.createSheet("截图"); + short reDefaultRowHeight = (short)Math.round(request.getSnapshotHeight()*3.5/8); + int reDefaultColumnWidth = (int)Math.round(request.getSnapshotWidth()*0.25/24); + snapshotSheet.setDefaultColumnWidth(reDefaultColumnWidth); + snapshotSheet.setDefaultRowHeight(reDefaultRowHeight); + + //画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)i + HSSFPatriarch patriarch = snapshotSheet.createDrawingPatriarch(); + HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, reDefaultColumnWidth, reDefaultColumnWidth,(short) 0, 0, (short)8, 24); + anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_DO_RESIZE); + patriarch.createPicture(anchor, wb.addPicture(Base64Utils.decodeFromString(snapshot.replace(DATA_URL_TITLE,"")), HSSFWorkbook.PICTURE_TYPE_JPEG)); + } + response.setContentType("application/vnd.ms-excel"); + //文件名称 + response.setHeader("Content-disposition", "attachment;filename=" + request.getViewName() + ".xlsx"); + wb.write(outputStream); + outputStream.flush(); + outputStream.close(); + } catch (Exception e) { + DataEaseException.throwException(e); + } + } } diff --git a/frontend/src/api/panel/panel.js b/frontend/src/api/panel/panel.js index 17f555d3c5..ef34e7fc64 100644 --- a/frontend/src/api/panel/panel.js +++ b/frontend/src/api/panel/panel.js @@ -188,4 +188,14 @@ export function initViewCache(panelId) { loading: false }) } +export function exportDetails(data) { + // 初始化仪表板视图缓存 + return request({ + url: 'panel/group/exportDetails', + method: 'post', + data: data, + loading: true, + responseType: 'blob' + }) +} diff --git a/frontend/src/components/canvas/custom-component/UserViewDialog.vue b/frontend/src/components/canvas/custom-component/UserViewDialog.vue index 92f602d5ce..5e7e7719b0 100644 --- a/frontend/src/components/canvas/custom-component/UserViewDialog.vue +++ b/frontend/src/components/canvas/custom-component/UserViewDialog.vue @@ -1,18 +1,19 @@