提交了新增的文件

This commit is contained in:
root 2025-06-23 10:40:21 +08:00
parent adabf1e604
commit a678c15c11
49 changed files with 5316 additions and 0 deletions

View File

@ -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<String, String> findTargetUrl() {
Map<String, String> templateParams = sysParameterManage.groupVal("ai.");
if (templateParams != null && StringUtils.isNotEmpty(templateParams.get("ai.baseUrl"))) {
return templateParams;
} else {
return new HashMap<>();
}
}
}

View File

@ -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<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> 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 extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> 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<String[]>) provider.fetchResultField(req).get("data");
result.setAssistData(assistData);
result.setDynamicAssistFields(dynamicAssistFields);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}

View File

@ -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<Map<String, String>> sysParams = new ArrayList<>();
TypeReference<List<SqlVariableDetails>> listTypeReference = new TypeReference<List<SqlVariableDetails>>() {
};
private List<SqlVariableDetails> defaultsSqlVariableDetails = new ArrayList<>();
public String handleVariableDefaultValue(String sql, String sqlVariableDetails, boolean isEdit, boolean isFromDataSet, List<SqlVariableDetails> parameters, boolean isCross, Map<Long, DatasourceSchemaDTO> 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<Long, DatasourceSchemaDTO> 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<XpackPluginsDatasourceVO> xpackPluginsDatasourceVOS = pluginManage.queryPluginDs();
List<XpackPluginsDatasourceVO> 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<Long, DatasourceSchemaDTO> 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<String> 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;
}
}
}

View File

@ -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));
}
}
}

View File

@ -0,0 +1,71 @@
package io.gisbi.copilot.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,276 @@
package io.gisbi.copilot.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,74 @@
package io.gisbi.copilot.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2024-07-08
*/
@Mapper
public interface CoreCopilotConfigMapper extends BaseMapper<CoreCopilotConfig> {
}

View File

@ -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;
/**
* <p>
* Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2024-07-04
*/
@Mapper
public interface CoreCopilotMsgMapper extends BaseMapper<CoreCopilotMsg> {
}

View File

@ -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;
/**
* <p>
* Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2024-07-08
*/
@Mapper
public interface CoreCopilotTokenMapper extends BaseMapper<CoreCopilotToken> {
}

View File

@ -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<UnionDTO> unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() {
});
dto.setUnion(unionDTOList);
// 获取field
List<DatasetTableFieldDTO> dsFields = datasetTableFieldManage.selectByDatasetGroupId(msgDTO.getDatasetGroupId());
List<DatasetTableFieldDTO> 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<String, Object> sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null);
String sql = (String) sqlMap.get("sql");// 数据集原始SQL
Map<Long, DatasourceSchemaDTO> dsMap = (Map<Long, DatasourceSchemaDTO>) 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());// 数据库类型如mysqloracle等可能需要映射成copilot需要的类型
datasetDataManage.buildFieldName(sqlMap, allFields);
List<String> 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<String, ColumnPermissionItem> desensitizationList = new HashMap<>();
allFields = permissionManage.filterColumnPermissions(allFields, desensitizationList, dto.getId(), null);
if (ObjectUtils.isEmpty(allFields)) {
DEException.throwException(Translator.get("i18n_no_column_permission"));
}
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> 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<DataSetRowPermissionsTreeDTO> 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<String, Object> 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<TableField> fields = (List<TableField>) data.get("fields");
fields = transField(fields);
Map<String, Object> map = new LinkedHashMap<>();
// 重新构造data
Map<String, Object> 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<TableField> 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<AxisFieldDTO> 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<AxisFieldDTO> columns = new ArrayList<>();
columns.add(receiveDTO.getChart().getAxis().getX());
columns.add(receiveDTO.getChart().getAxis().getY());
receiveDTO.getChart().setColumns(columns);
}
}
public List<MsgDTO> getList(Long userId) {
MsgDTO lastMsg = msgManage.getLastMsg(userId);
if (lastMsg == null) {
return null;
}
List<MsgDTO> 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<TableField> transField(List<TableField> fields) {
fields.forEach(field -> {
field.setDeExtractType(FieldUtils.transType2DeType(field.getFieldType()));
field.setDeType(FieldUtils.transType2DeType(field.getFieldType()));
});
return fields;
}
public Map<String, Object> buildPreviewData(Map<String, Object> data, List<TableField> fields, Map<String, ColumnPermissionItem> desensitizationList) {
Map<String, Object> map = new LinkedHashMap<>();
List<String[]> dataList = (List<String[]>) data.get("data");
List<LinkedHashMap<String, Object>> dataObjectList = new ArrayList<>();
if (ObjectUtils.isNotEmpty(dataList)) {
for (int i = 0; i < dataList.size(); i++) {
String[] row = dataList.get(i);
LinkedHashMap<String, Object> 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<String> transCreateTableFields(List<DatasetTableFieldDTO> allFields) {
List<String> 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;
}
}
}

View File

@ -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<MsgDTO> getMsg(MsgDTO msgDTO) {
QueryWrapper<CoreCopilotMsg> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", msgDTO.getUserId());
wrapper.eq("dataset_group_id", msgDTO.getDatasetGroupId());
wrapper.orderByAsc("create_time");
List<CoreCopilotMsg> perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper);
return perCopilotMsgs.stream().map(this::transRecord).toList();
}
public void deleteMsg(MsgDTO msgDTO) {
QueryWrapper<CoreCopilotMsg> 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<CoreCopilotMsg> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", userId);
coreCopilotMsgMapper.delete(wrapper);
}
public MsgDTO getLastMsg(Long userId) {
QueryWrapper<CoreCopilotMsg> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", userId);
wrapper.orderByDesc("create_time");
List<CoreCopilotMsg> perCopilotMsgs = coreCopilotMsgMapper.selectList(wrapper);
return ObjectUtils.isEmpty(perCopilotMsgs) ? null : transRecord(perCopilotMsgs.getFirst());
}
public MsgDTO getLastSuccessMsg(Long userId, Long datasetGroupId) {
QueryWrapper<CoreCopilotMsg> 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<CoreCopilotMsg> 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<List<HistoryDTO>> 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;
}
}

