From a678c15c1180f31e1f06fdd4200758ba87ba1520 Mon Sep 17 00:00:00 2001 From: root <13910913995@163.com> Date: Mon, 23 Jun 2025 10:40:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BA=86=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/gisbi/ai/service/AiBaseService.java | 34 + .../charts/impl/bar/BulletGraphHandler.java | 80 ++ .../gisbi/commons/utils/DeSqlparserUtils.java | 294 +++++++ .../java/io/gisbi/copilot/api/CopilotAPI.java | 102 +++ .../dao/auto/entity/CoreCopilotConfig.java | 71 ++ .../dao/auto/entity/CoreCopilotMsg.java | 276 ++++++ .../dao/auto/entity/CoreCopilotToken.java | 74 ++ .../auto/mapper/CoreCopilotConfigMapper.java | 18 + .../dao/auto/mapper/CoreCopilotMsgMapper.java | 18 + .../auto/mapper/CoreCopilotTokenMapper.java | 18 + .../gisbi/copilot/manage/CopilotManage.java | 474 ++++++++++ .../io/gisbi/copilot/manage/MsgManage.java | 100 +++ .../io/gisbi/copilot/manage/TokenManage.java | 36 + .../gisbi/copilot/service/CopilotService.java | 40 + .../auth/InteractiveAuthFeignService.java | 8 + .../auth/PermissionFeignService.java | 10 + .../permissions/user/UserFeignService.java | 8 + .../auto/entity/CoreExportDownloadTask.java | 57 ++ .../mapper/CoreExportDownloadTaskMapper.java | 18 + .../dao/ext/mapper/ExportTaskExtMapper.java | 43 + .../manage/ExportCenterDownLoadManage.java | 826 ++++++++++++++++++ .../gisbi/listener/DatasetCrossListener.java | 46 + .../system/manage/CorePermissionManage.java | 14 + .../auto/entity/SnapshotCoreChartView.java | 640 ++++++++++++++ .../entity/SnapshotDataVisualizationInfo.java | 374 ++++++++ .../entity/SnapshotVisualizationLinkJump.java | 122 +++ .../SnapshotVisualizationLinkJumpInfo.java | 192 ++++ ...otVisualizationLinkJumpTargetViewInfo.java | 138 +++ .../entity/SnapshotVisualizationLinkage.java | 178 ++++ .../SnapshotVisualizationLinkageField.java | 122 +++ .../SnapshotVisualizationOuterParams.java | 110 +++ .../SnapshotVisualizationOuterParamsInfo.java | 152 ++++ ...isualizationOuterParamsTargetViewInfo.java | 124 +++ .../mapper/SnapshotCoreChartViewMapper.java | 18 + .../SnapshotDataVisualizationInfoMapper.java | 18 + ...apshotVisualizationLinkJumpInfoMapper.java | 18 + .../SnapshotVisualizationLinkJumpMapper.java | 18 + ...alizationLinkJumpTargetViewInfoMapper.java | 18 + ...apshotVisualizationLinkageFieldMapper.java | 18 + .../SnapshotVisualizationLinkageMapper.java | 18 + ...hotVisualizationOuterParamsInfoMapper.java | 18 + ...napshotVisualizationOuterParamsMapper.java | 18 + ...zationOuterParamsTargetViewInfoMapper.java | 18 + .../main/resources/application-desktop.yml | 25 + .../resources/db/migration/V2.10.11__ddl.sql | 8 + .../resources/db/migration/V2.10.6__ddl.sql | 9 + .../resources/db/migration/V2.10.7__ddl.sql | 210 +++++ .../resources/db/migration/V2.10.8__ddl.sql | 5 + .../resources/mybatis/ExtCoreChartMapper.xml | 62 ++ 49 files changed, 5316 insertions(+) create mode 100644 core/core-backend/src/main/java/io/gisbi/ai/service/AiBaseService.java create mode 100644 core/core-backend/src/main/java/io/gisbi/chart/charts/impl/bar/BulletGraphHandler.java create mode 100644 core/core-backend/src/main/java/io/gisbi/commons/utils/DeSqlparserUtils.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/api/CopilotAPI.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotConfig.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotMsg.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotToken.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/manage/CopilotManage.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/manage/MsgManage.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/manage/TokenManage.java create mode 100644 core/core-backend/src/main/java/io/gisbi/copilot/service/CopilotService.java create mode 100644 core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/InteractiveAuthFeignService.java create mode 100644 core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/PermissionFeignService.java create mode 100644 core/core-backend/src/main/java/io/gisbi/defeign/permissions/user/UserFeignService.java create mode 100644 core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/entity/CoreExportDownloadTask.java create mode 100644 core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/mapper/CoreExportDownloadTaskMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/exportCenter/dao/ext/mapper/ExportTaskExtMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/exportCenter/manage/ExportCenterDownLoadManage.java create mode 100644 core/core-backend/src/main/java/io/gisbi/listener/DatasetCrossListener.java create mode 100644 core/core-backend/src/main/java/io/gisbi/system/manage/CorePermissionManage.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotCoreChartView.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotDataVisualizationInfo.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJump.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpInfo.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpTargetViewInfo.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkage.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkageField.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParams.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsInfo.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsTargetViewInfo.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotCoreChartViewMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotDataVisualizationInfoMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpInfoMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpTargetViewInfoMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageFieldMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsInfoMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsMapper.java create mode 100644 core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsTargetViewInfoMapper.java create mode 100644 core/core-backend/src/main/resources/application-desktop.yml create mode 100644 core/core-backend/src/main/resources/db/migration/V2.10.11__ddl.sql create mode 100644 core/core-backend/src/main/resources/db/migration/V2.10.6__ddl.sql create mode 100644 core/core-backend/src/main/resources/db/migration/V2.10.7__ddl.sql create mode 100644 core/core-backend/src/main/resources/db/migration/V2.10.8__ddl.sql create mode 100644 core/core-backend/src/main/resources/mybatis/ExtCoreChartMapper.xml diff --git a/core/core-backend/src/main/java/io/gisbi/ai/service/AiBaseService.java b/core/core-backend/src/main/java/io/gisbi/ai/service/AiBaseService.java new file mode 100644 index 0000000..3fde4cf --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/ai/service/AiBaseService.java @@ -0,0 +1,34 @@ +package io.gisbi.ai.service; + +import io.gisbi.api.ai.AiComponentApi; +import io.gisbi.commons.utils.UrlTestUtils; +import io.gisbi.system.manage.SysParameterManage; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author : WangJiaHao + * @date : 2024/3/27 09:47 + */ +@RestController +@RequestMapping("aiBase") +public class AiBaseService implements AiComponentApi { + @Resource + private SysParameterManage sysParameterManage; + + @Override + public Map findTargetUrl() { + Map templateParams = sysParameterManage.groupVal("ai."); + if (templateParams != null && StringUtils.isNotEmpty(templateParams.get("ai.baseUrl"))) { + return templateParams; + + } else { + return new HashMap<>(); + } + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/chart/charts/impl/bar/BulletGraphHandler.java b/core/core-backend/src/main/java/io/gisbi/chart/charts/impl/bar/BulletGraphHandler.java new file mode 100644 index 0000000..f55ddc1 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/chart/charts/impl/bar/BulletGraphHandler.java @@ -0,0 +1,80 @@ +package io.gisbi.chart.charts.impl.bar; + +import io.gisbi.api.dataset.union.DatasetGroupInfoDTO; +import io.gisbi.chart.charts.impl.YoyChartHandler; +import io.gisbi.chart.utils.ChartDataBuild; +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.view.dto.*; +import lombok.Getter; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Component +public class BulletGraphHandler extends YoyChartHandler { + @Getter + private String type = "bullet-graph"; + + @Override + public AxisFormatResult formatAxis(ChartViewDTO view) { + var result = super.formatAxis(view); + var yAxis = result.getAxisMap().get(ChartAxis.yAxis); + yAxis.addAll(view.getYAxisExt()); + yAxis.addAll(view.getExtBubble()); + yAxis.addAll(view.getExtTooltip()); + result.getAxisMap().put(ChartAxis.yAxis, yAxis); + result.getAxisMap().put(ChartAxis.yAxisExt, view.getYAxisExt()); + result.getAxisMap().put(ChartAxis.extBubble, view.getExtBubble()); + result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip()); + return result; + } + + @Override + public Map buildNormalResult(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); + return ChartDataBuild.transChartData(xAxis, yAxis, view, data, isDrill); + } + + @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()); + } + var result = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider); + try { + //如果有同环比过滤,应该用原始sql + var originSql = result.getQuerySql(); + var dynamicAssistFields = getDynamicAssistFields(view); + var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis); + var assistFields = getAssistFields(dynamicAssistFields, yAxis); + if (CollectionUtils.isNotEmpty(assistFields)) { + var req = new DatasourceRequest(); + req.setIsCross(((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross()); + req.setDsList(dsMap); + var assistSql = assistSQL(originSql, assistFields, dsMap, ((DatasetGroupInfoDTO) formatResult.getContext().get("dataset")).getIsCross()); + req.setQuery(assistSql); + logger.debug("calcite assistSql sql: " + assistSql); + var assistData = (List) provider.fetchResultField(req).get("data"); + result.setAssistData(assistData); + result.setDynamicAssistFields(dynamicAssistFields); + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + +} diff --git a/core/core-backend/src/main/java/io/gisbi/commons/utils/DeSqlparserUtils.java b/core/core-backend/src/main/java/io/gisbi/commons/utils/DeSqlparserUtils.java new file mode 100644 index 0000000..78d3472 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/commons/utils/DeSqlparserUtils.java @@ -0,0 +1,294 @@ +package io.gisbi.commons.utils; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.gisbi.api.permissions.user.vo.UserFormVO; +import io.gisbi.api.permissions.variable.dto.SysVariableValueDto; +import io.gisbi.api.permissions.variable.dto.SysVariableValueItem; +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.collections4.CollectionUtils; +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 io.gisbi.chart.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(); + } + for (SysVariableValueItem variable : userEntity.getVariables()) { + if (!variable.isValid()) { + continue; + } + if (!sysVariableId.equalsIgnoreCase(variable.getVariableId().toString())) { + continue; + } + if (variable.getSysVariableDto().getType().equalsIgnoreCase("text")) { + for (SysVariableValueDto sysVariableValueDto : variable.getValueList()) { + if (variable.getVariableValueIds().contains(sysVariableValueDto.getId().toString())) { + return sysVariableValueDto.getValue(); + } + } + } else { + return variable.getVariableValue(); + } + } + return null; + } else { + return null; + } + } + + + private String handleSubstitutedSqlForIn(String sysVariableId) { + if (userEntity != null) { + for (SysVariableValueItem variable : userEntity.getVariables()) { + List values = new ArrayList<>(); + if (!variable.isValid()) { + continue; + } + if (!sysVariableId.equalsIgnoreCase(variable.getVariableId().toString())) { + 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)) { + return "'" + String.join("','", values) + "'"; + } + } + return null; + } else { + return null; + } + } +} + + + diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/api/CopilotAPI.java b/core/core-backend/src/main/java/io/gisbi/copilot/api/CopilotAPI.java new file mode 100644 index 0000000..952b1e0 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/api/CopilotAPI.java @@ -0,0 +1,102 @@ +package io.gisbi.copilot.api; + +import io.gisbi.api.copilot.dto.ReceiveDTO; +import io.gisbi.api.copilot.dto.SendDTO; +import io.gisbi.copilot.dao.auto.entity.CoreCopilotConfig; +import io.gisbi.copilot.dao.auto.mapper.CoreCopilotConfigMapper; +import io.gisbi.exception.DEException; +import io.gisbi.utils.HttpClientConfig; +import io.gisbi.utils.HttpClientUtil; +import io.gisbi.utils.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.json.simple.JSONObject; +import org.springframework.stereotype.Component; + +import java.util.Base64; +import java.util.Map; + +/** + * @Author bi-coder + */ +@Component +public class CopilotAPI { + + public static final String TOKEN = "/auth/token/license"; + + public static final String FREE_TOKEN = "/auth/token/free"; + + public static final String API = "/copilot/v1"; + + public static final String CHART = "/generate-chart"; + + public static final String RATE_LIMIT = "/rate-limit"; + + @Resource + private CoreCopilotConfigMapper coreCopilotConfigMapper; + + public String basicAuth(String userName, String password) { + String auth = userName + ":" + password; + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes()); + return "Basic " + encodedAuth; + } + + public String bearerAuth(String token) { + return "Bearer " + token; + } + + public CoreCopilotConfig getConfig() { + CoreCopilotConfig coreCopilotConfig = coreCopilotConfigMapper.selectById(1); + coreCopilotConfig.setPwd(new String(Base64.getDecoder().decode(coreCopilotConfig.getPwd()))); + return coreCopilotConfig; + } + + public String getToken(String license) throws Exception { + String url = getConfig().getCopilotUrl() + TOKEN; + JSONObject json = new JSONObject(); + json.put("licenseText", license); + HttpClientConfig httpClientConfig = new HttpClientConfig(); + String tokenJson = HttpClientUtil.post(url, json.toString(), httpClientConfig); + return (String) JsonUtil.parse(tokenJson, Map.class).get("accessToken"); + } + + public String getFreeToken() throws Exception { + String url = getConfig().getCopilotUrl() + FREE_TOKEN; + HttpClientConfig httpClientConfig = new HttpClientConfig(); + String tokenJson = HttpClientUtil.post(url, "", httpClientConfig); + return (String) JsonUtil.parse(tokenJson, Map.class).get("accessToken"); + } + + public ReceiveDTO generateChart(String token, SendDTO sendDTO) { + String url = getConfig().getCopilotUrl() + API + CHART; + String request = (String) JsonUtil.toJSONString(sendDTO); + HttpClientConfig httpClientConfig = new HttpClientConfig(); + httpClientConfig.addHeader("Authorization", bearerAuth(token)); + String result = HttpClientUtil.post(url, request, httpClientConfig); + return JsonUtil.parseObject(result, ReceiveDTO.class); + } + + public void checkRateLimit(String token) { + String url = getConfig().getCopilotUrl() + API + RATE_LIMIT; + HttpClientConfig httpClientConfig = new HttpClientConfig(); + httpClientConfig.addHeader("Authorization", bearerAuth(token)); + HttpResponse httpResponse = HttpClientUtil.postWithHeaders(url, null, httpClientConfig); + Header[] allHeaders = httpResponse.getAllHeaders(); + + String limit = ""; + String seconds = ""; + for (Header header : allHeaders) { + if (StringUtils.equalsIgnoreCase(header.getName(), "x-rate-limit-remaining")) { + limit = header.getValue(); + } + if (StringUtils.equalsIgnoreCase(header.getName(), "x-rate-limit-retry-after-seconds")) { + seconds = header.getValue(); + } + } + if (Long.parseLong(limit) <= 0) { + DEException.throwException(String.format("当前请求频率已达上限,请在%s秒后重试", seconds)); + } + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotConfig.java b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotConfig.java new file mode 100644 index 0000000..3a43a50 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotConfig.java @@ -0,0 +1,71 @@ +package io.gisbi.copilot.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2024-07-08 + */ +@TableName("core_copilot_config") +public class CoreCopilotConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + private String copilotUrl; + + private String username; + + private String pwd; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCopilotUrl() { + return copilotUrl; + } + + public void setCopilotUrl(String copilotUrl) { + this.copilotUrl = copilotUrl; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPwd() { + return pwd; + } + + public void setPwd(String pwd) { + this.pwd = pwd; + } + + @Override + public String toString() { + return "CoreCopilotConfig{" + + "id = " + id + + ", copilotUrl = " + copilotUrl + + ", username = " + username + + ", pwd = " + pwd + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotMsg.java b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotMsg.java new file mode 100644 index 0000000..71e56d6 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotMsg.java @@ -0,0 +1,276 @@ +package io.gisbi.copilot.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2024-07-04 + */ +@TableName("core_copilot_msg") +public class CoreCopilotMsg implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * 用户ID + */ + private Long userId; + + /** + * 数据集ID + */ + private Long datasetGroupId; + + /** + * user or api + */ + private String msgType; + + /** + * mysql oracle ... + */ + private String engineType; + + /** + * create sql + */ + private String schemaSql; + + /** + * 用户提问 + */ + private String question; + + /** + * 历史信息 + */ + private String history; + + /** + * copilot 返回 sql + */ + private String copilotSql; + + /** + * copilot 返回信息 + */ + private String apiMsg; + + /** + * sql 状态 + */ + private Integer sqlOk; + + /** + * chart 状态 + */ + private Integer chartOk; + + /** + * chart 内容 + */ + private String chart; + + /** + * 视图数据 + */ + private String chartData; + + /** + * 执行请求的SQL + */ + private String execSql; + + /** + * msg状态,0失败 1成功 + */ + private Integer msgStatus; + + /** + * de错误信息 + */ + private String errMsg; + + /** + * 创建时间 + */ + private Long createTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getDatasetGroupId() { + return datasetGroupId; + } + + public void setDatasetGroupId(Long datasetGroupId) { + this.datasetGroupId = datasetGroupId; + } + + public String getMsgType() { + return msgType; + } + + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public String getEngineType() { + return engineType; + } + + public void setEngineType(String engineType) { + this.engineType = engineType; + } + + public String getSchemaSql() { + return schemaSql; + } + + public void setSchemaSql(String schemaSql) { + this.schemaSql = schemaSql; + } + + public String getQuestion() { + return question; + } + + public void setQuestion(String question) { + this.question = question; + } + + public String getHistory() { + return history; + } + + public void setHistory(String history) { + this.history = history; + } + + public String getCopilotSql() { + return copilotSql; + } + + public void setCopilotSql(String copilotSql) { + this.copilotSql = copilotSql; + } + + public String getApiMsg() { + return apiMsg; + } + + public void setApiMsg(String apiMsg) { + this.apiMsg = apiMsg; + } + + public Integer getSqlOk() { + return sqlOk; + } + + public void setSqlOk(Integer sqlOk) { + this.sqlOk = sqlOk; + } + + public Integer getChartOk() { + return chartOk; + } + + public void setChartOk(Integer chartOk) { + this.chartOk = chartOk; + } + + public String getChart() { + return chart; + } + + public void setChart(String chart) { + this.chart = chart; + } + + public String getChartData() { + return chartData; + } + + public void setChartData(String chartData) { + this.chartData = chartData; + } + + public String getExecSql() { + return execSql; + } + + public void setExecSql(String execSql) { + this.execSql = execSql; + } + + public Integer getMsgStatus() { + return msgStatus; + } + + public void setMsgStatus(Integer msgStatus) { + this.msgStatus = msgStatus; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + @Override + public String toString() { + return "CoreCopilotMsg{" + + "id = " + id + + ", userId = " + userId + + ", datasetGroupId = " + datasetGroupId + + ", msgType = " + msgType + + ", engineType = " + engineType + + ", schemaSql = " + schemaSql + + ", question = " + question + + ", history = " + history + + ", copilotSql = " + copilotSql + + ", apiMsg = " + apiMsg + + ", sqlOk = " + sqlOk + + ", chartOk = " + chartOk + + ", chart = " + chart + + ", chartData = " + chartData + + ", execSql = " + execSql + + ", msgStatus = " + msgStatus + + ", errMsg = " + errMsg + + ", createTime = " + createTime + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotToken.java b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotToken.java new file mode 100644 index 0000000..2454004 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/entity/CoreCopilotToken.java @@ -0,0 +1,74 @@ +package io.gisbi.copilot.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2024-07-08 + */ +@TableName("core_copilot_token") +public class CoreCopilotToken implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long id; + + /** + * free or license + */ + private String type; + + private String token; + + private Long updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Long updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "CoreCopilotToken{" + + "id = " + id + + ", type = " + type + + ", token = " + token + + ", updateTime = " + updateTime + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java new file mode 100644 index 0000000..9bd1755 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotConfigMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.copilot.dao.auto.mapper; + +import io.gisbi.copilot.dao.auto.entity.CoreCopilotConfig; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2024-07-08 + */ +@Mapper +public interface CoreCopilotConfigMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java new file mode 100644 index 0000000..19143fb --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotMsgMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.copilot.dao.auto.mapper; + +import io.gisbi.copilot.dao.auto.entity.CoreCopilotMsg; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2024-07-04 + */ +@Mapper +public interface CoreCopilotMsgMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java new file mode 100644 index 0000000..76f030e --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/dao/auto/mapper/CoreCopilotTokenMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.copilot.dao.auto.mapper; + +import io.gisbi.copilot.dao.auto.entity.CoreCopilotToken; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2024-07-08 + */ +@Mapper +public interface CoreCopilotTokenMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/manage/CopilotManage.java b/core/core-backend/src/main/java/io/gisbi/copilot/manage/CopilotManage.java new file mode 100644 index 0000000..fb915fe --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/manage/CopilotManage.java @@ -0,0 +1,474 @@ +package io.gisbi.copilot.manage; + +import com.fasterxml.jackson.core.type.TypeReference; +import io.gisbi.api.copilot.dto.*; +import io.gisbi.api.dataset.union.DatasetGroupInfoDTO; +import io.gisbi.api.dataset.union.UnionDTO; +import io.gisbi.chart.utils.ChartDataBuild; +import io.gisbi.copilot.api.CopilotAPI; +import io.gisbi.dataset.dao.auto.entity.CoreDatasetGroup; +import io.gisbi.dataset.dao.auto.mapper.CoreDatasetGroupMapper; +import io.gisbi.dataset.manage.DatasetDataManage; +import io.gisbi.dataset.manage.DatasetSQLManage; +import io.gisbi.dataset.manage.DatasetTableFieldManage; +import io.gisbi.dataset.manage.PermissionManage; +import io.gisbi.dataset.utils.FieldUtils; +import io.gisbi.constant.DeTypeConstants; +import io.gisbi.engine.utils.Utils; +import io.gisbi.exception.DEException; +import io.gisbi.extensions.datasource.constant.SqlPlaceholderConstants; +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.dto.TableField; +import io.gisbi.extensions.datasource.factory.ProviderFactory; +import io.gisbi.extensions.datasource.provider.Provider; +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.JsonUtil; +import jakarta.annotation.Resource; +import org.apache.calcite.config.Lex; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.parser.SqlParser; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author bi-coder + */ +@Component +public class CopilotManage { + @Resource + private DatasetSQLManage datasetSQLManage; + @Resource + private CoreDatasetGroupMapper coreDatasetGroupMapper; + @Resource + private DatasetTableFieldManage datasetTableFieldManage; + @Resource + private DatasetDataManage datasetDataManage; + @Resource + private PermissionManage permissionManage; + @Resource + private MsgManage msgManage; + + private static Logger logger = LoggerFactory.getLogger(CopilotManage.class); + + @Resource + private TokenManage tokenManage; + + @Resource + private CopilotAPI copilotAPI; + + + private String[] chartType = {"bar", "line", "pie"}; + + public MsgDTO chat(MsgDTO msgDTO) throws Exception { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(msgDTO.getDatasetGroupId()); + if (coreDatasetGroup == null) { + return null; + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + + // 获取field + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(msgDTO.getDatasetGroupId()); + List allFields = dsFields.stream().filter(ele -> ele.getExtField() == 0) + .map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + Map sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null); + String sql = (String) sqlMap.get("sql");// 数据集原始SQL + Map dsMap = (Map) sqlMap.get("dsMap"); + boolean crossDs = Utils.isCrossDs(dsMap); + if (crossDs) { + DEException.throwException(Translator.get("i18n_copilot_cross_ds_error")); + } + + // 调用copilot service 获取SQL和chart struct,将返回SQL中表名替换成数据集SQL + // deSendDTO 构建schema和engine + if (ObjectUtils.isEmpty(dsMap)) { + DEException.throwException("No datasource"); + } + + DatasourceSchemaDTO ds = dsMap.entrySet().iterator().next().getValue(); + String type = engine(ds.getType());// 数据库类型,如mysql,oracle等,可能需要映射成copilot需要的类型 + + datasetDataManage.buildFieldName(sqlMap, allFields); + List strings = transCreateTableFields(allFields); + String createSql = "CREATE TABLE de_tmp_table (" + StringUtils.join(strings, ",") + ")"; + logger.debug("Copilot Schema SQL: " + createSql); + +// PerMsgDTO perMsgDTO = new PerMsgDTO(); + msgDTO.setDatasetGroupId(dto.getId()); + msgDTO.setMsgType("user"); + msgDTO.setEngineType(type); + msgDTO.setSchemaSql(createSql); + msgDTO.setHistory(msgDTO.getHistory()); + msgDTO.setMsgStatus(1); + msgManage.save(msgDTO);// 到这里为止,提问所需参数构建完毕,往数据库插入一条提问记录 + + DESendDTO deSendDTO = new DESendDTO(); + deSendDTO.setDatasetGroupId(dto.getId()); + deSendDTO.setQuestion(msgDTO.getQuestion()); + deSendDTO.setHistory(msgDTO.getHistory()); + deSendDTO.setEngine(type); + deSendDTO.setSchema(createSql); + + // do copilot chat + ReceiveDTO receiveDTO = copilotChat(deSendDTO); + + // copilot 请求结束,继续de获取数据 + // 获取数据集相关行列权限、最终再套一层SQL + Map desensitizationList = new HashMap<>(); + allFields = permissionManage.filterColumnPermissions(allFields, desensitizationList, dto.getId(), null); + if (ObjectUtils.isEmpty(allFields)) { + DEException.throwException(Translator.get("i18n_no_column_permission")); + } + + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + + if (!crossDs) { + sql = Utils.replaceSchemaAlias(sql, dsMap); + } + + Provider provider; + if (crossDs) { + provider = ProviderFactory.getDefaultProvider(); + } else { + provider = ProviderFactory.getProvider(dsList.getFirst()); + } + +// List rowPermissionsTree = new ArrayList<>(); +// TokenUserBO user = AuthUtils.getUser(); +// if (user != null) { +// rowPermissionsTree = permissionManage.getRowPermissionsTree(dto.getId(), user.getUserId()); +// } + + // build query sql +// SQLMeta sqlMeta = new SQLMeta(); +// Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); +// Field2SQLObj.field2sqlObj(sqlMeta, allFields, allFields, crossDs, dsMap); +// WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, allFields, crossDs, dsMap); +// Order2SQLObj.getOrders(sqlMeta, dto.getSortFields(), allFields, crossDs, dsMap); +// String querySQL = SQLProvider.createQuerySQL(sqlMeta, false, false, needOrder); +// querySQL = provider.rebuildSQL(querySQL, sqlMeta, crossDs, dsMap); +// logger.debug("preview sql: " + querySQL); + + // 无法加行权限的情况下,直接用sql + String querySQL = sql; + + String copilotSQL = receiveDTO.getSql(); + // 用calcite尝试将SQL转方言,如果失败了,就按照原SQL执行 +// copilotSQL = transSql(type, copilotSQL, provider, receiveDTO); + + // 通过数据源请求数据 + // 调用数据源的calcite获得data + DatasourceRequest datasourceRequest = new DatasourceRequest(); + datasourceRequest.setDsList(dsMap); + datasourceRequest.setIsCross(coreDatasetGroup.getIsCross()); + String s = ""; + Map data; + try { + s = copilotSQL + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "de_tmp_table" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ")") + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "DE_TMP_TABLE" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ")"); + logger.debug("copilot sql: " + s); + datasourceRequest.setQuery(s); + data = provider.fetchResultField(datasourceRequest); + } catch (Exception e) { + try { + s = copilotSQL + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "de_tmp_table" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ") tmp") + .replaceAll(SqlPlaceholderConstants.KEYWORD_PREFIX_REGEX + "DE_TMP_TABLE" + SqlPlaceholderConstants.KEYWORD_SUFFIX_REGEX, "(" + querySQL + ") tmp"); + logger.debug("copilot sql: " + s); + datasourceRequest.setQuery(s); + data = provider.fetchResultField(datasourceRequest); + } catch (Exception e1) { + // 如果异常,则获取最后一条成功的history + MsgDTO lastSuccessMsg = msgManage.getLastSuccessMsg(AuthUtils.getUser().getUserId(), dto.getId()); + // 请求数据出错,记录错误信息和copilot返回的信息 + MsgDTO result = new MsgDTO(); + result.setDatasetGroupId(dto.getId()); + result.setMsgType("api"); + result.setHistory(lastSuccessMsg == null ? new ArrayList<>() : lastSuccessMsg.getHistory()); + result.setCopilotSql(receiveDTO.getSql()); + result.setApiMsg(receiveDTO.getApiMessage()); + result.setSqlOk(receiveDTO.getSqlOk() ? 1 : 0); + result.setChartOk(receiveDTO.getChartOk() ? 1 : 0); + result.setChart(receiveDTO.getChart()); + result.setExecSql(s); + result.setMsgStatus(0); + result.setErrMsg(e1.getMessage()); + msgManage.save(result); + return result; + } + } + + List fields = (List) data.get("fields"); + fields = transField(fields); + Map map = new LinkedHashMap<>(); + // 重新构造data + Map previewData = buildPreviewData(data, fields, desensitizationList); + + map.put("data", previewData); + map.put("sql", Base64.getEncoder().encodeToString(s.getBytes())); + + // 重构chart结构,补全缺失字段 + rebuildChart(receiveDTO, fields); + + MsgDTO result = new MsgDTO(); + result.setDatasetGroupId(dto.getId()); + result.setMsgType("api"); + result.setHistory(receiveDTO.getHistory()); + result.setCopilotSql(receiveDTO.getSql()); + result.setApiMsg(receiveDTO.getApiMessage()); + result.setSqlOk(receiveDTO.getSqlOk() ? 1 : 0); + result.setChartOk(receiveDTO.getChartOk() ? 1 : 0); + result.setChart(receiveDTO.getChart()); + result.setChartData(map); + result.setExecSql(s); + result.setMsgStatus(1); + msgManage.save(result); + return result; + } + + public ReceiveDTO copilotChat(DESendDTO deSendDTO) throws Exception { +// boolean valid = LicenseUtil.licenseValid(); + boolean valid = false; + // call copilot service + TokenDTO tokenDTO = tokenManage.getToken(valid); + ReceiveDTO receiveDTO; + if (StringUtils.isEmpty(tokenDTO.getToken())) { + // get token + String token; + token = copilotAPI.getFreeToken(); + tokenManage.updateToken(token, valid); + receiveDTO = copilotAPI.generateChart(token, deSendDTO); + } else { + try { + receiveDTO = copilotAPI.generateChart(tokenDTO.getToken(), deSendDTO); + } catch (Exception e) { + // error, get token again + String token; + token = copilotAPI.getFreeToken(); + tokenManage.updateToken(token, valid); + throw new Exception(e.getMessage()); + } + } + + if (!receiveDTO.getSqlOk() || !receiveDTO.getChartOk()) { + DEException.throwException((String) JsonUtil.toJSONString(receiveDTO)); + } + logger.debug("Copilot Service SQL: " + receiveDTO.getSql()); + logger.debug("Copilot Service Chart: " + JsonUtil.toJSONString(receiveDTO.getChart())); + return receiveDTO; + } + + public void rebuildChart(ReceiveDTO receiveDTO, List fields) { + if (StringUtils.equalsIgnoreCase(receiveDTO.getChart().getType(), "pie")) { + AxisFieldDTO column = receiveDTO.getChart().getColumn(); + if (fields.size() != 2 || column == null) { + DEException.throwException("build pie error: " + JsonUtil.toJSONString(receiveDTO)); + } + AxisDTO axisDTO = new AxisDTO(); + AxisFieldDTO x = new AxisFieldDTO(); + AxisFieldDTO y = new AxisFieldDTO(); + if (StringUtils.equals(fields.get(0).getOriginName(), column.getValue())) { + x.setName(column.getName()); + x.setValue(column.getValue()); + y.setName(fields.get(1).getOriginName()); + y.setValue(fields.get(1).getOriginName()); + } else if (StringUtils.equals(fields.get(1).getOriginName(), column.getValue())) { + x.setName(fields.get(0).getOriginName()); + x.setValue(fields.get(0).getOriginName()); + y.setName(column.getName()); + y.setValue(column.getValue()); + } else { + DEException.throwException("build pie error: " + JsonUtil.toJSONString(receiveDTO)); + } + axisDTO.setX(x); + axisDTO.setY(y); + receiveDTO.getChart().setAxis(axisDTO); + } else if (StringUtils.equalsIgnoreCase(receiveDTO.getChart().getType(), "table")) { + // 将fields赋值给columns + if (ObjectUtils.isEmpty(receiveDTO.getChart().getColumns())) { + List columns = new ArrayList<>(); + for (TableField field : fields) { + AxisFieldDTO dto = new AxisFieldDTO(); + dto.setName(field.getOriginName()); + dto.setValue(field.getOriginName()); + columns.add(dto); + } + receiveDTO.getChart().setColumns(columns); + } + } + + // 所有图表都加上columns字段用于切换明细表展示 + if (Arrays.asList(chartType).contains(receiveDTO.getChart().getType())) { + List columns = new ArrayList<>(); + columns.add(receiveDTO.getChart().getAxis().getX()); + columns.add(receiveDTO.getChart().getAxis().getY()); + receiveDTO.getChart().setColumns(columns); + } + } + + public List getList(Long userId) { + MsgDTO lastMsg = msgManage.getLastMsg(userId); + if (lastMsg == null) { + return null; + } + List msg = msgManage.getMsg(lastMsg); + msgManage.deleteMsg(lastMsg); + return msg; + } + + public void clearAll(Long userId) { + msgManage.clearAllUserMsg(userId); + } + + public MsgDTO errorMsg(MsgDTO msgDTO, String errMsg) throws Exception { + // 如果异常,则获取最后一条成功的history + MsgDTO lastSuccessMsg = msgManage.getLastSuccessMsg(AuthUtils.getUser().getUserId(), msgDTO.getDatasetGroupId()); + MsgDTO dto = new MsgDTO(); + dto.setDatasetGroupId(msgDTO.getDatasetGroupId()); + dto.setHistory(lastSuccessMsg == null ? new ArrayList<>() : lastSuccessMsg.getHistory()); + dto.setMsgStatus(0); + dto.setMsgType("api"); + dto.setErrMsg(errMsg); + msgManage.save(dto); + return dto; + } + + public List transField(List fields) { + fields.forEach(field -> { + field.setDeExtractType(FieldUtils.transType2DeType(field.getFieldType())); + field.setDeType(FieldUtils.transType2DeType(field.getFieldType())); + }); + return fields; + } + + public Map buildPreviewData(Map data, List fields, Map desensitizationList) { + Map map = new LinkedHashMap<>(); + List dataList = (List) data.get("data"); + List> dataObjectList = new ArrayList<>(); + if (ObjectUtils.isNotEmpty(dataList)) { + for (int i = 0; i < dataList.size(); i++) { + String[] row = dataList.get(i); + LinkedHashMap obj = new LinkedHashMap<>(); + if (row.length > 0) { + for (int j = 0; j < fields.size(); j++) { + TableField tableField = fields.get(j); + if (desensitizationList.containsKey(tableField.getOriginName())) { + obj.put(tableField.getOriginName(), ChartDataBuild.desensitizationValue(desensitizationList.get(tableField.getOriginName()), String.valueOf(row[j]))); + } else { + if (tableField.getDeExtractType() == DeTypeConstants.DE_INT + || tableField.getDeExtractType() == DeTypeConstants.DE_FLOAT + || tableField.getDeExtractType() == DeTypeConstants.DE_BOOL) { + try { + obj.put(tableField.getOriginName(), new BigDecimal(row[j])); + } catch (Exception e) { + obj.put(tableField.getOriginName(), row[j]); + } + } else { + obj.put(tableField.getOriginName(), row[j]); + } + } + } + } + dataObjectList.add(obj); + } + } + + map.put("fields", fields); + map.put("data", dataObjectList); + return map; + } + + public List transCreateTableFields(List allFields) { + List list = new ArrayList<>(); + for (DatasetTableFieldDTO dto : allFields) { + list.add(" " + dto.getGisbiName() + " " + transNum2Type(dto.getDeExtractType()) + + " COMMENT '" + dto.getName() + "'"); + } + return list; + } + + public String transNum2Type(Integer num) { + return switch (num) { + case 0, 1, 5 -> "VARCHAR(50)"; + case 2, 3, 4 -> "INT(10)"; + default -> "VARCHAR(50)"; + }; + } + + public Lex getLex(String type) { + switch (type) { + case "oracle": + return Lex.ORACLE; + case "sqlServer": + case "mssql": + return Lex.SQL_SERVER; + default: + return Lex.JAVA; + } + } + + public String transSql(String type, String copilotSQL, Provider provider, ReceiveDTO receiveDTO) { + if (type.equals("oracle") || type.equals("sqlServer")) { + try { + copilotSQL = copilotSQL.trim(); + if (copilotSQL.endsWith(";")) { + copilotSQL = copilotSQL.substring(0, copilotSQL.length() - 1); + } + DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO(); + datasourceSchemaDTO.setType(type); + SqlDialect dialect = provider.getDialect(datasourceSchemaDTO); + + SqlParser parser = SqlParser.create(copilotSQL, SqlParser.Config.DEFAULT.withLex(getLex(type))); + SqlNode sqlNode = parser.parseStmt(); + return sqlNode.toSqlString(dialect).toString().toLowerCase(); + } catch (Exception e) { + logger.debug("calcite trans copilot SQL error"); + return receiveDTO.getSql(); + } + } else { + return copilotSQL; + } + } + + private String engine(String type) { + switch (type) { + case "ck": + return "ClickHouse"; + case "pg": + return "PostgreSQL"; + case "mysql": + return "MySQL"; + case "sqlServer": + return "SQL Server"; + default: + return type; + } + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/manage/MsgManage.java b/core/core-backend/src/main/java/io/gisbi/copilot/manage/MsgManage.java new file mode 100644 index 0000000..91c362f --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/manage/MsgManage.java @@ -0,0 +1,100 @@ +package io.gisbi.copilot.manage; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.gisbi.api.copilot.dto.ChartDTO; +import io.gisbi.api.copilot.dto.HistoryDTO; +import io.gisbi.api.copilot.dto.MsgDTO; +import io.gisbi.copilot.dao.auto.entity.CoreCopilotMsg; +import io.gisbi.copilot.dao.auto.mapper.CoreCopilotMsgMapper; +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.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @Author bi-coder + */ +@Component +public class MsgManage { + @Resource + private CoreCopilotMsgMapper coreCopilotMsgMapper; + + private ObjectMapper objectMapper = new ObjectMapper(); + + public void save(MsgDTO msgDTO) throws Exception { + msgDTO.setId(IDUtils.snowID()); + msgDTO.setCreateTime(System.currentTimeMillis()); + msgDTO.setUserId(AuthUtils.getUser().getUserId()); + coreCopilotMsgMapper.insert(transDTO(msgDTO)); + } + + public List getMsg(MsgDTO msgDTO) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", msgDTO.getUserId()); + wrapper.eq("dataset_group_id", msgDTO.getDatasetGroupId()); + wrapper.orderByAsc("create_time"); + List perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper); + return perCopilotMsgs.stream().map(this::transRecord).toList(); + } + + public void deleteMsg(MsgDTO msgDTO) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", msgDTO.getUserId()); + wrapper.ne("dataset_group_id", msgDTO.getDatasetGroupId()); + coreCopilotMsgMapper.delete(wrapper); + } + + public void clearAllUserMsg(Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + coreCopilotMsgMapper.delete(wrapper); + } + + public MsgDTO getLastMsg(Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + wrapper.orderByDesc("create_time"); + List perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper); + return ObjectUtils.isEmpty(perCopilotMsgs) ? null : transRecord(perCopilotMsgs.getFirst()); + } + + public MsgDTO getLastSuccessMsg(Long userId, Long datasetGroupId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + wrapper.eq("dataset_group_id", datasetGroupId); + wrapper.eq("msg_status", 1); + wrapper.eq("msg_type", "api"); + wrapper.orderByDesc("create_time"); + List perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper); + return ObjectUtils.isEmpty(perCopilotMsgs) ? null : transRecord(perCopilotMsgs.getFirst()); + } + + private CoreCopilotMsg transDTO(MsgDTO dto) throws Exception { + CoreCopilotMsg record = new CoreCopilotMsg(); + BeanUtils.copyBean(record, dto); + record.setHistory(dto.getHistory() == null ? null : objectMapper.writeValueAsString(dto.getHistory())); + record.setChart(dto.getChart() == null ? null : objectMapper.writeValueAsString(dto.getChart())); + record.setChartData(dto.getChartData() == null ? null : objectMapper.writeValueAsString(dto.getChartData())); + return record; + } + + private MsgDTO transRecord(CoreCopilotMsg record) { + MsgDTO dto = new MsgDTO(); + BeanUtils.copyBean(dto, record); + TypeReference> tokenType = new TypeReference<>() { + }; + dto.setHistory(record.getHistory() == null ? new ArrayList<>() : JsonUtil.parseList(record.getHistory(), tokenType)); + dto.setChart(record.getChart() == null ? null : JsonUtil.parseObject(record.getChart(), ChartDTO.class)); + dto.setChartData(record.getChartData() == null ? null : JsonUtil.parse(record.getChartData(), Map.class)); + return dto; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/manage/TokenManage.java b/core/core-backend/src/main/java/io/gisbi/copilot/manage/TokenManage.java new file mode 100644 index 0000000..8af4c41 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/manage/TokenManage.java @@ -0,0 +1,36 @@ +package io.gisbi.copilot.manage; + +import io.gisbi.api.copilot.dto.TokenDTO; +import io.gisbi.copilot.dao.auto.entity.CoreCopilotToken; +import io.gisbi.copilot.dao.auto.mapper.CoreCopilotTokenMapper; +import io.gisbi.utils.BeanUtils; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * @Author bi-coder + */ +@Component +public class TokenManage { + @Resource + private CoreCopilotTokenMapper coreCopilotTokenMapper; + + public TokenDTO getToken(boolean valid) { + CoreCopilotToken perCopilotToken = coreCopilotTokenMapper.selectById(valid ? 2 : 1); + return transRecord(perCopilotToken); + } + + public void updateToken(String token, boolean valid) { + CoreCopilotToken record = new CoreCopilotToken(); + record.setId(valid ? 2L : 1L); + record.setToken(token); + record.setUpdateTime(System.currentTimeMillis()); + coreCopilotTokenMapper.updateById(record); + } + + private TokenDTO transRecord(CoreCopilotToken perCopilotToken) { + TokenDTO dto = new TokenDTO(); + BeanUtils.copyBean(dto, perCopilotToken); + return dto; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/copilot/service/CopilotService.java b/core/core-backend/src/main/java/io/gisbi/copilot/service/CopilotService.java new file mode 100644 index 0000000..1f24866 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/copilot/service/CopilotService.java @@ -0,0 +1,40 @@ +package io.gisbi.copilot.service; + +import io.gisbi.api.copilot.CopilotApi; +import io.gisbi.api.copilot.dto.MsgDTO; +import io.gisbi.copilot.manage.CopilotManage; +import io.gisbi.utils.AuthUtils; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @Author bi-coder + */ +@RestController +@RequestMapping("copilot") +public class CopilotService implements CopilotApi { + @Resource + private CopilotManage copilotManage; + + @Override + public MsgDTO chat(MsgDTO msgDTO) throws Exception { + try { + return copilotManage.chat(msgDTO); + } catch (Exception e) { + return copilotManage.errorMsg(msgDTO, e.getMessage()); + } + } + + @Override + public List getList() throws Exception { + return copilotManage.getList(AuthUtils.getUser().getUserId()); + } + + @Override + public void clearAll() throws Exception { + copilotManage.clearAll(AuthUtils.getUser().getUserId()); + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/InteractiveAuthFeignService.java b/core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/InteractiveAuthFeignService.java new file mode 100644 index 0000000..6e489c7 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/InteractiveAuthFeignService.java @@ -0,0 +1,8 @@ +package io.gisbi.defeign.permissions.auth; + +import io.gisbi.api.permissions.auth.api.InteractiveAuthApi; +import io.gisbi.feign.DeFeign; + +@DeFeign(value = "xpack-permissions", path = "/interactive") +public interface InteractiveAuthFeignService extends InteractiveAuthApi { +} diff --git a/core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/PermissionFeignService.java b/core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/PermissionFeignService.java new file mode 100644 index 0000000..b6dbf20 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/defeign/permissions/auth/PermissionFeignService.java @@ -0,0 +1,10 @@ +package io.gisbi.defeign.permissions.auth; + +import io.gisbi.feign.DeFeign; +import io.gisbi.api.permissions.auth.api.AuthApi; + + +@DeFeign(value = "xpack-permissions", path = "/auth") +public interface PermissionFeignService extends AuthApi { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/defeign/permissions/user/UserFeignService.java b/core/core-backend/src/main/java/io/gisbi/defeign/permissions/user/UserFeignService.java new file mode 100644 index 0000000..0b28a88 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/defeign/permissions/user/UserFeignService.java @@ -0,0 +1,8 @@ +package io.gisbi.defeign.permissions.user; + +import io.gisbi.api.permissions.user.api.UserApi; +import io.gisbi.feign.DeFeign; + +@DeFeign(value = "xpack-permissions", path = "/user") +public interface UserFeignService extends UserApi { +} diff --git a/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/entity/CoreExportDownloadTask.java b/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/entity/CoreExportDownloadTask.java new file mode 100644 index 0000000..ccf1e44 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/entity/CoreExportDownloadTask.java @@ -0,0 +1,57 @@ +package io.gisbi.exportCenter.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * 下载任务列表 + *

+ * + * @Author bi-coder + * @since 2025-06-16 + */ +@TableName("core_export_download_task") +public class CoreExportDownloadTask implements Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + + private Long createTime; + + private Long validTime; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public Long getValidTime() { + return validTime; + } + + public void setValidTime(Long validTime) { + this.validTime = validTime; + } + + @Override + public String toString() { + return "CoreExportDownloadTask{" + + "id = " + id + + ", createTime = " + createTime + + ", validTime = " + validTime + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/mapper/CoreExportDownloadTaskMapper.java b/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/mapper/CoreExportDownloadTaskMapper.java new file mode 100644 index 0000000..c7ed78f --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/auto/mapper/CoreExportDownloadTaskMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.exportCenter.dao.auto.mapper; + +import io.gisbi.exportCenter.dao.auto.entity.CoreExportDownloadTask; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 下载任务列表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-06-16 + */ +@Mapper +public interface CoreExportDownloadTaskMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/ext/mapper/ExportTaskExtMapper.java b/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/ext/mapper/ExportTaskExtMapper.java new file mode 100644 index 0000000..9baf246 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/exportCenter/dao/ext/mapper/ExportTaskExtMapper.java @@ -0,0 +1,43 @@ +package io.gisbi.exportCenter.dao.ext.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import io.gisbi.exportCenter.dao.auto.entity.CoreExportTask; +import io.gisbi.model.ExportTaskDTO; +import org.apache.ibatis.annotations.*; + + +@Mapper +public interface ExportTaskExtMapper extends BaseMapper { + + @Select( + """ + select * + from core_export_task + ${ew.customSqlSegment} + """ + ) + @Results( + id = "exportTasksMap", + value = { + @Result(property = "id", column = "id"), + @Result(property = "user_id", column = "userId"), + @Result(property = "file_name", column = "fileName"), + @Result(property = "file_size", column = "fileSize"), + @Result(property = "file_size_unit", column = "fileSizeUnit"), + @Result(property = "export_from", column = "exportFrom"), + @Result(property = "export_status", column = "exportStatus"), + @Result(property = "msg", column = "msg"), + @Result(property = "export_from_type", column = "exportFromType"), + @Result(property = "export_progress", column = "exportProgress"), + @Result(property = "export_machine_name", column = "exportMachineName"), + @Result(property = "export_from_name", column = "exportFromName"), + @Result(property = "org_name", column = "orgName"), + @Result(property = "export_time", column = "exportTime") + } + ) + IPage pager(IPage page, @Param("ew") QueryWrapper queryWrapper); + + +} diff --git a/core/core-backend/src/main/java/io/gisbi/exportCenter/manage/ExportCenterDownLoadManage.java b/core/core-backend/src/main/java/io/gisbi/exportCenter/manage/ExportCenterDownLoadManage.java new file mode 100644 index 0000000..271d761 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/exportCenter/manage/ExportCenterDownLoadManage.java @@ -0,0 +1,826 @@ +package io.gisbi.exportCenter.manage; + + +import com.fasterxml.jackson.core.type.TypeReference; +import io.gisbi.api.chart.dto.ViewDetailField; +import io.gisbi.api.chart.request.ChartExcelRequest; +import io.gisbi.api.chart.request.ChartExcelRequestInner; +import io.gisbi.api.dataset.dto.DataSetExportRequest; +import io.gisbi.api.dataset.union.DatasetGroupInfoDTO; +import io.gisbi.api.dataset.union.UnionDTO; +import io.gisbi.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO; +import io.gisbi.api.permissions.user.vo.UserFormVO; +import io.gisbi.api.xpack.dataFilling.DataFillingApi; +import io.gisbi.api.xpack.dataFilling.dto.DataFillFormTableDataRequest; +import io.gisbi.auth.bo.TokenUserBO; +import io.gisbi.chart.dao.auto.mapper.CoreChartViewMapper; +import io.gisbi.chart.server.ChartDataServer; +import io.gisbi.commons.utils.ExcelWatermarkUtils; +import io.gisbi.constant.DeTypeConstants; +import io.gisbi.constant.LogOT; +import io.gisbi.constant.LogST; +import io.gisbi.dataset.dao.auto.entity.CoreDatasetGroup; +import io.gisbi.dataset.dao.auto.mapper.CoreDatasetGroupMapper; +import io.gisbi.dataset.manage.*; +import io.gisbi.datasource.utils.DatasourceUtils; +import io.gisbi.engine.sql.SQLProvider; +import io.gisbi.engine.trans.Field2SQLObj; +import io.gisbi.engine.trans.Order2SQLObj; +import io.gisbi.engine.trans.Table2SQLObj; +import io.gisbi.engine.trans.WhereTree2Str; +import io.gisbi.engine.utils.Utils; +import io.gisbi.exception.DEException; +import io.gisbi.exportCenter.dao.auto.entity.CoreExportTask; +import io.gisbi.exportCenter.dao.auto.mapper.CoreExportTaskMapper; +import io.gisbi.exportCenter.util.ExportCenterUtils; +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.ChartViewDTO; +import io.gisbi.extensions.view.dto.ChartViewFieldDTO; +import io.gisbi.extensions.view.dto.ColumnPermissionItem; +import io.gisbi.extensions.view.dto.DatasetRowPermissionsTreeObj; +import io.gisbi.i18n.Translator; +import io.gisbi.log.DeLog; +import io.gisbi.model.ExportTaskDTO; +import io.gisbi.utils.*; +import io.gisbi.visualization.dao.auto.entity.VisualizationWatermark; +import io.gisbi.visualization.dao.auto.mapper.VisualizationWatermarkMapper; +import io.gisbi.visualization.dao.ext.mapper.ExtDataVisualizationMapper; +import io.gisbi.visualization.dto.WatermarkContentDTO; +import io.gisbi.websocket.WsMessage; +import io.gisbi.websocket.WsService; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.io.*; +import java.net.URLEncoder; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.StandardCharsets; +import java.text.DecimalFormat; +import java.util.*; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +@Component +@Transactional(rollbackFor = Exception.class) +public class ExportCenterDownLoadManage { + @Resource + private CoreExportTaskMapper exportTaskMapper; + @Resource + private CoreChartViewMapper coreChartViewMapper; + @Resource + private PermissionManage permissionManage; + @Autowired + private WsService wsService; + @Autowired(required = false) + private PluginManageApi pluginManage; + @Value("${gisbi.export.core.size:10}") + private int core; + @Value("${gisbi.export.max.size:10}") + private int max; + + @Value("${gisbi.path.exportData:/opt/gisbi2.0/data/exportData/}") + private String exportData_path; + @Resource + private VisualizationWatermarkMapper watermarkMapper; + @Resource + private ExtDataVisualizationMapper visualizationMapper; + @Value("${gisbi.export.page.size:50000}") + private Integer extractPageSize; + static private List STATUS = Arrays.asList("SUCCESS", "FAILED", "PENDING", "IN_PROGRESS", "ALL"); + private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor; + private int keepAliveSeconds = 600; + private Map Running_Task = new HashMap<>(); + @Resource + private ChartDataServer chartDataServer; + @Resource + private CoreDatasetGroupMapper coreDatasetGroupMapper; + @Resource + private DatasetSQLManage datasetSQLManage; + @Resource + private DatasetTableFieldManage datasetTableFieldManage; + @Resource + private DatasetDataManage datasetDataManage; + private final Long sheetLimit = 1000000L; + @Autowired(required = false) + private DataFillingApi dataFillingApi = null; + + private DataFillingApi getDataFillingApi() { + return dataFillingApi; + } + + @PostConstruct + public void init() { + scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core); + scheduledThreadPoolExecutor.setKeepAliveTime(keepAliveSeconds, TimeUnit.SECONDS); + scheduledThreadPoolExecutor.setMaximumPoolSize(max); + } + + @Scheduled(fixedRate = 5000) + public void checkRunningTask() { + Iterator> iterator = Running_Task.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + if (entry.getValue().isDone()) { + iterator.remove(); + try { + CoreExportTask exportTask = exportTaskMapper.selectById(entry.getKey()); + ExportTaskDTO exportTaskDTO = new ExportTaskDTO(); + BeanUtils.copyBean(exportTaskDTO, exportTask); + setExportFromName(exportTaskDTO); + WsMessage message = new WsMessage(exportTask.getUserId(), "/task-export-topic", exportTaskDTO); + wsService.releaseMessage(message); + } catch (Exception e) { + } + } + } + } + + private void setExportFromName(ExportTaskDTO exportTaskDTO) { + if (exportTaskDTO.getExportFromType().equalsIgnoreCase("chart")) { + exportTaskDTO.setExportFromName(coreChartViewMapper.selectById(exportTaskDTO.getExportFrom()).getTitle()); + } + if (exportTaskDTO.getExportFromType().equalsIgnoreCase("dataset")) { + exportTaskDTO.setExportFromName(coreDatasetGroupMapper.selectById(exportTaskDTO.getExportFrom()).getName()); + } + if (exportTaskDTO.getExportFromType().equalsIgnoreCase("data_filling")) { + exportTaskDTO.setExportFromName(getDataFillingApi().get(exportTaskDTO.getExportFrom()).getName()); + } + } + + @DeLog(id = "#p0.exportFrom", ot = LogOT.EXPORT, st = LogST.DATA_FILLING) + public void startDataFillingTask(CoreExportTask exportTask, HashMap request) { + if (ObjectUtils.isEmpty(getDataFillingApi())) { + return; + } + String dataPath = exportData_path + exportTask.getId(); + File directory = new File(dataPath); + boolean isCreated = directory.mkdir(); + TokenUserBO tokenUserBO = AuthUtils.getUser(); + Future future = scheduledThreadPoolExecutor.submit(() -> { + AuthUtils.setUser(tokenUserBO); + try { + exportTask.setExportStatus("IN_PROGRESS"); + exportTaskMapper.updateById(exportTask); + getDataFillingApi().writeExcel(dataPath + "/" + exportTask.getId() + ".xlsx", new DataFillFormTableDataRequest().setId(exportTask.getExportFrom()).setWithoutLogs(true), exportTask.getUserId(), Long.parseLong(request.get("org").toString())); + exportTask.setExportProgress("100"); + exportTask.setExportStatus("SUCCESS"); + + setFileSize(dataPath + "/" + exportTask.getId() + ".xlsx", exportTask); + } catch (Exception e) { + exportTask.setMsg(e.getMessage()); + LogUtil.error("Failed to export data", e); + exportTask.setExportStatus("FAILED"); + } finally { + exportTaskMapper.updateById(exportTask); + } + }); + Running_Task.put(exportTask.getId(), future); + } + + @DeLog(id = "#p0.exportFrom", ot = LogOT.EXPORT, st = LogST.DATASET) + public void startDatasetTask(CoreExportTask exportTask, DataSetExportRequest request) { + String dataPath = exportData_path + exportTask.getId(); + File directory = new File(dataPath); + boolean isCreated = directory.mkdir(); + + TokenUserBO tokenUserBO = AuthUtils.getUser(); + Future future = scheduledThreadPoolExecutor.submit(() -> { + AuthUtils.setUser(tokenUserBO); + try { + exportTask.setExportStatus("IN_PROGRESS"); + exportTaskMapper.updateById(exportTask); + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(exportTask.getExportFrom()); + if (coreDatasetGroup == null) { + throw new Exception("Not found dataset group: " + exportTask.getExportFrom()); + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(Long.valueOf(exportTask.getExportFrom())); + List allFields = dsFields.stream().map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + Map sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null); + String sql = (String) sqlMap.get("sql"); + if (ObjectUtils.isEmpty(allFields)) { + DEException.throwException(Translator.get("i18n_no_fields")); + } + Map desensitizationList = new HashMap<>(); + allFields = permissionManage.filterColumnPermissions(allFields, desensitizationList, dto.getId(), null); + if (ObjectUtils.isEmpty(allFields)) { + DEException.throwException(Translator.get("i18n_no_column_permission")); + } + dto.setAllFields(allFields); + datasetDataManage.buildFieldName(sqlMap, allFields); + Map dsMap = (Map) sqlMap.get("dsMap"); + DatasourceUtils.checkDsStatus(dsMap); + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + boolean needOrder = Utils.isNeedOrder(dsList); + boolean crossDs = dto.getIsCross(); + if (!crossDs) { + if (datasetDataManage.notFullDs.contains(dsMap.entrySet().iterator().next().getValue().getType()) && (boolean) sqlMap.get("isFullJoin")) { + DEException.throwException(Translator.get("i18n_not_full")); + } + sql = Utils.replaceSchemaAlias(sql, dsMap); + } + List rowPermissionsTree = new ArrayList<>(); + TokenUserBO user = AuthUtils.getUser(); + if (user != null) { + rowPermissionsTree = permissionManage.getRowPermissionsTree(dto.getId(), user.getUserId()); + } + if (StringUtils.isNotEmpty(request.getExpressionTree())) { + DatasetRowPermissionsTreeObj datasetRowPermissionsTreeObj = JsonUtil.parseObject(request.getExpressionTree(), DatasetRowPermissionsTreeObj.class); + permissionManage.getField(datasetRowPermissionsTreeObj); + DataSetRowPermissionsTreeDTO dataSetRowPermissionsTreeDTO = new DataSetRowPermissionsTreeDTO(); + dataSetRowPermissionsTreeDTO.setTree(datasetRowPermissionsTreeObj); + dataSetRowPermissionsTreeDTO.setExportData(true); + rowPermissionsTree.add(dataSetRowPermissionsTreeDTO); + } + + Provider provider; + if (crossDs) { + provider = ProviderFactory.getDefaultProvider(); + } else { + provider = ProviderFactory.getProvider(dsList.getFirst()); + } + SQLMeta sqlMeta = new SQLMeta(); + Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); + Field2SQLObj.field2sqlObj(sqlMeta, allFields, allFields, crossDs, dsMap, Utils.getParams(allFields), null, pluginManage); + WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, allFields, crossDs, dsMap, Utils.getParams(allFields), null, pluginManage); + Order2SQLObj.getOrders(sqlMeta, dto.getSortFields(), allFields, crossDs, dsMap, Utils.getParams(allFields), null, pluginManage); + String replaceSql = provider.rebuildSQL(SQLProvider.createQuerySQL(sqlMeta, false, false, false), sqlMeta, crossDs, dsMap); + Long totalCount = datasetDataManage.getDatasetTotal(dto, replaceSql, null); + Long curLimit = ExportCenterUtils.getExportLimit("dataset"); + totalCount = totalCount > curLimit ? curLimit : totalCount; + + Long sheetCount = (totalCount / sheetLimit) + (totalCount % sheetLimit > 0 ? 1 : 0); + Workbook wb = new SXSSFWorkbook(); + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + font.setFontHeightInPoints((short) 12); + font.setBold(true); + cellStyle.setFont(font); + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + for (Long s = 1L; s < sheetCount + 1; s++) { + Long sheetSize; + if (s.equals(sheetCount)) { + sheetSize = totalCount - (s - 1) * sheetLimit; + } else { + sheetSize = sheetLimit; + } + Long pageSize = (sheetSize / extractPageSize) + (sheetSize % extractPageSize > 0 ? 1 : 0); + Sheet detailsSheet = null; + List> details = new ArrayList<>(); + for (Long p = 0L; p < pageSize; p++) { + int beforeCount = (int) ((s - 1) * sheetLimit); + String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, beforeCount + p.intValue() * extractPageSize, extractPageSize); + if (pageSize == 1) { + querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, 0, sheetSize.intValue()); + } + querySQL = provider.rebuildSQL(querySQL, sqlMeta, crossDs, dsMap); + DatasourceRequest datasourceRequest = new DatasourceRequest(); + datasourceRequest.setQuery(querySQL); + datasourceRequest.setDsList(dsMap); + datasourceRequest.setIsCross(coreDatasetGroup.getIsCross()); + Map previewData = datasetDataManage.buildPreviewData(provider.fetchResultField(datasourceRequest), allFields, desensitizationList, false); + List> data = (List>) previewData.get("data"); + if (p.equals(0L)) { + detailsSheet = wb.createSheet("数据" + s); + List header = new ArrayList<>(); + for (DatasetTableFieldDTO field : allFields) { + header.add(field.getName()); + } + details.add(header); + for (Map obj : data) { + List row = new ArrayList<>(); + for (DatasetTableFieldDTO field : allFields) { + String string = (String) obj.get(field.getGisbiName()); + row.add(string); + } + details.add(row); + } + if (CollectionUtils.isNotEmpty(details)) { + for (int i = 0; i < details.size(); i++) { + Row row = detailsSheet.createRow(i); + List rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.size(); j++) { + Cell cell = row.createCell(j); + if (i == 0) { + cell.setCellValue(rowData.get(j)); + cell.setCellStyle(cellStyle); + detailsSheet.setColumnWidth(j, 255 * 20); + } else { + if ((allFields.get(j).getDeType().equals(DeTypeConstants.DE_INT) || allFields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) { + try { + cell.setCellValue(Double.valueOf(rowData.get(j))); + } catch (Exception e) { + cell.setCellValue(rowData.get(j)); + } + } else { + cell.setCellValue(rowData.get(j)); + } + } + } + } + } + } + } else { + details.clear(); + for (Map obj : data) { + List row = new ArrayList<>(); + for (DatasetTableFieldDTO field : allFields) { + String string = (String) obj.get(field.getGisbiName()); + row.add(string); + } + details.add(row); + } + int lastNum = detailsSheet.getLastRowNum(); + for (int i = 0; i < details.size(); i++) { + Row row = detailsSheet.createRow(i + lastNum + 1); + List rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.size(); j++) { + Cell cell = row.createCell(j); + if (i == 0) { + cell.setCellValue(rowData.get(j)); + cell.setCellStyle(cellStyle); + detailsSheet.setColumnWidth(j, 255 * 20); + } else { + if ((allFields.get(j).getDeType().equals(DeTypeConstants.DE_INT) || allFields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) { + try { + cell.setCellValue(Double.valueOf(rowData.get(j))); + } catch (Exception e) { + cell.setCellValue(rowData.get(j)); + } + } else { + cell.setCellValue(rowData.get(j)); + } + } + + } + } + } + } + exportTask.setExportStatus("IN_PROGRESS"); + double exportRogress2 = (double) ((double) s - 1) / ((double) sheetCount); + double exportRogress = (double) ((double) (p + 1) / (double) pageSize) * ((double) 1 / sheetCount); + DecimalFormat df = new DecimalFormat("#.##"); + String formattedResult = df.format((exportRogress + exportRogress2) * 100); + exportTask.setExportProgress(formattedResult); + exportTaskMapper.updateById(exportTask); + } + } + this.addWatermarkTools(wb); + FileOutputStream fileOutputStream = new FileOutputStream(dataPath + "/" + exportTask.getId() + ".xlsx"); + wb.write(fileOutputStream); + fileOutputStream.flush(); + fileOutputStream.close(); + wb.close(); + exportTask.setExportProgress("100"); + exportTask.setExportStatus("SUCCESS"); + setFileSize(dataPath + "/" + exportTask.getId() + ".xlsx", exportTask); + + } catch (Exception e) { + LogUtil.error("Failed to export data", e); + exportTask.setMsg(e.getMessage()); + exportTask.setExportStatus("FAILED"); + } finally { + exportTaskMapper.updateById(exportTask); + } + }); + Running_Task.put(exportTask.getId(), future); + } + + @DeLog(id = "#p0.exportFrom", ot = LogOT.EXPORT, st = LogST.PANEL) + public void startPanelViewTask(CoreExportTask exportTask, ChartExcelRequest request) { + startViewTask(exportTask, request); + } + + @DeLog(id = "#p0.exportFrom", ot = LogOT.EXPORT, st = LogST.SCREEN) + public void startDataVViewTask(CoreExportTask exportTask, ChartExcelRequest request) { + startViewTask(exportTask, request); + } + + + public void startViewTask(CoreExportTask exportTask, ChartExcelRequest request) { + String dataPath = exportData_path + exportTask.getId(); + File directory = new File(dataPath); + boolean isCreated = directory.mkdir(); + TokenUserBO tokenUserBO = AuthUtils.getUser(); + Future future = scheduledThreadPoolExecutor.submit(() -> { + AuthUtils.setUser(tokenUserBO); + try { + exportTask.setExportStatus("IN_PROGRESS"); + exportTaskMapper.updateById(exportTask); + Workbook wb = new SXSSFWorkbook(); + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + font.setFontHeightInPoints((short) 12); + font.setBold(true); + cellStyle.setFont(font); + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + List details = new ArrayList<>(); + Sheet detailsSheet; + Integer sheetIndex = 1; + if ("dataset".equals(request.getDownloadType()) || request.getViewInfo().getType().equalsIgnoreCase("table-info") || request.getViewInfo().getType().equalsIgnoreCase("table-normal")) { + request.getViewInfo().getChartExtRequest().setPageSize(Long.valueOf(extractPageSize)); + ChartViewDTO chartViewDTO = chartDataServer.findExcelData(request); + for (long i = 1; i < chartViewDTO.getTotalPage() + 1; i++) { + request.getViewInfo().getChartExtRequest().setGoPage(i); + chartDataServer.findExcelData(request); + details.addAll(request.getDetails()); + if (((details.size() + extractPageSize) > sheetLimit) || i == chartViewDTO.getTotalPage()) { + detailsSheet = wb.createSheet("数据" + sheetIndex); + Integer[] excelTypes = request.getExcelTypes(); + ViewDetailField[] detailFields = request.getDetailFields(); + Object[] header = request.getHeader(); + request.getViewInfo().setXAxis(request.getViewInfo().getXAxis().stream().filter(ele -> !ele.isHide()).collect(Collectors.toList())); + request.getViewInfo().setYAxis(request.getViewInfo().getYAxis().stream().filter(ele -> !ele.isHide()).collect(Collectors.toList())); + request.getViewInfo().setXAxisExt(request.getViewInfo().getXAxisExt().stream().filter(ele -> !ele.isHide()).collect(Collectors.toList())); + request.getViewInfo().setYAxisExt(request.getViewInfo().getYAxisExt().stream().filter(ele -> !ele.isHide()).collect(Collectors.toList())); + request.getViewInfo().setExtStack(request.getViewInfo().getExtStack().stream().filter(ele -> !ele.isHide()).collect(Collectors.toList())); + List xAxis = new ArrayList<>(); + xAxis.addAll(request.getViewInfo().getXAxis()); + xAxis.addAll(request.getViewInfo().getYAxis()); + xAxis.addAll(request.getViewInfo().getXAxisExt()); + xAxis.addAll(request.getViewInfo().getYAxisExt()); + xAxis.addAll(request.getViewInfo().getExtStack()); + xAxis.addAll(request.getViewInfo().getDrillFields()); + header = Arrays.stream(request.getHeader()).filter(item -> xAxis.stream().map(d -> StringUtils.isNotBlank(d.getChartShowName()) ? d.getChartShowName() : d.getName()).toList().contains(item)).toArray(); + details.add(0, header); + ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes, request.getViewInfo(), wb); + sheetIndex++; + details.clear(); + exportTask.setExportStatus("IN_PROGRESS"); + double exportProgress = (double) (i / (chartViewDTO.getTotalPage() + 1)); + DecimalFormat df = new DecimalFormat("#.##"); + String formattedResult = df.format((exportProgress) * 100); + exportTask.setExportProgress(formattedResult); + exportTaskMapper.updateById(exportTask); + } + } + } else { + downloadNotTableInfoData(request, wb); + } + this.addWatermarkTools(wb); + + try (FileOutputStream outputStream = new FileOutputStream(dataPath + "/" + exportTask.getId() + ".xlsx")) { + wb.write(outputStream); + outputStream.flush(); + } + wb.close(); + exportTask.setExportProgress("100"); + exportTask.setExportStatus("SUCCESS"); + setFileSize(dataPath + "/" + exportTask.getId() + ".xlsx", exportTask); + } catch (Exception e) { + exportTask.setMsg(e.getMessage()); + LogUtil.error("Failed to export data", e); + exportTask.setExportStatus("FAILED"); + } finally { + exportTaskMapper.updateById(exportTask); + } + }); + Running_Task.put(exportTask.getId(), future); + } + + private void downloadNotTableInfoData(ChartExcelRequest request, Workbook wb) { + chartDataServer.findExcelData(request); + //给单元格设置样式 + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + //设置字体大小 + font.setFontHeightInPoints((short) 12); + //设置字体加粗 + font.setBold(true); + //给字体设置样式 + cellStyle.setFont(font); + //设置单元格背景颜色 + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + //设置单元格填充样式(使用纯色背景颜色填充) + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + if (CollectionUtils.isEmpty(request.getMultiInfo())) { + if (request.getViewInfo().getType().equalsIgnoreCase("chart-mix-dual-line")) { + } else { + List details = request.getDetails(); + Integer[] excelTypes = request.getExcelTypes(); + details.add(0, request.getHeader()); + ViewDetailField[] detailFields = request.getDetailFields(); + Object[] header = request.getHeader(); + Sheet detailsSheet = wb.createSheet("数据"); + if (request.getViewInfo().getType().equalsIgnoreCase("table-normal")) { + ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes, request.getViewInfo(), wb); + } else { + ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes, request.getViewInfo(), null); + } + } + } else { + //多个sheet + for (int i = 0; i < request.getMultiInfo().size(); i++) { + ChartExcelRequestInner requestInner = request.getMultiInfo().get(i); + + List details = requestInner.getDetails(); + Integer[] excelTypes = requestInner.getExcelTypes(); + details.add(0, requestInner.getHeader()); + ViewDetailField[] detailFields = requestInner.getDetailFields(); + Object[] header = requestInner.getHeader(); + //明细sheet + Sheet detailsSheet = wb.createSheet("数据 " + (i + 1)); + ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes, request.getViewInfo(), null); + } + } + } + + private void setFileSize(String filePath, CoreExportTask exportTask) { + File file = new File(filePath); + long length = file.length(); + String unit = "Mb"; + Double size = 0.0; + if ((double) length / 1024 / 1024 > 1) { + if ((double) length / 1024 / 1024 / 1024 > 1) { + unit = "Gb"; + size = Double.valueOf(String.format("%.2f", (double) length / 1024 / 1024 / 1024)); + } else { + size = Double.valueOf(String.format("%.2f", (double) length / 1024 / 1024)); + } + + } else { + unit = "Kb"; + size = Double.valueOf(String.format("%.2f", (double) length / 1024)); + } + exportTask.setFileSize(size); + exportTask.setFileSizeUnit(unit); + } + + public void addWatermarkTools(Workbook wb) { + VisualizationWatermark watermark = watermarkMapper.selectById("system_default"); + WatermarkContentDTO watermarkContent = JsonUtil.parseObject(watermark.getSettingContent(), WatermarkContentDTO.class); + if (watermarkContent.getEnable() && watermarkContent.getExcelEnable()) { + UserFormVO userInfo = visualizationMapper.queryInnerUserInfo(AuthUtils.getUser().getUserId()); + // 在主逻辑中添加水印 + int watermarkPictureIdx = ExcelWatermarkUtils.addWatermarkImage(wb, watermarkContent, userInfo); // 生成水印图片并获取 ID + for (Sheet sheet : wb) { + ExcelWatermarkUtils.addWatermarkToSheet(sheet, watermarkPictureIdx); // 为每个 Sheet 添加水印 + } + } + } + + public void download(CoreExportTask exportTask, HttpServletResponse response) throws Exception { + response.setContentType("application/octet-stream"); + String encodedFileName = URLEncoder.encode(exportTask.getFileName(), StandardCharsets.UTF_8); + response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=utf-8''" + encodedFileName); + String filePath; + + if (exportTask.getExportTime() < 1730277243491L) { + filePath = exportData_path + exportTask.getId() + "/" + exportTask.getFileName(); + } else { + filePath = exportData_path + exportTask.getId() + "/" + exportTask.getId() + ".xlsx"; + } + + try (FileInputStream fileInputStream = new FileInputStream(filePath); OutputStream outputStream = response.getOutputStream()) { + FileChannel fileChannel = fileInputStream.getChannel(); + WritableByteChannel outputChannel = Channels.newChannel(outputStream); + fileChannel.transferTo(0, fileChannel.size(), outputChannel); + response.flushBuffer(); + } catch (IOException e) { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + + public void downloadDataset(DataSetExportRequest request, HttpServletResponse response) throws Exception { + OutputStream outputStream = response.getOutputStream(); + try { + CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(request.getId()); + if (coreDatasetGroup == null) { + throw new Exception("Not found dataset group: " + request.getFilename()); + } + DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO(); + BeanUtils.copyBean(dto, coreDatasetGroup); + dto.setUnionSql(null); + List unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() { + }); + dto.setUnion(unionDTOList); + List dsFields = datasetTableFieldManage.selectByDatasetGroupId(request.getId()); + List allFields = dsFields.stream().map(ele -> { + DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); + BeanUtils.copyBean(datasetTableFieldDTO, ele); + datasetTableFieldDTO.setFieldShortName(ele.getGisbiName()); + return datasetTableFieldDTO; + }).collect(Collectors.toList()); + + Map sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null); + String sql = (String) sqlMap.get("sql"); + if (ObjectUtils.isEmpty(allFields)) { + DEException.throwException(Translator.get("i18n_no_fields")); + } + Map desensitizationList = new HashMap<>(); + allFields = permissionManage.filterColumnPermissions(allFields, desensitizationList, dto.getId(), null); + if (ObjectUtils.isEmpty(allFields)) { + DEException.throwException(Translator.get("i18n_no_column_permission")); + } + dto.setAllFields(allFields); + datasetDataManage.buildFieldName(sqlMap, allFields); + Map dsMap = (Map) sqlMap.get("dsMap"); + DatasourceUtils.checkDsStatus(dsMap); + List dsList = new ArrayList<>(); + for (Map.Entry next : dsMap.entrySet()) { + dsList.add(next.getValue().getType()); + } + boolean needOrder = Utils.isNeedOrder(dsList); + boolean crossDs = dto.getIsCross(); + if (!crossDs) { + if (datasetDataManage.notFullDs.contains(dsMap.entrySet().iterator().next().getValue().getType()) && (boolean) sqlMap.get("isFullJoin")) { + DEException.throwException(Translator.get("i18n_not_full")); + } + sql = Utils.replaceSchemaAlias(sql, dsMap); + } + List rowPermissionsTree = new ArrayList<>(); + TokenUserBO user = AuthUtils.getUser(); + if (user != null) { + rowPermissionsTree = permissionManage.getRowPermissionsTree(dto.getId(), user.getUserId()); + } + if (StringUtils.isNotEmpty(request.getExpressionTree())) { + DatasetRowPermissionsTreeObj datasetRowPermissionsTreeObj = JsonUtil.parseObject(request.getExpressionTree(), DatasetRowPermissionsTreeObj.class); + permissionManage.getField(datasetRowPermissionsTreeObj); + DataSetRowPermissionsTreeDTO dataSetRowPermissionsTreeDTO = new DataSetRowPermissionsTreeDTO(); + dataSetRowPermissionsTreeDTO.setTree(datasetRowPermissionsTreeObj); + dataSetRowPermissionsTreeDTO.setExportData(true); + rowPermissionsTree.add(dataSetRowPermissionsTreeDTO); + } + + Provider provider; + if (crossDs) { + provider = ProviderFactory.getDefaultProvider(); + } else { + provider = ProviderFactory.getProvider(dsList.getFirst()); + } + SQLMeta sqlMeta = new SQLMeta(); + Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); + Field2SQLObj.field2sqlObj(sqlMeta, allFields, allFields, crossDs, dsMap, Utils.getParams(allFields), null, pluginManage); + WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, allFields, crossDs, dsMap, Utils.getParams(allFields), null, pluginManage); + Order2SQLObj.getOrders(sqlMeta, dto.getSortFields(), allFields, crossDs, dsMap, Utils.getParams(allFields), null, pluginManage); + String replaceSql = provider.rebuildSQL(SQLProvider.createQuerySQL(sqlMeta, false, false, false), sqlMeta, crossDs, dsMap); + Long totalCount = datasetDataManage.getDatasetTotal(dto, replaceSql, null); + Long curLimit = ExportCenterUtils.getExportLimit("dataset"); + totalCount = totalCount > curLimit ? curLimit : totalCount; + + Long sheetCount = (totalCount / sheetLimit) + (totalCount % sheetLimit > 0 ? 1 : 0); + Workbook wb = new SXSSFWorkbook(); + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + font.setFontHeightInPoints((short) 12); + font.setBold(true); + cellStyle.setFont(font); + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + for (Long s = 1L; s < sheetCount + 1; s++) { + Long sheetSize; + if (s.equals(sheetCount)) { + sheetSize = totalCount - (s - 1) * sheetLimit; + } else { + sheetSize = sheetLimit; + } + Long pageSize = (sheetSize / extractPageSize) + (sheetSize % extractPageSize > 0 ? 1 : 0); + Sheet detailsSheet = null; + List> details = new ArrayList<>(); + for (Long p = 0L; p < pageSize; p++) { + int beforeCount = (int) ((s - 1) * sheetLimit); + String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, beforeCount + p.intValue() * extractPageSize, extractPageSize); + if (pageSize == 1) { + querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, 0, sheetSize.intValue()); + } + querySQL = provider.rebuildSQL(querySQL, sqlMeta, crossDs, dsMap); + DatasourceRequest datasourceRequest = new DatasourceRequest(); + datasourceRequest.setQuery(querySQL); + datasourceRequest.setDsList(dsMap); + datasourceRequest.setIsCross(coreDatasetGroup.getIsCross()); + Map previewData = datasetDataManage.buildPreviewData(provider.fetchResultField(datasourceRequest), allFields, desensitizationList, false); + List> data = (List>) previewData.get("data"); + if (p.equals(0L)) { + detailsSheet = wb.createSheet("数据" + s); + List header = new ArrayList<>(); + for (DatasetTableFieldDTO field : allFields) { + header.add(field.getName()); + } + details.add(header); + for (Map obj : data) { + List row = new ArrayList<>(); + for (DatasetTableFieldDTO field : allFields) { + String string = (String) obj.get(field.getGisbiName()); + row.add(string); + } + details.add(row); + } + if (CollectionUtils.isNotEmpty(details)) { + for (int i = 0; i < details.size(); i++) { + Row row = detailsSheet.createRow(i); + List rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.size(); j++) { + Cell cell = row.createCell(j); + if (i == 0) { + cell.setCellValue(rowData.get(j)); + cell.setCellStyle(cellStyle); + detailsSheet.setColumnWidth(j, 255 * 20); + } else { + if ((allFields.get(j).getDeType().equals(DeTypeConstants.DE_INT) || allFields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) { + try { + cell.setCellValue(Double.valueOf(rowData.get(j))); + } catch (Exception e) { + cell.setCellValue(rowData.get(j)); + } + } else { + cell.setCellValue(rowData.get(j)); + } + } + } + } + } + } + } else { + details.clear(); + for (Map obj : data) { + List row = new ArrayList<>(); + for (DatasetTableFieldDTO field : allFields) { + String string = (String) obj.get(field.getGisbiName()); + row.add(string); + } + details.add(row); + } + int lastNum = detailsSheet.getLastRowNum(); + for (int i = 0; i < details.size(); i++) { + Row row = detailsSheet.createRow(i + lastNum + 1); + List rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.size(); j++) { + Cell cell = row.createCell(j); + if (i == 0) { + cell.setCellValue(rowData.get(j)); + cell.setCellStyle(cellStyle); + detailsSheet.setColumnWidth(j, 255 * 20); + } else { + if ((allFields.get(j).getDeType().equals(DeTypeConstants.DE_INT) || allFields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) { + try { + cell.setCellValue(Double.valueOf(rowData.get(j))); + } catch (Exception e) { + cell.setCellValue(rowData.get(j)); + } + } else { + cell.setCellValue(rowData.get(j)); + } + } + + } + } + } + } + } + } + this.addWatermarkTools(wb); + response.setContentType("application/vnd.ms-excel"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(request.getFilename(), StandardCharsets.UTF_8) + ".xlsx"); + wb.write(outputStream); + outputStream.flush(); + outputStream.close(); + } catch (Exception e) { + DEException.throwException(e); + } + } +} + diff --git a/core/core-backend/src/main/java/io/gisbi/listener/DatasetCrossListener.java b/core/core-backend/src/main/java/io/gisbi/listener/DatasetCrossListener.java new file mode 100644 index 0000000..c7561cc --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/listener/DatasetCrossListener.java @@ -0,0 +1,46 @@ +package io.gisbi.listener; + +import io.gisbi.chart.manage.ChartViewOldDataMergeService; +import io.gisbi.dataset.manage.DatasetSQLManage; +import io.gisbi.startup.dao.auto.entity.CoreSysStartupJob; +import io.gisbi.startup.dao.auto.mapper.CoreSysStartupJobMapper; +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.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + + +/** + * @Author bi-coder + */ +@Component +@Order(value = 10) +public class DatasetCrossListener implements ApplicationListener { + private final Logger logger = LoggerFactory.getLogger(DatasetCrossListener.class); + public static final String JOB_ID = "datasetCrossListener"; + @Resource + private CoreSysStartupJobMapper coreSysStartupJobMapper; + @Resource + private DatasetSQLManage datasetSQLManage; + + @Override + public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { + logger.info("====dataset cross listener [start]===="); + + CoreSysStartupJob sysStartupJob = coreSysStartupJobMapper.selectById(JOB_ID); + if (ObjectUtils.isNotEmpty(sysStartupJob) && StringUtils.equalsIgnoreCase(sysStartupJob.getStatus(), "ready")) { + logger.info("====dataset cross listener [doing]===="); + + datasetSQLManage.datasetCrossDefault(); + + sysStartupJob.setStatus("done"); + coreSysStartupJobMapper.updateById(sysStartupJob); + } + logger.info("====dataset cross listener [end]===="); + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/system/manage/CorePermissionManage.java b/core/core-backend/src/main/java/io/gisbi/system/manage/CorePermissionManage.java new file mode 100644 index 0000000..1168e7e --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/system/manage/CorePermissionManage.java @@ -0,0 +1,14 @@ +package io.gisbi.system.manage; + +import io.gisbi.api.permissions.auth.dto.BusiPerCheckDTO; + +import org.springframework.stereotype.Component; + +@Component +public class CorePermissionManage { + + + public boolean checkAuth(BusiPerCheckDTO dto) { + return true; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotCoreChartView.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotCoreChartView.java new file mode 100644 index 0000000..28dbb99 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotCoreChartView.java @@ -0,0 +1,640 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_core_chart_view") +public class SnapshotCoreChartView 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 customAttrMobile; + + /** + * 组件样式 + */ + private String customStyle; + + /** + * 组件样式_移动端 + */ + private String customStyleMobile; + + /** + * 结果过滤 + */ + 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 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 getCustomAttrMobile() { + return customAttrMobile; + } + + public void setCustomAttrMobile(String customAttrMobile) { + this.customAttrMobile = customAttrMobile; + } + + public String getCustomStyle() { + return customStyle; + } + + public void setCustomStyle(String customStyle) { + this.customStyle = customStyle; + } + + public String getCustomStyleMobile() { + return customStyleMobile; + } + + public void setCustomStyleMobile(String customStyleMobile) { + this.customStyleMobile = customStyleMobile; + } + + 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 getSortPriority() { + return sortPriority; + } + + public void setSortPriority(String sortPriority) { + this.sortPriority = sortPriority; + } + + @Override + public String toString() { + return "SnapshotCoreChartView{" + + "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 + + ", customAttrMobile = " + customAttrMobile + + ", customStyle = " + customStyle + + ", customStyleMobile = " + customStyleMobile + + ", 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 + + ", sortPriority = " + sortPriority + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotDataVisualizationInfo.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotDataVisualizationInfo.java new file mode 100644 index 0000000..dec4811 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotDataVisualizationInfo.java @@ -0,0 +1,374 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * 可视化大屏信息表 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_data_visualization_info") +public class SnapshotDataVisualizationInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 父id + */ + private Long pid; + + /** + * 所属组织id + */ + private Long orgId; + + /** + * 层级 + */ + private Integer level; + + /** + * 节点类型 folder or panel 目录或者文件夹 + */ + private String nodeType; + + /** + * 类型 + */ + private String type; + + /** + * 样式数据 + */ + private String canvasStyleData; + + /** + * 组件数据 + */ + private String componentData; + + /** + * 移动端布局0-关闭 1-开启 + */ + private Boolean mobileLayout; + + /** + * 状态 0-未发布 1-已发布 + */ + private Integer status; + + /** + * 是否单独打开水印 0-关闭 1-开启 + */ + private Integer selfWatermarkStatus; + + /** + * 排序 + */ + private Integer sort; + + /** + * 创建时间 + */ + private Long createTime; + + /** + * 创建人 + */ + private String createBy; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updateBy; + + /** + * 备注 + */ + private String remark; + + /** + * 数据来源 + */ + private String source; + + /** + * 删除标志 + */ + private Boolean deleteFlag; + + /** + * 删除时间 + */ + private Long deleteTime; + + /** + * 删除人 + */ + private String deleteBy; + + /** + * 可视化资源版本 + */ + private Integer version; + + /** + * 内容标识 + */ + private String contentId; + + /** + * 内容检查标识 + */ + private String checkVersion; + + 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 Long getOrgId() { + return orgId; + } + + public void setOrgId(Long orgId) { + this.orgId = orgId; + } + + 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 String getCanvasStyleData() { + return canvasStyleData; + } + + public void setCanvasStyleData(String canvasStyleData) { + this.canvasStyleData = canvasStyleData; + } + + public String getComponentData() { + return componentData; + } + + public void setComponentData(String componentData) { + this.componentData = componentData; + } + + public Boolean getMobileLayout() { + return mobileLayout; + } + + public void setMobileLayout(Boolean mobileLayout) { + this.mobileLayout = mobileLayout; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getSelfWatermarkStatus() { + return selfWatermarkStatus; + } + + public void setSelfWatermarkStatus(Integer selfWatermarkStatus) { + this.selfWatermarkStatus = selfWatermarkStatus; + } + + public Integer getSort() { + return sort; + } + + public void setSort(Integer sort) { + this.sort = sort; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Long updateTime) { + this.updateTime = updateTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public Boolean getDeleteFlag() { + return deleteFlag; + } + + public void setDeleteFlag(Boolean deleteFlag) { + this.deleteFlag = deleteFlag; + } + + public Long getDeleteTime() { + return deleteTime; + } + + public void setDeleteTime(Long deleteTime) { + this.deleteTime = deleteTime; + } + + public String getDeleteBy() { + return deleteBy; + } + + public void setDeleteBy(String deleteBy) { + this.deleteBy = deleteBy; + } + + public Integer getVersion() { + return version; + } + + public void setVersion(Integer version) { + this.version = version; + } + + public String getContentId() { + return contentId; + } + + public void setContentId(String contentId) { + this.contentId = contentId; + } + + public String getCheckVersion() { + return checkVersion; + } + + public void setCheckVersion(String checkVersion) { + this.checkVersion = checkVersion; + } + + @Override + public String toString() { + return "SnapshotDataVisualizationInfo{" + + "id = " + id + + ", name = " + name + + ", pid = " + pid + + ", orgId = " + orgId + + ", level = " + level + + ", nodeType = " + nodeType + + ", type = " + type + + ", canvasStyleData = " + canvasStyleData + + ", componentData = " + componentData + + ", mobileLayout = " + mobileLayout + + ", status = " + status + + ", selfWatermarkStatus = " + selfWatermarkStatus + + ", sort = " + sort + + ", createTime = " + createTime + + ", createBy = " + createBy + + ", updateTime = " + updateTime + + ", updateBy = " + updateBy + + ", remark = " + remark + + ", source = " + source + + ", deleteFlag = " + deleteFlag + + ", deleteTime = " + deleteTime + + ", deleteBy = " + deleteBy + + ", version = " + version + + ", contentId = " + contentId + + ", checkVersion = " + checkVersion + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJump.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJump.java new file mode 100644 index 0000000..85876b1 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJump.java @@ -0,0 +1,122 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * 跳转记录表 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_visualization_link_jump") +public class SnapshotVisualizationLinkJump implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + + /** + * 源仪表板ID + */ + private Long sourceDvId; + + /** + * 源图表ID + */ + private Long sourceViewId; + + /** + * 跳转信息 + */ + private String linkJumpInfo; + + /** + * 是否启用 + */ + private Boolean checked; + + /** + * 复制来源 + */ + private Long copyFrom; + + /** + * 复制来源ID + */ + private Long copyId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getSourceDvId() { + return sourceDvId; + } + + public void setSourceDvId(Long sourceDvId) { + this.sourceDvId = sourceDvId; + } + + public Long getSourceViewId() { + return sourceViewId; + } + + public void setSourceViewId(Long sourceViewId) { + this.sourceViewId = sourceViewId; + } + + public String getLinkJumpInfo() { + return linkJumpInfo; + } + + public void setLinkJumpInfo(String linkJumpInfo) { + this.linkJumpInfo = linkJumpInfo; + } + + public Boolean getChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + + 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 "SnapshotVisualizationLinkJump{" + + "id = " + id + + ", sourceDvId = " + sourceDvId + + ", sourceViewId = " + sourceViewId + + ", linkJumpInfo = " + linkJumpInfo + + ", checked = " + checked + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpInfo.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpInfo.java new file mode 100644 index 0000000..db73106 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpInfo.java @@ -0,0 +1,192 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * 跳转配置表 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_visualization_link_jump_info") +public class SnapshotVisualizationLinkJumpInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + + /** + * link jump ID + */ + private Long linkJumpId; + + /** + * 关联类型 inner 内部仪表板,outer 外部链接 + */ + private String linkType; + + /** + * 跳转类型 _blank 新开页面 _self 当前窗口 + */ + private String jumpType; + + /** + * 关联仪表板ID + */ + private Long targetDvId; + + /** + * 字段ID + */ + private Long sourceFieldId; + + /** + * 内容 linkType = outer时使用 + */ + private String content; + + /** + * 是否可用 + */ + private Boolean checked; + + /** + * 是否附加点击参数 + */ + private Boolean attachParams; + + /** + * 复制来源 + */ + private Long copyFrom; + + /** + * 复制来源ID + */ + private Long copyId; + + /** + * 窗口大小large middle small + */ + private String windowSize; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getLinkJumpId() { + return linkJumpId; + } + + public void setLinkJumpId(Long linkJumpId) { + this.linkJumpId = linkJumpId; + } + + public String getLinkType() { + return linkType; + } + + public void setLinkType(String linkType) { + this.linkType = linkType; + } + + public String getJumpType() { + return jumpType; + } + + public void setJumpType(String jumpType) { + this.jumpType = jumpType; + } + + public Long getTargetDvId() { + return targetDvId; + } + + public void setTargetDvId(Long targetDvId) { + this.targetDvId = targetDvId; + } + + public Long getSourceFieldId() { + return sourceFieldId; + } + + public void setSourceFieldId(Long sourceFieldId) { + this.sourceFieldId = sourceFieldId; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Boolean getChecked() { + return checked; + } + + public void setChecked(Boolean checked) { + this.checked = checked; + } + + public Boolean getAttachParams() { + return attachParams; + } + + public void setAttachParams(Boolean attachParams) { + this.attachParams = attachParams; + } + + 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 String getWindowSize() { + return windowSize; + } + + public void setWindowSize(String windowSize) { + this.windowSize = windowSize; + } + + @Override + public String toString() { + return "SnapshotVisualizationLinkJumpInfo{" + + "id = " + id + + ", linkJumpId = " + linkJumpId + + ", linkType = " + linkType + + ", jumpType = " + jumpType + + ", targetDvId = " + targetDvId + + ", sourceFieldId = " + sourceFieldId + + ", content = " + content + + ", checked = " + checked + + ", attachParams = " + attachParams + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + ", windowSize = " + windowSize + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpTargetViewInfo.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpTargetViewInfo.java new file mode 100644 index 0000000..8353c1f --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkJumpTargetViewInfo.java @@ -0,0 +1,138 @@ +package io.gisbi.visualization.dao.auto.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_link_jump_target_view_info") +public class SnapshotVisualizationLinkJumpTargetViewInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId("target_id") + private Long targetId; + + /** + * visualization_link_jump_info 表的 ID + */ + private Long linkJumpInfoId; + + /** + * 勾选字段设置的匹配字段,也可以不是勾选字段本身 + */ + private Long sourceFieldActiveId; + + /** + * 目标图表ID + */ + private String targetViewId; + + /** + * 目标字段ID + */ + private String targetFieldId; + + /** + * 复制来源 + */ + private Long copyFrom; + + /** + * 复制来源ID + */ + private Long copyId; + + /** + * 联动目标类型 view 图表 filter 过滤组件 outParams 外部参数 + */ + private String targetType; + + public Long getTargetId() { + return targetId; + } + + public void setTargetId(Long targetId) { + this.targetId = targetId; + } + + public Long getLinkJumpInfoId() { + return linkJumpInfoId; + } + + public void setLinkJumpInfoId(Long linkJumpInfoId) { + this.linkJumpInfoId = linkJumpInfoId; + } + + public Long getSourceFieldActiveId() { + return sourceFieldActiveId; + } + + public void setSourceFieldActiveId(Long sourceFieldActiveId) { + this.sourceFieldActiveId = sourceFieldActiveId; + } + + public String getTargetViewId() { + return targetViewId; + } + + public void setTargetViewId(String targetViewId) { + this.targetViewId = targetViewId; + } + + public String getTargetFieldId() { + return targetFieldId; + } + + public void setTargetFieldId(String targetFieldId) { + this.targetFieldId = targetFieldId; + } + + 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 String getTargetType() { + return targetType; + } + + public void setTargetType(String targetType) { + this.targetType = targetType; + } + + @Override + public String toString() { + return "SnapshotVisualizationLinkJumpTargetViewInfo{" + + "targetId = " + targetId + + ", linkJumpInfoId = " + linkJumpInfoId + + ", sourceFieldActiveId = " + sourceFieldActiveId + + ", targetViewId = " + targetViewId + + ", targetFieldId = " + targetFieldId + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + ", targetType = " + targetType + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkage.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkage.java new file mode 100644 index 0000000..86fd0a3 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkage.java @@ -0,0 +1,178 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * 联动记录表 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_visualization_linkage") +public class SnapshotVisualizationLinkage implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + private Long id; + + /** + * 联动大屏/仪表板ID + */ + private Long dvId; + + /** + * 源图表id + */ + private Long sourceViewId; + + /** + * 联动图表id + */ + private Long targetViewId; + + /** + * 更新时间 + */ + private Long updateTime; + + /** + * 更新人 + */ + private String updatePeople; + + /** + * 是否启用关联 + */ + private Boolean linkageActive; + + /** + * 扩展字段1 + */ + private String ext1; + + /** + * 扩展字段2 + */ + private String ext2; + + /** + * 复制来源 + */ + private Long copyFrom; + + /** + * 复制来源ID + */ + 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 "SnapshotVisualizationLinkage{" + + "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/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkageField.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkageField.java new file mode 100644 index 0000000..0481f74 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationLinkageField.java @@ -0,0 +1,122 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

+ * 联动字段 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@TableName("snapshot_visualization_linkage_field") +public class SnapshotVisualizationLinkageField 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; + + /** + * 复制来源ID + */ + 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 "SnapshotVisualizationLinkageField{" + + "id = " + id + + ", linkageId = " + linkageId + + ", sourceField = " + sourceField + + ", targetField = " + targetField + + ", updateTime = " + updateTime + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParams.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParams.java new file mode 100644 index 0000000..5ca4f35 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParams.java @@ -0,0 +1,110 @@ +package io.gisbi.visualization.dao.auto.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; + +/** + *

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

+ * + * @Author bi-coder + * @since 2025-03-31 + */ +@TableName("snapshot_visualization_outer_params") +public class SnapshotVisualizationOuterParams implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId("params_id") + private String paramsId; + + /** + * 可视化资源ID + */ + private String visualizationId; + + /** + * 是否启用外部参数标识(1-是,0-否) + */ + private Boolean checked; + + /** + * 备注 + */ + private String remark; + + /** + * 复制来源 + */ + private String copyFrom; + + /** + * 复制来源ID + */ + private String copyId; + + 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 "SnapshotVisualizationOuterParams{" + + "paramsId = " + paramsId + + ", visualizationId = " + visualizationId + + ", checked = " + checked + + ", remark = " + remark + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsInfo.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsInfo.java new file mode 100644 index 0000000..9ed23e3 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsInfo.java @@ -0,0 +1,152 @@ +package io.gisbi.visualization.dao.auto.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/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsTargetViewInfo.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsTargetViewInfo.java new file mode 100644 index 0000000..1c179ee --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/entity/SnapshotVisualizationOuterParamsTargetViewInfo.java @@ -0,0 +1,124 @@ +package io.gisbi.visualization.dao.auto.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_target_view_info") +public class SnapshotVisualizationOuterParamsTargetViewInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId("target_id") + private String targetId; + + /** + * visualization_outer_params_info 表的 ID + */ + private String paramsInfoId; + + /** + * 联动视图ID/联动过滤项ID + */ + private String targetViewId; + + /** + * 联动字段ID + */ + private String targetFieldId; + + /** + * 复制来源 + */ + private String copyFrom; + + /** + * 复制来源ID + */ + private String copyId; + + /** + * 联动数据集id/联动过滤组件id + */ + private String targetDsId; + + public String getTargetId() { + return targetId; + } + + public void setTargetId(String targetId) { + this.targetId = targetId; + } + + public String getParamsInfoId() { + return paramsInfoId; + } + + public void setParamsInfoId(String paramsInfoId) { + this.paramsInfoId = paramsInfoId; + } + + public String getTargetViewId() { + return targetViewId; + } + + public void setTargetViewId(String targetViewId) { + this.targetViewId = targetViewId; + } + + public String getTargetFieldId() { + return targetFieldId; + } + + public void setTargetFieldId(String targetFieldId) { + this.targetFieldId = targetFieldId; + } + + 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 String getTargetDsId() { + return targetDsId; + } + + public void setTargetDsId(String targetDsId) { + this.targetDsId = targetDsId; + } + + @Override + public String toString() { + return "SnapshotVisualizationOuterParamsTargetViewInfo{" + + "targetId = " + targetId + + ", paramsInfoId = " + paramsInfoId + + ", targetViewId = " + targetViewId + + ", targetFieldId = " + targetFieldId + + ", copyFrom = " + copyFrom + + ", copyId = " + copyId + + ", targetDsId = " + targetDsId + + "}"; + } +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotCoreChartViewMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotCoreChartViewMapper.java new file mode 100644 index 0000000..549c0e5 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotCoreChartViewMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotCoreChartView; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotCoreChartViewMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotDataVisualizationInfoMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotDataVisualizationInfoMapper.java new file mode 100644 index 0000000..19b95f9 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotDataVisualizationInfoMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotDataVisualizationInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 可视化大屏信息表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotDataVisualizationInfoMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpInfoMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpInfoMapper.java new file mode 100644 index 0000000..b8998a7 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpInfoMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationLinkJumpInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 跳转配置表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationLinkJumpInfoMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpMapper.java new file mode 100644 index 0000000..e30f213 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationLinkJump; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 跳转记录表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationLinkJumpMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpTargetViewInfoMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpTargetViewInfoMapper.java new file mode 100644 index 0000000..c74b3d1 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkJumpTargetViewInfoMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationLinkJumpTargetViewInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 跳转目标仪表板图表字段配置表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationLinkJumpTargetViewInfoMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageFieldMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageFieldMapper.java new file mode 100644 index 0000000..043ebc2 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageFieldMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationLinkageField; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 联动字段 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationLinkageFieldMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageMapper.java new file mode 100644 index 0000000..c36c54b --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationLinkageMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationLinkage; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 联动记录表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationLinkageMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsInfoMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsInfoMapper.java new file mode 100644 index 0000000..3b2bfdb --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsInfoMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationOuterParamsInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 外部参数配置表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationOuterParamsInfoMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsMapper.java new file mode 100644 index 0000000..e6e91f7 --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationOuterParams; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 外部参数关联关系表 Mapper 接口 + *

+ * + * @Author bi-coder + * @since 2025-03-31 + */ +@Mapper +public interface SnapshotVisualizationOuterParamsMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsTargetViewInfoMapper.java b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsTargetViewInfoMapper.java new file mode 100644 index 0000000..5455f0e --- /dev/null +++ b/core/core-backend/src/main/java/io/gisbi/visualization/dao/auto/mapper/SnapshotVisualizationOuterParamsTargetViewInfoMapper.java @@ -0,0 +1,18 @@ +package io.gisbi.visualization.dao.auto.mapper; + +import io.gisbi.visualization.dao.auto.entity.SnapshotVisualizationOuterParamsTargetViewInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

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

+ * + * @Author bi-coder + * @since 2025-03-24 + */ +@Mapper +public interface SnapshotVisualizationOuterParamsTargetViewInfoMapper extends BaseMapper { + +} diff --git a/core/core-backend/src/main/resources/application-desktop.yml b/core/core-backend/src/main/resources/application-desktop.yml new file mode 100644 index 0000000..7c9932c --- /dev/null +++ b/core/core-backend/src/main/resources/application-desktop.yml @@ -0,0 +1,25 @@ + +spring: + + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:/opt/dataease2.0/desktop;AUTO_SERVER=TRUE;AUTO_RECONNECT=TRUE;MODE=MySQL;CASE_INSENSITIVE_IDENTIFIERS=TRUE;DATABASE_TO_UPPER=FALSE + username: sa + password: 123456 + + h2: + console: + enabled: true + path: /h2-console + messages: + basename: i18n/core + flyway: + enabled: true + table: de_desktop_version + validate-on-migrate: false + locations: classpath:db/desktop + baseline-on-migrate: true + out-of-order: true + +mybatis-plus: + mapper-locations: classpath:mybatis/*.xml diff --git a/core/core-backend/src/main/resources/db/migration/V2.10.11__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10.11__ddl.sql new file mode 100644 index 0000000..04053fb --- /dev/null +++ b/core/core-backend/src/main/resources/db/migration/V2.10.11__ddl.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS `core_export_download_task`; +CREATE TABLE `core_export_download_task` +( + `id` varchar(255) NOT NULL, + `create_time` bigint(20) DEFAULT NULL, + `valid_time` bigint(20) DEFAULT NULL, + PRIMARY KEY (`id`) +) COMMENT='下载任务列表'; diff --git a/core/core-backend/src/main/resources/db/migration/V2.10.6__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10.6__ddl.sql new file mode 100644 index 0000000..8766d7e --- /dev/null +++ b/core/core-backend/src/main/resources/db/migration/V2.10.6__ddl.sql @@ -0,0 +1,9 @@ +ALTER TABLE `core_dataset_table_field` + ADD COLUMN `group_list` longtext NULL COMMENT '分组设置' AFTER `field_short_name`; + +ALTER TABLE `core_dataset_table_field` + ADD COLUMN `other_group` longtext NULL COMMENT '未分组的值' AFTER `group_list`; + +ALTER TABLE `visualization_report_filter` +DROP PRIMARY KEY; + diff --git a/core/core-backend/src/main/resources/db/migration/V2.10.7__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10.7__ddl.sql new file mode 100644 index 0000000..8da75d3 --- /dev/null +++ b/core/core-backend/src/main/resources/db/migration/V2.10.7__ddl.sql @@ -0,0 +1,210 @@ + +DROP TABLE IF EXISTS `snapshot_core_chart_view`; +CREATE TABLE `snapshot_core_chart_view` ( + `id` bigint NOT NULL COMMENT 'ID', + `title` varchar(1024) DEFAULT NULL COMMENT '标题', + `scene_id` bigint NOT NULL COMMENT '场景ID chart_type为private的时候 是仪表板id', + `table_id` bigint DEFAULT NULL COMMENT '数据集表ID', + `type` varchar(50) DEFAULT NULL COMMENT '图表类型', + `render` varchar(50) DEFAULT NULL COMMENT '图表渲染方式', + `result_count` int DEFAULT NULL COMMENT '展示结果', + `result_mode` varchar(50) DEFAULT NULL COMMENT '展示模式', + `x_axis` longtext COMMENT '横轴field', + `x_axis_ext` longtext COMMENT 'table-row', + `y_axis` longtext COMMENT '纵轴field', + `y_axis_ext` longtext COMMENT '副轴', + `ext_stack` longtext COMMENT '堆叠项', + `ext_bubble` longtext COMMENT '气泡大小', + `ext_label` longtext COMMENT '动态标签', + `ext_tooltip` longtext COMMENT '动态提示', + `custom_attr` longtext COMMENT '图形属性', + `custom_attr_mobile` longtext COMMENT '图形属性_移动端', + `custom_style` longtext COMMENT '组件样式', + `custom_style_mobile` longtext COMMENT '组件样式_移动端', + `custom_filter` longtext COMMENT '结果过滤', + `drill_fields` longtext COMMENT '钻取字段', + `senior` longtext COMMENT '高级', + `create_by` varchar(50) DEFAULT NULL COMMENT '创建人ID', + `create_time` bigint DEFAULT NULL COMMENT '创建时间', + `update_time` bigint DEFAULT NULL COMMENT '更新时间', + `snapshot` longtext COMMENT '缩略图 ', + `style_priority` varchar(255) DEFAULT 'panel' COMMENT '样式优先级 panel 仪表板 view 图表', + `chart_type` varchar(255) DEFAULT 'private' COMMENT '图表类型 public 公共 历史可复用的图表,private 私有 专属某个仪表板', + `is_plugin` bit(1) DEFAULT NULL COMMENT '是否插件', + `data_from` varchar(255) DEFAULT 'dataset' COMMENT '数据来源 template 模板数据 dataset 数据集数据', + `view_fields` longtext COMMENT '图表字段集合', + `refresh_view_enable` tinyint(1) DEFAULT '0' COMMENT '是否开启刷新', + `refresh_unit` varchar(255) DEFAULT 'minute' COMMENT '刷新时间单位', + `refresh_time` int DEFAULT '5' COMMENT '刷新时间', + `linkage_active` tinyint(1) DEFAULT '0' COMMENT '是否开启联动', + `jump_active` tinyint(1) DEFAULT '0' COMMENT '是否开启跳转', + `copy_from` bigint DEFAULT NULL COMMENT '复制来源', + `copy_id` bigint DEFAULT NULL COMMENT '复制ID', + `aggregate` bit(1) DEFAULT NULL COMMENT '区间条形图开启时间纬度开启聚合', + `flow_map_start_name` longtext COMMENT '流向地图起点名称field', + `flow_map_end_name` longtext COMMENT '流向地图终点名称field', + `ext_color` longtext COMMENT '颜色维度field', + `sort_priority` longtext COMMENT '字段排序优先级', + PRIMARY KEY (`id`) +); + +-- ---------------------------- +-- Table structure for snapshot_data_visualization_info +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_data_visualization_info`; +CREATE TABLE `snapshot_data_visualization_info` ( + `id` varchar(50) NOT NULL COMMENT '主键', + `name` varchar(255) DEFAULT NULL COMMENT '名称', + `pid` varchar(50) DEFAULT NULL COMMENT '父id', + `org_id` varchar(50) DEFAULT NULL COMMENT '所属组织id', + `level` int DEFAULT NULL COMMENT '层级', + `node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹', + `type` varchar(50) DEFAULT NULL COMMENT '类型', + `canvas_style_data` longtext COMMENT '样式数据', + `component_data` longtext COMMENT '组件数据', + `mobile_layout` tinyint DEFAULT '0' COMMENT '移动端布局0-关闭 1-开启', + `status` int DEFAULT '1' COMMENT '状态 0-未发布 1-已发布', + `self_watermark_status` int DEFAULT '0' COMMENT '是否单独打开水印 0-关闭 1-开启', + `sort` int DEFAULT '0' COMMENT '排序', + `create_time` bigint DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) DEFAULT NULL COMMENT '创建人', + `update_time` bigint DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) DEFAULT NULL COMMENT '更新人', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `source` varchar(255) DEFAULT NULL COMMENT '数据来源', + `delete_flag` tinyint(1) DEFAULT '0' COMMENT '删除标志', + `delete_time` bigint DEFAULT NULL COMMENT '删除时间', + `delete_by` varchar(255) DEFAULT NULL COMMENT '删除人', + `version` int DEFAULT '3' COMMENT '可视化资源版本', + `content_id` varchar(50) DEFAULT '0' COMMENT '内容标识', + `check_version` varchar(50) DEFAULT '1' COMMENT '内容检查标识', + PRIMARY KEY (`id`) +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_link_jump +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_link_jump`; +CREATE TABLE `snapshot_visualization_link_jump` ( + `id` bigint NOT NULL COMMENT '主键', + `source_dv_id` bigint DEFAULT NULL COMMENT '源仪表板ID', + `source_view_id` bigint DEFAULT NULL COMMENT '源图表ID', + `link_jump_info` varchar(4000) DEFAULT NULL COMMENT '跳转信息', + `checked` tinyint(1) DEFAULT NULL COMMENT '是否启用', + `copy_from` bigint DEFAULT NULL COMMENT '复制来源', + `copy_id` bigint DEFAULT NULL COMMENT '复制来源ID', + PRIMARY KEY (`id`) +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_link_jump_info +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_link_jump_info`; +CREATE TABLE `snapshot_visualization_link_jump_info` ( + `id` bigint NOT NULL COMMENT '主键', + `link_jump_id` bigint DEFAULT NULL COMMENT 'link jump ID', + `link_type` varchar(255) DEFAULT NULL COMMENT '关联类型 inner 内部仪表板,outer 外部链接', + `jump_type` varchar(255) DEFAULT NULL COMMENT '跳转类型 _blank 新开页面 _self 当前窗口', + `target_dv_id` bigint DEFAULT NULL COMMENT '关联仪表板ID', + `source_field_id` bigint DEFAULT NULL COMMENT '字段ID', + `content` varchar(4000) DEFAULT NULL COMMENT '内容 linkType = outer时使用', + `checked` tinyint(1) DEFAULT NULL COMMENT '是否可用', + `attach_params` tinyint(1) DEFAULT NULL COMMENT '是否附加点击参数', + `copy_from` bigint DEFAULT NULL COMMENT '复制来源', + `copy_id` bigint DEFAULT NULL COMMENT '复制来源ID', + `window_size` varchar(255) DEFAULT 'middle' COMMENT '窗口大小large middle small', + PRIMARY KEY (`id`) +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_link_jump_target_view_info +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_link_jump_target_view_info`; +CREATE TABLE `snapshot_visualization_link_jump_target_view_info` ( + `target_id` bigint NOT NULL COMMENT '主键', + `link_jump_info_id` bigint DEFAULT NULL COMMENT 'visualization_link_jump_info 表的 ID', + `source_field_active_id` bigint DEFAULT NULL COMMENT '勾选字段设置的匹配字段,也可以不是勾选字段本身', + `target_view_id` varchar(50) DEFAULT NULL COMMENT '目标图表ID', + `target_field_id` varchar(50) DEFAULT NULL COMMENT '目标字段ID', + `copy_from` bigint DEFAULT NULL COMMENT '复制来源', + `copy_id` bigint DEFAULT NULL COMMENT '复制来源ID', + `target_type` varchar(50) DEFAULT 'view' COMMENT '联动目标类型 view 图表 filter 过滤组件 outParams 外部参数', + PRIMARY KEY (`target_id`) USING BTREE +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_linkage +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_linkage`; +CREATE TABLE `snapshot_visualization_linkage` ( + `id` bigint NOT NULL COMMENT '主键', + `dv_id` bigint DEFAULT NULL COMMENT '联动大屏/仪表板ID', + `source_view_id` bigint DEFAULT NULL COMMENT '源图表id', + `target_view_id` bigint DEFAULT NULL COMMENT '联动图表id', + `update_time` bigint DEFAULT NULL COMMENT '更新时间', + `update_people` varchar(255) DEFAULT NULL COMMENT '更新人', + `linkage_active` tinyint(1) DEFAULT '0' COMMENT '是否启用关联', + `ext1` varchar(2000) DEFAULT NULL COMMENT '扩展字段1', + `ext2` varchar(2000) DEFAULT NULL COMMENT '扩展字段2', + `copy_from` bigint DEFAULT NULL COMMENT '复制来源', + `copy_id` bigint DEFAULT NULL COMMENT '复制来源ID', + PRIMARY KEY (`id`) +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_linkage_field +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_linkage_field`; +CREATE TABLE `snapshot_visualization_linkage_field` ( + `id` bigint NOT NULL COMMENT '主键', + `linkage_id` bigint DEFAULT NULL COMMENT '联动ID', + `source_field` bigint DEFAULT NULL COMMENT '源图表字段', + `target_field` bigint DEFAULT NULL COMMENT '目标图表字段', + `update_time` bigint DEFAULT NULL COMMENT '更新时间', + `copy_from` bigint DEFAULT NULL COMMENT '复制来源', + `copy_id` bigint DEFAULT NULL COMMENT '复制来源ID', + PRIMARY KEY (`id`) +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_outer_params +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_outer_params`; +CREATE TABLE `snapshot_visualization_outer_params` ( + `params_id` varchar(50) NOT NULL COMMENT '主键', + `visualization_id` varchar(50) DEFAULT NULL COMMENT '可视化资源ID', + `checked` tinyint(1) DEFAULT NULL COMMENT '是否启用外部参数标识(1-是,0-否)', + `remark` varchar(255) DEFAULT NULL COMMENT '备注', + `copy_from` varchar(50) DEFAULT NULL COMMENT '复制来源', + `copy_id` varchar(50) DEFAULT NULL COMMENT '复制来源ID', + PRIMARY KEY (`params_id`) USING BTREE +); + +-- ---------------------------- +-- Table structure for snapshot_visualization_outer_params_info +-- ---------------------------- +DROP TABLE IF EXISTS `snapshot_visualization_outer_params_info`; +CREATE TABLE `snapshot_visualization_outer_params_info` ( + `params_info_id` varchar(50) NOT NULL COMMENT '主键', + `params_id` varchar(50) DEFAULT NULL COMMENT 'visualization_outer_params 表的 ID', + `param_name` varchar(255) DEFAULT NULL COMMENT '参数名', + `checked` tinyint(1) DEFAULT NULL COMMENT '是否启用', + `copy_from` varchar(255) DEFAULT NULL COMMENT '复制来源', + `copy_id` varchar(50) DEFAULT NULL COMMENT '复制来源ID', + `required` tinyint(1) DEFAULT '0' COMMENT '是否必填', + `default_value` varchar(255) DEFAULT NULL COMMENT '默认值 JSON格式', + `enabled_default` tinyint(1) DEFAULT '0' COMMENT '是否启用默认值', + PRIMARY KEY (`params_info_id`) USING BTREE +); + +DROP TABLE IF EXISTS `snapshot_visualization_outer_params_target_view_info`; +CREATE TABLE `snapshot_visualization_outer_params_target_view_info` ( + `target_id` varchar(50) NOT NULL COMMENT '主键', + `params_info_id` varchar(50) DEFAULT NULL COMMENT 'visualization_outer_params_info 表的 ID', + `target_view_id` varchar(50) DEFAULT NULL COMMENT '联动视图ID/联动过滤项ID', + `target_field_id` varchar(50) DEFAULT NULL COMMENT '联动字段ID', + `copy_from` varchar(255) DEFAULT NULL COMMENT '复制来源', + `copy_id` varchar(50) DEFAULT NULL COMMENT '复制来源ID', + `target_ds_id` varchar(50) DEFAULT NULL COMMENT '联动数据集id/联动过滤组件id', + PRIMARY KEY (`target_id`) +); \ No newline at end of file diff --git a/core/core-backend/src/main/resources/db/migration/V2.10.8__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10.8__ddl.sql new file mode 100644 index 0000000..8376cf8 --- /dev/null +++ b/core/core-backend/src/main/resources/db/migration/V2.10.8__ddl.sql @@ -0,0 +1,5 @@ +alter table `core_dataset_group` + add is_cross bit null comment '是否跨源'; + +INSERT INTO `core_sys_startup_job` +VALUES ('datasetCrossListener', 'datasetCrossListener', 'ready'); \ No newline at end of file diff --git a/core/core-backend/src/main/resources/mybatis/ExtCoreChartMapper.xml b/core/core-backend/src/main/resources/mybatis/ExtCoreChartMapper.xml new file mode 100644 index 0000000..c0a3e3e --- /dev/null +++ b/core/core-backend/src/main/resources/mybatis/ExtCoreChartMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + delete from + + + snapshot_core_chart_view + + + core_chart_view + + + where scene_id = #{sceneId} + +