From 894d04609a549b9e3f45596c7bb2673f95ba795b Mon Sep 17 00:00:00 2001 From: tjlygdx Date: Mon, 18 May 2026 15:25:54 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E3=80=90=E5=9B=BE=E8=A1=A8=E3=80=91?= =?UTF-8?q?=E4=B8=8B=E9=92=BB=E5=90=8E=E5=AF=BC=E5=87=BA=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E9=94=99=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chart/server/ChartDataServer.java | 75 ++++++++++++----- .../chart/server/ChartDataServerTest.java | 81 +++++++++++++++++++ 2 files changed, 138 insertions(+), 18 deletions(-) diff --git a/core/core-backend/src/main/java/io/dataease/chart/server/ChartDataServer.java b/core/core-backend/src/main/java/io/dataease/chart/server/ChartDataServer.java index 971bbaab15..6cd202c0f5 100644 --- a/core/core-backend/src/main/java/io/dataease/chart/server/ChartDataServer.java +++ b/core/core-backend/src/main/java/io/dataease/chart/server/ChartDataServer.java @@ -140,6 +140,7 @@ public class ChartDataServer implements ChartDataApi { request.setHeader(dsHeader); request.setExcelTypes(dsTypes); } + viewDTO.setData(chartViewInfo.getData()); request.setDetails(tableRow); request.setData(chartViewInfo.getData()); } catch (Exception e) { @@ -386,19 +387,12 @@ public class ChartDataServer implements ChartDataApi { public static void setExcelData(Sheet detailsSheet, CellStyle cellStyle, Object[] header, List details, ViewDetailField[] detailFields, Integer[] excelTypes, Comment comment, ChartViewDTO viewInfo, Workbook wb) { List styles = new ArrayList<>(); - List xAxis = new ArrayList<>(); - - xAxis.addAll(viewInfo.getXAxis()); - xAxis.addAll(viewInfo.getYAxis()); - xAxis.addAll(viewInfo.getXAxisExt()); - xAxis.addAll(viewInfo.getYAxisExt()); - xAxis.addAll(viewInfo.getExtStack()); - xAxis.addAll(viewInfo.getDrillFields()); + List exportFields = resolveExportFields(viewInfo, header); TableHeader tableHeader = null; Integer totalDepth = 0; List mergeConfig = new ArrayList<>(); if (StringUtils.equalsAnyIgnoreCase(viewInfo.getType(), "table-normal", "table-info")) { - for (ChartViewFieldDTO tmpAxis : xAxis) { + for (ChartViewFieldDTO tmpAxis : exportFields) { if (tmpAxis.isHide()) { continue; } @@ -415,10 +409,7 @@ public class ChartDataServer implements ChartDataApi { if (tableHeaderMap.get("headerGroup") != null && Boolean.parseBoolean(tableHeaderMap.get("headerGroup").toString())) { var tmpHeader = JsonUtil.parseObject((String) JsonUtil.toJSONString(customAttr.get("tableHeader")), TableHeader.class); // 校验字段数量和顺序 - var allAxis = new ArrayList<>(viewInfo.getXAxis().stream().filter(x -> !x.isHide()).toList()); - if (StringUtils.equalsIgnoreCase(viewInfo.getType(), "table-normal")) { - allAxis.addAll(viewInfo.getYAxis().stream().filter(x -> !x.isHide()).toList()); - } + var allAxis = new ArrayList<>(exportFields.stream().filter(x -> !x.isHide()).toList()); if (validateHeaderGroup(tmpHeader, allAxis)) { tableHeader = tmpHeader; for (TableHeader.ColumnInfo column : tableHeader.getHeaderGroupConfig().getColumns()) { @@ -430,7 +421,6 @@ public class ChartDataServer implements ChartDataApi { } } if ("table-info".equalsIgnoreCase(viewInfo.getType()) && !"dataset".equalsIgnoreCase(viewInfo.getDownloadType())) { - xAxis = xAxis.stream().filter(x -> !x.isHide()).toList(); Map tableCell = (Map) viewInfo.getCustomAttr().get("tableCell"); Boolean mergeCells = (Boolean) tableCell.get("mergeCells"); if (mergeCells != null && mergeCells) { @@ -506,7 +496,7 @@ public class ChartDataServer implements ChartDataApi { int width = 0; Integer depth = 0; for (TableHeader.ColumnInfo column : tableHeader.getHeaderGroupConfig().getColumns()) { - createCell(tableHeader, column, width, depth, detailsSheet, cellStyle, totalDepth, rowMap, xAxis); + createCell(tableHeader, column, width, depth, detailsSheet, cellStyle, totalDepth, rowMap, exportFields); width = width + column.getWidth(); } } @@ -556,9 +546,11 @@ public class ChartDataServer implements ChartDataApi { detailsSheet.setColumnWidth(j, 255 * 20); } else if (cellValObj != null) { try { - if (StringUtils.equalsAnyIgnoreCase(viewInfo.getType(), "table-info", "table-normal") && Arrays.asList(DeTypeConstants.DE_INT,DeTypeConstants.DE_FLOAT).contains(xAxis.get(j).getDeType())) { + if (StringUtils.equalsAnyIgnoreCase(viewInfo.getType(), "table-info", "table-normal") + && j < exportFields.size() + && Arrays.asList(DeTypeConstants.DE_INT, DeTypeConstants.DE_FLOAT).contains(exportFields.get(j).getDeType())) { try { - FormatterCfgDTO formatterCfgDTO = xAxis.get(j).getFormatterCfg() == null ? new FormatterCfgDTO().setUnitLanguage(Lang.isChinese() ? "ch" : "en") : xAxis.get(j).getFormatterCfg(); + FormatterCfgDTO formatterCfgDTO = exportFields.get(j).getFormatterCfg() == null ? new FormatterCfgDTO().setUnitLanguage(Lang.isChinese() ? "ch" : "en") : exportFields.get(j).getFormatterCfg(); row.getCell(j).setCellStyle(styles.get(j)); row.getCell(j).setCellValue(Double.valueOf(cellValue(formatterCfgDTO, new BigDecimal(cellValObj.toString())))); } catch (Exception e) { @@ -581,7 +573,7 @@ public class ChartDataServer implements ChartDataApi { ChartSeniorFunctionCfgDTO functionCfgDTO = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("functionCfg")), ChartSeniorFunctionCfgDTO.class); if (functionCfgDTO != null && StringUtils.isNotEmpty(functionCfgDTO.getEmptyDataStrategy()) && functionCfgDTO.getEmptyDataStrategy().equalsIgnoreCase("setZero")) { if ((viewInfo.getType().equalsIgnoreCase("table-normal") || viewInfo.getType().equalsIgnoreCase("table-info"))) { - if (functionCfgDTO.getEmptyDataFieldCtrl().contains(xAxis.get(j).getDataeaseName())) { + if (j < exportFields.size() && functionCfgDTO.getEmptyDataFieldCtrl().contains(exportFields.get(j).getDataeaseName())) { cell.setCellValue(0); } } else { @@ -599,6 +591,53 @@ public class ChartDataServer implements ChartDataApi { } } + static List resolveExportFields(ChartViewDTO viewInfo, Object[] header) { + List fields = new ArrayList<>(); + if (viewInfo != null && viewInfo.getData() != null && viewInfo.getData().get("fields") != null) { + Object fieldsObj = viewInfo.getData().get("fields"); + if (fieldsObj instanceof List fieldList && !fieldList.isEmpty() && fieldList.getFirst() instanceof ChartViewFieldDTO) { + fields.addAll(fieldList.stream().map(ChartViewFieldDTO.class::cast).toList()); + } else { + fields.addAll(JsonUtil.parseList(JsonUtil.toJSONString(fieldsObj).toString(), new TypeReference>() { + })); + } + } + if (CollectionUtils.isEmpty(fields)) { + appendFields(fields, viewInfo == null ? null : viewInfo.getXAxis()); + appendFields(fields, viewInfo == null ? null : viewInfo.getYAxis()); + appendFields(fields, viewInfo == null ? null : viewInfo.getXAxisExt()); + appendFields(fields, viewInfo == null ? null : viewInfo.getYAxisExt()); + appendFields(fields, viewInfo == null ? null : viewInfo.getExtStack()); + appendFields(fields, viewInfo == null ? null : viewInfo.getDrillFields()); + } + if (ArrayUtils.isEmpty(header) || CollectionUtils.isEmpty(fields)) { + return fields; + } + Map> fieldMap = new HashMap<>(); + fields.forEach(field -> fieldMap.computeIfAbsent(getExportFieldName(field), key -> new ArrayDeque<>()).add(field)); + List orderedFields = new ArrayList<>(); + for (Object headerItem : header) { + if (headerItem == null) { + continue; + } + Deque matchedFields = fieldMap.get(headerItem.toString()); + if (matchedFields != null && !matchedFields.isEmpty()) { + orderedFields.add(matchedFields.removeFirst()); + } + } + return CollectionUtils.isNotEmpty(orderedFields) ? orderedFields : fields; + } + + private static void appendFields(List target, List source) { + if (CollectionUtils.isNotEmpty(source)) { + target.addAll(source); + } + } + + private static String getExportFieldName(ChartViewFieldDTO field) { + return StringUtils.isNotBlank(field.getChartShowName()) ? field.getChartShowName() : field.getName(); + } + private static List getMergeConfig(List data, int colIndex, int offsetHeight) { var result = new ArrayList(); var preRange = new ArrayList(); diff --git a/core/core-backend/src/test/java/io/dataease/chart/server/ChartDataServerTest.java b/core/core-backend/src/test/java/io/dataease/chart/server/ChartDataServerTest.java index 522a400e8a..ce1ce24fc4 100644 --- a/core/core-backend/src/test/java/io/dataease/chart/server/ChartDataServerTest.java +++ b/core/core-backend/src/test/java/io/dataease/chart/server/ChartDataServerTest.java @@ -3,17 +3,27 @@ package io.dataease.chart.server; import io.dataease.api.chart.request.ChartExcelRequest; import io.dataease.chart.constant.ChartConstants; import io.dataease.chart.manage.ChartDataManage; +import io.dataease.constant.DeTypeConstants; import io.dataease.exportCenter.manage.ExportCenterLimitManage; import io.dataease.exportCenter.util.ExportCenterUtils; +import io.dataease.extensions.view.dto.ChartViewFieldDTO; import io.dataease.extensions.view.dto.ChartViewDTO; +import io.dataease.extensions.view.dto.FormatterCfgDTO; import org.junit.Test; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.test.util.ReflectionTestUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -63,12 +73,75 @@ public class ChartDataServerTest { assertEquals(100_000, resultCount); } + @Test + public void findExcelDataStoresCalculatedFieldsOnViewInfo() throws Exception { + ChartDataServer chartDataServer = chartDataServerWithExportLimits(1_000_000L, 1_000_000L); + + ChartViewDTO view = new ChartViewDTO(); + view.setResultMode(ChartConstants.VIEW_RESULT_MODE.ALL); + + ChartExcelRequest request = new ChartExcelRequest(); + request.setDownloadType("view"); + request.setViewInfo(view); + + chartDataServer.findExcelData(request); + + assertNotNull(view.getData()); + assertEquals(1, ((List) view.getData().get("fields")).size()); + } + + @Test + public void setExcelDataUsesCurrentDrillFieldOrderForNumericFormats() { + ChartViewFieldDTO province = field("province", "省份", DeTypeConstants.DE_STRING); + ChartViewFieldDTO city = field("city", "城市", DeTypeConstants.DE_STRING); + ChartViewFieldDTO amount = field("amount", "销售额", DeTypeConstants.DE_FLOAT); + amount.setFormatterCfg(new FormatterCfgDTO().setType("value").setDecimalCount(2)); + + ChartViewDTO view = new ChartViewDTO(); + view.setType("table-info"); + view.setXAxis(new ArrayList<>(Arrays.asList(province, amount))); + view.setDrillFields(new ArrayList<>(List.of(city))); + Map customAttr = new HashMap<>(); + customAttr.put("tableHeader", new HashMap()); + customAttr.put("tableCell", new HashMap<>(Map.of("mergeCells", false))); + view.setCustomAttr(customAttr); + Map data = new HashMap<>(); + data.put("fields", new ArrayList<>(Arrays.asList(province, city, amount))); + view.setData(data); + + try (Workbook workbook = new XSSFWorkbook()) { + Sheet sheet = workbook.createSheet("data"); + CellStyle headStyle = workbook.createCellStyle(); + List details = new ArrayList<>(); + details.add(new Object[]{"省份", "城市", "销售额"}); + details.add(new Object[]{"浙江", "杭州", "1234.5"}); + + ChartDataServer.setExcelData( + sheet, + headStyle, + new Object[]{"省份", "城市", "销售额"}, + details, + null, + new Integer[]{DeTypeConstants.DE_STRING, DeTypeConstants.DE_STRING, DeTypeConstants.DE_FLOAT}, + view, + workbook + ); + + assertEquals("General", sheet.getRow(1).getCell(1).getCellStyle().getDataFormatString()); + assertEquals("0.00", sheet.getRow(1).getCell(2).getCellStyle().getDataFormatString()); + assertEquals(1234.5D, sheet.getRow(1).getCell(2).getNumericCellValue(), 0.0001D); + } catch (Exception e) { + throw new AssertionError(e); + } + } + private ChartDataServer chartDataServerWithExportLimits(Long viewLimit, Long datasetLimit) throws Exception { ChartDataManage chartDataManage = mock(ChartDataManage.class); when(chartDataManage.calcData(any(ChartViewDTO.class))).thenAnswer(invocation -> { ChartViewDTO result = new ChartViewDTO(); Map data = new HashMap<>(); data.put("sourceData", new ArrayList()); + data.put("fields", List.of(field("name", "名称", DeTypeConstants.DE_STRING))); result.setData(data); return result; }); @@ -82,4 +155,12 @@ public class ChartDataServerTest { ReflectionTestUtils.setField(chartDataServer, "chartDataManage", chartDataManage); return chartDataServer; } + + private static ChartViewFieldDTO field(String dataeaseName, String name, Integer deType) { + ChartViewFieldDTO field = new ChartViewFieldDTO(); + field.setDataeaseName(dataeaseName); + field.setName(name); + field.setDeType(deType); + return field; + } }