View File

@ -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;
}
}

View File

@ -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<MsgDTO> getList() throws Exception {
return copilotManage.getList(AuthUtils.getUser().getUserId());
}
@Override
public void clearAll() throws Exception {
copilotManage.clearAll(AuthUtils.getUser().getUserId());
}
}

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -0,0 +1,57 @@
package io.gisbi.exportCenter.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
* 下载任务列表
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* 下载任务列表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-06-16
*/
@Mapper
public interface CoreExportDownloadTaskMapper extends BaseMapper<CoreExportDownloadTask> {
}

View File

@ -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<CoreExportTask> {
@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<ExportTaskDTO> pager(IPage<ExportTaskDTO> page, @Param("ew") QueryWrapper queryWrapper);
}

View File

@ -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<String> STATUS = Arrays.asList("SUCCESS", "FAILED", "PENDING", "IN_PROGRESS", "ALL");
private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private int keepAliveSeconds = 600;
private Map<String, Future> 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<Map.Entry<String, Future>> iterator = Running_Task.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Future> 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<String, Object> 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<UnionDTO> unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() {
});
dto.setUnion(unionDTOList);
List<DatasetTableFieldDTO> dsFields = datasetTableFieldManage.selectByDatasetGroupId(Long.valueOf(exportTask.getExportFrom()));
List<DatasetTableFieldDTO> allFields = dsFields.stream().map(ele -> {
DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO();
BeanUtils.copyBean(datasetTableFieldDTO, ele);
datasetTableFieldDTO.setFieldShortName(ele.getGisbiName());
return datasetTableFieldDTO;
}).collect(Collectors.toList());
Map<String, Object> sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null);
String sql = (String) sqlMap.get("sql");
if (ObjectUtils.isEmpty(allFields)) {
DEException.throwException(Translator.get("i18n_no_fields"));
}
Map<String, ColumnPermissionItem> 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<Long, DatasourceSchemaDTO> dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
DatasourceUtils.checkDsStatus(dsMap);
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> 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<DataSetRowPermissionsTreeDTO> 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<List<String>> 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<String, Object> previewData = datasetDataManage.buildPreviewData(provider.fetchResultField(datasourceRequest), allFields, desensitizationList, false);
List<Map<String, Object>> data = (List<Map<String, Object>>) previewData.get("data");
if (p.equals(0L)) {
detailsSheet = wb.createSheet("数据" + s);
List<String> header = new ArrayList<>();
for (DatasetTableFieldDTO field : allFields) {
header.add(field.getName());
}
details.add(header);
for (Map<String, Object> obj : data) {
List<String> 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<String> 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<String, Object> obj : data) {
List<String> 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<String> 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<Object[]> 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<ChartViewFieldDTO> 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<Object[]> 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<Object[]> 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<UnionDTO> unionDTOList = JsonUtil.parseList(coreDatasetGroup.getInfo(), new TypeReference<>() {
});
dto.setUnion(unionDTOList);
List<DatasetTableFieldDTO> dsFields = datasetTableFieldManage.selectByDatasetGroupId(request.getId());
List<DatasetTableFieldDTO> allFields = dsFields.stream().map(ele -> {
DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO();
BeanUtils.copyBean(datasetTableFieldDTO, ele);
datasetTableFieldDTO.setFieldShortName(ele.getGisbiName());
return datasetTableFieldDTO;
}).collect(Collectors.toList());
Map<String, Object> sqlMap = datasetSQLManage.getUnionSQLForEdit(dto, null);
String sql = (String) sqlMap.get("sql");
if (ObjectUtils.isEmpty(allFields)) {
DEException.throwException(Translator.get("i18n_no_fields"));
}
Map<String, ColumnPermissionItem> 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<Long, DatasourceSchemaDTO> dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
DatasourceUtils.checkDsStatus(dsMap);
List<String> dsList = new ArrayList<>();
for (Map.Entry<Long, DatasourceSchemaDTO> 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<DataSetRowPermissionsTreeDTO> 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<List<String>> 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<String, Object> previewData = datasetDataManage.buildPreviewData(provider.fetchResultField(datasourceRequest), allFields, desensitizationList, false);
List<Map<String, Object>> data = (List<Map<String, Object>>) previewData.get("data");
if (p.equals(0L)) {
detailsSheet = wb.createSheet("数据" + s);
List<String> header = new ArrayList<>();
for (DatasetTableFieldDTO field : allFields) {
header.add(field.getName());
}
details.add(header);
for (Map<String, Object> obj : data) {
List<String> 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<String> 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<String, Object> obj : data) {
List<String> 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<String> 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);
}
}
}

View File

@ -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<ApplicationReadyEvent> {
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]====");
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,640 @@
package io.gisbi.visualization.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,374 @@
package io.gisbi.visualization.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
* 可视化大屏信息表
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,122 @@
package io.gisbi.visualization.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
* 跳转记录表
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,192 @@
package io.gisbi.visualization.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
* 跳转配置表
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* 跳转目标仪表板图表字段配置表
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,178 @@
package io.gisbi.visualization.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
* 联动记录表
* </p>
*
* @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 +
"}";
}
}

