From a375c2b35e6221e17c48e859499618f11fbddae3 Mon Sep 17 00:00:00 2001 From: root <13910913995@163.com> Date: Thu, 26 Jun 2025 18:26:54 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E6=A4=8D=E4=BA=86=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=9C=8B=E6=9D=BF=E7=9A=84=E6=9F=A5=E8=AF=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/pom.xml | 11 + .../stdproject/constant/ChartConstants.java | 23 + .../stdproject/constant/DatasetTableType.java | 10 + .../stdproject/constant/ExtFieldConstant.java | 14 + .../stdproject/constant/FunctionConstant.java | 11 + .../controller/ChartDataController.java | 51 + .../DataVisualizationController.java | 60 + .../com/stdproject/entity/CoreChartView.java | 641 ++++++ .../stdproject/entity/CoreDatasetGroup.java | 263 +++ .../stdproject/entity/CoreDatasetTable.java | 151 ++ .../entity/CoreDatasetTableField.java | 375 ++++ .../entity/CoreDatasetTableSqlLog.java | 123 ++ .../SnapshotVisualizationOuterParamsInfo.java | 153 ++ .../entity/VisualizationLinkage.java | 161 ++ .../entity/VisualizationLinkageField.java | 114 ++ .../entity/dto/BaseTreeNodeDTO.java | 28 + .../entity/dto/BusiPerCheckDTO.java | 21 + .../stdproject/entity/dto/DataSetNodeBO.java | 25 + .../dto/DataSetRowPermissionsTreeDTO.java | 71 + .../stdproject/entity/dto/DatasetNodeDTO.java | 98 + .../stdproject/entity/dto/DeSortField.java | 10 + .../stdproject/entity/dto/LinkageInfoDTO.java | 26 + .../stdproject/entity/dto/PreviewSqlDTO.java | 15 + .../entity/dto/ScatterChartDataDTO.java | 17 + .../com/stdproject/entity/dto/Series.java | 19 + .../entity/dto/VisualizationComponentDTO.java | 27 + .../entity/dto/VisualizationLinkJumpDTO.java | 26 + .../dto/VisualizationLinkJumpInfoDTO.java | 31 + .../entity/dto/VisualizationLinkageDTO.java | 44 + .../dto/VisualizationOuterParamsDTO.java | 22 + .../dto/VisualizationOuterParamsInfoDTO.java | 29 + ...alizationOuterParamsTargetViewInfoDTO.java | 9 + .../VisualizationTemplateExtendDataDTO.java | 24 + .../entity/dto/VisualizationViewTableDTO.java | 22 + .../com/stdproject/entity/po/ChartBasePO.java | 53 + .../stdproject/entity/po/DataSetNodePO.java | 22 + .../entity/po/VisualizationResourcePO.java | 40 + .../entity/union/DatasetGroupInfoDTO.java | 36 + .../entity/union/DatasetTableInfoDTO.java | 14 + .../com/stdproject/entity/union/UnionDTO.java | 21 + .../stdproject/entity/union/UnionItemDTO.java | 15 + .../entity/union/UnionParamDTO.java | 21 + .../entity/vo/AppCoreChartViewVO.java | 208 ++ .../entity/vo/AppCoreDatasetGroupVO.java | 92 + .../entity/vo/AppCoreDatasetTableFieldVO.java | 126 ++ .../entity/vo/AppCoreDatasetTableVO.java | 55 + .../entity/vo/AppCoreDatasourceTaskVO.java | 92 + .../entity/vo/AppCoreDatasourceVO.java | 91 + .../com/stdproject/entity/vo/ChartBaseVO.java | 76 + .../entity/vo/CoreDatasetGroupVO.java | 98 + .../entity/vo/CoreDatasetTableFieldVO.java | 132 ++ .../stdproject/entity/vo/DataSetBarVO.java | 39 + .../entity/vo/DataVisualizationBaseVO.java | 51 + .../entity/vo/DataVisualizationVO.java | 211 ++ .../entity/vo/DatasetTreeNodeVO.java | 18 + .../com/stdproject/entity/vo/UserFormVO.java | 49 + .../stdproject/entity/vo/ViewSelectorVO.java | 24 + .../entity/vo/VisualizationBackgroundVO.java | 34 + .../entity/vo/VisualizationBaseInfoVO.java | 48 + .../entity/vo/VisualizationExport2AppVO.java | 74 + .../vo/VisualizationLinkJumpInfoVO.java | 68 + ...VisualizationLinkJumpTargetViewInfoVO.java | 38 + .../entity/vo/VisualizationLinkJumpVO.java | 44 + .../vo/VisualizationLinkageFieldVO.java | 43 + .../entity/vo/VisualizationLinkageVO.java | 53 + .../vo/VisualizationOutParamsJumpVO.java | 15 + .../vo/VisualizationOuterParamsDsInfoVO.java | 19 + .../VisualizationOuterParamsFilterInfoVO.java | 12 + .../vo/VisualizationOuterParamsInfoVO.java | 76 + ...ualizationOuterParamsTargetViewInfoVO.java | 54 + .../entity/vo/VisualizationOuterParamsVO.java | 119 ++ .../vo/VisualizationReportFilterVO.java | 175 ++ .../entity/vo/VisualizationResourceVO.java | 40 + .../entity/vo/VisualizationStoreVO.java | 41 + .../entity/vo/VisualizationSubjectVO.java | 74 + .../vo/VisualizationTemplateExtendDataVO.java | 26 + .../entity/vo/VisualizationTemplateVO.java | 98 + .../entity/vo/VisualizationViewTableVO.java | 48 + .../entity/vo/VisualizationWatermarkVO.java | 80 + .../mapper/CoreDataSetExtMapper.java | 24 + .../mapper/CoreDatasetGroupMapper.java | 19 + .../mapper/CoreDatasetTableFieldMapper.java | 19 + .../mapper/CoreDatasetTableMapper.java | 24 + .../mapper/CoreDatasetTableSqlLogMapper.java | 19 + .../stdproject/mapper/ExtChartViewMapper.java | 39 + .../mapper/ExtDataVisualizationMapper.java | 23 + .../ExtVisualizationLinkJumpMapper.java | 57 + .../mapper/ExtVisualizationLinkageMapper.java | 44 + .../ExtVisualizationOuterParamsMapper.java | 35 + .../request/DataVisualizationBaseRequest.java | 78 + .../request/StaticResourceRequest.java | 12 + .../VisualizationAppExportRequest.java | 19 + .../VisualizationBackgroundRequest.java | 11 + .../VisualizationLinkJumpBaseRequest.java | 42 + .../request/VisualizationLinkageRequest.java | 36 + .../request/VisualizationStoreRequest.java | 20 + .../request/VisualizationSubjectRequest.java | 11 + .../VisualizationWatermarkRequest.java | 11 + .../VisualizationWorkbranchQueryRequest.java | 27 + .../VisualizationLinkJumpBaseResponse.java | 32 + .../VisualizationOuterParamsBaseResponse.java | 29 + .../service/manage/ChartDataBuild.java | 1819 +++++++++++++++++ .../service/manage/ChartDataManage.java | 867 ++++++++ .../manage/ChartFilterTreeService.java | 82 + .../service/manage/ChartHandlerManager.java | 27 + .../service/manage/ChartViewManege.java | 262 +++ .../service/manage/DataSourceManage.java | 115 ++ .../service/manage/DatasetGroupManage.java | 394 ++++ .../service/manage/DatasetSQLManage.java | 525 +++++ .../manage/DatasetTableFieldManage.java | 256 +++ .../service/manage/DatasetTableManage.java | 53 + .../service/manage/DefaultChartHandler.java | 854 ++++++++ .../service/provider/SQLProvider.java | 208 ++ .../service/provider/SqlTemplate.java | 84 + .../utils/DatasetTableTypeConstants.java | 9 + .../com/stdproject/utils/DatasetUtils.java | 148 ++ .../com/stdproject/utils/DatasourceUtils.java | 26 + .../stdproject/utils/DeSqlparserUtils.java | 257 +++ .../java/com/stdproject/utils/SqlUtils.java | 131 ++ .../com/stdproject/utils/SqlparserUtils.java | 779 +++++++ .../java/com/stdproject/utils/TableUtils.java | 62 + .../main/java/com/stdproject/utils/Utils.java | 565 +++++ .../utils/trans/CustomWhere2Str.java | 378 ++++ .../utils/trans/Dimension2SQLObj.java | 167 ++ .../stdproject/utils/trans/ExtWhere2Str.java | 302 +++ .../stdproject/utils/trans/Field2SQLObj.java | 140 ++ .../stdproject/utils/trans/Order2SQLObj.java | 131 ++ .../stdproject/utils/trans/Quota2SQLObj.java | 176 ++ .../stdproject/utils/trans/Table2SQLObj.java | 26 + .../stdproject/utils/trans/WhereTree2Str.java | 279 +++ backend/src/main/resources/application.yml | 4 +- .../resources/mybatis/ExtCoreChartMapper.xml | 53 + .../mybatis/ExtDataVisualizationMapper.xml | 162 ++ 133 files changed, 15558 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/stdproject/constant/ChartConstants.java create mode 100644 backend/src/main/java/com/stdproject/constant/DatasetTableType.java create mode 100644 backend/src/main/java/com/stdproject/constant/ExtFieldConstant.java create mode 100644 backend/src/main/java/com/stdproject/constant/FunctionConstant.java create mode 100644 backend/src/main/java/com/stdproject/controller/ChartDataController.java create mode 100644 backend/src/main/java/com/stdproject/controller/DataVisualizationController.java create mode 100644 backend/src/main/java/com/stdproject/entity/CoreChartView.java create mode 100644 backend/src/main/java/com/stdproject/entity/CoreDatasetGroup.java create mode 100644 backend/src/main/java/com/stdproject/entity/CoreDatasetTable.java create mode 100644 backend/src/main/java/com/stdproject/entity/CoreDatasetTableField.java create mode 100644 backend/src/main/java/com/stdproject/entity/CoreDatasetTableSqlLog.java create mode 100644 backend/src/main/java/com/stdproject/entity/SnapshotVisualizationOuterParamsInfo.java create mode 100644 backend/src/main/java/com/stdproject/entity/VisualizationLinkage.java create mode 100644 backend/src/main/java/com/stdproject/entity/VisualizationLinkageField.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/BaseTreeNodeDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/BusiPerCheckDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/DataSetNodeBO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/DataSetRowPermissionsTreeDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/DatasetNodeDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/DeSortField.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/LinkageInfoDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/PreviewSqlDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/ScatterChartDataDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/Series.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationComponentDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpInfoDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkageDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsInfoDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsTargetViewInfoDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationTemplateExtendDataDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/dto/VisualizationViewTableDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/po/ChartBasePO.java create mode 100644 backend/src/main/java/com/stdproject/entity/po/DataSetNodePO.java create mode 100644 backend/src/main/java/com/stdproject/entity/po/VisualizationResourcePO.java create mode 100644 backend/src/main/java/com/stdproject/entity/union/DatasetGroupInfoDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/union/DatasetTableInfoDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/union/UnionDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/union/UnionItemDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/union/UnionParamDTO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/AppCoreChartViewVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetGroupVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableFieldVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceTaskVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/ChartBaseVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/CoreDatasetGroupVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/CoreDatasetTableFieldVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/DataSetBarVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/DataVisualizationBaseVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/DataVisualizationVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/DatasetTreeNodeVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/UserFormVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/ViewSelectorVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationBackgroundVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationBaseInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationExport2AppVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpTargetViewInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageFieldVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationOutParamsJumpVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsDsInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsFilterInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsTargetViewInfoVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationReportFilterVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationResourceVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationStoreVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationSubjectVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateExtendDataVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationViewTableVO.java create mode 100644 backend/src/main/java/com/stdproject/entity/vo/VisualizationWatermarkVO.java create mode 100644 backend/src/main/java/com/stdproject/mapper/CoreDataSetExtMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/CoreDatasetGroupMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/CoreDatasetTableFieldMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/CoreDatasetTableMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/CoreDatasetTableSqlLogMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/ExtChartViewMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/ExtDataVisualizationMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkJumpMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkageMapper.java create mode 100644 backend/src/main/java/com/stdproject/mapper/ExtVisualizationOuterParamsMapper.java create mode 100644 backend/src/main/java/com/stdproject/request/DataVisualizationBaseRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/StaticResourceRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationAppExportRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationBackgroundRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationLinkJumpBaseRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationLinkageRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationStoreRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationSubjectRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationWatermarkRequest.java create mode 100644 backend/src/main/java/com/stdproject/request/VisualizationWorkbranchQueryRequest.java create mode 100644 backend/src/main/java/com/stdproject/response/VisualizationLinkJumpBaseResponse.java create mode 100644 backend/src/main/java/com/stdproject/response/VisualizationOuterParamsBaseResponse.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/ChartDataBuild.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/ChartDataManage.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/ChartFilterTreeService.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/ChartHandlerManager.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/ChartViewManege.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/DataSourceManage.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/DatasetGroupManage.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/DatasetSQLManage.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/DatasetTableFieldManage.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/DatasetTableManage.java create mode 100644 backend/src/main/java/com/stdproject/service/manage/DefaultChartHandler.java create mode 100644 backend/src/main/java/com/stdproject/service/provider/SQLProvider.java create mode 100644 backend/src/main/java/com/stdproject/service/provider/SqlTemplate.java create mode 100644 backend/src/main/java/com/stdproject/utils/DatasetTableTypeConstants.java create mode 100644 backend/src/main/java/com/stdproject/utils/DatasetUtils.java create mode 100644 backend/src/main/java/com/stdproject/utils/DatasourceUtils.java create mode 100644 backend/src/main/java/com/stdproject/utils/DeSqlparserUtils.java create mode 100644 backend/src/main/java/com/stdproject/utils/SqlUtils.java create mode 100644 backend/src/main/java/com/stdproject/utils/SqlparserUtils.java create mode 100644 backend/src/main/java/com/stdproject/utils/TableUtils.java create mode 100644 backend/src/main/java/com/stdproject/utils/Utils.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/CustomWhere2Str.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/Dimension2SQLObj.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/ExtWhere2Str.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/Field2SQLObj.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/Order2SQLObj.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/Quota2SQLObj.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/Table2SQLObj.java create mode 100644 backend/src/main/java/com/stdproject/utils/trans/WhereTree2Str.java create mode 100644 backend/src/main/resources/mybatis/ExtCoreChartMapper.xml create mode 100644 backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml diff --git a/backend/pom.xml b/backend/pom.xml index db9dfa8..79aeffd 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -149,6 +149,17 @@ fastjson 1.2.83 + + + org.antlr + antlr + 3.5.2 + + + com.beust + jcommander + 1.82 + diff --git a/backend/src/main/java/com/stdproject/constant/ChartConstants.java b/backend/src/main/java/com/stdproject/constant/ChartConstants.java new file mode 100644 index 0000000..7784234 --- /dev/null +++ b/backend/src/main/java/com/stdproject/constant/ChartConstants.java @@ -0,0 +1,23 @@ +package com.stdproject.constant; + +/** + * @Author bi-coder + */ +public class ChartConstants { + public static final String YEAR_MOM = "year_mom"; + public static final String MONTH_MOM = "month_mom"; + public static final String YEAR_YOY = "year_yoy"; + public static final String DAY_MOM = "day_mom"; + public static final String MONTH_YOY = "month_yoy"; + public static final String[] M_Y = {YEAR_MOM, MONTH_MOM, YEAR_YOY, DAY_MOM, MONTH_YOY}; + + //图表数据查询模式 + public static final class VIEW_RESULT_MODE { + + // 所有 + public static final String ALL = "all"; + + // 自定义 + public static final String CUSTOM = "custom"; + } +} diff --git a/backend/src/main/java/com/stdproject/constant/DatasetTableType.java b/backend/src/main/java/com/stdproject/constant/DatasetTableType.java new file mode 100644 index 0000000..d98b647 --- /dev/null +++ b/backend/src/main/java/com/stdproject/constant/DatasetTableType.java @@ -0,0 +1,10 @@ +package com.stdproject.constant; + +/** + * @Author bi-coder + */ +public class DatasetTableType { + public static String DB = "db"; + public static String SQL = "sql"; + public static String Es = "es"; +} diff --git a/backend/src/main/java/com/stdproject/constant/ExtFieldConstant.java b/backend/src/main/java/com/stdproject/constant/ExtFieldConstant.java new file mode 100644 index 0000000..28db8e4 --- /dev/null +++ b/backend/src/main/java/com/stdproject/constant/ExtFieldConstant.java @@ -0,0 +1,14 @@ +package com.stdproject.constant; + +/** + * @Author bi-coder + */ +public class ExtFieldConstant { + public final static Integer EXT_NORMAL = 0; + + public final static Integer EXT_COPY = 1; + + public final static Integer EXT_CALC = 2; + + public final static Integer EXT_GROUP = 3; +} diff --git a/backend/src/main/java/com/stdproject/constant/FunctionConstant.java b/backend/src/main/java/com/stdproject/constant/FunctionConstant.java new file mode 100644 index 0000000..3f23c24 --- /dev/null +++ b/backend/src/main/java/com/stdproject/constant/FunctionConstant.java @@ -0,0 +1,11 @@ +package com.stdproject.constant; + +/** + * @Author bi-coder + */ +public class FunctionConstant { + /** + * 所有聚合函数数组 + */ + public static final String[] AGG_FUNC = {"SUM", "AVG", "MAX", "MIN", "COUNT", "STDDEV", "STDDEV_POP", "STDDEV_SAMP", "VAR_POP", "VAR_SAMP"}; +} diff --git a/backend/src/main/java/com/stdproject/controller/ChartDataController.java b/backend/src/main/java/com/stdproject/controller/ChartDataController.java new file mode 100644 index 0000000..3720c0d --- /dev/null +++ b/backend/src/main/java/com/stdproject/controller/ChartDataController.java @@ -0,0 +1,51 @@ +package com.stdproject.controller; + +import com.stdproject.common.OperationLog; +import com.stdproject.config.ResponseResult; +import com.stdproject.entity.vo.DataVisualizationVO; +import com.stdproject.mapper.ExtDataVisualizationMapper; +import com.stdproject.request.DataVisualizationBaseRequest; +import com.stdproject.service.manage.ChartDataManage; +import com.stdproject.service.manage.ChartViewManege; +import com.stdproject.utils.DatasetUtils; +import io.gisbi.constant.CommonConstants; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import io.gisbi.result.ResultCode; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/chartData") +public class ChartDataController { + + @Resource + private ChartDataManage chartDataManage; + + @Operation(summary = "获取图表数据") + @OperationLog(type = "01", module = "数据可视化", description = "获取图表数据") + @PostMapping("getData") + public ResponseResult getData(ChartViewDTO chartViewDTO) throws Exception { + try { + // 从模板数据获取 + DatasetUtils.viewDecode(chartViewDTO); + ChartViewDTO dto = chartDataManage.calcData(chartViewDTO); + DatasetUtils.viewEncode(dto); + chartDataManage.encodeData(dto); + return ResponseResult.successData(dto); + } catch (Exception e) { + DEException.throwException(ResultCode.DATA_IS_WRONG.code(), e.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(e)); + } + return null; + } + +} \ No newline at end of file diff --git a/backend/src/main/java/com/stdproject/controller/DataVisualizationController.java b/backend/src/main/java/com/stdproject/controller/DataVisualizationController.java new file mode 100644 index 0000000..842a99f --- /dev/null +++ b/backend/src/main/java/com/stdproject/controller/DataVisualizationController.java @@ -0,0 +1,60 @@ +package com.stdproject.controller; + +import com.stdproject.common.OperationLog; +import com.stdproject.config.ResponseResult; +import com.stdproject.entity.vo.DataVisualizationVO; +import com.stdproject.mapper.ExtDataVisualizationMapper; +import com.stdproject.request.DataVisualizationBaseRequest; +import com.stdproject.service.manage.ChartViewManege; +import com.stdproject.utils.DatasetUtils; +import io.gisbi.constant.CommonConstants; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import io.gisbi.result.ResultCode; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/dataVisualization") +public class DataVisualizationController { + + @Resource + private ExtDataVisualizationMapper extDataVisualizationMapper; + @Resource + private ChartViewManege chartViewManege; + @Operation(summary = "根据视图ID查询模块数据") + @OperationLog(type = "01", module = "数据可视化", description = "根据ID查询数据看板") + @PostMapping("findById") + public ResponseResult findById(@RequestBody DataVisualizationBaseRequest request) { + Long dvId = request.getId(); + String busiFlag = request.getBusiFlag(); + String resourceTable = request.getResourceTable(); + DataVisualizationVO result = extDataVisualizationMapper.findDvInfo(dvId, busiFlag, resourceTable); + if (result != null) { + //获取图表信息 + List chartViewDTOS = chartViewManege.listBySceneId(dvId, resourceTable); + if (!CollectionUtils.isEmpty(chartViewDTOS)) { + // 增加过滤当前使用的图表信息 + Map viewInfo = chartViewDTOS.stream().filter(item -> result.getComponentData().indexOf("\"id\":\"" + item.getId()) > 0).collect(Collectors.toMap(ChartViewDTO::getId, chartView -> chartView)); + result.setCanvasViewInfo(viewInfo); + } + result.setWeight(9); + return ResponseResult.successData(result); + } else { + DEException.throwException("资源不存在或已经被删除..."); + } + return null; + } + + +} \ No newline at end of file diff --git a/backend/src/main/java/com/stdproject/entity/CoreChartView.java b/backend/src/main/java/com/stdproject/entity/CoreChartView.java new file mode 100644 index 0000000..d5412df --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/CoreChartView.java @@ -0,0 +1,641 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * 组件图表表 + *

+ * + * @Author bi-coder + * @since 2024-12-12 + */ +@TableName("core_chart_view") +public class CoreChartView implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 场景ID chart_type为private的时候 是仪表板id + */ + private Long sceneId; + + /** + * 数据集表ID + */ + private Long tableId; + + /** + * 图表类型 + */ + private String type; + + /** + * 图表渲染方式 + */ + private String render; + + /** + * 展示结果 + */ + private Integer resultCount; + + /** + * 展示模式 + */ + private String resultMode; + + /** + * 横轴field + */ + private String xAxis; + + /** + * table-row + */ + private String xAxisExt; + + /** + * 纵轴field + */ + private String yAxis; + + /** + * 副轴 + */ + private String yAxisExt; + + /** + * 堆叠项 + */ + private String extStack; + + /** + * 气泡大小 + */ + private String extBubble; + + /** + * 动态标签 + */ + private String extLabel; + + /** + * 动态提示 + */ + private String extTooltip; + + /** + * 图形属性 + */ + private String customAttr; + + /** + * 组件样式 + */ + private String customStyle; + + /** + * 结果过滤 + */ + private String customFilter; + + /** + * 钻取字段 + */ + private String drillFields; + + /** + * 高级 + */ + private String senior; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 缩略图 + */ + private String snapshot; + + /** + * 样式优先级 panel 仪表板 view 图表 + */ + private String stylePriority; + + /** + * 图表类型 public 公共 历史可复用的图表,private 私有 专属某个仪表板 + */ + private String chartType; + + /** + * 是否插件 + */ + private Boolean isPlugin; + + /** + * 数据来源 template 模板数据 dataset 数据集数据 + */ + private String dataFrom; + + /** + * 图表字段集合 + */ + private String viewFields; + + /** + * 是否开启刷新 + */ + private Boolean refreshViewEnable; + + /** + * 刷新时间单位 + */ + private String refreshUnit; + + /** + * 刷新时间 + */ + private Integer refreshTime; + + /** + * 是否开启联动 + */ + private Boolean linkageActive; + + /** + * 是否开启跳转 + */ + private Boolean jumpActive; + + /** + * 复制来源 + */ + private Long copyFrom; + + /** + * 复制ID + */ + private Long copyId; + + /** + * 区间条形图开启时间纬度开启聚合 + */ + private Boolean aggregate; + + /** + * 流向地图起点名称field + */ + private String flowMapStartName; + + /** + * 流向地图终点名称field + */ + private String flowMapEndName; + + /** + * 颜色维度field + */ + private String extColor; + + /** + * 图形属性_移动端 + */ + private String customAttrMobile; + + /** + * 组件样式_移动端 + */ + private String customStyleMobile; + + /** + * 字段排序优先级 + */ + private String sortPriority; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Long getSceneId() { + return sceneId; + } + + public void setSceneId(Long sceneId) { + this.sceneId = sceneId; + } + + public Long getTableId() { + return tableId; + } + + public void setTableId(Long tableId) { + this.tableId = tableId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getRender() { + return render; + } + + public void setRender(String render) { + this.render = render; + } + + public Integer getResultCount() { + return resultCount; + } + + public void setResultCount(Integer resultCount) { + this.resultCount = resultCount; + } + + public String getResultMode() { + return resultMode; + } + + public void setResultMode(String resultMode) { + this.resultMode = resultMode; + } + + public String getxAxis() { + return xAxis; + } + + public void setxAxis(String xAxis) { + this.xAxis = xAxis; + } + + public String getxAxisExt() { + return xAxisExt; + } + + public void setxAxisExt(String xAxisExt) { + this.xAxisExt = xAxisExt; + } + + public String getyAxis() { + return yAxis; + } + + public void setyAxis(String yAxis) { + this.yAxis = yAxis; + } + + public String getyAxisExt() { + return yAxisExt; + } + + public void setyAxisExt(String yAxisExt) { + this.yAxisExt = yAxisExt; + } + + public String getExtStack() { + return extStack; + } + + public void setExtStack(String extStack) { + this.extStack = extStack; + } + + public String getExtBubble() { + return extBubble; + } + + public void setExtBubble(String extBubble) { + this.extBubble = extBubble; + } + + public String getExtLabel() { + return extLabel; + } + + public void setExtLabel(String extLabel) { + this.extLabel = extLabel; + } + + public String getExtTooltip() { + return extTooltip; + } + + public void setExtTooltip(String extTooltip) { + this.extTooltip = extTooltip; + } + + public String getCustomAttr() { + return customAttr; + } + + public void setCustomAttr(String customAttr) { + this.customAttr = customAttr; + } + + public String getCustomStyle() { + return customStyle; + } + + public void setCustomStyle(String customStyle) { + this.customStyle = customStyle; + } + + public String getCustomFilter() { + return customFilter; + } + + public void setCustomFilter(String customFilter) { + this.customFilter = customFilter; + } + + public String getDrillFields() { + return drillFields; + } + + public void setDrillFields(String drillFields) { + this.drillFields = drillFields; + } + + public String getSenior() { + return senior; + } + + public void setSenior(String senior) { + this.senior = senior; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Long updateTime) { + this.updateTime = updateTime; + } + + public String getSnapshot() { + return snapshot; + } + + public void setSnapshot(String snapshot) { + this.snapshot = snapshot; + } + + public String getStylePriority() { + return stylePriority; + } + + public void setStylePriority(String stylePriority) { + this.stylePriority = stylePriority; + } + + public String getChartType() { + return chartType; + } + + public void setChartType(String chartType) { + this.chartType = chartType; + } + + public Boolean getIsPlugin() { + return isPlugin; + } + + public void setIsPlugin(Boolean isPlugin) { + this.isPlugin = isPlugin; + } + + public String getDataFrom() { + return dataFrom; + } + + public void setDataFrom(String dataFrom) { + this.dataFrom = dataFrom; + } + + public String getViewFields() { + return viewFields; + } + + public void setViewFields(String viewFields) { + this.viewFields = viewFields; + } + + public Boolean getRefreshViewEnable() { + return refreshViewEnable; + } + + public void setRefreshViewEnable(Boolean refreshViewEnable) { + this.refreshViewEnable = refreshViewEnable; + } + + public String getRefreshUnit() { + return refreshUnit; + } + + public void setRefreshUnit(String refreshUnit) { + this.refreshUnit = refreshUnit; + } + + public Integer getRefreshTime() { + return refreshTime; + } + + public void setRefreshTime(Integer refreshTime) { + this.refreshTime = refreshTime; + } + + public Boolean getLinkageActive() { + return linkageActive; + } + + public void setLinkageActive(Boolean linkageActive) { + this.linkageActive = linkageActive; + } + + public Boolean getJumpActive() { + return jumpActive; + } + + public void setJumpActive(Boolean jumpActive) { + this.jumpActive = jumpActive; + } + + public Long getCopyFrom() { + return copyFrom; + } + + public void setCopyFrom(Long copyFrom) { + this.copyFrom = copyFrom; + } + + public Long getCopyId() { + return copyId; + } + + public void setCopyId(Long copyId) { + this.copyId = copyId; + } + + public Boolean getAggregate() { + return aggregate; + } + + public void setAggregate(Boolean aggregate) { + this.aggregate = aggregate; + } + + public String getFlowMapStartName() { + return flowMapStartName; + } + + public void setFlowMapStartName(String flowMapStartName) { + this.flowMapStartName = flowMapStartName; + } + + public String getFlowMapEndName() { + return flowMapEndName; + } + + public void setFlowMapEndName(String flowMapEndName) { + this.flowMapEndName = flowMapEndName; + } + + public String getExtColor() { + return extColor; + } + + public void setExtColor(String extColor) { + this.extColor = extColor; + } + + public String getCustomAttrMobile() { + return customAttrMobile; + } + + public void setCustomAttrMobile(String customAttrMobile) { + this.customAttrMobile = customAttrMobile; + } + + public String getCustomStyleMobile() { + return customStyleMobile; + } + + public void setCustomStyleMobile(String customStyleMobile) { + this.customStyleMobile = customStyleMobile; + } + + public String getSortPriority() { + return sortPriority; + } + + public void setSortPriority(String sortPriority) { + this.sortPriority = sortPriority; + } + + @Override + public String toString() { + return "CoreChartView{" + + "id = " + id + + ", title = " + title + + ", sceneId = " + sceneId + + ", tableId = " + tableId + + ", type = " + type + + ", render = " + render + + ", resultCount = " + resultCount + + ", resultMode = " + resultMode + + ", xAxis = " + xAxis + + ", xAxisExt = " + xAxisExt + + ", yAxis = " + yAxis + + ", yAxisExt = " + yAxisExt + + ", extStack = " + extStack + + ", extBubble = " + extBubble + + ", extLabel = " + extLabel + + ", extTooltip = " + extTooltip + + ", customAttr = " + customAttr + + ", customStyle = " + customStyle + + ", customFilter = " + customFilter + + ", drillFields = " + drillFields + + ", senior = " + senior + + ", createBy = " + createBy + + ", createTime = " + createTime + + ", updateTime = " + updateTime + + ", snapshot = " + snapshot + + ", stylePriority = " + stylePriority + + ", chartType = " + chartType + + ", isPlugin = " + isPlugin + + ", dataFrom = " + dataFrom + + ", viewFields = " + viewFields + + ", refreshViewEnable = " + refreshViewEnable + + ", refreshUnit = " + refreshUnit + + ", refreshTime = " + refreshTime + + ", linkageActive = " + linkageActive + + ", jumpActive = " + jumpActive + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + ", aggregate = " + aggregate + + ", flowMapStartName = " + flowMapStartName + + ", flowMapEndName = " + flowMapEndName + + ", extColor = " + extColor + + ", customAttrMobile = " + customAttrMobile + + ", customStyleMobile = " + customStyleMobile + + ", sortPriority = " + sortPriority + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/CoreDatasetGroup.java b/backend/src/main/java/com/stdproject/entity/CoreDatasetGroup.java new file mode 100644 index 0000000..2489680 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/CoreDatasetGroup.java @@ -0,0 +1,263 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * 数据集分组表 + *

+ * + * @Author bi-coder + * @since 2023-08-28 + */ +@TableName("core_dataset_group") +public class CoreDatasetGroup implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 应用ID + */ + private String appId; + + /** + * 父级ID + */ + private Long pid; + + /** + * 当前分组处于第几级 + */ + private Integer level; + + /** + * node类型:folder or dataset + */ + private String nodeType; + + /** + * sql,union + */ + private String type; + + /** + * 连接模式:0-直连,1-同步(包括excel、api等数据存在de中的表) + */ + private Integer mode; + + /** + * 关联关系树 + */ + private String info; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * Quartz 实例 ID + */ + private String qrtzInstance; + + /** + * 同步状态 + */ + private String syncStatus; + + /** + * 更新人ID + */ + private String updateBy; + + /** + * 最后同步时间 + */ + private Long lastUpdateTime; + + /** + * 关联sql + */ + private String unionSql; + + /** + * 是否跨源 + */ + private Boolean isCross; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getPid() { + return pid; + } + + public void setPid(Long pid) { + this.pid = pid; + } + + public Integer getLevel() { + return level; + } + + public void setLevel(Integer level) { + this.level = level; + } + + public String getNodeType() { + return nodeType; + } + + public void setNodeType(String nodeType) { + this.nodeType = nodeType; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Integer getMode() { + return mode; + } + + public void setMode(Integer mode) { + this.mode = mode; + } + + public String getInfo() { + return info; + } + + public void setInfo(String info) { + this.info = info; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public String getQrtzInstance() { + return qrtzInstance; + } + + public void setQrtzInstance(String qrtzInstance) { + this.qrtzInstance = qrtzInstance; + } + + public String getSyncStatus() { + return syncStatus; + } + + public void setSyncStatus(String syncStatus) { + this.syncStatus = syncStatus; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Long getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(Long lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public String getUnionSql() { + return unionSql; + } + + public void setUnionSql(String unionSql) { + this.unionSql = unionSql; + } + + public Boolean getIsCross() { + return isCross; + } + + public void setIsCross(Boolean isCross) { + this.isCross = isCross; + } + + @Override + public String toString() { + return "CoreDatasetGroup{" + + "id = " + id + + ", appId = " + appId + + ", name = " + name + + ", pid = " + pid + + ", level = " + level + + ", nodeType = " + nodeType + + ", type = " + type + + ", mode = " + mode + + ", info = " + info + + ", createBy = " + createBy + + ", createTime = " + createTime + + ", qrtzInstance = " + qrtzInstance + + ", syncStatus = " + syncStatus + + ", updateBy = " + updateBy + + ", lastUpdateTime = " + lastUpdateTime + + ", unionSql = " + unionSql + + ", isCross = " + isCross + + "}"; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/CoreDatasetTable.java b/backend/src/main/java/com/stdproject/entity/CoreDatasetTable.java new file mode 100644 index 0000000..64e4e15 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/CoreDatasetTable.java @@ -0,0 +1,151 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2023-04-14 + */ +@TableName("core_dataset_table") +public class CoreDatasetTable implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 项目ID + */ + private String appId; + + /** + * 物理表名 + */ + private String tableName; + + /** + * 数据源ID + */ + private Long datasourceId; + + /** + * 数据集ID + */ + private Long datasetGroupId; + + /** + * db,sql,union,excel,api + */ + private String type; + + /** + * 表原始信息,表名,sql等 + */ + private String info; + + /** + * SQL参数 + */ + private String sqlVariableDetails; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public Long getDatasourceId() { + return datasourceId; + } + + public void setDatasourceId(Long datasourceId) { + this.datasourceId = datasourceId; + } + + public Long getDatasetGroupId() { + return datasetGroupId; + } + + public void setDatasetGroupId(Long datasetGroupId) { + this.datasetGroupId = datasetGroupId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getInfo() { + return info; + } + + public void setInfo(String info) { + this.info = info; + } + + public String getSqlVariableDetails() { + return sqlVariableDetails; + } + + public void setSqlVariableDetails(String sqlVariableDetails) { + this.sqlVariableDetails = sqlVariableDetails; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + @Override + public String toString() { + return "CoreDatasetTable{" + + "id = " + id + + "appId = " + appId + + ", name = " + name + + ", tableName = " + tableName + + ", datasourceId = " + datasourceId + + ", datasetGroupId = " + datasetGroupId + + ", type = " + type + + ", info = " + info + + ", sqlVariableDetails = " + sqlVariableDetails + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/CoreDatasetTableField.java b/backend/src/main/java/com/stdproject/entity/CoreDatasetTableField.java new file mode 100644 index 0000000..aeda1a1 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/CoreDatasetTableField.java @@ -0,0 +1,375 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * table数据集表字段 + *

+ * + * @Author bi-coder + * @since 2025-02-06 + */ +@TableName("core_dataset_table_field") +public class CoreDatasetTableField implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 数据源ID + */ + private Long datasourceId; + + /** + * 数据表ID + */ + private Long datasetTableId; + + /** + * 数据集ID + */ + private Long datasetGroupId; + + /** + * 视图ID + */ + private Long chartId; + + /** + * 原始字段名 + */ + private String originName; + + /** + * 字段名用于展示 + */ + private String name; + + /** + * 描述 + */ + private String description; + + /** + * 字段名用作唯一标识 + */ + private String gisbiName; + + /** + * de字段别名 + */ + private String fieldShortName; + + /** + * 分组设置 + */ + private String groupList; + + /** + * 未分组的值 + */ + private String otherGroup; + + /** + * 维度/指标标识 d:维度,q:指标 + */ + private String groupType; + + /** + * 原始字段类型 + */ + private String type; + + /** + * 字段长度(允许为空,默认0) + */ + private Integer size; + + /** + * gisbi字段类型:0-文本,1-时间,2-整型数值,3-浮点数值,4-布尔,5-地理位置,6-二进制 + */ + private Integer deType; + + /** + * de记录的原始类型 + */ + private Integer deExtractType; + + /** + * 是否扩展字段 0原始 1复制 2计算字段... + */ + private Integer extField; + + /** + * 是否选中 + */ + private Boolean checked; + + /** + * 列位置 + */ + private Integer columnIndex; + + /** + * 同步时间 + */ + private Long lastSyncTime; + + /** + * 精度 + */ + private Integer accuracy; + + /** + * 时间字段类型 + */ + private String dateFormat; + + /** + * 时间格式类型 + */ + private String dateFormatType; + + /** + * 计算字段参数 + */ + private String params; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getDatasourceId() { + return datasourceId; + } + + public void setDatasourceId(Long datasourceId) { + this.datasourceId = datasourceId; + } + + public Long getDatasetTableId() { + return datasetTableId; + } + + public void setDatasetTableId(Long datasetTableId) { + this.datasetTableId = datasetTableId; + } + + public Long getDatasetGroupId() { + return datasetGroupId; + } + + public void setDatasetGroupId(Long datasetGroupId) { + this.datasetGroupId = datasetGroupId; + } + + public Long getChartId() { + return chartId; + } + + public void setChartId(Long chartId) { + this.chartId = chartId; + } + + public String getOriginName() { + return originName; + } + + public void setOriginName(String originName) { + this.originName = originName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getGisbiName() { + return gisbiName; + } + + public void setGisbiName(String gisbiName) { + this.gisbiName = gisbiName; + } + + public String getFieldShortName() { + return fieldShortName; + } + + public void setFieldShortName(String fieldShortName) { + this.fieldShortName = fieldShortName; + } + + public String getGroupList() { + return groupList; + } + + public void setGroupList(String groupList) { + this.groupList = groupList; + } + + public String getOtherGroup() { + return otherGroup; + } + + public void setOtherGroup(String otherGroup) { + this.otherGroup = otherGroup; + } + + public String getGroupType() { + return groupType; + } + + public void setGroupType(String groupType) { + this.groupType = groupType; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Integer getSize() { + return size; + } + + public void setSize(Integer size) { + this.size = size; + } + + public Integer getDeType() { + return deType; + } + + public void setDeType(Integer deType) { + this.deType = deType; + } + + public Integer getDeExtractType() { + return deExtractType; + } + + public void setDeExtractType(Integer deExtractType) { + this.deExtractType = deExtractType; + } + + public Integer getExtField() { + return extField; + } + + public void setExtField(Integer extField) { + this.extField = extField; + } + + public Boolean getChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + + public Integer getColumnIndex() { + return columnIndex; + } + + public void setColumnIndex(Integer columnIndex) { + this.columnIndex = columnIndex; + } + + public Long getLastSyncTime() { + return lastSyncTime; + } + + public void setLastSyncTime(Long lastSyncTime) { + this.lastSyncTime = lastSyncTime; + } + + public Integer getAccuracy() { + return accuracy; + } + + public void setAccuracy(Integer accuracy) { + this.accuracy = accuracy; + } + + public String getDateFormat() { + return dateFormat; + } + + public void setDateFormat(String dateFormat) { + this.dateFormat = dateFormat; + } + + public String getDateFormatType() { + return dateFormatType; + } + + public void setDateFormatType(String dateFormatType) { + this.dateFormatType = dateFormatType; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + @Override + public String toString() { + return "CoreDatasetTableField{" + + "id = " + id + + ", datasourceId = " + datasourceId + + ", datasetTableId = " + datasetTableId + + ", datasetGroupId = " + datasetGroupId + + ", chartId = " + chartId + + ", originName = " + originName + + ", name = " + name + + ", description = " + description + + ", gisbiName = " + gisbiName + + ", fieldShortName = " + fieldShortName + + ", groupList = " + groupList + + ", otherGroup = " + otherGroup + + ", groupType = " + groupType + + ", type = " + type + + ", size = " + size + + ", deType = " + deType + + ", deExtractType = " + deExtractType + + ", extField = " + extField + + ", checked = " + checked + + ", columnIndex = " + columnIndex + + ", lastSyncTime = " + lastSyncTime + + ", accuracy = " + accuracy + + ", dateFormat = " + dateFormat + + ", dateFormatType = " + dateFormatType + + ", params = " + params + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/CoreDatasetTableSqlLog.java b/backend/src/main/java/com/stdproject/entity/CoreDatasetTableSqlLog.java new file mode 100644 index 0000000..c8a228c --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/CoreDatasetTableSqlLog.java @@ -0,0 +1,123 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2023-08-08 + */ +@TableName("core_dataset_table_sql_log") +public class CoreDatasetTableSqlLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 数据集SQL节点ID + */ + private String tableId; + + /** + * 开始时间 + */ + private Long startTime; + + /** + * 结束时间 + */ + private Long endTime; + + /** + * 耗时(毫秒) + */ + private Long spend; + + /** + * 详细信息 + */ + private String sql; + + /** + * 状态 + */ + private String status; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTableId() { + return tableId; + } + + public void setTableId(String tableId) { + this.tableId = tableId; + } + + public Long getStartTime() { + return startTime; + } + + public void setStartTime(Long startTime) { + this.startTime = startTime; + } + + public Long getEndTime() { + return endTime; + } + + public void setEndTime(Long endTime) { + this.endTime = endTime; + } + + public Long getSpend() { + return spend; + } + + public void setSpend(Long spend) { + this.spend = spend; + } + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + @Override + public String toString() { + return "CoreDatasetTableSqlLog{" + + "id = " + id + + ", tableId = " + tableId + + ", startTime = " + startTime + + ", endTime = " + endTime + + ", spend = " + spend + + ", sql = " + sql + + ", status = " + status + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/SnapshotVisualizationOuterParamsInfo.java b/backend/src/main/java/com/stdproject/entity/SnapshotVisualizationOuterParamsInfo.java new file mode 100644 index 0000000..5c679d2 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/SnapshotVisualizationOuterParamsInfo.java @@ -0,0 +1,153 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * 外部参数配置表 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_visualization_outer_params_info") +public class SnapshotVisualizationOuterParamsInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId("params_info_id") + private String paramsInfoId; + + /** + * visualization_outer_params 表的 ID + */ + private String paramsId; + + /** + * 参数名 + */ + private String paramName; + + /** + * 是否启用 + */ + private Boolean checked; + + /** + * 复制来源 + */ + private String copyFrom; + + /** + * 复制来源ID + */ + private String copyId; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 默认值 JSON格式 + */ + private String defaultValue; + + /** + * 是否启用默认值 + */ + private Boolean enabledDefault; + + public String getParamsInfoId() { + return paramsInfoId; + } + + public void setParamsInfoId(String paramsInfoId) { + this.paramsInfoId = paramsInfoId; + } + + public String getParamsId() { + return paramsId; + } + + public void setParamsId(String paramsId) { + this.paramsId = paramsId; + } + + public String getParamName() { + return paramName; + } + + public void setParamName(String paramName) { + this.paramName = paramName; + } + + public Boolean getChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + + public String getCopyFrom() { + return copyFrom; + } + + public void setCopyFrom(String copyFrom) { + this.copyFrom = copyFrom; + } + + public String getCopyId() { + return copyId; + } + + public void setCopyId(String copyId) { + this.copyId = copyId; + } + + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public Boolean getEnabledDefault() { + return enabledDefault; + } + + public void setEnabledDefault(Boolean enabledDefault) { + this.enabledDefault = enabledDefault; + } + + @Override + public String toString() { + return "SnapshotVisualizationOuterParamsInfo{" + + "paramsInfoId = " + paramsInfoId + + ", paramsId = " + paramsId + + ", paramName = " + paramName + + ", checked = " + checked + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + ", required = " + required + + ", defaultValue = " + defaultValue + + ", enabledDefault = " + enabledDefault + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/VisualizationLinkage.java b/backend/src/main/java/com/stdproject/entity/VisualizationLinkage.java new file mode 100644 index 0000000..7402d5b --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/VisualizationLinkage.java @@ -0,0 +1,161 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2023-09-22 + */ +@TableName("visualization_linkage") +public class VisualizationLinkage implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + private Long dvId; + + /** + * 源图表id + */ + private Long sourceViewId; + + /** + * 联动图表id + */ + private Long targetViewId; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updatePeople; + + /** + * 是否启用关联 + */ + private Boolean linkageActive; + + private String ext1; + + private String ext2; + + private Long copyFrom; + + private Long copyId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getDvId() { + return dvId; + } + + public void setDvId(Long dvId) { + this.dvId = dvId; + } + + public Long getSourceViewId() { + return sourceViewId; + } + + public void setSourceViewId(Long sourceViewId) { + this.sourceViewId = sourceViewId; + } + + public Long getTargetViewId() { + return targetViewId; + } + + public void setTargetViewId(Long targetViewId) { + this.targetViewId = targetViewId; + } + + public Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Long updateTime) { + this.updateTime = updateTime; + } + + public String getUpdatePeople() { + return updatePeople; + } + + public void setUpdatePeople(String updatePeople) { + this.updatePeople = updatePeople; + } + + public Boolean getLinkageActive() { + return linkageActive; + } + + public void setLinkageActive(Boolean linkageActive) { + this.linkageActive = linkageActive; + } + + public String getExt1() { + return ext1; + } + + public void setExt1(String ext1) { + this.ext1 = ext1; + } + + public String getExt2() { + return ext2; + } + + public void setExt2(String ext2) { + this.ext2 = ext2; + } + + public Long getCopyFrom() { + return copyFrom; + } + + public void setCopyFrom(Long copyFrom) { + this.copyFrom = copyFrom; + } + + public Long getCopyId() { + return copyId; + } + + public void setCopyId(Long copyId) { + this.copyId = copyId; + } + + @Override + public String toString() { + return "VisualizationLinkage{" + + "id = " + id + + ", dvId = " + dvId + + ", sourceViewId = " + sourceViewId + + ", targetViewId = " + targetViewId + + ", updateTime = " + updateTime + + ", updatePeople = " + updatePeople + + ", linkageActive = " + linkageActive + + ", ext1 = " + ext1 + + ", ext2 = " + ext2 + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/VisualizationLinkageField.java b/backend/src/main/java/com/stdproject/entity/VisualizationLinkageField.java new file mode 100644 index 0000000..0bdaffa --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/VisualizationLinkageField.java @@ -0,0 +1,114 @@ +package com.stdproject.entity; + +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2023-09-22 + */ +@TableName("visualization_linkage_field") +public class VisualizationLinkageField implements Serializable { + + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 联动ID + */ + private Long linkageId; + + /** + * 源图表字段 + */ + private Long sourceField; + + /** + * 目标图表字段 + */ + private Long targetField; + + /** + * 更新时间 + */ + private Long updateTime; + + private Long copyFrom; + + private Long copyId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getLinkageId() { + return linkageId; + } + + public void setLinkageId(Long linkageId) { + this.linkageId = linkageId; + } + + public Long getSourceField() { + return sourceField; + } + + public void setSourceField(Long sourceField) { + this.sourceField = sourceField; + } + + public Long getTargetField() { + return targetField; + } + + public void setTargetField(Long targetField) { + this.targetField = targetField; + } + + public Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Long updateTime) { + this.updateTime = updateTime; + } + + public Long getCopyFrom() { + return copyFrom; + } + + public void setCopyFrom(Long copyFrom) { + this.copyFrom = copyFrom; + } + + public Long getCopyId() { + return copyId; + } + + public void setCopyId(Long copyId) { + this.copyId = copyId; + } + + @Override + public String toString() { + return "VisualizationLinkageField{" + + "id = " + id + + ", linkageId = " + linkageId + + ", sourceField = " + sourceField + + ", targetField = " + targetField + + ", updateTime = " + updateTime + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/BaseTreeNodeDTO.java b/backend/src/main/java/com/stdproject/entity/dto/BaseTreeNodeDTO.java new file mode 100644 index 0000000..a1ac4ff --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/BaseTreeNodeDTO.java @@ -0,0 +1,28 @@ +package com.stdproject.entity.dto; + + +import lombok.Data; + +import java.util.List; + +@Data +public class BaseTreeNodeDTO { + + private String id; + + private String pid; + + private String text; + + private String nodeType; + + private List children; + + public BaseTreeNodeDTO(String id, String pid, String text, String nodeType) { + this.id = id; + this.pid = pid; + this.text = text; + this.nodeType = nodeType; + } + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/BusiPerCheckDTO.java b/backend/src/main/java/com/stdproject/entity/dto/BusiPerCheckDTO.java new file mode 100644 index 0000000..df7814a --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/BusiPerCheckDTO.java @@ -0,0 +1,21 @@ +package com.stdproject.entity.dto; + +import io.gisbi.constant.AuthEnum; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class BusiPerCheckDTO implements Serializable { + @Serial + private static final long serialVersionUID = -6047004531129863548L; + + private Long id; + + private AuthEnum authEnum; +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/DataSetNodeBO.java b/backend/src/main/java/com/stdproject/entity/dto/DataSetNodeBO.java new file mode 100644 index 0000000..46ffa6f --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/DataSetNodeBO.java @@ -0,0 +1,25 @@ +package com.stdproject.entity.dto; + +import io.gisbi.model.TreeBaseModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DataSetNodeBO implements TreeBaseModel { + + @Serial + private static final long serialVersionUID = 728340676442387790L; + private String appId; + private Long id; + private String name; + private Boolean leaf; + private Integer weight = 3; + private Long pid; + private Integer extraFlag; +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/DataSetRowPermissionsTreeDTO.java b/backend/src/main/java/com/stdproject/entity/dto/DataSetRowPermissionsTreeDTO.java new file mode 100644 index 0000000..732e096 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/DataSetRowPermissionsTreeDTO.java @@ -0,0 +1,71 @@ +package com.stdproject.entity.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.stdproject.entity.vo.UserFormVO; +import io.gisbi.extensions.view.dto.DatasetRowPermissionsTreeObj; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class DataSetRowPermissionsTreeDTO { + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 是否启用 + */ + private Boolean enable; + + /** + * 权限类型:dept/role/user + */ + private String authTargetType; + + /** + * 权限对象ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long authTargetId; + + /** + * 数据集ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetId; + + /** + * 关系表达式 + */ + private String expressionTree; + + /** + * 用户白名单 + */ + private String whiteListUser; + + /** + * 角色白名单 + */ + private String whiteListRole; + + /** + * 组织白名单 + */ + private String whiteListDept; + + private Long updateTime; + private String datasetName; + + private String authTargetName; + + private DatasetRowPermissionsTreeObj tree; + private List whiteListUsers; + private List authTargetIds; + private boolean exportData; + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/DatasetNodeDTO.java b/backend/src/main/java/com/stdproject/entity/dto/DatasetNodeDTO.java new file mode 100644 index 0000000..efac34c --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/DatasetNodeDTO.java @@ -0,0 +1,98 @@ +package com.stdproject.entity.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Schema(description = "数据集结构") +@Data +public class DatasetNodeDTO implements Serializable { + + /** + * ID + */ + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 名称 + */ + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String name; + + /** + * 父级ID + */ + @Schema(description = "父级目录ID", requiredMode = Schema.RequiredMode.REQUIRED) + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 当前分组处于第几级 + */ + @Schema(description = "层级") + private Integer level; + + /** + * node类型:folder or dataset + */ + @Schema(description = "叶子节点类型", requiredMode = Schema.RequiredMode.REQUIRED) + private String nodeType; + + /** + * sql,union + */ + @Schema(description = "数据集类型") + private String type; + + /** + * 连接模式:0-直连,1-同步(包括excel、api等数据存在de中的表) + */ + @Schema(description = "连接模式", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer mode; + + /** + * 关联关系树 + */ + @Schema(description = "关联tree", requiredMode = Schema.RequiredMode.REQUIRED) + private String info; + + /** + * 创建人ID + */ + @Schema(description = "创建人ID") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + private Long createTime; + + private String qrtzInstance; + + /** + * 同步状态 + */ + private String syncStatus; + + /** + * 创建人ID + */ + private String updateBy; + + /** + * 最后同步时间 + */ + private Long lastUpdateTime; + + /** + * 关联sql,由tree + */ + private String unionSql; + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/DeSortField.java b/backend/src/main/java/com/stdproject/entity/dto/DeSortField.java new file mode 100644 index 0000000..30adb3a --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/DeSortField.java @@ -0,0 +1,10 @@ +package com.stdproject.entity.dto; + +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import lombok.Data; + +@Data +public class DeSortField extends DatasetTableFieldDTO { + + private String orderDirection; +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/LinkageInfoDTO.java b/backend/src/main/java/com/stdproject/entity/dto/LinkageInfoDTO.java new file mode 100644 index 0000000..6a1754f --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/LinkageInfoDTO.java @@ -0,0 +1,26 @@ +package com.stdproject.entity.dto; + +import java.util.List; + +public class LinkageInfoDTO { + + private String sourceInfo; + + private List targetInfoList; + + public String getSourceInfo() { + return sourceInfo; + } + + public void setSourceInfo(String sourceInfo) { + this.sourceInfo = sourceInfo; + } + + public List getTargetInfoList() { + return targetInfoList; + } + + public void setTargetInfoList(List targetInfoList) { + this.targetInfoList = targetInfoList; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/PreviewSqlDTO.java b/backend/src/main/java/com/stdproject/entity/dto/PreviewSqlDTO.java new file mode 100644 index 0000000..5f32104 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/PreviewSqlDTO.java @@ -0,0 +1,15 @@ +package com.stdproject.entity.dto; + +import lombok.Data; + +/** + * @Author Junjun + */ +@Data +public class PreviewSqlDTO { + private String tableId; + private String sql; + private Long datasourceId; + private String sqlVariableDetails; + private Boolean isCross; +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/ScatterChartDataDTO.java b/backend/src/main/java/com/stdproject/entity/dto/ScatterChartDataDTO.java new file mode 100644 index 0000000..8245312 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/ScatterChartDataDTO.java @@ -0,0 +1,17 @@ +package com.stdproject.entity.dto; + +import io.gisbi.extensions.view.dto.ChartDimensionDTO; +import io.gisbi.extensions.view.dto.ChartQuotaDTO; +import lombok.Data; + +import java.util.List; + +/** + * @Author gin + */ +@Data +public class ScatterChartDataDTO { + private Object[] value; + private List dimensionList; + private List quotaList; +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/Series.java b/backend/src/main/java/com/stdproject/entity/dto/Series.java new file mode 100644 index 0000000..b6e0e06 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/Series.java @@ -0,0 +1,19 @@ +package com.stdproject.entity.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Set; + +/** + * @Author gin + */ +@Getter +@Setter +public class Series { + private String name; + private String type; + private List data; + private Set categories; +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationComponentDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationComponentDTO.java new file mode 100644 index 0000000..16b51a5 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationComponentDTO.java @@ -0,0 +1,27 @@ +package com.stdproject.entity.dto; + + +import com.stdproject.entity.vo.VisualizationOutParamsJumpVO; +import com.stdproject.entity.vo.VisualizationViewTableVO; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author : WangJiaHao + * @date : 2024/4/18 17:14 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class VisualizationComponentDTO { + + private String bashComponentData; + + List visualizationViewTables; + + List outParamsJumpInfo; + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpDTO.java new file mode 100644 index 0000000..0184a30 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpDTO.java @@ -0,0 +1,26 @@ +package com.stdproject.entity.dto; + + +import com.stdproject.entity.vo.VisualizationLinkJumpVO; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 14:21 + */ +@Data +public class VisualizationLinkJumpDTO extends VisualizationLinkJumpVO { + //仪表板可以跳转图表信息 sourceViewId# + private String sourceInfo; + + private List targetInfoList; + + private List linkJumpInfoArray = new ArrayList<>(); + + private Map mapJumpInfoArray = new HashMap<>(); +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpInfoDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpInfoDTO.java new file mode 100644 index 0000000..e452908 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkJumpInfoDTO.java @@ -0,0 +1,31 @@ +package com.stdproject.entity.dto; + + +import com.stdproject.entity.vo.VisualizationLinkJumpInfoVO; +import com.stdproject.entity.vo.VisualizationLinkJumpTargetViewInfoVO; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 14:20 + */ +@Data +public class VisualizationLinkJumpInfoDTO extends VisualizationLinkJumpInfoVO { + private String sourceFieldName; + + private String sourceJumpInfo; + + private Integer sourceDeType; + + //存在公共链接的目标仪表板 + private String publicJumpId; + + // 目标类型 + private String targetDvType; + + private List targetViewInfoList=new ArrayList<>();// linkType = inner 时使用 + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkageDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkageDTO.java new file mode 100644 index 0000000..359686f --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationLinkageDTO.java @@ -0,0 +1,44 @@ +package com.stdproject.entity.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.stdproject.entity.vo.VisualizationLinkageFieldVO; +import com.stdproject.entity.vo.VisualizationLinkageVO; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author : WangJiaHao + * @date : 2023/7/13 + */ +@Data +public class VisualizationLinkageDTO extends VisualizationLinkageVO { + + /** + * 目标图表名称 + */ + private String targetViewName; + + /** + * 目标图表类型 + */ + private String targetViewType; + /** + * 联动字段 + */ + private List linkageFields = new ArrayList<>(); + + /** + * 目标图表字段 + */ + private List targetViewFields = new ArrayList<>(); + /** + * 表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long tableId; + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsDTO.java new file mode 100644 index 0000000..d980017 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsDTO.java @@ -0,0 +1,22 @@ +package com.stdproject.entity.dto; + + +import com.stdproject.entity.vo.VisualizationOuterParamsVO; +import lombok.Data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@Data +public class VisualizationOuterParamsDTO extends VisualizationOuterParamsVO { + + private List targetInfoList; + + private List outerParamsInfoArray = new ArrayList<>(); + + private Map mapOuterParamsInfoArray = new HashMap<>(); + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsInfoDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsInfoDTO.java new file mode 100644 index 0000000..522c504 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsInfoDTO.java @@ -0,0 +1,29 @@ +package com.stdproject.entity.dto; + +import com.stdproject.entity.vo.VisualizationOuterParamsDsInfoVO; +import com.stdproject.entity.vo.VisualizationOuterParamsFilterInfoVO; +import com.stdproject.entity.vo.VisualizationOuterParamsInfoVO; +import com.stdproject.entity.vo.VisualizationOuterParamsTargetViewInfoVO; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + + +@Data +public class VisualizationOuterParamsInfoDTO extends VisualizationOuterParamsInfoVO { + private String dvId; + + private List targetViewInfoList=new ArrayList<>(); + + //仪表板外部参数信息 dvId#paramName + private String sourceInfo; + + //目标联动参数 targetViewId#targetFieldId + private List targetInfoList; + + private List dsInfoVOList = new ArrayList<>(); + + private List filterInfoVOList = new ArrayList<>(); + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsTargetViewInfoDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsTargetViewInfoDTO.java new file mode 100644 index 0000000..d590270 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationOuterParamsTargetViewInfoDTO.java @@ -0,0 +1,9 @@ +package com.stdproject.entity.dto; + + +import com.stdproject.entity.vo.VisualizationOuterParamsTargetViewInfoVO; + +public class VisualizationOuterParamsTargetViewInfoDTO extends VisualizationOuterParamsTargetViewInfoVO { + + +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationTemplateExtendDataDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationTemplateExtendDataDTO.java new file mode 100644 index 0000000..ce0bd27 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationTemplateExtendDataDTO.java @@ -0,0 +1,24 @@ +package com.stdproject.entity.dto; + +import com.stdproject.entity.vo.VisualizationTemplateExtendDataVO; +import io.gisbi.utils.IDUtils; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author : WangJiaHao + * @date : 2023/11/13 10:25 + */ +@Data +@NoArgsConstructor +public class VisualizationTemplateExtendDataDTO extends VisualizationTemplateExtendDataVO { + + + public VisualizationTemplateExtendDataDTO(Long dvId, Long viewId, String viewDetails) { + super(); + super.setId(IDUtils.snowID()); + super.setDvId(dvId); + super.setViewId(viewId); + super.setViewDetails(viewDetails); + } +} diff --git a/backend/src/main/java/com/stdproject/entity/dto/VisualizationViewTableDTO.java b/backend/src/main/java/com/stdproject/entity/dto/VisualizationViewTableDTO.java new file mode 100644 index 0000000..39f0a46 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/dto/VisualizationViewTableDTO.java @@ -0,0 +1,22 @@ +package com.stdproject.entity.dto; + + +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import lombok.Data; + +import java.util.List; + +/** + * @author : WangJiaHao + * @date : 2024/3/14 12:42 + */ +@Data +public class VisualizationViewTableDTO extends ChartViewDTO { + + private String visualizationId; + + private String baseVisualizationData; + + private List tableFields; +} diff --git a/backend/src/main/java/com/stdproject/entity/po/ChartBasePO.java b/backend/src/main/java/com/stdproject/entity/po/ChartBasePO.java new file mode 100644 index 0000000..dd45646 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/po/ChartBasePO.java @@ -0,0 +1,53 @@ +package com.stdproject.entity.po; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +public class ChartBasePO implements Serializable { + @Serial + private static final long serialVersionUID = 183064537525500481L; + + private Long chartId; + + private String chartType; + + private String chartName; + + private Long resourceId; + + private String resourceType; + + private String resourceName; + + private Long tableId; + + private String xAxis; + + + private String xAxisExt; + + + private String yAxis; + + + private String yAxisExt; + + + private String extStack; + + + private String extBubble; + + private String flowMapStartName; + + private String flowMapEndName; + + private String extColor; + + private String extLabel; + + private String extTooltip; +} diff --git a/backend/src/main/java/com/stdproject/entity/po/DataSetNodePO.java b/backend/src/main/java/com/stdproject/entity/po/DataSetNodePO.java new file mode 100644 index 0000000..c214d8e --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/po/DataSetNodePO.java @@ -0,0 +1,22 @@ +package com.stdproject.entity.po; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DataSetNodePO implements Serializable { + + @Serial + private static final long serialVersionUID = -4457506330575500164L; + private String appId; + private Long id; + private String name; + private String nodeType; + private Long pid; +} diff --git a/backend/src/main/java/com/stdproject/entity/po/VisualizationResourcePO.java b/backend/src/main/java/com/stdproject/entity/po/VisualizationResourcePO.java new file mode 100644 index 0000000..76004f8 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/po/VisualizationResourcePO.java @@ -0,0 +1,40 @@ +package com.stdproject.entity.po; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VisualizationResourcePO implements Serializable { + @Serial + private static final long serialVersionUID = 627770173259978185L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long resourceId; + + private String name; + + private String type; + + private Long creator; + + private Long lastEditor; + + private Long lastEditTime; + + private Boolean favorite; + + private int weight; + + private Integer extFlag; +} diff --git a/backend/src/main/java/com/stdproject/entity/union/DatasetGroupInfoDTO.java b/backend/src/main/java/com/stdproject/entity/union/DatasetGroupInfoDTO.java new file mode 100644 index 0000000..9887447 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/union/DatasetGroupInfoDTO.java @@ -0,0 +1,36 @@ +package com.stdproject.entity.union; + + +import com.stdproject.entity.dto.DatasetNodeDTO; +import com.stdproject.entity.dto.DeSortField; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * @Author Junjun + */ +@Data +public class DatasetGroupInfoDTO extends DatasetNodeDTO { + private List union;// 关联数据集 + + private List sortFields;// 自定义排序(如仪表板查询组件) + + private Map data; + + private List allFields; + + private String sql; + + private String appId; + + private Long total; + + private String creator; + + private String updater; + + private Boolean isCross; +} diff --git a/backend/src/main/java/com/stdproject/entity/union/DatasetTableInfoDTO.java b/backend/src/main/java/com/stdproject/entity/union/DatasetTableInfoDTO.java new file mode 100644 index 0000000..553ca7b --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/union/DatasetTableInfoDTO.java @@ -0,0 +1,14 @@ +package com.stdproject.entity.union; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author gin + */ +@Data +public class DatasetTableInfoDTO implements Serializable { + private String table; + private String sql; +} diff --git a/backend/src/main/java/com/stdproject/entity/union/UnionDTO.java b/backend/src/main/java/com/stdproject/entity/union/UnionDTO.java new file mode 100644 index 0000000..09032d8 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/union/UnionDTO.java @@ -0,0 +1,21 @@ +package com.stdproject.entity.union; + +import io.gisbi.extensions.datasource.dto.DatasetTableDTO; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @Author gin + */ +@Data +public class UnionDTO implements Serializable { + private DatasetTableDTO currentDs; + private List currentDsField; + private List currentDsFields; + private List childrenDs; + private UnionParamDTO unionToParent; + private int allChildCount; +} diff --git a/backend/src/main/java/com/stdproject/entity/union/UnionItemDTO.java b/backend/src/main/java/com/stdproject/entity/union/UnionItemDTO.java new file mode 100644 index 0000000..a828d34 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/union/UnionItemDTO.java @@ -0,0 +1,15 @@ +package com.stdproject.entity.union; + +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author gin + */ +@Data +public class UnionItemDTO implements Serializable { + private DatasetTableFieldDTO parentField; + private DatasetTableFieldDTO currentField; +} diff --git a/backend/src/main/java/com/stdproject/entity/union/UnionParamDTO.java b/backend/src/main/java/com/stdproject/entity/union/UnionParamDTO.java new file mode 100644 index 0000000..2777658 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/union/UnionParamDTO.java @@ -0,0 +1,21 @@ +package com.stdproject.entity.union; + +import io.gisbi.extensions.datasource.dto.DatasetTableDTO; +import io.gisbi.extensions.datasource.model.SQLObj; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * @Author gin + */ +@Data +public class UnionParamDTO implements Serializable { + private String unionType; + private List unionFields; + private DatasetTableDTO parentDs; + private DatasetTableDTO currentDs; + private SQLObj parentSQLObj; + private SQLObj currentSQLObj; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/AppCoreChartViewVO.java b/backend/src/main/java/com/stdproject/entity/vo/AppCoreChartViewVO.java new file mode 100644 index 0000000..9268d59 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/AppCoreChartViewVO.java @@ -0,0 +1,208 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AppCoreChartViewVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 场景ID chart_type为private的时候 是仪表板id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sceneId; + + /** + * 数据集表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long tableId; + + /** + * 图表类型 + */ + private String type; + + /** + * 图表渲染方式 + */ + private String render; + + /** + * 展示结果 + */ + private Integer resultCount; + + /** + * 展示模式 + */ + private String resultMode; + + /** + * 横轴field + */ + private String xAxis; + + /** + * table-row + */ + private String xAxisExt; + + /** + * 纵轴field + */ + private String yAxis; + + /** + * 副轴 + */ + private String yAxisExt; + + /** + * 堆叠项 + */ + private String extStack; + + /** + * 气泡大小 + */ + private String extBubble; + + /** + * 动态标签 + */ + private String extLabel; + + /** + * 动态提示 + */ + private String extTooltip; + + /** + * 图形属性 + */ + private String customAttr; + + /** + * 组件样式 + */ + private String customStyle; + + /** + * 结果过滤 + */ + private String customFilter; + + /** + * 钻取字段 + */ + private String drillFields; + + /** + * 高级 + */ + private String senior; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 缩略图 + */ + private String snapshot; + + /** + * 样式优先级 panel 仪表板 view 图表 + */ + private String stylePriority; + + /** + * 图表类型 public 公共 历史可复用的图表,private 私有 专属某个仪表板 + */ + private String chartType; + + /** + * 是否插件 + */ + private Boolean isPlugin; + + /** + * 数据来源 template 模板数据 dataset 数据集数据 + */ + private String dataFrom; + + /** + * 图表字段集合 + */ + private String viewFields; + + /** + * 是否开启刷新 + */ + private Boolean refreshViewEnable; + + /** + * 刷新时间单位 + */ + private String refreshUnit; + + /** + * 刷新时间 + */ + private Integer refreshTime; + + /** + * 是否开启联动 + */ + private Boolean linkageActive; + + /** + * 是否开启跳转 + */ + private Boolean jumpActive; + + /** + * 复制来源 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long copyFrom; + + /** + * 复制ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long copyId; + + /** + * 区间条形图开启时间纬度开启聚合 + */ + private Boolean aggregate; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetGroupVO.java b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetGroupVO.java new file mode 100644 index 0000000..d14acde --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetGroupVO.java @@ -0,0 +1,92 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AppCoreDatasetGroupVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 当前分组处于第几级 + */ + private Integer level; + + /** + * node类型:folder or dataset + */ + private String nodeType; + + /** + * sql,union + */ + private String type; + + /** + * 连接模式:0-直连,1-同步(包括excel、api等数据存在de中的表) + */ + private Integer mode; + + /** + * 关联关系树 + */ + private String info; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + private String qrtzInstance; + + /** + * 同步状态 + */ + private String syncStatus; + + /** + * 更新人ID + */ + private String updateBy; + + /** + * 最后同步时间 + */ + private Long lastUpdateTime; + + /** + * 关联sql + */ + private String unionSql; + + /** + * 是否跨源 + */ + private Boolean isCross; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableFieldVO.java b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableFieldVO.java new file mode 100644 index 0000000..d94e4d0 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableFieldVO.java @@ -0,0 +1,126 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AppCoreDatasetTableFieldVO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 数据源ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasourceId; + + /** + * 数据表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetTableId; + + /** + * 数据集ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetGroupId; + + /** + * 图表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long chartId; + + /** + * 原始字段名 + */ + private String originName; + + /** + * 字段名用于展示 + */ + private String name; + + /** + * 描述 + */ + private String description; + + /** + * de字段名用作唯一标识 + */ + private String gisbiName; + + /** + * de字段别名 + */ + private String fieldShortName; + + /** + * 维度/指标标识 d:维度,q:指标 + */ + private String groupType; + + /** + * 原始字段类型 + */ + private String type; + + private Integer size; + + /** + * gisbi字段类型:0-文本,1-时间,2-整型数值,3-浮点数值,4-布尔,5-地理位置,6-二进制 + */ + private Integer deType; + + /** + * de记录的原始类型 + */ + private Integer deExtractType; + + /** + * 是否扩展字段 0原始 1复制 2计算字段... + */ + private Integer extField; + + /** + * 是否选中 + */ + private Boolean checked; + + /** + * 列位置 + */ + private Integer columnIndex; + + /** + * 同步时间 + */ + private Long lastSyncTime; + + /** + * 精度 + */ + private Integer accuracy; + + private String dateFormat; + + /** + * 时间格式类型 + */ + private String dateFormatType; + + /** + * params + */ + private String params; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableVO.java b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableVO.java new file mode 100644 index 0000000..f0d2058 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasetTableVO.java @@ -0,0 +1,55 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AppCoreDatasetTableVO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 物理表名 + */ + private String tableName; + + /** + * 数据源ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasourceId; + + /** + * 数据集ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetGroupId; + + /** + * db,sql,union,excel,api + */ + private String type; + + /** + * 表原始信息,表名,sql等 + */ + private String info; + + /** + * SQL参数 + */ + private String sqlVariableDetails; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceTaskVO.java b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceTaskVO.java new file mode 100644 index 0000000..827b0f2 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceTaskVO.java @@ -0,0 +1,92 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AppCoreDatasourceTaskVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 数据源ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long dsId; + + /** + * 任务名称 + */ + private String name; + + /** + * 更新方式 + */ + private String updateType; + + /** + * 开始时间 + */ + private Long startTime; + + /** + * 执行频率:0 一次性 1 cron + */ + private String syncRate; + + /** + * cron表达式 + */ + private String cron; + + /** + * 简单重复间隔 + */ + private Long simpleCronValue; + + /** + * 简单重复类型:分、时、天 + */ + private String simpleCronType; + + /** + * 结束限制 0 无限制 1 设定结束时间 + */ + private String endLimit; + + /** + * 结束时间 + */ + private Long endTime; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 上次执行时间 + */ + private Long lastExecTime; + + /** + * 上次执行结果 + */ + private String lastExecStatus; + + private String extraData; + + /** + * 任务状态 + */ + private String taskStatus; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceVO.java b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceVO.java new file mode 100644 index 0000000..e316420 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/AppCoreDatasourceVO.java @@ -0,0 +1,91 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class AppCoreDatasourceVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 描述 + */ + private String description; + + /** + * 类型 + */ + private String type; + + /** + * 父级ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 更新方式:0:替换;1:追加 + */ + private String editType; + + /** + * 详细信息 + */ + private String configuration; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 变更人 + */ + private Long updateBy; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 状态 + */ + private String status; + + /** + * 状态 + */ + private String qrtzInstance; + + /** + * 任务状态 + */ + private String taskStatus; + + /** + * 映射系统数据源ID + */ + private Long systemDatasourceId; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/ChartBaseVO.java b/backend/src/main/java/com/stdproject/entity/vo/ChartBaseVO.java new file mode 100644 index 0000000..85971dd --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/ChartBaseVO.java @@ -0,0 +1,76 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.gisbi.extensions.view.dto.ChartViewFieldDTO; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +public class ChartBaseVO implements Serializable { + @Serial + private static final long serialVersionUID = -2445689467486374464L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long chartId; + + private String chartType; + + private String chartName; + + @JsonSerialize(using = ToStringSerializer.class) + private Long resourceId; + + private String resourceType; + + private String resourceName; + + @JsonSerialize(using = ToStringSerializer.class) + private Long tableId; + + @JsonProperty("xAxis") + private List xAxis; + + /** + * 横轴field ext + */ + @JsonProperty("xAxisExt") + private List xAxisExt; + + /** + * 纵轴field + */ + @JsonProperty("yAxis") + private List yAxis; + + /** + * 副轴 + */ + @JsonProperty("yAxisExt") + private List yAxisExt; + + /** + * 堆叠项 + */ + private List extStack; + + /** + * 气泡大小 + */ + private List extBubble; + + private List flowMapStartName; + + private List flowMapEndName; + + private List extColor; + + private List extLabel; + + private List extTooltip; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/CoreDatasetGroupVO.java b/backend/src/main/java/com/stdproject/entity/vo/CoreDatasetGroupVO.java new file mode 100644 index 0000000..aec5037 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/CoreDatasetGroupVO.java @@ -0,0 +1,98 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Data +public class CoreDatasetGroupVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 父级ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 当前分组处于第几级 + */ + private Integer level; + + /** + * node类型:folder or dataset + */ + private String nodeType; + + /** + * sql,union + */ + private String type; + + /** + * 连接模式:0-直连,1-同步(包括excel、api等数据存在de中的表) + */ + private Integer mode; + + /** + * 关联关系树 + */ + private String info; + + /** + * 创建人ID + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + private String qrtzInstance; + + /** + * 同步状态 + */ + private String syncStatus; + + /** + * 更新人ID + */ + private String updateBy; + + /** + * 最后同步时间 + */ + private Long lastUpdateTime; + + /** + * 关联sql + */ + private String unionSql; + + /** + * 是否跨源 + */ + private Boolean isCross; + + private List datasetFields = new ArrayList<>(); + + private List datasetViews = new ArrayList<>(); +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/CoreDatasetTableFieldVO.java b/backend/src/main/java/com/stdproject/entity/vo/CoreDatasetTableFieldVO.java new file mode 100644 index 0000000..6c99580 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/CoreDatasetTableFieldVO.java @@ -0,0 +1,132 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@NoArgsConstructor +public class CoreDatasetTableFieldVO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 数据源ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasourceId; + + /** + * 数据表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetTableId; + + /** + * 数据集ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long datasetGroupId; + + /** + * 图表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long chartId; + + /** + * 原始字段名 + */ + private String originName; + + /** + * 字段名用于展示 + */ + private String name; + + /** + * 描述 + */ + private String description; + + /** + * de字段名用作唯一标识 + */ + private String gisbiName; + + /** + * de字段别名 + */ + private String fieldShortName; + + /** + * 维度/指标标识 d:维度,q:指标 + */ + private String groupType; + + /** + * 原始字段类型 + */ + private String type; + + private Integer size; + + /** + * gisbi字段类型:0-文本,1-时间,2-整型数值,3-浮点数值,4-布尔,5-地理位置,6-二进制 + */ + private Integer deType; + + /** + * de记录的原始类型 + */ + private Integer deExtractType; + + /** + * 是否扩展字段 0原始 1复制 2计算字段... + */ + private Integer extField; + + /** + * 是否选中 + */ + private Boolean checked; + + /** + * 列位置 + */ + private Integer columnIndex; + + /** + * 同步时间 + */ + private Long lastSyncTime; + + /** + * 精度 + */ + private Integer accuracy; + + private String dateFormat; + + /** + * 时间格式类型 + */ + private String dateFormatType; + + // 附加ID 兼容自定义参数ID + private String attachId; + + public CoreDatasetTableFieldVO(String attachId, String name, Integer deType) { + this.attachId = attachId; + this.name = name; + this.deType = deType; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/DataSetBarVO.java b/backend/src/main/java/com/stdproject/entity/vo/DataSetBarVO.java new file mode 100644 index 0000000..3c9e14e --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/DataSetBarVO.java @@ -0,0 +1,39 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.gisbi.extensions.datasource.dto.DatasourceDTO; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +@Data +public class DataSetBarVO implements Serializable { + @Serial + private static final long serialVersionUID = 7791029875759340927L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String name; + + private String nodeType; + + private String createBy; + + private Long createTime; + + private String creator; + + private Long lastUpdateTime; + + private String updateBy; + + private String updater; + + private List datasourceDTOList; + + private Boolean isCross; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/DataVisualizationBaseVO.java b/backend/src/main/java/com/stdproject/entity/vo/DataVisualizationBaseVO.java new file mode 100644 index 0000000..4bdbbfa --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/DataVisualizationBaseVO.java @@ -0,0 +1,51 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.gisbi.model.ITreeBase; +import lombok.Data; + +import java.util.List; + +@Data +public class DataVisualizationBaseVO implements ITreeBase { + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String name; + + private String label; + + private String nodeType; + + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 移动端布局 + */ + private String mobileLayout; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 创建人 + */ + private String createBy; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updateBy; + + private List children; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/DataVisualizationVO.java b/backend/src/main/java/com/stdproject/entity/vo/DataVisualizationVO.java new file mode 100644 index 0000000..189eebb --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/DataVisualizationVO.java @@ -0,0 +1,211 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.stdproject.entity.dto.VisualizationTemplateExtendDataDTO; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import io.gisbi.utils.JsonUtil; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +@Data +@NoArgsConstructor +public class DataVisualizationVO implements Serializable { + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + /** + * 应用ID + */ + private String appId; + /** + * 名称 + */ + private String name; + + /** + * 父id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 所属组织id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long orgId; + + /** + * 层级 + */ + private Integer level; + + /** + * 节点类型 folder or panel 目录或者文件夹 + */ + private String nodeType; + + /** + * 类型 + */ + private String type; + + /** + * 样式数据 + */ + private String canvasStyleData; + + /** + * 组件数据 + */ + private String componentData; + + /** + * 移动端布局 + */ + private Boolean mobileLayout; + /** + * 移动端布局 + */ + private Integer extFlag; + + /** + * 状态 0-未发布 1-已发布 + */ + private Integer status; + + /** + * 是否单独打开水印 0-关闭 1-开启 + */ + private Boolean selfWatermarkStatus; + + /** + * 排序 + */ + private Integer sort; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 创建人 + */ + private String createBy; + /** + * 创建人姓名 + */ + private String creatorName; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updateBy; + /** + * 更新人姓名 + */ + private String updateName; + + /** + * 备注 + */ + private String remark; + + /** + * 数据来源 + */ + private String source; + + /** + * 删除标志 + */ + private Boolean deleteFlag; + + /** + * 删除时间 + */ + private Long deleteTime; + + /** + * 删除人 + */ + private String deleteBy; + + /** + * 可视化资源版本 + */ + private Integer version; + + /** + * 内容标识 + */ + private String contentId; + + /** + * 内容检查标识 + */ + private String checkVersion; + + /** + * 图表基本信息 + */ + private Map canvasViewInfo = new HashMap<>(); + + /** + * 图表模板数据 + */ + private Map extendDataInfo = new HashMap<>(); + + + /** + * 定时报告自定义过滤数据 + */ + private Map reportFilterInfo = new HashMap<>(); + + /** + * 水印信息 + */ + private VisualizationWatermarkVO watermarkInfo; + + /** + * 权限信息 + */ + private Integer weight; + + private int ext; + + /** + * 应用信息 + */ + private VisualizationExport2AppVO appData; + + + public DataVisualizationVO(Long id, String name, String type, Integer version, String canvasStyleData, String componentData, String appDataStr, Map canvasViewInfo, Map extendDataInfo) { + this.id = id; + this.name = name; + this.type = type; + this.canvasStyleData = canvasStyleData; + this.componentData = componentData; + this.canvasViewInfo = canvasViewInfo; + this.extendDataInfo = extendDataInfo; + if(StringUtils.isNotEmpty(appDataStr)){ + this.appData= JsonUtil.parseObject(appDataStr,VisualizationExport2AppVO.class); + } + this.version = version; + } + + public DataVisualizationVO(Integer status) { + this.status = status; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/DatasetTreeNodeVO.java b/backend/src/main/java/com/stdproject/entity/vo/DatasetTreeNodeVO.java new file mode 100644 index 0000000..cd8a9f9 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/DatasetTreeNodeVO.java @@ -0,0 +1,18 @@ +package com.stdproject.entity.vo; + + +import com.stdproject.entity.dto.DatasetNodeDTO; +import io.gisbi.model.ITreeBase; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +public class DatasetTreeNodeVO extends DatasetNodeDTO implements Serializable, ITreeBase { + + private List children; + + private Boolean leaf; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/UserFormVO.java b/backend/src/main/java/com/stdproject/entity/vo/UserFormVO.java new file mode 100644 index 0000000..0fa9e09 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/UserFormVO.java @@ -0,0 +1,49 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Schema(description = "用户详情VO") +@Data +public class UserFormVO implements Serializable { + + @Schema(description = "ID") + @JsonSerialize(using= ToStringSerializer.class) + private Long id; + + @Schema(description = "账号") + private String account; + + @Schema(description = "名称") + private String name; + + @Schema(description = "角色ID集合") + private List roleIds; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "状态") + private Boolean enable; + + @Schema(description = "电话前缀") + private String phonePrefix; + + @Schema(description = "电话") + private String phone; + + @Schema(description = "IP") + private String ip; + + @Schema(description = "模式") + private String model; + + @Schema(description = "MFA状态") + private Boolean mfaEnable = false; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/ViewSelectorVO.java b/backend/src/main/java/com/stdproject/entity/vo/ViewSelectorVO.java new file mode 100644 index 0000000..1cd7b2a --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/ViewSelectorVO.java @@ -0,0 +1,24 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +public class ViewSelectorVO implements Serializable { + @Serial + private static final long serialVersionUID = -7163837502596313691L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String title; + + private String type; + + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationBackgroundVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationBackgroundVO.java new file mode 100644 index 0000000..6f35dac --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationBackgroundVO.java @@ -0,0 +1,34 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author : WangJiaHao + * @date : 2023/6/12 19:27 + */ +@Data +public class VisualizationBackgroundVO implements Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + + private String name; + + private String classification; + + private String content; + + private String remark; + + private Integer sort; + + private Long uploadTime; + + private String baseUrl; + + private String url; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationBaseInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationBaseInfoVO.java new file mode 100644 index 0000000..952ea05 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationBaseInfoVO.java @@ -0,0 +1,48 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + + +@Data +public class VisualizationBaseInfoVO { + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String name; + + private String label; + + private String nodeType; + + @JsonSerialize(using = ToStringSerializer.class) + private Long pid; + + /** + * 移动端布局 + */ + private String mobileLayout; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 创建人 + */ + private String createBy; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updateBy; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationExport2AppVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationExport2AppVO.java new file mode 100644 index 0000000..34598f0 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationExport2AppVO.java @@ -0,0 +1,74 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class VisualizationExport2AppVO { + + private Boolean checkStatus = false; + + private String checkMes; + + private String visualizationInfo; + + private String visualizationViewsInfo; + + List chartViewsInfo; + + List datasetGroupsInfo; + + List datasetTablesInfo; + + List datasetTableFieldsInfo; + + List datasourceInfo; + + List datasourceTaskInfo; + + List linkJumps; + + List linkJumpInfos; + + List linkJumpTargetInfos; + + List linkages; + + List linkageFields; + + public VisualizationExport2AppVO() { + + } + + public VisualizationExport2AppVO(String checkMes) { + this.checkMes = checkMes; + } + + public VisualizationExport2AppVO(List chartViewVOInfo, + List datasetGroupVOInfo, + List datasetTableVOInfo, + List datasetTableFieldVOInfo, + List datasourceVOInfo, + List datasourceTaskVOInfo, + List linkJumpVOInfo, + List linkJumpInfoVOInfo, + List linkJumpTargetViewVOInfo, + List linkagesVOInfo, + List linkageFieldVOInfo) { + this.checkStatus = true; + this.checkMes = "success"; + this.chartViewsInfo = chartViewVOInfo != null ? chartViewVOInfo : new ArrayList<>(); + this.datasetGroupsInfo = datasetGroupVOInfo != null ? datasetGroupVOInfo : new ArrayList<>(); + this.datasetTablesInfo = datasetTableVOInfo != null ? datasetTableVOInfo : new ArrayList<>(); + this.datasetTableFieldsInfo = datasetTableFieldVOInfo != null ? datasetTableFieldVOInfo : new ArrayList<>(); + this.datasourceTaskInfo = datasourceTaskVOInfo != null ? datasourceTaskVOInfo : new ArrayList<>(); + this.datasourceInfo = datasourceVOInfo != null ? datasourceVOInfo : new ArrayList<>(); + this.linkJumps = linkJumpVOInfo != null ? linkJumpVOInfo : new ArrayList<>(); + this.linkJumpInfos = linkJumpInfoVOInfo != null ? linkJumpInfoVOInfo : new ArrayList<>(); + this.linkJumpTargetInfos = linkJumpTargetViewVOInfo != null ? linkJumpTargetViewVOInfo : new ArrayList<>(); + this.linkages = linkagesVOInfo != null ? linkagesVOInfo : new ArrayList<>(); + this.linkageFields = linkageFieldVOInfo != null ? linkageFieldVOInfo : new ArrayList<>(); + } +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpInfoVO.java new file mode 100644 index 0000000..8698b64 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpInfoVO.java @@ -0,0 +1,68 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 13:21 + */ +@Data +public class VisualizationLinkJumpInfoVO { + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * link jump ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long linkJumpId; + + /** + * 关联类型 inner 内部仪表板,outer 外部链接 + */ + private String linkType; + + /** + * 跳转类型 _blank 新开页面 _self 当前窗口 + */ + private String jumpType; + + /** + * 窗口大小large middle small + */ + private String windowSize; + + + /** + * 关联仪表板ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long targetDvId; + + /** + * 字段ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceFieldId; + + /** + * 内容 linkType = outer时使用 + */ + private String content; + + /** + * 是否可用 + */ + private Boolean checked; + + /** + * 是否附加点击参数 + */ + private Boolean attachParams; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyFrom; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyId; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpTargetViewInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpTargetViewInfoVO.java new file mode 100644 index 0000000..e77c22a --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpTargetViewInfoVO.java @@ -0,0 +1,38 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 14:18 + */ +@Data +public class VisualizationLinkJumpTargetViewInfoVO { + @JsonSerialize(using = ToStringSerializer.class) + private Long targetId; + @JsonSerialize(using = ToStringSerializer.class) + private Long linkJumpInfoId; + /** + * 勾选字段设置的匹配字段,也可以不是勾选字段本身 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceFieldActiveId; + private String targetViewId; + private String targetFieldId; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyFrom; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyId; + + /** + * 联动目标类型 view 图表 filter 过滤组件 outParams 外部参数 + */ + private String targetType; + + /** + * 外部参数名称 当targetType==outParams时 实时查询对应名称 + */ + private String outerParamsName; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpVO.java new file mode 100644 index 0000000..20689de --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkJumpVO.java @@ -0,0 +1,44 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 12:40 + */ +@Data +public class VisualizationLinkJumpVO { + private static final long serialVersionUID = 1L; + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 源仪表板ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceDvId; + + /** + * 源图表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceViewId; + + /** + * 跳转信息 + */ + private String linkJumpInfo; + + /** + * 是否启用 + */ + private Boolean checked; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyFrom; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyId; + @JsonSerialize(using = ToStringSerializer.class) + private Long queryUid; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageFieldVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageFieldVO.java new file mode 100644 index 0000000..1580ef9 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageFieldVO.java @@ -0,0 +1,43 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class VisualizationLinkageFieldVO implements Serializable { + + private static final long serialVersionUID = 1L; + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 联动ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long linkageId; + + /** + * 源图表字段 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceField; + + /** + * 目标图表字段 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long targetField; + + /** + * 更新时间 + */ + private Long updateTime; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyFrom; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyId; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageVO.java new file mode 100644 index 0000000..78c0a94 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationLinkageVO.java @@ -0,0 +1,53 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class VisualizationLinkageVO implements Serializable { + + private static final long serialVersionUID = 1L; + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + @JsonSerialize(using = ToStringSerializer.class) + private Long dvId; + + /** + * 源图表id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceViewId; + + /** + * 联动图表id + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long targetViewId; + + /** + * 更新时间 + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long updateTime; + + /** + * 更新人 + */ + private String updatePeople; + + /** + * 是否启用关联 + */ + private Boolean linkageActive; + + private String ext1; + + private String ext2; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyFrom; + @JsonSerialize(using = ToStringSerializer.class) + private Long copyId; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationOutParamsJumpVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOutParamsJumpVO.java new file mode 100644 index 0000000..7e179db --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOutParamsJumpVO.java @@ -0,0 +1,15 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +@Data +public class VisualizationOutParamsJumpVO { + + private String id; + + private String type; + + private String name; + + private String title; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsDsInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsDsInfoVO.java new file mode 100644 index 0000000..116becb --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsDsInfoVO.java @@ -0,0 +1,19 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class VisualizationOuterParamsDsInfoVO { + + private String dsName; + + private String dsId; + + private List targetFieldInfo; + + private Map viewCheckedInfo; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsFilterInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsFilterInfoVO.java new file mode 100644 index 0000000..ee2a2ac --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsFilterInfoVO.java @@ -0,0 +1,12 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +@Data +public class VisualizationOuterParamsFilterInfoVO { + + private String filterComponentId; + + private String filterId; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsInfoVO.java new file mode 100644 index 0000000..9420262 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsInfoVO.java @@ -0,0 +1,76 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 外部参数配置表 + *

+ * + * @author fit2cloud + * @since 2024-03-08 + */ +@Data +public class VisualizationOuterParamsInfoVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private String paramsInfoId; + + /** + * visualization_outer_params 表的 ID + */ + private String paramsId; + + /** + * 参数名 + */ + private String paramName; + + /** + * 是否启用 + */ + private Boolean checked; + + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 默认值 JSON格式 + */ + private String defaultValue; + + /** + * 是否启用默认值 + */ + private Boolean enabledDefault; + /** + * 复制来源 + */ + private String copyFrom; + + /** + * 复制来源ID + */ + private String copyId; + + @Override + public String toString() { + return "VisualizationOuterParamsInfo{" + + "paramsInfoId = " + paramsInfoId + + ", paramsId = " + paramsId + + ", paramName = " + paramName + + ", checked = " + checked + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsTargetViewInfoVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsTargetViewInfoVO.java new file mode 100644 index 0000000..884d91a --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsTargetViewInfoVO.java @@ -0,0 +1,54 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + *

+ * 外部参数联动视图字段信息表 + *

+ * + * @author fit2cloud + * @since 2024-03-08 + */ +@Data +public class VisualizationOuterParamsTargetViewInfoVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private String targetId; + + /** + * visualization_outer_params_info 表的 ID + */ + private String paramsInfoId; + + /** + * 联动视图ID + */ + private String targetViewId; + + /** + * 联动数据集id/联动过滤组件id + */ + private String targetDsId; + + /** + * 联动字段ID + */ + private String targetFieldId; + + /** + * 复制来源 + */ + private String copyFrom; + + /** + * 复制来源ID + */ + private String copyId; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsVO.java new file mode 100644 index 0000000..8faa02c --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationOuterParamsVO.java @@ -0,0 +1,119 @@ +package com.stdproject.entity.vo; + +import java.io.Serializable; + +/** + *

+ * 外部参数关联关系表 + *

+ * + * @author fit2cloud + * @since 2024-03-08 + */ +public class VisualizationOuterParamsVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private String paramsId; + + /** + * 可视化资源ID + */ + private String visualizationId; + + /** + * 是否启用外部参数标识(1-是,0-否) + */ + private Boolean checked; + + /** + * 备注 + */ + private String remark; + + /** + * 复制来源 + */ + private String copyFrom; + + /** + * 复制来源ID + */ + private String copyId; + + /** + * 是否必填 + */ + private Boolean required; + + /** + * 默认值 JSON格式 + */ + private String defaultValue; + + + public String getParamsId() { + return paramsId; + } + + public void setParamsId(String paramsId) { + this.paramsId = paramsId; + } + + public String getVisualizationId() { + return visualizationId; + } + + public void setVisualizationId(String visualizationId) { + this.visualizationId = visualizationId; + } + + public Boolean getChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getCopyFrom() { + return copyFrom; + } + + public void setCopyFrom(String copyFrom) { + this.copyFrom = copyFrom; + } + + public String getCopyId() { + return copyId; + } + + public void setCopyId(String copyId) { + this.copyId = copyId; + } + + @Override + public String toString() { + return "VisualizationOuterParams{" + + "paramsId = " + paramsId + + ", visualizationId = " + visualizationId + + ", checked = " + checked + + ", required = " + required + + ", defaultValue = " + defaultValue + + ", remark = " + remark + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationReportFilterVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationReportFilterVO.java new file mode 100644 index 0000000..4e6a37a --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationReportFilterVO.java @@ -0,0 +1,175 @@ +package com.stdproject.entity.vo; + +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @author fit2cloud + * @since 2024-06-25 + */ +public class VisualizationReportFilterVO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + + /** + * 定时报告id + */ + private Long reportId; + + /** + * 任务id + */ + private Long taskId; + + /** + * 资源id + */ + private Long resourceId; + + /** + * 资源类型 + */ + private String dvType; + + /** + * 组件id + */ + private Long componentId; + + /** + * 过滤项id + */ + private Long filterId; + + /** + * 过滤组件内容 + */ + private String filterInfo; + + /** + * 过滤组件版本 + */ + private Integer filterVersion; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 创建人 + */ + private String createUser; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getReportId() { + return reportId; + } + + public void setReportId(Long reportId) { + this.reportId = reportId; + } + + public Long getTaskId() { + return taskId; + } + + public void setTaskId(Long taskId) { + this.taskId = taskId; + } + + public Long getResourceId() { + return resourceId; + } + + public void setResourceId(Long resourceId) { + this.resourceId = resourceId; + } + + public String getDvType() { + return dvType; + } + + public void setDvType(String dvType) { + this.dvType = dvType; + } + + public Long getComponentId() { + return componentId; + } + + public void setComponentId(Long componentId) { + this.componentId = componentId; + } + + public Long getFilterId() { + return filterId; + } + + public void setFilterId(Long filterId) { + this.filterId = filterId; + } + + public String getFilterInfo() { + return filterInfo; + } + + public void setFilterInfo(String filterInfo) { + this.filterInfo = filterInfo; + } + + public Integer getFilterVersion() { + return filterVersion; + } + + public void setFilterVersion(Integer filterVersion) { + this.filterVersion = filterVersion; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public String getCreateUser() { + return createUser; + } + + public void setCreateUser(String createUser) { + this.createUser = createUser; + } + + @Override + public String toString() { + return "VisualizationReportFilter{" + + "id = " + id + + ", reportId = " + reportId + + ", taskId = " + taskId + + ", resourceId = " + resourceId + + ", dvType = " + dvType + + ", componentId = " + componentId + + ", filterId = " + filterId + + ", filterInfo = " + filterInfo + + ", filterVersion = " + filterVersion + + ", createTime = " + createTime + + ", createUser = " + createUser + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationResourceVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationResourceVO.java new file mode 100644 index 0000000..b245d4d --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationResourceVO.java @@ -0,0 +1,40 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VisualizationResourceVO implements Serializable { + @Serial + private static final long serialVersionUID = 627770173259978185L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long resourceId; + + private String name; + + private String type; + + private String creator; + + private String lastEditor; + + private Long lastEditTime; + + private Boolean favorite; + + private int weight; + + private Integer extFlag; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationStoreVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationStoreVO.java new file mode 100644 index 0000000..7c0d805 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationStoreVO.java @@ -0,0 +1,41 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VisualizationStoreVO implements Serializable { + @Serial + private static final long serialVersionUID = 627770173259978185L; + + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @JsonSerialize(using = ToStringSerializer.class) + private Long resourceId; + + private String name; + + private String type; + + private String creator; + + private String lastEditor; + + private Long lastEditTime; + + private int weight; + + private Integer extFlag; + + private Integer extFlag1; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationSubjectVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationSubjectVO.java new file mode 100644 index 0000000..b8615f4 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationSubjectVO.java @@ -0,0 +1,74 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @author : wangjiahao + * @date : 2023/6/9 14:57 + */ +@Data +public class VisualizationSubjectVO implements Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + + /** + * 主题名称 + */ + private String name; + + /** + * 主题类型 system 系统主题,self 自定义主题 + */ + private String type; + + private Integer createNum; + + /** + * 主题内容 + */ + private String details; + + /** + * 封面 + */ + private String coverUrl; + + /** + * 删除标记 + */ + private Boolean deleteFlag; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 创建人 + */ + private String createBy; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updateBy; + + /** + * 删除时间 + */ + private Long deleteTime; + + /** + * 删除人 + */ + private Long deleteBy; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateExtendDataVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateExtendDataVO.java new file mode 100644 index 0000000..f4250ec --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateExtendDataVO.java @@ -0,0 +1,26 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @author : WangJiaHao + * @date : 2023/11/13 10:25 + */ +@Data +public class VisualizationTemplateExtendDataVO { + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + @JsonSerialize(using = ToStringSerializer.class) + private Long dvId; + @JsonSerialize(using = ToStringSerializer.class) + private Long viewId; + + private String viewDetails; + + private String copyFrom; + + private String copyId; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateVO.java new file mode 100644 index 0000000..4102e72 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationTemplateVO.java @@ -0,0 +1,98 @@ +package com.stdproject.entity.vo; + +import lombok.Data; + +import java.util.List; + +/** + * @author : WangJiaHao + * @date : 2023/11/7 13:22 + */ +@Data +public class VisualizationTemplateVO { + + /** + * 主键 + */ + private String id; + + /** + * 名称 + */ + private String name; + + /** + * 父级id + */ + private String pid; + + /** + * 层级 + */ + private Integer level; + + /** + * 模板种类 dataV or dashboard 目录或者文件夹 + */ + private String dvType; + + /** + * 节点类型 folder or panel 目录或者文件夹 + */ + private String nodeType; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 缩略图 + */ + private String snapshot; + + /** + * 模板类型 system 系统内置 self 用户自建 + */ + private String templateType; + + /** + * template 样式 + */ + private String templateStyle; + + /** + * template 数据 + */ + private String templateData; + + /** + * 预存数据 + */ + private String dynamicData; + + /** + * app数据 + */ + private String appData; + + /** + * 使用次数 + */ + private Integer useCount; + + /** + * 版本号 + */ + private Integer version; + + /** + * 分类 + */ + private List categories; +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationViewTableVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationViewTableVO.java new file mode 100644 index 0000000..5c36b02 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationViewTableVO.java @@ -0,0 +1,48 @@ +package com.stdproject.entity.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import lombok.Data; + +import java.util.List; + + +/** + * @author : WangJiaHao + * @date : 2023/7/19 + */ +@Data +public class VisualizationViewTableVO { + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String title; + + @JsonSerialize(using = ToStringSerializer.class) + private Long dvId; + + /** + * 数据集表ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long tableId; + + /** + * 图表类型 + */ + private String type; + + /** + * 图表渲染方式 + */ + private String render; + + + private List tableFields; + +} diff --git a/backend/src/main/java/com/stdproject/entity/vo/VisualizationWatermarkVO.java b/backend/src/main/java/com/stdproject/entity/vo/VisualizationWatermarkVO.java new file mode 100644 index 0000000..35916a5 --- /dev/null +++ b/backend/src/main/java/com/stdproject/entity/vo/VisualizationWatermarkVO.java @@ -0,0 +1,80 @@ +package com.stdproject.entity.vo; + +public class VisualizationWatermarkVO{ + + /** + * 主键 + */ + private String id; + + /** + * 版本号 + */ + private String version; + + /** + * 设置内容 + */ + private String settingContent; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + private Long createTime; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getSettingContent() { + return settingContent; + } + + public void setSettingContent(String settingContent) { + this.settingContent = settingContent; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + @Override + public String toString() { + return "VisualizationWatermark{" + + "id = " + id + + ", version = " + version + + ", settingContent = " + settingContent + + ", createBy = " + createBy + + ", createTime = " + createTime + + "}"; + } +} diff --git a/backend/src/main/java/com/stdproject/mapper/CoreDataSetExtMapper.java b/backend/src/main/java/com/stdproject/mapper/CoreDataSetExtMapper.java new file mode 100644 index 0000000..d038c5f --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/CoreDataSetExtMapper.java @@ -0,0 +1,24 @@ +package com.stdproject.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; + +import com.stdproject.entity.po.DataSetNodePO; +import com.stdproject.entity.vo.DataSetBarVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface CoreDataSetExtMapper { + + @Select(""" + select id, name, node_type, pid,app_id from core_dataset_group + ${ew.customSqlSegment} + """) + List query(@Param("ew") QueryWrapper queryWrapper); + + @Select("select id, name, node_type, create_by, create_time, update_by, last_update_time, is_cross from core_dataset_group where id = #{id}") + DataSetBarVO queryBarInfo(@Param("id") Long id); +} diff --git a/backend/src/main/java/com/stdproject/mapper/CoreDatasetGroupMapper.java b/backend/src/main/java/com/stdproject/mapper/CoreDatasetGroupMapper.java new file mode 100644 index 0000000..0449269 --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/CoreDatasetGroupMapper.java @@ -0,0 +1,19 @@ +package com.stdproject.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.stdproject.entity.CoreDatasetGroup; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2023-08-28 + */ +@Mapper +public interface CoreDatasetGroupMapper extends BaseMapper { + +} diff --git a/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableFieldMapper.java b/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableFieldMapper.java new file mode 100644 index 0000000..19df00a --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableFieldMapper.java @@ -0,0 +1,19 @@ +package com.stdproject.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.stdproject.entity.CoreDatasetTableField; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * table数据集表字段 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-02-06 + */ +@Mapper +public interface CoreDatasetTableFieldMapper extends BaseMapper { + +} diff --git a/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableMapper.java b/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableMapper.java new file mode 100644 index 0000000..6b216fe --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableMapper.java @@ -0,0 +1,24 @@ +package com.stdproject.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.stdproject.entity.CoreDatasetTable; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Map; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2023-04-14 + */ +@Mapper +public interface CoreDatasetTableMapper extends BaseMapper { + @Select("select b.name group_name,a.table_name table_name,a.id table_id,a.datasource_id datasource_id from core_dataset_table a join core_dataset_group b on (a.dataset_group_id=b.id) where b.app_id=#{appid} and a.type='db' order by a.name") + List> getTablesByAppId(String appid); +} diff --git a/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableSqlLogMapper.java b/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableSqlLogMapper.java new file mode 100644 index 0000000..8b9326e --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/CoreDatasetTableSqlLogMapper.java @@ -0,0 +1,19 @@ +package com.stdproject.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.stdproject.entity.CoreDatasetTableSqlLog; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2023-08-08 + */ +@Mapper +public interface CoreDatasetTableSqlLogMapper extends BaseMapper { + +} diff --git a/backend/src/main/java/com/stdproject/mapper/ExtChartViewMapper.java b/backend/src/main/java/com/stdproject/mapper/ExtChartViewMapper.java new file mode 100644 index 0000000..9a41d75 --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/ExtChartViewMapper.java @@ -0,0 +1,39 @@ +package com.stdproject.mapper; + + +import com.stdproject.entity.CoreChartView; +import com.stdproject.entity.po.ChartBasePO; +import com.stdproject.entity.vo.ViewSelectorVO; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface ExtChartViewMapper { + + @Select(""" + select id, scene_id as pid, title, type from core_chart_view where type != 'VQuery' and scene_id = #{resourceId} + """) + List queryViewOption(@Param("resourceId") Long resourceId); + + ChartBasePO queryChart(@Param("id") Long id, @Param("resourceTable")String resourceTable); + + List selectListCustom(@Param("sceneId") Long sceneId, @Param("resourceTable") String resourceTable); + + void deleteViewsBySceneId(@Param("sceneId") Long sceneId, @Param("resourceTable") String resourceTable); + + @Select(""" + SELECT id, scene_id as pid, title, type FROM ( + SELECT id, scene_id, title, type FROM core_chart_view + WHERE id = #{viewId} + UNION ALL + SELECT id, scene_id, title, type FROM snapshot_core_chart_view + WHERE id = #{viewId} + ) combined_views + LIMIT 1 + """) + ChartViewDTO findChartViewAround(@Param("viewId") String viewId); +} diff --git a/backend/src/main/java/com/stdproject/mapper/ExtDataVisualizationMapper.java b/backend/src/main/java/com/stdproject/mapper/ExtDataVisualizationMapper.java new file mode 100644 index 0000000..299730f --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/ExtDataVisualizationMapper.java @@ -0,0 +1,23 @@ +package com.stdproject.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.stdproject.entity.CoreChartView; +import com.stdproject.entity.dto.VisualizationViewTableDTO; +import com.stdproject.entity.po.VisualizationResourcePO; +import com.stdproject.entity.vo.DataVisualizationBaseVO; +import com.stdproject.entity.vo.DataVisualizationVO; +import com.stdproject.entity.vo.UserFormVO; +import com.stdproject.entity.vo.VisualizationReportFilterVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Mapper +public interface ExtDataVisualizationMapper { + DataVisualizationVO findDvInfo(@Param("dvId") Long dvId, @Param("dvType") String dvType, @Param("resourceTable") String resourceTable); + +} diff --git a/backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkJumpMapper.java b/backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkJumpMapper.java new file mode 100644 index 0000000..1c28437 --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkJumpMapper.java @@ -0,0 +1,57 @@ +package com.stdproject.mapper; + + +import com.stdproject.entity.dto.VisualizationLinkJumpDTO; +import com.stdproject.entity.vo.VisualizationLinkJumpInfoVO; +import com.stdproject.entity.vo.VisualizationLinkJumpVO; +import com.stdproject.entity.vo.VisualizationOutParamsJumpVO; +import com.stdproject.entity.vo.VisualizationViewTableVO; +import com.stdproject.request.VisualizationLinkJumpBaseRequest; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +@Mapper +public interface ExtVisualizationLinkJumpMapper { + List queryWithDvId(@Param("dvId") Long dvId, @Param("uid") Long uid, @Param("isDesktop") Boolean isDesktop); + + List queryWithDvIdSnapshot(@Param("dvId") Long dvId,@Param("uid") Long uid,@Param("isDesktop") Boolean isDesktop); + + VisualizationLinkJumpDTO queryWithViewId(@Param("dvId") Long dvId,@Param("viewId") Long viewId,@Param("uid") Long uid,@Param("isDesktop") Boolean isDesktop); + + void deleteJumpTargetViewInfoSnapshot(@Param("dvId") Long dvId,@Param("viewId") Long viewId); + + void deleteJumpInfoSnapshot(@Param("dvId") Long dvId,@Param("viewId") Long viewId); + + void deleteJumpSnapshot(@Param("dvId") Long dvId,@Param("viewId") Long viewId); + + void deleteJumpTargetViewInfoWithVisualization(@Param("dvId") Long dvId); + + void deleteJumpInfoWithVisualization(@Param("dvId") Long dvId); + + void deleteJumpWithVisualization(@Param("dvId") Long dvId); + + void deleteJumpTargetViewInfoWithVisualizationSnapshot(@Param("dvId") Long dvId); + + void deleteJumpInfoWithVisualizationSnapshot(@Param("dvId") Long dvId); + + void deleteJumpWithVisualizationSnapshot(@Param("dvId") Long dvId); + + List getTargetVisualizationJumpInfo(@Param("request") VisualizationLinkJumpBaseRequest request); + + List getTargetVisualizationJumpInfoSnapshot(@Param("request") VisualizationLinkJumpBaseRequest request); + + void copyLinkJump(@Param("copyId")Long copyId); + + void copyLinkJumpInfo(@Param("copyId")Long copyId); + + void copyLinkJumpTarget(@Param("copyId")Long copyId); + + List findLinkJumpWithDvId(@Param("dvId")Long dvId); + + List findLinkJumpInfoWithDvId(@Param("dvId")Long dvId); + + List getViewTableDetails(@Param("dvId")Long dvId); + + List queryOutParamsTargetWithDvId(@Param("dvId")Long dvId); +} diff --git a/backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkageMapper.java b/backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkageMapper.java new file mode 100644 index 0000000..4d6e6f9 --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/ExtVisualizationLinkageMapper.java @@ -0,0 +1,44 @@ +package com.stdproject.mapper; + +import com.stdproject.entity.VisualizationLinkage; +import com.stdproject.entity.VisualizationLinkageField; +import com.stdproject.entity.dto.LinkageInfoDTO; +import com.stdproject.entity.dto.VisualizationLinkageDTO; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface ExtVisualizationLinkageMapper { + + List getViewLinkageGather(@Param("dvId") Long dvId, @Param("sourceViewId") Long sourceViewId, @Param("targetViewIds") List targetViewIds); + + List getPanelAllLinkageInfo(@Param("dvId") Long dvId); + + List getViewLinkageGatherSnapshot(@Param("dvId") Long dvId, @Param("sourceViewId") Long sourceViewId, @Param("targetViewIds") List targetViewIds); + + List getPanelAllLinkageInfoSnapshot(@Param("dvId") Long dvId); + + List queryTableField(@Param("table_id") Long tableId); + + List queryTableFieldWithViewId(@Param("viewId") Long viewId); + + void deleteViewLinkage(@Param("dvId") Long dvId,@Param("sourceViewId") Long sourceViewId); + + void deleteViewLinkageField(@Param("dvId") Long dvId,@Param("sourceViewId") Long sourceViewId); + + void deleteViewLinkageSnapshot(@Param("dvId") Long dvId,@Param("sourceViewId") Long sourceViewId); + + void deleteViewLinkageFieldSnapshot(@Param("dvId") Long dvId,@Param("sourceViewId") Long sourceViewId); + + void copyViewLinkage(@Param("copyId") Long copyId); + + void copyViewLinkageField(@Param("copyId") Long copyId); + + List findLinkageWithDvId(@Param("dvId") Long dvId); + + List findLinkageFieldWithDvId(@Param("dvId") Long dvId); +} diff --git a/backend/src/main/java/com/stdproject/mapper/ExtVisualizationOuterParamsMapper.java b/backend/src/main/java/com/stdproject/mapper/ExtVisualizationOuterParamsMapper.java new file mode 100644 index 0000000..c378030 --- /dev/null +++ b/backend/src/main/java/com/stdproject/mapper/ExtVisualizationOuterParamsMapper.java @@ -0,0 +1,35 @@ +package com.stdproject.mapper; + + +import com.stdproject.entity.SnapshotVisualizationOuterParamsInfo; +import com.stdproject.entity.dto.VisualizationOuterParamsDTO; +import com.stdproject.entity.dto.VisualizationOuterParamsInfoDTO; +import com.stdproject.entity.vo.CoreDatasetGroupVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface ExtVisualizationOuterParamsMapper { + + VisualizationOuterParamsDTO queryWithVisualizationIdSnapshot(@Param("visualizationId") String visualizationId); + + void deleteOuterParamsTargetWithVisualizationId(@Param("visualizationId") String visualizationId); + + void deleteOuterParamsInfoWithVisualizationId(@Param("visualizationId") String visualizationId); + + void deleteOuterParamsWithVisualizationId(@Param("visualizationId") String visualizationId); + + void deleteOuterParamsTargetWithVisualizationIdSnapshot(@Param("visualizationId") String visualizationId); + + void deleteOuterParamsInfoWithVisualizationIdSnapshot(@Param("visualizationId") String visualizationId); + + void deleteOuterParamsWithVisualizationIdSnapshot(@Param("visualizationId") String visualizationId); + + List getVisualizationOuterParamsInfo(@Param("visualizationId") String visualizationId); + + List getVisualizationOuterParamsInfoBase(@Param("visualizationId") String visualizationId); + + List queryDsWithVisualizationId(@Param("visualizationId") String visualizationId); +} diff --git a/backend/src/main/java/com/stdproject/request/DataVisualizationBaseRequest.java b/backend/src/main/java/com/stdproject/request/DataVisualizationBaseRequest.java new file mode 100644 index 0000000..5cdeb55 --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/DataVisualizationBaseRequest.java @@ -0,0 +1,78 @@ +package com.stdproject.request; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; + +import com.stdproject.entity.vo.DataVisualizationVO; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +public class DataVisualizationBaseRequest extends DataVisualizationVO { + + private String opt; + + private String resourceName; + + private Boolean moveFromUpdate = false; + + private String optType; + + private String newFrom; + + private String dynamicData; + + private String templateId; + + private String staticResource; + + private String templateUrl; + + private String busiFlag; + + private List activeViewIds; + + // 查询来源 main-edit= 主工程编辑区 main=主工程 report=定时报告 + private String source; + + // 定时报告id + @JsonSerialize(using = ToStringSerializer.class) + private Long reportId; + + // 定时报告任务id + @JsonSerialize(using = ToStringSerializer.class) + private Long taskId; + + private Boolean showWatermark; + + @JsonSerialize(using = ToStringSerializer.class) + // 数据集分组PID + private Long datasetFolderPid; + + // 数据集分组名称 + private String datasetFolderName; + + //新赋值的content_id + private String newContentId; + + // 是否强制校验新旧contentId + private Boolean checkHistory = false; + + //数据来源 core 主表 snapshot 镜像表 + private String resourceTable = "core"; + + public DataVisualizationBaseRequest(Long id,String busiFlag,String resource,String source) { + this.busiFlag = busiFlag; + this.resourceTable = resource; + super.setId(id); + this.setSource(source); + } + + public DataVisualizationBaseRequest(Long id,String busiFlag) { + this.busiFlag = busiFlag; + super.setId(id); + } +} diff --git a/backend/src/main/java/com/stdproject/request/StaticResourceRequest.java b/backend/src/main/java/com/stdproject/request/StaticResourceRequest.java new file mode 100644 index 0000000..1d4c30d --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/StaticResourceRequest.java @@ -0,0 +1,12 @@ +package com.stdproject.request; + + +import lombok.Data; + +import java.util.List; + +@Data +public class StaticResourceRequest { + private List resourcePathList; + +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationAppExportRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationAppExportRequest.java new file mode 100644 index 0000000..eed82e8 --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationAppExportRequest.java @@ -0,0 +1,19 @@ +package com.stdproject.request; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +import java.util.List; + +@Data +public class VisualizationAppExportRequest { + @JsonSerialize(using = ToStringSerializer.class) + private Long dvId; + + @JsonSerialize(using = ToStringSerializer.class) + private List viewIds; + + @JsonSerialize(using = ToStringSerializer.class) + private List dsIds; +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationBackgroundRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationBackgroundRequest.java new file mode 100644 index 0000000..7b304aa --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationBackgroundRequest.java @@ -0,0 +1,11 @@ +package com.stdproject.request; + + +import com.stdproject.entity.vo.VisualizationBackgroundVO; + +/** + * @author : WangJiaHao + * @date : 2023/6/12 19:28 + */ +public class VisualizationBackgroundRequest extends VisualizationBackgroundVO { +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationLinkJumpBaseRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationLinkJumpBaseRequest.java new file mode 100644 index 0000000..0da64a2 --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationLinkJumpBaseRequest.java @@ -0,0 +1,42 @@ +package com.stdproject.request; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.gisbi.constant.CommonConstants; +import lombok.Data; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 14:26 + */ +@Data +public class VisualizationLinkJumpBaseRequest { + + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceDvId; + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceViewId; + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceFieldId; + @JsonSerialize(using = ToStringSerializer.class) + private Long targetDvId; + @JsonSerialize(using = ToStringSerializer.class) + private Long targetViewId; + @JsonSerialize(using = ToStringSerializer.class) + private Long linkJumpId; + + private Boolean activeStatus; + + private String resourceTable = CommonConstants.RESOURCE_TABLE.CORE; + + public VisualizationLinkJumpBaseRequest() { + } + + public VisualizationLinkJumpBaseRequest(Long sourceDvId, Long sourceViewId, Long targetDvId, Long targetViewId, Long linkJumpId) { + this.sourceDvId = sourceDvId; + this.sourceViewId = sourceViewId; + this.targetDvId = targetDvId; + this.targetViewId = targetViewId; + this.linkJumpId = linkJumpId; + } +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationLinkageRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationLinkageRequest.java new file mode 100644 index 0000000..88c44c0 --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationLinkageRequest.java @@ -0,0 +1,36 @@ +package com.stdproject.request; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.stdproject.entity.dto.VisualizationLinkageDTO; +import com.stdproject.entity.vo.VisualizationLinkageVO; +import io.gisbi.constant.CommonConstants; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author : WangJiaHao + * @date : 2023/7/13 + */ +@Data +public class VisualizationLinkageRequest extends VisualizationLinkageVO { + + /** + * 仪表板 or 大屏ID + * */ + @JsonSerialize(using = ToStringSerializer.class) + private Long dvId; + @JsonSerialize(using = ToStringSerializer.class) + private Long sourceViewId; + + private Boolean ActiveStatus; + + private List targetViewIds; + + private String resourceTable = CommonConstants.RESOURCE_TABLE.CORE; + + private List linkageInfo = new ArrayList<>(); + +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationStoreRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationStoreRequest.java new file mode 100644 index 0000000..78fae74 --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationStoreRequest.java @@ -0,0 +1,20 @@ +package com.stdproject.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VisualizationStoreRequest implements Serializable { + @Serial + private static final long serialVersionUID = 166667337997303748L; + + private Long id; + + private String type; +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationSubjectRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationSubjectRequest.java new file mode 100644 index 0000000..d316c3f --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationSubjectRequest.java @@ -0,0 +1,11 @@ +package com.stdproject.request; + + +import com.stdproject.entity.vo.VisualizationSubjectVO; + +/** + * @author : WangJiaHao + * @date : 2023/6/9 14:59 + */ +public class VisualizationSubjectRequest extends VisualizationSubjectVO { +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationWatermarkRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationWatermarkRequest.java new file mode 100644 index 0000000..f9b9fbb --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationWatermarkRequest.java @@ -0,0 +1,11 @@ +package com.stdproject.request; + + +import com.stdproject.entity.vo.VisualizationWatermarkVO; + +/** + * @author : WangJiaHao + * @date : 2024/1/10 17:02 + */ +public class VisualizationWatermarkRequest extends VisualizationWatermarkVO { +} diff --git a/backend/src/main/java/com/stdproject/request/VisualizationWorkbranchQueryRequest.java b/backend/src/main/java/com/stdproject/request/VisualizationWorkbranchQueryRequest.java new file mode 100644 index 0000000..1e33358 --- /dev/null +++ b/backend/src/main/java/com/stdproject/request/VisualizationWorkbranchQueryRequest.java @@ -0,0 +1,27 @@ +package com.stdproject.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Schema(description = "分享列表过滤器") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class VisualizationWorkbranchQueryRequest implements Serializable { + @Serial + private static final long serialVersionUID = -3522243514336261778L; + + @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED) + private String type; + @Schema(description = "关键字") + private String keyword; + @Schema(description = "查询来源") + private String queryFrom; + @Schema(description = "是否升序", requiredMode = Schema.RequiredMode.REQUIRED) + private boolean asc = false; +} diff --git a/backend/src/main/java/com/stdproject/response/VisualizationLinkJumpBaseResponse.java b/backend/src/main/java/com/stdproject/response/VisualizationLinkJumpBaseResponse.java new file mode 100644 index 0000000..86b41ec --- /dev/null +++ b/backend/src/main/java/com/stdproject/response/VisualizationLinkJumpBaseResponse.java @@ -0,0 +1,32 @@ +package com.stdproject.response; + + +import com.stdproject.entity.dto.VisualizationLinkJumpInfoDTO; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * @author : WangJiaHao + * @date : 2023/7/18 14:24 + */ +@Data +public class VisualizationLinkJumpBaseResponse { + + // 获取基础的所有映射 + private Map baseJumpInfoMap; + + // 获取仪表板类型映射 + private Map> baseJumpInfoVisualizationMap; + + + public VisualizationLinkJumpBaseResponse(Map baseJumpInfoMap, Map> baseJumpInfoVisualizationMap) { + this.baseJumpInfoMap = baseJumpInfoMap; + this.baseJumpInfoVisualizationMap = baseJumpInfoVisualizationMap; + } + + public VisualizationLinkJumpBaseResponse() { + + } +} diff --git a/backend/src/main/java/com/stdproject/response/VisualizationOuterParamsBaseResponse.java b/backend/src/main/java/com/stdproject/response/VisualizationOuterParamsBaseResponse.java new file mode 100644 index 0000000..9e2ebc6 --- /dev/null +++ b/backend/src/main/java/com/stdproject/response/VisualizationOuterParamsBaseResponse.java @@ -0,0 +1,29 @@ +package com.stdproject.response; + + +import com.stdproject.entity.dto.VisualizationOuterParamsInfoDTO; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * Author: wangjiahao + * Description: + */ +@Data +public class VisualizationOuterParamsBaseResponse { + + // 获取仪表板外部参数映射信息 + private Map> outerParamsInfoMap; + + private Map outerParamsInfoBaseMap; + + public VisualizationOuterParamsBaseResponse(Map> outerParamsInfoMap,Map outerParamsInfoBaseMap) { + this.outerParamsInfoMap = outerParamsInfoMap; + this.outerParamsInfoBaseMap = outerParamsInfoBaseMap; + } + + public VisualizationOuterParamsBaseResponse() { + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/ChartDataBuild.java b/backend/src/main/java/com/stdproject/service/manage/ChartDataBuild.java new file mode 100644 index 0000000..c569a77 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/ChartDataBuild.java @@ -0,0 +1,1819 @@ +package com.stdproject.service.manage; + +import com.stdproject.entity.dto.ScatterChartDataDTO; +import com.stdproject.entity.dto.Series; +import io.gisbi.extensions.view.dto.*; +import io.gisbi.i18n.Lang; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.IDUtils; +import io.gisbi.utils.JsonUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +public class ChartDataBuild { + + private final static String format = "(%s)"; + + // AntV + public static Map transChartDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + if (StringUtils.containsIgnoreCase(view.getType(), "table")) { + for (int i = 0; i < xAxis.size() + yAxis.size(); i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + if (j > -1) { + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + } + dataList.add(axisChartDataDTO); + } + } else { + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + } + } + } + map.put("data", dataList); + return map; + } + + public static Map transHeatMapChartDataAntV(List xAxisBase, List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + List> dataList = new ArrayList<>(); + + if (xAxisBase.size() != 2) { + map.put("data", dataList); + return map; + } + + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + + Map object = JsonUtil.parse((String) JsonUtil.toJSONString(axisChartDataDTO), HashMap.class); + + object.put("x", new BigDecimal(row[0])); + object.put("y", new BigDecimal(row[1])); + + dataList.add(object); + } + + } + map.put("data", dataList); + return map; + } + + public static Map transBaseGroupDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + StringBuilder b = new StringBuilder(); + for (int i = xAxisBase.size(); i < xAxisBase.size() + xAxisExt.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() - 1) { + b.append(row[i]); + } else { + b.append(row[i]).append("\n"); + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(b.toString()); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + + if ("line".equals(view.getType())) { + if (ObjectUtils.isEmpty(xAxisExt)) { + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + } else { + // 多指标只取第一个 + break; + } + } + } + } + map.put("data", dataList); + return map; + } + + // AntV柱状堆叠图 + public static Map transStackChartDataAntV(List xAxisBase, List xAxis, List yAxis, ChartViewDTO view, List data, List extStack, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + + if (ObjectUtils.isNotEmpty(extStack)) { + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + axisChartDataDTO.setCategory(row[xAxisBase.size()]); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int k = 0; k < xAxis.size(); k++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(k).getId()); + chartDimensionDTO.setValue(row[k]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + if (ObjectUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + dataList.add(axisChartDataDTO); + } + } else { + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + dataList.add(axisChartDataDTO); + } + } + } + map.put("data", dataList); + return map; + } + + //AntV scatter + public static Map transScatterDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, List extBubble, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size() + extBubble.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size() + extBubble.size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, ObjectUtils.isNotEmpty(extBubble) ? extSize - 1 : extSize); + // pop + if (ObjectUtils.isNotEmpty(extBubble)) { + try { + axisChartDataDTO.setPopSize(StringUtils.isEmpty(row[2]) ? null : new BigDecimal(row[2])); + ChartQuotaDTO bubbleQuotaDTO = new ChartQuotaDTO(); + bubbleQuotaDTO.setId(extBubble.get(0).getId()); + quotaList.add(bubbleQuotaDTO); + } catch (Exception e) { + axisChartDataDTO.setPopSize(new BigDecimal(0)); + } + } + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + // antv radar + public static Map transRadarChartDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + // antV组合图形 + public static Map transMixChartDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + return transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, false); + } + + public static Map transMixChartDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, ChartViewDTO view, List data, boolean isDrill, boolean isLine) { + + Map map = new HashMap<>(); + + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(y.getChartType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + Set categories = new HashSet<>(); + + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int ii = 0; ii < xAxisBase.size(); ii++) { + if (ii == xAxisBase.size() - 1) { + a.append(d[ii]); + } else { + a.append(d[ii]).append("\n"); + } + } + } + StringBuilder b = new StringBuilder(); + for (int ii = xAxisBase.size(); ii < xAxisBase.size() + xAxisExt.size(); ii++) { + if (ii == xAxisBase.size() + xAxisExt.size() - 1) { + b.append(d[ii]); + } else { + b.append(d[ii]).append("\n"); + } + } + + axisChartDataDTO.setName(a.toString()); + axisChartDataDTO.setField(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + + String category = StringUtils.defaultIfBlank(b.toString(), + StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + + if (isLine) { + if (ObjectUtils.isEmpty(xAxisExt)) { + category = StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName()); + } + } + + axisChartDataDTO.setCategory(category); + categories.add(category); + + buildDynamicValue(view, axisChartDataDTO, d, size, extSize); + series.get(j).getData().add(axisChartDataDTO); + } + } + if (CollectionUtils.isNotEmpty(series)) { + series.get(0).setCategories(categories); + } + + map.put("data", series); + return map; + } + + public static Map transMixChartStackDataAntV(List xAxisBase, List xAxis, List extStack, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + + if (CollectionUtils.isEmpty(extStack)) { + return transMixChartDataAntV(xAxisBase, xAxis, new ArrayList<>(), yAxis, view, data, isDrill); + } + + Map map = new HashMap<>(); + + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(y.getChartType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + Set categories = new HashSet<>(); + + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + String category = row[xAxisBase.size()]; + axisChartDataDTO.setCategory(category); + if (category != null) { + categories.add(category); + } + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int k = 0; k < xAxis.size(); k++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(k).getId()); + chartDimensionDTO.setValue(row[k]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + if (ObjectUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + series.get(0).getData().add(axisChartDataDTO); + } + + if (CollectionUtils.isNotEmpty(series)) { + series.get(0).setCategories(categories); + } + + map.put("data", series); + return map; + } + + // 基础图形 + public static Map transChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + // yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值 + int size = xAxis.size() + yAxis.size(); + int extSize = view.getExtLabel().size() + view.getExtTooltip().size(); + + for (int i = xAxis.size(); i < size - extSize; i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + buildDynamicValue(view, axisChartDataDTO, row, size, extSize); + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + // 组合图形 + public static Map transMixChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(y.getChartType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + StringBuilder a = new StringBuilder(); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + series.get(j).getData().add(axisChartDataDTO); + } + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 文本卡图形 + public static Map transLabelChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + Series series1 = new Series(); + series1.setName(xAxis.get(0).getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + series.get(0).getData().add(a.toString()); + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 常规图形 + public static Map transNormalChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + int j = i - xAxis.size(); + try { + series.get(j).getData().add(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + series.get(j).getData().add(new BigDecimal(0)); + } + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // radar图 + public static Map transRadarChartData(List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + int j = i - xAxis.size(); + try { + series.get(j).getData().add(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + series.get(j).getData().add(new BigDecimal(0)); + } + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 堆叠图 + public static Map transStackChartData(List xAxis, List yAxis, ChartViewDTO view, List data, List extStack, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List stack = new ArrayList<>(); + List series = new ArrayList<>(); + + if (ObjectUtils.isNotEmpty(extStack)) { + AxisChartDataDTO defaultAxisChartDataDTO = new AxisChartDataDTO(); + BigDecimal defaultValue = StringUtils.containsIgnoreCase(view.getType(), "line") ? new BigDecimal(0) : null; + defaultAxisChartDataDTO.setValue(defaultValue); + // 构建横轴 + for (String[] d : data) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + } + x = x.stream().distinct().collect(Collectors.toList()); + // 构建堆叠 + for (String[] d : data) { + stack.add(d[xAxis.size()]); + } + stack = stack.stream().distinct().collect(Collectors.toList()); + for (String s : stack) { + Series series1 = new Series(); + series1.setName(s); + series1.setType(view.getType()); + List list = new ArrayList<>(); + for (int i = 0; i < x.size(); i++) { + list.add(defaultAxisChartDataDTO); + } + series1.setData(list); + series.add(series1); + } + for (Series ss : series) { + for (int i = 0; i < x.size(); i++) { + for (String[] row : data) { + String stackColumn = row[xAxis.size()]; + if (StringUtils.equals(ss.getName(), stackColumn)) { + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int j = 0; j < xAxis.size(); j++) { + if (j == xAxis.size() - 1) { + a.append(row[j]); + } else { + a.append(row[j]).append("\n"); + } + } + } + if (StringUtils.equals(a.toString(), x.get(i))) { + if (row.length > xAxis.size() + extStack.size()) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO(); + + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + + for (int k = 0; k < xAxis.size(); k++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(k).getId()); + chartDimensionDTO.setValue(row[k]); + dimensionList.add(chartDimensionDTO); + } + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(extStack.get(0).getId()); + chartDimensionDTO.setValue(row[xAxis.size()]); + dimensionList.add(chartDimensionDTO); + axisChartDataDTO.setDimensionList(dimensionList); + + String s = row[xAxis.size() + extStack.size()]; + if (StringUtils.isNotEmpty(s)) { + axisChartDataDTO.setValue(new BigDecimal(s)); + ss.getData().set(i, axisChartDataDTO); + } + } + break; + } + } + } + } + } + } else { + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + StringBuilder a = new StringBuilder(); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + series.get(j).getData().add(axisChartDataDTO); + } + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 散点图 + public static Map transScatterData(List xAxis, List yAxis, ChartViewDTO view, List data, List extBubble, boolean isDrill) { + Map map = new HashMap<>(); + + List x = new ArrayList<>(); + List series = new ArrayList<>(); + for (ChartViewFieldDTO y : yAxis) { + Series series1 = new Series(); + series1.setName(y.getName()); + series1.setType(view.getType()); + series1.setData(new ArrayList<>()); + series.add(series1); + } + for (int i1 = 0; i1 < data.size(); i1++) { + String[] d = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } + } + } + x.add(a.toString()); + for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) { + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + ScatterChartDataDTO scatterChartDataDTO = new ScatterChartDataDTO(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(d[j]); + dimensionList.add(chartDimensionDTO); + } + scatterChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + scatterChartDataDTO.setQuotaList(quotaList); + + if (ObjectUtils.isNotEmpty(extBubble) && extBubble.size() > 0) { + try { + scatterChartDataDTO.setValue(new Object[]{ + a.toString(), + StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i]), + StringUtils.isEmpty(d[xAxis.size() + yAxis.size()]) ? null : new BigDecimal(d[xAxis.size() + yAxis.size()]) + }); + } catch (Exception e) { + scatterChartDataDTO.setValue(new Object[]{a.toString(), new BigDecimal(0), new BigDecimal(0)}); + } + } else { + try { + scatterChartDataDTO.setValue(new Object[]{ + a.toString(), + StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i]) + }); + } catch (Exception e) { + scatterChartDataDTO.setValue(new Object[]{a.toString(), new BigDecimal(0)}); + } + } + series.get(j).getData().add(scatterChartDataDTO); + } + } + + map.put("x", x); + map.put("series", series); + return map; + } + + // 表格 + public static Map transTableNormal(List xAxis, List yAxis, ChartViewDTO view, List data, List extStack, Map desensitizationList) { + List fields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xAxis)) { + fields.addAll(xAxis); + } + if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { + if (ObjectUtils.isNotEmpty(extStack)) { + fields.addAll(extStack); + } + } + fields.addAll(yAxis); + return transTableNormal(fields, view, data, desensitizationList); + } + + public static Map transTableNormalWithDetail(List xAxis, List yAxis, List data, List detailFields, List detailData, Map desensitizationList) { + int detailIndex = xAxis.size(); + + List realDetailFields = detailFields.subList(detailIndex, detailFields.size()); + + List fields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xAxis)) + fields.addAll(xAxis); + if (ObjectUtils.isNotEmpty(yAxis)) + fields.addAll(yAxis); + Map map = transTableNormal(fields, null, data, desensitizationList); + List> tableRow = (List>) map.get("tableRow"); + final int xEndIndex = detailIndex; + Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> "(" + StringUtils.join(ArrayUtils.subarray(item, 0, xEndIndex), ")-de-(") + ")")); + + tableRow.forEach(row -> { + String key = xAxis.stream().map(x -> String.format(format, row.get(x.getGisbiName()).toString())).collect(Collectors.joining("-de-")); + List detailFieldValueList = groupDataList.get(key); + List> detailValueMapList = detailFieldValueList.stream().map((detailArr -> { + Map temp = new HashMap<>(); + for (int i = 0; i < realDetailFields.size(); i++) { + ChartViewFieldDTO realDetailField = realDetailFields.get(i); + temp.put(realDetailField.getGisbiName(), detailArr[detailIndex + i]); + } + return temp; + })).collect(Collectors.toList()); + row.put("details", detailValueMapList); + }); + + ChartViewFieldDTO detailFieldDTO = new ChartViewFieldDTO(); + detailFieldDTO.setId(IDUtils.snowID()); + detailFieldDTO.setName("detail"); + detailFieldDTO.setGisbiName("detail"); + fields.add(detailFieldDTO); + map.put("fields", fields); + map.put("detailFields", realDetailFields); + map.put("tableRow", tableRow); + return map; + } + + // 表格 + public static Map transTableNormal(Map> fieldMap, ChartViewDTO view, List data, Map desensitizationList) { + + List fields = new ArrayList<>(); + List yfields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(fieldMap.get("xAxis"))) fields.addAll(fieldMap.get("xAxis")); + if (ObjectUtils.isNotEmpty(fieldMap.get("tooltipAxis"))) { + fieldMap.get("tooltipAxis").forEach(field -> { + Integer deType = field.getDeType(); + if (deType == 2 || deType == 3) { + yfields.add(field); + } else { + fields.add(field); + } + }); + } + if (ObjectUtils.isNotEmpty(fieldMap.get("labelAxis"))) { + fieldMap.get("labelAxis").forEach(field -> { + Integer deType = field.getDeType(); + if (deType == 2 || deType == 3) { + yfields.add(field); + } else { + fields.add(field); + } + }); + } + if (ObjectUtils.isNotEmpty(fieldMap.get("yAxis"))) fields.addAll(fieldMap.get("yAxis")); + if (ObjectUtils.isNotEmpty(yfields)) fields.addAll(yfields); + return transTableNormal(fields, view, data, desensitizationList); + } + + public static String desensitizationValue(ColumnPermissionItem columnPermissionItem, String originStr) { + String desensitizationStr = ""; + if (!columnPermissionItem.getDesensitizationRule().getBuiltInRule().toString().equalsIgnoreCase("custom")) { + switch (columnPermissionItem.getDesensitizationRule().getBuiltInRule()) { + case CompleteDesensitization: + desensitizationStr = ColumnPermissionItem.CompleteDesensitization; + break; + case KeepMiddleThreeCharacters: + if (StringUtils.isEmpty(originStr) || originStr.length() < 4) { + desensitizationStr = ColumnPermissionItem.KeepMiddleThreeCharacters; + } else { + desensitizationStr = "***" + StringUtils.substring(originStr, originStr.length() / 2 - 1, originStr.length() / 2 + 2) + "***"; + } + break; + case KeepFirstAndLastThreeCharacters: + if (StringUtils.isEmpty(originStr) || originStr.length() < 7) { + desensitizationStr = ColumnPermissionItem.KeepFirstAndLastThreeCharacters; + } else { + desensitizationStr = StringUtils.substring(originStr, 0, 3) + "***" + StringUtils.substring(originStr, originStr.length() - 3, originStr.length()); + } + break; + default: + break; + + } + } else { + switch (columnPermissionItem.getDesensitizationRule().getCustomBuiltInRule()) { + case RetainBeforeMAndAfterN: + if (StringUtils.isEmpty(originStr) || originStr.length() < columnPermissionItem.getDesensitizationRule().getM() + columnPermissionItem.getDesensitizationRule().getN()) { + desensitizationStr = String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getM(), "X")) + "***" + String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getN(), "X")); + } else { + desensitizationStr = StringUtils.substring(originStr, 0, columnPermissionItem.getDesensitizationRule().getM()) + "***" + StringUtils.substring(originStr, originStr.length() - columnPermissionItem.getDesensitizationRule().getN(), originStr.length()); + } + break; + case RetainMToN: + if (columnPermissionItem.getDesensitizationRule().getM() > columnPermissionItem.getDesensitizationRule().getN()) { + desensitizationStr = "*** ***"; + break; + } + if (StringUtils.isEmpty(originStr) || originStr.length() < columnPermissionItem.getDesensitizationRule().getM()) { + desensitizationStr = "*** ***"; + break; + } + if (columnPermissionItem.getDesensitizationRule().getM() == 1) { + desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***"; + break; + } else { + desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***"; + break; + } + default: + break; + + } + } + return desensitizationStr; + } + + public static Map transTableNormal(List fields, ChartViewDTO view, List data, Map desensitizationList) { + Map map = new TreeMap<>(); + List> tableRow = new ArrayList<>(); + data.forEach(ele -> { + Map d = new HashMap<>(); + for (int i = 0; i < fields.size(); i++) { + if (ObjectUtils.isNotEmpty(desensitizationList.keySet()) && desensitizationList.containsKey(fields.get(i).getGisbiName())) { + String desensitizationValue = desensitizationValue(desensitizationList.get(fields.get(i).getGisbiName()), String.valueOf(ele[i])); + ele[i] = desensitizationValue; + d.put(fields.get(i).getGisbiName(), desensitizationValue); + continue; + } + if (i == ele.length) break; + ChartViewFieldDTO chartViewFieldDTO = fields.get(i); + if (chartViewFieldDTO.getDeType() == 0 || chartViewFieldDTO.getDeType() == 1 || chartViewFieldDTO.getDeType() == 5 || chartViewFieldDTO.getDeType() == 7) { + d.put(fields.get(i).getGisbiName(), StringUtils.isEmpty(ele[i]) ? "" : ele[i]); + } else if (chartViewFieldDTO.getDeType() == 2 || chartViewFieldDTO.getDeType() == 3 || chartViewFieldDTO.getDeType() == 4) { + if (view.getIsExcelExport()) { + d.put(fields.get(i).getGisbiName(), StringUtils.isEmpty(ele[i]) ? "" : ele[i]); + } else { + d.put(fields.get(i).getGisbiName(), StringUtils.isEmpty(ele[i]) ? null : new BigDecimal(ele[i]).setScale(8, RoundingMode.HALF_UP)); + } + } + } + tableRow.add(d); + }); + map.put("fields", fields); + map.put("tableRow", tableRow); + return map; + } + + public static Map transGroupStackDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, List extStack, List data, ChartViewDTO view, boolean isDrill) { + // 堆叠柱状图 + if (ObjectUtils.isEmpty(xAxisExt)) { + return transStackChartDataAntV(xAxisBase, xAxis, yAxis, view, data, extStack, isDrill); + // 分组柱状图 + } else if (ObjectUtils.isNotEmpty(xAxisExt) && ObjectUtils.isEmpty(extStack)) { + return transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill); + // 分组堆叠柱状图 + } else { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder xField = new StringBuilder(); + if (isDrill) { + xField.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + xField.append(row[i]); + } else { + xField.append(row[i]).append("\n"); + } + } + } + + StringBuilder groupField = new StringBuilder(); + for (int i = xAxisBase.size(); i < xAxisBase.size() + xAxisExt.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() - 1) { + groupField.append(row[i]); + } else { + groupField.append(row[i]).append("\n"); + } + } + + StringBuilder stackField = new StringBuilder(); + for (int i = xAxisBase.size() + xAxisExt.size(); i < xAxisBase.size() + xAxisExt.size() + extStack.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() + extStack.size() - 1) { + stackField.append(row[i]); + } else { + stackField.append(row[i]).append("\n"); + } + } + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(xField.toString()); + axisChartDataDTO.setName(xField.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + + axisChartDataDTO.setDimensionList(dimensionList); + + if (ObjectUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setGroup(groupField.toString()); + axisChartDataDTO.setCategory(stackField.toString()); + dataList.add(axisChartDataDTO); + } + map.put("data", dataList); + return map; + } + } + + // 计算动态标签和提示 + private static void buildDynamicValue(ChartViewDTO view, AxisChartDataAntVDTO axisChartDataDTO, String[] row, int size, int extSize) { + List dynamicLabelValue = new ArrayList<>(); + List dynamicTooltipValue = new ArrayList<>(); + // 计算动态标签和提示 + if (ObjectUtils.isNotEmpty(view.getExtLabel())) { + for (int ii = 0; ii < view.getExtLabel().size(); ii++) { + DynamicValueDTO valueDTO = new DynamicValueDTO(); + ChartViewFieldDTO chartViewFieldDTO = view.getExtLabel().get(ii); + BigDecimal value = StringUtils.isEmpty(row[ii + (size - extSize)]) ? null : new BigDecimal(row[ii + (size - extSize)]); + valueDTO.setFieldId(chartViewFieldDTO.getId()); + valueDTO.setValue(value); + dynamicLabelValue.add(valueDTO); + } + } + if (ObjectUtils.isNotEmpty(view.getExtTooltip())) { + for (int ii = 0; ii < view.getExtTooltip().size(); ii++) { + DynamicValueDTO valueDTO = new DynamicValueDTO(); + ChartViewFieldDTO chartViewFieldDTO = view.getExtTooltip().get(ii); + BigDecimal value = StringUtils.isEmpty(row[ii + (size - extSize) + view.getExtLabel().size()]) ? null : new BigDecimal(row[ii + (size - extSize) + view.getExtLabel().size()]); + valueDTO.setFieldId(chartViewFieldDTO.getId()); + valueDTO.setValue(value); + dynamicTooltipValue.add(valueDTO); + } + } + + axisChartDataDTO.setDynamicLabelValue(dynamicLabelValue); + axisChartDataDTO.setDynamicTooltipValue(dynamicTooltipValue); + } + + //AntV quadrant + public static Map transQuadrantDataAntV(List xAxis, List yAxis, ChartViewDTO view, List data, List extBubble, boolean isDrill) { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder a = new StringBuilder(); + if (isDrill) { + a.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(row[i]); + } else { + a.append(row[i]).append("\n"); + } + } + } + for (int i = 0; i < xAxis.size() + yAxis.size(); i++) { + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(a.toString()); + axisChartDataDTO.setName(a.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + int j = i - xAxis.size(); + if (j > -1) { + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(j).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i])); + axisChartDataDTO.setField(yAxis.get(j).getOriginName()); + axisChartDataDTO.setName(yAxis.get(j).getName()); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName())); + } + dataList.add(axisChartDataDTO); + } + } + map.put("data", dataList); + return map; + } + + public static Map transBarRangeDataAntV(boolean skipBarRange, boolean isDate, List xAxisBase, List xAxis, List yAxis, ChartViewDTO view, List data, boolean isDrill) { + + Map map = new HashMap<>(); + if (skipBarRange) { + map.put("data", new ArrayList<>()); + return map; + } + + List dates = new ArrayList<>(); + List numbers = new ArrayList<>(); + + ChartViewFieldDTO dateAxis1 = null; + + SimpleDateFormat sdf = null; + if (isDate) { + if (BooleanUtils.isTrue(view.getAggregate())) { + dateAxis1 = yAxis.get(0); + } else { + dateAxis1 = xAxis.get(xAxisBase.size()); + } + sdf = new SimpleDateFormat(getDateFormat(dateAxis1.getDateStyle(), dateAxis1.getDatePattern())); + } + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder xField = new StringBuilder(); + if (isDrill) { + xField.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + xField.append(row[i]); + } else { + xField.append(row[i]).append("\n"); + } + } + } + + + Map obj = new HashMap<>(); + obj.put("field", xField.toString()); + obj.put("category", xField.toString()); + + List dimensionList = new ArrayList<>(); + + for (int i = 0; i < xAxisBase.size(); i++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(i).getId()); + chartDimensionDTO.setValue(row[i]); + dimensionList.add(chartDimensionDTO); + } + if (isDrill) { + int index = xAxis.size() - 1; + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(index).getId()); + chartDimensionDTO.setValue(row[index]); + dimensionList.add(chartDimensionDTO); + } + obj.put("dimensionList", dimensionList); + + + List values = new ArrayList<>(); + + if (row[xAxisBase.size()] == null || row[xAxisBase.size() + 1] == null) { + continue; + } + + if (isDate) { + int index; + if (BooleanUtils.isTrue(view.getAggregate())) { + index = xAxis.size(); + } else { + index = xAxisBase.size(); + } + + values.add(row[index]); + values.add(row[index + 1]); + obj.put("values", values); + Date date1 = null, date2 = null; + try { + date1 = sdf.parse(row[index]); + if (date1 != null) { + dates.add(date1); + } + } catch (Exception ignore) { + } + try { + date2 = sdf.parse(row[index + 1]); + if (date2 != null) { + dates.add(date2); + } + } catch (Exception ignore) { + } + //间隔时间 + obj.put("gap", getTimeGap(date1, date2, dateAxis1.getDateStyle())); + + } else { + values.add(new BigDecimal(row[xAxis.size()])); + values.add(new BigDecimal(row[xAxis.size() + 1])); + obj.put("values", values); + + numbers.add(new BigDecimal(row[xAxis.size()])); + numbers.add(new BigDecimal(row[xAxis.size() + 1])); + + //间隔差 + obj.put("gap", new BigDecimal(row[xAxis.size() + 1]).subtract(new BigDecimal(row[xAxis.size()]))); + } + + dataList.add(obj); + } + + if (isDate) { + Date minDate = dates.stream().min(Date::compareTo).orElse(null); + if (minDate != null) { + map.put("minTime", sdf.format(minDate)); + } + Date maxDate = dates.stream().max(Date::compareTo).orElse(null); + if (maxDate != null) { + map.put("maxTime", sdf.format(maxDate)); + } + } else { + map.put("min", numbers.stream().min(BigDecimal::compareTo).orElse(null)); + map.put("max", numbers.stream().max(BigDecimal::compareTo).orElse(null)); + } + + map.put("isDate", isDate); + map.put("data", dataList); + return map; + + } + + private static String getDateFormat(String dateStyle, String datePattern) { + String split; + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + split = "/"; + } else { + split = "-"; + } + switch (dateStyle) { + case "y": + return "yyyy"; + case "y_M": + return "yyyy" + split + "MM"; + case "y_M_d": + return "yyyy" + split + "MM" + split + "dd"; + case "M_d": + return "MM" + split + "dd"; + case "H_m_s": + return "HH:mm:ss"; + case "y_M_d_H": + return "yyyy" + split + "MM" + split + "dd" + " HH"; + case "y_M_d_H_m": + return "yyyy" + split + "MM" + split + "dd" + " HH:mm"; + case "y_M_d_H_m_s": + return "yyyy" + split + "MM" + split + "dd" + " HH:mm:ss"; + default: + return "yyyy-MM-dd HH:mm:ss"; + } + } + + private static String getTimeGap(Date from, Date to, String dateStyle) { + if (from == null || to == null) { + return ""; + } + Calendar fromCalender = Calendar.getInstance(); + fromCalender.setTime(from); + + Calendar toCalender = Calendar.getInstance(); + toCalender.setTime(to); + + long yearGap = 0; + long monthGap = 0; + long dayGap = (toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 3600 * 24); + long hourGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 3600)) % 24; + long minuteGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / (1000 * 60)) % 60; + long secondGap = ((toCalender.getTimeInMillis() - fromCalender.getTimeInMillis()) / 1000) % 60; + + String language = "zh-CN"; //国际化 + Lang lang = Lang.getLangWithoutDefault(language); + boolean isEnUs = Lang.en_US.equals(lang); + String splitter = isEnUs ? " " : ""; + + String yearGapStr = ""; + String monthGapStr = ""; + + String dayGapStr = ""; + if (dayGap != 0) { + dayGapStr = dayGap + splitter + Translator.get("i18n_day") + (isEnUs && dayGap != 1 ? "s" : ""); + } + String hourGapStr = ""; + if (hourGap != 0) { + hourGapStr = hourGap + splitter + Translator.get("i18n_hour") + (isEnUs && hourGap != 1 ? "s" : ""); + } + String minuteGapStr = ""; + if (minuteGap != 0) { + minuteGapStr = minuteGap + splitter + Translator.get("i18n_minute") + (isEnUs && minuteGap != 1 ? "s" : ""); + } + String secondGapStr = ""; + if (secondGap != 0) { + secondGapStr = secondGap + splitter + Translator.get("i18n_second") + (isEnUs && secondGap != 1 ? "s" : ""); + } + + List list = new ArrayList<>(); + + switch (dateStyle) { + case "y": + yearGap = toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR); + yearGapStr = yearGap == 0 ? "" : (yearGap + splitter + Translator.get("i18n_year") + (isEnUs && yearGap != 1 ? "s" : "")); + return yearGapStr; + case "y_M": + yearGap = ((toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR)) * 12L + (toCalender.get(Calendar.MONTH) - fromCalender.get(Calendar.MONTH))) / 12; + monthGap = ((toCalender.get(Calendar.YEAR) - fromCalender.get(Calendar.YEAR)) * 12L + (toCalender.get(Calendar.MONTH) - fromCalender.get(Calendar.MONTH))) % 12; + + yearGapStr = yearGap == 0 ? "" : (yearGap + splitter + Translator.get("i18n_year") + (isEnUs && yearGap != 1 ? "s" : "")); + monthGapStr = monthGap == 0 ? "" : (monthGap + splitter + Translator.get("i18n_month") + (isEnUs && monthGap != 1 ? "s" : "")); + + if (!yearGapStr.isEmpty()) { + list.add(yearGapStr); + } + if (!monthGapStr.isEmpty()) { + list.add(monthGapStr); + } + return StringUtils.join(list, splitter); + case "y_M_d": + case "M_d": + return dayGapStr; + case "y_M_d_H": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + return StringUtils.join(list, splitter); + case "y_M_d_H_m": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + if (!minuteGapStr.isEmpty()) { + list.add(minuteGapStr); + } + return StringUtils.join(list, splitter); + case "H_m_s": + case "y_M_d_H_m_s": + if (!dayGapStr.isEmpty()) { + list.add(dayGapStr); + } + if (!hourGapStr.isEmpty()) { + list.add(hourGapStr); + } + if (!minuteGapStr.isEmpty()) { + list.add(minuteGapStr); + } + if (!secondGapStr.isEmpty()) { + list.add(secondGapStr); + } + return StringUtils.join(list, splitter); + default: + return ""; + } + } + + public static Map transSymbolicMapNormalWithDetail(ChartViewDTO view, List xAxis, List yAxis, List extBubble, List data, List detailFields, List detailData) { + int detailIndex = xAxis.size(); + + List realDetailFields = detailFields.subList(detailIndex, detailFields.size()); + + List fields = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xAxis)) + fields.addAll(xAxis); + if (ObjectUtils.isNotEmpty(extBubble)) + fields.addAll(extBubble); + if (ObjectUtils.isNotEmpty(yAxis)) + fields.addAll(yAxis); + Map map = transTableNormal(fields, view, data, new HashMap<>()); + List> tableRow = (List>) map.get("tableRow"); + final int xEndIndex = detailIndex; + Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> "(" + StringUtils.join(ArrayUtils.subarray(item, 0, xEndIndex), ")-de-(") + ")")); + String extBubblegisbiName = ObjectUtils.isNotEmpty(extBubble) ? extBubble.get(0).getGisbiName() : ""; + tableRow.forEach(row -> { + BigDecimal rowValue = row.get(extBubblegisbiName) == null ? BigDecimal.ZERO : new BigDecimal(row.get(extBubblegisbiName).toString()); + String key = xAxis.stream().map(x -> String.format(format, row.get(x.getGisbiName()).toString())).collect(Collectors.joining("-de-")); + List detailFieldValueList = groupDataList.get(key); + List> detailValueMapList = Optional.ofNullable(detailFieldValueList).orElse(new ArrayList<>()).stream().map((detailArr -> { + Map temp = new HashMap<>(); + for (int i = 0; i < realDetailFields.size(); i++) { + ChartViewFieldDTO realDetailField = realDetailFields.get(i); + if (StringUtils.equalsIgnoreCase(extBubblegisbiName, realDetailField.getGisbiName())) { + temp.put(realDetailField.getGisbiName(), rowValue); + } else { + temp.put(realDetailField.getGisbiName(), detailArr[detailIndex + i]); + } + } + return temp; + })).collect(Collectors.toList()); + //详情只要一个 + row.put("details", !detailValueMapList.isEmpty() ? Collections.singletonList(detailValueMapList.getFirst()) : detailValueMapList); + }); + // 先过滤掉所有记录数字段 + List filterCountAxis = fields.stream() + .filter(item -> !StringUtils.equalsIgnoreCase(item.getGisbiName(), "*")) + .collect(Collectors.toList()); + // 如果气泡大小是记录数,添加到字段列表中 + if (ObjectUtils.isNotEmpty(extBubble) && "*".equals(extBubble.get(0).getGisbiName())) { + filterCountAxis.addAll(yAxis); + } + map.put("fields", filterCountAxis); + map.put("detailFields", realDetailFields); + map.put("tableRow", tableRow); + return map; + } + +} diff --git a/backend/src/main/java/com/stdproject/service/manage/ChartDataManage.java b/backend/src/main/java/com/stdproject/service/manage/ChartDataManage.java new file mode 100644 index 0000000..9efbf12 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/ChartDataManage.java @@ -0,0 +1,867 @@ +package com.stdproject.service.manage; + +import com.stdproject.constant.ChartConstants; +import com.stdproject.entity.dto.DataSetRowPermissionsTreeDTO; +import com.stdproject.entity.union.DatasetGroupInfoDTO; +import com.stdproject.service.provider.SQLProvider; +import com.stdproject.utils.DatasetUtils; +import com.stdproject.utils.SqlUtils; +import com.stdproject.utils.Utils; +import com.stdproject.utils.trans.*; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceRequest; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.factory.ProviderFactory; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.provider.Provider; +import io.gisbi.extensions.view.dto.*; +import io.gisbi.extensions.view.factory.PluginsChartFactory; +import io.gisbi.extensions.view.filter.FilterTreeObj; +import io.gisbi.extensions.view.plugin.AbstractChartPlugin; +import io.gisbi.extensions.view.util.FieldUtil; +import io.gisbi.i18n.Translator; +import io.gisbi.result.ResultCode; +import io.gisbi.utils.AuthUtils; +import io.gisbi.utils.BeanUtils; +import jakarta.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Component +public class ChartDataManage { + @Resource + private DatasetTableFieldManage datasetTableFieldManage; + @Resource + private DatasetGroupManage datasetGroupManage; + @Resource + private DatasetSQLManage datasetSQLManage; + @Resource + private ChartViewManege chartViewManege; + + @Resource + private ChartHandlerManager chartHandlerManager; + + @Resource + private ChartFilterTreeService chartFilterTreeService; + + @Autowired(required = false) + private PluginManageApi pluginManage; + + 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) { + chartExtRequest = new ChartExtRequest(); + } + + if (ObjectUtils.isEmpty(view)) { + DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_chart_delete")); + } + if (ObjectUtils.isNotEmpty(AuthUtils.getUser())) { + chartExtRequest.setUser(AuthUtils.getUser().getUserId()); + } + if (view.getChartExtRequest() == null) { + view.setChartExtRequest(chartExtRequest); + } + + //excel导出,如果是从仪表板获取图表数据,则仪表板的查询模式,查询结果的数量,覆盖图表对应的属性 + if (view.getIsExcelExport()) { + view.setResultMode(ChartConstants.VIEW_RESULT_MODE.CUSTOM); + } else if (ChartConstants.VIEW_RESULT_MODE.CUSTOM.equals(chartExtRequest.getResultMode())) { + view.setResultMode(chartExtRequest.getResultMode()); + view.setResultCount(chartExtRequest.getResultCount()); + } + + AbstractChartPlugin chartHandler; + if (BooleanUtils.isTrue(view.getIsPlugin())) { + chartHandler = PluginsChartFactory.getInstance(view.getRender(), view.getType()); + } else { + chartHandler = chartHandlerManager.getChartHandler(view.getRender(), view.getType()); + } + if (chartHandler == null) { + DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_chart_not_handler") + ": " + view.getRender() + "," + view.getType()); + } + + var dillAxis = new ArrayList(); + DatasetGroupInfoDTO table = datasetGroupManage.getDatasetGroupInfoDTO(view.getTableId(), null); + if (table == null) { + DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_no_ds")); + } + + List allFields = getAllChartFields(view); + // column permission + Map desensitizationList = new HashMap<>(); + List columnPermissionFields = transFields(allFields); + // row permission 默认不过滤用户组织数据权限,后续完善 + List rowPermissionsTree = new ArrayList(); + //将没有权限的列删掉 + List gisbiNames = columnPermissionFields.stream().map(DatasetTableFieldDTO::getGisbiName).collect(Collectors.toList()); + //计数字段 + gisbiNames.add("*"); + AxisFormatResult formatResult = chartHandler.formatAxis(view); + formatResult.getContext().put("dataset", table); + formatResult.getContext().put("desensitizationList", desensitizationList); + var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis); + var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis); + formatResult.getContext().put("allFields", allFields); + var axisMap = formatResult.getAxisMap(); + axisMap.forEach((axis, fields) -> { + fields.removeIf(fieldDTO -> !gisbiNames.contains(fieldDTO.getGisbiName())); + }); + + // 过滤来自仪表板的条件 + List extFilterList = new ArrayList<>(); + //组件过滤条件 + List sqlVariables = datasetGroupManage.getSqlParams(Collections.singletonList(view.getTableId())); + if (ObjectUtils.isNotEmpty(chartExtRequest.getFilter())) { + for (ChartExtFilterDTO request : chartExtRequest.getFilter()) { + // 解析多个fieldId,fieldId是一个逗号分隔的字符串 + String fieldId = request.getFieldId(); + if (request.getIsTree() == null) { + request.setIsTree(false); + } + + boolean hasParameters = false; + if (CollectionUtils.isNotEmpty(sqlVariables)) { + for (SqlVariableDetails parameter : Optional.ofNullable(request.getParameters()).orElse(new ArrayList<>())) { + String parameterId = StringUtils.endsWith(parameter.getId(), START_END_SEPARATOR) ? parameter.getId().split(START_END_SEPARATOR)[0] : parameter.getId(); + if (sqlVariables.stream().map(SqlVariableDetails::getId).collect(Collectors.toList()).contains(parameterId)) { + hasParameters = true; + } + } + } + + if (hasParameters) { + continue; + } + + if (StringUtils.isNotEmpty(fieldId)) { + List fieldIds = Arrays.stream(fieldId.split(",")).map(Long::valueOf).collect(Collectors.toList()); + + if (request.getIsTree()) { + ChartExtFilterDTO filterRequest = new ChartExtFilterDTO(); + BeanUtils.copyBean(filterRequest, request); + filterRequest.setFilterType(0); + filterRequest.setDatasetTableFieldList(new ArrayList<>()); + for (Long fId : fieldIds) { + DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(fId); + if (datasetTableField == null) { + continue; + } + if (Objects.equals(datasetTableField.getDatasetGroupId(), view.getTableId())) { + if (ObjectUtils.isNotEmpty(filterRequest.getViewIds())) { + if (filterRequest.getViewIds().contains(view.getId())) { + filterRequest.getDatasetTableFieldList().add(datasetTableField); + } + } else { + filterRequest.getDatasetTableFieldList().add(datasetTableField); + } + } + } + if (ObjectUtils.isNotEmpty(filterRequest.getDatasetTableFieldList())) { + extFilterList.add(filterRequest); + } + } else { + for (Long fId : fieldIds) { + ChartExtFilterDTO filterRequest = new ChartExtFilterDTO(); + BeanUtils.copyBean(filterRequest, request); + filterRequest.setFilterType(0); + filterRequest.setFieldId(fId + ""); + + DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(fId); + if (datasetTableField == null) { + continue; + } + filterRequest.setDatasetTableField(datasetTableField); + if (Objects.equals(datasetTableField.getDatasetGroupId(), view.getTableId())) { + if (ObjectUtils.isNotEmpty(filterRequest.getViewIds())) { + if (filterRequest.getViewIds().contains(view.getId())) { + extFilterList.add(filterRequest); + } + } else { + extFilterList.add(filterRequest); + } + } + } + } + } + } + } + + List filters = new ArrayList<>(); + FilterTreeObj customLinkageFilter = null; + // 联动条件 + if (ObjectUtils.isNotEmpty(chartExtRequest.getLinkageFilters())) { + for (ChartExtFilterDTO linkageFilter : chartExtRequest.getLinkageFilters()) { + if (3 == linkageFilter.getFilterType()) { + customLinkageFilter = linkageFilter.getCustomFilter(); + } else { + filters.add(linkageFilter); + } + } + } + // 外部参数条件 + if (ObjectUtils.isNotEmpty(chartExtRequest.getOuterParamsFilters())) { + filters.addAll(chartExtRequest.getOuterParamsFilters()); + } + + // web参数条件 + if (ObjectUtils.isNotEmpty(chartExtRequest.getWebParamsFilters())) { + filters.addAll(chartExtRequest.getWebParamsFilters()); + } + + + //联动过滤条件和外部参数过滤条件全部加上 + if (ObjectUtils.isNotEmpty(filters)) { + for (ChartExtFilterDTO request : filters) { + // 包含 DE 的为数据集参数 + if (request.getFieldId().contains("DE")) { + // 组装sql 参数原始数据 + if (CollectionUtils.isNotEmpty(sqlVariables)) { + for (SqlVariableDetails sourceVariables : sqlVariables) { + if (sourceVariables.getId().equals(request.getFieldId())) { + if (CollectionUtils.isEmpty(request.getParameters())) { + request.setParameters(new ArrayList<>()); + } + request.getParameters().add(sourceVariables); + } + } + + } + } else { + DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(Long.valueOf(request.getFieldId())); + request.setDatasetTableField(datasetTableField); + request.setFilterType(2); + // 相同数据集 + if (Objects.equals(datasetTableField.getDatasetGroupId(), view.getTableId())) { + if (ObjectUtils.isNotEmpty(request.getViewIds())) { + if (request.getViewIds().contains(view.getId())) { + extFilterList.add(request); + } + } else { + extFilterList.add(request); + } + } + + } + } + } + + // 下钻 + List drillRequestList = chartExtRequest.getDrill(); + var drill = formatResult.getAxisMap().get(ChartAxis.drill); + if (ObjectUtils.isNotEmpty(drillRequestList) && (drill.size() > drillRequestList.size())) { + var fields = xAxis.stream().map(ChartViewFieldDTO::getId).collect(Collectors.toSet()); + for (int i = 0; i < drillRequestList.size(); i++) { + ChartDrillRequest request = drillRequestList.get(i); + for (ChartDimensionDTO dim : request.getDimensionList()) { + ChartViewFieldDTO viewField = drill.get(i); + // 将钻取值作为条件传递,将所有钻取字段作为xAxis并加上下一个钻取字段 + if (Objects.equals(dim.getId(), viewField.getId())) { + DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(dim.getId()); + ChartViewFieldDTO d = new ChartViewFieldDTO(); + BeanUtils.copyBean(d, datasetTableField); + + ChartExtFilterDTO drillFilter = new ChartExtFilterDTO(); + drillFilter.setFieldId(String.valueOf(dim.getId())); + drillFilter.setDatasetTableField(datasetTableField); + drillFilter.setDatePattern(viewField.getDatePattern()); + drillFilter.setDateStyle(viewField.getDateStyle()); + drillFilter.setFilterType(1); + if (datasetTableField.getDeType() == 1) { + drillFilter.setOperator("between"); + drillFilter.setOriginValue(Collections.singletonList(dim.getValue())); + // 把value类似过滤组件处理,获得start time和end time + Map stringLongMap = Utils.parseDateTimeValue(dim.getValue()); + drillFilter.setValue(Arrays.asList(String.valueOf(stringLongMap.get("startTime")), String.valueOf(stringLongMap.get("endTime")))); + } else { + drillFilter.setOperator("in"); + drillFilter.setValue(Collections.singletonList(dim.getValue())); + } + extFilterList.add(drillFilter); + + if (!fields.contains(dim.getId())) { + viewField.setSource(FieldSource.DRILL); + xAxis.add(viewField); + dillAxis.add(viewField); + fields.add(dim.getId()); + } + if (i == drillRequestList.size() - 1) { + ChartViewFieldDTO nextDrillField = drill.get(i + 1); + if (!fields.contains(nextDrillField.getId())) { + nextDrillField.setSource(FieldSource.DRILL); + xAxis.add(nextDrillField); + dillAxis.add(nextDrillField); + fields.add(nextDrillField.getId()); + } else { + Optional axis = xAxis.stream().filter(x -> Objects.equals(x.getId(), nextDrillField.getId())).findFirst(); + axis.ifPresent(field -> { + field.setSort(nextDrillField.getSort()); + field.setCustomSort(nextDrillField.getCustomSort()); + }); + dillAxis.add(nextDrillField); + } + } + } + } + } + } + + formatResult.getContext().put("dillAxis", dillAxis); + + //转义特殊字符 + extFilterList = extFilterList.stream().peek(ele -> { + if (ObjectUtils.isNotEmpty(ele.getValue())) { + List collect = ele.getValue().stream().map(SqlUtils::transKeyword).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(ele.getOriginValue())) { + ele.setOriginValue(ele.getValue()); + } + ele.setValue(collect); + } + }).collect(Collectors.toList()); + // 视图自定义过滤逻辑 + CustomFilterResult filterResult = chartHandler.customFilter(view, extFilterList, formatResult); + + if (ObjectUtils.isEmpty(xAxis) && ObjectUtils.isEmpty(yAxis)) { + return emptyChartViewDTO(view); + } + // 字段过滤器 + FilterTreeObj fieldCustomFilter = view.getCustomFilter(); + // 指标表联动时 使用的CustomFilter + if (customLinkageFilter != null) { + fieldCustomFilter = customLinkageFilter; + } + chartFilterTreeService.searchFieldAndSet(fieldCustomFilter); + fieldCustomFilter = chartFilterTreeService.charReplace(fieldCustomFilter); + // 获取dsMap,union sql + Map sqlMap = datasetSQLManage.getUnionSQLForEdit(table, chartExtRequest); + String sql = (String) sqlMap.get("sql"); + Map dsMap = (Map) sqlMap.get("dsMap"); + boolean crossDs = table.getIsCross(); + if (!crossDs) { + sql = Utils.replaceSchemaAlias(sql, dsMap); + } + + if (ObjectUtils.isEmpty(dsMap)) { + DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_datasource_delete")); + } + for (Map.Entry next : dsMap.entrySet()) { + DatasourceSchemaDTO ds = next.getValue(); + if (StringUtils.isNotEmpty(ds.getStatus()) && "Error".equalsIgnoreCase(ds.getStatus())) { + DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_invalid_ds")); + } + } + + Provider provider; + if (crossDs) { + provider = ProviderFactory.getDefaultProvider(); + } else { + provider = ProviderFactory.getProvider(dsMap.entrySet().iterator().next().getValue().getType()); + } + + if (ObjectUtils.isEmpty(view.getCalParams())) { + view.setCalParams(Utils.getParams(transFields(allFields))); + } + + SQLMeta sqlMeta = new SQLMeta(); + Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); + CustomWhere2Str.customWhere2sqlObj(sqlMeta, fieldCustomFilter, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); + ExtWhere2Str.extWhere2sqlOjb(sqlMeta, extFilterList, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); + WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); + // TODO 數據源插件化之後放到插件裡面組裝SQL + if (BooleanUtils.isTrue(view.getIsPlugin())) { + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + boolean needOrder = Utils.isNeedOrder(dsList); + Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage); + Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage); + String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view); + querySql = provider.rebuildSQL(querySql, sqlMeta, crossDs, dsMap); + filterResult.getContext().put("querySql", querySql); + } + + ChartCalcDataResult calcResult = chartHandler.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider); + return chartHandler.buildChart(view, calcResult, formatResult, filterResult); + } + + private List getSizeField(ChartViewDTO view) throws Exception { + List list = new ArrayList<>(); + Map customAttr = view.getCustomAttr(); + + Map size = (Map) customAttr.get("misc"); + + ChartViewFieldDTO gaugeMinViewField = getDynamicField(size, "gaugeMinType", "gaugeMinField"); + if (gaugeMinViewField != null) { + list.add(gaugeMinViewField); + } + ChartViewFieldDTO gaugeMaxViewField = getDynamicField(size, "gaugeMaxType", "gaugeMaxField"); + if (gaugeMaxViewField != null) { + list.add(gaugeMaxViewField); + } + ChartViewFieldDTO liquidMaxViewField = getDynamicField(size, "liquidMaxType", "liquidMaxField"); + if (liquidMaxViewField != null) { + list.add(liquidMaxViewField); + } + + return list; + } + + private ChartViewFieldDTO getDynamicField(Map sizeObj, String type, String field) { + String maxType = (String) sizeObj.get(type); + if (StringUtils.equalsIgnoreCase("dynamic", maxType)) { + Map maxField = (Map) sizeObj.get(field); + Long id = Long.valueOf((String) maxField.get("id")); + String summary = (String) maxField.get("summary"); + DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(id); + if (ObjectUtils.isNotEmpty(datasetTableField)) { + if (datasetTableField.getDeType() == 0 || datasetTableField.getDeType() == 1 || datasetTableField.getDeType() == 5) { + if (!StringUtils.containsIgnoreCase(summary, "count")) { + DEException.throwException(Translator.get("i18n_gauge_field_change")); + } + } + ChartViewFieldDTO dto = new ChartViewFieldDTO(); + BeanUtils.copyBean(dto, datasetTableField); + dto.setSummary(summary); + return dto; + } else { + DEException.throwException(Translator.get("i18n_gauge_field_delete")); + } + } + return null; + } + + private ChartViewDTO emptyChartViewDTO(ChartViewDTO view) { + ChartViewDTO dto = new ChartViewDTO(); + BeanUtils.copyBean(dto, view); + return dto; + } + + private String getDrillSort(List xAxis, ChartViewFieldDTO field) { + String res = ""; + for (ChartViewFieldDTO f : xAxis) { + if (Objects.equals(f.getId(), field.getId())) { + if (StringUtils.equalsIgnoreCase(f.getSort(), "asc") || StringUtils.equalsIgnoreCase(f.getSort(), "desc")) { + res = f.getSort(); + break; + } + } + } + return res; + } + + private List transFields(List list) { + return list.stream().map(ele -> { + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + BeanUtils.copyBean(dto, ele); + return dto; + }).collect(Collectors.toList()); + } + + // 对结果排序 + public List resultCustomSort(List xAxis, List data) { + List res = new ArrayList<>(data); + if (xAxis.size() > 0) { + // 找到对应维度 + for (int i = 0; i < xAxis.size(); i++) { + ChartViewFieldDTO item = xAxis.get(i); + if (StringUtils.equalsIgnoreCase(item.getSort(), "custom_sort")) { + // 获取自定义值与data对应列的结果 + if (i > 0) { + // 首先根据优先级高的字段分类,在每个前置字段相同的组里排序 + Map> map = new LinkedHashMap<>(); + for (String[] d : res) { + StringBuilder stringBuilder = new StringBuilder(); + for (int j = 0; j < i; j++) { + if (StringUtils.equalsIgnoreCase(xAxis.get(j).getSort(), "none")) { + continue; + } + stringBuilder.append(d[j]); + } + if (ObjectUtils.isEmpty(map.get(stringBuilder.toString()))) { + map.put(stringBuilder.toString(), new ArrayList<>()); + } + map.get(stringBuilder.toString()).add(d); + } + Iterator>> iterator = map.entrySet().iterator(); + List list = new ArrayList<>(); + while (iterator.hasNext()) { + Map.Entry> next = iterator.next(); + list.addAll(customSort(Optional.ofNullable(item.getCustomSort()).orElse(new ArrayList<>()), next.getValue(), i)); + } + res.clear(); + res.addAll(list); + } else { + res = customSort(Optional.ofNullable(item.getCustomSort()).orElse(new ArrayList<>()), res, i); + } + } + } + } + return res; + } + + public List customSort(List custom, List data, int index) { + List res = new ArrayList<>(); + + List indexArr = new ArrayList<>(); + List joinArr = new ArrayList<>(); + for (int i = 0; i < custom.size(); i++) { + String ele = custom.get(i); + for (int j = 0; j < data.size(); j++) { + String[] d = data.get(j); + if (StringUtils.equalsIgnoreCase(ele, d[index])) { + joinArr.add(d); + indexArr.add(j); + } + } + } + // 取得 joinArr 就是两者的交集 + List indexArrData = new ArrayList<>(); + for (int i = 0; i < data.size(); i++) { + indexArrData.add(i); + } + List indexResult = new ArrayList<>(); + for (int i = 0; i < indexArrData.size(); i++) { + if (!indexArr.contains(indexArrData.get(i))) { + indexResult.add(indexArrData.get(i)); + } + } + + List subArr = new ArrayList<>(); + for (int i = 0; i < indexResult.size(); i++) { + subArr.add(data.get(indexResult.get(i))); + } + res.addAll(joinArr); + res.addAll(subArr); + 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")) {// 此处与已有的自定义字段对比 + chartViewFieldDTO = item; + index = i; + } + if (Objects.equals(item.getId(), field.getId())) {// 获得当前自定义的字段 + getIndex = i; + } + } + + // 根据字段类型调整索引偏移量 + if (StringUtils.equalsIgnoreCase(fieldType, "xAxisExt")) { + List xAxis = view.getXAxis(); + index += xAxis.size(); + getIndex += xAxis.size(); + } + if (StringUtils.equalsIgnoreCase(fieldType, "extStack")) { + int xAxisSize = CollectionUtils.size(view.getXAxis()); + int extSize = CollectionUtils.size(view.getXAxisExt()); + index += xAxisSize + extSize; + getIndex += xAxisSize + extSize; + } + + // 执行自定义排序后的数据结果 + List sortResult = resultCustomSort(fieldList, sqlData); + if (ObjectUtils.isNotEmpty(chartViewFieldDTO) && (getIndex >= index)) { + // 使用自定义排序规则提取对应列数据 + 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]); + } + } + } + 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")); + } + + // 获取图表所有字段配置 + List allFields = getAllChartFields(view); + + // 针对分组切换堆叠时会遇到的问题 + 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())) + || StringUtils.equalsIgnoreCase(view.getType(), "flow-map") + || StringUtils.equalsIgnoreCase(view.getType(), "t-heatmap") + || StringUtils.equalsIgnoreCase(view.getType(), "sankey") + ) { + xAxis.addAll(xAxisExt); + } + List yAxis = new ArrayList<>(view.getYAxis()); + 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<>(); + + // 处理自定义过滤条件 + chartFilterTreeService.searchFieldAndSet(view.getCustomFilter()); + + // 空值校验:当x/y轴都为空时直接返回空结果 + if (ObjectUtils.isEmpty(xAxis) && ObjectUtils.isEmpty(yAxis)) { + return new ArrayList(); + } + + // 特殊图表类型配置调整 + switch (view.getType()) { + case "label": + yAxis = new ArrayList<>(); + if (ObjectUtils.isEmpty(xAxis)) { + return new ArrayList(); + } + break; + case "indicator": + case "gauge": + case "liquid": + xAxis = new ArrayList<>(); + if (ObjectUtils.isEmpty(yAxis)) { + return new ArrayList(); + } + break; + case "table-info": + yAxis = new ArrayList<>(); + if (ObjectUtils.isEmpty(xAxis)) { + return new ArrayList(); + } + break; + case "table-normal": + break; + case "bar-group": + case "bar-group-stack": + case "flow-map": + break; + default: + } + + // 生成联合查询SQL并处理数据源信息 + Map sqlMap = datasetSQLManage.getUnionSQLForEdit(table, null); + String sql = (String) sqlMap.get("sql"); + Map dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + boolean needOrder = Utils.isNeedOrder(dsList); + boolean crossDs = Utils.isCrossDs(dsMap); + if (!crossDs) { + sql = Utils.replaceSchemaAlias(sql, dsMap); + } + + // 初始化数据源请求对象 + DatasourceRequest datasourceRequest = new DatasourceRequest(); + datasourceRequest.setDsList(dsMap); + datasourceRequest.setIsCross(crossDs); + + // 根据数据源类型选择查询提供器 + Provider provider; + if (crossDs) { + provider = ProviderFactory.getDefaultProvider(); + } else { + provider = ProviderFactory.getProvider(dsMap.entrySet().iterator().next().getValue().getType()); + } + + // 执行数据查询 + List data = new ArrayList<>(); + + String querySql = null; + //如果不是插件图表 走原生逻辑 + 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())) { + DEException.throwException(Translator.get("i18n_invalid_ds")); + } + } + + // 构建SQL元数据并生成最终查询语句 + SQLMeta sqlMeta = new SQLMeta(); + Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); + // row permission 默认不过滤用户组织数据权限,后续完善 + List rowPermissionsTree = new ArrayList(); + WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); + + 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); + 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); + 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); + } else if (StringUtils.equalsIgnoreCase("table-info", view.getType())) { + Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, transFields(allFields), crossDs, dsMap, Utils.getParams(transFields(allFields)), view.getCalParams(), pluginManage); + querySql = SQLProvider.createQuerySQL(sqlMeta, false, true, view); + } else { + Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, 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); + } + + querySql = provider.rebuildSQL(querySql, sqlMeta, crossDs, dsMap); + datasourceRequest.setQuery(querySql); + logger.debug("calcite chart get field enum sql: " + querySql); + + data = (List) provider.fetchResultField(datasourceRequest).get("data"); + } + return data; + } + + private List getAllChartFields(ChartViewDTO view) { + // get all fields + Map> stringListMap = chartViewManege.listByDQ(view.getTableId(), view.getId(), view); + List dimensionList = stringListMap.get("dimensionList"); + List quotaList = stringListMap.get("quotaList"); + List allFields = new ArrayList<>(); + allFields.addAll(dimensionList); + allFields.addAll(quotaList); + return allFields.stream().filter(ele -> ele.getId() != -1L).collect(Collectors.toList()); + } + + + /** + * 根据图表视图和字段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)) { + targetField = tmp; + 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()); + } + + public void encodeData(ChartViewDTO chartViewDTO) { + if (chartViewDTO.getData() != null) { + if (chartViewDTO.getType().startsWith("chart-mix")) { + DatasetUtils.listEncode((List) ((Map) chartViewDTO.getData().get("left")).get("sourceFields")); + DatasetUtils.listEncode((List) ((Map) chartViewDTO.getData().get("right")).get("sourceFields")); + } else { + DatasetUtils.listEncode((List) chartViewDTO.getData().get("sourceFields")); + } + } + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/ChartFilterTreeService.java b/backend/src/main/java/com/stdproject/service/manage/ChartFilterTreeService.java new file mode 100644 index 0000000..1a3c262 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/ChartFilterTreeService.java @@ -0,0 +1,82 @@ +package com.stdproject.service.manage; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.stdproject.entity.CoreDatasetTableField; +import com.stdproject.mapper.CoreDatasetTableFieldMapper; +import com.stdproject.utils.SqlUtils; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.FieldGroupDTO; +import io.gisbi.extensions.view.filter.FilterTreeItem; +import io.gisbi.extensions.view.filter.FilterTreeObj; +import io.gisbi.utils.BeanUtils; +import io.gisbi.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Service +public class ChartFilterTreeService { + @Resource + private CoreDatasetTableFieldMapper coreDatasetTableFieldMapper; + + public void searchFieldAndSet(FilterTreeObj tree) { + if (ObjectUtils.isNotEmpty(tree)) { + if (ObjectUtils.isNotEmpty(tree.getItems())) { + for (FilterTreeItem item : tree.getItems()) { + if (ObjectUtils.isNotEmpty(item)) { + if (StringUtils.equalsIgnoreCase(item.getType(), "item") || ObjectUtils.isEmpty(item.getSubTree())) { + CoreDatasetTableField coreDatasetTableField = coreDatasetTableFieldMapper.selectById(item.getFieldId()); + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + BeanUtils.copyBean(dto, coreDatasetTableField); + if (StringUtils.isNotEmpty(coreDatasetTableField.getParams())) { + TypeReference> tokenType = new TypeReference<>() { + }; + List calParams = JsonUtil.parseList(coreDatasetTableField.getParams(), tokenType); + dto.setParams(calParams); + } + if (StringUtils.isNotEmpty(coreDatasetTableField.getGroupList())) { + TypeReference> groupTokenType = new TypeReference<>() { + }; + List fieldGroups = JsonUtil.parseList(coreDatasetTableField.getGroupList(), groupTokenType); + dto.setGroupList(fieldGroups); + } + item.setField(dto); + } else if (StringUtils.equalsIgnoreCase(item.getType(), "tree") || (ObjectUtils.isNotEmpty(item.getSubTree()) && StringUtils.isNotEmpty(item.getSubTree().getLogic()))) { + searchFieldAndSet(item.getSubTree()); + } + } + } + } + } + } + + public FilterTreeObj charReplace(FilterTreeObj tree) { + if (ObjectUtils.isNotEmpty(tree)) { + if (ObjectUtils.isNotEmpty(tree.getItems())) { + for (FilterTreeItem item : tree.getItems()) { + if (ObjectUtils.isNotEmpty(item)) { + if (StringUtils.equalsIgnoreCase(item.getType(), "item") || ObjectUtils.isEmpty(item.getSubTree())) { + if (CollectionUtils.isNotEmpty(item.getEnumValue())) { + List collect = item.getEnumValue().stream().map(SqlUtils::transKeyword).collect(Collectors.toList()); + item.setEnumValue(collect); + } + item.setValue(SqlUtils.transKeyword(item.getValue())); + } else if (StringUtils.equalsIgnoreCase(item.getType(), "tree") || (ObjectUtils.isNotEmpty(item.getSubTree()) && StringUtils.isNotEmpty(item.getSubTree().getLogic()))) { + charReplace(item.getSubTree()); + } + } + } + } + } + return tree; + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/ChartHandlerManager.java b/backend/src/main/java/com/stdproject/service/manage/ChartHandlerManager.java new file mode 100644 index 0000000..f973c53 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/ChartHandlerManager.java @@ -0,0 +1,27 @@ +package com.stdproject.service.manage; +import io.gisbi.extensions.view.plugin.AbstractChartPlugin; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Component; + +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class ChartHandlerManager { + @Lazy + @Resource + private DefaultChartHandler defaultChartHandler; + private static final ConcurrentHashMap CHART_HANDLER_MAP = new ConcurrentHashMap<>(); + + public void registerChartHandler(String render, String type, AbstractChartPlugin chartHandler) { + CHART_HANDLER_MAP.put(render + "-" + type, chartHandler); + } + + public AbstractChartPlugin getChartHandler(String render, String type) { + var handler = CHART_HANDLER_MAP.get(render + "-" + type); + if (handler == null) { + return defaultChartHandler; + } + return handler; + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/ChartViewManege.java b/backend/src/main/java/com/stdproject/service/manage/ChartViewManege.java new file mode 100644 index 0000000..041cc01 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/ChartViewManege.java @@ -0,0 +1,262 @@ +package com.stdproject.service.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.constant.FunctionConstant; +import com.stdproject.entity.CoreChartView; +import com.stdproject.entity.CoreDatasetTableField; +import com.stdproject.mapper.CoreDatasetTableFieldMapper; +import com.stdproject.mapper.ExtChartViewMapper; +import com.stdproject.utils.Utils; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.FieldGroupDTO; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.view.dto.*; +import io.gisbi.extensions.view.filter.FilterTreeObj; +import io.gisbi.i18n.Lang; +import io.gisbi.utils.BeanUtils; +import io.gisbi.utils.JsonUtil; +import io.gisbi.utils.LogUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Component +public class ChartViewManege { + + @Resource + private CoreDatasetTableFieldMapper coreDatasetTableFieldMapper; + @Resource + private ExtChartViewMapper extChartViewMapper; + @Resource + private DatasetTableFieldManage datasetTableFieldManage; + /** + * sceneId 为仪表板或者数据大屏id + */ + public List listBySceneId(Long sceneId, String resourceTable) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("scene_id", sceneId); + List chartViewDTOS = transChart(extChartViewMapper.selectListCustom(sceneId, resourceTable)); + if (!CollectionUtils.isEmpty(chartViewDTOS)) { + List tableIds = chartViewDTOS.stream() + .map(ChartViewDTO::getTableId) + .filter(tableId -> tableId != null) // 过滤掉空值 + .distinct() + .toList(); + if (!CollectionUtils.isEmpty(tableIds)) { + QueryWrapper wp = new QueryWrapper<>(); + wp.in("dataset_group_id", tableIds); + List coreDatasetTableFields = coreDatasetTableFieldMapper.selectList(wp); + Map> groupedByTableId = coreDatasetTableFields.stream() + .collect(Collectors.groupingBy(CoreDatasetTableField::getDatasetGroupId)); + if (chartViewDTOS.size() < 10) { + chartViewDTOS.forEach(dto -> { + if (dto.getTableId() != null) { + dto.setCalParams(Utils.getParams(datasetTableFieldManage.transDTO(groupedByTableId.get(dto.getTableId())))); + } + }); + } else { + ExecutorService executor = Executors.newFixedThreadPool(10); + try { + // 超过10个图表要处理启用多线程处理 + CountDownLatch latch = new CountDownLatch(chartViewDTOS.size()); + chartViewDTOS.forEach(dto -> { + executor.submit(() -> { + try { + if (dto.getTableId() != null) { + dto.setCalParams(Utils.getParams(datasetTableFieldManage.transDTO(groupedByTableId.get(dto.getTableId())))); + } + } finally { + latch.countDown(); // 减少计数器 + } + }); + }); + + // 等待所有线程完成 + boolean completedInTime = latch.await(200, TimeUnit.SECONDS); + if (!completedInTime) { + throw new InterruptedException("Tasks did not complete within 200 seconds"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + LogUtil.error(e); + } finally { + executor.shutdown(); // 确保线程池关闭 + } + } + + } + } + return chartViewDTOS; + } + + public List transChart(List list) { + if (ObjectUtils.isEmpty(list)) { + return Collections.emptyList(); + } + return list.stream().map(ele -> { + ChartViewDTO dto = transRecord2DTO(ele); + return dto; + }).collect(Collectors.toList()); + } + + public ChartViewDTO transRecord2DTO(CoreChartView record) { + ChartViewDTO dto = new ChartViewDTO(); + BeanUtils.copyBean(dto, record); + + TypeReference> tokenType = new TypeReference<>() { + }; + + dto.setXAxis(JsonUtil.parseList(record.getxAxis(), tokenType)); + dto.setXAxisExt(JsonUtil.parseList(record.getxAxisExt(), tokenType)); + dto.setYAxis(JsonUtil.parseList(record.getyAxis(), tokenType)); + dto.setYAxisExt(JsonUtil.parseList(record.getyAxisExt(), tokenType)); + dto.setExtStack(JsonUtil.parseList(record.getExtStack(), tokenType)); + dto.setExtBubble(JsonUtil.parseList(record.getExtBubble(), tokenType)); + dto.setExtLabel(JsonUtil.parseList(record.getExtLabel(), tokenType)); + dto.setExtTooltip(JsonUtil.parseList(record.getExtTooltip(), tokenType)); + dto.setCustomAttr(JsonUtil.parse(record.getCustomAttr(), Map.class)); + if (record.getCustomAttrMobile() != null) { + dto.setCustomAttrMobile(JsonUtil.parse(record.getCustomAttrMobile(), Map.class)); + } + dto.setCustomStyle(JsonUtil.parse(record.getCustomStyle(), Map.class)); + if (record.getCustomStyleMobile() != null) { + dto.setCustomStyleMobile(JsonUtil.parse(record.getCustomStyleMobile(), Map.class)); + } + dto.setSenior(JsonUtil.parse(record.getSenior(), Map.class)); + dto.setDrillFields(JsonUtil.parseList(record.getDrillFields(), tokenType)); + dto.setCustomFilter(JsonUtil.parseObject(record.getCustomFilter(), FilterTreeObj.class)); + dto.setViewFields(JsonUtil.parseList(record.getViewFields(), tokenType)); + dto.setFlowMapStartName(JsonUtil.parseList(record.getFlowMapStartName(), tokenType)); + dto.setFlowMapEndName(JsonUtil.parseList(record.getFlowMapEndName(), tokenType)); + dto.setExtColor(JsonUtil.parseList(record.getExtColor(), tokenType)); + dto.setSortPriority(JsonUtil.parseList(record.getSortPriority(), new TypeReference>() { + })); + return dto; + } + + public Map> listByDQ(Long id, Long chartId, ChartViewDTO chartViewDTO) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", id); + wrapper.eq("checked", true); + wrapper.isNull("chart_id"); + + TypeReference> typeToken = new TypeReference<>() { + }; + TypeReference> groupTokenType = new TypeReference<>() { + }; + List fields = coreDatasetTableFieldMapper.selectList(wrapper); + List collect = fields.stream().map(ele -> { + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + BeanUtils.copyBean(dto, ele); + dto.setParams(JsonUtil.parseList(ele.getParams(), typeToken)); + dto.setGroupList(JsonUtil.parseList(ele.getGroupList(), groupTokenType)); + return dto; + }).collect(Collectors.toList()); + // filter column disable field + Map desensitizationList = new HashMap<>(); + List datasetTableFieldDTOS = collect; + datasetTableFieldDTOS.forEach(ele -> ele.setDesensitized(desensitizationList.containsKey(ele.getGisbiName()))); + datasetTableFieldDTOS.add(createCountField(id)); + List list = transFieldDTO(datasetTableFieldDTOS); + + // 获取图表计算字段 + wrapper.clear(); + wrapper.eq("chart_id", chartId); + List chartFields = coreDatasetTableFieldMapper.selectList(wrapper).stream().map(ele -> { + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + BeanUtils.copyBean(dto, ele); + dto.setGroupList(JsonUtil.parseList(ele.getGroupList(), groupTokenType)); + return dto; + }).collect(Collectors.toList()); + list.addAll(transFieldDTO(chartFields)); + + // 获取list中的聚合函数,将字段的summary设置成空 + SQLObj tableObj = new SQLObj(); + tableObj.setTableAlias(""); + + for (ChartViewFieldDTO ele : list) { + if (Objects.equals(ele.getExtField(), ExtFieldConstant.EXT_CALC)) { + List f = list.stream().map(e -> { + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + BeanUtils.copyBean(dto, e); + return dto; + }).collect(Collectors.toList()); + String originField = Utils.calcFieldRegex(ele, tableObj, f, true, null, Utils.mergeParam(Utils.getParams(f), null)); + for (String func : FunctionConstant.AGG_FUNC) { + if (Utils.matchFunction(func, originField)) { + ele.setSummary(""); + ele.setAgg(true); + break; + } + } + } + } + + List dimensionList = list.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "d")).collect(Collectors.toList()); + List quotaList = list.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "q")).collect(Collectors.toList()); + + Map> map = new LinkedHashMap<>(); + map.put("dimensionList", dimensionList); + map.put("quotaList", quotaList); + return map; + } + + public DatasetTableFieldDTO createCountField(Long id) { + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + dto.setId(-1L); + dto.setDatasetGroupId(id); + dto.setOriginName("*"); + dto.setName("记录数*"); + dto.setGisbiName("*"); + dto.setType("INT"); + dto.setChecked(true); + dto.setColumnIndex(999); + dto.setDeType(2); + dto.setExtField(1); + dto.setGroupType("q"); + return dto; + } + + public List transFieldDTO(List list) { + return list.stream().map(ele -> { + ChartViewFieldDTO dto = new ChartViewFieldDTO(); + if (ele == null) return null; + BeanUtils.copyBean(dto, ele); + dto.setDateStyle("y_M_d"); + dto.setDatePattern("date_sub"); + dto.setDateShowFormat("y_M_d"); + dto.setChartType("bar"); + + if (dto.getId() == -1L || dto.getDeType() == 0 || dto.getDeType() == 1 || dto.getDeType() == 7) { + dto.setSummary("count"); + } else { + dto.setSummary("sum"); + } + + ChartFieldCompareDTO chartFieldCompareDTO = new ChartFieldCompareDTO(); + chartFieldCompareDTO.setType("none"); + dto.setCompareCalc(chartFieldCompareDTO); + + dto.setFormatterCfg(new FormatterCfgDTO().setUnitLanguage(Lang.isChinese() ? "ch" : "en")); + + dto.setSort("none"); + dto.setFilter(Collections.emptyList()); + return dto; + }).collect(Collectors.toList()); + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/DataSourceManage.java b/backend/src/main/java/com/stdproject/service/manage/DataSourceManage.java new file mode 100644 index 0000000..e2c4905 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/DataSourceManage.java @@ -0,0 +1,115 @@ +package com.stdproject.service.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.stdproject.entity.CoreDatasource; +import com.stdproject.mapper.CoreDatasourceMapper; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.DatasourceDTO; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.BeanUtils; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class DataSourceManage { + + + + @Resource + private CoreDatasourceMapper coreDatasourceMapper; + + + + @Resource + private EngineManage engineManage; + + @Autowired(required = false) + private PluginManageApi pluginManage; + + + + + + + public void checkName(DatasourceDTO dto) { + if (StringUtils.isEmpty(dto.getName()) || StringUtils.isEmpty(dto.getName().trim())) { + DEException.throwException(Translator.get("i18n_df_name_can_not_empty")); + } + QueryWrapper wrapper = new QueryWrapper<>(); + if (ObjectUtils.isNotEmpty(dto.getPid())) { + if ( dto.getPid().equals(0L)) { + wrapper.eq("pid", -100L); + } else { + wrapper.eq("pid", dto.getPid()); + } + } + if (StringUtils.isNotEmpty(dto.getName())) { + wrapper.eq("name", dto.getName()); + } + if (ObjectUtils.isNotEmpty(dto.getId())) { + wrapper.ne("id", dto.getId()); + } + if (ObjectUtils.isNotEmpty(dto.getNodeType())) { + if (dto.getNodeType().equalsIgnoreCase("folder")) { + wrapper.eq("type", dto.getType()); + } else { + wrapper.ne("type", "folder"); + } + + } + List list = coreDatasourceMapper.selectList(wrapper); + if (list.size() > 0) { + DEException.throwException(Translator.get("i18n_ds_name_exists")); + } + } + + + public String getTenantAccessToken() { + return null; + } + + + + public void innerEditStatus(CoreDatasource coreDatasource) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("id", coreDatasource.getId()); + updateWrapper.set("status", coreDatasource.getStatus()); + coreDatasourceMapper.update(null, updateWrapper); + } + + + + public void encryptDsConfig() { + coreDatasourceMapper.selectList(null).forEach(dataSource -> { + coreDatasourceMapper.updateById(dataSource); + }); + } + + + public CoreDatasource getCoreDatasource(Long id) { + if (id == -1L) { + return engineManage.getDeEngine(); + } + return coreDatasourceMapper.selectById(id); + } + + + + public CoreDatasource getDatasource(Long id) { + return getCoreDatasource(id); + } + + public DatasourceDTO getDs(Long id) { + CoreDatasource coreDatasource = getCoreDatasource(id); + DatasourceDTO dto = new DatasourceDTO(); + BeanUtils.copyBean(dto, coreDatasource); + return dto; + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/DatasetGroupManage.java b/backend/src/main/java/com/stdproject/service/manage/DatasetGroupManage.java new file mode 100644 index 0000000..7997274 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/DatasetGroupManage.java @@ -0,0 +1,394 @@ +package com.stdproject.service.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.stdproject.entity.CoreDatasetGroup; +import com.stdproject.entity.CoreDatasetTable; +import com.stdproject.entity.CoreDatasource; +import com.stdproject.entity.dto.DataSetNodeBO; +import com.stdproject.entity.po.DataSetNodePO; +import com.stdproject.entity.union.DatasetGroupInfoDTO; +import com.stdproject.entity.union.UnionDTO; +import com.stdproject.entity.vo.DataSetBarVO; +import com.stdproject.mapper.CoreDataSetExtMapper; +import com.stdproject.mapper.CoreDatasetGroupMapper; +import com.stdproject.mapper.CoreDatasetTableMapper; +import com.stdproject.mapper.CoreDatasourceMapper; +import com.stdproject.utils.DatasetUtils; +import com.stdproject.utils.FieldUtils; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.dto.DatasetTableDTO; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceDTO; +import io.gisbi.extensions.view.dto.SqlVariableDetails; +import io.gisbi.i18n.Translator; +import io.gisbi.model.BusiNodeRequest; +import io.gisbi.model.BusiNodeVO; +import io.gisbi.utils.*; +import jakarta.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Component +@Transactional(rollbackFor = Exception.class) +public class DatasetGroupManage { + @Resource + private CoreDatasetGroupMapper coreDatasetGroupMapper; + @Resource + private DatasetSQLManage datasetSQLManage; + @Resource + private DatasetTableManage datasetTableManage; + @Resource + private DatasetTableFieldManage datasetTableFieldManage; + + @Resource + private CoreDataSetExtMapper coreDataSetExtMapper; + @Resource + private CoreDatasetTableMapper coreDatasetTableMapper; + @Resource + private CoreDatasourceMapper coreDatasourceMapper; + + + + + private static final String leafType = "dataset"; + + private Lock lock = new ReentrantLock(); + + + + public List tree(BusiNodeRequest request) { + + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (ObjectUtils.isNotEmpty(request.getLeaf())) { + queryWrapper.eq("node_type", request.getLeaf() ? "dataset" : "folder"); + } + if (ObjectUtils.isNotEmpty(request.getAppId())) { + queryWrapper.eq("app_id", request.getAppId()); + } + String info = CommunityUtils.getInfo(); + if (StringUtils.isNotBlank(info)) { + queryWrapper.notExists(String.format(info, "core_dataset_group.id")); + } + queryWrapper.orderByDesc("create_time"); + List pos = coreDataSetExtMapper.query(queryWrapper); + List nodes = new ArrayList<>(); + if (ObjectUtils.isEmpty(request.getLeaf()) || !request.getLeaf()) nodes.add(rootNode(request.getAppId())); + List bos = pos.stream().map(this::convert).toList(); + if (CollectionUtils.isNotEmpty(bos)) { + nodes.addAll(bos); + } + return TreeUtils.mergeTree(nodes, BusiNodeVO.class, false); + } + + public DataSetBarVO queryBarInfo(Long id) { + DataSetBarVO dataSetBarVO = coreDataSetExtMapper.queryBarInfo(id); + dataSetBarVO.setDatasourceDTOList(getDatasource(id)); + return dataSetBarVO; + } + + private List getDatasource(Long datasetId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", datasetId); + List coreDatasetTables = coreDatasetTableMapper.selectList(wrapper); + Set ids = new LinkedHashSet(); + coreDatasetTables.forEach(ele -> ids.add(ele.getDatasourceId())); + if (CollectionUtils.isEmpty(ids)) { + DEException.throwException(Translator.get("i18n_dataset_create_error")); + } + + QueryWrapper datasourceQueryWrapper = new QueryWrapper<>(); + datasourceQueryWrapper.in("id", ids); + List datasourceDTOList = coreDatasourceMapper.selectList(datasourceQueryWrapper).stream().map(ele -> { + DatasourceDTO dto = new DatasourceDTO(); + BeanUtils.copyBean(dto, ele); + dto.setConfiguration(null); + return dto; + }).collect(Collectors.toList()); + if (ids.size() != datasourceDTOList.size()) { + DEException.throwException(Translator.get("i18n_dataset_ds_delete")); + } + return datasourceDTOList; + } + + private DataSetNodeBO rootNode(String appId) { + return new DataSetNodeBO(appId,0L, "root", false, 7, -1L, 0); + } + + private DataSetNodeBO convert(DataSetNodePO po) { + return new DataSetNodeBO(po.getAppId(),po.getId(), po.getName(), StringUtils.equals(po.getNodeType(), leafType), 9, po.getPid(), 0); + } + + public void checkName(DatasetGroupInfoDTO dto) { + QueryWrapper wrapper = new QueryWrapper<>(); + if (ObjectUtils.isNotEmpty(dto.getPid())) { + wrapper.eq("pid", dto.getPid()); + } + if (StringUtils.isNotEmpty(dto.getName())) { + wrapper.eq("name", dto.getName()); + } + if (ObjectUtils.isNotEmpty(dto.getId())) { + wrapper.ne("id", dto.getId()); + } + if (ObjectUtils.isNotEmpty(dto.getLevel())) { + wrapper.eq("level", dto.getLevel()); + } + if (ObjectUtils.isNotEmpty(dto.getNodeType())) { + wrapper.eq("node_type", dto.getNodeType()); + } + List list = coreDatasetGroupMapper.selectList(wrapper); + if (list.size() > 0) { + DEException.throwException(Translator.get("i18n_ds_name_exists")); + } + } + + + public DatasetGroupInfoDTO getForCount(Long id) throws Exception { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(id); + if (coreDatasetGroup == null) { + return null; + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + if (StringUtils.equalsIgnoreCase(dto.getNodeType(), "dataset")) { + dto.setUnion(JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + })); + // 获取field + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(id); + List allFields = dsFields.stream().map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + dto.setAllFields(allFields); + } + return dto; + } + + public DatasetGroupInfoDTO getDetail(Long id) throws Exception { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(id); + if (coreDatasetGroup == null) { + return null; + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + if (StringUtils.equalsIgnoreCase(dto.getNodeType(), "dataset")) { + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + + // 获取field + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(id); + List allFields = dsFields.stream().map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + DatasetUtils.listEncode(allFields); + + dto.setAllFields(allFields); + } + return dto; + } + + public DatasetGroupInfoDTO getDatasetGroupInfoDTO(Long id, String type) throws Exception { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(id); + if (coreDatasetGroup == null) { + return null; + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + if (StringUtils.equalsIgnoreCase(dto.getNodeType(), "dataset")) { + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + + // 获取field + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(id); + List allFields = dsFields.stream().map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + dto.setAllFields(allFields); + +// if ("preview".equalsIgnoreCase(type)) { +// // 请求数据 +// Map map = datasetDataManage.previewDataWithLimit(dto, 0, 100, true, false); +// // 获取data,sql +// Map data = (Map) map.get("data"); +// String sql = (String) map.get("sql"); +// Long total = (Long) map.get("total"); +// dto.setData(data); +// dto.setSql(Base64.getEncoder().encodeToString(sql.getBytes())); +// dto.setTotal(total); +// } + } + return dto; + } + + public List getDetail(List ids) { + if (ObjectUtils.isEmpty(ids)) { + DEException.throwException(Translator.get("i18n_table_id_can_not_empty")); + } + List list = new ArrayList<>(); + for (Long id : ids) { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(id); + if (coreDatasetGroup == null) { + list.add(null); + } else { + DatasetTableDTO dto = new DatasetTableDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + Map> listByDQ = datasetTableFieldManage.listByDQ(id); + dto.setFields(listByDQ); + list.add(dto); + } + } + return list; + } + + public List getSqlParams(List ids) { + List list = new ArrayList<>(); + if (ObjectUtils.isEmpty(ids)) { + return list; + } + TypeReference> listTypeReference = new TypeReference>() { + }; + for (Long id : ids) { + List datasetTables = datasetTableManage.selectByDatasetGroupId(id); + for (CoreDatasetTable datasetTable : datasetTables) { + if (StringUtils.isNotEmpty(datasetTable.getSqlVariableDetails())) { + List defaultsSqlVariableDetails = JsonUtil.parseList(datasetTable.getSqlVariableDetails(), listTypeReference); + if (CollectionUtils.isNotEmpty(defaultsSqlVariableDetails)) { + List fullName = new ArrayList<>(); + geFullName(id, fullName); + Collections.reverse(fullName); + List finalFullName = fullName; + defaultsSqlVariableDetails.forEach(sqlVariableDetails -> { + sqlVariableDetails.setDatasetGroupId(id); + sqlVariableDetails.setDatasetTableId(datasetTable.getId()); + sqlVariableDetails.setDatasetFullName(String.join("/", finalFullName)); + }); + } + + list.addAll(defaultsSqlVariableDetails); + } + } + } + list.forEach(sqlVariableDetail -> { + sqlVariableDetail.setId(sqlVariableDetail.getDatasetTableId() + "|DE|" + sqlVariableDetail.getVariableName()); + sqlVariableDetail.setDeType(FieldUtils.transType2DeType(sqlVariableDetail.getType().get(0).contains("DATETIME") ? "DATETIME" : sqlVariableDetail.getType().get(0))); + }); + return list; + } + + public void checkMove(DatasetGroupInfoDTO datasetGroupInfoDTO) { + if (Objects.equals(datasetGroupInfoDTO.getId(), datasetGroupInfoDTO.getPid())) { + DEException.throwException(Translator.get("i18n_pid_not_eq_id")); + } + List ids = new ArrayList<>(); + getParents(datasetGroupInfoDTO.getPid(), ids); + if (ids.contains(datasetGroupInfoDTO.getId())) { + DEException.throwException(Translator.get("i18n_pid_not_eq_id")); + } + } + + private void getParents(Long pid, List ids) { + CoreDatasetGroup parent = coreDatasetGroupMapper.selectById(pid);// 查找父级folder + ids.add(parent.getId()); + if (parent.getPid() != null && parent.getPid() != 0) { + getParents(parent.getPid(), ids); + } + } + + public void geFullName(Long pid, List fullName) { + CoreDatasetGroup parent = coreDatasetGroupMapper.selectById(pid);// 查找父级folder + if (parent == null) { + return; + } + fullName.add(parent.getName()); + if (parent.getId().equals(parent.getPid())) { + return; + } + if (parent.getPid() != null && parent.getPid() != 0) { + geFullName(parent.getPid(), fullName); + } + } + + public List getDetailWithPerm(List ids) { + var result = new ArrayList(); + if (CollectionUtils.isNotEmpty(ids)) { + var dsList = coreDatasetGroupMapper.selectBatchIds(ids); + if (CollectionUtils.isNotEmpty(dsList)) { + dsList.forEach(ds -> { + DatasetTableDTO dto = new DatasetTableDTO(); + BeanUtils.copyBean(dto, ds); + var fields = datasetTableFieldManage.listFieldsWithPermissions(ds.getId()); + List dimensionList = fields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "d")).toList(); + List quotaList = fields.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "q")).toList(); + Map> map = new LinkedHashMap<>(); + DatasetUtils.listEncode(dimensionList); + DatasetUtils.listEncode(quotaList); + map.put("dimensionList", dimensionList); + map.put("quotaList", quotaList); + dto.setFields(map); + result.add(dto); + }); + } + } + return result; + } + + public List getAllList() { + List coreDatasetGroupList = coreDatasetGroupMapper.selectList(new QueryWrapper<>()); + if (CollectionUtils.isEmpty(coreDatasetGroupList)) { + return new ArrayList<>(); + } + List list = new ArrayList<>(); + for (CoreDatasetGroup coreDatasetGroup : coreDatasetGroupList) { + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + if (StringUtils.equalsIgnoreCase(dto.getNodeType(), "dataset")) { + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + + // 获取field + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(coreDatasetGroup.getId()); + List allFields = dsFields.stream().map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + DatasetUtils.listEncode(allFields); + + dto.setAllFields(allFields); + + list.add(dto); + } + } + return list; + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/DatasetSQLManage.java b/backend/src/main/java/com/stdproject/service/manage/DatasetSQLManage.java new file mode 100644 index 0000000..e86de99 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/DatasetSQLManage.java @@ -0,0 +1,525 @@ +package com.stdproject.service.manage; + + +import com.stdproject.constant.DatasetTableType; +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.entity.CoreDatasetGroup; +import com.stdproject.entity.CoreDatasource; +import com.stdproject.entity.union.*; +import com.stdproject.mapper.CoreDatasetGroupMapper; +import com.stdproject.mapper.CoreDatasourceMapper; +import com.stdproject.utils.DatasetTableTypeConstants; +import com.stdproject.utils.SqlUtils; +import com.stdproject.utils.SqlparserUtils; +import com.stdproject.utils.TableUtils; +import io.gisbi.constant.SQLConstants; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.DatasetTableDTO; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.dto.DsTypeDTO; +import io.gisbi.extensions.datasource.factory.ProviderFactory; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.datasource.provider.Provider; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.datasource.vo.XpackPluginsDatasourceVO; +import io.gisbi.extensions.view.dto.ChartExtFilterDTO; +import io.gisbi.extensions.view.dto.ChartExtRequest; +import io.gisbi.extensions.view.dto.SqlVariableDetails; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.BeanUtils; +import io.gisbi.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.text.MessageFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Component +public class DatasetSQLManage { + + @Resource + private CoreDatasourceMapper coreDatasourceMapper; + @Resource + private EngineManage engineManage; + + @Autowired(required = false) + private PluginManageApi pluginManage; + + @Resource + private DataSourceManage dataSourceManage; + + @Resource + private CoreDatasetGroupMapper coreDatasetGroupMapper; + + + private static Logger logger = LoggerFactory.getLogger(DatasetSQLManage.class); + + private List filterParameters(ChartExtRequest chartExtRequest, Long datasetTableId) { + List parameters = new ArrayList<>(); + if (chartExtRequest != null && ObjectUtils.isNotEmpty(chartExtRequest.getOuterParamsFilters())) { + for (ChartExtFilterDTO filterDTO : chartExtRequest.getOuterParamsFilters()) { + if (CollectionUtils.isEmpty(filterDTO.getValue())) { + continue; + } + filterParametersAdaptor(parameters, filterDTO, datasetTableId); + } + } + if (chartExtRequest != null && ObjectUtils.isNotEmpty(chartExtRequest.getWebParamsFilters())) { + for (ChartExtFilterDTO filterDTO : chartExtRequest.getWebParamsFilters()) { + if (CollectionUtils.isEmpty(filterDTO.getValue())) { + continue; + } + filterParametersAdaptor(parameters, filterDTO, datasetTableId); + } + } + if (chartExtRequest != null && ObjectUtils.isNotEmpty(chartExtRequest.getFilter())) { + for (ChartExtFilterDTO filterDTO : chartExtRequest.getFilter()) { + if (CollectionUtils.isEmpty(filterDTO.getValue())) { + continue; + } + filterParametersAdaptor(parameters, filterDTO, datasetTableId); + } + } + return parameters; + } + + private void filterParametersAdaptor(List parameters, ChartExtFilterDTO filterDTO, Long datasetTableId) { + if (ObjectUtils.isNotEmpty(filterDTO.getParameters())) { + for (SqlVariableDetails parameter : filterDTO.getParameters()) { + if (parameter.getDatasetTableId().equals(datasetTableId)) { + parameter.setValue(filterDTO.getValue()); + parameter.setOperator(filterDTO.getOperator()); + parameters.add(parameter); + } + } + } + } + + public Map getUnionSQLForEdit(DatasetGroupInfoDTO dataTableInfoDTO, ChartExtRequest chartExtRequest) throws Exception { + Map dsMap = new LinkedHashMap<>(); + List union = dataTableInfoDTO.getUnion(); + // 所有选中的字段,即select后的查询字段 + Map checkedInfo = new LinkedHashMap<>(); + List unionList = new ArrayList<>(); + List checkedFields = new ArrayList<>(); + String sql = ""; + if (ObjectUtils.isEmpty(union)) { + return null; + } + boolean isCross = dataTableInfoDTO.getIsCross(); + DatasetTableDTO currentDs = union.get(0).getCurrentDs(); + SQLObj tableName = null; + for (int i = 0; i < union.size(); i++) { + UnionDTO unionDTO = union.get(i); + DatasetTableDTO datasetTable = unionDTO.getCurrentDs(); + DatasetTableInfoDTO tableInfo = JsonUtil.parseObject(datasetTable.getInfo(), DatasetTableInfoDTO.class); + + String schema; + if (dsMap.containsKey(datasetTable.getDatasourceId())) { + schema = dsMap.get(datasetTable.getDatasourceId()).getSchemaAlias(); + } else { + schema = putObj2Map(dsMap, datasetTable, isCross); + } + SQLObj table = getUnionTable(datasetTable, tableInfo, schema, i, filterParameters(chartExtRequest, currentDs.getId()), chartExtRequest == null, isCross, dsMap); + if (i == 0) { + tableName = table; + } + // 获取前端传过来选中的字段 + List fields = unionDTO.getCurrentDsFields(); + fields = fields.stream().filter(DatasetTableFieldDTO::getChecked).collect(Collectors.toList()); + + String[] array = fields.stream() + .map(f -> { + String alias; + if (StringUtils.isEmpty(f.getGisbiName())) { + alias = TableUtils.fieldNameShort(table.getTableAlias() + "_" + f.getOriginName()); + } else { + alias = f.getGisbiName(); + } + f.setFieldShortName(alias); + f.setGisbiName(f.getFieldShortName()); + f.setDatasetTableId(datasetTable.getId()); + String prefix = ""; + String suffix = ""; + + DsTypeDTO datasourceType = getDatasourceType(dsMap, datasetTable.getDatasourceId()); + if (Objects.equals(f.getExtField(), ExtFieldConstant.EXT_NORMAL)) { + if (isCross) { + prefix = "`"; + suffix = "`"; + } else { + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } + } + if (StringUtils.equalsIgnoreCase(datasourceType.getType(), "es")) { + return table.getTableAlias() + "." + prefix + f.getOriginName() + suffix; + } else { + return table.getTableAlias() + "." + prefix + f.getOriginName() + suffix + " AS " + prefix + alias + suffix; + } + }) + .toArray(String[]::new); + checkedInfo.put(table.getTableAlias(), array); + checkedFields.addAll(fields); + // 获取child的fields和union + if (!CollectionUtils.isEmpty(unionDTO.getChildrenDs())) { + getUnionForEdit(datasetTable, table, unionDTO.getChildrenDs(), checkedInfo, unionList, checkedFields, dsMap, chartExtRequest, isCross); + } + } + // build sql + boolean isFullJoin = false; + if (!CollectionUtils.isEmpty(unionList)) { + // field + StringBuilder field = new StringBuilder(); + for (Map.Entry next : checkedInfo.entrySet()) { + if (next.getValue().length > 0) { + field.append(StringUtils.join(next.getValue(), ",")).append(","); + } + } + String f = subPrefixSuffixChar(field.toString()); + // join + StringBuilder join = new StringBuilder(); + for (UnionParamDTO unionParamDTO : unionList) { + // get join type + String joinType = convertUnionTypeToSQL(unionParamDTO.getUnionType()); + // 如果不是全连接则需要校验连接方式 + if (!isFullJoin) { + if (StringUtils.equalsIgnoreCase(unionParamDTO.getUnionType(), "full")) { + isFullJoin = true; + } + } + + SQLObj parentSQLObj = unionParamDTO.getParentSQLObj(); + SQLObj currentSQLObj = unionParamDTO.getCurrentSQLObj(); + DatasetTableDTO parentDs = unionParamDTO.getParentDs(); + DatasetTableDTO currentDs1 = unionParamDTO.getCurrentDs(); + + String ts = ""; + String tablePrefix = ""; + String tableSuffix = ""; + if (ObjectUtils.isNotEmpty(currentSQLObj.getTableSchema())) { + if (isCross) { + tablePrefix = "`"; + tableSuffix = "`"; + } else { + DsTypeDTO datasourceType = getDatasourceType(dsMap, currentDs1.getDatasourceId()); + tablePrefix = datasourceType.getPrefix(); + tableSuffix = datasourceType.getSuffix(); + } + + ts = tablePrefix + currentSQLObj.getTableSchema() + tableSuffix + "."; + } + // build join + join.append(" ").append(joinType).append(" ") + .append(ts) + .append(tablePrefix + currentSQLObj.getTableName() + tableSuffix) + .append(" ").append(currentSQLObj.getTableAlias()).append(" ") + .append(" ON "); + if (unionParamDTO.getUnionFields().size() == 0) { + DEException.throwException(Translator.get("i18n_union_field_can_not_empty")); + } + for (int i = 0; i < unionParamDTO.getUnionFields().size(); i++) { + UnionItemDTO unionItemDTO = unionParamDTO.getUnionFields().get(i); + // 通过field id取得field详情,并且以第一组为准,寻找dataset table + DatasetTableFieldDTO parentField = unionItemDTO.getParentField(); + DatasetTableFieldDTO currentField = unionItemDTO.getCurrentField(); + String pPrefix = ""; + String pSuffix = ""; + if (Objects.equals(parentField.getExtField(), ExtFieldConstant.EXT_NORMAL)) { + if (isCross) { + pPrefix = "`"; + pSuffix = "`"; + } else { + DsTypeDTO datasourceType = getDatasourceType(dsMap, parentDs.getDatasourceId()); + pPrefix = datasourceType.getPrefix(); + pSuffix = datasourceType.getSuffix(); + } + } + String cPrefix = ""; + String cSuffix = ""; + if (Objects.equals(currentField.getExtField(), ExtFieldConstant.EXT_NORMAL)) { + if (isCross) { + cPrefix = "`"; + cSuffix = "`"; + } else { + DsTypeDTO datasourceType = getDatasourceType(dsMap, currentDs1.getDatasourceId()); + cPrefix = datasourceType.getPrefix(); + cSuffix = datasourceType.getSuffix(); + } + } + join.append(parentSQLObj.getTableAlias()).append(".") + .append(pPrefix + parentField.getOriginName() + pSuffix) + .append(" = ") + .append(currentSQLObj.getTableAlias()).append(".") + .append(cPrefix + currentField.getOriginName() + cSuffix); + if (i < unionParamDTO.getUnionFields().size() - 1) { + join.append(" AND "); + } + } + } + if (StringUtils.isEmpty(f)) { + DEException.throwException(Translator.get("i18n_union_ds_no_checked")); + } + sql = MessageFormat.format("SELECT {0} FROM {1}", f, TableUtils.getTableAndAlias(tableName, getDatasourceType(dsMap, currentDs.getDatasourceId()), isCross)) + join.toString(); + } else { + String f = StringUtils.join(checkedInfo.get(tableName.getTableAlias()), ","); + if (StringUtils.isEmpty(f)) { + DEException.throwException(Translator.get("i18n_union_ds_no_checked")); + } + sql = MessageFormat.format("SELECT {0} FROM {1}", f, TableUtils.getTableAndAlias(tableName, getDatasourceType(dsMap, currentDs.getDatasourceId()), isCross)); + } + logger.debug("calcite origin sql: " + sql); + Map map = new HashMap<>(); + map.put("sql", sql); + map.put("field", checkedFields); + map.put("join", unionList); + map.put("dsMap", dsMap); + map.put("isFullJoin", isFullJoin); + return map; + } + + // 递归计算出所有子级的checkedFields和unionParam + private void getUnionForEdit(DatasetTableDTO parentTable, SQLObj parentSQLObj, + List childrenDs, Map checkedInfo, + List unionList, List checkedFields, + Map dsMap, ChartExtRequest chartExtRequest, + boolean isCross) throws Exception { + for (int i = 0; i < childrenDs.size(); i++) { + int index = unionList.size() + 1; + + UnionDTO unionDTO = childrenDs.get(i); + DatasetTableDTO datasetTable = unionDTO.getCurrentDs(); + DatasetTableInfoDTO tableInfo = JsonUtil.parseObject(datasetTable.getInfo(), DatasetTableInfoDTO.class); + + String schema; + if (dsMap.containsKey(datasetTable.getDatasourceId())) { + schema = dsMap.get(datasetTable.getDatasourceId()).getSchemaAlias(); + } else { + schema = putObj2Map(dsMap, datasetTable, isCross); + } + SQLObj table = getUnionTable(datasetTable, tableInfo, schema, index, filterParameters(chartExtRequest, datasetTable.getId()), chartExtRequest == null, isCross, dsMap); + + List fields = unionDTO.getCurrentDsFields(); + fields = fields.stream().filter(DatasetTableFieldDTO::getChecked).collect(Collectors.toList()); + + String[] array = fields.stream() + .map(f -> { + String alias; + if (StringUtils.isEmpty(f.getGisbiName())) { + alias = TableUtils.fieldNameShort(table.getTableAlias() + "_" + f.getOriginName()); + } else { + alias = f.getGisbiName(); + } + + f.setFieldShortName(alias); + f.setGisbiName(f.getFieldShortName()); + f.setDatasetTableId(datasetTable.getId()); + String prefix = ""; + String suffix = ""; + if (Objects.equals(f.getExtField(), ExtFieldConstant.EXT_NORMAL)) { + if (isCross) { + prefix = "`"; + suffix = "`"; + } else { + DsTypeDTO datasourceType = getDatasourceType(dsMap, datasetTable.getDatasourceId()); + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } + } + return table.getTableAlias() + "." + prefix + f.getOriginName() + suffix + " AS " + prefix + alias + suffix; + }) + .toArray(String[]::new); + checkedInfo.put(table.getTableAlias(), array); + checkedFields.addAll(fields); + + UnionParamDTO unionToParent = unionDTO.getUnionToParent(); + // 设置关联关系中,两个table信息 + unionToParent.setParentDs(parentTable); + unionToParent.setParentSQLObj(parentSQLObj); + unionToParent.setCurrentDs(datasetTable); + unionToParent.setCurrentSQLObj(table); + unionList.add(unionToParent); + if (!CollectionUtils.isEmpty(unionDTO.getChildrenDs())) { + getUnionForEdit(datasetTable, table, unionDTO.getChildrenDs(), checkedInfo, unionList, checkedFields, dsMap, chartExtRequest, isCross); + } + } + } + + private Set getAllDs(List union) { + Set set = new HashSet<>(); + for (UnionDTO unionDTO : union) { + Long datasourceId = unionDTO.getCurrentDs().getDatasourceId(); + set.add(datasourceId); + getChildrenDs(unionDTO.getChildrenDs(), set); + } + return set; + } + + private void getChildrenDs(List childrenDs, Set set) { + for (UnionDTO unionDTO : childrenDs) { + set.add(unionDTO.getCurrentDs().getDatasourceId()); + if (!CollectionUtils.isEmpty(unionDTO.getChildrenDs())) { + getChildrenDs(unionDTO.getChildrenDs(), set); + } + } + } + + private DsTypeDTO getDatasourceType(Map dsMap, Long datasourceId) { + DatasourceSchemaDTO datasourceSchemaDTO = dsMap.get(datasourceId); + String type; + if (datasourceSchemaDTO == null) { + CoreDatasource coreDatasource = dataSourceManage.getCoreDatasource(datasourceId); + if (coreDatasource == null) { + DEException.throwException(Translator.get("i18n_dataset_ds_error") + ",ID:" + datasourceId); + } + type = engineManage.getDeEngine().getType(); + } else { + type = datasourceSchemaDTO.getType(); + } + + if (Arrays.stream(DatasourceConfiguration.DatasourceType.values()).map(DatasourceConfiguration.DatasourceType::getType).toList().contains(type)) { + DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(type); + DsTypeDTO dto = new DsTypeDTO(); + BeanUtils.copyBean(dto, datasourceType); + return dto; + } else { + List xpackPluginsDatasourceVOS = pluginManage.queryPluginDs(); + List list = xpackPluginsDatasourceVOS.stream().filter(ele -> StringUtils.equals(ele.getType(), type)).toList(); + if (ObjectUtils.isNotEmpty(list)) { + XpackPluginsDatasourceVO first = list.getFirst(); + DsTypeDTO dto = new DsTypeDTO(); + dto.setName(first.getName()); + dto.setCatalog(first.getCategory()); + dto.setType(first.getType()); + dto.setPrefix(first.getPrefix()); + dto.setSuffix(first.getSuffix()); + return dto; + } else { + DEException.throwException(Translator.get("i18n_dataset_plugin_error")); + } + return null; + } + } + + public String subPrefixSuffixChar(String str) { + while (StringUtils.startsWith(str, ",")) { + str = str.substring(1, str.length()); + } + while (StringUtils.endsWith(str, ",")) { + str = str.substring(0, str.length() - 1); + } + return str; + } + + private String convertUnionTypeToSQL(String unionType) { + switch (unionType) { + case "1:1": + case "inner": + return " INNER JOIN "; + case "1:N": + case "left": + return " LEFT JOIN "; + case "N:1": + case "right": + return " RIGHT JOIN "; + case "N:N": + case "full": + return " FULL JOIN "; + default: + return " INNER JOIN "; + } + } + + + + private SQLObj getUnionTable(DatasetTableDTO currentDs, DatasetTableInfoDTO infoDTO, String tableSchema, int index, List parameters, boolean isFromDataSet, boolean isCross, Map dsMap) { + SQLObj tableObj; + String tableAlias = String.format(SQLConstants.TABLE_ALIAS_PREFIX, index); + if (StringUtils.equalsIgnoreCase(currentDs.getType(), DatasetTableTypeConstants.DATASET_TABLE_DB)) { + tableObj = SQLObj.builder().tableSchema(tableSchema).tableName(infoDTO.getTable()).tableAlias(tableAlias).build(); + } else if (StringUtils.equalsIgnoreCase(currentDs.getType(), DatasetTableTypeConstants.DATASET_TABLE_SQL)) { + Provider provider = ProviderFactory.getProvider(dsMap.entrySet().iterator().next().getValue().getType()); + // parser sql params and replace default value + String s = new String(Base64.getDecoder().decode(infoDTO.getSql())); + String sql = new SqlparserUtils().handleVariableDefaultValue(s, currentDs.getSqlVariableDetails(), false, isFromDataSet, parameters, isCross, dsMap, pluginManage, null); + sql = provider.replaceComment(sql); + // add table schema + if (isCross) { + sql = SqlUtils.addSchema(sql, tableSchema); + } + tableObj = SQLObj.builder().tableSchema("").tableName("(" + sql + ")").tableAlias(tableAlias).build(); + } else { + // excel,api + tableObj = SQLObj.builder().tableSchema(tableSchema).tableName(infoDTO.getTable()).tableAlias(tableAlias).build(); + } + return tableObj; + } + + public String putObj2Map(Map dsMap, DatasetTableDTO ds, boolean isCross) { + + + + String schemaAlias; + if (StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.DB) || StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.SQL)) { + CoreDatasource coreDatasource = dataSourceManage.getCoreDatasource(ds.getDatasourceId()); + if (coreDatasource == null) { + DEException.throwException(Translator.get("i18n_dataset_ds_error") + ",ID:" + ds.getDatasourceId()); + } + if (coreDatasource.getType().contains(DatasourceConfiguration.DatasourceType.Excel.name()) || coreDatasource.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) { + coreDatasource = engineManage.getDeEngine(); + } + + Map map = JsonUtil.parseObject(coreDatasource.getConfiguration(), Map.class); + if (!isCross && ObjectUtils.isNotEmpty(map.get("schema"))) { + schemaAlias = (String) map.get("schema"); + } else { + schemaAlias = String.format(SQLConstants.SCHEMA, coreDatasource.getId()); + } + + if (!dsMap.containsKey(coreDatasource.getId())) { + DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO(); + BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource); + datasourceSchemaDTO.setSchemaAlias(schemaAlias); + dsMap.put(coreDatasource.getId(), datasourceSchemaDTO); + } + } else if (StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.Es)) { + CoreDatasource coreDatasource = dataSourceManage.getCoreDatasource(ds.getDatasourceId()); + schemaAlias = String.format(SQLConstants.SCHEMA, coreDatasource.getId()); + if (!dsMap.containsKey(coreDatasource.getId())) { + DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO(); + BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource); + datasourceSchemaDTO.setSchemaAlias(schemaAlias); + dsMap.put(coreDatasource.getId(), datasourceSchemaDTO); + } + } else { + CoreDatasource coreDatasource = engineManage.getDeEngine(); + schemaAlias = String.format(SQLConstants.SCHEMA, coreDatasource.getId()); + if (!dsMap.containsKey(coreDatasource.getId())) { + DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO(); + BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource); + datasourceSchemaDTO.setSchemaAlias(schemaAlias); + dsMap.put(coreDatasource.getId(), datasourceSchemaDTO); + } + } + return schemaAlias; + } + + + public void mergeDatasetCrossDefault(DatasetGroupInfoDTO ele) { + Set allDs = getAllDs(ele.getUnion()); + boolean isCross = allDs.size() > 1; + ele.setIsCross(isCross); + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/DatasetTableFieldManage.java b/backend/src/main/java/com/stdproject/service/manage/DatasetTableFieldManage.java new file mode 100644 index 0000000..3035137 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/DatasetTableFieldManage.java @@ -0,0 +1,256 @@ +package com.stdproject.service.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.stdproject.entity.CoreDatasetTableField; +import com.stdproject.mapper.CoreDatasetTableFieldMapper; +import com.stdproject.utils.TableUtils; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.dto.FieldGroupDTO; +import io.gisbi.extensions.view.dto.ColumnPermissionItem; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.AuthUtils; +import io.gisbi.utils.BeanUtils; +import io.gisbi.utils.IDUtils; +import io.gisbi.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Component +@Transactional +public class DatasetTableFieldManage { + @Resource + private CoreDatasetTableFieldMapper coreDatasetTableFieldMapper; + + @Autowired(required = false) + private PluginManageApi pluginManage; + + + + public DatasetTableFieldDTO chartFieldSave(DatasetTableFieldDTO datasetTableFieldDTO) { + checkNameLength(datasetTableFieldDTO.getName()); + CoreDatasetTableField coreDatasetTableField = coreDatasetTableFieldMapper.selectById(datasetTableFieldDTO.getId()); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("name", datasetTableFieldDTO.getName()); + wrapper.eq("chart_id", datasetTableFieldDTO.getChartId()); + if (ObjectUtils.isNotEmpty(coreDatasetTableField)) { + wrapper.ne("id", datasetTableFieldDTO.getId()); + } + List fields = coreDatasetTableFieldMapper.selectList(wrapper); + if (ObjectUtils.isNotEmpty(fields)) { + DEException.throwException(Translator.get("i18n_field_name_duplicated")); + } + datasetTableFieldDTO.setDatasetGroupId(null); + return save(datasetTableFieldDTO); + } + + /** + * 数据集保存时使用 + * + * @param datasetTableFieldDTO + * @return + */ + public DatasetTableFieldDTO save(DatasetTableFieldDTO datasetTableFieldDTO) { + checkNameLength(datasetTableFieldDTO.getName()); + CoreDatasetTableField coreDatasetTableField = coreDatasetTableFieldMapper.selectById(datasetTableFieldDTO.getId()); + CoreDatasetTableField record = transDTO2Record(datasetTableFieldDTO); + if (ObjectUtils.isEmpty(record.getGisbiName())) { + String n = TableUtils.fieldNameShort(record.getId() + ""); + record.setFieldShortName(n); + record.setGisbiName(n); + } + if (ObjectUtils.isEmpty(coreDatasetTableField)) { + coreDatasetTableFieldMapper.insert(record); + } else { + coreDatasetTableFieldMapper.updateById(record); + } + return datasetTableFieldDTO; + } + + public DatasetTableFieldDTO saveField(DatasetTableFieldDTO datasetTableFieldDTO) { + CoreDatasetTableField record = new CoreDatasetTableField(); + if (ObjectUtils.isEmpty(datasetTableFieldDTO.getId())) { + datasetTableFieldDTO.setId(IDUtils.snowID()); + BeanUtils.copyBean(record, datasetTableFieldDTO); + coreDatasetTableFieldMapper.insert(record); + } else { + BeanUtils.copyBean(record, datasetTableFieldDTO); + coreDatasetTableFieldMapper.updateById(record); + } + return datasetTableFieldDTO; + } + + public List getChartCalcFields(Long chartId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("chart_id", chartId); + return transDTO(coreDatasetTableFieldMapper.selectList(wrapper)); + } + + public void deleteById(Long id) { + coreDatasetTableFieldMapper.deleteById(id); + } + + public void deleteByDatasetTableUpdate(Long datasetTableId, List fieldIds) { + if (!CollectionUtils.isEmpty(fieldIds)) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_table_id", datasetTableId); + wrapper.notIn("id", fieldIds); + coreDatasetTableFieldMapper.delete(wrapper); + } + } + + public void deleteByDatasetGroupUpdate(Long datasetGroupId, List fieldIds) { + if (!CollectionUtils.isEmpty(fieldIds)) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", datasetGroupId); + wrapper.notIn("id", fieldIds); + coreDatasetTableFieldMapper.delete(wrapper); + } + } + + public void deleteByDatasetGroupDelete(Long datasetGroupId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", datasetGroupId); + coreDatasetTableFieldMapper.delete(wrapper); + } + + public void deleteByChartId(Long chartId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("chart_id", chartId); + coreDatasetTableFieldMapper.delete(wrapper); + } + + public List selectByDatasetTableId(Long id) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_table_id", id); + return transDTO(coreDatasetTableFieldMapper.selectList(wrapper)); + } + + public List selectByDatasetGroupId(Long id) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", id); + wrapper.eq("checked", true); + wrapper.isNull("chart_id"); + return transDTO(coreDatasetTableFieldMapper.selectList(wrapper)); + } + + public Map> selectByDatasetGroupIds(List ids) { + Map> map = new HashMap<>(); + for (Long id : ids) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", id); + wrapper.eq("checked", true); + wrapper.isNull("chart_id"); + wrapper.eq("ext_field", 0); + map.put(String.valueOf(id), transDTO(coreDatasetTableFieldMapper.selectList(wrapper))); + } + return map; + } + + public List selectByFieldIds(List ids) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.in("id", ids); + return transDTO(coreDatasetTableFieldMapper.selectList(wrapper)); + } + + public DatasetTableFieldDTO selectById(Long id) { + CoreDatasetTableField coreDatasetTableField = coreDatasetTableFieldMapper.selectById(id); + if (coreDatasetTableField == null) return null; + return transObj(coreDatasetTableField); + } + + /** + * 返回维度、指标列表 + * + * @return + */ + public Map> listByDQ(Long id) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", id); + wrapper.eq("checked", true); + List list = transDTO(coreDatasetTableFieldMapper.selectList(wrapper)); + List dimensionList = list.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "d")).collect(Collectors.toList()); + List quotaList = list.stream().filter(ele -> StringUtils.equalsIgnoreCase(ele.getGroupType(), "q")).collect(Collectors.toList()); + Map> map = new LinkedHashMap<>(); + map.put("dimensionList", dimensionList); + map.put("quotaList", quotaList); + return map; + } + + + public List listFieldsWithPermissions(Long id) { + List fields = selectByDatasetGroupId(id); + Map desensitizationList = new HashMap<>(); + Long userId = AuthUtils.getUser() == null ? null : AuthUtils.getUser().getUserId(); + List tmp = fields; + tmp.forEach(ele -> ele.setDesensitized(desensitizationList.containsKey(ele.getGisbiName()))); + return tmp; + } + + + + public DatasetTableFieldDTO transObj(CoreDatasetTableField ele) { + DatasetTableFieldDTO dto = new DatasetTableFieldDTO(); + if (ele == null) return null; + BeanUtils.copyBean(dto, ele); + if (StringUtils.isNotEmpty(ele.getParams())) { + TypeReference> tokenType = new TypeReference<>() { + }; + List calParams = JsonUtil.parseList(ele.getParams(), tokenType); + dto.setParams(calParams); + } + if (StringUtils.isNotEmpty(ele.getGroupList())) { + TypeReference> groupTokenType = new TypeReference<>() { + }; + List fieldGroups = JsonUtil.parseList(ele.getGroupList(), groupTokenType); + dto.setGroupList(fieldGroups); + } + return dto; + } + + public List transDTO(List list) { + if (!CollectionUtils.isEmpty(list)) { + return list.stream().map(this::transObj).collect(Collectors.toList()); + } else { + return new ArrayList<>(); + } + } + + private CoreDatasetTableField transDTO2Record(DatasetTableFieldDTO dto) { + CoreDatasetTableField record = new CoreDatasetTableField(); + BeanUtils.copyBean(record, dto); + if (ObjectUtils.isNotEmpty(dto.getParams())) { + record.setParams(JsonUtil.toJSONString(dto.getParams()).toString()); + } + if (ObjectUtils.isNotEmpty(dto.getGroupList())) { + record.setGroupList(JsonUtil.toJSONString(dto.getGroupList()).toString()); + } + return record; + } + + private void checkNameLength(String name) { + if (name != null && name.length() > 100) { + DEException.throwException(Translator.get("i18n_name_limit_100")); + } + } + + public boolean isCopilotSupport(Map dsMap) { + DatasourceSchemaDTO value = dsMap.entrySet().iterator().next().getValue(); + return StringUtils.equalsIgnoreCase(value.getType(), "mysql"); + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/DatasetTableManage.java b/backend/src/main/java/com/stdproject/service/manage/DatasetTableManage.java new file mode 100644 index 0000000..ccaed3f --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/DatasetTableManage.java @@ -0,0 +1,53 @@ +package com.stdproject.service.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.stdproject.entity.CoreDatasetTable; +import com.stdproject.mapper.CoreDatasetTableMapper; +import io.gisbi.exception.DEException; +import io.gisbi.i18n.Translator; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.List; + +/** + * @Author bi-coder + */ +@Component +public class DatasetTableManage { + @Resource + private CoreDatasetTableMapper coreDatasetTableMapper; + + + public List selectByDatasetGroupId(Long datasetGroupId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", datasetGroupId); + return coreDatasetTableMapper.selectList(wrapper); + } + + public CoreDatasetTable selectById(Long id) { + return coreDatasetTableMapper.selectById(id); + } + + public void deleteByDatasetGroupUpdate(Long datasetGroupId, List ids) { + if (!CollectionUtils.isEmpty(ids)) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", datasetGroupId); + wrapper.notIn("id", ids); + coreDatasetTableMapper.delete(wrapper); + } + } + + public void deleteByDatasetGroupDelete(Long datasetGroupId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("dataset_group_id", datasetGroupId); + coreDatasetTableMapper.delete(wrapper); + } + + private void checkNameLength(String name) { + if (name != null && name.length() > 100) { + DEException.throwException(Translator.get("i18n_name_limit_100")); + } + } +} diff --git a/backend/src/main/java/com/stdproject/service/manage/DefaultChartHandler.java b/backend/src/main/java/com/stdproject/service/manage/DefaultChartHandler.java new file mode 100644 index 0000000..63dcbad --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/manage/DefaultChartHandler.java @@ -0,0 +1,854 @@ +package com.stdproject.service.manage; + +import com.beust.jcommander.Strings; +import com.stdproject.constant.ChartConstants; +import com.stdproject.entity.union.DatasetGroupInfoDTO; +import com.stdproject.service.provider.SQLProvider; +import com.stdproject.utils.Utils; +import com.stdproject.utils.trans.Dimension2SQLObj; +import com.stdproject.utils.trans.Quota2SQLObj; +import io.gisbi.constant.SQLConstants; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceRequest; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.provider.Provider; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.datasource.vo.XpackPluginsDatasourceVO; +import io.gisbi.extensions.view.dto.*; +import io.gisbi.extensions.view.plugin.AbstractChartPlugin; +import io.gisbi.extensions.view.util.ChartDataUtil; +import io.gisbi.extensions.view.util.FieldUtil; +import io.gisbi.utils.BeanUtils; +import io.gisbi.utils.JsonUtil; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.Getter; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +@Component +public class DefaultChartHandler extends AbstractChartPlugin { + public static Logger logger = LoggerFactory.getLogger(ChartDataManage.class); + @Resource + protected ChartHandlerManager chartHandlerManager; + @Resource + protected DatasetTableFieldManage datasetTableFieldManage; + @Resource + protected ChartViewManege chartViewManege; + @Getter + private String render = "antv"; + @Getter + private String type = "*"; + @Autowired(required = false) + public PluginManageApi pluginManage; + + @PostConstruct + public void init() { + chartHandlerManager.registerChartHandler(this.getRender(), this.getType(), this); + } + + @Override + public AxisFormatResult formatAxis(ChartViewDTO view) { + var axisMap = new HashMap>(); + var context = new HashMap(); + var result = new AxisFormatResult(axisMap, context); + axisMap.put(ChartAxis.xAxis, new ArrayList<>(view.getXAxis())); + axisMap.put(ChartAxis.yAxis, new ArrayList<>(view.getYAxis())); + axisMap.put(ChartAxis.drill, new ArrayList<>(view.getDrillFields())); + return result; + } + + @Override + public T customFilter(ChartViewDTO view, List filterList, AxisFormatResult formatResult) { + var desensitizationList = (Map) formatResult.getContext().get("desensitizationList"); + if (MapUtils.isNotEmpty(desensitizationList)) { + formatResult.getAxisMap().forEach((axis, fields) -> { + fields.removeIf(f -> desensitizationList.containsKey(f.getGisbiName())); + }); + } + return (T) new CustomFilterResult(filterList, formatResult.getContext()); + } + + public Map buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List data) { + boolean isDrill = filterResult + .getFilterList() + .stream() + .anyMatch(ele -> ele.getFilterType() == 1); + var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis); + var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis); + Map result = ChartDataBuild.transChartData(xAxis, yAxis, view, data, isDrill); + return result; + } + + @Override + public T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map sqlMap, SQLMeta sqlMeta, Provider provider) { + var dsMap = (Map) sqlMap.get("dsMap"); + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + boolean needOrder = Utils.isNeedOrder(dsList); + boolean crossDs = ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross(); + DatasourceRequest datasourceRequest = new DatasourceRequest(); + datasourceRequest.setIsCross(crossDs); + datasourceRequest.setDsList(dsMap); + var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis); + var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis); + var allFields = (List) filterResult.getContext().get("allFields"); + Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage); + Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap, Utils.getParams(FieldUtil.transFields(allFields)), view.getCalParams(), pluginManage); + String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view); + querySql = provider.rebuildSQL(querySql, sqlMeta, crossDs, dsMap); + datasourceRequest.setQuery(querySql); + logger.debug("calcite chart sql: " + querySql); + List data = (List) provider.fetchResultField(datasourceRequest).get("data"); + //自定义排序 + data = ChartDataUtil.resultCustomSort(xAxis, yAxis, view.getSortPriority(), data); + //快速计算 + var extStack = formatResult.getAxisMap().get(ChartAxis.extStack); + var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt); + quickCalc(xAxis, yAxis, xAxisExt, extStack, view.getType(), data); + //数据重组逻辑可重载 + var result = this.buildResult(view, formatResult, filterResult, data); + T calcResult = (T) new ChartCalcDataResult(); + calcResult.setData(result); + calcResult.setContext(filterResult.getContext()); + calcResult.setQuerySql(querySql); + calcResult.setOriginData(data); + return calcResult; + } + + @Override + public ChartViewDTO buildChart(ChartViewDTO view, ChartCalcDataResult calcResult, AxisFormatResult formatResult, CustomFilterResult filterResult) { + var desensitizationList = (Map) filterResult.getContext().get("desensitizationList"); + var allFields = (List) filterResult.getContext().get("allFields"); + var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis); + var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis); + // 如果是表格导出查询 则在此处直接就可以返回 + var extStack = formatResult.getAxisMap().get(ChartAxis.extStack); + if (CollectionUtils.isNotEmpty(extStack) && xAxis.size() > extStack.size()) { + xAxis = xAxis.subList(0, xAxis.size() - extStack.size()); + } + if (view.getIsExcelExport()) { + Map sourceInfo = ChartDataBuild.transTableNormal(xAxis, yAxis, view, calcResult.getOriginData(), extStack, desensitizationList); + sourceInfo.put("sourceData", calcResult.getOriginData()); + view.setData(sourceInfo); + return view; + } + + Map mapTableNormal = ChartDataBuild.transTableNormal(xAxis, yAxis, view, calcResult.getOriginData(), extStack, desensitizationList); + var drillFilters = filterResult.getFilterList().stream().filter(f -> f.getFilterType() == 1).collect(Collectors.toList()); + // 日期下钻替换回去 + drillFilters.forEach(f -> { + if (CollectionUtils.isNotEmpty(f.getOriginValue())) { + f.setValue(f.getOriginValue()); + } + }); + var isDrill = CollectionUtils.isNotEmpty(drillFilters); + // 构建结果 + Map dataMap = new HashMap<>(); + dataMap.putAll(calcResult.getData()); + dataMap.putAll(mapTableNormal); + dataMap.put("sourceFields", allFields); + List chartSeniorAssistDTOS = mergeAssistField(calcResult.getDynamicAssistFields(), calcResult.getAssistData(), calcResult.getDynamicAssistFieldsOriginList(), calcResult.getAssistDataOriginList()); + dataMap.put("dynamicAssistLines", chartSeniorAssistDTOS); + view.setData(dataMap); + view.setSql(Base64.getEncoder().encodeToString(calcResult.getQuerySql().getBytes())); + view.setDrill(isDrill); + view.setDrillFilters(drillFilters); + return view; + } + + protected List mergeAssistField(List dynamicAssistFields, List assistData, List dynamicAssistFieldsOriginList, List assistDataOriginList) { + List list = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(assistData)) { + String[] strings = assistData.getFirst(); + for (int i = 0; i < dynamicAssistFields.size(); i++) { + if (i < strings.length) { + ChartSeniorAssistDTO chartSeniorAssistDTO = dynamicAssistFields.get(i); + chartSeniorAssistDTO.setValue(strings[i]); + list.add(chartSeniorAssistDTO); + } + } + } + + if (ObjectUtils.isNotEmpty(assistDataOriginList)) { + String[] stringsOriginList = assistDataOriginList.getLast();// 取最后一项,如果有其他运算逻辑需要取明细数据可增加逻辑 + for (int i = 0; i < dynamicAssistFieldsOriginList.size(); i++) { + if (i < stringsOriginList.length) { + ChartSeniorAssistDTO chartSeniorAssistDTO = dynamicAssistFieldsOriginList.get(i); + chartSeniorAssistDTO.setValue(stringsOriginList[i]); + list.add(chartSeniorAssistDTO); + } + } + } + return list; + } + + protected List getDynamicAssistFields(ChartViewDTO view) { + List list = new ArrayList<>(); + + Map senior = view.getSenior(); + if (ObjectUtils.isEmpty(senior)) { + return list; + } + + ChartSeniorAssistCfgDTO assistLineCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("assistLineCfg")), ChartSeniorAssistCfgDTO.class); + if (null == assistLineCfg || !assistLineCfg.isEnable()) { + return list; + } + List assistLines = assistLineCfg.getAssistLine(); + + if (ObjectUtils.isEmpty(assistLines)) { + return list; + } + + for (ChartSeniorAssistDTO dto : assistLines) { + if (StringUtils.equalsIgnoreCase(dto.getField(), "0")) { + continue; + } + Long fieldId = dto.getFieldId(); + String summary = dto.getSummary(); + if (ObjectUtils.isEmpty(fieldId) || StringUtils.isEmpty(summary)) { + continue; + } + + DatasetTableFieldDTO datasetTableFieldDTO = datasetTableFieldManage.selectById(fieldId); + + if (ObjectUtils.isEmpty(datasetTableFieldDTO)) { + continue; + } + list.add(dto); + } + return list; + } + + protected List getAssistFields(List list, List yAxis) { + List res = new ArrayList<>(); + for (ChartSeniorAssistDTO dto : list) { + DatasetTableFieldDTO curField = dto.getCurField(); + ChartViewFieldDTO yField = null; + String alias = ""; + for (int i = 0; i < yAxis.size(); i++) { + ChartViewFieldDTO field = yAxis.get(i); + if (Objects.equals(field.getId(), curField.getId())) { + yField = field; + alias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + break; + } + } + if (ObjectUtils.isEmpty(yField)) { + continue; + } + + ChartViewFieldDTO chartViewFieldDTO = new ChartViewFieldDTO(); + BeanUtils.copyBean(chartViewFieldDTO, curField); + chartViewFieldDTO.setSummary(dto.getSummary()); + chartViewFieldDTO.setOriginName(alias);// yAxis的字段别名,就是查找的字段名 + res.add(chartViewFieldDTO); + } + return res; + } + + protected List getAssistFields(List list, List yAxis, List xAxis) { + List res = new ArrayList<>(); + for (ChartSeniorAssistDTO dto : list) { + DatasetTableFieldDTO curField = dto.getCurField(); + ChartViewFieldDTO field = null; + String alias = ""; + for (int i = 0; i < yAxis.size(); i++) { + ChartViewFieldDTO yField = yAxis.get(i); + if (Objects.equals(yField.getId(), curField.getId())) { + field = yField; + alias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + break; + } + } + if (ObjectUtils.isEmpty(field) && CollectionUtils.isNotEmpty(xAxis)) { + for (int i = 0; i < xAxis.size(); i++) { + ChartViewFieldDTO xField = xAxis.get(i); + if (StringUtils.equalsIgnoreCase(String.valueOf(xField.getId()), String.valueOf(curField.getId()))) { + field = xField; + alias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + break; + } + } + } + if (ObjectUtils.isEmpty(field)) { + continue; + } + + ChartViewFieldDTO chartViewFieldDTO = new ChartViewFieldDTO(); + BeanUtils.copyBean(chartViewFieldDTO, curField); + chartViewFieldDTO.setSummary(dto.getSummary()); + chartViewFieldDTO.setOriginName(alias);// yAxis的字段别名,就是查找的字段名 + res.add(chartViewFieldDTO); + } + return res; + } + + public List getDynamicThresholdFields(ChartViewDTO view) { + List list = new ArrayList<>(); + Map senior = view.getSenior(); + if (ObjectUtils.isEmpty(senior)) { + return list; + } + ChartSeniorThresholdCfgDTO thresholdCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("threshold")), ChartSeniorThresholdCfgDTO.class); + + if (null == thresholdCfg || !thresholdCfg.isEnable()) { + return list; + } + List tableThreshold = thresholdCfg.getTableThreshold(); + + if (ObjectUtils.isEmpty(tableThreshold)) { + return list; + } + + List conditionsList = tableThreshold.stream() + .filter(item -> !ObjectUtils.isEmpty(item)) + .map(TableThresholdDTO::getConditions) + .flatMap(List::stream) + .filter(condition -> StringUtils.equalsAnyIgnoreCase(condition.getType(), "dynamic")) + .toList(); + + List assistDTOs = conditionsList.stream() + .flatMap(condition -> getConditionFields(condition).stream()) + .filter(this::solveThresholdCondition) + .toList(); + + list.addAll(assistDTOs); + + return list; + } + + private boolean solveThresholdCondition(ChartSeniorAssistDTO fieldDTO) { + Long fieldId = fieldDTO.getFieldId(); + String summary = fieldDTO.getValue(); + if (ObjectUtils.isEmpty(fieldId) || StringUtils.isEmpty(summary)) { + return false; + } + + DatasetTableFieldDTO datasetTableFieldDTO = datasetTableFieldManage.selectById(fieldId); + if (ObjectUtils.isEmpty(datasetTableFieldDTO)) { + return false; + } + ChartViewFieldDTO datasetTableField = new ChartViewFieldDTO(); + BeanUtils.copyBean(datasetTableField, datasetTableFieldDTO); + fieldDTO.setCurField(datasetTableField); + fieldDTO.setSummary(summary); + return true; + } + + private List getConditionFields(ChartSeniorThresholdDTO condition) { + List list = new ArrayList<>(); + if ("between".equals(condition.getTerm())) { + if (!StringUtils.equalsIgnoreCase(condition.getDynamicMaxField().getSummary(), "value")) { + list.add(of(condition.getDynamicMaxField())); + } + if (!StringUtils.equalsIgnoreCase(condition.getDynamicMinField().getSummary(), "value")) { + list.add(of(condition.getDynamicMinField())); + } + } else { + if (!StringUtils.equalsIgnoreCase(condition.getDynamicField().getSummary(), "value")) { + list.add(of(condition.getDynamicField())); + } + } + + return list; + } + + private ChartSeniorAssistDTO of(ThresholdDynamicFieldDTO dynamicField) { + ChartSeniorAssistDTO conditionField = new ChartSeniorAssistDTO(); + conditionField.setFieldId(Long.parseLong(dynamicField.getFieldId())); + conditionField.setValue(dynamicField.getSummary()); + return conditionField; + } + + protected String assistSQL(String sql, List assistFields, Map dsMap, boolean crossDs) { + // get datasource prefix and suffix + String dsType = dsMap.entrySet().iterator().next().getValue().getType(); + String prefix = ""; + String suffix = ""; + if (Arrays.stream(DatasourceConfiguration.DatasourceType.values()).map(DatasourceConfiguration.DatasourceType::getType).toList().contains(dsType)) { + DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(dsType); + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } else { + List xpackPluginsDatasourceVOS = pluginManage.queryPluginDs(); + List list = xpackPluginsDatasourceVOS.stream().filter(ele -> StringUtils.equals(ele.getType(), dsType)).toList(); + if (ObjectUtils.isNotEmpty(list)) { + XpackPluginsDatasourceVO first = list.getFirst(); + prefix = first.getPrefix(); + suffix = first.getSuffix(); + } else { + DEException.throwException("当前数据源插件不存在"); + } + } + + List fieldList = new ArrayList<>(); + for (int i = 0; i < assistFields.size(); i++) { + ChartViewFieldDTO dto = assistFields.get(i); + if (StringUtils.equalsIgnoreCase(dto.getSummary(), "last_item")) { + continue; + } + if (crossDs) { + fieldList.add(dto.getSummary() + "(" + dto.getOriginName() + ")"); + } else { + fieldList.add(dto.getSummary() + "(" + prefix + dto.getOriginName() + suffix + ")"); + } + } + return "SELECT " + Strings.join(",", fieldList) + " FROM (" + sql + ") tmp"; + } + + protected String assistSQLOriginList(String sql, List assistFields, Map dsMap, boolean crossDs) { + // get datasource prefix and suffix + String dsType = dsMap.entrySet().iterator().next().getValue().getType(); + String prefix = ""; + String suffix = ""; + if (Arrays.stream(DatasourceConfiguration.DatasourceType.values()).map(DatasourceConfiguration.DatasourceType::getType).toList().contains(dsType)) { + DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(dsType); + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } else { + List xpackPluginsDatasourceVOS = pluginManage.queryPluginDs(); + List list = xpackPluginsDatasourceVOS.stream().filter(ele -> StringUtils.equals(ele.getType(), dsType)).toList(); + if (ObjectUtils.isNotEmpty(list)) { + XpackPluginsDatasourceVO first = list.getFirst(); + prefix = first.getPrefix(); + suffix = first.getSuffix(); + } else { + DEException.throwException("当前数据源插件不存在"); + } + } + + List fieldList = new ArrayList<>(); + for (int i = 0; i < assistFields.size(); i++) { + ChartViewFieldDTO dto = assistFields.get(i); + if (StringUtils.equalsIgnoreCase(dto.getSummary(), "last_item")) { + if (crossDs) { + fieldList.add(dto.getOriginName()); + } else { + fieldList.add(prefix + dto.getOriginName() + suffix); + } + } + } + return "SELECT " + Strings.join(",", fieldList) + " FROM (" + sql + ") tmp"; + } + + protected List mergeIds(List xAxisExt, List extStack) { + Set idSet = new HashSet<>(); + if (xAxisExt != null) { + xAxisExt.forEach(field -> idSet.add(String.valueOf(field.getId()))); + } + if (extStack != null) { + extStack.forEach(field -> idSet.add(String.valueOf(field.getId()))); + } + return new ArrayList<>(idSet); + } + + protected void quickCalc(List xAxis, List yAxis + , List xAxisExt, List extStack, String chartType, List data) { + for (int i = 0; i < yAxis.size(); i++) { + ChartViewFieldDTO chartViewFieldDTO = yAxis.get(i); + ChartFieldCompareDTO compareCalc = chartViewFieldDTO.getCompareCalc(); + if (ObjectUtils.isEmpty(compareCalc)) { + continue; + } + if (StringUtils.isNotEmpty(compareCalc.getType()) + && !StringUtils.equalsIgnoreCase(compareCalc.getType(), "none")) { + Long compareFieldId = compareCalc.getField();// 选中字段 + // 数据字段下标 + int dataIndex = xAxis.size() + i; + if (Arrays.asList(ChartConstants.M_Y).contains(compareCalc.getType())) { + String resultData = compareCalc.getResultData();// 数据设置 + // 获取选中字段以及下标 + List checkedField = new ArrayList<>(xAxis); + int timeIndex = 0;// 时间字段下标 + ChartViewFieldDTO timeField = null; + for (int j = 0; j < checkedField.size(); j++) { + if (Objects.equals(checkedField.get(j).getId(), compareFieldId)) { + timeIndex = j; + timeField = checkedField.get(j); + } + } + // 无选中字段,或者选中字段已经不在维度list中,或者选中字段日期格式不符合对比类型的,直接将对应数据置为null + if (ObjectUtils.isEmpty(timeField) || !checkCalcType(timeField.getDateStyle(), compareCalc.getType())) { + // set null + for (String[] item : data) { + item[dataIndex] = null; + } + } else { + // 计算 同比/环比 + // 1,处理当期数据;2,根据type计算上一期数据;3,根据resultData计算结果 + Map currentMap = new LinkedHashMap<>(); + for (String[] item : data) { + String[] dimension = Arrays.copyOfRange(item, 0, checkedField.size()); + currentMap.put(StringUtils.join(dimension, "-"), item[dataIndex]); + } + + for (int index = 0; index < data.size(); index++) { + String[] item = data.get(index); + String cTime = item[timeIndex]; + String cValue = item[dataIndex]; + + // 获取计算后的时间,并且与所有维度拼接 + String lastTime = calcLastTime(cTime, compareCalc.getType(), timeField.getDateStyle(), timeField.getDatePattern()); + String[] dimension = Arrays.copyOfRange(item, 0, checkedField.size()); + dimension[timeIndex] = lastTime; + + String lastValue = currentMap.get(StringUtils.join(dimension, "-")); + if (StringUtils.isEmpty(cValue) || StringUtils.isEmpty(lastValue)) { + item[dataIndex] = null; + } else { + if (StringUtils.equalsIgnoreCase(resultData, "sub")) { + item[dataIndex] = new BigDecimal(cValue).subtract(new BigDecimal(lastValue)).toString(); + } else if (StringUtils.equalsIgnoreCase(resultData, "percent")) { + if (new BigDecimal(lastValue).compareTo(BigDecimal.ZERO) == 0) { + item[dataIndex] = null; + } else { + item[dataIndex] = new BigDecimal(cValue) + .divide(new BigDecimal(lastValue).abs(), 8, RoundingMode.HALF_UP) + .subtract(new BigDecimal(1)) + .setScale(8, RoundingMode.HALF_UP) + .toString(); + } + } else if (StringUtils.equalsIgnoreCase(resultData, "pre")) { + item[dataIndex] = new BigDecimal(lastValue).toString(); + } + } + } + } + } else if (StringUtils.equalsIgnoreCase(compareCalc.getType(), "percent")) { + // 求和 + BigDecimal sum = new BigDecimal(0); + for (int index = 0; index < data.size(); index++) { + String[] item = data.get(index); + String cValue = item[dataIndex]; + if (StringUtils.isEmpty(cValue)) { + continue; + } + sum = sum.add(new BigDecimal(cValue)); + } + // 计算占比 + for (int index = 0; index < data.size(); index++) { + String[] item = data.get(index); + String cValue = item[dataIndex]; + if (StringUtils.isEmpty(cValue)) { + continue; + } + item[dataIndex] = new BigDecimal(cValue) + .divide(sum, 8, RoundingMode.HALF_UP) + .toString(); + } + } else if (StringUtils.equalsIgnoreCase(compareCalc.getType(), "accumulate")) { + // 累加 + if (CollectionUtils.isEmpty(data)) { + break; + } + if (Objects.isNull(extStack)) { + extStack = Arrays.asList(); + } + if (Objects.isNull(xAxisExt)) { + xAxisExt = Arrays.asList(); + } + boolean isStack = StringUtils.containsIgnoreCase(chartType, "stack") && CollectionUtils.isNotEmpty(extStack); + boolean isGroup = StringUtils.containsIgnoreCase(chartType, "group") + || (CollectionUtils.isNotEmpty(xAxisExt)); + if (isStack || isGroup) { + if (CollectionUtils.isEmpty(xAxis)) { + break; + } + final Map mainIndexMap = new HashMap<>(); + final List> mainMatrix = new ArrayList<>(); + // 排除group和stack的字段 + List groupStackAxisIds = mergeIds(xAxisExt, extStack); + List xAxisBase = xAxis.stream().filter(ele -> !groupStackAxisIds.contains(String.valueOf(ele.getId()))).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(xAxisBase) && CollectionUtils.isNotEmpty(xAxis)) { + xAxisBase.add(xAxis.get(0)); + } + data.forEach(item -> { + String[] mainAxisArr = Arrays.copyOfRange(item, 0, xAxisBase.size()); + String mainAxis = StringUtils.join(mainAxisArr, '-'); + Integer index = mainIndexMap.get(mainAxis); + if (index == null) { + mainIndexMap.put(mainAxis, mainMatrix.size()); + List tmp = new ArrayList<>(); + tmp.add(item); + mainMatrix.add(tmp); + } else { + List tmp = mainMatrix.get(index); + tmp.add(item); + } + }); + int finalDataIndex = dataIndex; + int subEndIndex = xAxisBase.size(); + if (CollectionUtils.isNotEmpty(xAxisExt) + || StringUtils.containsIgnoreCase(chartType, "group") + || StringUtils.containsIgnoreCase(chartType, "-mix")) { + subEndIndex += xAxisExt.size(); + } + if (StringUtils.containsIgnoreCase(chartType, "stack")) { + subEndIndex += extStack.size(); + } + int finalSubEndIndex = subEndIndex; + // 存储上次的值 + Map preDataMap = new HashMap<>(); + //滑动累加 + for (int k = 1; k < mainMatrix.size(); k++) { + List preDataItems = mainMatrix.get(k - 1); + List curDataItems = mainMatrix.get(k); + preDataItems.forEach(preDataItem -> { + String[] groupStackAxisArr = Arrays.copyOfRange(preDataItem, xAxisBase.size(), finalSubEndIndex); + String groupStackAxis = StringUtils.join(groupStackAxisArr, '-'); + String preVal = preDataItem[finalDataIndex]; + if (StringUtils.isBlank(preVal)) { + preVal = "0"; + } + preDataMap.put(groupStackAxis, new BigDecimal(preVal)); + }); + curDataItems.forEach(curDataItem -> { + String[] groupStackAxisArr = Arrays.copyOfRange(curDataItem, xAxisBase.size(), finalSubEndIndex); + String groupStackAxis = StringUtils.join(groupStackAxisArr, '-'); + BigDecimal preValue = preDataMap.get(groupStackAxis); + if (preValue != null) { + curDataItem[finalDataIndex] = new BigDecimal(curDataItem[finalDataIndex]) + .add(preValue) + .toString(); + } else { + if (preDataMap.containsKey(groupStackAxis)) { + curDataItem[finalDataIndex] = new BigDecimal(curDataItem[finalDataIndex]) + .add(preDataMap.get(groupStackAxis)) + .toString(); + } + } + }); + } + } else { + final int index = dataIndex; + final AtomicReference accumValue = new AtomicReference<>(new BigDecimal(0)); + data.forEach(item -> { + String val = item[index]; + BigDecimal curAccumValue = accumValue.get(); + if (!StringUtils.isBlank(val)) { + BigDecimal curVal = new BigDecimal(val); + curAccumValue = curAccumValue.add(curVal); + accumValue.set(curAccumValue); + } + item[index] = curAccumValue.toString(); + }); + } + } + } + } + } + + private String calcLastTime(String cTime, String type, String dateStyle, String datePattern) { + try { + String lastTime = null; + Calendar calendar = Calendar.getInstance(); + if (StringUtils.equalsIgnoreCase(type, ChartConstants.YEAR_MOM)) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy"); + Date date = simpleDateFormat.parse(cTime); + calendar.setTime(date); + calendar.add(Calendar.YEAR, -1); + lastTime = simpleDateFormat.format(calendar.getTime()); + } else if (StringUtils.equalsIgnoreCase(type, ChartConstants.MONTH_MOM)) { + SimpleDateFormat simpleDateFormat = null; + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + simpleDateFormat = new SimpleDateFormat("yyyy/MM"); + } else { + simpleDateFormat = new SimpleDateFormat("yyyy-MM"); + } + Date date = simpleDateFormat.parse(cTime); + calendar.setTime(date); + calendar.add(Calendar.MONTH, -1); + lastTime = simpleDateFormat.format(calendar.getTime()); + } else if (StringUtils.equalsIgnoreCase(type, ChartConstants.YEAR_YOY)) { + SimpleDateFormat simpleDateFormat = null; + if (StringUtils.equalsIgnoreCase(dateStyle, "y_M")) { + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + simpleDateFormat = new SimpleDateFormat("yyyy/MM"); + } else { + simpleDateFormat = new SimpleDateFormat("yyyy-MM"); + } + } else if (StringUtils.equalsIgnoreCase(dateStyle, "y_M_d")) { + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd"); + } else { + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + } + } + Date date = simpleDateFormat.parse(cTime); + calendar.setTime(date); + calendar.add(Calendar.YEAR, -1); + lastTime = simpleDateFormat.format(calendar.getTime()); + } else if (StringUtils.equalsIgnoreCase(type, ChartConstants.DAY_MOM)) { + SimpleDateFormat simpleDateFormat = null; + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd"); + } else { + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + } + Date date = simpleDateFormat.parse(cTime); + calendar.setTime(date); + calendar.add(Calendar.DAY_OF_MONTH, -1); + lastTime = simpleDateFormat.format(calendar.getTime()); + } else if (StringUtils.equalsIgnoreCase(type, ChartConstants.MONTH_YOY)) { + SimpleDateFormat simpleDateFormat = null; + if (StringUtils.equalsIgnoreCase(dateStyle, "y_M")) { + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + simpleDateFormat = new SimpleDateFormat("yyyy/MM"); + } else { + simpleDateFormat = new SimpleDateFormat("yyyy-MM"); + } + } else if (StringUtils.equalsIgnoreCase(dateStyle, "y_M_d")) { + if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd"); + } else { + simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + } + } + Date date = simpleDateFormat.parse(cTime); + calendar.setTime(date); + calendar.add(Calendar.MONTH, -1); + lastTime = simpleDateFormat.format(calendar.getTime()); + } + return lastTime; + } catch (Exception e) { + return cTime; + } + } + + private boolean checkCalcType(String dateStyle, String calcType) { + switch (dateStyle) { + case "y": + return StringUtils.equalsIgnoreCase(calcType, "year_mom"); + case "y_M": + return StringUtils.equalsIgnoreCase(calcType, "month_mom") + || StringUtils.equalsIgnoreCase(calcType, "year_yoy"); + case "y_M_d": + return StringUtils.equalsIgnoreCase(calcType, "day_mom") + || StringUtils.equalsIgnoreCase(calcType, "month_yoy") + || StringUtils.equalsIgnoreCase(calcType, "year_yoy"); + } + return false; + } + + protected boolean checkYoyFilter(List filter, List yoyAxis) { + boolean flag = false; + for (ChartExtFilterDTO filterDTO : filter) { + for (ChartViewFieldDTO chartViewFieldDTO : yoyAxis) { + ChartFieldCompareDTO compareCalc = chartViewFieldDTO.getCompareCalc(); + if (ObjectUtils.isEmpty(compareCalc)) { + continue; + } + if (StringUtils.isNotEmpty(compareCalc.getType()) + && !StringUtils.equalsIgnoreCase(compareCalc.getType(), "none")) { + if (Arrays.asList(ChartConstants.M_Y).contains(compareCalc.getType())) { + if (StringUtils.equalsIgnoreCase(compareCalc.getField() + "", filterDTO.getFieldId()) + && (filterDTO.getFilterType() == 0 || filterDTO.getFilterType() == 2)) { + // -1 year + try { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date(Long.parseLong(filterDTO.getValue().getFirst()))); + calendar.add(Calendar.YEAR, -1); + filterDTO.getValue().set(0, String.valueOf(calendar.getTime().getTime())); + flag = true; + } catch (Exception e) { + } + } + } + } + } + } + return flag; + } + protected void groupStackDrill(List xAxis, + List filterList, + List fieldsToFilter, + List drillFields, + List drillRequestList) { + var fields = xAxis.stream().map(ChartViewFieldDTO::getId).collect(Collectors.toSet()); + ChartDrillRequest head = drillRequestList.getFirst(); + Map dimValMap = new HashMap<>(); + head.getDimensionList().forEach(item -> dimValMap.put(item.getId(), item.getValue())); + Map fieldMap = xAxis.stream().collect(Collectors.toMap(ChartViewFieldDTO::getId, o -> o, ((p, n) -> p))); + for (int i = 0; i < drillRequestList.size(); i++) { + ChartDrillRequest request = drillRequestList.get(i); + ChartViewFieldDTO chartViewFieldDTO = drillFields.get(i); + for (ChartDimensionDTO requestDimension : request.getDimensionList()) { + // 将钻取值作为条件传递,将所有钻取字段作为xAxis并加上下一个钻取字段 + if (Objects.equals(requestDimension.getId(), chartViewFieldDTO.getId())) { + fieldsToFilter.add(chartViewFieldDTO); + dimValMap.put(requestDimension.getId(), requestDimension.getValue()); + if (!fields.contains(requestDimension.getId())) { + fieldMap.put(chartViewFieldDTO.getId(), chartViewFieldDTO); + chartViewFieldDTO.setSource(FieldSource.DRILL); + xAxis.add(chartViewFieldDTO); + fields.add(requestDimension.getId()); + } + if (i == drillRequestList.size() - 1) { + ChartViewFieldDTO nextDrillField = drillFields.get(i + 1); + if (!fields.contains(nextDrillField.getId())) { + // get drill list first element's sort,then assign to nextDrillField + nextDrillField.setSort(getDrillSort(xAxis, drillFields.get(0))); + nextDrillField.setSource(FieldSource.DRILL); + xAxis.add(nextDrillField); + fields.add(nextDrillField.getId()); + } + } + } + } + } + for (int i = 0; i < fieldsToFilter.size(); i++) { + ChartViewFieldDTO tmpField = fieldsToFilter.get(i); + ChartExtFilterDTO tmpFilter = new ChartExtFilterDTO(); + DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(tmpField.getId()); + tmpFilter.setDatasetTableField(datasetTableField); + tmpFilter.setDateStyle(fieldMap.get(tmpField.getId()).getDateStyle()); + tmpFilter.setDatePattern(fieldMap.get(tmpField.getId()).getDatePattern()); + tmpFilter.setFieldId(String.valueOf(tmpField.getId())); + tmpFilter.setFilterType(1); + if (datasetTableField.getDeType() == 1) { + tmpFilter.setOriginValue(Collections.singletonList(dimValMap.get(tmpField.getId()))); + tmpFilter.setOperator("between"); + // 把value类似过滤组件处理,获得start time和end time + Map stringLongMap = Utils.parseDateTimeValue(dimValMap.get(tmpField.getId())); + tmpFilter.setValue(Arrays.asList(String.valueOf(stringLongMap.get("startTime")), String.valueOf(stringLongMap.get("endTime")))); + } else { + tmpFilter.setOperator("in"); + tmpFilter.setValue(Collections.singletonList(dimValMap.get(tmpField.getId()))); + } + filterList.add(tmpFilter); + } + } + + private String getDrillSort(List xAxis, ChartViewFieldDTO field) { + String res = ""; + for (ChartViewFieldDTO f : xAxis) { + if (Objects.equals(f.getId(), field.getId())) { + if (StringUtils.equalsIgnoreCase(f.getSort(), "asc") || StringUtils.equalsIgnoreCase(f.getSort(), "desc")) { + res = f.getSort(); + break; + } + } + } + return res; + } +} diff --git a/backend/src/main/java/com/stdproject/service/provider/SQLProvider.java b/backend/src/main/java/com/stdproject/service/provider/SQLProvider.java new file mode 100644 index 0000000..13f601e --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/provider/SQLProvider.java @@ -0,0 +1,208 @@ +package com.stdproject.service.provider; + +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import io.gisbi.extensions.view.dto.SortAxis; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; +import org.stringtemplate.v4.STGroupString; +/** + * @Author bi-coder + *

+ * 将SQLMeta各个部分先构建完毕,然后在这个类中拼接 + */ +public class SQLProvider { + + /** + * @param sqlMeta sql作为table,首尾用'(',')' + * @param isGroup 是否聚合 + * @return + */ + public static String createQuerySQLAsTmp(SQLMeta sqlMeta, boolean isGroup, boolean needOrder, boolean distinct) { + return createQuerySQL(sqlMeta, isGroup, needOrder, distinct); + } + + public static String createQuerySQLWithLimit(SQLMeta sqlMeta, boolean isGroup, boolean needOrder, boolean distinct, int start, int count) { + return createQuerySQL(sqlMeta, isGroup, needOrder, distinct) + " LIMIT " + count + " OFFSET " + start; + } + + public static String createQuerySQL(SQLMeta sqlMeta, boolean isGroup, boolean needOrder, boolean distinct) { + List xFields = sqlMeta.getXFields(); + SQLObj tableObj = sqlMeta.getTable(); + List xOrders = sqlMeta.getXOrders(); + + STGroup stg = new STGroupString(SqlTemplate.PREVIEW_SQL); + ST st_sql = stg.getInstanceOf("previewSql"); + st_sql.add("isGroup", isGroup); + st_sql.add("distinct", distinct); + if (ObjectUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + String customWheres = sqlMeta.getCustomWheres(); + String extWheres = sqlMeta.getExtWheres(); + String whereTrees = sqlMeta.getWhereTrees(); + List wheres = new ArrayList<>(); + if (customWheres != null) wheres.add(customWheres); + if (extWheres != null) wheres.add(extWheres); + if (whereTrees != null) wheres.add(whereTrees); + if (ObjectUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + + // check datasource 是否需要排序 + if (needOrder && ObjectUtils.isEmpty(xOrders)) { + if (ObjectUtils.isNotEmpty(xFields)) { + xOrders = new ArrayList<>(); + SQLObj sqlObj = xFields.get(0); + SQLObj result = SQLObj.builder() + .orderField(String.format(SQLConstants.FIELD_DOT, sqlObj.getFieldAlias())) + .orderAlias(String.format(SQLConstants.FIELD_DOT, sqlObj.getFieldAlias())) + .orderDirection("ASC").build(); + xOrders.add(result); + } + } + if (ObjectUtils.isNotEmpty(xOrders)) { + st_sql.add("orders", xOrders); + } + + return st_sql.render(); + } + + public static String createQuerySQL(SQLMeta sqlMeta, boolean isGroup, boolean needOrder, ChartViewDTO view) { + STGroup stg = new STGroupString(SqlTemplate.PREVIEW_SQL); + ST st_sql = stg.getInstanceOf("previewSql"); + + st_sql.add("isGroup", isGroup); + + SQLObj tableObj = sqlMeta.getTable(); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + + List xFields = sqlMeta.getXFields(); + List xOrders = sqlMeta.getXOrders(); + if (ObjectUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + + List yFields = sqlMeta.getYFields(); + List yWheres = sqlMeta.getYWheres(); + List yOrders = sqlMeta.getYOrders(); + if (ObjectUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields); + + String customWheres = sqlMeta.getCustomWheres(); + String extWheres = sqlMeta.getExtWheres(); + String whereTrees = sqlMeta.getWhereTrees(); + List wheres = new ArrayList<>(); + if (customWheres != null) wheres.add(customWheres); + if (extWheres != null) wheres.add(extWheres); + if (whereTrees != null) wheres.add(whereTrees); + if (ObjectUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + String sql = st_sql.render(); + + ST st = stg.getInstanceOf("previewSql"); + st_sql.add("isGroup", isGroup); + + SQLObj tableSQL = SQLObj.builder() + .tableName(String.format(SQLConstants.BRACKETS, sql)) + .tableAlias(String.format(SQLConstants.TABLE_ALIAS_PREFIX, 1)) + .build(); + if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL); + + List aggWheres = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(yWheres)) aggWheres.addAll(yWheres); + if (ObjectUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); + + List orders = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(xOrders)) orders.addAll(xOrders); + if (ObjectUtils.isNotEmpty(yOrders)) orders.addAll(yOrders); + if (!orders.isEmpty() && CollectionUtils.isNotEmpty(view.getSortPriority())) { + var sortPriority = view.getSortPriority(); + var tmp = new ArrayList(); + var ids = new HashSet(); + for (SortAxis sortAxis : sortPriority) { + for (SQLObj order : orders) { + if (sortAxis.getId().equals(order.getId())){ + tmp.add(order); + ids.add(order.getId()); + } + } + } + for (SQLObj order : orders) { + if (!ids.contains(order.getId())) { + tmp.add(order); + } + } + orders = tmp; + } + // check datasource 是否需要排序 + if (needOrder && ObjectUtils.isEmpty(orders)) { + if (ObjectUtils.isNotEmpty(xFields) || ObjectUtils.isNotEmpty(yFields)) { + SQLObj sqlObj = ObjectUtils.isNotEmpty(xFields) ? xFields.get(0) : yFields.get(0); + SQLObj result = SQLObj.builder() + .orderField(String.format(SQLConstants.FIELD_DOT, sqlObj.getFieldAlias())) + .orderAlias(String.format(SQLConstants.FIELD_DOT, sqlObj.getFieldAlias())) + .orderDirection("ASC").build(); + orders.add(result); + } + } + if (ObjectUtils.isNotEmpty(orders)) st.add("orders", orders); + + return sqlLimit(st.render(), view); + } + + public static String createQuerySQLNoSort(SQLMeta sqlMeta, boolean isGroup, ChartViewDTO view) { + STGroup stg = new STGroupString(SqlTemplate.PREVIEW_SQL); + ST st_sql = stg.getInstanceOf("previewSql"); + + st_sql.add("isGroup", isGroup); + + SQLObj tableObj = sqlMeta.getTable(); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + + List xFields = sqlMeta.getXFields(); + if (ObjectUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + + List yFields = sqlMeta.getYFields(); + List yWheres = sqlMeta.getYWheres(); + if (ObjectUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields); + + String customWheres = sqlMeta.getCustomWheres(); + String extWheres = sqlMeta.getExtWheres(); + String whereTrees = sqlMeta.getWhereTrees(); + List wheres = new ArrayList<>(); + if (customWheres != null) wheres.add(customWheres); + if (extWheres != null) wheres.add(extWheres); + if (whereTrees != null) wheres.add(whereTrees); + if (ObjectUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + String sql = st_sql.render(); + + ST st = stg.getInstanceOf("previewSql"); + st_sql.add("isGroup", isGroup); + + SQLObj tableSQL = SQLObj.builder() + .tableName(String.format(SQLConstants.BRACKETS, sql)) + .tableAlias(String.format(SQLConstants.TABLE_ALIAS_PREFIX, 1)) + .build(); + if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL); + + List aggWheres = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(yWheres)) aggWheres.addAll(yWheres); + if (ObjectUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); + + return sqlLimit(st.render(), view); + } + + public static String sqlLimit(String sql, ChartViewDTO view) { + if (StringUtils.equalsAnyIgnoreCase(view.getType(), "table-info", "table-normal")) { + return sql; + } + if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) { + return sql + " LIMIT " + view.getResultCount() + " OFFSET 0"; + } else { + return sql; + } + } +} diff --git a/backend/src/main/java/com/stdproject/service/provider/SqlTemplate.java b/backend/src/main/java/com/stdproject/service/provider/SqlTemplate.java new file mode 100644 index 0000000..fab2fa5 --- /dev/null +++ b/backend/src/main/java/com/stdproject/service/provider/SqlTemplate.java @@ -0,0 +1,84 @@ +package com.stdproject.service.provider; + +/** + * @Author bi-coder + */ +public class SqlTemplate { + public static String QUERY_SQL = "querySql(limitFiled, groups, aggregators, filters, orders, table, notUseAs, useAliasForGroup)\n" + + "::=<<\n" + + "SELECT\n" + + "\n" + + " \n" + + "\n" + + "\n" + + " *\n" + + "\n" + + "\n" + + " }; separator=\",\\n\">\n" + + "\n" + + "\n" + + " AS }; separator=\",\\n\">\n" + + "\n" + + " ,\n" + + "\n" + + " AS }; separator=\",\\n\">\n" + + "\n" + + "FROM\n" + + " \n" + + "\n" + + "WHERE\n" + + " }; separator=\"\\nAND \">\n" + + "\n" + + "\n" + + "GROUP BY\n" + + " }; separator=\",\\n\">\n" + + "\n" + + "\n" + + "GROUP BY\n" + + " }; separator=\",\\n\">\n" + + "\n" + + "\n" + + "ORDER BY\n" + + " }; separator=\",\\n\">\n" + + "\n" + + ">>"; + + public static String PREVIEW_SQL = "previewSql(limitFiled, groups, aggregators, filters, orders, table, isGroup, notUseAs, useAliasForGroup, distinct)\n" + + "::=<<\n" + + "SELECT\n" + + "\n" + + " \n" + + "\n" + + "\n" + + " *\n" + + "\n" + + "\n" + + " }; separator=\",\\n\">\n" + + "\n" + + "\n" + + " DISTINCT AS }; separator=\",\\n\">\n" + + "\n" + + " ,\n" + + "\n" + + " AS }; separator=\",\\n\">\n" + + "\n" + + "FROM\n" + + " \n" + + "\n" + + "WHERE\n" + + " }; separator=\"\\nAND \">\n" + + "\n" + + "\n" + + "GROUP BY\n" + + " }; separator=\",\\n\">\n" + + "\n" + + "\n" + + "GROUP BY\n" + + " }; separator=\",\\n\">\n" + + "\n" + + "\n" + + "ORDER BY\n" + + " }; separator=\",\\n\">\n" + + "\n" + + ">>"; +} diff --git a/backend/src/main/java/com/stdproject/utils/DatasetTableTypeConstants.java b/backend/src/main/java/com/stdproject/utils/DatasetTableTypeConstants.java new file mode 100644 index 0000000..4d291a3 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/DatasetTableTypeConstants.java @@ -0,0 +1,9 @@ +package com.stdproject.utils; + +/** + * @Author bi-coder + */ +public class DatasetTableTypeConstants { + public static String DATASET_TABLE_DB = "db"; + public static String DATASET_TABLE_SQL = "sql"; +} diff --git a/backend/src/main/java/com/stdproject/utils/DatasetUtils.java b/backend/src/main/java/com/stdproject/utils/DatasetUtils.java new file mode 100644 index 0000000..b162c02 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/DatasetUtils.java @@ -0,0 +1,148 @@ +package com.stdproject.utils; + + +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.entity.dto.BaseTreeNodeDTO; +import com.stdproject.entity.union.DatasetGroupInfoDTO; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.view.dto.ChartViewDTO; +import io.gisbi.utils.TreeUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.util.Assert; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +public class DatasetUtils { + public final static String SEPARATOR = "-de-"; + + public static List mergeDuplicateTree(List tree, String... rootPid) { + Assert.notNull(rootPid, "Root Pid cannot be null"); + if (CollectionUtils.isEmpty(tree)) { + return null; + } + List result = new ArrayList<>(); + // 构建id-节点map映射 + Map treePidMap = tree.stream().collect(Collectors.toMap(node -> node.getNodeType(), t -> t)); + tree.stream().filter(item -> ObjectUtils.isNotEmpty(item.getId())).forEach(node -> { + + String nodeType = node.getNodeType(); + String[] links = nodeType.split(SEPARATOR); + int length = links.length; + int level = Integer.parseInt(links[length - 1]); + // 判断根节点 + if (Arrays.asList(rootPid).contains(node.getPid()) && 0 == level) { + result.add(node); + } else { + //找到父元素 + String[] pLinks = new String[level]; + System.arraycopy(links, 0, pLinks, 0, level); + String parentType = Arrays.stream(pLinks).collect(Collectors.joining(SEPARATOR)) + TreeUtils.SEPARATOR + (level - 1); + BaseTreeNodeDTO parentNode = treePidMap.get(parentType); + if (parentNode == null) { + // 可能出现 rootPid 更高的节点 这个操作相当于截断 + return; + } + if (parentNode.getChildren() == null) { + parentNode.setChildren(new ArrayList()); + } + parentNode.getChildren().add(node); + } + }); + return result; + } + + public static String getEncode(String str) { + return Base64.getEncoder().encodeToString(str.getBytes()); + } + + public static String getDecode(String str) { + return new String(Base64.getDecoder().decode(str)); + } + + /** + * 计算字段表达式base64加密 + * + * @param obj + */ + public static void dsEncode(DatasetGroupInfoDTO obj) { + for (DatasetTableFieldDTO dto : obj.getAllFields()) { + if (dto.getExtField().equals(ExtFieldConstant.EXT_CALC)) { + dto.setOriginName(getEncode(dto.getOriginName())); + } + } + } + + /** + * 计算字段表达式base64解密 + * + * @param obj + */ + public static void dsDecode(DatasetGroupInfoDTO obj) { + for (DatasetTableFieldDTO dto : obj.getAllFields()) { + if (dto.getExtField().equals(ExtFieldConstant.EXT_CALC)) { + dto.setOriginName(getDecode(dto.getOriginName())); + } + } + } + + /** + * 计算字段表达式base64加密 + * + * @param fields + */ + public static void listEncode(List fields) { + if (CollectionUtils.isEmpty(fields)) { + return; + } + for (DatasetTableFieldDTO dto : fields) { + if (dto.getExtField().equals(ExtFieldConstant.EXT_CALC)) { + dto.setOriginName(getEncode(dto.getOriginName())); + } + } + } + + /** + * 计算字段表达式base64解密 + * + * @param fields + */ + public static void listDecode(List fields) { + if (CollectionUtils.isEmpty(fields)) { + return; + } + for (DatasetTableFieldDTO dto : fields) { + if (dto.getExtField().equals(ExtFieldConstant.EXT_CALC)) { + dto.setOriginName(getDecode(dto.getOriginName())); + } + } + } + + public static void viewDecode(ChartViewDTO view) { + DatasetUtils.listDecode(view.getXAxis()); + DatasetUtils.listDecode(view.getXAxisExt()); + DatasetUtils.listDecode(view.getYAxis()); + DatasetUtils.listDecode(view.getYAxisExt()); + DatasetUtils.listDecode(view.getExtStack()); + DatasetUtils.listDecode(view.getExtBubble()); + DatasetUtils.listDecode(view.getExtLabel()); + DatasetUtils.listDecode(view.getExtTooltip()); + DatasetUtils.listDecode(view.getExtColor()); + } + + public static void viewEncode(ChartViewDTO view) { + DatasetUtils.listEncode(view.getXAxis()); + DatasetUtils.listEncode(view.getXAxisExt()); + DatasetUtils.listEncode(view.getYAxis()); + DatasetUtils.listEncode(view.getYAxisExt()); + DatasetUtils.listEncode(view.getExtStack()); + DatasetUtils.listEncode(view.getExtBubble()); + DatasetUtils.listEncode(view.getExtLabel()); + DatasetUtils.listEncode(view.getExtTooltip()); + DatasetUtils.listEncode(view.getExtColor()); + } +} diff --git a/backend/src/main/java/com/stdproject/utils/DatasourceUtils.java b/backend/src/main/java/com/stdproject/utils/DatasourceUtils.java new file mode 100644 index 0000000..3c7b942 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/DatasourceUtils.java @@ -0,0 +1,26 @@ +package com.stdproject.utils; + +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.i18n.Translator; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; + +/** + * @Author bi-coder + */ +public class DatasourceUtils { + public static void checkDsStatus(Map dsMap) { + 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())) { + DEException.throwException(Translator.get("i18n_invalid_ds")); + } + } + } +} diff --git a/backend/src/main/java/com/stdproject/utils/DeSqlparserUtils.java b/backend/src/main/java/com/stdproject/utils/DeSqlparserUtils.java new file mode 100644 index 0000000..2f843db --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/DeSqlparserUtils.java @@ -0,0 +1,257 @@ +package com.stdproject.utils; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.stdproject.entity.vo.UserFormVO; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.datasource.vo.XpackPluginsDatasourceVO; +import io.gisbi.extensions.view.dto.SqlVariableDetails; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.JsonUtil; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.relational.InExpression; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.stdproject.service.manage.ChartDataManage.START_END_SEPARATOR; + + +public class DeSqlparserUtils { + private static final String deVariablePattern = "\\$DE_PARAM\\{(.*?)\\}"; + + public static final String sqlParamsRegex = "\\$\\[(.*?)\\]"; + public static final String sysVariableRegex = "\\$f2cde\\[(.*?)\\]"; + private static final String SysParamsSubstitutedParams = "DeSysParams_"; + private UserFormVO userEntity; + private static final String SubstitutedSql = " 'DE-BI' = 'DE-BI' "; + private final List> sysParams = new ArrayList<>(); + TypeReference> listTypeReference = new TypeReference>() { + }; + private List defaultsSqlVariableDetails = new ArrayList<>(); + + public String handleVariableDefaultValue(String sql, String sqlVariableDetails, boolean isEdit, boolean isFromDataSet, List parameters, boolean isCross, Map dsMap, PluginManageApi pluginManage, UserFormVO userEntity) { + DatasourceSchemaDTO ds = dsMap.entrySet().iterator().next().getValue(); + if (StringUtils.isEmpty(sql)) { + DEException.throwException(Translator.get("i18n_sql_not_empty")); + } + this.userEntity = userEntity; + sql = sql.trim(); + if (sql.endsWith(";")) { + sql = sql.substring(0, sql.length() - 1); + } + if (StringUtils.isNotEmpty(sqlVariableDetails)) { + defaultsSqlVariableDetails = JsonUtil.parseList(sqlVariableDetails, listTypeReference); + } + Pattern pattern = Pattern.compile(deVariablePattern); + Matcher matcher = pattern.matcher(sql); + while (matcher.find()) { + String sqlItemWithParam = matcher.group(); + String sqlItem = sqlItemWithParam.substring(10, sqlItemWithParam.length() - 1); + boolean replaceParam = false; + Pattern p = Pattern.compile(sqlParamsRegex); + Matcher m = p.matcher(sqlItemWithParam); + while (m.find()) { + String sqlVariable = m.group(); + boolean replaceParamItem = false; + SqlVariableDetails defaultsSqlVariableDetail = null; + for (SqlVariableDetails sqlVariableDetail : defaultsSqlVariableDetails) { + if (sqlVariable.substring(2, sqlVariable.length() - 1).equalsIgnoreCase(sqlVariableDetail.getVariableName())) { + defaultsSqlVariableDetail = sqlVariableDetail; + break; + } + } + SqlVariableDetails filterParameter = null; + if (ObjectUtils.isNotEmpty(parameters)) { + for (SqlVariableDetails parameter : parameters) { + if (parameter.getVariableName().equalsIgnoreCase(defaultsSqlVariableDetail.getVariableName())) { + filterParameter = parameter; + } + } + } + if (filterParameter != null) { + sqlItem = sqlItem.replace(sqlVariable, transFilter(filterParameter, dsMap)); + replaceParamItem = true; + } else { + if (defaultsSqlVariableDetail != null && StringUtils.isNotEmpty(defaultsSqlVariableDetail.getDefaultValue())) { + if (!isEdit && isFromDataSet && defaultsSqlVariableDetail.getDefaultValueScope().equals(SqlVariableDetails.DefaultValueScope.ALLSCOPE)) { + sqlItem = sqlItem.replace(sqlVariable, defaultsSqlVariableDetail.getDefaultValue()); + replaceParamItem = true; + } + if (isEdit) { + sqlItem = sqlItem.replace(sqlVariable, defaultsSqlVariableDetail.getDefaultValue()); + replaceParamItem = true; + } + } + } + if (!replaceParamItem) { + replaceParam = false; + break; + } else { + replaceParam = true; + } + } + p = Pattern.compile(sysVariableRegex); + m = p.matcher(sqlItemWithParam); + while (m.find()) { + boolean replaceParamItem = false; + + String sysVariableId = m.group().substring(7, m.group().length() - 1); + if (!isParams(sysVariableId)) { + continue; + } + sqlItem = sqlItem.replace(m.group(), SysParamsSubstitutedParams + sysVariableId); + try { + Expression expression = CCJSqlParserUtil.parseCondExpression(sqlItem); + String value = null; + if (expression instanceof InExpression) { + value = handleSubstitutedSqlForIn(sysVariableId); + } else { + value = handleSubstitutedSql(sysVariableId); + } + if (value != null) { + sqlItem = sqlItem.replace(SysParamsSubstitutedParams + sysVariableId, value); + replaceParamItem = true; + } + } catch (Exception e) { + e.printStackTrace(); + } + if (!replaceParamItem) { + replaceParam = false; + break; + } else { + replaceParam = true; + } + } + if (!replaceParam) { + sql = sql.replace(sqlItemWithParam, SubstitutedSql); + } else { + sql = sql.replace(sqlItemWithParam, sqlItem); + } + } + + try { + if (!isCross) { + Map.Entry next = dsMap.entrySet().iterator().next(); + DatasourceSchemaDTO value = next.getValue(); + + String prefix = ""; + String suffix = ""; + if (Arrays.stream(DatasourceConfiguration.DatasourceType.values()).map(DatasourceConfiguration.DatasourceType::getType).toList().contains(value.getType())) { + DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(value.getType()); + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } else { + List xpackPluginsDatasourceVOS = pluginManage.queryPluginDs(); + List list = xpackPluginsDatasourceVOS.stream().filter(ele -> StringUtils.equals(ele.getType(), value.getType())).toList(); + if (ObjectUtils.isNotEmpty(list)) { + XpackPluginsDatasourceVO first = list.getFirst(); + prefix = first.getPrefix(); + suffix = first.getSuffix(); + } else { + DEException.throwException("当前数据源插件不存在"); + } + } + + Pattern patternCross = Pattern.compile("(`.*?`)"); + Matcher matcherCross = patternCross.matcher(sql); + while (matcherCross.find()) { + String group = matcherCross.group(); + String info = group.substring(1, group.length() - 1); + sql = sql.replaceAll(group, prefix + info + suffix); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return sql; + } + + private static boolean isParams(String paramId) { + if (Arrays.asList("sysParams.userId", "sysParams.userEmail", "sysParams.userName").contains(paramId)) { + return true; + } + boolean isLong = false; + try { + Long.valueOf(paramId); + isLong = true; + } catch (Exception e) { + isLong = false; + } + if (paramId.length() >= 18 && isLong) { + return true; + } + return false; + } + + + private String transFilter(SqlVariableDetails sqlVariableDetails, Map dsMap) { + if (sqlVariableDetails.getOperator().equals("in")) { + if (StringUtils.equalsIgnoreCase(dsMap.entrySet().iterator().next().getValue().getType(), DatasourceConfiguration.DatasourceType.sqlServer.getType()) && sqlVariableDetails.getDeType() == 0) { + return "N'" + String.join("', N'", sqlVariableDetails.getValue()) + "'"; + } else { + if (sqlVariableDetails.getDeType() == 2 || sqlVariableDetails.getDeType() == 3) { + return String.join(",", sqlVariableDetails.getValue()); + } else { + return "'" + String.join("','", sqlVariableDetails.getValue()) + "'"; + } + } + } else if (sqlVariableDetails.getOperator().equals("between")) { + if (sqlVariableDetails.getDeType() == 1) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sqlVariableDetails.getType().size() > 1 ? (String) sqlVariableDetails.getType().get(1).replace("DD", "dd").replace("YYYY", "yyyy") : "yyyy"); + if (StringUtils.endsWith(sqlVariableDetails.getId(), START_END_SEPARATOR)) { + return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(1)))); + } else { + return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(0)))); + } + } else { + if (StringUtils.endsWith(sqlVariableDetails.getId(), START_END_SEPARATOR)) { + return sqlVariableDetails.getValue().get(1); + } else { + return sqlVariableDetails.getValue().get(0); + } + } + } else { + return (String) sqlVariableDetails.getValue().get(0); + } + + } + + private String handleSubstitutedSql(String sysVariableId) { + if (userEntity != null) { + if (sysVariableId.equalsIgnoreCase("sysParams.userId")) { + return userEntity.getAccount(); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userEmail")) { + return userEntity.getEmail(); + } + if (sysVariableId.equalsIgnoreCase("sysParams.userName")) { + return userEntity.getName(); + } + + return null; + } else { + return null; + } + } + + + private String handleSubstitutedSqlForIn(String sysVariableId) { + if (userEntity != null) { + + return null; + } else { + return null; + } + } +} + + + diff --git a/backend/src/main/java/com/stdproject/utils/SqlUtils.java b/backend/src/main/java/com/stdproject/utils/SqlUtils.java new file mode 100644 index 0000000..f07bde3 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/SqlUtils.java @@ -0,0 +1,131 @@ +package com.stdproject.utils; + +import com.google.common.collect.ImmutableList; +import io.gisbi.exception.DEException; +import org.apache.calcite.config.Lex; +import org.apache.calcite.sql.*; +import org.apache.calcite.sql.parser.SqlParseException; +import org.apache.calcite.sql.parser.SqlParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; + +import static org.apache.calcite.sql.SqlKind.*; + +/** + * @Author bi-coder + */ +public class SqlUtils { + public static Logger logger = LoggerFactory.getLogger(SqlUtils.class); + + public static String addSchema(String sql, String schema) { + sql = sql.trim(); + if (sql.endsWith(";")) { + sql = sql.substring(0, sql.length() - 1); + } + + SqlParser.Config config = + SqlParser.config() + .withLex(Lex.JAVA) + .withIdentifierMaxLength(256); + // 创建解析器 + SqlParser sqlParser = SqlParser + .create(sql, config); + // 生成 AST 语法树 + SqlNode sqlNode = null; + try { + sqlNode = sqlParser.parseStmt(); + addTableSchema(sqlNode, false, schema, config); + } catch (SqlParseException e) { + DEException.throwException("使用 Calcite 进行语法分析发生了异常:" + e); + } + String sqlRender = sqlNode.toString(); + // 处理sql中多余的`都替换成1个 + sqlRender = sqlRender.replaceAll("(`+)", "`"); + return sqlRender.replaceAll("`", ""); + } + + private static void addTableSchema(SqlNode sqlNode, Boolean fromOrJoin, String schema, SqlParser.Config config) { + try { + if (sqlNode.getKind() == JOIN) { + SqlJoin sqlKind = (SqlJoin) sqlNode; + addTableSchema(sqlKind.getLeft(), true, schema, config); + addTableSchema(sqlKind.getRight(), true, schema, config); + } else if (sqlNode.getKind() == IDENTIFIER) { + if (fromOrJoin) { + // 获取表名 + String tableName = sqlNode.toString(); + SqlIdentifier sqlKind = (SqlIdentifier) sqlNode; + sqlKind.setNames(ImmutableList.of(schema + "`.`" + tableName), null); + } + } else if (sqlNode.getKind() == AS) { + SqlBasicCall sqlKind = (SqlBasicCall) sqlNode; + if (sqlKind.getOperandList().size() >= 2) { + addTableSchema(sqlKind.getOperandList().get(0), fromOrJoin, schema, config); + } + } else if (sqlNode.getKind() == SELECT) { + SqlSelect sqlKind = (SqlSelect) sqlNode; + + // 解析from + addTableSchema(sqlKind.getFrom(), true, schema, config); + + // 解析where + SqlBasicCall where = (SqlBasicCall) sqlKind.getWhere(); + if (where != null && where.getOperandList().size() >= 2) { + for (int i = 0; i < where.getOperandList().size(); i++) { + addTableSchema(where.getOperandList().get(i), false, schema, config); + } + } + } else if (sqlNode.getKind() == UNION) { + SqlBasicCall sqlKind = (SqlBasicCall) sqlNode; + // 使用union,至少会有2个子SQL,否则语法不正确 + if (sqlKind.getOperandList().size() >= 2) { + for (int i = 0; i < sqlKind.getOperandList().size(); i++) { + addTableSchema(sqlKind.getOperandList().get(i), fromOrJoin, schema, config); + } + } + } else if (sqlNode.getKind() == ORDER_BY) { + SqlOrderBy sqlKind = (SqlOrderBy) sqlNode; + List operandList = sqlKind.getOperandList(); + if (operandList.size() > 0) { + addTableSchema(operandList.get(0), fromOrJoin, schema, config); + } + } else if (sqlNode.getKind() == IN + || sqlNode.getKind() == NOT_IN + || sqlNode.getKind() == AND + || sqlNode.getKind() == OR + || sqlNode.getKind() == LESS_THAN + || sqlNode.getKind() == GREATER_THAN + || sqlNode.getKind() == LESS_THAN_OR_EQUAL + || sqlNode.getKind() == GREATER_THAN_OR_EQUAL + || sqlNode.getKind() == EQUALS + || sqlNode.getKind() == NOT_EQUALS) { + SqlBasicCall where = (SqlBasicCall) sqlNode; + if (where.getOperandList().size() >= 2) { + for (int i = 0; i < where.getOperandList().size(); i++) { + addTableSchema(where.getOperandList().get(i), fromOrJoin, schema, config); + } + } + } + } catch (Exception e) { + DEException.throwException("使用 Calcite 进行语法分析发生了异常:" + e); + } + } + + public static String transKeyword(String value) { + return Optional.ofNullable(value).orElse("").replaceAll("'", "''").replaceAll("\\\\","\\\\\\\\").replace("\n", "\\n"); + } + + public static String buildOriginPreviewSql(String sql, int limit, int offset) { + return "SELECT * FROM (" + sql + ") tmp LIMIT " + limit + " OFFSET " + offset; + } + + public static String buildOriginPreviewSqlWithOrderBy(String sql, int limit, int offset, String orderBy) { + return "SELECT * FROM (" + sql + ") tmp ORDER BY " + orderBy + " LIMIT " + limit + " OFFSET " + offset; + } + + + +} diff --git a/backend/src/main/java/com/stdproject/utils/SqlparserUtils.java b/backend/src/main/java/com/stdproject/utils/SqlparserUtils.java new file mode 100644 index 0000000..87a1aa3 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/SqlparserUtils.java @@ -0,0 +1,779 @@ +package com.stdproject.utils; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.stdproject.entity.vo.UserFormVO; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.datasource.vo.XpackPluginsDatasourceVO; +import io.gisbi.extensions.view.dto.SqlVariableDetails; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.JsonUtil; +import io.gisbi.utils.LogUtil; +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.*; +import net.sf.jsqlparser.util.deparser.ExpressionDeParser; +import org.apache.calcite.sql.*; +import org.apache.calcite.sql.parser.SqlParser; +import org.apache.calcite.sql.util.SqlShuttle; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.stdproject.service.manage.ChartDataManage.START_END_SEPARATOR; +import static org.apache.calcite.sql.SqlKind.*; + +public class SqlparserUtils { + public static final String regex = "\\$\\{(.*?)\\}"; + public static final String regex2 = "\\$f2cde\\[(.*?)\\]"; + private static final String SubstitutedParams = "gisbi_PATAMS_BI"; + private static final String SysParamsSubstitutedParams = "DeSysParams_"; + private static final String SubstitutedSql = " 'DE-BI' = 'DE-BI' "; + private boolean removeSysParams; + boolean hasVariables = false; + private UserFormVO userEntity; + private final List> sysParams = new ArrayList<>(); + private static final String deVariablePattern = "\\$DE_PARAM\\{(.*?)\\}"; + + public String handleVariableDefaultValue(String sql, String sqlVariableDetails, boolean isEdit, boolean isFromDataSet, List parameters, boolean isCross, Map dsMap, PluginManageApi pluginManage, UserFormVO userEntity) { + Pattern r = Pattern.compile(deVariablePattern); + Matcher m = r.matcher(sql); + if (m.find()) { + return new DeSqlparserUtils().handleVariableDefaultValue(sql, sqlVariableDetails, isEdit, isFromDataSet, parameters, isCross, dsMap, pluginManage, userEntity); + } + + DatasourceSchemaDTO ds = dsMap.entrySet().iterator().next().getValue(); + if (StringUtils.isEmpty(sql)) { + DEException.throwException(Translator.get("i18n_sql_not_empty")); + } + this.userEntity = userEntity; + hasVariables = false; + sql = sql.trim(); + if (sql.endsWith(";")) { + sql = sql.substring(0, sql.length() - 1); + } + if (StringUtils.isNotEmpty(sqlVariableDetails)) { + TypeReference> listTypeReference = new TypeReference>() { + }; + List defaultsSqlVariableDetails = JsonUtil.parseList(sqlVariableDetails, listTypeReference); + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(sql); + + while (matcher.find()) { + SqlVariableDetails defaultsSqlVariableDetail = null; + for (SqlVariableDetails sqlVariableDetail : defaultsSqlVariableDetails) { + if (matcher.group().substring(2, matcher.group().length() - 1).equalsIgnoreCase(sqlVariableDetail.getVariableName())) { + defaultsSqlVariableDetail = sqlVariableDetail; + break; + } + } + SqlVariableDetails filterParameter = null; + if (ObjectUtils.isNotEmpty(parameters)) { + for (SqlVariableDetails parameter : parameters) { + if (parameter.getVariableName().equalsIgnoreCase(defaultsSqlVariableDetail.getVariableName())) { + filterParameter = parameter; + } + } + } + if (filterParameter != null) { + sql = sql.replace(matcher.group(), transFilter(filterParameter, dsMap)); + } else { + if (defaultsSqlVariableDetail != null && StringUtils.isNotEmpty(defaultsSqlVariableDetail.getDefaultValue())) { + if (!isEdit && isFromDataSet && defaultsSqlVariableDetail.getDefaultValueScope().equals(SqlVariableDetails.DefaultValueScope.ALLSCOPE)) { + sql = sql.replace(matcher.group(), defaultsSqlVariableDetail.getDefaultValue()); + } + if (isEdit) { + sql = sql.replace(matcher.group(), defaultsSqlVariableDetail.getDefaultValue()); + } + } + } + } + } + + try { + this.removeSysParams = false; + sql = removeVariables(sql, ds.getType()); + // replace keyword '`' + if (!isCross) { + Map.Entry next = dsMap.entrySet().iterator().next(); + DatasourceSchemaDTO value = next.getValue(); + + String prefix = ""; + String suffix = ""; + if (Arrays.stream(DatasourceConfiguration.DatasourceType.values()).map(DatasourceConfiguration.DatasourceType::getType).toList().contains(value.getType())) { + DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(value.getType()); + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } else { + List xpackPluginsDatasourceVOS = pluginManage.queryPluginDs(); + List list = xpackPluginsDatasourceVOS.stream().filter(ele -> StringUtils.equals(ele.getType(), value.getType())).toList(); + if (ObjectUtils.isNotEmpty(list)) { + XpackPluginsDatasourceVO first = list.getFirst(); + prefix = first.getPrefix(); + suffix = first.getSuffix(); + } else { + DEException.throwException("当前数据源插件不存在"); + } + } + + Pattern pattern = Pattern.compile("(`.*?`)"); + Matcher matcher = pattern.matcher(sql); + while (matcher.find()) { + String group = matcher.group(); + String info = group.substring(1, group.length() - 1); + sql = sql.replaceAll(group, prefix + info + suffix); + } + } + this.removeSysParams = true; + sql = removeVariables(sql, ds.getType()); + } catch (Exception e) { + e.printStackTrace(); + } + return sql; + } + + private static boolean isParams(String paramId) { + if (Arrays.asList("sysParams.userId", "sysParams.userEmail", "sysParams.userName").contains(paramId)) { + return true; + } + boolean isLong = false; + try { + Long.valueOf(paramId); + isLong = true; + } catch (Exception e) { + isLong = false; + } + if (paramId.length() >= 18 && isLong) { + return true; + } + return false; + } + + private String removeVariables(final String sql, String dsType) throws Exception { + String tmpSql = sql.replaceAll("(?m)^\\s*$[\n\r]{0,}", ""); + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(tmpSql); + while (matcher.find()) { + hasVariables = true; + tmpSql = tmpSql.replace(matcher.group(), SubstitutedParams); + } + if (removeSysParams) { + for (Map sysParam : sysParams) { + tmpSql = tmpSql.replace(sysParam.get("replace"), sysParam.get("origin")); + } + pattern = Pattern.compile(regex2); + matcher = pattern.matcher(tmpSql); + while (matcher.find()) { + String paramId = matcher.group().substring(7, matcher.group().length() - 1); + if (!isParams(paramId)) { + continue; + } + hasVariables = true; + tmpSql = tmpSql.replace(matcher.group(), SubstitutedParams); + } + } else { + pattern = Pattern.compile(regex2); + matcher = pattern.matcher(tmpSql); + while (matcher.find()) { + String paramId = matcher.group().substring(7, matcher.group().length() - 1); + if (!isParams(paramId)) { + continue; + } + hasVariables = true; + tmpSql = tmpSql.replace(matcher.group(), SysParamsSubstitutedParams + matcher.group().substring(7, matcher.group().length() - 1)); + Map sysParam = new HashMap<>(); + sysParam.put("origin", matcher.group()); + sysParam.put("replace", SysParamsSubstitutedParams + matcher.group().substring(7, matcher.group().length() - 1)); + sysParams.add(sysParam); + } + } + if (!hasVariables && !sql.contains(SubstitutedParams)) { + return sql; + } + Statement statement = CCJSqlParserUtil.parse(tmpSql); + Select select = (Select) statement; + if (CollectionUtils.isNotEmpty(select.getWithItemsList())) { + for (Iterator iter = select.getWithItemsList().iterator(); iter.hasNext(); ) { + WithItem withItem = iter.next(); + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) withItem.getSelect(); + parenthesedSelect.setSelect((Select) CCJSqlParserUtil.parse(removeVariables(parenthesedSelect.getSelect().toString(), dsType))); + } + } + + if (select.getSelectBody() instanceof PlainSelect) { + return handlePlainSelect((PlainSelect) select.getSelectBody(), select, dsType); + } else { + StringBuilder result = new StringBuilder(); + SetOperationList setOperationList = (SetOperationList) select.getSelectBody(); + for (int i = 0; i < setOperationList.getSelects().size(); i++) { + result.append(handlePlainSelect((PlainSelect) setOperationList.getSelects().get(i), null, dsType)); + if (i < setOperationList.getSelects().size() - 1) { + result.append(" ").append(setOperationList.getOperations().get(i).toString()).append(" "); + } + } + return select.toString(); + } + } + + private String handlePlainSelect(PlainSelect plainSelect, Select statementSelect, String dsType) throws Exception { + handleSelectItems(plainSelect, dsType); + handleFromItems(plainSelect, dsType); + handleJoins(plainSelect, dsType); + handleHaving(plainSelect); + return handleWhere(plainSelect, statementSelect, dsType); + } + + private void handleSelectItems(PlainSelect plainSelect, String dsType) throws Exception { + List> selectItems = new ArrayList<>(); + for (SelectItem selectItem : plainSelect.getSelectItems()) { + try { + if (selectItem.getExpression() instanceof ParenthesedSelect) { + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) selectItem.getExpression(); + parenthesedSelect.setSelect((Select) CCJSqlParserUtil.parse(removeVariables(((Select) selectItem.getExpression()).getPlainSelect().toString(), dsType))); + selectItem.setExpression(parenthesedSelect); + } + } catch (Exception e) { + e.printStackTrace(); + } + selectItems.add(selectItem); + } + plainSelect.setSelectItems(selectItems); + } + + private void handleFromItems(PlainSelect plainSelect, String dsType) throws Exception { + FromItem fromItem = plainSelect.getFromItem(); + if (fromItem instanceof ParenthesedSelect) { + handleParenthesedSelect(fromItem, dsType); + plainSelect.setFromItem(fromItem); + } else { + if (fromItem instanceof ParenthesedFromItem) { + fromItem = ((ParenthesedFromItem) fromItem).getFromItem(); + while (fromItem instanceof ParenthesedFromItem) { + fromItem = ((ParenthesedFromItem) fromItem).getFromItem(); + } + handleParenthesedSelect(fromItem, dsType); + } + plainSelect.setFromItem(fromItem); + } + } + + private void handleParenthesedSelect(FromItem fromItem, String dsType) throws Exception { + if (((ParenthesedSelect) fromItem).getSelect() instanceof SetOperationList) { + StringBuilder result = new StringBuilder(); + SetOperationList setOperationList = (SetOperationList) ((ParenthesedSelect) fromItem).getSelect().getSelectBody(); + for (int i = 0; i < setOperationList.getSelects().size(); i++) { + result.append(handlePlainSelect((PlainSelect) setOperationList.getSelects().get(i), null, dsType)); + if (i < setOperationList.getSelects().size() - 1) { + result.append(" ").append(setOperationList.getOperations().get(i).toString()).append(" "); + } + } + } else { + PlainSelect selectBody = ((ParenthesedSelect) fromItem).getSelect().getPlainSelect(); + Select subSelectTmp = (Select) CCJSqlParserUtil.parse(removeVariables(selectBody.toString(), dsType)); + ((ParenthesedSelect) fromItem).setSelect(subSelectTmp.getSelectBody()); + if (dsType.equals(DatasourceConfiguration.DatasourceType.oracle.getType())) { + if (fromItem.getAlias() != null) { + fromItem.setAlias(new Alias(fromItem.getAlias().toString(), false)); + } + } else { + if (fromItem.getAlias() == null) { + throw new Exception("Failed to parse sql, Every derived table must have its own alias!"); + } + fromItem.setAlias(new Alias(fromItem.getAlias().toString(), false)); + } + } + } + + private void handleJoins(PlainSelect plainSelect, String dsType) throws Exception { + List joins = plainSelect.getJoins(); + if (joins != null) { + List joinsList = new ArrayList<>(); + for (Join join : joins) { + FromItem rightItem = join.getRightItem(); + Collection exprs = join.getOnExpressions(); + Collection exprs2 = new ArrayList<>(); + for (Expression expr : exprs) { + StringBuilder stringBuilder = new StringBuilder(); + BinaryExpression binaryExpression = null; + try { + binaryExpression = (BinaryExpression) expr; + } catch (Exception e) { + } + if (binaryExpression != null) { + boolean hasSubBinaryExpression = binaryExpression instanceof AndExpression || binaryExpression instanceof OrExpression; + if (!hasSubBinaryExpression && !(binaryExpression.getLeftExpression() instanceof BinaryExpression) && !(binaryExpression.getLeftExpression() instanceof InExpression) && (hasVariable(binaryExpression.getLeftExpression().toString()) || hasVariable(binaryExpression.getRightExpression().toString()))) { + stringBuilder.append(handleSubstitutedSql(binaryExpression.toString())); + } else { + expr.accept(getExpressionDeParser(stringBuilder)); + } + } else { + expr.accept(getExpressionDeParser(stringBuilder)); + } + exprs2.add(CCJSqlParserUtil.parseCondExpression(stringBuilder.toString())); + } + join.setOnExpressions(exprs2); + if (rightItem instanceof ParenthesedSelect) { + try { + PlainSelect selectBody = ((ParenthesedSelect) rightItem).getPlainSelect(); + Select subSelectTmp = (Select) CCJSqlParserUtil.parse(removeVariables(selectBody.toString(), dsType)); + PlainSelect subPlainSelect = ((PlainSelect) subSelectTmp.getSelectBody()); + ((ParenthesedSelect) rightItem).setSelect(subPlainSelect); + } catch (Exception e) { + SetOperationList select = ((ParenthesedSelect) rightItem).getSetOperationList(); + SetOperationList setOperationList = new SetOperationList(); + setOperationList.setSelects(new ArrayList<>()); + setOperationList.setOperations(select.getOperations()); + for (Select selectSelect : select.getSelects()) { + Select subSelectTmp = (Select) CCJSqlParserUtil.parse(removeVariables(selectSelect.toString(), dsType)); + setOperationList.getSelects().add(subSelectTmp); + } + ((ParenthesedSelect) rightItem).setSelect(setOperationList); + } + if (dsType.equals(DatasourceConfiguration.DatasourceType.oracle.getType())) { + rightItem.setAlias(new Alias(rightItem.getAlias().toString(), false)); + } else { + if (rightItem.getAlias() == null) { + throw new Exception("Failed to parse sql, Every derived table must have its own alias!"); + } + rightItem.setAlias(new Alias(rightItem.getAlias().toString(), false)); + } + join.setRightItem(rightItem); + } + joinsList.add(join); + } + plainSelect.setJoins(joinsList); + } + } + + private void handleHaving(PlainSelect plainSelect) throws Exception { + Expression expr = plainSelect.getHaving(); + if (expr == null) { + return; + } + StringBuilder stringBuilder = new StringBuilder(); + BinaryExpression binaryExpression = null; + try { + binaryExpression = (BinaryExpression) expr; + } catch (Exception e) { + } + if (binaryExpression != null) { + boolean hasSubBinaryExpression = binaryExpression instanceof AndExpression || binaryExpression instanceof OrExpression; + if (!hasSubBinaryExpression && !(binaryExpression.getLeftExpression() instanceof BinaryExpression) && !(binaryExpression.getLeftExpression() instanceof InExpression) && (hasVariable(binaryExpression.getLeftExpression().toString()) || hasVariable(binaryExpression.getRightExpression().toString()))) { + stringBuilder.append(handleSubstitutedSql(binaryExpression.toString())); + } else { + expr.accept(getExpressionDeParser(stringBuilder)); + } + } else { + expr.accept(getExpressionDeParser(stringBuilder)); + } + plainSelect.setHaving(CCJSqlParserUtil.parseCondExpression(stringBuilder.toString())); + } + + private String handleWhere(PlainSelect plainSelect, Select statementSelect, String dsType) throws Exception { + Expression expr = plainSelect.getWhere(); + if (expr == null) { + return handleWith(plainSelect, statementSelect, dsType); + } + StringBuilder stringBuilder = new StringBuilder(); + BinaryExpression binaryExpression = null; + try { + binaryExpression = (BinaryExpression) expr; + } catch (Exception e) { + } + if (binaryExpression != null) { + boolean hasSubBinaryExpression = binaryExpression instanceof AndExpression || binaryExpression instanceof OrExpression; + if (!hasSubBinaryExpression && !(binaryExpression.getLeftExpression() instanceof BinaryExpression) && !(binaryExpression.getLeftExpression() instanceof InExpression) && (hasVariable(binaryExpression.getLeftExpression().toString()) || hasVariable(binaryExpression.getRightExpression().toString()))) { + stringBuilder.append(handleSubstitutedSql(binaryExpression.toString())); + } else { + expr.accept(getExpressionDeParser(stringBuilder)); + } + } else { + expr.accept(getExpressionDeParser(stringBuilder)); + } + plainSelect.setWhere(CCJSqlParserUtil.parseCondExpression(stringBuilder.toString())); + return handleWith(plainSelect, statementSelect, dsType); + } + + private String handleWith(PlainSelect plainSelect, Select select, String dsType) throws Exception { + if (select != null && CollectionUtils.isNotEmpty(select.getWithItemsList())) { + for (Iterator iter = select.getWithItemsList().iterator(); iter.hasNext(); ) { + WithItem withItem = iter.next(); + ParenthesedSelect parenthesedSelect = (ParenthesedSelect) withItem.getSelect(); + parenthesedSelect.setSelect((Select) CCJSqlParserUtil.parse(removeVariables(parenthesedSelect.getSelect().toString(), dsType))); + } + } + return plainSelect.toString(); + } + + private ExpressionDeParser getExpressionDeParser(StringBuilder stringBuilder) { + ExpressionDeParser expressionDeParser = new ExpressionDeParser(null, stringBuilder) { + @Override + public void visit(Parenthesis parenthesis) { + getBuffer().append("("); + parenthesis.getExpression().accept(this); + getBuffer().append(")"); + } + + @Override + public void visit(OrExpression orExpression) { + visitBinaryExpr(orExpression, "OR"); + } + + @Override + public void visit(AndExpression andExpression) { + visitBinaryExpr(andExpression, andExpression.isUseOperator() ? " && " : " AND "); + } + + @Override + public void visit(Between between) { + if (hasVariable(between.getBetweenExpressionStart().toString()) || hasVariable(between.getBetweenExpressionEnd().toString())) { + getBuffer().append(handleSubstitutedSql(between.toString())); + } else { + getBuffer().append(between.getLeftExpression()).append(" BETWEEN ").append(between.getBetweenExpressionStart()).append(" AND ").append(between.getBetweenExpressionEnd()); + } + } + + @Override + public void visit(MinorThan minorThan) { + if (hasVariable(minorThan.getLeftExpression().toString()) || hasVariable(minorThan.getRightExpression().toString())) { + getBuffer().append(handleSubstitutedSql(minorThan.toString())); + return; + } + getBuffer().append(minorThan.getLeftExpression()); + getBuffer().append(" < "); + getBuffer().append(minorThan.getRightExpression()); + } + + @Override + public void visit(MinorThanEquals minorThan) { + if (hasVariable(minorThan.getLeftExpression().toString()) || hasVariable(minorThan.getRightExpression().toString())) { + getBuffer().append(handleSubstitutedSql(minorThan.toString())); + return; + } + getBuffer().append(minorThan.getLeftExpression()); + getBuffer().append(" <= "); + getBuffer().append(minorThan.getRightExpression()); + } + + @Override + public void visit(GreaterThanEquals minorThan) { + if (hasVariable(minorThan.getLeftExpression().toString()) || hasVariable(minorThan.getRightExpression().toString())) { + getBuffer().append(handleSubstitutedSql(minorThan.toString())); + return; + } + getBuffer().append(minorThan.getLeftExpression()); + getBuffer().append(" >= "); + getBuffer().append(minorThan.getRightExpression()); + } + + @Override + public void visit(GreaterThan greaterThan) { + if (hasVariable(greaterThan.getLeftExpression().toString()) || hasVariable(greaterThan.getRightExpression().toString())) { + getBuffer().append(handleSubstitutedSql(greaterThan.toString())); + return; + } + getBuffer().append(greaterThan.getLeftExpression()); + getBuffer().append(" > "); + getBuffer().append(greaterThan.getRightExpression()); + } + + @Override + public void visit(ExpressionList expressionList) { + for (Iterator iter = expressionList.getExpressions().iterator(); iter.hasNext(); ) { + Expression expression = iter.next(); + expression.accept(this); + if (iter.hasNext()) { + buffer.append(", "); + } + } + } + + @Override + public void visit(LikeExpression likeExpression) { + if (hasVariable(likeExpression.toString())) { + getBuffer().append(handleSubstitutedSql(likeExpression.toString())); + return; + } + visitBinaryExpression(likeExpression, (likeExpression.isNot() ? " NOT" : "") + (likeExpression.isCaseInsensitive() ? " ILIKE " : " LIKE ")); + if (likeExpression.getEscape() != null) { + buffer.append(" ESCAPE '").append(likeExpression.getEscape()).append('\''); + } + } + + @Override + public void visit(InExpression inExpression) { + if (inExpression.getRightExpression() != null && hasVariable(inExpression.getRightExpression().toString()) && !(inExpression.getRightExpression() instanceof ParenthesedSelect)) { + stringBuilder.append(handleSubstitutedSqlForIn(inExpression.toString())); + return; + } + inExpression.getLeftExpression().accept(this); + if (inExpression.isNot()) { + getBuffer().append(" " + " NOT IN " + " "); + } else { + getBuffer().append(" IN "); + } + if (inExpression.getRightExpression() != null && inExpression.getRightExpression() instanceof ParenthesedSelect) { + try { + ParenthesedSelect subSelect = (ParenthesedSelect) inExpression.getRightExpression(); + Select select = (Select) CCJSqlParserUtil.parse(removeVariables(subSelect.getPlainSelect().toString(), "")); + subSelect.setSelect(select); + inExpression.setRightExpression(subSelect); + } catch (Exception e) { + e.printStackTrace(); + } + inExpression.getRightExpression().accept(this); + } + if (inExpression.getRightExpression() instanceof ParenthesedExpressionList) { + buffer.append(inExpression.getRightExpression()); + } + } + + @Override + public void visit(ParenthesedSelect subSelect) { + StringBuilder stringBuilder = new StringBuilder(); + Expression in = ((PlainSelect) subSelect.getSelectBody()).getWhere(); + if (in instanceof BinaryExpression && hasVariable(in.toString())) { + stringBuilder.append(SubstitutedParams); + } else { + in.accept(getExpressionDeParser(stringBuilder)); + } + + try { + Expression where = CCJSqlParserUtil.parseCondExpression(stringBuilder.toString()); + ((PlainSelect) subSelect.getSelectBody()).setWhere(where); + getBuffer().append(subSelect.getSelectBody()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void visit(Select selectBody) { + getBuffer().append(selectBody.toString()); + } + + + private void visitBinaryExpr(BinaryExpression expr, String operator) { + boolean hasSubBinaryExpression = false; + if (expr.getLeftExpression() instanceof Parenthesis) { + try { + Parenthesis parenthesis = (Parenthesis) expr.getLeftExpression(); + BinaryExpression leftBinaryExpression = (BinaryExpression) parenthesis.getExpression(); + hasSubBinaryExpression = leftBinaryExpression instanceof AndExpression || leftBinaryExpression instanceof OrExpression; + } catch (Exception e) { + e.printStackTrace(); + } + } + if (expr.getLeftExpression() instanceof BinaryExpression) { + try { + BinaryExpression leftBinaryExpression = (BinaryExpression) expr.getLeftExpression(); + hasSubBinaryExpression = leftBinaryExpression instanceof AndExpression || leftBinaryExpression instanceof OrExpression; + } catch (Exception e) { + e.printStackTrace(); + } + } + if ((expr.getLeftExpression() instanceof BinaryExpression || expr.getLeftExpression() instanceof Parenthesis) && !hasSubBinaryExpression && hasVariable(expr.getLeftExpression().toString())) { + getBuffer().append(handleSubstitutedSql(expr.getLeftExpression().toString())); + } else { + expr.getLeftExpression().accept(this); + } + getBuffer().append(" " + operator + " "); + hasSubBinaryExpression = false; + if (expr.getRightExpression() instanceof Parenthesis) { + try { + Parenthesis parenthesis = (Parenthesis) expr.getRightExpression(); + BinaryExpression rightBinaryExpression = (BinaryExpression) parenthesis.getExpression(); + hasSubBinaryExpression = rightBinaryExpression instanceof AndExpression || rightBinaryExpression instanceof OrExpression; + } catch (Exception e) { + LogUtil.error("Failed parse sql", e); + } + } + if (expr.getRightExpression() instanceof BinaryExpression) { + try { + BinaryExpression rightBinaryExpression = (BinaryExpression) expr.getRightExpression(); + hasSubBinaryExpression = rightBinaryExpression instanceof AndExpression || rightBinaryExpression instanceof OrExpression; + } catch (Exception e) { + e.printStackTrace(); + } + } + + if ((expr.getRightExpression() instanceof Parenthesis || expr.getRightExpression() instanceof BinaryExpression || expr.getRightExpression() instanceof Function) && !hasSubBinaryExpression && hasVariable(expr.getRightExpression().toString())) { + getBuffer().append(handleSubstitutedSql(expr.getRightExpression().toString())); + } else { + expr.getRightExpression().accept(this); + } + } + }; + return expressionDeParser; + } + + private boolean hasVariable(String sql) { + return sql.contains(SubstitutedParams) || (!removeSysParams && sql.contains(SysParamsSubstitutedParams)); + } + + + private void getDependencies(SqlNode sqlNode, Boolean fromOrJoin) { + if (sqlNode == null) { + return; + } + if (sqlNode.getKind() == JOIN) { + SqlJoin sqlKind = (SqlJoin) sqlNode; + + } else if (sqlNode.getKind() == IDENTIFIER) { + } else if (sqlNode.getKind() == AS) { + SqlBasicCall sqlKind = (SqlBasicCall) sqlNode; + } else if (sqlNode.getKind() == SELECT) { + SqlSelect sqlKind = (SqlSelect) sqlNode; + List list = sqlKind.getSelectList().getList(); + for (SqlNode i : list) { + getDependencies(i, false); + } + SqlNode from = sqlKind.getFrom().accept(getSqlShuttle()); + sqlKind.setFrom(from); + if (sqlKind.getWhere() != null) { + SqlNode newWhere = sqlKind.getWhere().accept(getSqlShuttle()); + sqlKind.setWhere(newWhere); + } + } else if (sqlNode.getKind() == ORDER_BY) { + SqlOrderBy sqlKind = (SqlOrderBy) sqlNode; + List operandList = sqlKind.getOperandList(); + for (int i = 0; i < operandList.size(); i++) { + getDependencies(operandList.get(i), false); + } + } else if (sqlNode.getKind() == UNION) { + SqlBasicCall sqlKind = (SqlBasicCall) sqlNode; + if (sqlKind.getOperandList().size() >= 2) { + for (int i = 0; i < sqlKind.getOperandList().size(); i++) { + getDependencies(sqlKind.getOperandList().get(i), false); + } + } + } + } + + private SqlShuttle getSqlShuttle() { + return new SqlShuttle() { + + @Override + public @Nullable SqlNode visit(final SqlCall call) { + CallCopyingArgHandler argHandler = new CallCopyingArgHandler(call, false); + call.getOperator().acceptCall(this, call, false, argHandler); + if (argHandler.result().toString().contains(SubstitutedParams)) { + SqlNode sqlNode1 = null; + try { + sqlNode1 = SqlParser.create(SubstitutedSql).parseExpression(); + } catch (Exception e) { + + } + return sqlNode1; + } + return argHandler.result(); + } + }; + } + + private String transFilter(SqlVariableDetails sqlVariableDetails, Map dsMap) { + if (sqlVariableDetails.getOperator().equals("in")) { + if (StringUtils.equalsIgnoreCase(dsMap.entrySet().iterator().next().getValue().getType(), DatasourceConfiguration.DatasourceType.sqlServer.getType()) + && sqlVariableDetails.getDeType() == 0) { + return "N'" + String.join("', N'", sqlVariableDetails.getValue()) + "'"; + } else { + if (sqlVariableDetails.getDeType() == 2 || sqlVariableDetails.getDeType() == 3) { + return String.join(",", sqlVariableDetails.getValue()); + } else { + return "'" + String.join("','", sqlVariableDetails.getValue()) + "'"; + } + } + } else if (sqlVariableDetails.getOperator().equals("between")) { + if (sqlVariableDetails.getDeType() == 1) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sqlVariableDetails.getType().size() > 1 ? (String) sqlVariableDetails.getType().get(1).replace("DD", "dd").replace("YYYY", "yyyy") : "yyyy"); + if (StringUtils.endsWith(sqlVariableDetails.getId(), START_END_SEPARATOR)) { + return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(1)))); + } else { + return simpleDateFormat.format(new Date(Long.parseLong((String) sqlVariableDetails.getValue().get(0)))); + } + } else { + if (StringUtils.endsWith(sqlVariableDetails.getId(), START_END_SEPARATOR)) { + return sqlVariableDetails.getValue().get(1); + } else { + return sqlVariableDetails.getValue().get(0); + } + } + } else { + return (String) sqlVariableDetails.getValue().get(0); + } + + } + + private String handleSubstitutedSql(String sql) { +// if (sql.contains(SysParamsSubstitutedParams) && userEntity != null) { +// sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userId", userEntity.getAccount()); +// sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userEmail", userEntity.getEmail()); +// sql = sql.replace(SysParamsSubstitutedParams + "sysParams.userName", userEntity.getName()); +// for (SysVariableValueItem variable : userEntity.getVariables()) { +// String value = null; +// if (!variable.isValid()) { +// continue; +// } +// if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { +// for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { +// if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { +// value = sysVariableValueDto.getValue(); +// break; +// } +// } +// } else { +// value = variable.getVariableValue(); +// } +// if (StringUtils.isNotEmpty(value)) { +// sql = sql.replace(SysParamsSubstitutedParams + variable.getVariableId(), value); +// } +// } +// return sql; +// } else { +// return SubstitutedSql; +// } + return sql; + } + + + private String handleSubstitutedSqlForIn(String sql) { +// if (sql.contains(SysParamsSubstitutedParams) && userEntity != null) { +// for (SysVariableValueItem variable : userEntity.getVariables()) { +// List values = new ArrayList<>(); +// if (!variable.isValid()) { +// continue; +// } +// if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { +// +// for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { +// if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { +// values.add(sysVariableValueDto.getValue()); +// } +// } +// } +// if (CollectionUtils.isNotEmpty(values)) { +// sql = sql.replace(SysParamsSubstitutedParams + variable.getVariableId(), "'" + String.join("','", values) + "'"); +// } +// } +// return sql; +// } else { +// return SubstitutedSql; +// } + return sql; + } +} + + + diff --git a/backend/src/main/java/com/stdproject/utils/TableUtils.java b/backend/src/main/java/com/stdproject/utils/TableUtils.java new file mode 100644 index 0000000..9fae7f0 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/TableUtils.java @@ -0,0 +1,62 @@ +package com.stdproject.utils; + +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.dto.DsTypeDTO; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.utils.Md5Utils; +import org.apache.calcite.avatica.util.Quoting; +import org.apache.commons.lang3.StringUtils; + +public class TableUtils { + + public static String format = Quoting.BACK_TICK.string + "%s" + Quoting.BACK_TICK.string; + + public static String tableName(String name) { + return name; + } + + public static String tmpName(String name) { + return "tmp_" + name; + } + + public static String deleteName(String dorisName) { + return "delete_" + dorisName; + } + + public static String addName(String dorisName) { + return "add_" + dorisName; + } + + public static String fieldName(String dorisName) { + return "f_" + Md5Utils.md5(dorisName); + } + + public static String fieldNameShort(String dorisName) { + return "f_" + Md5Utils.md5(dorisName).substring(8, 24); + } + + public static String columnName(String fieldName) { + return "C_" + Md5Utils.md5(fieldName); + } + + public static String getTableAndAlias(SQLObj sqlObj, DsTypeDTO datasourceType, boolean isCross) { + String schema = ""; + String prefix = ""; + String suffix = ""; + if (StringUtils.isNotEmpty(sqlObj.getTableSchema())) { + if (isCross) { + prefix = "`"; + suffix = "`"; + } else { + prefix = datasourceType.getPrefix(); + suffix = datasourceType.getSuffix(); + } + schema = prefix + sqlObj.getTableSchema() + suffix + "."; + } + return schema + prefix + sqlObj.getTableName() + suffix + " " + sqlObj.getTableAlias(); + } + + public static String tableName2Sql(DatasourceSchemaDTO ds, String tableName) { + return "SELECT * FROM " + ds.getSchemaAlias() + "." + String.format(format, tableName); + } +} diff --git a/backend/src/main/java/com/stdproject/utils/Utils.java b/backend/src/main/java/com/stdproject/utils/Utils.java new file mode 100644 index 0000000..65ad66a --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/Utils.java @@ -0,0 +1,565 @@ +package com.stdproject.utils; + +import com.stdproject.constant.ExtFieldConstant; +import io.gisbi.constant.SQLConstants; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.*; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.datasource.vo.XpackPluginsDatasourceVO; +import io.gisbi.i18n.Translator; +import io.gisbi.utils.JsonUtil; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class Utils { + public static boolean joinSort(String sort) { + return (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")); + } + + // 解析计算字段 + public static String calcFieldRegex(DatasetTableFieldDTO chartField, SQLObj tableObj, List originFields, boolean isCross, Map dsMap, Map paramMap) { + try { + int i = 0; + DsTypeDTO datasourceType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + datasourceType = getDs(next.getValue().getType()); + } + return buildCalcField(chartField, tableObj, originFields, i, isCross, datasourceType, paramMap, true, chartField.getOriginName()); + } catch (Exception e) { + DEException.throwException(Translator.get("i18n_field_circular_ref")); + } + return null; + } + + public static String calcSimpleFieldRegex(DatasetTableFieldDTO chartField, SQLObj tableObj, List originFields, boolean isCross, Map dsTypeMap, PluginManageApi pluginManage) { + try { + int i = 0; + DsTypeDTO datasourceType = null; + if (dsTypeMap != null && dsTypeMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsTypeMap.entrySet().iterator().next(); + datasourceType = getDs(next.getValue()); + } + return buildCalcField(chartField, tableObj, originFields, i, isCross, datasourceType, null, true, chartField.getOriginName()); + } catch (Exception e) { + DEException.throwException(Translator.get("i18n_field_circular_ref")); + } + return null; + } + + public static String buildCalcField(DatasetTableFieldDTO chartField, SQLObj tableObj, List originFields, int i, boolean isCross, DsTypeDTO datasourceType, Map paramMap, boolean isFirst, String fieldExpression) throws Exception { + try { + i++; + if (i > 100) { + DEException.throwException(Translator.get("i18n_field_circular_error")); + } + String originField = getCalcField(chartField, originFields, isFirst, fieldExpression); + originField = originField.replaceAll("[\\t\\n\\r]]", ""); + // 正则提取[xxx] + String regex = "\\[(.*?)]"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(originField); + Set ids = new HashSet<>(); + while (matcher.find()) { + String id = matcher.group(1); + ids.add(id); + } + if (CollectionUtils.isEmpty(ids)) { + return originField; + } + // 替换参数 + if (ObjectUtils.isNotEmpty(paramMap)) { + Set> entries = paramMap.entrySet(); + for (Map.Entry ele : entries) { + originField = originField.replaceAll("\\[" + ele.getKey() + "]", ele.getValue()); + } + } + // 替换字段引用 + for (DatasetTableFieldDTO ele : originFields) { + if (StringUtils.containsIgnoreCase(originField, ele.getId() + "")) { + // 计算字段允许二次引用,这里递归查询完整引用链 + if (Objects.equals(ele.getExtField(), ExtFieldConstant.EXT_NORMAL)) { + if (isCross) { + originField = originField.replaceAll("\\[" + ele.getId() + "]", String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), ele.getGisbiName())); + } else { + originField = originField.replaceAll("\\[" + ele.getId() + "]", datasourceType.getPrefix() + tableObj.getTableAlias() + datasourceType.getSuffix() + "." + datasourceType.getPrefix() + ele.getGisbiName() + datasourceType.getSuffix()); + } + } else { + originField = originField.replaceAll("\\[" + ele.getId() + "]", "(" + ele.getOriginName() + ")"); + originField = buildCalcField(chartField, tableObj, originFields, i, isCross, datasourceType, paramMap, false, originField); + } + } + } + return originField; + } catch (Exception e) { + DEException.throwException(Translator.get("i18n_field_circular_error")); + } + return null; + } + + public static String getCalcField(DatasetTableFieldDTO ele, List originFields, boolean isFirst, String fieldExpression) { + if (isFirst) { + for (DatasetTableFieldDTO field : originFields) { + if (Objects.equals(ele.getId(), field.getId())) { + return field.getOriginName(); + } + } + return ""; + } else { + return fieldExpression; + } + } + + public static String getLogic(String logic) { + if (logic != null) { + switch (logic) { + case "and": + return "AND"; + case "or": + return "OR"; + } + } + return "AND"; + } + + public static String transDateFormat(String dateStyle, String datePattern) { + String split = "-"; + if (StringUtils.equalsIgnoreCase(datePattern, "date_sub")) { + split = "-"; + } else if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + split = "/"; + } else { + split = "-"; + } + + if (StringUtils.isEmpty(dateStyle)) { + return "yyyy-MM-dd HH:mm:ss"; + } + + switch (dateStyle) { + case "y": + return "yyyy"; + case "y_Q": + return "CONCAT(%s,'" + split + "',%s)"; + case "y_M": + return "yyyy" + split + "MM"; + case "y_W": + return "%Y" + split + "%u"; + case "y_M_d": + return "yyyy" + split + "MM" + split + "dd"; + case "M_d": + return "MM" + split + "dd"; + case "H_m_s": + return "HH:mm:ss"; + case "y_M_d_H": + return "yyyy" + split + "MM" + split + "dd" + " HH"; + case "y_M_d_H_m": + return "yyyy" + split + "MM" + split + "dd" + " HH:mm"; + case "y_M_d_H_m_s": + return "yyyy" + split + "MM" + split + "dd" + " HH:mm:ss"; + default: + return "yyyy-MM-dd HH:mm:ss"; + } + } + + public static String transFilterTerm(String term) { + switch (term) { + case "eq": + return " = "; + case "not_eq": + return " <> "; + case "lt": + return " < "; + case "le": + return " <= "; + case "gt": + return " > "; + case "ge": + return " >= "; + case "in": + return " IN "; + case "not in": + return " NOT IN "; + case "like": + return " LIKE "; + case "not like": + return " NOT LIKE "; + case "null": + return " IS NULL "; + case "not_null": + return " IS NOT NULL "; + case "empty": + return " = "; + case "not_empty": + return " <> "; + case "between": + return " BETWEEN "; + default: + return ""; + } + } + + public static void checkCircularReference(String originField, List fields) { + originField = originField.replaceAll("[\\t\\n\\r]]", ""); + // 正则提取[xxx] + String regex = "\\[(.*?)]"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(originField); + while (matcher.find()) { + Set ids = new HashSet<>(); + String id = matcher.group(1); + for (DatasetTableFieldDTO ele : fields) { + if (StringUtils.containsIgnoreCase(id, ele.getId() + "")) { + if (ids.contains(id)) { + DEException.throwException(Translator.get("i18n_field_circular_ref")); + } + ids.add(id); + if (Objects.equals(ele.getExtField(), ExtFieldConstant.EXT_CALC)) { + originField = originField.replaceAll("\\[" + ele.getId() + "]", ele.getOriginName()); + checkField(ids, originField, fields); + } + } + } + } + } + + public static void checkField(Set ids, String originField, List fields) { + originField = originField.replaceAll("[\\t\\n\\r]]", ""); + // 正则提取[xxx] + String regex = "\\[(.*?)]"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(originField); + while (matcher.find()) { + String id = matcher.group(1); + for (DatasetTableFieldDTO ele : fields) { + if (StringUtils.containsIgnoreCase(id, ele.getId() + "")) { + if (ids.contains(id)) { + DEException.throwException(Translator.get("i18n_field_circular_ref")); + } + ids.add(id); + if (Objects.equals(ele.getExtField(), ExtFieldConstant.EXT_CALC)) { + originField = originField.replaceAll("\\[" + ele.getId() + "]", ele.getOriginName()); + checkField(ids, originField, fields); + } + } + } + } + } + + public static boolean matchFunction(String func, String originField) { + String pattern = func + "\\s*\\((.*?)\\)"; + Pattern r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); + Matcher m = r.matcher(originField.replaceAll("[\\t\\n\\r]", "")); + while (m.find()) { + return true; + } + return false; + } + + public static boolean isNeedOrder(List dsList) { + String[] list = {"sqlServer", "db2", "impala"}; + List strings = Arrays.asList(list); + List collect = strings.stream().filter(dsList::contains).collect(Collectors.toList()); + return ObjectUtils.isNotEmpty(collect); + } + + public static boolean isCrossDs(Map dsMap) { + return dsMap.size() != 1; + } + + public static String replaceSchemaAlias(String sql, Map dsMap) { + DatasourceSchemaDTO value = dsMap.entrySet().iterator().next().getValue(); + Map map = JsonUtil.parseObject(value.getConfiguration(), Map.class); + if (ObjectUtils.isNotEmpty(map.get("schema"))) { + return sql; + } + return sql.replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + value.getSchemaAlias() + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX + "\\.", ""); + } + + public static long allDateFormat2Long(String value) { + String split = "-"; + if (value != null && value.contains("/")) { + split = "/"; + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd HH:mm:ss"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd HH:mm"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd HH"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy"); + return simpleDateFormat.parse(value).getTime(); + } catch (Exception e) { + } + return 0; + } + + public static String parseTime(String time, String sourceFormat, String targetFormat) { + if (StringUtils.equalsIgnoreCase(sourceFormat, targetFormat)) { + String[] s = time.split(" "); + if (s.length > 1) { + time = s[1]; + } else { + time = s[0]; + } + } + return time; + } + + public static Map parseDateTimeValue(String value) { + Map map = new LinkedHashMap<>(); + long startTime = 0; + long endTime = 0; + + String split = "-"; + if (value != null && value.contains("/")) { + split = "/"; + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd HH:mm:ss"); + startTime = simpleDateFormat.parse(value).getTime(); + endTime = startTime + 999; + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd HH:mm"); + startTime = simpleDateFormat.parse(value).getTime(); + endTime = startTime + (60 * 1000 - 1); + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd HH"); + startTime = simpleDateFormat.parse(value).getTime(); + endTime = startTime + (60 * 60 * 1000 - 1); + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); + startTime = simpleDateFormat.parse(value).getTime(); + endTime = startTime + 999; + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM" + split + "dd"); + startTime = simpleDateFormat.parse(value).getTime(); + endTime = startTime + (24 * 60 * 60 * 1000 - 1); + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy" + split + "MM"); + Date parse = simpleDateFormat.parse(value); + startTime = parse.getTime(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(parse); + calendar.add(Calendar.MONTH, 1); + endTime = calendar.getTime().getTime() - 1; + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + try { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy"); + Date parse = simpleDateFormat.parse(value); + startTime = parse.getTime(); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(parse); + calendar.add(Calendar.YEAR, 1); + endTime = calendar.getTime().getTime() - 1; + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } catch (Exception e) { + } + + map.put("startTime", startTime); + map.put("endTime", endTime); + return map; + } + + public static String transLong2Str(Long ts) { + Date date = new Date(ts); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return simpleDateFormat.format(date); + } + + public static String transLong2StrShort(Long ts) { + Date date = new Date(ts); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return simpleDateFormat.format(date); + } + + public static List getParams(List list) { + if (ObjectUtils.isEmpty(list)) return Collections.emptyList(); + List param = new ArrayList<>(); + for (DatasetTableFieldDTO dto : list) { + if (Objects.equals(dto.getExtField(), ExtFieldConstant.EXT_CALC) && ObjectUtils.isNotEmpty(dto.getParams())) { + param.addAll(dto.getParams()); + } + } + return param; + } + + public static Map mergeParam(List fieldParam, List chartParam) { + Map map = new HashMap<>(); + if (ObjectUtils.isNotEmpty(fieldParam)) { + for (CalParam param : fieldParam) { + map.put(param.getId(), param.getValue()); + } + } + if (ObjectUtils.isNotEmpty(chartParam)) { + for (CalParam param : chartParam) { + map.put(param.getId(), param.getValue()); + } + } + return map; + } + + private static DsTypeDTO getDs(String type) { + DsTypeDTO dto = new DsTypeDTO(); + try { + DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(type); + dto.setType(type); + dto.setName(datasourceType.getName()); + dto.setCatalog(datasourceType.getCatalog()); + dto.setPrefix(datasourceType.getPrefix()); + dto.setSuffix(datasourceType.getSuffix()); + return dto; + } catch (Exception e) { + } + return null; + } + + public static String transGroupFieldToSql(DatasetTableFieldDTO dto, List fields, boolean isCross, Map dsMap, PluginManageApi pluginManage) { + // 从fields里取最新的dto + for (DatasetTableFieldDTO fieldDTO : fields) { + if (Objects.equals(dto.getId(), fieldDTO.getId())) { + dto.setGroupList(fieldDTO.getGroupList()); + dto.setOtherGroup(fieldDTO.getOtherGroup()); + break; + } + } + // get origin field + DatasetTableFieldDTO originField = null; + for (DatasetTableFieldDTO ele : fields) { + if (Objects.equals(ele.getId(), Long.valueOf(dto.getOriginName()))) { + originField = ele; + break; + } + } + if (originField == null) { + DEException.throwException("Field not exists"); + } + + DsTypeDTO datasourceType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + datasourceType = getDs(next.getValue().getType()); + } + if (datasourceType == null) { + DEException.throwException("Datasource not exists"); + } + + String fieldName; + if (isCross) { + fieldName = originField.getGisbiName(); + } else { + fieldName = datasourceType.getPrefix() + originField.getGisbiName() + datasourceType.getSuffix(); + } + + StringBuilder exp = new StringBuilder(); + exp.append(" (CASE "); + if (originField.getDeType() == 0) { + for (FieldGroupDTO fieldGroupDTO : dto.getGroupList()) { + exp.append(" WHEN "); + for (int i = 0; i < fieldGroupDTO.getText().size(); i++) { + String value = fieldGroupDTO.getText().get(i); + exp.append(fieldName).append(" = ").append("'").append(transValue(value)).append("'"); + if (i < fieldGroupDTO.getText().size() - 1) { + exp.append(" OR "); + } + } + exp.append(" THEN '").append(transValue(fieldGroupDTO.getName())).append("'"); + } + } else if (originField.getDeType() == 1) { + for (FieldGroupDTO fieldGroupDTO : dto.getGroupList()) { + exp.append(" WHEN "); + exp.append(fieldName).append(" >= ").append("'").append(fieldGroupDTO.getStartTime()).append("'"); + exp.append(" AND "); + exp.append(fieldName).append(" <= ").append("'").append(fieldGroupDTO.getEndTime()).append("'"); + exp.append(" THEN '").append(transValue(fieldGroupDTO.getName())).append("'"); + } + } else if (originField.getDeType() == 2 || originField.getDeType() == 3 || originField.getDeType() == 4) { + for (FieldGroupDTO fieldGroupDTO : dto.getGroupList()) { + exp.append(" WHEN "); + exp.append(fieldName).append(StringUtils.equalsIgnoreCase(fieldGroupDTO.getMinTerm(), "le") ? " >= " : " > ").append(fieldGroupDTO.getMin()); + exp.append(" AND "); + exp.append(fieldName).append(StringUtils.equalsIgnoreCase(fieldGroupDTO.getMaxTerm(), "le") ? " <= " : " < ").append(fieldGroupDTO.getMax()); + exp.append(" THEN '").append(transValue(fieldGroupDTO.getName())).append("'"); + } + } + exp.append(" ELSE ").append("'").append(transValue(dto.getOtherGroup())).append("'").append(" END) "); + return exp.toString(); + } + + public static String transValue(String value) { + return value.replace("\\", "\\\\").replace("'", "''"); + } +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/CustomWhere2Str.java b/backend/src/main/java/com/stdproject/utils/trans/CustomWhere2Str.java new file mode 100644 index 0000000..7cbb242 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/CustomWhere2Str.java @@ -0,0 +1,378 @@ +package com.stdproject.utils.trans; + +import com.stdproject.utils.Utils; +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.view.filter.DynamicTimeSetting; +import io.gisbi.extensions.view.filter.FilterTreeItem; +import io.gisbi.extensions.view.filter.FilterTreeObj; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +public class CustomWhere2Str { + + public static void customWhere2sqlObj(SQLMeta meta, FilterTreeObj tree, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + List res = new ArrayList<>(); + // permission trees + // 解析每个tree,然后多个tree之间用and拼接 + // 每个tree,如果是sub tree节点,则使用递归合并成一组条件 + if (ObjectUtils.isEmpty(tree)) { + return; + } + Map fieldsDialect = new HashMap<>(); + String treeExp = transTreeToWhere(tableObj, tree, fieldsDialect, originFields, isCross, dsMap, fieldParam, chartParam, pluginManage); + if (StringUtils.isNotEmpty(treeExp)) { + res.add(treeExp); + } + meta.setCustomWheres(ObjectUtils.isNotEmpty(res) ? "(" + String.join(" AND ", res) + ")" : null); + meta.setCustomWheresDialect(fieldsDialect); + } + + private static String transTreeToWhere(SQLObj tableObj, FilterTreeObj tree, Map fieldsDialect, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + if (ObjectUtils.isEmpty(tree)) { + return null; + } + String logic = tree.getLogic(); + List items = tree.getItems(); + List list = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(items)) { + // type is item or tree + for (FilterTreeItem item : items) { + String exp = null; + if (StringUtils.equalsIgnoreCase(item.getType(), "item")) { + // 单个item拼接SQL,最后根据logic汇总 + exp = transTreeItem(tableObj, item, fieldsDialect, originFields, isCross, dsMap, fieldParam, chartParam, pluginManage); + } else if (StringUtils.equalsIgnoreCase(item.getType(), "tree")) { + // 递归tree + exp = transTreeToWhere(tableObj, item.getSubTree(), fieldsDialect, originFields, isCross, dsMap, fieldParam, chartParam, pluginManage); + } + if (StringUtils.isNotEmpty(exp)) { + list.add(exp); + } + } + } + return CollectionUtils.isNotEmpty(list) ? "(" + String.join(" " + logic + " ", list) + ")" : null; + } + + private static String transTreeItem(SQLObj tableObj, FilterTreeItem item, Map fieldsDialect, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + String res = null; + DatasetTableFieldDTO field = item.getField(); + + if (ObjectUtils.isEmpty(field)) { + return null; + } + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + String whereName = ""; + String originName; + if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(field, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); + fieldsDialect.put(originName, calcFieldExp); + if (isCross) { + originName = calcFieldExp; + } + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 3) { + String groupFieldExp = Utils.transGroupFieldToSql(field, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); + fieldsDialect.put(originName, groupFieldExp); + if (isCross) { + originName = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getGisbiName()); + } + } + if (field.getDeType() == 1) { + if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5) { + // 此处获取标准格式的日期 + whereName = String.format(SQLConstants.DE_STR_TO_DATE, originName, StringUtils.isNotEmpty(field.getDateFormat()) ? field.getDateFormat() : SQLConstants.DEFAULT_DATE_FORMAT); + } + if (field.getDeExtractType() == 2 || field.getDeExtractType() == 3 || field.getDeExtractType() == 4) { + String cast = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT); + // 此处获取标准格式的日期 + whereName = String.format(SQLConstants.FROM_UNIXTIME, cast, SQLConstants.DEFAULT_DATE_FORMAT); + } + if (field.getDeExtractType() == 1) { + // 如果都是时间类型,把date和time类型进行字符串拼接 + if (isCross) { + if (StringUtils.equalsIgnoreCase(field.getType(), "date")) { + originName = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, originName, "' 00:00:00'"), SQLConstants.DEFAULT_DATE_FORMAT); + } else if (StringUtils.equalsIgnoreCase(field.getType(), "time")) { + originName = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, "'1970-01-01 '", originName), SQLConstants.DEFAULT_DATE_FORMAT); + } + } + // 此处获取标准格式的日期 + if (StringUtils.equalsIgnoreCase(field.getType(), "date") + || (StringUtils.equalsIgnoreCase(dsMap.entrySet().iterator().next().getValue().getType(), "oracle") && StringUtils.equalsIgnoreCase(field.getType(), "timestamp"))) { + whereName = String.format(SQLConstants.DE_CAST_DATE_FORMAT, originName, + SQLConstants.DEFAULT_DATE_FORMAT, + SQLConstants.DEFAULT_DATE_FORMAT); + } else { + whereName = originName; + } + } + } else if (field.getDeType() == 2 || field.getDeType() == 3) { + if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_FLOAT_FORMAT); + } + if (field.getDeExtractType() == 1) { + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, originName); + } + if (field.getDeExtractType() == 2 || field.getDeExtractType() == 4) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT); + } + if (field.getDeExtractType() == 3) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_FLOAT_FORMAT); + } + } else { + whereName = originName; + } + + if (StringUtils.equalsIgnoreCase(item.getFilterType(), "enum")) { + if (ObjectUtils.isNotEmpty(item.getEnumValue())) { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + res = "(" + whereName + " IN (" + item.getEnumValue().stream().map(str -> "'" + SQLConstants.MSSQL_N_PREFIX + str + "'").collect(Collectors.joining(",")) + "))"; + } else { + res = "(" + whereName + " IN ('" + String.join("','", item.getEnumValue()) + "'))"; + } + } + } else { + if (field.getDeType() == 1 && isCross) { + // 规定几种日期格式,一一匹配,匹配到就是该格式 + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName); + } + + String value = item.getValue(); + String whereTerm = Utils.transFilterTerm(item.getTerm()); + String whereValue = ""; + + if (StringUtils.equalsIgnoreCase(item.getTerm(), "null")) { + whereValue = ""; + } else if (StringUtils.equalsIgnoreCase(item.getTerm(), "not_null")) { + whereValue = ""; + } else if (StringUtils.equalsIgnoreCase(item.getTerm(), "empty")) { + whereValue = "''"; + } else if (StringUtils.equalsIgnoreCase(item.getTerm(), "not_empty")) { + whereValue = "''"; + } else if (StringUtils.containsIgnoreCase(item.getTerm(), "in") || StringUtils.containsIgnoreCase(item.getTerm(), "not in")) { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "(" + Arrays.stream(value.split(",")).map(str -> "'" + SQLConstants.MSSQL_N_PREFIX + str + "'").collect(Collectors.joining(",")) + ")"; + } else { + whereValue = "('" + String.join("','", value.split(",")) + "')"; + } + } else if (StringUtils.containsIgnoreCase(item.getTerm(), "like")) { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "'" + SQLConstants.MSSQL_N_PREFIX + "%" + value + "%'"; + } else { + whereValue = "'%" + value + "%'"; + } + } else { + // 如果是时间字段过滤,当条件是等于和不等于的时候转换成between和not between + if (field.getDeType() == 1) { + // 如果是动态时间,计算具体值 + value = fixValue(item); + Map stringLongMap = Utils.parseDateTimeValue(value); + if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) { + whereTerm = " BETWEEN "; + // 把value类似过滤组件处理,获得start time和end time + if (isCross) { + whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2Str(stringLongMap.get("startTime")), Utils.transLong2Str(stringLongMap.get("endTime"))); + } + } else if (StringUtils.equalsIgnoreCase(whereTerm, " <> ")) { + whereTerm = " NOT BETWEEN "; + if (isCross) { + whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2Str(stringLongMap.get("startTime")), Utils.transLong2Str(stringLongMap.get("endTime"))); + } + } else { + Long startTime = stringLongMap.get("startTime"); + Long endTime = stringLongMap.get("endTime"); + if (isCross) { + if (StringUtils.equalsIgnoreCase(whereTerm, " > ") || StringUtils.equalsIgnoreCase(whereTerm, " <= ")) { + value = endTime + ""; + } else if (StringUtils.equalsIgnoreCase(whereTerm, " >= ") || StringUtils.equalsIgnoreCase(whereTerm, " < ")) { + value = startTime + ""; + } + } else { + if (StringUtils.equalsIgnoreCase(whereTerm, " > ") || StringUtils.equalsIgnoreCase(whereTerm, " <= ")) { + value = Utils.transLong2Str(endTime); + } else if (StringUtils.equalsIgnoreCase(whereTerm, " >= ") || StringUtils.equalsIgnoreCase(whereTerm, " < ")) { + value = Utils.transLong2Str(startTime); + } + } + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, value); + } + } else { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE_CH, value); + } else { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, value); + } + } + } + SQLObj build = SQLObj.builder() + .whereField(whereName) + .whereTermAndValue(whereTerm + whereValue) + .build(); + res = build.getWhereField() + " " + build.getWhereTermAndValue(); + } + return res; + } + + private static String fixValue(FilterTreeItem item) { + if (StringUtils.isNotEmpty(item.getFilterTypeTime()) && StringUtils.equalsIgnoreCase(item.getFilterTypeTime(), "dynamicDate")) { + DynamicTimeSetting dynamicTimeSetting = item.getDynamicTimeSetting(); + Calendar instance = Calendar.getInstance(); + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "thisYear")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "lastYear")) { + instance.add(Calendar.YEAR, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } + return "" + instance.get(Calendar.YEAR); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "thisMonth")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "lastMonth")) { + instance.add(Calendar.MONTH, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.MONTH, dynamicTimeSetting.getTimeNum()); + } + } + } + return instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1 < 10 ? "0" : "") + (instance.get(Calendar.MONTH) + 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "date")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "today")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yesterday")) { + instance.add(Calendar.DAY_OF_MONTH, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "monthBeginning")) { + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yearBeginning")) { + instance.set(Calendar.MONTH, 0); + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.MONTH, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "date")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.DAY_OF_MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.DAY_OF_MONTH, dynamicTimeSetting.getTimeNum()); + } + } + } + return instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1 < 10 ? "0" : "") + (instance.get(Calendar.MONTH) + 1) + "-" + (instance.get(Calendar.DAY_OF_MONTH) < 10 ? "0" : "") + instance.get(Calendar.DAY_OF_MONTH); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getTimeGranularity(), "datetime")) { + String time = " 00:00:00"; + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "today")) { + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yesterday")) { + instance.add(Calendar.DAY_OF_MONTH, -1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "monthBeginning")) { + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "yearBeginning")) { + instance.set(Calendar.MONTH, 0); + instance.set(Calendar.DAY_OF_MONTH, 1); + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrent(), "custom")) { + time = " " + dynamicTimeSetting.getArbitraryTime().substring(11, 19); + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "year")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.YEAR, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.YEAR, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "month")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.MONTH, dynamicTimeSetting.getTimeNum()); + } + } else if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getRelativeToCurrentType(), "date")) { + if (StringUtils.equalsIgnoreCase(dynamicTimeSetting.getAround(), "f")) { + instance.add(Calendar.DAY_OF_MONTH, -dynamicTimeSetting.getTimeNum()); + } else { + instance.add(Calendar.DAY_OF_MONTH, dynamicTimeSetting.getTimeNum()); + } + } + } + return instance.get(Calendar.YEAR) + "-" + (instance.get(Calendar.MONTH) + 1 < 10 ? "0" : "") + (instance.get(Calendar.MONTH) + 1) + "-" + (instance.get(Calendar.DAY_OF_MONTH) < 10 ? "0" : "") + instance.get(Calendar.DAY_OF_MONTH) + time; + } + } + return item.getValue(); + } +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/Dimension2SQLObj.java b/backend/src/main/java/com/stdproject/utils/trans/Dimension2SQLObj.java new file mode 100644 index 0000000..9182bce --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/Dimension2SQLObj.java @@ -0,0 +1,167 @@ +package com.stdproject.utils.trans; + +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.utils.Utils; +import io.gisbi.constant.DeTypeConstants; +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.view.dto.ChartViewFieldDTO; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.util.*; + +/** + * @Author bi-coder + */ +public class Dimension2SQLObj { + + public static void dimension2sqlObj(SQLMeta meta, List fields, List originFields, + boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + List xFields = new ArrayList<>(); + List xOrders = new ArrayList<>(); + Map fieldsDialect = new HashMap<>(); + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + + if (!CollectionUtils.isEmpty(fields)) { + for (int i = 0; i < fields.size(); i++) { + ChartViewFieldDTO x = fields.get(i); + String originField; + if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_CALC)) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(x, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId()); + fieldsDialect.put(originField, calcFieldExp); + if (isCross) { + originField = calcFieldExp; + } + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_COPY)) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_GROUP)) { + String groupFieldExp = Utils.transGroupFieldToSql(x, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId()); + fieldsDialect.put(originField, groupFieldExp); + if (isCross) { + originField = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getGisbiName()); + } + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + // 处理横轴字段 + xFields.add(getXFields(x, originField, fieldAlias, isCross)); + + // 处理横轴排序 + if (StringUtils.isNotEmpty(x.getSort()) && Utils.joinSort(x.getSort())) { + xOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(x.getSort()) + .id(x.getId()) + .build()); + } + } + } + meta.setXFields(xFields); + meta.setXOrders(xOrders); + meta.setXFieldsDialect(fieldsDialect); + } + + public static SQLObj getXFields(ChartViewFieldDTO x, String originField, String fieldAlias, boolean isCross) { + String fieldName = ""; + if (Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_TIME)) { + if (Objects.equals(x.getDeType(), DeTypeConstants.DE_INT) || Objects.equals(x.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.UNIX_TIMESTAMP, originField); + } else if (Objects.equals(x.getDeType(), DeTypeConstants.DE_TIME) && !StringUtils.equalsIgnoreCase(x.getType(), "year")) { + // 如果都是时间类型,把date和time类型进行字符串拼接 + if (isCross) { + if (StringUtils.equalsIgnoreCase(x.getType(), "date")) { + originField = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, originField, "' 00:00:00'"), SQLConstants.DEFAULT_DATE_FORMAT); + } else if (StringUtils.equalsIgnoreCase(x.getType(), "time")) { + originField = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, "'1970-01-01 '", originField), SQLConstants.DEFAULT_DATE_FORMAT); + } + } + String format = Utils.transDateFormat(x.getDateStyle(), x.getDatePattern()); + if (StringUtils.equalsIgnoreCase(x.getDateStyle(), "y_Q")) { + fieldName = String.format(format, + String.format(SQLConstants.DE_DATE_FORMAT, originField, "yyyy"), + String.format(SQLConstants.QUARTER, originField)); + } else { + fieldName = String.format(SQLConstants.DE_CAST_DATE_FORMAT, originField, + SQLConstants.DEFAULT_DATE_FORMAT, + format); + } + } else { + fieldName = originField; + } + } else { + if (Objects.equals(x.getDeType(), DeTypeConstants.DE_TIME)) { + String format = Utils.transDateFormat(x.getDateStyle(), x.getDatePattern()); + if (Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_STRING) || Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_LOCATION)) { + if (StringUtils.equalsIgnoreCase(x.getDateStyle(), "y_Q")) { + fieldName = String.format(format, + String.format(SQLConstants.DE_DATE_FORMAT, String.format(SQLConstants.DE_STR_TO_DATE, originField, SQLConstants.DEFAULT_DATE_FORMAT), "yyyy"), + String.format(SQLConstants.QUARTER, String.format(SQLConstants.DE_STR_TO_DATE, originField, SQLConstants.DEFAULT_DATE_FORMAT))); + } else { + String s = String.format(SQLConstants.DE_STR_TO_DATE, originField, StringUtils.isEmpty(x.getDateFormat()) ? SQLConstants.DEFAULT_DATE_FORMAT : x.getDateFormat()); + fieldName = String.format(SQLConstants.DE_CAST_DATE_FORMAT, s, SQLConstants.DEFAULT_DATE_FORMAT, format); + } + } else if (Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_INT) || Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_FLOAT) || Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_BOOL)) { + String cast = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + String from_unixtime = String.format(SQLConstants.FROM_UNIXTIME, cast, SQLConstants.DEFAULT_DATE_FORMAT); + if (StringUtils.equalsIgnoreCase(x.getDateStyle(), "y_Q")) { + fieldName = String.format(format, + String.format(SQLConstants.DE_DATE_FORMAT, from_unixtime, "yyyy"), + String.format(SQLConstants.QUARTER, from_unixtime)); + } else { + fieldName = String.format(SQLConstants.DE_CAST_DATE_FORMAT, from_unixtime, SQLConstants.DEFAULT_DATE_FORMAT, format); + } + } else { + fieldName = String.format(SQLConstants.DE_DATE_FORMAT, originField, format); + } + } else if (Objects.equals(x.getDeType(), DeTypeConstants.DE_STRING) && Objects.equals(x.getDeExtractType(), DeTypeConstants.DE_STRING)) { + fieldName = originField; + } else { + if (Objects.equals(x.getDeType(), DeTypeConstants.DE_INT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + } else if (Objects.equals(x.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_FLOAT_FORMAT); + } else { + fieldName = originField; + } + } + } + return SQLObj.builder() + .fieldName(fieldName) + .fieldAlias(fieldAlias) + .build(); + } + +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/ExtWhere2Str.java b/backend/src/main/java/com/stdproject/utils/trans/ExtWhere2Str.java new file mode 100644 index 0000000..b54461a --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/ExtWhere2Str.java @@ -0,0 +1,302 @@ +package com.stdproject.utils.trans; + +import com.stdproject.utils.Utils; +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.view.dto.ChartExtFilterDTO; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +public class ExtWhere2Str { + + public static void extWhere2sqlOjb(SQLMeta meta, List fields, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + List list = new ArrayList<>(); + Map fieldsDialect = new HashMap<>(); + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + + if (ObjectUtils.isNotEmpty(fields)) { + for (ChartExtFilterDTO request : fields) { + List value = request.getValue(); + + List whereNameList = new ArrayList<>(); + List fieldList = new ArrayList<>(); + if (request.getIsTree()) { + fieldList.addAll(request.getDatasetTableFieldList()); + } else { + fieldList.add(request.getDatasetTableField()); + } + + for (DatasetTableFieldDTO field : fieldList) { + if (ObjectUtils.isEmpty(value) || ObjectUtils.isEmpty(field)) { + continue; + } + String whereName = ""; + + String originName; + if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(field, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); + fieldsDialect.put(originName, calcFieldExp); + if (isCross) { + originName = calcFieldExp; + } + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 3) { + String groupFieldExp = Utils.transGroupFieldToSql(field, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); + fieldsDialect.put(originName, groupFieldExp); + if (isCross) { + originName = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getGisbiName()); + } + } + + if (field.getDeType() == 1) { + if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5) { + // 此处获取标准格式的日期 + whereName = String.format(SQLConstants.DE_STR_TO_DATE, originName, StringUtils.isEmpty(field.getDateFormat()) ? SQLConstants.DEFAULT_DATE_FORMAT : field.getDateFormat()); + } + if (field.getDeExtractType() == 2 || field.getDeExtractType() == 3 || field.getDeExtractType() == 4) { + String cast = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT); + // 此处获取标准格式的日期 + whereName = String.format(SQLConstants.FROM_UNIXTIME, cast, SQLConstants.DEFAULT_DATE_FORMAT); + if (isCross) { + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName); + } + } + if (field.getDeExtractType() == 1) { + // 如果都是时间类型,把date和time类型进行字符串拼接 + if (isCross) { + if (StringUtils.equalsIgnoreCase(field.getType(), "date")) { + originName = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, originName, "' 00:00:00'"), SQLConstants.DEFAULT_DATE_FORMAT); + } else if (StringUtils.equalsIgnoreCase(field.getType(), "time")) { + originName = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, "'1970-01-01 '", originName), SQLConstants.DEFAULT_DATE_FORMAT); + } + } + // 此处获取标准格式的日期,同时此处是仪表板过滤,仪表板中图表的日期均已经格式化,所以要强制加上日期转换 + whereName = String.format(SQLConstants.DE_CAST_DATE_FORMAT, originName, + SQLConstants.DEFAULT_DATE_FORMAT, + SQLConstants.DEFAULT_DATE_FORMAT); + } + } else if (field.getDeType() == 2 || field.getDeType() == 3) { + if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_FLOAT_FORMAT); + } + if (field.getDeExtractType() == 1) { + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, originName); + } + if (field.getDeExtractType() == 2 || field.getDeExtractType() == 4) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT); + } + if (field.getDeExtractType() == 3) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_FLOAT_FORMAT); + } + } else { + whereName = originName; + } + whereNameList.add(whereName); + } + + String whereName = ""; + if (request.getIsTree()) { + whereName = "CONCAT(" + StringUtils.join(whereNameList, ",',',") + ")"; + } else { + whereName = whereNameList.get(0); + } + String whereTerm = Utils.transFilterTerm(request.getOperator()); + String whereValue = ""; + + if (StringUtils.containsIgnoreCase(request.getOperator(), "-")) { + String[] split = request.getOperator().split("-"); + String term1 = split[0]; + String logic = split[1]; + String term2 = split[2]; + whereValue = Utils.transFilterTerm(term1) + getValue(term1, value.get(0)) + " " + logic + " " + whereName + Utils.transFilterTerm(term2) + getValue(term2, value.get(1)); + } else if (StringUtils.containsIgnoreCase(request.getOperator(), "in")) { + // 过滤空数据 + if (value.contains(SQLConstants.EMPTY_SIGN)) { + whereValue = "('" + StringUtils.join(value, "','") + "', '')" + " or " + whereName + " is null "; + } else { + // tree的情况需额外处理 + if (request.getIsTree()) { + List datasetTableFieldList = request.getDatasetTableFieldList(); + boolean hasN = false; + for (DatasetTableFieldDTO dto : datasetTableFieldList) { + if (StringUtils.containsIgnoreCase(dto.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(dto.getType(), "NCHAR")) { + hasN = true; + break; + } + } + if (hasN && !isCross && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "(" + value.stream().map(str -> "'" + SQLConstants.MSSQL_N_PREFIX + str + "'").collect(Collectors.joining(",")) + ")"; + } else { + whereValue = "('" + StringUtils.join(value, "','") + "')"; + } + } else { + if ((StringUtils.containsIgnoreCase(request.getDatasetTableField().getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(request.getDatasetTableField().getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "(" + value.stream().map(str -> "'" + SQLConstants.MSSQL_N_PREFIX + str + "'").collect(Collectors.joining(",")) + ")"; + } else { + if (request.getDatasetTableField().getDeType() == 2 || request.getDatasetTableField().getDeType() == 3) { + whereValue = "(" + StringUtils.join(value, ",") + ")"; + } else { + whereValue = "('" + StringUtils.join(value, "','") + "')"; + } + } + } + } + } else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) { + // tree的情况需额外处理 + if (request.getIsTree()) { + List datasetTableFieldList = request.getDatasetTableFieldList(); + boolean hasN = false; + for (DatasetTableFieldDTO dto : datasetTableFieldList) { + if (StringUtils.containsIgnoreCase(dto.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(dto.getType(), "NCHAR")) { + hasN = true; + break; + } + } + if (hasN && !isCross && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "'" + SQLConstants.MSSQL_N_PREFIX + "%" + value.get(0) + "%'"; + } else { + whereValue = "'%" + value.get(0) + "%'"; + } + } else { + if ((StringUtils.containsIgnoreCase(request.getDatasetTableField().getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(request.getDatasetTableField().getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "'" + SQLConstants.MSSQL_N_PREFIX + "%" + value.get(0) + "%'"; + } else { + whereValue = "'%" + value.get(0) + "%'"; + } + } + } else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) { + if (request.getDatasetTableField().getDeType() == 1) { + if (request.getDatasetTableField().getDeExtractType() == 2 + || request.getDatasetTableField().getDeExtractType() == 3 + || request.getDatasetTableField().getDeExtractType() == 4) { + if (isCross) { + whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, value.get(0), value.get(1)); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2Str(Long.parseLong(value.get(0))), Utils.transLong2Str(Long.parseLong(value.get(1)))); + } + } else { + if (isCross) { + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName); + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Long.parseLong(value.get(0)), Long.parseLong(value.get(1))); + } else { + if (StringUtils.equalsIgnoreCase(request.getDatasetTableField().getType(), "date")) { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2StrShort(Long.parseLong(value.get(0))), Utils.transLong2StrShort(Long.parseLong(value.get(1))) + " 23:59:59"); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2Str(Long.parseLong(value.get(0))), Utils.transLong2Str(Long.parseLong(value.get(1)))); + } + } + } + } else if (request.getDatasetTableField().getDeType() == 2 + || request.getDatasetTableField().getDeType() == 3 + || request.getDatasetTableField().getDeType() == 4) { + whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, value.get(0), value.get(1)); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, value.get(0), value.get(1)); + } + } else { + // 过滤空数据 + if (StringUtils.equals(value.get(0), SQLConstants.EMPTY_SIGN)) { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, "") + " or " + whereName + " is null "; + } else { + // tree的情况需额外处理 + if (request.getIsTree()) { + List datasetTableFieldList = request.getDatasetTableFieldList(); + boolean hasN = false; + for (DatasetTableFieldDTO dto : datasetTableFieldList) { + if ((StringUtils.containsIgnoreCase(dto.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(dto.getType(), "NCHAR")) + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + hasN = true; + break; + } + } + if (hasN && !isCross) { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE_CH, value.get(0)); + } else { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, value.get(0)); + } + } else { + if ((StringUtils.containsIgnoreCase(request.getDatasetTableField().getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(request.getDatasetTableField().getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE_CH, value.get(0)); + } else { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, value.get(0)); + } + } + } + } + list.add(SQLObj.builder() + .whereField(whereName) + .whereTermAndValue(whereTerm + whereValue) + .build()); + } + List strList = new ArrayList<>(); + list.forEach(ele -> strList.add("(" + ele.getWhereField() + " " + ele.getWhereTermAndValue() + ")")); + meta.setExtWheres(ObjectUtils.isNotEmpty(list) ? "(" + String.join(" AND ", strList) + ")" : null); + } + meta.setExtWheresDialect(fieldsDialect); + } + + private static String getValue(String term, String value) { + switch (term) { + case "like": + return "'%" + value + "%'"; + case "eq": + return "'" + value + "'"; + } + return null; + } + +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/Field2SQLObj.java b/backend/src/main/java/com/stdproject/utils/trans/Field2SQLObj.java new file mode 100644 index 0000000..34a8819 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/Field2SQLObj.java @@ -0,0 +1,140 @@ +package com.stdproject.utils.trans; + +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.constant.FunctionConstant; +import com.stdproject.utils.Utils; +import io.gisbi.constant.DeTypeConstants; +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; + +/** + * @Author bi-coder + */ +public class Field2SQLObj { + + public static void field2sqlObj(SQLMeta meta, List fields, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + List xFields = new ArrayList<>(); + Map fieldsDialect = new HashMap<>(); + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + + if (ObjectUtils.isNotEmpty(fields)) { + for (int i = 0; i < fields.size(); i++) { + DatasetTableFieldDTO x = fields.get(i); + String originField; + if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_CALC)) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(x, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId()); + fieldsDialect.put(originField, calcFieldExp); + if (isCross) { + originField = calcFieldExp; + } + // 此处是数据集预览,获取数据库原始字段枚举值等操作使用,如果遇到聚合函数则将originField设置为null + for (String func : FunctionConstant.AGG_FUNC) { + if (Utils.matchFunction(func, calcFieldExp)) { + originField = null; + break; + } + } + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_COPY)) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_GROUP)) { + String groupFieldExp = Utils.transGroupFieldToSql(x, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId()); + fieldsDialect.put(originField, groupFieldExp); + if (isCross) { + originField = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getGisbiName()); + } + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + // 处理横轴字段 + xFields.add(getXFields(x, originField, fieldAlias, isCross)); + } + } + meta.setXFields(xFields); + meta.setXFieldsDialect(fieldsDialect); + } + + public static SQLObj getXFields(DatasetTableFieldDTO f, String originField, String fieldAlias, boolean isCross) { + String fieldName = ""; + if (originField != null) { + // 处理横轴字段 + if (Objects.equals(f.getDeExtractType(), DeTypeConstants.DE_TIME)) { + if (Objects.equals(f.getDeType(), DeTypeConstants.DE_INT) || Objects.equals(f.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.UNIX_TIMESTAMP, originField); + } else { + // 如果都是时间类型,把date和time类型进行字符串拼接 + if (isCross) { + if (StringUtils.equalsIgnoreCase(f.getType(), "date")) { + originField = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, originField, "' 00:00:00'"), SQLConstants.DEFAULT_DATE_FORMAT); + } else if (StringUtils.equalsIgnoreCase(f.getType(), "time")) { + originField = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, "'1970-01-01 '", originField), SQLConstants.DEFAULT_DATE_FORMAT); + } + } + fieldName = originField; + } + } else if (Objects.equals(f.getDeExtractType(), DeTypeConstants.DE_STRING)) { + if (Objects.equals(f.getDeType(), DeTypeConstants.DE_INT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_FLOAT_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_TIME)) { + fieldName = StringUtils.isEmpty(f.getDateFormat()) ? String.format(SQLConstants.DE_STR_TO_DATE, originField, SQLConstants.DEFAULT_DATE_FORMAT) : + String.format(SQLConstants.DE_STR_TO_DATE, originField, f.getDateFormat()); + } else { + fieldName = originField; + } + } else { + if (Objects.equals(f.getDeType(), DeTypeConstants.DE_TIME)) { + String cast = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + fieldName = String.format(SQLConstants.FROM_UNIXTIME, cast, SQLConstants.DEFAULT_DATE_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_INT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_FLOAT_FORMAT); + } else { + fieldName = originField; + } + } + } else { + fieldName = "'-'"; + } + return SQLObj.builder() + .fieldName(fieldName) + .fieldAlias(fieldAlias) + .build(); + } + +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/Order2SQLObj.java b/backend/src/main/java/com/stdproject/utils/trans/Order2SQLObj.java new file mode 100644 index 0000000..f1d5a03 --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/Order2SQLObj.java @@ -0,0 +1,131 @@ +package com.stdproject.utils.trans; + +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.entity.dto.DeSortField; +import com.stdproject.utils.Utils; +import io.gisbi.constant.DeTypeConstants; +import io.gisbi.constant.SQLConstants; + +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; + +/** + * @Author bi-coder + */ +public class Order2SQLObj { + + public static void getOrders(SQLMeta meta, List sortFields, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + List xOrders = meta.getXOrders() == null ? new ArrayList<>() : meta.getXOrders(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + if (ObjectUtils.isNotEmpty(sortFields)) { + int step = originFields.size(); + for (int i = step; i < (step + sortFields.size()); i++) { + DeSortField deSortField = sortFields.get(i - step); + SQLObj order = buildSortField(deSortField, tableObj, i, originFields, isCross, dsMap, fieldParam, chartParam, pluginManage); + xOrders.add(order); + } + meta.setXOrders(xOrders); + } + } + + private static SQLObj buildSortField(DeSortField f, SQLObj tableObj, int i, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + String originField; + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + Map fieldsDialect = new HashMap<>(); + + if (ObjectUtils.isNotEmpty(f.getExtField()) && Objects.equals(f.getExtField(), ExtFieldConstant.EXT_CALC)) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(f, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, f.getId()); + fieldsDialect.put(originField, calcFieldExp); + if (isCross) { + originField = calcFieldExp; + } + } else if (ObjectUtils.isNotEmpty(f.getExtField()) && Objects.equals(f.getExtField(), ExtFieldConstant.EXT_COPY)) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), f.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), f.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(f.getExtField()) && Objects.equals(f.getExtField(), ExtFieldConstant.EXT_GROUP)) { + String groupFieldExp = Utils.transGroupFieldToSql(f, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, f.getId()); + fieldsDialect.put(originField, groupFieldExp); + if (isCross) { + originField = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), f.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), f.getGisbiName()); + } + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + String fieldName = ""; + // 处理横轴字段 + if (Objects.equals(f.getDeExtractType(), DeTypeConstants.DE_TIME)) { + if (Objects.equals(f.getDeType(), DeTypeConstants.DE_INT) || Objects.equals(f.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.UNIX_TIMESTAMP, originField); + } else { + // 如果都是时间类型,把date和time类型进行字符串拼接 + if (isCross) { + if (StringUtils.equalsIgnoreCase(f.getType(), "date")) { + originField = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, originField, "' 00:00:00'"), SQLConstants.DEFAULT_DATE_FORMAT); + } else if (StringUtils.equalsIgnoreCase(f.getType(), "time")) { + originField = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, "'1970-01-01 '", originField), SQLConstants.DEFAULT_DATE_FORMAT); + } + } + fieldName = originField; + } + } else if (Objects.equals(f.getDeExtractType(), DeTypeConstants.DE_STRING)) { + if (Objects.equals(f.getDeType(), DeTypeConstants.DE_INT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_FLOAT_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_TIME)) { + fieldName = StringUtils.isEmpty(f.getDateFormat()) ? String.format(SQLConstants.DE_STR_TO_DATE, originField, SQLConstants.DEFAULT_DATE_FORMAT) : + String.format(SQLConstants.DE_DATE_FORMAT, String.format(SQLConstants.DE_STR_TO_DATE, originField, f.getDateFormat()), SQLConstants.DEFAULT_DATE_FORMAT); + } else { + fieldName = originField; + } + } else { + if (Objects.equals(f.getDeType(), DeTypeConstants.DE_TIME)) { + String cast = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + fieldName = String.format(SQLConstants.FROM_UNIXTIME, cast, SQLConstants.DEFAULT_DATE_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_INT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_INT_FORMAT); + } else if (Objects.equals(f.getDeType(), DeTypeConstants.DE_FLOAT)) { + fieldName = String.format(SQLConstants.CAST, originField, SQLConstants.DEFAULT_FLOAT_FORMAT); + } else { + fieldName = originField; + } + } + SQLObj result = SQLObj.builder() + .orderField(String.format(SQLConstants.FIELD_DOT, originField)) + .orderAlias(String.format(SQLConstants.FIELD_DOT, originField)) + .orderDirection(f.getOrderDirection()).build(); + return result; + } + +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/Quota2SQLObj.java b/backend/src/main/java/com/stdproject/utils/trans/Quota2SQLObj.java new file mode 100644 index 0000000..25cef3a --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/Quota2SQLObj.java @@ -0,0 +1,176 @@ +package com.stdproject.utils.trans; + +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.utils.Utils; +import io.gisbi.constant.DeTypeConstants; +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.view.dto.ChartViewFieldDTO; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.util.*; + +/** + * @Author bi-coder + */ +public class Quota2SQLObj { + + public static void quota2sqlObj(SQLMeta meta, List fields, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + List yFields = new ArrayList<>(); + List yWheres = new ArrayList<>(); + List yOrders = new ArrayList<>(); + Map fieldsDialect = new HashMap<>(); + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + + if (!CollectionUtils.isEmpty(fields)) { + for (int i = 0; i < fields.size(); i++) { + ChartViewFieldDTO y = fields.get(i); + String originField; + if (ObjectUtils.isNotEmpty(y.getExtField()) && Objects.equals(y.getExtField(), ExtFieldConstant.EXT_CALC)) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(y, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, y.getId()); + fieldsDialect.put(originField, calcFieldExp); + if (isCross) { + originField = calcFieldExp; + } + } else if (ObjectUtils.isNotEmpty(y.getExtField()) && Objects.equals(y.getExtField(), ExtFieldConstant.EXT_COPY)) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(y.getExtField()) && Objects.equals(y.getExtField(), ExtFieldConstant.EXT_GROUP)) { + String groupFieldExp = Utils.transGroupFieldToSql(y, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, y.getId()); + fieldsDialect.put(originField, groupFieldExp); + if (isCross) { + originField = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getOriginName()); + } else { + originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getGisbiName()); + } + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + // 处理纵轴字段 + SQLObj ySQLObj = getYFields(y, originField, fieldAlias); + if (StringUtils.equalsIgnoreCase("bar-range", meta.getChartType()) && StringUtils.equalsIgnoreCase(y.getGroupType(), "d") && y.getDeType() == 1) { + yFields.add(Dimension2SQLObj.getXFields(y, ySQLObj.getFieldName(), fieldAlias, isCross)); + } else { + yFields.add(ySQLObj); + } + // 处理纵轴过滤 + String wheres = getYWheres(y, originField, fieldAlias); + if (ObjectUtils.isNotEmpty(wheres)) { + yWheres.add(wheres); + } + // 处理纵轴排序 + if (StringUtils.isNotEmpty(y.getSort()) && Utils.joinSort(y.getSort())) { + yOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(y.getSort()) + .id(y.getId()) + .build()); + } + } + } + meta.setYFields(yFields); + meta.setYWheres(yWheres); + meta.setYOrders(yOrders); + meta.setYFieldsDialect(fieldsDialect); + } + + private static SQLObj getYFields(ChartViewFieldDTO y, String originField, String fieldAlias) { + String fieldName = ""; + if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) { + fieldName = SQLConstants.AGG_COUNT; + } else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) { + if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) { + fieldName = String.format(SQLConstants.AGG_FIELD, "COUNT", "DISTINCT " + originField); + } else { + fieldName = String.format(SQLConstants.AGG_FIELD, y.getSummary(), originField); + } + } else { + if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) { + String cast = String.format(SQLConstants.CAST, originField, Objects.equals(y.getDeType(), DeTypeConstants.DE_INT) ? SQLConstants.DEFAULT_INT_FORMAT : SQLConstants.DEFAULT_FLOAT_FORMAT); + String agg = String.format(SQLConstants.AGG_FIELD, y.getSummary(), cast); + String cast1 = String.format(SQLConstants.CAST, agg, SQLConstants.DEFAULT_FLOAT_FORMAT); + fieldName = String.format(SQLConstants.ROUND, cast1, "8"); + } else { + String cast = String.format(SQLConstants.CAST, originField, Objects.equals(y.getDeType(), DeTypeConstants.DE_INT) ? SQLConstants.DEFAULT_INT_FORMAT : SQLConstants.DEFAULT_FLOAT_FORMAT); + if (StringUtils.equalsIgnoreCase(y.getSummary(), "count_distinct")) { + fieldName = String.format(SQLConstants.AGG_FIELD, "COUNT", "DISTINCT " + cast); + } else if (y.getSummary() == null) { + // 透视表自定义汇总不用聚合 + fieldName = cast; + } else { + fieldName = String.format(SQLConstants.AGG_FIELD, y.getSummary(), cast); + } + } + } + + return SQLObj.builder() + .fieldName(fieldName) + .fieldAlias(fieldAlias) + .build(); + } + + private static String getYWheres(ChartViewFieldDTO y, String originField, String fieldAlias) { + List list = new ArrayList<>(); + if (!CollectionUtils.isEmpty(y.getFilter()) && y.getFilter().size() > 0) { + y.getFilter().forEach(f -> { + String whereTerm = Utils.transFilterTerm(f.getTerm()); + String whereValue = ""; + // 原始类型不是时间,在de中被转成时间的字段做处理 + if (StringUtils.equalsIgnoreCase(f.getTerm(), "null")) { + whereValue = ""; + } else if (StringUtils.equalsIgnoreCase(f.getTerm(), "not_null")) { + whereValue = ""; + } else if (StringUtils.equalsIgnoreCase(f.getTerm(), "empty")) { + whereValue = "''"; + } else if (StringUtils.equalsIgnoreCase(f.getTerm(), "not_empty")) { + whereValue = "''"; + } else if (StringUtils.containsIgnoreCase(f.getTerm(), "in")) { + whereValue = "('" + StringUtils.join(f.getValue(), "','") + "')"; + } else if (StringUtils.containsIgnoreCase(f.getTerm(), "like")) { + whereValue = "'%" + f.getValue() + "%'"; + } else { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, f.getValue()); + } + list.add(SQLObj.builder() + .whereField(fieldAlias) + .whereAlias(fieldAlias) + .whereTermAndValue(whereTerm + whereValue) + .build()); + }); + } + List strList = new ArrayList<>(); + list.forEach(ele -> strList.add(ele.getWhereField() + " " + ele.getWhereTermAndValue())); + return !CollectionUtils.isEmpty(list) ? "(" + String.join(" " + Utils.getLogic(y.getLogic()) + " ", strList) + ")" : null; + } + +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/Table2SQLObj.java b/backend/src/main/java/com/stdproject/utils/trans/Table2SQLObj.java new file mode 100644 index 0000000..43453ee --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/Table2SQLObj.java @@ -0,0 +1,26 @@ +package com.stdproject.utils.trans; + +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; + +/** + * @Author bi-coder + */ +public class Table2SQLObj { + public static void table2sqlobj(SQLMeta meta, String tablePrefix, String table, boolean crossDs) { + String sql; + if (table.startsWith("(") && table.endsWith(")") && !crossDs) {// SQL片段和关联 + meta.setTableDialect(table.substring(1, table.length() - 1)); + sql = "(" + SqlPlaceholderConstants.TABLE_PLACEHOLDER + ")"; + } else { + sql = table; + } + SQLObj tableObj = SQLObj.builder() + .tableName((table.startsWith("(") && table.endsWith(")")) ? sql : String.format(SQLConstants.TABLE_NAME, tablePrefix, table)) + .tableAlias(String.format(SQLConstants.TABLE_ALIAS_PREFIX, 0)) + .build(); + meta.setTable(tableObj); + } +} diff --git a/backend/src/main/java/com/stdproject/utils/trans/WhereTree2Str.java b/backend/src/main/java/com/stdproject/utils/trans/WhereTree2Str.java new file mode 100644 index 0000000..513cc0b --- /dev/null +++ b/backend/src/main/java/com/stdproject/utils/trans/WhereTree2Str.java @@ -0,0 +1,279 @@ +package com.stdproject.utils.trans; +import com.stdproject.constant.ExtFieldConstant; +import com.stdproject.entity.dto.DataSetRowPermissionsTreeDTO; +import com.stdproject.utils.Utils; +import io.gisbi.constant.SQLConstants; +import io.gisbi.extensions.datasource.api.PluginManageApi; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +import io.gisbi.extensions.datasource.dto.CalParam; +import io.gisbi.extensions.datasource.dto.DatasetTableFieldDTO; +import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO; +import io.gisbi.extensions.datasource.model.SQLMeta; +import io.gisbi.extensions.datasource.model.SQLObj; +import io.gisbi.extensions.datasource.vo.DatasourceConfiguration; +import io.gisbi.extensions.view.dto.DatasetRowPermissionsTreeItem; +import io.gisbi.extensions.view.dto.DatasetRowPermissionsTreeObj; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +public class WhereTree2Str { + public static void transFilterTrees(SQLMeta meta, List requestList, List originFields, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + SQLObj tableObj = meta.getTable(); + if (ObjectUtils.isEmpty(tableObj)) { + return; + } + if (CollectionUtils.isEmpty(requestList)) { + return; + } + List res = new ArrayList<>(); + List exportFilters = new ArrayList<>(); + Map fieldsDialect = new HashMap<>(); + // permission trees + // 解析每个tree,然后多个tree之间用and拼接 + // 每个tree,如果是sub tree节点,则使用递归合并成一组条件 + for (DataSetRowPermissionsTreeDTO request : requestList) { + DatasetRowPermissionsTreeObj tree = request.getTree(); + if (ObjectUtils.isEmpty(tree)) { + continue; + } + String treeExp = transTreeToWhere(tableObj, tree, originFields, fieldsDialect, isCross, dsMap, fieldParam, chartParam, pluginManage); + if (StringUtils.isNotEmpty(treeExp) && !request.isExportData()) { + res.add(treeExp); + } + if (StringUtils.isNotEmpty(treeExp) && request.isExportData()) { + exportFilters.add(treeExp); + } + } + String whereSql = null; + if (CollectionUtils.isNotEmpty(res)) { + whereSql = String.join(" OR ", res); + } + if (CollectionUtils.isNotEmpty(exportFilters)) { + whereSql = whereSql == null ? String.join(" and ", exportFilters) : whereSql + " AND " + String.join(" and ", exportFilters); + } + meta.setWhereTrees(whereSql != null ? "(" + whereSql + ")" : null); + meta.setWhereTreesDialect(fieldsDialect); + } + + private static String transTreeToWhere(SQLObj tableObj, DatasetRowPermissionsTreeObj tree, List originFields, Map fieldsDialect, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + if (ObjectUtils.isEmpty(tree)) { + return null; + } + String logic = tree.getLogic(); + List items = tree.getItems(); + List list = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(items)) { + // type is item or tree + for (DatasetRowPermissionsTreeItem item : items) { + String exp = null; + if (StringUtils.equalsIgnoreCase(item.getType(), "item")) { + // 单个item拼接SQL,最后根据logic汇总 + exp = transTreeItem(tableObj, item, originFields, fieldsDialect, isCross, dsMap, fieldParam, chartParam, pluginManage); + } else if (StringUtils.equalsIgnoreCase(item.getType(), "tree")) { + // 递归tree + exp = transTreeToWhere(tableObj, item.getSubTree(), originFields, fieldsDialect, isCross, dsMap, fieldParam, chartParam, pluginManage); + } + if (StringUtils.isNotEmpty(exp)) { + list.add(exp); + } + } + } + return CollectionUtils.isNotEmpty(list) ? "(" + String.join(" " + logic + " ", list) + ")" : null; + } + + public static String transTreeItem(SQLObj tableObj, DatasetRowPermissionsTreeItem item, List originFields, Map fieldsDialect, boolean isCross, Map dsMap, List fieldParam, List chartParam, PluginManageApi pluginManage) { + String res = null; + DatasetTableFieldDTO field = item.getField(); + if (ObjectUtils.isEmpty(field)) { + return null; + } + Map paramMap = Utils.mergeParam(fieldParam, chartParam); + String whereName = ""; + String originName; + + String dsType = null; + if (dsMap != null && dsMap.entrySet().iterator().hasNext()) { + Map.Entry next = dsMap.entrySet().iterator().next(); + dsType = next.getValue().getType(); + } + + if (ObjectUtils.isNotEmpty(field.getExtField()) && Objects.equals(field.getExtField(), ExtFieldConstant.EXT_CALC)) { + // 解析origin name中有关联的字段生成sql表达式 + String calcFieldExp = Utils.calcFieldRegex(field, tableObj, originFields, isCross, dsMap, paramMap); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); + fieldsDialect.put(originName, calcFieldExp); + if (isCross) { + originName = calcFieldExp; + } + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && Objects.equals(field.getExtField(), ExtFieldConstant.EXT_COPY)) { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getGisbiName()); + } + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && Objects.equals(field.getExtField(), ExtFieldConstant.EXT_GROUP)) { + String groupFieldExp = Utils.transGroupFieldToSql(field, originFields, isCross, dsMap, pluginManage); + // 给计算字段处加一个占位符,后续SQL方言转换后再替换 + originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); + fieldsDialect.put(originName, groupFieldExp); + if (isCross) { + originName = groupFieldExp; + } + } else { + if (StringUtils.equalsIgnoreCase(dsType, "es")) { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getGisbiName()); + } + } + if (field.getDeType() == 1) { + if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5) { + whereName = String.format(SQLConstants.DE_STR_TO_DATE, originName, StringUtils.isNotEmpty(field.getDateFormat()) ? field.getDateFormat() : SQLConstants.DEFAULT_DATE_FORMAT); + } + if (field.getDeExtractType() == 2 || field.getDeExtractType() == 3 || field.getDeExtractType() == 4) { + String cast = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT); + whereName = String.format(SQLConstants.FROM_UNIXTIME, cast, SQLConstants.DEFAULT_DATE_FORMAT); + } + if (field.getDeExtractType() == 1) { + // 如果都是时间类型,把date和time类型进行字符串拼接 + if (isCross) { + if (StringUtils.equalsIgnoreCase(field.getType(), "date")) { + originName = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, originName, "' 00:00:00'"), SQLConstants.DEFAULT_DATE_FORMAT); + } else if (StringUtils.equalsIgnoreCase(field.getType(), "time")) { + originName = String.format(SQLConstants.DE_STR_TO_DATE, String.format(SQLConstants.CONCAT, "'1970-01-01 '", originName), SQLConstants.DEFAULT_DATE_FORMAT); + } + } + if (StringUtils.equalsIgnoreCase(field.getType(), "date") + || (StringUtils.equalsIgnoreCase(dsMap.entrySet().iterator().next().getValue().getType(), "oracle") && StringUtils.equalsIgnoreCase(field.getType(), "timestamp"))) { + whereName = String.format(SQLConstants.DE_CAST_DATE_FORMAT, originName, + SQLConstants.DEFAULT_DATE_FORMAT, + SQLConstants.DEFAULT_DATE_FORMAT); + } else { + whereName = originName; + } + } + } else if (field.getDeType() == 2 || field.getDeType() == 3) { + if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_FLOAT_FORMAT); + } + if (field.getDeExtractType() == 1) { + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, originName); + } + if (field.getDeExtractType() == 2 || field.getDeExtractType() == 4) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_INT_FORMAT); + } + if (field.getDeExtractType() == 3) { + whereName = String.format(SQLConstants.CAST, originName, SQLConstants.DEFAULT_FLOAT_FORMAT); + } + } else { + whereName = originName; + } + + if (StringUtils.equalsIgnoreCase(item.getFilterType(), "enum")) { + if (CollectionUtils.isNotEmpty(item.getEnumValue())) { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + res = "(" + whereName + " IN (" + item.getEnumValue().stream().map(str -> "'" + SQLConstants.MSSQL_N_PREFIX + str + "'").collect(Collectors.joining(",")) + "))"; + } else { + res = "(" + whereName + " IN ('" + String.join("','", item.getEnumValue()) + "'))"; + } + } + } else { + String value = item.getValue(); + String whereTerm = Utils.transFilterTerm(item.getTerm()); + String whereValue = ""; + + if (field.getDeType() == 1 && isCross) { + whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName); + } + + if (StringUtils.equalsIgnoreCase(item.getTerm(), "null")) { + whereValue = ""; + } else if (StringUtils.equalsIgnoreCase(item.getTerm(), "not_null")) { + whereValue = ""; + } else if (StringUtils.equalsIgnoreCase(item.getTerm(), "empty")) { + whereValue = "''"; + } else if (StringUtils.equalsIgnoreCase(item.getTerm(), "not_empty")) { + whereValue = "''"; + } else if (StringUtils.containsIgnoreCase(item.getTerm(), "in") || StringUtils.containsIgnoreCase(item.getTerm(), "not in")) { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "(" + Arrays.stream(value.split(",")).map(str -> "'" + SQLConstants.MSSQL_N_PREFIX + str + "'").collect(Collectors.joining(",")) + ")"; + } else { + whereValue = "('" + String.join("','", value.split(",")) + "')"; + } + } else if (StringUtils.containsIgnoreCase(item.getTerm(), "like")) { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = "'" + SQLConstants.MSSQL_N_PREFIX + "%" + value + "%'"; + } else { + whereValue = "'%" + value + "%'"; + } + } else { + // 如果是时间字段过滤,当条件是等于和不等于的时候转换成between和not between + if (field.getDeType() == 1) { + Map stringLongMap = Utils.parseDateTimeValue(value); + if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) { + whereTerm = " BETWEEN "; + // 把value类似过滤组件处理,获得start time和end time + if (isCross) { + whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2Str(stringLongMap.get("startTime")), Utils.transLong2Str(stringLongMap.get("endTime"))); + } + } else if (StringUtils.equalsIgnoreCase(whereTerm, " <> ")) { + whereTerm = " NOT BETWEEN "; + if (isCross) { + whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); + } else { + whereValue = String.format(SQLConstants.WHERE_BETWEEN, Utils.transLong2Str(stringLongMap.get("startTime")), Utils.transLong2Str(stringLongMap.get("endTime"))); + } + } else { + Long startTime = stringLongMap.get("startTime"); + Long endTime = stringLongMap.get("endTime"); + if (isCross) { + if (StringUtils.equalsIgnoreCase(whereTerm, " > ") || StringUtils.equalsIgnoreCase(whereTerm, " <= ")) { + value = endTime + ""; + } else if (StringUtils.equalsIgnoreCase(whereTerm, " >= ") || StringUtils.equalsIgnoreCase(whereTerm, " < ")) { + value = startTime + ""; + } + } else { + if (StringUtils.equalsIgnoreCase(whereTerm, " > ") || StringUtils.equalsIgnoreCase(whereTerm, " <= ")) { + value = Utils.transLong2Str(endTime); + } else if (StringUtils.equalsIgnoreCase(whereTerm, " >= ") || StringUtils.equalsIgnoreCase(whereTerm, " < ")) { + value = Utils.transLong2Str(startTime); + } + } + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, value); + } + } else { + if ((StringUtils.containsIgnoreCase(field.getType(), "NVARCHAR") + || StringUtils.containsIgnoreCase(field.getType(), "NCHAR")) + && !isCross + && StringUtils.equalsIgnoreCase(dsType, DatasourceConfiguration.DatasourceType.sqlServer.getType())) { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE_CH, value); + } else { + whereValue = String.format(SQLConstants.WHERE_VALUE_VALUE, value); + } + } + } + SQLObj build = SQLObj.builder().whereField(whereName).whereTermAndValue(whereTerm + whereValue).build(); + res = build.getWhereField() + " " + build.getWhereTermAndValue(); + } + return res; + } +} diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index bf86952..11060a5 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -1,5 +1,5 @@ server: - port: 8080 + port: 8083 servlet: context-path: / encoding: @@ -50,7 +50,7 @@ spring: private-key: ${RSA_PRIVATE_KEY:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==} mybatis-plus: - mapper-locations: classpath*:/mapper/**/*.xml # MyBatis Mapper XML文件位置 + mapper-locations: classpath*:/mybatis/**/*.xml # MyBatis Mapper XML文件位置 type-aliases-package: com.stdproject.entity global-config: db-config: diff --git a/backend/src/main/resources/mybatis/ExtCoreChartMapper.xml b/backend/src/main/resources/mybatis/ExtCoreChartMapper.xml new file mode 100644 index 0000000..c9ef951 --- /dev/null +++ b/backend/src/main/resources/mybatis/ExtCoreChartMapper.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + diff --git a/backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml b/backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml new file mode 100644 index 0000000..7bfd40b --- /dev/null +++ b/backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +