diff --git a/core/core-backend/src/main/java/io/gisbi/chart/manage/ChartDataManage.java b/core/core-backend/src/main/java/io/gisbi/chart/manage/ChartDataManage.java index c7b53de..17d9a99 100644 --- a/core/core-backend/src/main/java/io/gisbi/chart/manage/ChartDataManage.java +++ b/core/core-backend/src/main/java/io/gisbi/chart/manage/ChartDataManage.java @@ -70,7 +70,13 @@ public class ChartDataManage { public static final String START_END_SEPARATOR = "_START_END_SPLIT"; private static final Logger logger = LoggerFactory.getLogger(ChartDataManage.class); - + /** + * 计算并生成图表数据。 + * + * @param view 图表视图对象,包含图表配置、数据集ID、过滤条件等信息 + * @return 处理后的图表数据对象,包含计算后的数据结果和格式化信息 + * @throws Exception 当数据校验失败或处理异常时抛出 + */ public ChartViewDTO calcData(ChartViewDTO view) throws Exception { ChartExtRequest chartExtRequest = view.getChartExtRequest(); if (chartExtRequest == null) { @@ -557,33 +563,45 @@ public class ChartDataManage { return res; } + /** + * 根据图表视图配置和字段信息获取指定字段的数据列表 + * @param view 图表视图配置对象,包含图表扩展请求及字段信息 + * @param fieldId 需要查询的字段唯一标识 + * @param fieldType 字段类型,可选值包括"xAxis"、"xAxisExt"、"extStack" + * @return 根据字段类型和数据源处理后的字段值列表,去重后返回 + * @throws Exception 数据查询或处理异常 + */ public List getFieldData(ChartViewDTO view, Long fieldId, String fieldType) throws Exception { ChartExtRequest requestList = view.getChartExtRequest(); List sqlData = sqlData(view, requestList, fieldId); List fieldList = new ArrayList<>(); + // 根据字段类型获取对应的字段集合 switch (fieldType) { case "xAxis" -> fieldList = view.getXAxis(); case "xAxisExt" -> fieldList = view.getXAxisExt(); case "extStack" -> fieldList = view.getExtStack(); } + // 通过ID查询字段信息 DatasetTableFieldDTO field = datasetTableFieldManage.selectById(fieldId); List res = new ArrayList<>(); if (ObjectUtils.isNotEmpty(field) && fieldList.size() > 0) { - // 找到对应维度 + // 遍历字段列表确定当前字段及自定义排序字段的位置 ChartViewFieldDTO chartViewFieldDTO = null; int index = 0; int getIndex = 0; for (int i = 0; i < fieldList.size(); i++) { ChartViewFieldDTO item = fieldList.get(i); - if (StringUtils.equalsIgnoreCase(item.getSort(), "custom_sort")) {// 此处与已有的自定义字段对比 + if (StringUtils.equalsIgnoreCase(item.getSort(), "custom_sort")) { chartViewFieldDTO = item; index = i; } - if (Objects.equals(item.getId(), field.getId())) {// 获得当前自定义的字段 + if (Objects.equals(item.getId(), field.getId())) { getIndex = i; } } + + // 根据字段类型调整索引偏移量 if (StringUtils.equalsIgnoreCase(fieldType, "xAxisExt")) { List xAxis = view.getXAxis(); index += xAxis.size(); @@ -596,15 +614,16 @@ public class ChartDataManage { getIndex += xAxisSize + extSize; } + // 执行自定义排序后的数据结果 List sortResult = resultCustomSort(fieldList, sqlData); if (ObjectUtils.isNotEmpty(chartViewFieldDTO) && (getIndex >= index)) { - // 获取自定义值与data对应列的结果 + // 使用自定义排序规则提取对应列数据 List strings = customSort(Optional.ofNullable(chartViewFieldDTO.getCustomSort()).orElse(new ArrayList<>()), sortResult, index); for (int i = 0; i < strings.size(); i++) { res.add(strings.get(i)[getIndex]); } } else { - // 返回请求结果 + // 直接提取原始排序结果中的对应列数据 for (int i = 0; i < sortResult.size(); i++) { res.add(sortResult.get(i)[getIndex]); } @@ -613,22 +632,32 @@ public class ChartDataManage { return res.stream().distinct().collect(Collectors.toList()); } + /** + * 根据图表配置生成并执行SQL查询,返回数据结果集 + * @param view 图表配置对象,包含图表类型、轴配置等信息 + * @param requestList 图表扩展请求参数 + * @param fieldId 字段标识ID + * @return 查询结果数据列表,每个元素代表一行数据 + * @throws Exception 数据处理或权限验证异常 + */ public List sqlData(ChartViewDTO view, ChartExtRequest requestList, Long fieldId) throws Exception { if (ObjectUtils.isEmpty(view)) { DEException.throwException(Translator.get("i18n_chart_delete")); } - // get all fields + // 获取图表所有字段配置 List allFields = getAllChartFields(view); - // 针对分组切换堆叠时会遇到的问题 + // 处理堆叠/分组图表的特殊x轴配置 if (StringUtils.equalsIgnoreCase(view.getType(), "bar-stack") || StringUtils.equalsIgnoreCase(view.getType(), "chart-mix-stack")) { view.setXAxisExt(new ArrayList<>()); } + // 初始化基础轴配置 List xAxisBase = new ArrayList<>(view.getXAxis()); List xAxis = new ArrayList<>(view.getXAxis()); List xAxisExt = new ArrayList<>(view.getXAxisExt()); + // 合并扩展x轴配置(针对特定图表类型) if (StringUtils.equalsIgnoreCase(view.getType(), "table-pivot") || StringUtils.containsIgnoreCase(view.getType(), "group") || ("antv".equalsIgnoreCase(view.getRender()) && "line".equalsIgnoreCase(view.getType())) @@ -639,30 +668,31 @@ public class ChartDataManage { xAxis.addAll(xAxisExt); } List yAxis = new ArrayList<>(view.getYAxis()); + // 合并扩展y轴配置(针对混合图表类型) if (StringUtils.containsIgnoreCase(view.getType(), "chart-mix")) { List yAxisExt = new ArrayList<>(view.getYAxisExt()); yAxis.addAll(yAxisExt); } + // 处理仪表盘类型特殊配置 if (StringUtils.equalsIgnoreCase(view.getRender(), "antv") && StringUtils.equalsAnyIgnoreCase(view.getType(), "gauge", "liquid")) { List sizeField = getSizeField(view); yAxis.addAll(sizeField); } - List extStack = new ArrayList<>(view.getExtStack()); - List extBubble = new ArrayList<>(view.getExtBubble()); - FilterTreeObj fieldCustomFilter = view.getCustomFilter(); - List drill = new ArrayList<>(view.getDrillFields()); - // 获取数据集,需校验权限 + // 获取数据集权限信息 DatasetGroupInfoDTO table = datasetGroupManage.getDatasetGroupInfoDTO(view.getTableId(), null); Map desensitizationList = new HashMap<>(); List rowPermissionsTree = permissionManage.getRowPermissionsTree(table.getId(), view.getChartExtRequest().getUser()); - chartFilterTreeService.searchFieldAndSet(fieldCustomFilter); + // 处理自定义过滤条件 + chartFilterTreeService.searchFieldAndSet(view.getCustomFilter()); + // 空值校验:当x/y轴都为空时直接返回空结果 if (ObjectUtils.isEmpty(xAxis) && ObjectUtils.isEmpty(yAxis)) { return new ArrayList(); } + // 特殊图表类型配置调整 switch (view.getType()) { case "label": yAxis = new ArrayList<>(); @@ -685,7 +715,6 @@ public class ChartDataManage { } break; case "table-normal": - break; case "bar-group": case "bar-group-stack": case "flow-map": @@ -693,7 +722,7 @@ public class ChartDataManage { default: } - // 获取dsMap,union sql + // 生成联合查询SQL并处理数据源信息 Map sqlMap = datasetSQLManage.getUnionSQLForEdit(table, null); String sql = (String) sqlMap.get("sql"); Map dsMap = (Map) sqlMap.get("dsMap"); @@ -707,10 +736,11 @@ public class ChartDataManage { sql = Utils.replaceSchemaAlias(sql, dsMap); } - // 调用数据源的calcite获得data + // 初始化数据源请求对象 DatasourceRequest datasourceRequest = new DatasourceRequest(); datasourceRequest.setDsList(dsMap); + // 根据数据源类型选择查询提供器 Provider provider; if (crossDs) { provider = ProviderFactory.getDefaultProvider(); @@ -718,14 +748,14 @@ public class ChartDataManage { provider = ProviderFactory.getProvider(dsMap.entrySet().iterator().next().getValue().getType()); } + // 执行数据查询 List data = new ArrayList<>(); - String querySql = null; - //如果不是插件图表 走原生逻辑 - if (table.getMode() == 0) {// 直连 + if (table.getMode() == 0) { // 直连模式处理 if (ObjectUtils.isEmpty(dsMap)) { DEException.throwException(Translator.get("i18n_datasource_delete")); } + // 数据源状态校验 for (Map.Entry next : dsMap.entrySet()) { DatasourceSchemaDTO ds = next.getValue(); if (StringUtils.isNotEmpty(ds.getStatus()) && "Error".equalsIgnoreCase(ds.getStatus())) { @@ -733,24 +763,26 @@ public class ChartDataManage { } } + // 构建SQL元数据并生成最终查询语句 SQLMeta sqlMeta = new SQLMeta(); Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); + // 根据图表类型生成不同SQL逻辑 if (StringUtils.equalsAnyIgnoreCase(view.getType(), "indicator", "gauge", "liquid")) { Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view); } else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { List xFields = new ArrayList<>(); xFields.addAll(xAxis); - xFields.addAll(extStack); + xFields.addAll(view.getExtStack()); Dimension2SQLObj.dimension2sqlObj(sqlMeta, xFields, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view); } else if (StringUtils.containsIgnoreCase(view.getType(), "scatter")) { List yFields = new ArrayList<>(); yFields.addAll(yAxis); - yFields.addAll(extBubble); + yFields.addAll(view.getExtBubble()); Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); Quota2SQLObj.quota2sqlObj(sqlMeta, yFields, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view); @@ -772,6 +804,7 @@ public class ChartDataManage { return data; } + private List getAllChartFields(ChartViewDTO view) { // get all fields Map> stringListMap = chartViewManege.listByDQ(view.getTableId(), view.getId(), view); @@ -783,30 +816,52 @@ public class ChartDataManage { return allFields.stream().filter(ele -> ele.getId() != -1L).collect(Collectors.toList()); } + /** + * 根据检查数据保存图表视图并标记废弃的图表视图。 + * + * @param checkData 包含需要保留的图表ID的字符串(通常为逗号分隔格式) + * @param sceneId 图表视图关联的场景ID + * @param chartViewsInfo 包含图表视图信息的映射(键为ID,值为ChartViewDTO对象) + */ public void saveChartViewFromVisualization(String checkData, Long sceneId, Map chartViewsInfo) { if (!MapUtils.isEmpty(chartViewsInfo)) { List disuseChartIdList = new ArrayList<>(); + // 遍历所有图表视图信息,判断是否需要保存或标记为废弃 chartViewsInfo.forEach((key, chartViewDTO) -> { if (checkData.contains(chartViewDTO.getId() + "")) { try { + // 如果当前图表ID存在于检查数据中,则更新场景ID并保存 chartViewDTO.setSceneId(sceneId); chartViewManege.save(chartViewDTO); } catch (Exception e) { DEException.throwException(e); } } else { + // 如果当前图表ID未存在于检查数据中,则记录为废弃ID disuseChartIdList.add(chartViewDTO.getId()); } }); + // 如果存在需要废弃的图表ID列表,则批量标记为废弃 if (CollectionUtils.isNotEmpty(disuseChartIdList)) { chartViewManege.disuse(disuseChartIdList); } } } + + /** + * 根据图表视图和字段ID获取钻取字段的数据列表。 + * + * @param view 图表视图的数据传输对象,包含钻取字段等配置信息 + * @param fieldId 需要查询的字段ID + * @return 匹配字段ID的数据列表,若未找到字段则返回空列表 + * @throws Exception 可能抛出的异常(具体类型需根据实际业务场景确定) + */ public List getDrillFieldData(ChartViewDTO view, Long fieldId) throws Exception { List drillField = view.getDrillFields(); ChartViewFieldDTO targetField = null; + + // 查找匹配的钻取字段 for (int i = 0; i < drillField.size(); i++) { ChartViewFieldDTO tmp = drillField.get(i); if (tmp.getId().equals(fieldId)) { @@ -814,13 +869,29 @@ public class ChartDataManage { break; } } + if (targetField == null) { return Collections.emptyList(); } + + // 设置X轴为当前目标字段 view.setXAxis(Collections.singletonList(targetField)); + // 执行SQL查询获取原始数据 List sqlData = sqlData(view, view.getChartExtRequest(), fieldId); - List result = customSort(Optional.ofNullable(targetField.getCustomSort()).orElse(new ArrayList<>()), sqlData, 0); - return result.stream().map(i -> i[0]).distinct().collect(Collectors.toList()); + + // 根据自定义排序规则对数据进行排序 + List result = customSort( + Optional.ofNullable(targetField.getCustomSort()).orElse(new ArrayList<>()), + sqlData, + 0 + ); + + // 提取第一列数据并去重生成最终结果列表 + return result.stream() + .map(i -> i[0]) + .distinct() + .collect(Collectors.toList()); } + }