View File

@ -0,0 +1,122 @@
package io.gisbi.visualization.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
* 联动字段
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* 外部参数关联关系表
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* 外部参数配置表
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* 外部参数联动视图字段信息表
* </p>
*
* @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 +
"}";
}
}

View File

@ -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;
/**
* <p>
* Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotCoreChartViewMapper extends BaseMapper<SnapshotCoreChartView> {
}

View File

@ -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;
/**
* <p>
* 可视化大屏信息表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotDataVisualizationInfoMapper extends BaseMapper<SnapshotDataVisualizationInfo> {
}

View File

@ -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;
/**
* <p>
* 跳转配置表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationLinkJumpInfoMapper extends BaseMapper<SnapshotVisualizationLinkJumpInfo> {
}

View File

@ -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;
/**
* <p>
* 跳转记录表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationLinkJumpMapper extends BaseMapper<SnapshotVisualizationLinkJump> {
}

View File

@ -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;
/**
* <p>
* 跳转目标仪表板图表字段配置表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationLinkJumpTargetViewInfoMapper extends BaseMapper<SnapshotVisualizationLinkJumpTargetViewInfo> {
}

View File

@ -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;
/**
* <p>
* 联动字段 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationLinkageFieldMapper extends BaseMapper<SnapshotVisualizationLinkageField> {
}

View File

@ -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;
/**
* <p>
* 联动记录表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationLinkageMapper extends BaseMapper<SnapshotVisualizationLinkage> {
}

View File

@ -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;
/**
* <p>
* 外部参数配置表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationOuterParamsInfoMapper extends BaseMapper<SnapshotVisualizationOuterParamsInfo> {
}

View File

@ -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;
/**
* <p>
* 外部参数关联关系表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-31
*/
@Mapper
public interface SnapshotVisualizationOuterParamsMapper extends BaseMapper<SnapshotVisualizationOuterParams> {
}

View File

@ -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;
/**
* <p>
* 外部参数联动视图字段信息表 Mapper 接口
* </p>
*
* @Author bi-coder
* @since 2025-03-24
*/
@Mapper
public interface SnapshotVisualizationOuterParamsTargetViewInfoMapper extends BaseMapper<SnapshotVisualizationOuterParamsTargetViewInfo> {
}

View File

@ -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

View File

@ -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='下载任务列表';

View File

@ -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;

View File

@ -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`)
);

View File

@ -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');

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.dataease.chart.dao.ext.mapper.ExtChartViewMapper">
<select id="queryChart" resultType="io.dataease.chart.dao.ext.entity.ChartBasePO">
select
ccv.id as chart_id,
ccv.title as chart_name,
ccv.type as chart_type,
ccv.table_id,
dvi.id as resource_id,
dvi.name as resource_name,
dvi.type as resource_type,
ccv.x_axis,
ccv.x_axis_ext,
ccv.y_axis,
ccv.y_axis_ext,
ccv.ext_stack,
ccv.ext_bubble,
ccv.ext_label,
ccv.ext_tooltip,
ccv.flow_map_start_name,
ccv.flow_map_end_name,
ccv.ext_color
<choose>
<when test="resourceTable == 'snapshot'">
from snapshot_core_chart_view ccv
left join snapshot_data_visualization_info dvi on dvi.id = ccv.scene_id
</when>
<otherwise>
from core_chart_view ccv
left join data_visualization_info dvi on dvi.id = ccv.scene_id
</otherwise>
</choose>
where ccv.id = #{id}
</select>
<select id="selectListCustom" resultType="io.dataease.chart.dao.auto.entity.CoreChartView">
select * from
<choose>
<when test="resourceTable == 'snapshot'">
snapshot_core_chart_view
</when>
<otherwise>
core_chart_view
</otherwise>
</choose>
where scene_id = #{sceneId}
</select>
<delete id="deleteViewsBySceneId">
delete from
<choose>
<when test="resourceTable == 'snapshot'">
snapshot_core_chart_view
</when>
<otherwise>
core_chart_view
</otherwise>
</choose>
where scene_id = #{sceneId}
</delete>
</mapper>