Merge branch 'dev-v2' into pr@dev-v2_search_tree
This commit is contained in:
commit
637bd80096
16
README.md
16
README.md
@ -22,16 +22,16 @@ DataEase 是开源的数据可视化分析工具( BI 工具 ),帮助用户
|
||||
|
||||
**DataEase 支持的数据源:**
|
||||
|
||||
- OLTP 数据库: MySQL、Oracle、SQL Server、PostgreSQL、MariaDB、Db2、TiDB、MongoDB-BI 等;
|
||||
- OLAP 数据库: ClickHouse、Apache Doris、Apache Impala、StarRocks 等;
|
||||
- 数据仓库/数据湖: Amazon RedShift 等;
|
||||
- 数据文件: Excel、CSV 等;
|
||||
- OLTP 数据库: MySQL、Oracle、SQL Server、PostgreSQL、MariaDB、Db2、TiDB、MongoDB-BI 等;
|
||||
- OLAP 数据库: ClickHouse、Apache Doris、Apache Impala、StarRocks 等;
|
||||
- 数据仓库/数据湖: Amazon RedShift 等;
|
||||
- 数据文件: Excel、CSV 等;
|
||||
- API 数据源。
|
||||
|
||||
## 快速开始
|
||||
|
||||
```
|
||||
# 准备一台 2核4G 以上 Linux 服务器,以 root 运行以下一键安装脚本:
|
||||
# 准备一台 2 核 4G 以上的 Linux 服务器,并以 root 用户运行以下一键安装脚本:
|
||||
|
||||
curl -sSL https://dataease.oss-cn-hangzhou.aliyuncs.com/quick_start_v2.sh | bash
|
||||
|
||||
@ -74,12 +74,12 @@ curl -sSL https://dataease.oss-cn-hangzhou.aliyuncs.com/quick_start_v2.sh | bash
|
||||
- 数据处理:[Apache Calcite](https://github.com/apache/calcite/)、[Apache SeaTunnel](https://github.com/apache/seatunnel)
|
||||
- 基础设施:[Docker](https://www.docker.com/)
|
||||
|
||||
## 我们的其他明星开源项目
|
||||
## 飞致云的其他明星项目
|
||||
|
||||
- [JumpServer](https://github.com/jumpserver/jumpserver/) - 广受欢迎的开源堡垒机
|
||||
- [1Panel](https://github.com/1panel-dev/1panel/) - 现代化、开源的 Linux 服务器运维管理面板
|
||||
- [Halo](https://github.com/halo-dev/halo/) - 强大易用的开源建站工具
|
||||
- [MaxKB](https://github.com/1panel-dev/MaxKB/) - 基于 LLM 大语言模型的开源知识库问答系统
|
||||
- [JumpServer](https://github.com/jumpserver/jumpserver/) - 广受欢迎的开源堡垒机
|
||||
- [Halo](https://github.com/halo-dev/halo/) - 强大易用的开源建站工具
|
||||
- [MeterSphere](https://github.com/metersphere/metersphere/) - 开源的测试管理和接口测试工具
|
||||
|
||||
## License
|
||||
|
||||
@ -14,18 +14,18 @@ public class MybatisPlusGenerator {
|
||||
* 第一 我嫌麻烦
|
||||
* 第二 后面配置会放到nacos读起来更麻烦了
|
||||
*/
|
||||
private static final String url = "jdbc:mysql://localhost:3306/de_standalone?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false";
|
||||
private static final String url = "jdbc:mysql://localhost:3306/dataease?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false";
|
||||
private static final String username = "root";
|
||||
private static final String password = "Password123@mysql";
|
||||
private static final String password = "123456";
|
||||
|
||||
/**
|
||||
* 业务模块例如datasource,dataset,panel等
|
||||
*/
|
||||
private static final String busi = "share";
|
||||
private static final String busi = "visualization";
|
||||
/**
|
||||
* 这是要生成代码的表名称
|
||||
*/
|
||||
private static final String TABLE_NAME = "xpack_share";
|
||||
private static final String TABLE_NAME = "visualization_report_filter";
|
||||
|
||||
/**
|
||||
* 下面两个配置基本上不用动
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package io.dataease.chart.charts;
|
||||
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractChartHandler {
|
||||
public abstract <T> T formatAxis(ChartViewDTO view);
|
||||
public abstract <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult);
|
||||
public abstract <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider provider);
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package io.dataease.chart.charts;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
public class ChartHandlerManager {
|
||||
@Lazy
|
||||
@Resource
|
||||
private DefaultChartHandler defaultChartHandler;
|
||||
private static final ConcurrentHashMap<String, AbstractChartHandler> CHART_HANDLER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
public void registerChartHandler(String render, String type, AbstractChartHandler chartHandler) {
|
||||
CHART_HANDLER_MAP.put(render + "-" + type, chartHandler);
|
||||
}
|
||||
|
||||
public AbstractChartHandler getChartHandler(String render, String type) {
|
||||
var handler = CHART_HANDLER_MAP.get(render + "-" + type);
|
||||
if (handler == null) {
|
||||
return defaultChartHandler;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,495 @@
|
||||
package io.dataease.chart.charts.impl;
|
||||
|
||||
import io.dataease.chart.charts.AbstractChartHandler;
|
||||
import io.dataease.chart.constant.ChartConstants;
|
||||
import io.dataease.chart.manage.ChartViewManege;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.manage.DatasetTableFieldManage;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.constant.SQLConstants;
|
||||
import io.dataease.engine.sql.SQLProvider;
|
||||
import io.dataease.engine.trans.Dimension2SQLObj;
|
||||
import io.dataease.engine.trans.Quota2SQLObj;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.chart.charts.ChartHandlerManager;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.extensions.view.util.ChartDataUtil;
|
||||
import io.dataease.extensions.view.util.FieldUtil;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Component
|
||||
public class DefaultChartHandler extends AbstractChartHandler {
|
||||
@Resource
|
||||
protected ChartHandlerManager chartHandlerManager;
|
||||
@Resource
|
||||
protected DatasetTableFieldManage datasetTableFieldManage;
|
||||
@Resource
|
||||
protected ChartViewManege chartViewManege;
|
||||
@Getter
|
||||
private String render = "antv";
|
||||
@Getter
|
||||
private String type = "*";
|
||||
|
||||
@PostConstruct
|
||||
public void init(){
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), this.getType(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
|
||||
var context = new HashMap<String, Object>();
|
||||
var result = new AxisFormatResult(axisMap, context);
|
||||
axisMap.put(ChartAxis.xAxis, new ArrayList<>(view.getXAxis()));
|
||||
axisMap.put(ChartAxis.yAxis, new ArrayList<>(view.getYAxis()));
|
||||
axisMap.put(ChartAxis.drill, new ArrayList<>(view.getDrillFields()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
return (T) new CustomFilterResult(filterList, formatResult.getContext());
|
||||
}
|
||||
|
||||
public Map<String, Object> buildResult(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);
|
||||
Map<String, Object> result = ChartDataBuild.transChartData(xAxis, yAxis, view, data, isDrill);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
DatasourceRequest datasourceRequest = new DatasourceRequest();
|
||||
datasourceRequest.setDsList(dsMap);
|
||||
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var allFields = getAllChartFields(view);
|
||||
filterResult.getContext().put("allFields", allFields);
|
||||
Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, FieldUtil.transFields(allFields), crossDs, dsMap);
|
||||
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap);
|
||||
String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
|
||||
querySql = SqlUtils.rebuildSQL(querySql, sqlMeta, crossDs, dsMap);
|
||||
datasourceRequest.setQuery(querySql);
|
||||
List<String[]> data = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
|
||||
//自定义排序
|
||||
data = ChartDataUtil.resultCustomSort(xAxis, data);
|
||||
//快速计算
|
||||
quickCalc(xAxis, yAxis, data);
|
||||
//数据重组逻辑可重载
|
||||
var result = this.buildResult(view, formatResult, filterResult, data);
|
||||
T calcResult = (T) new ChartCalcDataResult();
|
||||
calcResult.setData(result);
|
||||
calcResult.setContext(filterResult.getContext());
|
||||
calcResult.setQuerySql(querySql);
|
||||
calcResult.setOriginData(data);
|
||||
return calcResult;
|
||||
}
|
||||
|
||||
protected List<ChartViewFieldDTO> getAllChartFields(ChartViewDTO view) {
|
||||
// get all fields
|
||||
Map<String, List<ChartViewFieldDTO>> stringListMap = chartViewManege.listByDQ(view.getTableId(), view.getId(), view);
|
||||
List<ChartViewFieldDTO> dimensionList = stringListMap.get("dimensionList");
|
||||
List<ChartViewFieldDTO> quotaList = stringListMap.get("quotaList");
|
||||
List<ChartViewFieldDTO> allFields = new ArrayList<>();
|
||||
allFields.addAll(dimensionList);
|
||||
allFields.addAll(quotaList);
|
||||
return allFields.stream().filter(ele -> ele.getId() != -1L).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected List<ChartSeniorAssistDTO> getDynamicAssistFields(ChartViewDTO view) throws Exception {
|
||||
List<ChartSeniorAssistDTO> list = new ArrayList<>();
|
||||
|
||||
Map<String, Object> senior = view.getSenior();
|
||||
if (ObjectUtils.isEmpty(senior)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
ChartSeniorAssistCfgDTO assistLineCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("assistLineCfg")), ChartSeniorAssistCfgDTO.class);
|
||||
if (null == assistLineCfg || !assistLineCfg.isEnable()) {
|
||||
return list;
|
||||
}
|
||||
List<ChartSeniorAssistDTO> assistLines = assistLineCfg.getAssistLine();
|
||||
|
||||
if (ObjectUtils.isEmpty(assistLines)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
for (ChartSeniorAssistDTO dto : assistLines) {
|
||||
if (StringUtils.equalsIgnoreCase(dto.getField(), "0")) {
|
||||
continue;
|
||||
}
|
||||
Long fieldId = dto.getFieldId();
|
||||
String summary = dto.getSummary();
|
||||
if (ObjectUtils.isEmpty(fieldId) || StringUtils.isEmpty(summary)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DatasetTableFieldDTO datasetTableFieldDTO = datasetTableFieldManage.selectById(fieldId);
|
||||
|
||||
if (ObjectUtils.isEmpty(datasetTableFieldDTO)) {
|
||||
continue;
|
||||
}
|
||||
list.add(dto);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected List<ChartViewFieldDTO> getAssistFields(List<ChartSeniorAssistDTO> list, List<ChartViewFieldDTO> yAxis) {
|
||||
List<ChartViewFieldDTO> res = new ArrayList<>();
|
||||
for (ChartSeniorAssistDTO dto : list) {
|
||||
DatasetTableFieldDTO curField = dto.getCurField();
|
||||
ChartViewFieldDTO yField = null;
|
||||
String alias = "";
|
||||
for (int i = 0; i < yAxis.size(); i++) {
|
||||
ChartViewFieldDTO field = yAxis.get(i);
|
||||
if (Objects.equals(field.getId(), curField.getId())) {
|
||||
yField = field;
|
||||
alias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ObjectUtils.isEmpty(yField)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ChartViewFieldDTO chartViewFieldDTO = new ChartViewFieldDTO();
|
||||
BeanUtils.copyBean(chartViewFieldDTO, curField);
|
||||
chartViewFieldDTO.setSummary(dto.getSummary());
|
||||
chartViewFieldDTO.setOriginName(alias);// yAxis的字段别名,就是查找的字段名
|
||||
res.add(chartViewFieldDTO);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
protected String assistSQL(String sql, List<ChartViewFieldDTO> assistFields) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < assistFields.size(); i++) {
|
||||
ChartViewFieldDTO dto = assistFields.get(i);
|
||||
if (i == (assistFields.size() - 1)) {
|
||||
stringBuilder.append(dto.getSummary() + "(" + dto.getOriginName() + ")");
|
||||
} else {
|
||||
stringBuilder.append(dto.getSummary() + "(" + dto.getOriginName() + "),");
|
||||
}
|
||||
}
|
||||
return "SELECT " + stringBuilder + " FROM (" + sql + ") tmp";
|
||||
}
|
||||
|
||||
protected void quickCalc(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, List<String[]> data) {
|
||||
for (int i = 0; i < yAxis.size(); i++) {
|
||||
ChartViewFieldDTO chartViewFieldDTO = yAxis.get(i);
|
||||
ChartFieldCompareDTO compareCalc = chartViewFieldDTO.getCompareCalc();
|
||||
if (ObjectUtils.isEmpty(compareCalc)) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(compareCalc.getType())
|
||||
&& !StringUtils.equalsIgnoreCase(compareCalc.getType(), "none")) {
|
||||
Long compareFieldId = compareCalc.getField();// 选中字段
|
||||
// 数据字段下标
|
||||
int dataIndex = xAxis.size() + i;
|
||||
if (Arrays.asList(ChartConstants.M_Y).contains(compareCalc.getType())) {
|
||||
String resultData = compareCalc.getResultData();// 数据设置
|
||||
// 获取选中字段以及下标
|
||||
List<ChartViewFieldDTO> checkedField = new ArrayList<>(xAxis);
|
||||
int timeIndex = 0;// 时间字段下标
|
||||
ChartViewFieldDTO timeField = null;
|
||||
for (int j = 0; j < checkedField.size(); j++) {
|
||||
if (Objects.equals(checkedField.get(j).getId(), compareFieldId)) {
|
||||
timeIndex = j;
|
||||
timeField = checkedField.get(j);
|
||||
}
|
||||
}
|
||||
// 无选中字段,或者选中字段已经不在维度list中,或者选中字段日期格式不符合对比类型的,直接将对应数据置为null
|
||||
if (ObjectUtils.isEmpty(timeField) || !checkCalcType(timeField.getDateStyle(), compareCalc.getType())) {
|
||||
// set null
|
||||
for (String[] item : data) {
|
||||
item[dataIndex] = null;
|
||||
}
|
||||
} else {
|
||||
// 计算 同比/环比
|
||||
// 1,处理当期数据;2,根据type计算上一期数据;3,根据resultData计算结果
|
||||
Map<String, String> currentMap = new LinkedHashMap<>();
|
||||
for (String[] item : data) {
|
||||
String[] dimension = Arrays.copyOfRange(item, 0, checkedField.size());
|
||||
currentMap.put(StringUtils.join(dimension, "-"), item[dataIndex]);
|
||||
}
|
||||
|
||||
for (int index = 0; index < data.size(); index++) {
|
||||
String[] item = data.get(index);
|
||||
String cTime = item[timeIndex];
|
||||
String cValue = item[dataIndex];
|
||||
|
||||
// 获取计算后的时间,并且与所有维度拼接
|
||||
String lastTime = calcLastTime(cTime, compareCalc.getType(), timeField.getDateStyle(), timeField.getDatePattern());
|
||||
String[] dimension = Arrays.copyOfRange(item, 0, checkedField.size());
|
||||
dimension[timeIndex] = lastTime;
|
||||
|
||||
String lastValue = currentMap.get(StringUtils.join(dimension, "-"));
|
||||
if (StringUtils.isEmpty(cValue) || StringUtils.isEmpty(lastValue)) {
|
||||
item[dataIndex] = null;
|
||||
} else {
|
||||
if (StringUtils.equalsIgnoreCase(resultData, "sub")) {
|
||||
item[dataIndex] = new BigDecimal(cValue).subtract(new BigDecimal(lastValue)).toString();
|
||||
} else if (StringUtils.equalsIgnoreCase(resultData, "percent")) {
|
||||
if (new BigDecimal(lastValue).compareTo(BigDecimal.ZERO) == 0) {
|
||||
item[dataIndex] = null;
|
||||
} else {
|
||||
item[dataIndex] = new BigDecimal(cValue)
|
||||
.divide(new BigDecimal(lastValue).abs(), 8, RoundingMode.HALF_UP)
|
||||
.subtract(new BigDecimal(1))
|
||||
.setScale(8, RoundingMode.HALF_UP)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (StringUtils.equalsIgnoreCase(compareCalc.getType(), "percent")) {
|
||||
// 求和
|
||||
BigDecimal sum = new BigDecimal(0);
|
||||
for (int index = 0; index < data.size(); index++) {
|
||||
String[] item = data.get(index);
|
||||
String cValue = item[dataIndex];
|
||||
if (StringUtils.isEmpty(cValue)) {
|
||||
continue;
|
||||
}
|
||||
sum = sum.add(new BigDecimal(cValue));
|
||||
}
|
||||
// 计算占比
|
||||
for (int index = 0; index < data.size(); index++) {
|
||||
String[] item = data.get(index);
|
||||
String cValue = item[dataIndex];
|
||||
if (StringUtils.isEmpty(cValue)) {
|
||||
continue;
|
||||
}
|
||||
item[dataIndex] = new BigDecimal(cValue)
|
||||
.divide(sum, 8, RoundingMode.HALF_UP)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String calcLastTime(String cTime, String type, String dateStyle, String datePattern) {
|
||||
try {
|
||||
String lastTime = null;
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (StringUtils.equalsIgnoreCase(type, ChartConstants.YEAR_MOM)) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy");
|
||||
Date date = simpleDateFormat.parse(cTime);
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.YEAR, -1);
|
||||
lastTime = simpleDateFormat.format(calendar.getTime());
|
||||
} else if (StringUtils.equalsIgnoreCase(type, ChartConstants.MONTH_MOM)) {
|
||||
SimpleDateFormat simpleDateFormat = null;
|
||||
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy/MM");
|
||||
} else {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy-MM");
|
||||
}
|
||||
Date date = simpleDateFormat.parse(cTime);
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
lastTime = simpleDateFormat.format(calendar.getTime());
|
||||
} else if (StringUtils.equalsIgnoreCase(type, ChartConstants.YEAR_YOY)) {
|
||||
SimpleDateFormat simpleDateFormat = null;
|
||||
if (StringUtils.equalsIgnoreCase(dateStyle, "y_M")) {
|
||||
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy/MM");
|
||||
} else {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy-MM");
|
||||
}
|
||||
} else if (StringUtils.equalsIgnoreCase(dateStyle, "y_M_d")) {
|
||||
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
|
||||
} else {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
Date date = simpleDateFormat.parse(cTime);
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.YEAR, -1);
|
||||
lastTime = simpleDateFormat.format(calendar.getTime());
|
||||
} else if (StringUtils.equalsIgnoreCase(type, ChartConstants.DAY_MOM)) {
|
||||
SimpleDateFormat simpleDateFormat = null;
|
||||
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
|
||||
} else {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
}
|
||||
Date date = simpleDateFormat.parse(cTime);
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
lastTime = simpleDateFormat.format(calendar.getTime());
|
||||
} else if (StringUtils.equalsIgnoreCase(type, ChartConstants.MONTH_YOY)) {
|
||||
SimpleDateFormat simpleDateFormat = null;
|
||||
if (StringUtils.equalsIgnoreCase(dateStyle, "y_M")) {
|
||||
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy/MM");
|
||||
} else {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy-MM");
|
||||
}
|
||||
} else if (StringUtils.equalsIgnoreCase(dateStyle, "y_M_d")) {
|
||||
if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
|
||||
} else {
|
||||
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
Date date = simpleDateFormat.parse(cTime);
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
lastTime = simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return lastTime;
|
||||
} catch (Exception e) {
|
||||
return cTime;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkCalcType(String dateStyle, String calcType) {
|
||||
switch (dateStyle) {
|
||||
case "y":
|
||||
return StringUtils.equalsIgnoreCase(calcType, "year_mom");
|
||||
case "y_M":
|
||||
return StringUtils.equalsIgnoreCase(calcType, "month_mom")
|
||||
|| StringUtils.equalsIgnoreCase(calcType, "year_yoy");
|
||||
case "y_M_d":
|
||||
return StringUtils.equalsIgnoreCase(calcType, "day_mom")
|
||||
|| StringUtils.equalsIgnoreCase(calcType, "month_yoy")
|
||||
|| StringUtils.equalsIgnoreCase(calcType, "year_yoy");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean checkYoyFilter(List<ChartExtFilterDTO> filter, List<ChartViewFieldDTO> yoyAxis){
|
||||
boolean flag = false;
|
||||
for (ChartExtFilterDTO filterDTO : filter) {
|
||||
for (ChartViewFieldDTO chartViewFieldDTO : yoyAxis) {
|
||||
ChartFieldCompareDTO compareCalc = chartViewFieldDTO.getCompareCalc();
|
||||
if (ObjectUtils.isEmpty(compareCalc)) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(compareCalc.getType())
|
||||
&& !StringUtils.equalsIgnoreCase(compareCalc.getType(), "none")) {
|
||||
if (Arrays.asList(ChartConstants.M_Y).contains(compareCalc.getType())) {
|
||||
if (StringUtils.equalsIgnoreCase(compareCalc.getField() + "", filterDTO.getFieldId()) && filterDTO.getFilterType() == 0) {
|
||||
// -1 year
|
||||
try {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date(Long.parseLong(filterDTO.getValue().getFirst())));
|
||||
calendar.add(Calendar.YEAR, -1);
|
||||
filterDTO.getValue().set(0, String.valueOf(calendar.getTime().getTime()));
|
||||
flag = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
};
|
||||
|
||||
protected void groupStackDrill(List<ChartViewFieldDTO> xAxis,
|
||||
List<ChartExtFilterDTO> filterList,
|
||||
List<ChartViewFieldDTO> fieldsToFilter,
|
||||
List<ChartViewFieldDTO> drillFields,
|
||||
List<ChartDrillRequest> drillRequestList) {
|
||||
var fields = xAxis.stream().map(ChartViewFieldDTO::getId).collect(Collectors.toSet());
|
||||
ChartDrillRequest head = drillRequestList.get(0);
|
||||
Map<Long, String> dimValMap = new HashMap<>();
|
||||
head.getDimensionList().forEach(item -> dimValMap.put(item.getId(), item.getValue()));
|
||||
Map<Long, ChartViewFieldDTO> fieldMap = xAxis.stream().collect(Collectors.toMap(ChartViewFieldDTO::getId, o -> o, ((p, n) -> p)));
|
||||
for (int i = 0; i < drillRequestList.size(); i++) {
|
||||
ChartDrillRequest request = drillRequestList.get(i);
|
||||
ChartViewFieldDTO chartViewFieldDTO = drillFields.get(i);
|
||||
for (ChartDimensionDTO requestDimension : request.getDimensionList()) {
|
||||
// 将钻取值作为条件传递,将所有钻取字段作为xAxis并加上下一个钻取字段
|
||||
if (Objects.equals(requestDimension.getId(), chartViewFieldDTO.getId())) {
|
||||
fieldsToFilter.add(chartViewFieldDTO);
|
||||
dimValMap.put(requestDimension.getId(), requestDimension.getValue());
|
||||
if (!fields.contains(requestDimension.getId())) {
|
||||
fieldMap.put(chartViewFieldDTO.getId(), chartViewFieldDTO);
|
||||
chartViewFieldDTO.setSource(FieldSource.DRILL);
|
||||
xAxis.add(chartViewFieldDTO);
|
||||
fields.add(requestDimension.getId());
|
||||
}
|
||||
if (i == drillRequestList.size() - 1) {
|
||||
ChartViewFieldDTO nextDrillField = drillFields.get(i + 1);
|
||||
if (!fields.contains(nextDrillField.getId())) {
|
||||
// get drill list first element's sort,then assign to nextDrillField
|
||||
nextDrillField.setSort(getDrillSort(xAxis, drillFields.get(0)));
|
||||
nextDrillField.setSource(FieldSource.DRILL);
|
||||
xAxis.add(nextDrillField);
|
||||
fields.add(nextDrillField.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < fieldsToFilter.size(); i++) {
|
||||
ChartViewFieldDTO tmpField = fieldsToFilter.get(i);
|
||||
ChartExtFilterDTO tmpFilter = new ChartExtFilterDTO();
|
||||
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(tmpField.getId());
|
||||
tmpFilter.setDatasetTableField(datasetTableField);
|
||||
tmpFilter.setDateStyle(fieldMap.get(tmpField.getId()).getDateStyle());
|
||||
tmpFilter.setDatePattern(fieldMap.get(tmpField.getId()).getDatePattern());
|
||||
tmpFilter.setFieldId(String.valueOf(tmpField.getId()));
|
||||
tmpFilter.setFilterType(1);
|
||||
if (datasetTableField.getDeType() == 1) {
|
||||
tmpFilter.setOperator("between");
|
||||
// 把value类似过滤组件处理,获得start time和end time
|
||||
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(dimValMap.get(tmpField.getId()));
|
||||
tmpFilter.setValue(Arrays.asList(String.valueOf(stringLongMap.get("startTime")), String.valueOf(stringLongMap.get("endTime"))));
|
||||
} else {
|
||||
tmpFilter.setOperator("in");
|
||||
tmpFilter.setValue(Collections.singletonList(dimValMap.get(tmpField.getId())));
|
||||
}
|
||||
filterList.add(tmpFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDrillSort(List<ChartViewFieldDTO> xAxis, ChartViewFieldDTO field) {
|
||||
String res = "";
|
||||
for (ChartViewFieldDTO f : xAxis) {
|
||||
if (Objects.equals(f.getId(), field.getId())) {
|
||||
if (StringUtils.equalsIgnoreCase(f.getSort(), "asc") || StringUtils.equalsIgnoreCase(f.getSort(), "desc")) {
|
||||
res = f.getSort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package io.dataease.chart.charts.impl;
|
||||
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ExtQuotaChartHandler extends DefaultChartHandler {
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package io.dataease.chart.charts.impl;
|
||||
|
||||
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GroupChartHandler extends DefaultChartHandler {
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var xAxis = new ArrayList<ChartViewFieldDTO>(view.getXAxis());
|
||||
xAxis.addAll(view.getXAxisExt());
|
||||
result.getAxisMap().put(ChartAxis.xAxis, xAxis);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
package io.dataease.chart.charts.impl;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.sql.SQLProvider;
|
||||
import io.dataease.engine.trans.ExtWhere2Str;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.extensions.view.util.FieldUtil;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 带同环比计算的图表处理器
|
||||
*/
|
||||
public class YoyChartHandler extends DefaultChartHandler {
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
String originFilterJson = (String) JsonUtil.toJSONString(filterList);
|
||||
// 如果设置了同环比的指标字段设置了过滤器,那就需要把该过滤器的时间往前回调一年
|
||||
// 计算完同环比之后,再把计算结果和原有的过滤结果对比,去除不该出现的前一年的数据
|
||||
boolean yoyFiltered = checkYoyFilter(filterList, yAxis);
|
||||
if (yoyFiltered) {
|
||||
List<ChartExtFilterDTO> originFilter = JsonUtil.parseList(originFilterJson, new TypeReference<>() {
|
||||
});
|
||||
formatResult.getContext().put("originFilter", originFilter);
|
||||
formatResult.getContext().put("yoyFiltered", true);
|
||||
}
|
||||
return (T) new CustomFilterResult(filterList, formatResult.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> buildResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
|
||||
var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null;
|
||||
// 带过滤同环比直接返回原始数据,再由视图重新组装
|
||||
if (yoyFiltered) {
|
||||
var result = new HashMap<String, Object>();
|
||||
result.put("data", data);
|
||||
return result;
|
||||
}
|
||||
return buildNormalResult(view, formatResult, filterResult, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建同环比类型的数据
|
||||
* @param view 视图对象
|
||||
* @param formatResult 处理后的轴
|
||||
* @param filterResult 处理后的过滤器
|
||||
* @param data 原始数据
|
||||
* @return 视图构建结果
|
||||
*/
|
||||
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
|
||||
return super.buildResult(view, formatResult, filterResult, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
// 这里拿到的可能有一年前的数据
|
||||
var expandedResult = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
|
||||
// 检查同环比过滤,拿到实际数据
|
||||
var yoyFiltered = filterResult.getContext().get("yoyFiltered") != null;
|
||||
if (yoyFiltered) {
|
||||
var originFilter = (List<ChartExtFilterDTO>) filterResult.getContext().get("originFilter");
|
||||
var allFields = (List<ChartViewFieldDTO>) filterResult.getContext().get("allFields");
|
||||
ExtWhere2Str.extWhere2sqlOjb(sqlMeta, originFilter, FieldUtil.transFields(allFields), crossDs, dsMap);
|
||||
var originSql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
|
||||
originSql = SqlUtils.rebuildSQL(originSql, sqlMeta, crossDs, dsMap);
|
||||
var request = new DatasourceRequest();
|
||||
request.setDsList(dsMap);
|
||||
request.setQuery(originSql);
|
||||
// 实际过滤后的数据
|
||||
var originData = (List<String[]>) provider.fetchResultField(request).get("data");
|
||||
List<String[]> resultData = new ArrayList<>();
|
||||
// 包含一年前的数据, 已计算同环比
|
||||
var yoyData = (List<String[]>) expandedResult.getData().get("data");
|
||||
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
|
||||
// 对比维度,只保留实际过滤后的数据
|
||||
for (String[] yoyDataLine : yoyData) {
|
||||
StringBuilder x1 = new StringBuilder();
|
||||
for (int i = 0; i < xAxis.size(); i++) {
|
||||
x1.append(yoyDataLine[i]);
|
||||
}
|
||||
for (String[] originDataLine : originData) {
|
||||
StringBuilder x2 = new StringBuilder();
|
||||
for (int i = 0; i < xAxis.size(); i++) {
|
||||
x2.append(originDataLine[i]);
|
||||
}
|
||||
if (StringUtils.equals(x1, x2)) {
|
||||
resultData.add(yoyDataLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
yoyData.clear();
|
||||
yoyData.addAll(resultData);
|
||||
var result = this.buildNormalResult(view, formatResult, filterResult, yoyData);
|
||||
expandedResult.setData(result);
|
||||
expandedResult.setOriginData(originData);
|
||||
expandedResult.setQuerySql(originSql);
|
||||
}
|
||||
return expandedResult;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.chart.constant.ChartConstants;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.sql.SQLProvider;
|
||||
import io.dataease.engine.trans.ExtWhere2Str;
|
||||
import io.dataease.engine.utils.SQLUtils;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.extensions.view.util.FieldUtil;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class BarHandler extends YoyChartHandler {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "bar", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "bar-horizontal", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
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.setDsList(dsMap);
|
||||
var assistSql = assistSQL(originSql, assistFields);
|
||||
req.setQuery(assistSql);
|
||||
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
|
||||
result.setAssistData(assistData);
|
||||
result.setDynamicAssistFields(dynamicAssistFields);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class BidirectionalBarHandler extends ProgressBarHandler {
|
||||
@Getter
|
||||
private String type = "bidirectional-bar";
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Component
|
||||
public class GroupBarHandler extends BarHandler {
|
||||
@Getter
|
||||
private String type = "bar-group";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
|
||||
xAxis.addAll(view.getXAxisExt());
|
||||
result.getAxisMap().put(ChartAxis.xAxisExt, view.getXAxisExt());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), this.getType(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
var result = super.customFilter(view, filterList, formatResult);
|
||||
List<ChartDrillRequest> drillRequestList = view.getChartExtRequest().getDrill();
|
||||
var drillFields = formatResult.getAxisMap().get(ChartAxis.drill);
|
||||
// 分组维度下钻
|
||||
if (ObjectUtils.isNotEmpty(drillRequestList) && (drillFields.size() > drillRequestList.size())) {
|
||||
List<ChartExtFilterDTO> noDrillFilterList = filterList
|
||||
.stream()
|
||||
.filter(ele -> ele.getFilterType() != 1)
|
||||
.collect(Collectors.toList());
|
||||
var noDrillFieldAxis = formatResult.getAxisMap().get(ChartAxis.xAxis)
|
||||
.stream()
|
||||
.filter(ele -> ele.getSource() != FieldSource.DRILL)
|
||||
.collect(Collectors.toList());
|
||||
List<ChartExtFilterDTO> drillFilters = new ArrayList<>();
|
||||
ArrayList<ChartViewFieldDTO> fieldsToFilter = new ArrayList<>();
|
||||
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
|
||||
if (ObjectUtils.isNotEmpty(xAxisExt) &&
|
||||
Objects.equals(drillFields.get(0).getId(), xAxisExt.get(0).getId())) {
|
||||
fieldsToFilter.addAll(view.getXAxis());
|
||||
}
|
||||
groupStackDrill(noDrillFieldAxis, noDrillFilterList, fieldsToFilter, drillFields, drillRequestList);
|
||||
formatResult.getAxisMap().put(ChartAxis.xAxis, noDrillFieldAxis);
|
||||
result.setFilterList(noDrillFilterList);
|
||||
}
|
||||
return (T) 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 xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size());
|
||||
return ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ProgressBarHandler extends BarHandler {
|
||||
@Getter
|
||||
private String type = "progress-bar";
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), this.getType(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = new ArrayList<>(view.getYAxis());
|
||||
yAxis.addAll(view.getYAxisExt());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
|
||||
result.getAxisMap().put(ChartAxis.yAxisExt, view.getYAxisExt());
|
||||
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);
|
||||
Map<String, Object> result = ChartDataBuild.transMixChartDataAntV(xAxis, xAxis, new ArrayList<>(), yAxis, view, data, isDrill);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class RangeBarHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "bar-range";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = new ArrayList<ChartViewFieldDTO>();
|
||||
var xAxis = new ArrayList<ChartViewFieldDTO>(view.getXAxis());
|
||||
boolean skipBarRange = false;
|
||||
boolean barRangeDate = false;
|
||||
if (CollectionUtils.isNotEmpty(view.getYAxis()) && CollectionUtils.isNotEmpty(view.getYAxisExt())) {
|
||||
ChartViewFieldDTO axis1 = view.getYAxis().get(0);
|
||||
ChartViewFieldDTO axis2 = view.getYAxisExt().get(0);
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(axis1.getGroupType(), "q") && StringUtils.equalsIgnoreCase(axis2.getGroupType(), "q")) {
|
||||
yAxis.add(axis1);
|
||||
yAxis.add(axis2);
|
||||
} else if (StringUtils.equalsIgnoreCase(axis1.getGroupType(), "d") && axis1.getDeType() == 1 && StringUtils.equalsIgnoreCase(axis2.getGroupType(), "d") && axis2.getDeType() == 1) {
|
||||
barRangeDate = true;
|
||||
if (BooleanUtils.isTrue(view.getAggregate())) {
|
||||
axis1.setSummary("min");
|
||||
axis2.setSummary("max");
|
||||
yAxis.add(axis1);
|
||||
yAxis.add(axis2);
|
||||
} else {
|
||||
xAxis.add(axis1);
|
||||
xAxis.add(axis2);
|
||||
}
|
||||
} else {
|
||||
skipBarRange = true;
|
||||
}
|
||||
} else {
|
||||
skipBarRange = true;
|
||||
}
|
||||
result.getContext().put("skipBarRange", skipBarRange);
|
||||
result.getContext().put("barRangeDate", barRangeDate);
|
||||
result.getAxisMap().put(ChartAxis.xAxis, xAxis);
|
||||
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
|
||||
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);
|
||||
var skipBarRange = (boolean) formatResult.getContext().get("skipBarRange");
|
||||
var barRangeDate = (boolean) formatResult.getContext().get("barRangeDate");
|
||||
Map<String, Object> result = ChartDataBuild.transBarRangeDataAntV(skipBarRange, barRangeDate, xAxis, xAxis, yAxis, view, data, isDrill);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider provider) {
|
||||
sqlMeta.setChartType(this.type);
|
||||
return super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class StackBarHandler extends BarHandler {
|
||||
@Getter
|
||||
private String type = "bar-stack";
|
||||
@Override
|
||||
public void init() {
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "bar-stack", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "bar-stack-horizontal", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "percentage-bar-stack", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "percentage-bar-stack-horizontal", this);
|
||||
}
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
|
||||
xAxis.addAll(view.getExtStack());
|
||||
result.getAxisMap().put(ChartAxis.extStack, view.getExtStack());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
var result = super.customFilter(view, filterList, formatResult);
|
||||
List<ChartDrillRequest> drillRequestList = view.getChartExtRequest().getDrill();
|
||||
var drillFields = formatResult.getAxisMap().get(ChartAxis.drill);
|
||||
// 堆叠维度下钻
|
||||
if (ObjectUtils.isNotEmpty(drillRequestList) && (drillFields.size() > drillRequestList.size())) {
|
||||
List<ChartExtFilterDTO> noDrillFilterList = filterList
|
||||
.stream()
|
||||
.filter(ele -> ele.getFilterType() != 1)
|
||||
.collect(Collectors.toList());
|
||||
var noDrillFieldAxis = formatResult.getAxisMap().get(ChartAxis.xAxis)
|
||||
.stream()
|
||||
.filter(ele -> ele.getSource() != FieldSource.DRILL)
|
||||
.collect(Collectors.toList());
|
||||
List<ChartExtFilterDTO> drillFilters = new ArrayList<>();
|
||||
ArrayList<ChartViewFieldDTO> fieldsToFilter = new ArrayList<>();
|
||||
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
if (ObjectUtils.isNotEmpty(extStack) &&
|
||||
Objects.equals(drillFields.get(0).getId(), extStack.get(0).getId())) {
|
||||
fieldsToFilter.addAll(view.getXAxis());
|
||||
}
|
||||
groupStackDrill(noDrillFieldAxis, noDrillFilterList, fieldsToFilter, drillFields, drillRequestList);
|
||||
formatResult.getAxisMap().put(ChartAxis.xAxis, noDrillFieldAxis);
|
||||
result.setFilterList(noDrillFilterList);
|
||||
}
|
||||
return (T) 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 extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var xAxisBase = xAxis.subList(0, xAxis.size() - extStack.size());
|
||||
return ChartDataBuild.transStackChartDataAntV(xAxisBase, yAxis, view, data, extStack, isDrill);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package io.dataease.chart.charts.impl.bar;
|
||||
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.dataease.extensions.view.dto.ChartAxis.extStack;
|
||||
import static io.dataease.extensions.view.dto.ChartAxis.xAxisExt;
|
||||
|
||||
@Component
|
||||
public class StackGroupBarHandler extends BarHandler {
|
||||
@Getter
|
||||
private String type = "bar-group-stack";
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), this.getType(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
|
||||
xAxis.addAll(view.getXAxisExt());
|
||||
xAxis.addAll(view.getExtStack());
|
||||
result.getAxisMap().put(ChartAxis.xAxisExt, view.getExtStack());
|
||||
result.getAxisMap().put(ChartAxis.extStack, view.getExtStack());
|
||||
result.getAxisMap().put(ChartAxis.xAxisExt, view.getXAxisExt());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
var result = super.customFilter(view, filterList, formatResult);
|
||||
List<ChartDrillRequest> drillRequestList = view.getChartExtRequest().getDrill();
|
||||
var drillFields = formatResult.getAxisMap().get(ChartAxis.drill);
|
||||
// 分组维度下钻
|
||||
if (ObjectUtils.isNotEmpty(drillRequestList) && (drillFields.size() > drillRequestList.size())) {
|
||||
List<ChartExtFilterDTO> noDrillFilterList = filterList
|
||||
.stream()
|
||||
.filter(ele -> ele.getFilterType() != 1)
|
||||
.collect(Collectors.toList());
|
||||
var noDrillFieldAxis = formatResult.getAxisMap().get(ChartAxis.xAxis)
|
||||
.stream()
|
||||
.filter(ele -> ele.getSource() != FieldSource.DRILL)
|
||||
.collect(Collectors.toList());
|
||||
List<ChartExtFilterDTO> drillFilters = new ArrayList<>();
|
||||
ArrayList<ChartViewFieldDTO> fieldsToFilter = new ArrayList<>();
|
||||
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
|
||||
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
if (ObjectUtils.isNotEmpty(xAxisExt) && ObjectUtils.isNotEmpty(extStack)) {
|
||||
if (Objects.equals(drillFields.get(0).getId(), xAxisExt.get(0).getId())) {
|
||||
fieldsToFilter.addAll(view.getXAxis());
|
||||
fieldsToFilter.addAll(extStack);
|
||||
}
|
||||
if (Objects.equals(drillFields.get(0).getId(), extStack.get(0).getId())) {
|
||||
fieldsToFilter.addAll(view.getXAxis());
|
||||
fieldsToFilter.addAll(xAxisExt);
|
||||
}
|
||||
}
|
||||
groupStackDrill(noDrillFieldAxis, noDrillFilterList, fieldsToFilter, drillFields, drillRequestList);
|
||||
formatResult.getAxisMap().put(ChartAxis.xAxis, noDrillFieldAxis);
|
||||
result.setFilterList(noDrillFilterList);
|
||||
}
|
||||
return (T) 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 xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
|
||||
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size() - extStack.size());
|
||||
var xAxisMain = xAxis.subList(0, xAxis.size() - extStack.size());
|
||||
return ChartDataBuild.transGroupStackDataAntV(xAxisBase, xAxisMain, xAxisExt, yAxis, extStack, data, view, isDrill);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package io.dataease.chart.charts.impl.line;
|
||||
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class AreaHandler extends LineHandler {
|
||||
@Getter
|
||||
private String type = "area";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
result.getAxisMap().put(ChartAxis.xAxis, view.getXAxis());
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
package io.dataease.chart.charts.impl.line;
|
||||
|
||||
import io.dataease.chart.charts.impl.GroupChartHandler;
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class LineHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "line";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
|
||||
xAxis.addAll(view.getXAxisExt());
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.xAxisExt, view.getXAxisExt());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
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 xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size());
|
||||
return ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
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.setDsList(dsMap);
|
||||
var assistSql = assistSQL(originSql, assistFields);
|
||||
req.setQuery(assistSql);
|
||||
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
|
||||
result.setAssistData(assistData);
|
||||
result.setDynamicAssistFields(dynamicAssistFields);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
package io.dataease.chart.charts.impl.line;
|
||||
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class StackAreaHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "area-stack";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var xAxis = result.getAxisMap().get(ChartAxis.xAxis);
|
||||
xAxis.addAll(view.getExtStack());
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.extStack, view.getExtStack());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
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 extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
var axisBase = xAxis.subList(0, xAxis.size() - extStack.size());
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
return ChartDataBuild.transStackChartDataAntV(axisBase, yAxis, view, data, extStack, isDrill);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
var result = super.customFilter(view, filterList, formatResult);
|
||||
List<ChartDrillRequest> drillRequestList = view.getChartExtRequest().getDrill();
|
||||
var drillFields = formatResult.getAxisMap().get(ChartAxis.drill);
|
||||
// 堆叠维度下钻
|
||||
if (ObjectUtils.isNotEmpty(drillRequestList) && (drillFields.size() > drillRequestList.size())) {
|
||||
List<ChartExtFilterDTO> noDrillFilterList = filterList
|
||||
.stream()
|
||||
.filter(ele -> ele.getFilterType() != 1)
|
||||
.collect(Collectors.toList());
|
||||
var noDrillFieldAxis = formatResult.getAxisMap().get(ChartAxis.xAxis)
|
||||
.stream()
|
||||
.filter(ele -> ele.getSource() != FieldSource.DRILL)
|
||||
.collect(Collectors.toList());
|
||||
List<ChartExtFilterDTO> drillFilters = new ArrayList<>();
|
||||
ArrayList<ChartViewFieldDTO> fieldsToFilter = new ArrayList<>();
|
||||
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
if (ObjectUtils.isNotEmpty(extStack) &&
|
||||
Objects.equals(drillFields.get(0).getId(), extStack.get(0).getId())) {
|
||||
fieldsToFilter.addAll(view.getXAxis());
|
||||
}
|
||||
groupStackDrill(noDrillFieldAxis, noDrillFilterList, fieldsToFilter, drillFields, drillRequestList);
|
||||
formatResult.getAxisMap().put(ChartAxis.xAxis, noDrillFieldAxis);
|
||||
result.setFilterList(noDrillFilterList);
|
||||
}
|
||||
return (T) result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
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.setDsList(dsMap);
|
||||
var assistSql = assistSQL(originSql, assistFields);
|
||||
req.setQuery(assistSql);
|
||||
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
|
||||
result.setAssistData(assistData);
|
||||
result.setDynamicAssistFields(dynamicAssistFields);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package io.dataease.chart.charts.impl.map;
|
||||
|
||||
import io.dataease.chart.charts.impl.GroupChartHandler;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class FlowMapHandler extends GroupChartHandler {
|
||||
@Getter
|
||||
private String type = "flow-map";
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package io.dataease.chart.charts.impl.map;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class HeatMapHandler extends DefaultChartHandler {
|
||||
@Getter
|
||||
private String type = "heat-map";
|
||||
|
||||
@Override
|
||||
public Map<String, Object> buildResult(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);
|
||||
Map<String, Object> result = ChartDataBuild.transHeatMapChartDataAntV(xAxis, xAxis, yAxis, view, data, isDrill);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package io.dataease.chart.charts.impl.map;
|
||||
|
||||
import io.dataease.chart.charts.impl.ExtQuotaChartHandler;
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class MapHandler extends ExtQuotaChartHandler {
|
||||
@Getter
|
||||
private String type = "map";
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package io.dataease.chart.charts.impl.map;
|
||||
|
||||
import io.dataease.chart.charts.impl.GroupChartHandler;
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SymbolicMapHandler extends GroupChartHandler {
|
||||
@Getter
|
||||
private String type = "symbolic-map";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtBubble());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package io.dataease.chart.charts.impl.mix;
|
||||
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ChartMixHandler extends DefaultChartHandler {
|
||||
@Getter
|
||||
private final String type = "chart-mix";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package io.dataease.chart.charts.impl.numberic;
|
||||
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.dataset.manage.DatasetTableFieldManage;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class GaugeHandler extends NumbericChartHandler {
|
||||
@Getter
|
||||
private String type = "gauge";
|
||||
@Resource
|
||||
private DatasetTableFieldManage datasetTableFieldManage;
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
|
||||
var yAxis = new ArrayList<>(view.getYAxis());
|
||||
Map<String, Object> customAttr = view.getCustomAttr();
|
||||
Map<String, Object> size = (Map<String, Object>) customAttr.get("misc");
|
||||
ChartViewFieldDTO gaugeMinViewField = getDynamicField(size, "gaugeMinType", "gaugeMinField");
|
||||
if (gaugeMinViewField != null) {
|
||||
yAxis.add(gaugeMinViewField);
|
||||
}
|
||||
ChartViewFieldDTO gaugeMaxViewField = getDynamicField(size, "gaugeMaxType", "gaugeMaxField");
|
||||
if (gaugeMaxViewField != null) {
|
||||
yAxis.add(gaugeMaxViewField);
|
||||
}
|
||||
axisMap.put(ChartAxis.xAxis, new ArrayList<>());
|
||||
axisMap.put(ChartAxis.yAxis, yAxis);
|
||||
var context = new HashMap<String, Object>();
|
||||
var result = new AxisFormatResult(axisMap, context);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package io.dataease.chart.charts.impl.numberic;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class IndicatorHandler extends NumbericChartHandler {
|
||||
@Getter
|
||||
private String render = "custom";
|
||||
@Getter
|
||||
private String type = "indicator";
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package io.dataease.chart.charts.impl.numberic;
|
||||
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class LiquidHandler extends NumbericChartHandler {
|
||||
@Getter
|
||||
private String type = "liquid";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
|
||||
var yAxis = new ArrayList<>(view.getYAxis());
|
||||
Map<String, Object> customAttr = view.getCustomAttr();
|
||||
Map<String, Object> misc = (Map<String, Object>) customAttr.get("misc");
|
||||
ChartViewFieldDTO liquidMaxViewField = getDynamicField(misc, "liquidMaxType", "liquidMaxField");
|
||||
if (liquidMaxViewField != null) {
|
||||
yAxis.add(liquidMaxViewField);
|
||||
}
|
||||
axisMap.put(ChartAxis.xAxis, new ArrayList<>());
|
||||
axisMap.put(ChartAxis.yAxis, yAxis);
|
||||
var context = new HashMap<String, Object>();
|
||||
var result = new AxisFormatResult(axisMap, context);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package io.dataease.chart.charts.impl.numberic;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.sql.SQLProvider;
|
||||
import io.dataease.engine.trans.Quota2SQLObj;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.extensions.view.util.FieldUtil;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NumbericChartHandler extends DefaultChartHandler {
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
DatasourceRequest datasourceRequest = new DatasourceRequest();
|
||||
datasourceRequest.setDsList(dsMap);
|
||||
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var allFields = getAllChartFields(view);
|
||||
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, FieldUtil.transFields(allFields), crossDs, dsMap);
|
||||
String querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
|
||||
querySql = SqlUtils.rebuildSQL(querySql, sqlMeta, crossDs, dsMap);
|
||||
datasourceRequest.setQuery(querySql);
|
||||
List<String[]> data = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
|
||||
boolean isdrill = filterResult
|
||||
.getFilterList()
|
||||
.stream()
|
||||
.anyMatch(ele -> ele.getFilterType() == 1);
|
||||
Map<String, Object> result = ChartDataBuild.transNormalChartData(xAxis, yAxis, view, data, isdrill);
|
||||
T calcResult = (T) new ChartCalcDataResult();
|
||||
calcResult.setData(result);
|
||||
calcResult.setContext(filterResult.getContext());
|
||||
calcResult.setQuerySql(querySql);
|
||||
calcResult.setOriginData(data);
|
||||
return calcResult;
|
||||
}
|
||||
|
||||
protected ChartViewFieldDTO getDynamicField(Map<String, Object> target, String type, String field) {
|
||||
String maxType = (String) target.get(type);
|
||||
if (StringUtils.equalsIgnoreCase("dynamic", maxType)) {
|
||||
Map<String, Object> maxField = (Map<String, Object>) target.get(field);
|
||||
Long id = Long.valueOf((String) maxField.get("id"));
|
||||
String summary = (String) maxField.get("summary");
|
||||
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(id);
|
||||
if (ObjectUtils.isNotEmpty(datasetTableField)) {
|
||||
if (datasetTableField.getDeType() == 0 || datasetTableField.getDeType() == 1 || datasetTableField.getDeType() == 5) {
|
||||
if (!StringUtils.containsIgnoreCase(summary, "count")) {
|
||||
DEException.throwException(Translator.get("i18n_gauge_field_change"));
|
||||
}
|
||||
}
|
||||
ChartViewFieldDTO dto = new ChartViewFieldDTO();
|
||||
BeanUtils.copyBean(dto, datasetTableField);
|
||||
dto.setSummary(summary);
|
||||
return dto;
|
||||
} else {
|
||||
DEException.throwException(Translator.get("i18n_gauge_field_delete"));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package io.dataease.chart.charts.impl.others;
|
||||
|
||||
import io.dataease.chart.charts.impl.ExtQuotaChartHandler;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class FunnelHandler extends ExtQuotaChartHandler {
|
||||
@Getter
|
||||
private String type = "funnel";
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package io.dataease.chart.charts.impl.others;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RadarHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "radar";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package io.dataease.chart.charts.impl.others;
|
||||
|
||||
import io.dataease.chart.charts.impl.GroupChartHandler;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SankeyHandler extends GroupChartHandler {
|
||||
@Getter
|
||||
private String type = "sankey";
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package io.dataease.chart.charts.impl.others;
|
||||
|
||||
import io.dataease.chart.charts.impl.ExtQuotaChartHandler;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WaterfallHandler extends ExtQuotaChartHandler {
|
||||
@Getter
|
||||
private String type = "waterfall";
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package io.dataease.chart.charts.impl.others;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.chart.charts.impl.ExtQuotaChartHandler;
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WordCloudHandler extends ExtQuotaChartHandler {
|
||||
@Getter
|
||||
private String type = "word-cloud";
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package io.dataease.chart.charts.impl.pie;
|
||||
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.chart.charts.impl.ExtQuotaChartHandler;
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.extensions.view.dto.AxisFormatResult;
|
||||
import io.dataease.extensions.view.dto.ChartAxis;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class PieHandler extends YoyChartHandler {
|
||||
@Override
|
||||
public void init() {
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "pie", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "pie-rose", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "pie-donut", this);
|
||||
chartHandlerManager.registerChartHandler(this.getRender(), "pie-rose-donut", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = result.getAxisMap().get(ChartAxis.yAxis);
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package io.dataease.chart.charts.impl.scatter;
|
||||
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class QuadrantHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "quadrant";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = new ArrayList<>(view.getYAxis());
|
||||
yAxis.addAll(view.getYAxisExt());
|
||||
yAxis.addAll(view.getExtBubble());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
|
||||
result.getAxisMap().put(ChartAxis.extBubble, view.getExtBubble());
|
||||
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.yAxisExt, view.getYAxisExt());
|
||||
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);
|
||||
Map<String, Object> result = ChartDataBuild.transMixChartDataAntV(xAxis, xAxis, new ArrayList<>(), yAxis, view, data, isDrill);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package io.dataease.chart.charts.impl.scatter;
|
||||
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ScatterHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "scatter";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
var yAxis = new ArrayList<>(view.getYAxis());
|
||||
yAxis.addAll(view.getExtBubble());
|
||||
yAxis.addAll(view.getExtLabel());
|
||||
yAxis.addAll(view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.yAxis, yAxis);
|
||||
result.getAxisMap().put(ChartAxis.extBubble, view.getExtBubble());
|
||||
result.getAxisMap().put(ChartAxis.extTooltip, view.getExtTooltip());
|
||||
result.getAxisMap().put(ChartAxis.extLabel, view.getExtLabel());
|
||||
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);
|
||||
var extBubble = formatResult.getAxisMap().get(ChartAxis.extBubble);
|
||||
Map<String, Object> result = ChartDataBuild.transScatterDataAntV(xAxis, yAxis, view, data, extBubble, isDrill);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
package io.dataease.chart.charts.impl.table;
|
||||
|
||||
import io.dataease.api.chart.dto.PageInfo;
|
||||
import io.dataease.chart.charts.impl.DefaultChartHandler;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.engine.sql.SQLProvider;
|
||||
import io.dataease.engine.trans.Dimension2SQLObj;
|
||||
import io.dataease.engine.trans.Quota2SQLObj;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.extensions.view.util.ChartDataUtil;
|
||||
import io.dataease.extensions.view.util.FieldUtil;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class TableInfoHandler extends DefaultChartHandler {
|
||||
@Getter
|
||||
private String type = "table-info";
|
||||
|
||||
@Override
|
||||
public AxisFormatResult formatAxis(ChartViewDTO view) {
|
||||
var result = super.formatAxis(view);
|
||||
result.getAxisMap().put(ChartAxis.yAxis, new ArrayList<>());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends CustomFilterResult, K extends AxisFormatResult> T customFilter(ChartViewDTO view, List<ChartExtFilterDTO> filterList, K formatResult) {
|
||||
var chartExtRequest = view.getChartExtRequest();
|
||||
Map<String, Object> mapAttr = view.getCustomAttr();
|
||||
Map<String, Object> mapSize = (Map<String, Object>) mapAttr.get("basicStyle");
|
||||
var tablePageMode = (String) mapSize.get("tablePageMode");
|
||||
formatResult.getContext().put("tablePageMode", tablePageMode);
|
||||
if (StringUtils.equalsIgnoreCase(tablePageMode, "page") && !view.getIsExcelExport()) {
|
||||
if (chartExtRequest.getGoPage() == null) {
|
||||
chartExtRequest.setGoPage(1L);
|
||||
}
|
||||
if (chartExtRequest.getPageSize() == null) {
|
||||
int pageSize = (int) mapSize.get("tablePageSize");
|
||||
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
|
||||
chartExtRequest.setPageSize(Math.min(pageSize, view.getResultCount().longValue()));
|
||||
} else {
|
||||
chartExtRequest.setPageSize((long) pageSize);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
|
||||
chartExtRequest.setGoPage(1L);
|
||||
chartExtRequest.setPageSize(view.getResultCount().longValue());
|
||||
} else if (!view.getIsExcelExport()) {
|
||||
chartExtRequest.setGoPage(null);
|
||||
chartExtRequest.setPageSize(null);
|
||||
}
|
||||
}
|
||||
return super.customFilter(view, filterList, formatResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, CalciteProvider provider) {
|
||||
var chartExtRequest = view.getChartExtRequest();
|
||||
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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
DatasourceRequest datasourceRequest = new DatasourceRequest();
|
||||
datasourceRequest.setDsList(dsMap);
|
||||
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
|
||||
var allFields = getAllChartFields(view);
|
||||
PageInfo pageInfo = new PageInfo();
|
||||
pageInfo.setGoPage(chartExtRequest.getGoPage());
|
||||
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
|
||||
pageInfo.setPageSize(Math.min(view.getResultCount() - (chartExtRequest.getGoPage() - 1) * chartExtRequest.getPageSize(), chartExtRequest.getPageSize()));
|
||||
} else {
|
||||
pageInfo.setPageSize(chartExtRequest.getPageSize());
|
||||
}
|
||||
Dimension2SQLObj.dimension2sqlObj(sqlMeta, xAxis, FieldUtil.transFields(allFields), crossDs, dsMap);
|
||||
String originSql = SQLProvider.createQuerySQL(sqlMeta, false, true, view);// 明细表强制加排序
|
||||
String limit = ((pageInfo.getGoPage() != null && pageInfo.getPageSize() != null) ? " LIMIT " + pageInfo.getPageSize() + " OFFSET " + (pageInfo.getGoPage() - 1) * pageInfo.getPageSize() : "");
|
||||
var querySql = originSql + limit;
|
||||
|
||||
var tablePageMode = (String) filterResult.getContext().get("tablePageMode");
|
||||
var totalPageSql = "SELECT COUNT(*) FROM (" + SQLProvider.createQuerySQL(sqlMeta, false, false, view) + ") COUNT_TEMP";
|
||||
if (StringUtils.isNotEmpty(totalPageSql) && StringUtils.equalsIgnoreCase(tablePageMode, "page")) {
|
||||
totalPageSql = SqlUtils.rebuildSQL(totalPageSql, sqlMeta, crossDs, dsMap);
|
||||
datasourceRequest.setQuery(totalPageSql);
|
||||
datasourceRequest.setTotalPageFlag(true);
|
||||
List<String[]> tmpData = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
|
||||
var totalItems = ObjectUtils.isEmpty(tmpData) ? 0 : Long.valueOf(tmpData.get(0)[0]);
|
||||
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
|
||||
totalItems = totalItems <= view.getResultCount() ? totalItems : view.getResultCount();
|
||||
}
|
||||
var totalPage = (totalItems / pageInfo.getPageSize()) + (totalItems % pageInfo.getPageSize() > 0 ? 1 : 0);
|
||||
view.setTotalItems(totalItems);
|
||||
view.setTotalPage(totalPage);
|
||||
}
|
||||
|
||||
querySql = SqlUtils.rebuildSQL(querySql, sqlMeta, crossDs, dsMap);
|
||||
datasourceRequest.setQuery(querySql);
|
||||
List<String[]> data = (List<String[]>) provider.fetchResultField(datasourceRequest).get("data");
|
||||
//自定义排序
|
||||
data = ChartDataUtil.resultCustomSort(xAxis, data);
|
||||
//数据重组逻辑可重载
|
||||
var result = this.buildResult(view, formatResult, filterResult, data);
|
||||
T calcResult = (T) new ChartCalcDataResult();
|
||||
calcResult.setData(result);
|
||||
calcResult.setContext(filterResult.getContext());
|
||||
calcResult.setQuerySql(querySql);
|
||||
calcResult.setOriginData(data);
|
||||
return calcResult;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package io.dataease.chart.charts.impl.table;
|
||||
|
||||
import io.dataease.chart.charts.impl.GroupChartHandler;
|
||||
import lombok.Getter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TablePivotHandler extends GroupChartHandler {
|
||||
@Getter
|
||||
private String type = "table-pivot";
|
||||
}
|
||||
@ -6,6 +6,8 @@ import io.dataease.api.chart.dto.PageInfo;
|
||||
import io.dataease.api.dataset.union.DatasetGroupInfoDTO;
|
||||
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
|
||||
import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO;
|
||||
import io.dataease.chart.charts.AbstractChartHandler;
|
||||
import io.dataease.chart.charts.ChartHandlerManager;
|
||||
import io.dataease.chart.constant.ChartConstants;
|
||||
import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.constant.AuthEnum;
|
||||
@ -51,6 +53,8 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static io.dataease.extensions.view.dto.ChartAxis.*;
|
||||
|
||||
/**
|
||||
* @Author Junjun
|
||||
*/
|
||||
@ -70,6 +74,8 @@ public class ChartDataManage {
|
||||
private PermissionManage permissionManage;
|
||||
@Resource
|
||||
private ChartFilterTreeService chartFilterTreeService;
|
||||
@Resource
|
||||
private ChartHandlerManager chartHandlerManager;
|
||||
|
||||
@Resource
|
||||
private CorePermissionManage corePermissionManage;
|
||||
@ -115,6 +121,9 @@ public class ChartDataManage {
|
||||
List<ChartViewFieldDTO> allFields = getAllChartFields(view);
|
||||
ChartViewDTO chartViewDTO = null;
|
||||
|
||||
if (ObjectUtils.isNotEmpty(view.getIsPlugin()) && view.getIsPlugin()) {
|
||||
return calcData1(view, chartExtRequest, allFields, viewFields);
|
||||
}
|
||||
if (StringUtils.containsIgnoreCase(view.getType(), "chart-mix")) {
|
||||
// 需要排除掉除类别轴以外所有的排序
|
||||
view.getXAxisExt().forEach(dto -> dto.setSort("none"));
|
||||
@ -145,7 +154,7 @@ public class ChartDataManage {
|
||||
view1.getSenior().put("assistLineCfg", assistLineCfg1);
|
||||
}
|
||||
}
|
||||
ChartViewDTO left = calcData(view1, chartExtRequest, allFields, viewFields);
|
||||
ChartViewDTO left = calcData1(view1, chartExtRequest, allFields, viewFields);
|
||||
data.put("left", left.getData());
|
||||
//针对右轴,删除yAxis
|
||||
ChartViewDTO view2 = JsonUtil.parseObject(viewJson, ChartViewDTO.class);
|
||||
@ -162,7 +171,7 @@ public class ChartDataManage {
|
||||
view2.setXAxisExt(view2.getExtBubble());
|
||||
view2.setExtStack(new ArrayList<>());
|
||||
view2.setExtBubble(new ArrayList<>());
|
||||
ChartViewDTO right = calcData(view2, chartExtRequest, allFields, viewFields);
|
||||
ChartViewDTO right = calcData1(view2, chartExtRequest, allFields, viewFields);
|
||||
data.put("right", right.getData());
|
||||
|
||||
//重新组装
|
||||
@ -181,6 +190,273 @@ public class ChartDataManage {
|
||||
}
|
||||
|
||||
public ChartViewDTO calcData(ChartViewDTO view, ChartExtRequest chartExtRequest, List<ChartViewFieldDTO> allFields, List<ChartViewFieldDTO> viewFields) throws Exception {
|
||||
AbstractChartHandler chartHandler = chartHandlerManager.getChartHandler(view.getRender(), view.getType());
|
||||
AxisFormatResult formatResult = chartHandler.formatAxis(view);
|
||||
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
|
||||
DatasetGroupInfoDTO table = datasetGroupManage.getDatasetGroupInfoDTO(view.getTableId(), null);
|
||||
if (table == null) {
|
||||
DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_no_ds"));
|
||||
}
|
||||
// check permission
|
||||
BusiPerCheckDTO dto = new BusiPerCheckDTO();
|
||||
dto.setId(table.getId());
|
||||
dto.setAuthEnum(AuthEnum.READ);
|
||||
boolean checked = corePermissionManage.checkAuth(dto);
|
||||
if (!checked) {
|
||||
DEException.throwException(Translator.get("i18n_no_datasource_permission"));
|
||||
}
|
||||
|
||||
// column permission
|
||||
Map<String, ColumnPermissionItem> desensitizationList = new HashMap<>();
|
||||
List<DatasetTableFieldDTO> columnPermissionFields = permissionManage.filterColumnPermissions(transFields(allFields), desensitizationList, table.getId(), chartExtRequest.getUser());
|
||||
// row permission
|
||||
List<DataSetRowPermissionsTreeDTO> rowPermissionsTree = permissionManage.getRowPermissionsTree(table.getId(), chartExtRequest.getUser());
|
||||
//将没有权限的列删掉
|
||||
List<String> dataeaseNames = columnPermissionFields.stream().map(DatasetTableFieldDTO::getDataeaseName).collect(Collectors.toList());
|
||||
dataeaseNames.add("*");
|
||||
var axisMap = formatResult.getAxisMap();
|
||||
axisMap.forEach((axis, fields) -> {
|
||||
Iterator<ChartViewFieldDTO> iterator = fields.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ChartViewFieldDTO fieldDTO = iterator.next();
|
||||
if (desensitizationList.containsKey(fieldDTO.getDataeaseName()) || !dataeaseNames.contains(fieldDTO.getDataeaseName())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (ObjectUtils.isEmpty(xAxis) && ObjectUtils.isEmpty(yAxis)) {
|
||||
return emptyChartViewDTO(view);
|
||||
}
|
||||
|
||||
// 过滤来自仪表板的条件
|
||||
List<ChartExtFilterDTO> extFilterList = new ArrayList<>();
|
||||
//组件过滤条件
|
||||
if (ObjectUtils.isNotEmpty(chartExtRequest.getFilter())) {
|
||||
for (ChartExtFilterDTO request : chartExtRequest.getFilter()) {
|
||||
// 解析多个fieldId,fieldId是一个逗号分隔的字符串
|
||||
String fieldId = request.getFieldId();
|
||||
if (request.getIsTree() == null) {
|
||||
request.setIsTree(false);
|
||||
}
|
||||
|
||||
boolean hasParameters = false;
|
||||
List<SqlVariableDetails> sqlVariables = datasetGroupManage.getSqlParams(Arrays.asList(view.getTableId()));
|
||||
if (CollectionUtils.isNotEmpty(sqlVariables)) {
|
||||
for (SqlVariableDetails parameter : Optional.ofNullable(request.getParameters()).orElse(new ArrayList<>())) {
|
||||
String parameterId = StringUtils.endsWith(parameter.getId(), START_END_SEPARATOR) ? parameter.getId().split(START_END_SEPARATOR)[0] : parameter.getId();
|
||||
if (sqlVariables.stream().map(SqlVariableDetails::getId).collect(Collectors.toList()).contains(parameterId)) {
|
||||
hasParameters = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasParameters) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(fieldId)) {
|
||||
List<Long> fieldIds = Arrays.stream(fieldId.split(",")).map(Long::valueOf).collect(Collectors.toList());
|
||||
|
||||
if (request.getIsTree()) {
|
||||
ChartExtFilterDTO filterRequest = new ChartExtFilterDTO();
|
||||
BeanUtils.copyBean(filterRequest, request);
|
||||
filterRequest.setFilterType(0);
|
||||
filterRequest.setDatasetTableFieldList(new ArrayList<>());
|
||||
for (Long fId : fieldIds) {
|
||||
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(fId);
|
||||
if (datasetTableField == null) {
|
||||
continue;
|
||||
}
|
||||
if (Objects.equals(datasetTableField.getDatasetTableId(), view.getTableId())) {
|
||||
if (ObjectUtils.isNotEmpty(filterRequest.getViewIds())) {
|
||||
if (filterRequest.getViewIds().contains(view.getId())) {
|
||||
filterRequest.getDatasetTableFieldList().add(datasetTableField);
|
||||
}
|
||||
} else {
|
||||
filterRequest.getDatasetTableFieldList().add(datasetTableField);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ObjectUtils.isNotEmpty(filterRequest.getDatasetTableFieldList())) {
|
||||
extFilterList.add(filterRequest);
|
||||
}
|
||||
} else {
|
||||
for (Long fId : fieldIds) {
|
||||
ChartExtFilterDTO filterRequest = new ChartExtFilterDTO();
|
||||
BeanUtils.copyBean(filterRequest, request);
|
||||
filterRequest.setFilterType(0);
|
||||
filterRequest.setFieldId(fId + "");
|
||||
|
||||
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(fId);
|
||||
if (datasetTableField == null) {
|
||||
continue;
|
||||
}
|
||||
filterRequest.setDatasetTableField(datasetTableField);
|
||||
if (Objects.equals(datasetTableField.getDatasetGroupId(), view.getTableId())) {
|
||||
if (ObjectUtils.isNotEmpty(filterRequest.getViewIds())) {
|
||||
if (filterRequest.getViewIds().contains(view.getId())) {
|
||||
extFilterList.add(filterRequest);
|
||||
}
|
||||
} else {
|
||||
extFilterList.add(filterRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<ChartExtFilterDTO> filters = new ArrayList<>();
|
||||
// 联动条件
|
||||
if (ObjectUtils.isNotEmpty(chartExtRequest.getLinkageFilters())) {
|
||||
filters.addAll(chartExtRequest.getLinkageFilters());
|
||||
}
|
||||
|
||||
// 外部参数条件
|
||||
if (ObjectUtils.isNotEmpty(chartExtRequest.getOuterParamsFilters())) {
|
||||
filters.addAll(chartExtRequest.getOuterParamsFilters());
|
||||
}
|
||||
|
||||
//联动过滤条件和外部参数过滤条件全部加上
|
||||
if (ObjectUtils.isNotEmpty(filters)) {
|
||||
for (ChartExtFilterDTO request : filters) {
|
||||
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(Long.valueOf(request.getFieldId()));
|
||||
request.setDatasetTableField(datasetTableField);
|
||||
request.setFilterType(2);
|
||||
// 相同数据集
|
||||
if (Objects.equals(datasetTableField.getDatasetGroupId(), view.getTableId())) {
|
||||
if (ObjectUtils.isNotEmpty(request.getViewIds())) {
|
||||
if (request.getViewIds().contains(view.getId())) {
|
||||
extFilterList.add(request);
|
||||
}
|
||||
} else {
|
||||
extFilterList.add(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 下钻
|
||||
List<ChartDrillRequest> drillRequestList = chartExtRequest.getDrill();
|
||||
var drill = formatResult.getAxisMap().get(ChartAxis.drill);
|
||||
if (ObjectUtils.isNotEmpty(drillRequestList) && (drill.size() > drillRequestList.size())) {
|
||||
var fields = xAxis.stream().map(ChartViewFieldDTO::getId).collect(Collectors.toSet());
|
||||
for (int i = 0; i < drillRequestList.size(); i++) {
|
||||
ChartDrillRequest request = drillRequestList.get(i);
|
||||
for (ChartDimensionDTO dim : request.getDimensionList()) {
|
||||
ChartViewFieldDTO viewField = drill.get(i);
|
||||
// 将钻取值作为条件传递,将所有钻取字段作为xAxis并加上下一个钻取字段
|
||||
if (Objects.equals(dim.getId(), viewField.getId())) {
|
||||
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(dim.getId());
|
||||
ChartViewFieldDTO d = new ChartViewFieldDTO();
|
||||
BeanUtils.copyBean(d, datasetTableField);
|
||||
|
||||
ChartExtFilterDTO drillFilter = new ChartExtFilterDTO();
|
||||
drillFilter.setFieldId(String.valueOf(dim.getId()));
|
||||
drillFilter.setDatasetTableField(datasetTableField);
|
||||
drillFilter.setDatePattern(viewField.getDatePattern());
|
||||
drillFilter.setDateStyle(viewField.getDateStyle());
|
||||
drillFilter.setFilterType(1);
|
||||
if (datasetTableField.getDeType() == 1) {
|
||||
drillFilter.setOperator("between");
|
||||
// 把value类似过滤组件处理,获得start time和end time
|
||||
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(dim.getValue());
|
||||
drillFilter.setValue(Arrays.asList(String.valueOf(stringLongMap.get("startTime")), String.valueOf(stringLongMap.get("endTime"))));
|
||||
} else {
|
||||
drillFilter.setOperator("in");
|
||||
drillFilter.setValue(Collections.singletonList(dim.getValue()));
|
||||
}
|
||||
extFilterList.add(drillFilter);
|
||||
|
||||
if (!fields.contains(dim.getId())) {
|
||||
viewField.setSource(FieldSource.DRILL);
|
||||
xAxis.add(viewField);
|
||||
fields.add(dim.getId());
|
||||
}
|
||||
if (i == drillRequestList.size() - 1) {
|
||||
ChartViewFieldDTO nextDrillField = drill.get(i + 1);
|
||||
if (!fields.contains(nextDrillField.getId())) {
|
||||
viewField.setSource(FieldSource.DRILL);
|
||||
nextDrillField.setSort(getDrillSort(xAxis, drill.get(0)));
|
||||
xAxis.add(nextDrillField);
|
||||
fields.add(nextDrillField.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//转义特殊字符
|
||||
extFilterList = extFilterList.stream().peek(ele -> {
|
||||
if (ObjectUtils.isNotEmpty(ele.getValue())) {
|
||||
List<String> collect = ele.getValue().stream().map(SQLUtils::transKeyword).collect(Collectors.toList());
|
||||
ele.setValue(collect);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
// 视图自定义过滤逻辑
|
||||
CustomFilterResult filterResult = chartHandler.customFilter(view, extFilterList, formatResult);
|
||||
// 字段过滤器
|
||||
FilterTreeObj fieldCustomFilter = view.getCustomFilter();
|
||||
chartFilterTreeService.searchFieldAndSet(fieldCustomFilter);
|
||||
fieldCustomFilter = chartFilterTreeService.charReplace(fieldCustomFilter);
|
||||
// 获取dsMap,union sql
|
||||
Map<String, Object> sqlMap = datasetSQLManage.getUnionSQLForEdit(table, chartExtRequest);
|
||||
String sql = (String) sqlMap.get("sql");
|
||||
Map<Long, DatasourceSchemaDTO> 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());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
if (!crossDs) {
|
||||
sql = Utils.replaceSchemaAlias(sql, dsMap);
|
||||
}
|
||||
|
||||
List<ChartViewFieldDTO> detailFieldList = new ArrayList<>();
|
||||
String detailFieldSql = null;
|
||||
List<String[]> detailData = new ArrayList<>();
|
||||
if (ObjectUtils.isEmpty(dsMap)) {
|
||||
DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_datasource_delete"));
|
||||
}
|
||||
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
|
||||
DatasourceSchemaDTO ds = next.getValue();
|
||||
if (StringUtils.isNotEmpty(ds.getStatus()) && "Error".equalsIgnoreCase(ds.getStatus())) {
|
||||
DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_invalid_ds"));
|
||||
}
|
||||
}
|
||||
|
||||
SQLMeta sqlMeta = new SQLMeta();
|
||||
Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs);
|
||||
CustomWhere2Str.customWhere2sqlObj(sqlMeta, fieldCustomFilter, transFields(allFields), crossDs, dsMap);
|
||||
ExtWhere2Str.extWhere2sqlOjb(sqlMeta, extFilterList, transFields(allFields), crossDs, dsMap);
|
||||
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, transFields(allFields), crossDs, dsMap);
|
||||
Map<Long, String> dsTypeMap = dsMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getType()));
|
||||
ChartCalcDataResult calcResult = chartHandler.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, calciteProvider);
|
||||
// 如果是表格导出查询 则在此处直接就可以返回
|
||||
var extStack = formatResult.getAxisMap().get(ChartAxis.extStack);
|
||||
if (view.getIsExcelExport()) {
|
||||
Map<String, Object> sourceInfo = ChartDataBuild.transTableNormal(xAxis, yAxis, view, calcResult.getOriginData(), extStack, desensitizationList);
|
||||
sourceInfo.put("sourceData", calcResult.getOriginData());
|
||||
view.setData(sourceInfo);
|
||||
return view;
|
||||
}
|
||||
|
||||
// 构建结果
|
||||
Map<String, Object> map = new TreeMap<>();
|
||||
// 图表组件可再扩展
|
||||
Map<String, Object> mapTableNormal = ChartDataBuild.transTableNormal(xAxis, yAxis, view, calcResult.getOriginData(), extStack, desensitizationList);
|
||||
var drillFilters = filterResult.getFilterList().stream().filter(f -> f.getFilterType() == 1).collect(Collectors.toList());
|
||||
var isDrill = CollectionUtils.isNotEmpty(drillFilters);
|
||||
ChartViewDTO chartViewDTO = uniteViewResult(calcResult.getQuerySql(), calcResult.getData(), mapTableNormal, view, isDrill, drillFilters, calcResult.getDynamicAssistFields(), calcResult.getAssistData());
|
||||
return chartViewDTO;
|
||||
}
|
||||
|
||||
public ChartViewDTO calcData1(ChartViewDTO view, ChartExtRequest chartExtRequest, List<ChartViewFieldDTO> allFields, List<ChartViewFieldDTO> viewFields) throws Exception {
|
||||
List<ChartViewFieldDTO> xAxisBase = null;
|
||||
List<ChartViewFieldDTO> xAxis = null;
|
||||
List<ChartViewFieldDTO> xAxisExt = null;
|
||||
@ -413,7 +689,7 @@ public class ChartDataManage {
|
||||
if (datasetTableField == null) {
|
||||
continue;
|
||||
}
|
||||
if (Objects.equals(datasetTableField.getDatasetTableId(), view.getTableId())) {
|
||||
if (Objects.equals(datasetTableField.getDatasetGroupId(), view.getTableId())) {
|
||||
if (ObjectUtils.isNotEmpty(filterRequest.getViewIds())) {
|
||||
if (filterRequest.getViewIds().contains(view.getId())) {
|
||||
filterRequest.getDatasetTableFieldList().add(datasetTableField);
|
||||
|
||||
@ -699,28 +699,38 @@ public class ChartDataBuild {
|
||||
public static Map<String, Object> transChartData(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, ChartViewDTO view, List<String[]> data, boolean isDrill) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
List<String> x = new ArrayList<>();
|
||||
List<Series> series = new ArrayList<>();
|
||||
for (ChartViewFieldDTO y : yAxis) {
|
||||
Series series1 = new Series();
|
||||
series1.setName(y.getName());
|
||||
series1.setType(view.getType());
|
||||
series1.setData(new ArrayList<>());
|
||||
series.add(series1);
|
||||
}
|
||||
List<AxisChartDataAntVDTO> dataList = new ArrayList<>();
|
||||
for (int i1 = 0; i1 < data.size(); i1++) {
|
||||
String[] d = data.get(i1);
|
||||
String[] row = data.get(i1);
|
||||
|
||||
StringBuilder a = new StringBuilder();
|
||||
for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) {
|
||||
if (isDrill) {
|
||||
a.append(row[xAxis.size() - 1]);
|
||||
} else {
|
||||
for (int i = 0; i < xAxis.size(); i++) {
|
||||
if (i == xAxis.size() - 1) {
|
||||
a.append(row[i]);
|
||||
} else {
|
||||
a.append(row[i]).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
// yAxis最后的数据对应extLabel和extTooltip,将他们从yAxis中去掉,同时转换成动态值
|
||||
int size = xAxis.size() + yAxis.size();
|
||||
int extSize = view.getExtLabel().size() + view.getExtTooltip().size();
|
||||
|
||||
for (int i = xAxis.size(); i < size - extSize; i++) {
|
||||
AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO();
|
||||
axisChartDataDTO.setField(a.toString());
|
||||
axisChartDataDTO.setName(a.toString());
|
||||
|
||||
List<ChartDimensionDTO> dimensionList = new ArrayList<>();
|
||||
List<ChartQuotaDTO> quotaList = new ArrayList<>();
|
||||
AxisChartDataDTO axisChartDataDTO = new AxisChartDataDTO();
|
||||
|
||||
for (int j = 0; j < xAxis.size(); j++) {
|
||||
ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO();
|
||||
chartDimensionDTO.setId(xAxis.get(j).getId());
|
||||
chartDimensionDTO.setValue(d[j]);
|
||||
chartDimensionDTO.setValue(row[j]);
|
||||
dimensionList.add(chartDimensionDTO);
|
||||
}
|
||||
axisChartDataDTO.setDimensionList(dimensionList);
|
||||
@ -731,28 +741,16 @@ public class ChartDataBuild {
|
||||
quotaList.add(chartQuotaDTO);
|
||||
axisChartDataDTO.setQuotaList(quotaList);
|
||||
try {
|
||||
axisChartDataDTO.setValue(StringUtils.isEmpty(d[i]) ? null : new BigDecimal(d[i]));
|
||||
axisChartDataDTO.setValue(StringUtils.isEmpty(row[i]) ? null : new BigDecimal(row[i]));
|
||||
} catch (Exception e) {
|
||||
axisChartDataDTO.setValue(new BigDecimal(0));
|
||||
}
|
||||
series.get(j).getData().add(axisChartDataDTO);
|
||||
axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName()));
|
||||
buildDynamicValue(view, axisChartDataDTO, row, size, extSize);
|
||||
dataList.add(axisChartDataDTO);
|
||||
}
|
||||
if (isDrill) {
|
||||
a.append(d[xAxis.size() - 1]);
|
||||
} else {
|
||||
for (int i = 0; i < xAxis.size(); i++) {
|
||||
if (i == xAxis.size() - 1) {
|
||||
a.append(d[i]);
|
||||
} else {
|
||||
a.append(d[i]).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
x.add(a.toString());
|
||||
}
|
||||
|
||||
map.put("x", x);
|
||||
map.put("series", series);
|
||||
map.put("data", dataList);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,16 @@ package io.dataease.commons.constants;
|
||||
|
||||
public class DataVisualizationConstants {
|
||||
|
||||
//新建仪表板来源
|
||||
public static final class QUERY_SOURCE {
|
||||
|
||||
// 定时报告
|
||||
public static final String REPORT = "report";
|
||||
|
||||
// 主工程
|
||||
public static final String MAIN = "main";
|
||||
}
|
||||
|
||||
//新建仪表板来源
|
||||
public static final class NEW_PANEL_FROM {
|
||||
|
||||
|
||||
@ -561,7 +561,7 @@ public class SqlparserUtils {
|
||||
if (sqlVariableDetails.getOperator().equals("in")) {
|
||||
return "'" + String.join("','", sqlVariableDetails.getValue()) + "'";
|
||||
} else if (sqlVariableDetails.getOperator().equals("between")) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sqlVariableDetails.getType().size() > 1 ? (String) sqlVariableDetails.getType().get(1).replace("DD", "dd") : "YYYY");
|
||||
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 {
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
package io.dataease.dataset.manage;
|
||||
|
||||
import io.dataease.extensions.view.dto.ChartExtFilterDTO;
|
||||
import io.dataease.api.chart.dto.ColumnPermissionItem;
|
||||
import io.dataease.api.chart.dto.DeSortField;
|
||||
import io.dataease.extensions.view.dto.ChartExtRequest;
|
||||
import io.dataease.api.dataset.dto.*;
|
||||
import io.dataease.api.dataset.union.DatasetGroupInfoDTO;
|
||||
import io.dataease.api.dataset.union.DatasetTableInfoDTO;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.api.ds.vo.TableField;
|
||||
import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO;
|
||||
import io.dataease.auth.bo.TokenUserBO;
|
||||
@ -16,16 +13,13 @@ import io.dataease.chart.utils.ChartDataBuild;
|
||||
import io.dataease.commons.utils.SqlparserUtils;
|
||||
import io.dataease.dataset.constant.DatasetTableType;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.utils.FieldUtils;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
import io.dataease.dataset.utils.TableUtils;
|
||||
import io.dataease.dataset.utils.*;
|
||||
import io.dataease.datasource.dao.auto.entity.CoreDatasource;
|
||||
import io.dataease.datasource.dao.auto.mapper.CoreDatasourceMapper;
|
||||
import io.dataease.datasource.manage.EngineManage;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.datasource.utils.DatasourceUtils;
|
||||
import io.dataease.extensions.view.dto.DatasetTableFieldDTO;
|
||||
import io.dataease.engine.constant.ExtFieldConstant;
|
||||
import io.dataease.engine.constant.SQLConstants;
|
||||
import io.dataease.engine.constant.SqlPlaceholderConstants;
|
||||
@ -34,11 +28,16 @@ import io.dataease.engine.trans.*;
|
||||
import io.dataease.engine.utils.SQLUtils;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.extensions.view.dto.ChartExtFilterDTO;
|
||||
import io.dataease.extensions.view.dto.ChartExtRequest;
|
||||
import io.dataease.extensions.view.dto.DatasetTableFieldDTO;
|
||||
import io.dataease.extensions.view.dto.SqlVariableDetails;
|
||||
import io.dataease.extensions.view.model.SQLMeta;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.utils.AuthUtils;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import io.dataease.utils.TreeUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -733,4 +732,114 @@ public class DatasetDataManage {
|
||||
}
|
||||
return previewData;
|
||||
}
|
||||
|
||||
public List<BaseTreeNodeDTO> getFieldValueTree(List<Long> ids) throws Exception {
|
||||
if (ids.isEmpty()) {
|
||||
DEException.throwException("no field selected.");
|
||||
}
|
||||
// 根据前端传的查询组件field ids,获取所有字段枚举值并去重合并
|
||||
List<List<String>> list = new ArrayList<>();
|
||||
List<DatasetTableFieldDTO> fields = new ArrayList<>();
|
||||
|
||||
// 根据图表计算字段,获取数据集
|
||||
List<DatasetTableFieldDTO> allFields = new ArrayList<>();
|
||||
DatasetTableFieldDTO field = datasetTableFieldManage.selectById(ids.getFirst());
|
||||
Long datasetGroupId = field.getDatasetGroupId();
|
||||
if (field.getChartId() != null) {
|
||||
allFields.addAll(datasetTableFieldManage.getChartCalcFields(field.getChartId()));
|
||||
}
|
||||
DatasetGroupInfoDTO datasetGroupInfoDTO = datasetGroupManage.get(datasetGroupId, null);
|
||||
|
||||
Map<String, Object> sqlMap = datasetSQLManage.getUnionSQLForEdit(datasetGroupInfoDTO, new ChartExtRequest());
|
||||
String sql = (String) sqlMap.get("sql");
|
||||
|
||||
allFields.addAll(datasetGroupInfoDTO.getAllFields());
|
||||
|
||||
Map<Long, DatasourceSchemaDTO> dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
|
||||
boolean crossDs = Utils.isCrossDs(dsMap);
|
||||
if (!crossDs) {
|
||||
sql = Utils.replaceSchemaAlias(sql, dsMap);
|
||||
}
|
||||
|
||||
// build query sql
|
||||
SQLMeta sqlMeta = new SQLMeta();
|
||||
Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs);
|
||||
|
||||
for (Long id : ids) {
|
||||
DatasetTableFieldDTO f = datasetTableFieldManage.selectById(id);
|
||||
if (f == null) {
|
||||
DEException.throwException(Translator.get("i18n_no_field"));
|
||||
}
|
||||
// 获取allFields
|
||||
fields.add(f);
|
||||
}
|
||||
|
||||
Map<String, ColumnPermissionItem> desensitizationList = new HashMap<>();
|
||||
fields = permissionManage.filterColumnPermissions(fields, desensitizationList, datasetGroupInfoDTO.getId(), null);
|
||||
if (ObjectUtils.isEmpty(fields)) {
|
||||
DEException.throwException(Translator.get("i18n_no_column_permission"));
|
||||
}
|
||||
buildFieldName(sqlMap, fields);
|
||||
|
||||
List<String> dsList = new ArrayList<>();
|
||||
for (Map.Entry<Long, DatasourceSchemaDTO> next : dsMap.entrySet()) {
|
||||
dsList.add(next.getValue().getType());
|
||||
}
|
||||
boolean needOrder = Utils.isNeedOrder(dsList);
|
||||
|
||||
List<DataSetRowPermissionsTreeDTO> rowPermissionsTree = new ArrayList<>();
|
||||
TokenUserBO user = AuthUtils.getUser();
|
||||
if (user != null) {
|
||||
rowPermissionsTree = permissionManage.getRowPermissionsTree(datasetGroupInfoDTO.getId(), user.getUserId());
|
||||
}
|
||||
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, allFields, crossDs, dsMap);
|
||||
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, allFields, crossDs, dsMap);
|
||||
Order2SQLObj.getOrders(sqlMeta, datasetGroupInfoDTO.getSortFields(), allFields, crossDs, dsMap);
|
||||
String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, 0, 1000);
|
||||
querySQL = SqlUtils.rebuildSQL(querySQL, sqlMeta, crossDs, dsMap);
|
||||
logger.info("filter tree sql: " + querySQL);
|
||||
|
||||
// 通过数据源请求数据
|
||||
// 调用数据源的calcite获得data
|
||||
DatasourceRequest datasourceRequest = new DatasourceRequest();
|
||||
datasourceRequest.setQuery(querySQL);
|
||||
datasourceRequest.setDsList(dsMap);
|
||||
Map<String, Object> data = calciteProvider.fetchResultField(datasourceRequest);
|
||||
List<String[]> rows = (List<String[]>) data.get("data");
|
||||
|
||||
// 重新构造data
|
||||
Set<String> pkSet = new HashSet<>();
|
||||
rows = rows.stream().filter(row -> {
|
||||
boolean allEmpty = true;
|
||||
for (String s : row) {
|
||||
if (StringUtils.isNotBlank(s)) {
|
||||
allEmpty = false;
|
||||
}
|
||||
}
|
||||
return !allEmpty;
|
||||
}).toList();
|
||||
List<BaseTreeNodeDTO> treeNodes = rows.stream().map(row -> buildTreeNode(row, pkSet)).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
List<BaseTreeNodeDTO> tree = DatasetUtils.mergeDuplicateTree(treeNodes, "root");
|
||||
return tree;
|
||||
}
|
||||
|
||||
private List<BaseTreeNodeDTO> buildTreeNode(String[] row, Set<String> pkSet) {
|
||||
List<BaseTreeNodeDTO> nodes = new ArrayList<>();
|
||||
List<String> parentPkList = new ArrayList<>();
|
||||
for (int i = 0; i < row.length; i++) {
|
||||
String text = row[i];
|
||||
|
||||
parentPkList.add(text);
|
||||
String val = String.join(TreeUtils.SEPARATOR, parentPkList);
|
||||
String parentVal = i == 0 ? TreeUtils.DEFAULT_ROOT : row[i - 1];
|
||||
String pk = String.join(TreeUtils.SEPARATOR, parentPkList);
|
||||
if (pkSet.contains(pk)) continue;
|
||||
pkSet.add(pk);
|
||||
BaseTreeNodeDTO node = new BaseTreeNodeDTO(val, parentVal, StringUtils.isNotBlank(text) ? text.trim() : text, pk + TreeUtils.SEPARATOR + i);
|
||||
nodes.add(node);
|
||||
}
|
||||
return nodes;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package io.dataease.dataset.server;
|
||||
|
||||
import io.dataease.api.dataset.DatasetDataApi;
|
||||
import io.dataease.api.dataset.dto.BaseTreeNodeDTO;
|
||||
import io.dataease.api.dataset.dto.DatasetTableDTO;
|
||||
import io.dataease.api.dataset.dto.EnumValueRequest;
|
||||
import io.dataease.api.dataset.dto.PreviewSqlDTO;
|
||||
@ -70,4 +71,15 @@ public class DatasetDataServer implements DatasetDataApi {
|
||||
public Long getDatasetCount(DatasetGroupInfoDTO datasetGroupInfoDTO) throws Exception {
|
||||
return datasetDataManage.getDatasetTotal(datasetGroupInfoDTO.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseTreeNodeDTO> getFieldValueTree(List<Long> ids) throws Exception {
|
||||
try {
|
||||
return datasetDataManage.getFieldValueTree(ids);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LogUtil.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package io.dataease.dataset.utils;
|
||||
|
||||
import io.dataease.api.dataset.dto.BaseTreeNodeDTO;
|
||||
import io.dataease.utils.TreeUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author Junjun
|
||||
*/
|
||||
public class DatasetUtils {
|
||||
public final static String SEPARATOR = "-de-";
|
||||
|
||||
public static List<BaseTreeNodeDTO> mergeDuplicateTree(List<BaseTreeNodeDTO> tree, String... rootPid) {
|
||||
Assert.notNull(rootPid, "Root Pid cannot be null");
|
||||
if (CollectionUtils.isEmpty(tree)) {
|
||||
return null;
|
||||
}
|
||||
List<BaseTreeNodeDTO> result = new ArrayList<>();
|
||||
// 构建id-节点map映射
|
||||
Map<String, BaseTreeNodeDTO> treePidMap = tree.stream().collect(Collectors.toMap(node -> node.getNodeType(), t -> t));
|
||||
tree.stream().filter(item -> ObjectUtils.isNotEmpty(item.getId())).forEach(node -> {
|
||||
|
||||
String nodeType = node.getNodeType();
|
||||
String[] links = nodeType.split(SEPARATOR);
|
||||
int length = links.length;
|
||||
int level = Integer.parseInt(links[length - 1]);
|
||||
// 判断根节点
|
||||
if (Arrays.asList(rootPid).contains(node.getPid()) && 0 == level) {
|
||||
result.add(node);
|
||||
} else {
|
||||
//找到父元素
|
||||
String[] pLinks = new String[level];
|
||||
System.arraycopy(links, 0, pLinks, 0, level);
|
||||
String parentType = Arrays.stream(pLinks).collect(Collectors.joining(SEPARATOR)) + TreeUtils.SEPARATOR + (level - 1);
|
||||
BaseTreeNodeDTO parentNode = treePidMap.get(parentType);
|
||||
if (parentNode == null) {
|
||||
// 可能出现 rootPid 更高的节点 这个操作相当于截断
|
||||
return;
|
||||
}
|
||||
if (parentNode.getChildren() == null) {
|
||||
parentNode.setChildren(new ArrayList());
|
||||
}
|
||||
parentNode.getChildren().add(node);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -41,6 +41,9 @@ public class ApiUtils {
|
||||
};
|
||||
List<ApiDefinition> apiDefinitionList = JsonUtil.parseList(datasourceRequest.getDatasource().getConfiguration(), listTypeReference);
|
||||
for (ApiDefinition apiDefinition : apiDefinitionList) {
|
||||
if (StringUtils.isNotEmpty(apiDefinition.getType()) && apiDefinition.getType().equalsIgnoreCase("params")) {
|
||||
continue;
|
||||
}
|
||||
DatasetTableDTO datasetTableDTO = new DatasetTableDTO();
|
||||
datasetTableDTO.setTableName(apiDefinition.getDeTableName());
|
||||
datasetTableDTO.setName(apiDefinition.getName());
|
||||
@ -59,7 +62,7 @@ public class ApiUtils {
|
||||
if (apiDefinition == null) {
|
||||
DEException.throwException("未找到");
|
||||
}
|
||||
String response = execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout());
|
||||
String response = execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout(), params(datasourceRequest));
|
||||
fieldList = getTableFields(apiDefinition);
|
||||
result.put("fieldList", fieldList);
|
||||
dataList = fetchResult(response, apiDefinition);
|
||||
@ -116,19 +119,38 @@ public class ApiUtils {
|
||||
if (apiDefinition == null) {
|
||||
DEException.throwException("未找到");
|
||||
}
|
||||
String response = execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout());
|
||||
String response = execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout(), params(datasourceRequest));
|
||||
return fetchResult(response, apiDefinition);
|
||||
}
|
||||
|
||||
|
||||
public static String execHttpRequest(ApiDefinition apiDefinition, int socketTimeout) {
|
||||
public static String execHttpRequest(ApiDefinition apiDefinition, int socketTimeout, List<ApiDefinition> paramsList) {
|
||||
String response = "";
|
||||
HttpClientConfig httpClientConfig = new HttpClientConfig();
|
||||
httpClientConfig.setSocketTimeout(socketTimeout * 1000);
|
||||
ApiDefinitionRequest apiDefinitionRequest = apiDefinition.getRequest();
|
||||
for (Map header : apiDefinitionRequest.getHeaders()) {
|
||||
if (header.get("name") != null && StringUtils.isNotEmpty(header.get("name").toString()) && header.get("value") != null && StringUtils.isNotEmpty(header.get("value").toString())) {
|
||||
httpClientConfig.addHeader(header.get("name").toString(), header.get("value").toString());
|
||||
if (header.get("nameType") != null && header.get("nameType").toString().equalsIgnoreCase("params")) {
|
||||
String param = header.get("value").toString();
|
||||
for (ApiDefinition definition : paramsList) {
|
||||
for (int i = 0; i < definition.getFields().size(); i++) {
|
||||
TableField field = definition.getFields().get(i);
|
||||
if (field.getOriginName().equalsIgnoreCase(param)) {
|
||||
String resultStr = execHttpRequest(definition, definition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout(), null);
|
||||
List<String[]> dataList = fetchResult(resultStr, definition);
|
||||
System.out.println(dataList.get(0)[i]);
|
||||
if (dataList.size() > 0) {
|
||||
httpClientConfig.addHeader(header.get("name").toString(), dataList.get(0)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
httpClientConfig.addHeader(header.get("name").toString(), header.get("value").toString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (apiDefinitionRequest.getAuthManager() != null
|
||||
@ -194,7 +216,7 @@ public class ApiUtils {
|
||||
return response;
|
||||
}
|
||||
|
||||
private static void previewNum(List<Map<String, Object>> field){
|
||||
private static void previewNum(List<Map<String, Object>> field) {
|
||||
for (Map<String, Object> stringObjectMap : field) {
|
||||
JSONArray newArray = new JSONArray();
|
||||
if (stringObjectMap.get("value") != null) {
|
||||
@ -202,7 +224,7 @@ public class ApiUtils {
|
||||
TypeReference<JSONArray> listTypeReference = new TypeReference<JSONArray>() {
|
||||
};
|
||||
JSONArray array = objectMapper.readValue(stringObjectMap.get("value").toString(), listTypeReference);
|
||||
if(array.size() > 100){
|
||||
if (array.size() > 100) {
|
||||
for (int i = 0; i < Math.min(100, array.size()); i++) {
|
||||
newArray.add(array.get(i));
|
||||
}
|
||||
@ -254,8 +276,8 @@ public class ApiUtils {
|
||||
}
|
||||
int i = 0;
|
||||
try {
|
||||
LinkedHashMap data = currentData.get(0);
|
||||
}catch (Exception e){
|
||||
LinkedHashMap data = currentData.get(0);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException("数据不符合规范, " + e.getMessage());
|
||||
}
|
||||
for (LinkedHashMap data : currentData) {
|
||||
@ -540,6 +562,18 @@ public class ApiUtils {
|
||||
}
|
||||
|
||||
|
||||
private static List<ApiDefinition> params(DatasourceRequest datasourceRequest) {
|
||||
TypeReference<List<ApiDefinition>> listTypeReference = new TypeReference<List<ApiDefinition>>() {
|
||||
};
|
||||
List<ApiDefinition> apiDefinitionListTemp = null;
|
||||
try {
|
||||
apiDefinitionListTemp = objectMapper.readValue(datasourceRequest.getDatasource().getConfiguration(), listTypeReference);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
}
|
||||
return apiDefinitionListTemp.stream().filter(apiDefinition -> apiDefinition.getType() != null && apiDefinition.getType().equalsIgnoreCase("params")).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static ApiDefinition checkApiDefinition(DatasourceRequest datasourceRequest) throws DEException {
|
||||
List<ApiDefinition> apiDefinitionList = new ArrayList<>();
|
||||
TypeReference<List<ApiDefinition>> listTypeReference = new TypeReference<List<ApiDefinition>>() {
|
||||
|
||||
@ -393,7 +393,7 @@ public class CalciteProvider {
|
||||
configuration = JsonUtil.parseObject(datasourceDTO.getConfiguration(), Impala.class);
|
||||
if (StringUtils.isNotEmpty(configuration.getUrlType()) && configuration.getUrlType().equalsIgnoreCase("jdbcUrl")) {
|
||||
if (configuration.getJdbcUrl().contains("password=")) {
|
||||
String[] params = configuration.getJdbcUrl().split(";")[1].split("&");
|
||||
String[] params = configuration.getJdbcUrl().split(";");
|
||||
String pd = "";
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (params[i].contains("password=")) {
|
||||
|
||||
@ -107,6 +107,8 @@ public class DatasourceServer implements DatasourceApi {
|
||||
all_scope, add_scope
|
||||
}
|
||||
|
||||
private TypeReference<List<ApiDefinition>> listTypeReference = new TypeReference<List<ApiDefinition>>() {
|
||||
};
|
||||
@Resource
|
||||
private CommonThreadPool commonThreadPool;
|
||||
|
||||
@ -505,11 +507,11 @@ public class DatasourceServer implements DatasourceApi {
|
||||
DEException.throwException("不存在的数据源!");
|
||||
}
|
||||
BeanUtils.copyBean(datasourceDTO, datasource);
|
||||
TypeReference<List<ApiDefinition>> listTypeReference = new TypeReference<List<ApiDefinition>>() {
|
||||
};
|
||||
|
||||
if (datasourceDTO.getType().equalsIgnoreCase(DatasourceConfiguration.DatasourceType.API.toString())) {
|
||||
List<ApiDefinition> apiDefinitionList = JsonUtil.parseList(datasourceDTO.getConfiguration(), listTypeReference);
|
||||
List<ApiDefinition> apiDefinitionListWithStatus = new ArrayList<>();
|
||||
List<ApiDefinition> params = new ArrayList<>();
|
||||
int success = 0;
|
||||
for (ApiDefinition apiDefinition : apiDefinitionList) {
|
||||
String status = null;
|
||||
@ -534,9 +536,16 @@ public class DatasourceServer implements DatasourceApi {
|
||||
if (log != null) {
|
||||
apiDefinition.setUpdateTime(log.getStartTime());
|
||||
}
|
||||
apiDefinitionListWithStatus.add(apiDefinition);
|
||||
|
||||
|
||||
if (StringUtils.isEmpty(apiDefinition.getType()) || apiDefinition.getType().equalsIgnoreCase("table")) {
|
||||
apiDefinitionListWithStatus.add(apiDefinition);
|
||||
} else {
|
||||
params.add(apiDefinition);
|
||||
}
|
||||
}
|
||||
datasourceDTO.setApiConfigurationStr(new String(Base64.getEncoder().encode(Objects.requireNonNull(JsonUtil.toJSONString(apiDefinitionListWithStatus)).toString().getBytes())));
|
||||
datasourceDTO.setParamsStr(new String(Base64.getEncoder().encode(Objects.requireNonNull(JsonUtil.toJSONString(params)).toString().getBytes())));
|
||||
if (success == apiDefinitionList.size()) {
|
||||
datasourceDTO.setStatus("Success");
|
||||
} else {
|
||||
@ -847,12 +856,13 @@ public class DatasourceServer implements DatasourceApi {
|
||||
}
|
||||
|
||||
public ApiDefinition checkApiDatasource(Map<String, String> request) throws DEException {
|
||||
|
||||
ApiDefinition apiDefinition = JsonUtil.parseObject(new String(java.util.Base64.getDecoder().decode(request.get("data"))), ApiDefinition.class);
|
||||
String response = ApiUtils.execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout());
|
||||
List<ApiDefinition> paramsList = JsonUtil.parseList(new String(java.util.Base64.getDecoder().decode(request.get("paramsList"))), listTypeReference);
|
||||
String response = ApiUtils.execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 10 : apiDefinition.getApiQueryTimeout(), paramsList);
|
||||
if (request.keySet().contains("type") && request.get("type").equals("apiStructure")) {
|
||||
apiDefinition.setShowApiStructure(true);
|
||||
}
|
||||
|
||||
ApiUtils.checkApiDefinition(apiDefinition, response);
|
||||
if (apiDefinition.getRequest().getAuthManager() != null && StringUtils.isNotBlank(apiDefinition.getRequest().getAuthManager().getUsername()) && StringUtils.isNotBlank(apiDefinition.getRequest().getAuthManager().getPassword()) && apiDefinition.getRequest().getAuthManager().getVerification().equals("Basic Auth")) {
|
||||
apiDefinition.getRequest().getAuthManager().setUsername(new String(Base64.getEncoder().encode(apiDefinition.getRequest().getAuthManager().getUsername().getBytes())));
|
||||
|
||||
@ -87,12 +87,12 @@ public class MenuManage {
|
||||
}
|
||||
|
||||
private boolean isXpackMenu(CoreMenu coreMenu) {
|
||||
if (coreMenu.getId().equals(21L)) return false;
|
||||
return coreMenu.getId().equals(7L)
|
||||
|| coreMenu.getPid().equals(7L)
|
||||
|| coreMenu.getId().equals(14L)
|
||||
|| coreMenu.getId().equals(17L)
|
||||
|| coreMenu.getId().equals(18L)
|
||||
|| coreMenu.getId().equals(21L)
|
||||
|| coreMenu.getPid().equals(21L)
|
||||
|| coreMenu.getId().equals(25L)
|
||||
|| coreMenu.getId().equals(26L)
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
package io.dataease.visualization.dao.auto.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-06-25
|
||||
*/
|
||||
@TableName("visualization_report_filter")
|
||||
public class VisualizationReportFilter implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 报告ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 资源id
|
||||
*/
|
||||
private Long resourceId;
|
||||
|
||||
/**
|
||||
* 资源类型
|
||||
*/
|
||||
private String dvType;
|
||||
|
||||
/**
|
||||
* 组件id
|
||||
*/
|
||||
private Long componentId;
|
||||
|
||||
/**
|
||||
* 过滤项id
|
||||
*/
|
||||
private Long filterId;
|
||||
|
||||
/**
|
||||
* 过滤组件内容
|
||||
*/
|
||||
private String filterInfo;
|
||||
|
||||
/**
|
||||
* 过滤组件版本
|
||||
*/
|
||||
private Integer filterVersion;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Long createTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createUser;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public void setResourceId(Long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public String getDvType() {
|
||||
return dvType;
|
||||
}
|
||||
|
||||
public void setDvType(String dvType) {
|
||||
this.dvType = dvType;
|
||||
}
|
||||
|
||||
public Long getComponentId() {
|
||||
return componentId;
|
||||
}
|
||||
|
||||
public void setComponentId(Long componentId) {
|
||||
this.componentId = componentId;
|
||||
}
|
||||
|
||||
public Long getFilterId() {
|
||||
return filterId;
|
||||
}
|
||||
|
||||
public void setFilterId(Long filterId) {
|
||||
this.filterId = filterId;
|
||||
}
|
||||
|
||||
public String getFilterInfo() {
|
||||
return filterInfo;
|
||||
}
|
||||
|
||||
public void setFilterInfo(String filterInfo) {
|
||||
this.filterInfo = filterInfo;
|
||||
}
|
||||
|
||||
public Integer getFilterVersion() {
|
||||
return filterVersion;
|
||||
}
|
||||
|
||||
public void setFilterVersion(Integer filterVersion) {
|
||||
this.filterVersion = filterVersion;
|
||||
}
|
||||
|
||||
public Long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getCreateUser() {
|
||||
return createUser;
|
||||
}
|
||||
|
||||
public void setCreateUser(String createUser) {
|
||||
this.createUser = createUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VisualizationReportFilter{" +
|
||||
"id = " + id +
|
||||
", resourceId = " + resourceId +
|
||||
", dvType = " + dvType +
|
||||
", componentId = " + componentId +
|
||||
", filterId = " + filterId +
|
||||
", filterInfo = " + filterInfo +
|
||||
", filterVersion = " + filterVersion +
|
||||
", createTime = " + createTime +
|
||||
", createUser = " + createUser +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package io.dataease.visualization.dao.auto.mapper;
|
||||
|
||||
import io.dataease.visualization.dao.auto.entity.VisualizationReportFilter;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-06-25
|
||||
*/
|
||||
@Mapper
|
||||
public interface VisualizationReportFilterMapper extends BaseMapper<VisualizationReportFilter> {
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.dataease.api.visualization.dto.VisualizationViewTableDTO;
|
||||
import io.dataease.api.visualization.vo.DataVisualizationBaseVO;
|
||||
import io.dataease.api.visualization.vo.DataVisualizationVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationReportFilterVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationResourceVO;
|
||||
import io.dataease.chart.dao.auto.entity.CoreChartView;
|
||||
import io.dataease.visualization.dao.ext.po.StorePO;
|
||||
@ -48,5 +49,7 @@ public interface ExtDataVisualizationMapper {
|
||||
|
||||
List<VisualizationViewTableDTO> getVisualizationViewDetails(@Param("dvId") Long dvId);
|
||||
|
||||
List<VisualizationReportFilterVO> queryReportFilter(@Param("dvId") Long dvId,@Param("reportId") Long reportId);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package io.dataease.visualization.server;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.dataease.api.visualization.vo.VisualizationReportFilterVO;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.api.template.dto.TemplateManageFileDTO;
|
||||
import io.dataease.api.template.dto.VisualizationTemplateExtendDataDTO;
|
||||
@ -35,6 +36,7 @@ import io.dataease.utils.*;
|
||||
import io.dataease.visualization.dao.auto.entity.DataVisualizationInfo;
|
||||
import io.dataease.visualization.dao.auto.entity.VisualizationWatermark;
|
||||
import io.dataease.visualization.dao.auto.mapper.DataVisualizationInfoMapper;
|
||||
import io.dataease.visualization.dao.auto.mapper.VisualizationReportFilterMapper;
|
||||
import io.dataease.visualization.dao.auto.mapper.VisualizationWatermarkMapper;
|
||||
import io.dataease.visualization.dao.ext.mapper.ExtDataVisualizationMapper;
|
||||
import io.dataease.visualization.manage.CoreVisualizationManage;
|
||||
@ -90,9 +92,12 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
@Resource
|
||||
private VisualizationWatermarkMapper watermarkMapper;
|
||||
|
||||
@Resource
|
||||
private VisualizationReportFilterMapper reportFilterMapper;
|
||||
|
||||
@Override
|
||||
public DataVisualizationVO findCopyResource(Long dvId, String busiFlag) {
|
||||
DataVisualizationVO result = findById(dvId, busiFlag);
|
||||
DataVisualizationVO result = findById(new DataVisualizationBaseRequest(dvId, busiFlag));
|
||||
if (result != null && result.getPid() == -1) {
|
||||
return result;
|
||||
} else {
|
||||
@ -100,10 +105,12 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
}
|
||||
}
|
||||
|
||||
@DeLog(id = "#p0", ot = LogOT.READ, stExp = "#p1")
|
||||
@DeLog(id = "#p0.id", ot = LogOT.READ, stExp = "#p0.busiFlag")
|
||||
@Override
|
||||
@XpackInteract(value = "dataVisualizationServer", original = true)
|
||||
public DataVisualizationVO findById(Long dvId, String busiFlag) {
|
||||
public DataVisualizationVO findById(DataVisualizationBaseRequest request) {
|
||||
Long dvId = request.getId();
|
||||
String busiFlag = request.getBusiFlag();
|
||||
DataVisualizationVO result = extDataVisualizationMapper.findDvInfo(dvId, busiFlag);
|
||||
if (result != null) {
|
||||
//获取图表信息
|
||||
@ -116,6 +123,16 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
VisualizationWatermarkVO watermarkVO = new VisualizationWatermarkVO();
|
||||
BeanUtils.copyBean(watermarkVO, watermark);
|
||||
result.setWatermarkInfo(watermarkVO);
|
||||
|
||||
if(DataVisualizationConstants.QUERY_SOURCE.REPORT.equals(request.getSource()) && request.getReportId() != null){
|
||||
//获取定时报告过自定义过滤组件信息
|
||||
List<VisualizationReportFilterVO> filterVOS = extDataVisualizationMapper.queryReportFilter(dvId,request.getReportId());
|
||||
if (!CollectionUtils.isEmpty(filterVOS)) {
|
||||
Map<Long, VisualizationReportFilterVO> reportFilterInfo = filterVOS.stream().collect(Collectors.toMap(VisualizationReportFilterVO::getFilterId, filterVo ->filterVo));
|
||||
result.setReportFilterInfo(reportFilterInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
DEException.throwException("资源不存在或已经被删除...");
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
ALTER TABLE `core_export_task`
|
||||
ADD COLUMN `msg` LONGTEXT NULL COMMENT '错误信息' AFTER `params`;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `xpack_plugin`;
|
||||
CREATE TABLE `xpack_plugin`
|
||||
(
|
||||
`id` bigint NOT NULL COMMENT 'ID',
|
||||
`name` varchar(255) NOT NULL COMMENT '插件名称',
|
||||
`icon` longtext NOT NULL COMMENT '图标',
|
||||
`version` varchar(255) NOT NULL COMMENT '版本',
|
||||
`install_time` bigint NOT NULL COMMENT '安装时间',
|
||||
`flag` varchar(255) NOT NULL COMMENT '类型',
|
||||
`developer` varchar(255) NOT NULL COMMENT '开发者',
|
||||
`config` longtext NOT NULL COMMENT '插件配置',
|
||||
`require_version` varchar(255) NOT NULL COMMENT 'DE最低版本',
|
||||
`module_name` varchar(255) NOT NULL COMMENT '模块名称',
|
||||
`jar_name` varchar(255) NOT NULL COMMENT 'Jar包名称',
|
||||
PRIMARY KEY (`id`)
|
||||
) COMMENT ='插件表';
|
||||
|
||||
ALTER TABLE `xpack_share`
|
||||
ADD COLUMN `ticket_require` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'ticket必须' AFTER `auto_pwd`;
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `core_share_ticket`;
|
||||
CREATE TABLE `core_share_ticket`
|
||||
(
|
||||
`id` bigint NOT NULL COMMENT 'ID',
|
||||
`uuid` varchar(255) NOT NULL COMMENT '分享uuid',
|
||||
`ticket` varchar(255) NOT NULL COMMENT 'ticket',
|
||||
`exp` bigint DEFAULT NULL COMMENT 'ticket有效期',
|
||||
`args` longtext COMMENT 'ticket参数',
|
||||
`access_time` bigint DEFAULT NULL COMMENT '首次访问时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) COMMENT ='分享Ticket表';
|
||||
|
||||
DROP TABLE IF EXISTS `visualization_report_filter`;
|
||||
CREATE TABLE `visualization_report_filter` (
|
||||
`id` bigint NOT NULL COMMENT '报告ID',
|
||||
`resource_id` bigint DEFAULT NULL COMMENT '资源id',
|
||||
`dv_type` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '资源类型',
|
||||
`component_id` bigint DEFAULT NULL COMMENT '组件id',
|
||||
`filter_id` bigint DEFAULT NULL COMMENT '过滤项id',
|
||||
`filter_info` longtext COLLATE utf8mb4_general_ci COMMENT '过滤组件内容',
|
||||
`filter_version` int DEFAULT NULL COMMENT '过滤组件版本',
|
||||
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`create_user` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
@ -33,4 +33,18 @@ CREATE TABLE `core_share_ticket`
|
||||
`args` longtext COMMENT 'ticket参数',
|
||||
`access_time` bigint DEFAULT NULL COMMENT '首次访问时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) COMMENT ='分享Ticket表';
|
||||
) COMMENT ='分享Ticket表';
|
||||
|
||||
DROP TABLE IF EXISTS `visualization_report_filter`;
|
||||
CREATE TABLE `visualization_report_filter` (
|
||||
`id` bigint NOT NULL COMMENT '报告ID',
|
||||
`resource_id` bigint DEFAULT NULL COMMENT '资源id',
|
||||
`dv_type` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '资源类型',
|
||||
`component_id` bigint DEFAULT NULL COMMENT '组件id',
|
||||
`filter_id` bigint DEFAULT NULL COMMENT '过滤项id',
|
||||
`filter_info` longtext COLLATE utf8mb4_general_ci COMMENT '过滤组件内容',
|
||||
`filter_version` int DEFAULT NULL COMMENT '过滤组件版本',
|
||||
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
|
||||
`create_user` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
@ -403,4 +403,20 @@
|
||||
WHERE core_chart_view.scene_id = #{dvId}
|
||||
AND core_chart_view.id IS NOT NULL and core_chart_view.`type` != 'VQuery'
|
||||
</select>
|
||||
|
||||
<select id="queryReportFilter" resultType="io.dataease.api.visualization.vo.VisualizationReportFilterVO">
|
||||
SELECT
|
||||
`id`,
|
||||
`resource_id`,
|
||||
`dv_type`,
|
||||
`component_id`,
|
||||
`filter_id`,
|
||||
`filter_info`,
|
||||
`filter_version`,
|
||||
`create_time`,
|
||||
`create_user`
|
||||
FROM
|
||||
visualization_report_filter
|
||||
where visualization_report_filter.resource_id = #{dvId} and visualization_report_filter.id = #{reportId}
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/dataease.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>DataEase</title>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@ -20,14 +20,15 @@ export const findCopyResource = async (dvId, busiFlag): Promise<IResponse> => {
|
||||
return request.get({ url: '/dataVisualization/findCopyResource/' + dvId + '/' + busiFlag })
|
||||
}
|
||||
|
||||
export const findById = async (dvId, busiFlag): Promise<IResponse> => {
|
||||
export const findById = async (dvId, busiFlag, source = 'main'): Promise<IResponse> => {
|
||||
let busiFlagResult = busiFlag
|
||||
if (!busiFlagResult) {
|
||||
await findDvType(dvId).then(res => {
|
||||
busiFlagResult = res.data
|
||||
})
|
||||
}
|
||||
return request.get({ url: '/dataVisualization/findById/' + dvId + '/' + busiFlagResult })
|
||||
const data = { id: dvId, busiFlag: busiFlagResult, source }
|
||||
return request.post({ url: '/dataVisualization/findById', data })
|
||||
}
|
||||
|
||||
export const queryTreeApi = async (data: BusiTreeRequest): Promise<IResponse> => {
|
||||
|
||||
@ -289,6 +289,8 @@ const updateQueryCriteria = () => {
|
||||
ele.checkedFields = checkedFields
|
||||
ele.checkedFieldsMap = checkedFieldsMap
|
||||
} else {
|
||||
if (!ele.dataset.id || ele.optionValueSource !== 1 || ![0, 2, 5].includes(+ele.displayType))
|
||||
return
|
||||
const checkedFields = []
|
||||
datasetFieldList.value.forEach(itx => {
|
||||
if (itx.tableId === ele.dataset.id) {
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { useRoute } from 'vue-router'
|
||||
const route = useRoute()
|
||||
</script>
|
||||
<template>
|
||||
<router-view :key="route.path" />
|
||||
</template>
|
||||
@ -4,6 +4,7 @@ import { XpackComponent } from '@/components/plugin'
|
||||
const modules = import.meta.glob('../views/**/*.vue')
|
||||
export const Layout = () => import('@/layout/index.vue')
|
||||
const xpackComName = 'components/plugin'
|
||||
export const LayoutTransition = () => import('@/layout/components/LayoutTransition.vue')
|
||||
// 后端控制路由生成
|
||||
export const generateRoutesFn2 = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => {
|
||||
const res: AppRouteRecordRaw[] = []
|
||||
@ -37,12 +38,14 @@ export const generateRoutesFn2 = (routes: AppCustomRouteRecordRaw[]): AppRouteRe
|
||||
let comModule = null
|
||||
if (route.component === xpackComName) {
|
||||
comModule = XpackComponent
|
||||
} else {
|
||||
} else if (!route.component.startsWith('Layout')) {
|
||||
comModule = modules[`../views/${route.component}/index.vue`]
|
||||
}
|
||||
|
||||
if (route.component === 'Layout') {
|
||||
data.component = Layout
|
||||
} else if (route.component === 'LayoutTransition') {
|
||||
data.component = LayoutTransition
|
||||
} else if (!comModule) {
|
||||
} else {
|
||||
data.component = comModule
|
||||
|
||||
@ -19,7 +19,7 @@ export const useAppStore = defineStore('app', {
|
||||
return {
|
||||
size: true, // 尺寸图标
|
||||
pageLoading: false, // 路由跳转loading
|
||||
title: 'DataEase',
|
||||
title: '',
|
||||
dekey: 'DataEaseKey',
|
||||
isDataEaseBi: false,
|
||||
isIframe: false,
|
||||
|
||||
@ -152,10 +152,12 @@ export const useAppearanceStore = defineStore('appearanceStore', {
|
||||
if (this.loaded) {
|
||||
return
|
||||
}
|
||||
document.title = ''
|
||||
const res = await uiLoadApi()
|
||||
this.loaded = true
|
||||
const resData = res.data
|
||||
if (!resData?.length) {
|
||||
document.title = 'DataEase'
|
||||
return
|
||||
}
|
||||
const data: AppearanceState = { loaded: false, community: true }
|
||||
@ -223,6 +225,8 @@ export const useAppearanceStore = defineStore('appearanceStore', {
|
||||
this.footContent = data.footContent
|
||||
if (this.name) {
|
||||
document.title = this.name
|
||||
} else {
|
||||
document.title = 'DataEase'
|
||||
}
|
||||
if (isDataEaseBi) return
|
||||
const link = document.querySelector('link[rel="icon"]')
|
||||
|
||||
27
core/core-frontend/src/utils/CanvasInfoTransUtils.ts
Normal file
27
core/core-frontend/src/utils/CanvasInfoTransUtils.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
|
||||
export default function defaultConditionTrans(canvasInfo) {
|
||||
const { reportFilterInfo, componentData } = canvasInfo
|
||||
const componentDataArray = JSON.parse(componentData)
|
||||
const allFilter = []
|
||||
// 获取所有查询条件
|
||||
componentDataArray.forEach(item => {
|
||||
if (item.component === 'VQuery') {
|
||||
Array.prototype.push.apply(allFilter, item.propValue)
|
||||
}
|
||||
})
|
||||
|
||||
const allDefaultFilter = deepCopy(allFilter)
|
||||
if (reportFilterInfo) {
|
||||
allFilter.forEach((itemFilter, index) => {
|
||||
if (reportFilterInfo[itemFilter.id]) {
|
||||
allDefaultFilter.splice(index, 1, JSON.parse(reportFilterInfo[itemFilter.id]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
sourceFilter: allFilter,
|
||||
defaultFilter: allDefaultFilter
|
||||
}
|
||||
}
|
||||
@ -394,7 +394,6 @@ export class RangeBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyseHorizontal,
|
||||
this.configEmptyDataStrategy
|
||||
)(chart, options)
|
||||
}
|
||||
|
||||
@ -238,12 +238,19 @@ export const quotaViews = ['label', 'richTextView', 'indicator', 'gauge', 'liqui
|
||||
|
||||
export function handleEmptyDataStrategy<O extends PickOptions>(chart: Chart, options: O): O {
|
||||
const { data } = options as unknown as Options
|
||||
const isChartMix = chart.type.includes('chart-mix')
|
||||
if (!data?.length) {
|
||||
return options
|
||||
}
|
||||
const strategy = parseJson(chart.senior).functionCfg.emptyDataStrategy
|
||||
if (strategy === 'ignoreData') {
|
||||
handleIgnoreData(data)
|
||||
if (isChartMix) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
handleIgnoreData(data[i] as Record<string, any>[])
|
||||
}
|
||||
} else {
|
||||
handleIgnoreData(data)
|
||||
}
|
||||
return options
|
||||
}
|
||||
const { yAxis, xAxisExt, extStack } = chart
|
||||
@ -252,7 +259,13 @@ export function handleEmptyDataStrategy<O extends PickOptions>(chart: Chart, opt
|
||||
case 'breakLine': {
|
||||
if (multiDimension) {
|
||||
// 多维度保持空
|
||||
handleBreakLineMultiDimension(data)
|
||||
if (isChartMix) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
handleBreakLineMultiDimension(data[i] as Record<string, any>[])
|
||||
}
|
||||
} else {
|
||||
handleBreakLineMultiDimension(data)
|
||||
}
|
||||
}
|
||||
return {
|
||||
...options,
|
||||
@ -262,10 +275,22 @@ export function handleEmptyDataStrategy<O extends PickOptions>(chart: Chart, opt
|
||||
case 'setZero': {
|
||||
if (multiDimension) {
|
||||
// 多维度置0
|
||||
handleSetZeroMultiDimension(data)
|
||||
if (isChartMix) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
handleSetZeroMultiDimension(data[i] as Record<string, any>[])
|
||||
}
|
||||
} else {
|
||||
handleSetZeroMultiDimension(data)
|
||||
}
|
||||
} else {
|
||||
// 单维度置0
|
||||
handleSetZeroSingleDimension(data)
|
||||
if (isChartMix) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
handleSetZeroSingleDimension(data[i] as Record<string, any>[])
|
||||
}
|
||||
} else {
|
||||
handleSetZeroSingleDimension(data)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
@ -80,6 +80,7 @@
|
||||
min="0"
|
||||
max="1440"
|
||||
size="small"
|
||||
@input="v => handleInput(v, scope.$index)"
|
||||
@change="val => validateExp(val, scope.$index)"
|
||||
/>
|
||||
<span v-else>
|
||||
@ -251,7 +252,12 @@ const refreshTicket = row => {
|
||||
row.ticket = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const handleInput = (val, index) => {
|
||||
if (val === null || val === '') {
|
||||
return
|
||||
}
|
||||
state.tableData[index]['exp'] = val.replace(/[^\d]/g, '')
|
||||
}
|
||||
const validateExp = (val, index) => {
|
||||
const cref = expRefs.value[index]
|
||||
const e = cref.input
|
||||
|
||||
@ -24,6 +24,7 @@ export interface Field {
|
||||
export interface ApiItem {
|
||||
status: string
|
||||
name: string
|
||||
type: string
|
||||
deTableName?: string
|
||||
url: string
|
||||
method: string
|
||||
@ -57,10 +58,12 @@ const originFieldItem = reactive({
|
||||
})
|
||||
|
||||
let apiItemList = reactive<ApiConfiguration[]>([])
|
||||
let paramsList = reactive<ApiConfiguration[]>([])
|
||||
|
||||
let apiItem = reactive<ApiItem>({
|
||||
status: '',
|
||||
name: '',
|
||||
type: 'table',
|
||||
url: '',
|
||||
method: 'GET',
|
||||
request: {
|
||||
@ -95,6 +98,7 @@ const edit_api_item = ref(false)
|
||||
const active = ref(1)
|
||||
const loading = ref(false)
|
||||
const columns = shallowRef([])
|
||||
const valueList = shallowRef([])
|
||||
const tableData = shallowRef([])
|
||||
const apiItemBasicInfo = ref<FormInstance>()
|
||||
const isNumber = (rule, value, callback) => {
|
||||
@ -152,9 +156,16 @@ const rule = reactive<FormRules>({
|
||||
})
|
||||
const activeName = ref('third')
|
||||
provide('api-active-name', activeName)
|
||||
const initApiItem = (val: ApiItem, apiList, name) => {
|
||||
const initApiItem = (val: ApiItem, from, name) => {
|
||||
activeName.value = name
|
||||
apiItemList = apiList
|
||||
apiItemList = from.apiConfiguration
|
||||
paramsList = from.paramsConfiguration
|
||||
if (val.type !== 'params') {
|
||||
valueList.value = []
|
||||
for (let i = 0; i < paramsList.length; i++) {
|
||||
valueList.value = valueList.value.concat(paramsList[i].fields)
|
||||
}
|
||||
}
|
||||
Object.assign(apiItem, val)
|
||||
edit_api_item.value = true
|
||||
active.value = 0
|
||||
@ -167,9 +178,10 @@ const showApiData = () => {
|
||||
apiItemBasicInfo.value.validate(valid => {
|
||||
if (valid) {
|
||||
const data = Base64.encode(JSON.stringify(apiItem))
|
||||
const params = Base64.encode(JSON.stringify(paramsList))
|
||||
loading.value = true
|
||||
cancelMap['/datasource/checkApiDatasource']?.()
|
||||
checkApiItem({ data: data, type: 'apiStructure' })
|
||||
checkApiItem({ data: data, type: 'apiStructure', paramsList: params })
|
||||
.then(response => {
|
||||
originFieldItem.jsonFields = response.data.jsonFields
|
||||
})
|
||||
@ -203,7 +215,7 @@ const fieldOptions = [
|
||||
]
|
||||
const disabledNext = ref(false)
|
||||
const saveItem = () => {
|
||||
if (apiItem.fields.length === 0) {
|
||||
if (apiItem.type !== 'params' && apiItem.fields.length === 0) {
|
||||
ElMessage.error(t('datasource.api_field_not_empty'))
|
||||
return
|
||||
}
|
||||
@ -239,7 +251,8 @@ const next = () => {
|
||||
}
|
||||
cancelMap['/datasource/checkApiDatasource']?.()
|
||||
|
||||
checkApiItem({ data: Base64.encode(JSON.stringify(apiItem)) })
|
||||
const params = Base64.encode(JSON.stringify(paramsList))
|
||||
checkApiItem({ data: Base64.encode(JSON.stringify(apiItem)), paramsList: params })
|
||||
.then(response => {
|
||||
apiItem.jsonFields = response.data.jsonFields
|
||||
apiItem.fields = []
|
||||
@ -465,6 +478,7 @@ defineExpose({
|
||||
<api-http-request-form
|
||||
v-if="edit_api_item"
|
||||
:request="apiItem.request"
|
||||
:value-list="valueList"
|
||||
@changeId="changeId"
|
||||
/>
|
||||
</el-form-item>
|
||||
@ -572,7 +586,11 @@ defineExpose({
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="deExtractType" :label="t('datasource.field_type')">
|
||||
<el-table-column
|
||||
prop="deExtractType"
|
||||
:label="t('datasource.field_type')"
|
||||
:disabled="apiItem.type == 'params'"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.deExtractType"
|
||||
|
||||
@ -22,6 +22,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
valueList: {
|
||||
type: Array as PropType<Item[]>,
|
||||
default: () => []
|
||||
},
|
||||
request: {
|
||||
type: Object as PropType<ApiRequest>,
|
||||
default: () => ({
|
||||
@ -143,6 +147,7 @@ const emits = defineEmits(['changeId'])
|
||||
:show-desc="true"
|
||||
:suggestions="headerSuggestions"
|
||||
:items="apiRequest.headers"
|
||||
:value-list="valueList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
|
||||
@ -22,6 +22,10 @@ const props = defineProps({
|
||||
type: Array as PropType<Item[]>,
|
||||
default: () => []
|
||||
},
|
||||
valueList: {
|
||||
type: Array as PropType<Item[]>,
|
||||
default: () => []
|
||||
},
|
||||
suggestions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
@ -78,7 +82,6 @@ const options = [
|
||||
value: 'fixed'
|
||||
}
|
||||
]
|
||||
|
||||
const value = ref('')
|
||||
</script>
|
||||
|
||||
@ -91,7 +94,7 @@ const value = ref('')
|
||||
<el-icon class="drag handle">
|
||||
<Icon name="icon_drag_outlined"></Icon>
|
||||
</el-icon>
|
||||
<el-col :span="activeName === 'third' ? 8 : 6" v-if="!unShowSelect">
|
||||
<el-col :span="activeName === 'params' ? 8 : 6" v-if="!unShowSelect">
|
||||
<el-input
|
||||
v-if="!suggestions"
|
||||
v-model="element.name"
|
||||
@ -110,8 +113,8 @@ const value = ref('')
|
||||
show-word-limit
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="3" v-if="activeName === 'fourth'">
|
||||
<el-select v-model="value">
|
||||
<el-col :span="3" v-if="activeName === 'table'">
|
||||
<el-select v-model="element.nameType">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
@ -131,19 +134,31 @@ const value = ref('')
|
||||
/>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="activeName === 'third' ? 7 : 6">
|
||||
<el-col :span="activeName === 'params' ? 7 : 6">
|
||||
<el-input
|
||||
v-if="!needMock && activeName === 'third'"
|
||||
v-if="!needMock && activeName === 'params'"
|
||||
v-model="element.value"
|
||||
:disabled="isReadOnly"
|
||||
:placeholder="unShowSelect ? t('common.description') : valueText"
|
||||
show-word-limit
|
||||
/>
|
||||
<el-select
|
||||
v-model="element.value"
|
||||
v-if="!needMock && activeName === 'table' && element.nameType === 'params'"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in valueList"
|
||||
:key="item.originName"
|
||||
:label="item.name"
|
||||
:value="item.originName"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-input
|
||||
v-if="!needMock && activeName === 'fourth'"
|
||||
v-if="!needMock && activeName === 'table' && element.nameType !== 'params'"
|
||||
v-model="element.value"
|
||||
:disabled="isReadOnly"
|
||||
:placeholder="value === 'params' ? '参数名称' : '值'"
|
||||
:placeholder="'值'"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-col>
|
||||
|
||||
@ -27,6 +27,7 @@ const prop = defineProps({
|
||||
syncSetting?: SyncSetting
|
||||
configuration?: Configuration
|
||||
apiConfiguration?: ApiConfiguration[]
|
||||
paramsConfiguration?: ApiConfiguration[]
|
||||
}>({
|
||||
id: 0,
|
||||
name: '',
|
||||
@ -80,6 +81,7 @@ const defaultApiItem = {
|
||||
name: '',
|
||||
deTableName: '',
|
||||
url: '',
|
||||
type: '',
|
||||
serialNumber: 0,
|
||||
method: 'GET',
|
||||
request: {
|
||||
@ -319,17 +321,24 @@ const addApiItem = item => {
|
||||
apiItem = cloneDeep(item)
|
||||
} else {
|
||||
apiItem = cloneDeep(defaultApiItem)
|
||||
apiItem.serialNumber =
|
||||
apiItem.type = activeName.value
|
||||
let serialNumber1 =
|
||||
form.value.apiConfiguration.length > 0
|
||||
? form.value.apiConfiguration[form.value.apiConfiguration.length - 1].serialNumber + 1
|
||||
: 0
|
||||
let serialNumber2 =
|
||||
form.value.paramsConfiguration.length > 0
|
||||
? form.value.paramsConfiguration[form.value.paramsConfiguration.length - 1].serialNumber + 1
|
||||
: 0
|
||||
|
||||
apiItem.serialNumber = serialNumber1 + serialNumber2
|
||||
}
|
||||
nextTick(() => {
|
||||
editApiItem.value.initApiItem(apiItem, form.value.apiConfiguration, activeName.value)
|
||||
editApiItem.value.initApiItem(apiItem, form.value, activeName.value)
|
||||
})
|
||||
}
|
||||
|
||||
const activeName = ref('third')
|
||||
const activeName = ref('table')
|
||||
const showPriority = ref(false)
|
||||
|
||||
const deleteItem = (item, idx) => {
|
||||
@ -354,15 +363,28 @@ const resetForm = () => {
|
||||
|
||||
const returnItem = apiItem => {
|
||||
var find = false
|
||||
for (let i = 0; i < form.value.apiConfiguration.length; i++) {
|
||||
if (form.value.apiConfiguration[i].serialNumber === apiItem.serialNumber) {
|
||||
find = true
|
||||
form.value.apiConfiguration[i] = apiItem
|
||||
if (apiItem.type !== 'params') {
|
||||
for (let i = 0; i < form.value.apiConfiguration.length; i++) {
|
||||
if (form.value.apiConfiguration[i].serialNumber === apiItem.serialNumber) {
|
||||
find = true
|
||||
form.value.apiConfiguration[i] = apiItem
|
||||
}
|
||||
}
|
||||
if (!find) {
|
||||
state.itemRef = []
|
||||
form.value.apiConfiguration.push(apiItem)
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < form.value.paramsConfiguration.length; i++) {
|
||||
if (form.value.paramsConfiguration[i].serialNumber === apiItem.serialNumber) {
|
||||
find = true
|
||||
form.value.paramsConfiguration[i] = apiItem
|
||||
}
|
||||
}
|
||||
if (!find) {
|
||||
state.itemRef = []
|
||||
form.value.paramsConfiguration.push(apiItem)
|
||||
}
|
||||
}
|
||||
if (!find) {
|
||||
state.itemRef = []
|
||||
form.value.apiConfiguration.push(apiItem)
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,12 +498,6 @@ const apiRule = {
|
||||
const dialogEditParams = ref(false)
|
||||
const dialogRenameApi = ref(false)
|
||||
const activeParamsName = ref('')
|
||||
const apiParams = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '接口1'
|
||||
}
|
||||
])
|
||||
const paramsObj = ref({
|
||||
name: '',
|
||||
id: 1,
|
||||
@ -490,7 +506,7 @@ const paramsObj = ref({
|
||||
|
||||
const apiObj = ref({
|
||||
name: '',
|
||||
id: 1
|
||||
serialNumber: 1
|
||||
})
|
||||
const paramsObjRules = {
|
||||
name: [
|
||||
@ -524,6 +540,7 @@ const apiObjRules = {
|
||||
]
|
||||
}
|
||||
const setActiveName = val => {
|
||||
gridData.value = val.fields
|
||||
activeParamsName.value = val.name
|
||||
}
|
||||
|
||||
@ -545,12 +562,13 @@ const saveParamsObj = () => {
|
||||
const saveApiObj = () => {
|
||||
apiObjRef.value.validate(result => {
|
||||
if (result) {
|
||||
apiParams.value.forEach(ele => {
|
||||
if (ele.id === apiObj.value.id) {
|
||||
form.value.paramsConfiguration.forEach(ele => {
|
||||
if (ele.serialNumber === apiObj.value.serialNumber) {
|
||||
ele.name = apiObj.value.name
|
||||
}
|
||||
})
|
||||
}
|
||||
dialogRenameApi.value = false
|
||||
})
|
||||
}
|
||||
|
||||
@ -562,17 +580,12 @@ const apiResetForm = () => {
|
||||
dialogRenameApi.value = false
|
||||
}
|
||||
|
||||
const gridData = ref([
|
||||
{
|
||||
name: 'name',
|
||||
deType: 0,
|
||||
id: 0
|
||||
}
|
||||
])
|
||||
const gridData = ref([])
|
||||
const handleApiParams = (cmd: string, data) => {
|
||||
if (cmd === 'rename') {
|
||||
dialogRenameApi.value = true
|
||||
paramsObj.value.name = data.name
|
||||
apiObj.value.name = data.name
|
||||
apiObj.value.serialNumber = data.serialNumber
|
||||
}
|
||||
if (cmd === 'delete') {
|
||||
ElMessageBox.confirm('确定删除吗?', {
|
||||
@ -581,7 +594,10 @@ const handleApiParams = (cmd: string, data) => {
|
||||
autofocus: false,
|
||||
showClose: false
|
||||
}).then(() => {
|
||||
apiParams.value.splice(0, 1)
|
||||
form.value.paramsConfiguration.splice(0, 1)
|
||||
if (activeParamsName.value === data.name) {
|
||||
gridData.value = []
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -601,7 +617,7 @@ const delParams = data => {
|
||||
autofocus: false,
|
||||
showClose: false
|
||||
}).then(() => {
|
||||
apiParams.value.splice(0, 1)
|
||||
gridData.value.splice(0, 1)
|
||||
})
|
||||
}
|
||||
const datasetTypeList = [
|
||||
@ -668,8 +684,8 @@ defineExpose({
|
||||
<template v-if="form.type === 'API'">
|
||||
<div class="title-form_primary flex-space table-info-mr" v-show="activeStep !== 2">
|
||||
<el-tabs v-model="activeName" class="api-tabs">
|
||||
<el-tab-pane :label="t('datasource.data_table')" name="third"></el-tab-pane>
|
||||
<el-tab-pane label="接口参数" name="fourth"></el-tab-pane>
|
||||
<el-tab-pane :label="t('datasource.data_table')" name="table"></el-tab-pane>
|
||||
<el-tab-pane label="接口参数" name="params"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-button type="primary" style="margin-left: auto" @click="() => addApiItem(null)">
|
||||
<template #icon>
|
||||
@ -680,11 +696,11 @@ defineExpose({
|
||||
</div>
|
||||
<empty-background
|
||||
v-show="activeStep !== 2"
|
||||
v-if="!form.apiConfiguration.length"
|
||||
v-if="!form.apiConfiguration.length && activeName === 'table'"
|
||||
:description="t('datasource.no_data_table')"
|
||||
img-type="noneWhite"
|
||||
/>
|
||||
<template v-if="form.type === 'API' && activeStep === 1 && activeName === 'third'">
|
||||
<template v-if="form.type === 'API' && activeStep === 1 && activeName === 'table'">
|
||||
<div class="api-card-content">
|
||||
<div
|
||||
v-for="(api, idx) in form.apiConfiguration"
|
||||
@ -759,11 +775,11 @@ defineExpose({
|
||||
</template>
|
||||
<div
|
||||
style="display: flex"
|
||||
v-if="form.type === 'API' && activeStep === 1 && activeName === 'fourth'"
|
||||
v-if="form.type === 'API' && activeStep === 1 && activeName === 'params'"
|
||||
>
|
||||
<div class="left-api_params">
|
||||
<div
|
||||
v-for="ele in apiParams"
|
||||
v-for="ele in form.paramsConfiguration"
|
||||
:class="[{ active: activeParamsName === ele.name }]"
|
||||
class="list-item_primary"
|
||||
:title="ele.name"
|
||||
@ -812,12 +828,6 @@ defineExpose({
|
||||
|
||||
<el-table-column :label="t('common.operate')">
|
||||
<template #default="scope">
|
||||
<el-button text @click.stop="editParams(scope.row)">
|
||||
<template #icon>
|
||||
<Icon name="icon_edit_outlined"></Icon>
|
||||
</template>
|
||||
</el-button>
|
||||
|
||||
<el-button text @click.stop="delParams(scope.row)">
|
||||
<template #icon>
|
||||
<Icon name="icon_delete-trash_outlined"></Icon>
|
||||
@ -1217,7 +1227,7 @@ defineExpose({
|
||||
<el-form
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
ref="paramsObjRef"
|
||||
ref="apiObjRef"
|
||||
@keydown.stop.prevent.enter
|
||||
:model="apiObj"
|
||||
:rules="apiObjRules"
|
||||
|
||||
@ -36,6 +36,7 @@ interface Form {
|
||||
type: string
|
||||
configuration?: Configuration
|
||||
apiConfiguration?: ApiConfiguration[]
|
||||
paramsConfiguration?: ApiConfiguration[]
|
||||
syncSetting?: SyncSetting
|
||||
}
|
||||
|
||||
@ -353,7 +354,10 @@ const saveDS = () => {
|
||||
request.apiConfiguration[i].fields[j].value = []
|
||||
}
|
||||
}
|
||||
request.configuration = Base64.encode(JSON.stringify(request.apiConfiguration))
|
||||
let apiItems = []
|
||||
apiItems = apiItems.concat(request.apiConfiguration)
|
||||
apiItems = apiItems.concat(request.paramsConfiguration)
|
||||
request.configuration = Base64.encode(JSON.stringify(apiItems))
|
||||
request.syncSetting.startTime = new Date(request.syncSetting.startTime).getTime()
|
||||
request.syncSetting.endTime = new Date(request.syncSetting.endTime).getTime()
|
||||
} else {
|
||||
@ -421,7 +425,8 @@ const defaultForm = {
|
||||
name: '',
|
||||
description: '',
|
||||
type: 'API',
|
||||
apiConfiguration: []
|
||||
apiConfiguration: [],
|
||||
paramsConfiguration: []
|
||||
}
|
||||
const form = reactive<Form>(cloneDeep(defaultForm))
|
||||
const defaultForm2 = {
|
||||
|
||||
@ -141,6 +141,7 @@ export interface Configuration {
|
||||
export interface ApiConfiguration {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
deTableName: string
|
||||
method: string
|
||||
url: string
|
||||
@ -176,6 +177,7 @@ export interface Node {
|
||||
editType?: number
|
||||
configuration?: Configuration
|
||||
apiConfiguration?: ApiConfiguration[]
|
||||
paramsConfiguration?: ApiConfiguration[]
|
||||
weight?: number
|
||||
lastSyncTime?: number | string
|
||||
}
|
||||
|
||||
@ -471,6 +471,7 @@ const handleNodeClick = data => {
|
||||
configuration,
|
||||
syncSetting,
|
||||
apiConfigurationStr,
|
||||
paramsStr,
|
||||
fileName,
|
||||
size,
|
||||
description,
|
||||
@ -482,6 +483,9 @@ const handleNodeClick = data => {
|
||||
if (apiConfigurationStr) {
|
||||
apiConfigurationStr = JSON.parse(Base64.decode(apiConfigurationStr))
|
||||
}
|
||||
if (paramsStr) {
|
||||
paramsStr = JSON.parse(Base64.decode(paramsStr))
|
||||
}
|
||||
Object.assign(nodeInfo, {
|
||||
name,
|
||||
pid,
|
||||
@ -496,6 +500,7 @@ const handleNodeClick = data => {
|
||||
configuration,
|
||||
syncSetting,
|
||||
apiConfiguration: apiConfigurationStr,
|
||||
paramsConfiguration: paramsStr,
|
||||
weight: data.weight,
|
||||
lastSyncTime
|
||||
})
|
||||
@ -587,6 +592,7 @@ const editDatasource = (editType?: number) => {
|
||||
configuration,
|
||||
syncSetting,
|
||||
apiConfigurationStr,
|
||||
paramsStr,
|
||||
fileName,
|
||||
size,
|
||||
description,
|
||||
@ -595,6 +601,9 @@ const editDatasource = (editType?: number) => {
|
||||
if (configuration) {
|
||||
configuration = JSON.parse(Base64.decode(configuration))
|
||||
}
|
||||
if (paramsStr) {
|
||||
paramsStr = JSON.parse(Base64.decode(paramsStr))
|
||||
}
|
||||
if (apiConfigurationStr) {
|
||||
apiConfigurationStr = JSON.parse(Base64.decode(apiConfigurationStr))
|
||||
}
|
||||
@ -613,6 +622,7 @@ const editDatasource = (editType?: number) => {
|
||||
configuration,
|
||||
syncSetting,
|
||||
apiConfiguration: apiConfigurationStr,
|
||||
paramsConfiguration: paramsStr,
|
||||
lastSyncTime
|
||||
})
|
||||
datasourceEditor.value.init(datasource)
|
||||
|
||||
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
||||
Subproject commit 178f8f52209c1ffb81b58c8055733d411aef054a
|
||||
Subproject commit d03ecc9d0d31d2b09caa19afd1e3601b4a4b3f7e
|
||||
18
null/VisualizationReportFilterController.java
Normal file
18
null/VisualizationReportFilterController.java
Normal file
@ -0,0 +1,18 @@
|
||||
package io.dataease.visualization.dao.auto.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-06-25
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/visualizationReportFilter")
|
||||
public class VisualizationReportFilterController {
|
||||
|
||||
}
|
||||
5
null/VisualizationReportFilterMapper.xml
Normal file
5
null/VisualizationReportFilterMapper.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?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.visualization.dao.auto.mapper.VisualizationReportFilterMapper">
|
||||
|
||||
</mapper>
|
||||
20
null/VisualizationReportFilterServiceImpl.java
Normal file
20
null/VisualizationReportFilterServiceImpl.java
Normal file
@ -0,0 +1,20 @@
|
||||
package io.dataease.visualization.dao.auto.service.impl;
|
||||
|
||||
import io.dataease.visualization.dao.auto.entity.VisualizationReportFilter;
|
||||
import io.dataease.visualization.dao.auto.mapper.VisualizationReportFilterMapper;
|
||||
import io.dataease.visualization.dao.auto.service.IVisualizationReportFilterService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-06-25
|
||||
*/
|
||||
@Service
|
||||
public class VisualizationReportFilterServiceImpl extends ServiceImpl<VisualizationReportFilterMapper, VisualizationReportFilter> implements IVisualizationReportFilterService {
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package io.dataease.api.dataset;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.api.dataset.dto.BaseTreeNodeDTO;
|
||||
import io.dataease.api.dataset.dto.DatasetTableDTO;
|
||||
import io.dataease.api.dataset.dto.EnumValueRequest;
|
||||
import io.dataease.api.dataset.dto.PreviewSqlDTO;
|
||||
@ -47,4 +48,8 @@ public interface DatasetDataApi {
|
||||
@Operation(summary = "获取数据集总数据量", hidden = true)
|
||||
@PostMapping("getDatasetCount")
|
||||
Long getDatasetCount(@RequestBody DatasetGroupInfoDTO datasetGroupInfoDTO) throws Exception;
|
||||
|
||||
@Operation(summary = "获取下拉树数据", hidden = true)
|
||||
@PostMapping("getFieldTree")
|
||||
List<BaseTreeNodeDTO> getFieldValueTree(@RequestBody List<Long> ids) throws Exception;
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
package io.dataease.api.dataset.dto;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BaseTreeNodeDTO {
|
||||
|
||||
private String id;
|
||||
|
||||
private String pid;
|
||||
|
||||
private String text;
|
||||
|
||||
private String nodeType;
|
||||
|
||||
private List<BaseTreeNodeDTO> children;
|
||||
|
||||
public BaseTreeNodeDTO(String id, String pid, String text, String nodeType) {
|
||||
this.id = id;
|
||||
this.pid = pid;
|
||||
this.text = text;
|
||||
this.nodeType = nodeType;
|
||||
}
|
||||
|
||||
}
|
||||
@ -28,4 +28,5 @@ public class ApiDefinition {
|
||||
private String orgName;
|
||||
private boolean showApiStructure;
|
||||
private Long updateTime;
|
||||
private String type = "table";
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ public class DatasourceDTO implements Serializable {
|
||||
private String configuration;
|
||||
|
||||
private String apiConfigurationStr;
|
||||
private String paramsStr;
|
||||
|
||||
/**
|
||||
* Create timestamp
|
||||
|
||||
@ -30,10 +30,11 @@ public interface DataVisualizationApi {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/findById/{dvId}/{busiFlag}")
|
||||
@DePermit(value = {"#p0+':read'"}, busiFlag = "#p1")
|
||||
@PostMapping("/findById")
|
||||
@DePermit(value = {"#p0.id+':read'"}, busiFlag = "#p0.busiFlag")
|
||||
@Operation(summary = "查询可视化资源")
|
||||
DataVisualizationVO findById(@PathVariable("dvId") Long dvId,@PathVariable("busiFlag") String busiFlag);
|
||||
DataVisualizationVO findById(@RequestBody DataVisualizationBaseRequest request);
|
||||
|
||||
|
||||
@GetMapping("/findCopyResource/{dvId}/{busiFlag}")
|
||||
@Operation(summary = "查询临时复制资源")
|
||||
|
||||
@ -2,8 +2,10 @@ package io.dataease.api.visualization.request;
|
||||
|
||||
import io.dataease.api.visualization.vo.DataVisualizationVO;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class DataVisualizationBaseRequest extends DataVisualizationVO {
|
||||
|
||||
private String opt;
|
||||
@ -24,4 +26,17 @@ public class DataVisualizationBaseRequest extends DataVisualizationVO {
|
||||
|
||||
private String templateUrl;
|
||||
|
||||
private String busiFlag;
|
||||
|
||||
// 查询来源 main=主工程 report=定时报告
|
||||
private String source;
|
||||
|
||||
// 定时报告id
|
||||
private Long reportId;
|
||||
|
||||
|
||||
public DataVisualizationBaseRequest(Long id,String busiFlag) {
|
||||
this.busiFlag = busiFlag;
|
||||
super.setId(id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,6 +152,12 @@ public class DataVisualizationVO implements Serializable {
|
||||
*/
|
||||
private Map<Long, VisualizationTemplateExtendDataDTO> extendDataInfo = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 定时报告自定义过滤数据
|
||||
*/
|
||||
private Map<Long,VisualizationReportFilterVO> reportFilterInfo = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 水印信息
|
||||
*/
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
package io.dataease.api.visualization.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-06-25
|
||||
*/
|
||||
public class VisualizationReportFilterVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 报告ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 资源id
|
||||
*/
|
||||
private Long resourceId;
|
||||
|
||||
/**
|
||||
* 资源类型
|
||||
*/
|
||||
private String dvType;
|
||||
|
||||
/**
|
||||
* 组件id
|
||||
*/
|
||||
private Long componentId;
|
||||
|
||||
/**
|
||||
* 过滤项id
|
||||
*/
|
||||
private Long filterId;
|
||||
|
||||
/**
|
||||
* 过滤组件内容
|
||||
*/
|
||||
private String filterInfo;
|
||||
|
||||
/**
|
||||
* 过滤组件版本
|
||||
*/
|
||||
private Integer filterVersion;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Long createTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createUser;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
public void setResourceId(Long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public String getDvType() {
|
||||
return dvType;
|
||||
}
|
||||
|
||||
public void setDvType(String dvType) {
|
||||
this.dvType = dvType;
|
||||
}
|
||||
|
||||
public Long getComponentId() {
|
||||
return componentId;
|
||||
}
|
||||
|
||||
public void setComponentId(Long componentId) {
|
||||
this.componentId = componentId;
|
||||
}
|
||||
|
||||
public Long getFilterId() {
|
||||
return filterId;
|
||||
}
|
||||
|
||||
public void setFilterId(Long filterId) {
|
||||
this.filterId = filterId;
|
||||
}
|
||||
|
||||
public String getFilterInfo() {
|
||||
return filterInfo;
|
||||
}
|
||||
|
||||
public void setFilterInfo(String filterInfo) {
|
||||
this.filterInfo = filterInfo;
|
||||
}
|
||||
|
||||
public Integer getFilterVersion() {
|
||||
return filterVersion;
|
||||
}
|
||||
|
||||
public void setFilterVersion(Integer filterVersion) {
|
||||
this.filterVersion = filterVersion;
|
||||
}
|
||||
|
||||
public Long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getCreateUser() {
|
||||
return createUser;
|
||||
}
|
||||
|
||||
public void setCreateUser(String createUser) {
|
||||
this.createUser = createUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VisualizationReportFilter{" +
|
||||
"id = " + id +
|
||||
", resourceId = " + resourceId +
|
||||
", dvType = " + dvType +
|
||||
", componentId = " + componentId +
|
||||
", filterId = " + filterId +
|
||||
", filterInfo = " + filterInfo +
|
||||
", filterVersion = " + filterVersion +
|
||||
", createTime = " + createTime +
|
||||
", createUser = " + createUser +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@ -8,10 +8,7 @@ import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.EntityBuilder;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPatch;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
@ -225,6 +222,41 @@ public class HttpClientUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static String put(String url, String json, HttpClientConfig config) {
|
||||
CloseableHttpClient httpClient = null;
|
||||
try {
|
||||
httpClient = buildHttpClient(url);
|
||||
HttpPut httpPut = new HttpPut(url);
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
httpPut.setConfig(config.buildRequestConfig());
|
||||
Map<String, String> header = config.getHeader();
|
||||
for (String key : header.keySet()) {
|
||||
httpPut.addHeader(key, header.get(key));
|
||||
}
|
||||
EntityBuilder entityBuilder = EntityBuilder.create();
|
||||
entityBuilder.setText(json);
|
||||
entityBuilder.setContentType(ContentType.APPLICATION_JSON);
|
||||
HttpEntity requestEntity = entityBuilder.build();
|
||||
httpPut.setEntity(requestEntity);
|
||||
|
||||
HttpResponse response = httpClient.execute(httpPut);
|
||||
return getResponseStr(response, config);
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClient查询失败", e);
|
||||
throw new DEException(SYSTEM_INNER_ERROR.code(), "HttpClient查询失败: " + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (httpClient != null) {
|
||||
httpClient.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClient关闭连接失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post请求,请求内容必须为JSON格式的字符串
|
||||
*
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package io.dataease.extensions.view.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AxisFormatResult {
|
||||
private Map<ChartAxis, List<ChartViewFieldDTO>> axisMap;
|
||||
private Map<String, Object> context;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package io.dataease.extensions.view.dto;
|
||||
|
||||
public enum ChartAxis {
|
||||
xAxis,
|
||||
xAxisExt,
|
||||
extStack,
|
||||
extLabel,
|
||||
extTooltip,
|
||||
yAxis,
|
||||
yAxisExt,
|
||||
drill,
|
||||
extBubble;
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package io.dataease.extensions.view.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ChartCalcDataResult {
|
||||
private Map<String, Object> data;
|
||||
private List<String[]> originData;
|
||||
private List<String[]> assistData;
|
||||
private List<ChartSeniorAssistDTO> dynamicAssistFields;
|
||||
private Map<String, Object> context;
|
||||
// TODO 数据源插件化之后换成整个请求对象
|
||||
private String querySql;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package io.dataease.extensions.view.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -23,4 +24,10 @@ public class ChartViewFieldDTO extends ChartViewFieldBaseDTO implements Serializ
|
||||
private String busiType;
|
||||
|
||||
private boolean isAgg;
|
||||
|
||||
/**
|
||||
* 字段来源
|
||||
*/
|
||||
@JsonIgnore
|
||||
private FieldSource source;
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package io.dataease.extensions.view.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class CustomFilterResult {
|
||||
private List<ChartExtFilterDTO> filterList;
|
||||
private Map<String, Object> context;
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
package io.dataease.extensions.view.dto;
|
||||
|
||||
public enum FieldSource {
|
||||
DRILL
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package io.dataease.extensions.view.util;
|
||||
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ChartDataUtil {
|
||||
// 对结果排序
|
||||
public static List<String[]> resultCustomSort(List<ChartViewFieldDTO> xAxis, List<String[]> data) {
|
||||
List<String[]> res = new ArrayList<>(data);
|
||||
if (xAxis.size() > 0) {
|
||||
// 找到对应维度
|
||||
for (int i = 0; i < xAxis.size(); i++) {
|
||||
ChartViewFieldDTO item = xAxis.get(i);
|
||||
if (StringUtils.equalsIgnoreCase(item.getSort(), "custom_sort")) {
|
||||
// 获取自定义值与data对应列的结果
|
||||
if (i > 0) {
|
||||
// 首先根据优先级高的字段分类,在每个前置字段相同的组里排序
|
||||
Map<String, List<String[]>> map = new LinkedHashMap<>();
|
||||
for (String[] d : res) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (StringUtils.equalsIgnoreCase(xAxis.get(j).getSort(), "none")) {
|
||||
continue;
|
||||
}
|
||||
stringBuilder.append(d[j]);
|
||||
}
|
||||
if (ObjectUtils.isEmpty(map.get(stringBuilder.toString()))) {
|
||||
map.put(stringBuilder.toString(), new ArrayList<>());
|
||||
}
|
||||
map.get(stringBuilder.toString()).add(d);
|
||||
}
|
||||
Iterator<Map.Entry<String, List<String[]>>> iterator = map.entrySet().iterator();
|
||||
List<String[]> list = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, List<String[]>> next = iterator.next();
|
||||
list.addAll(customSort(Optional.ofNullable(item.getCustomSort()).orElse(new ArrayList<>()), next.getValue(), i));
|
||||
}
|
||||
res.clear();
|
||||
res.addAll(list);
|
||||
} else {
|
||||
res = customSort(Optional.ofNullable(item.getCustomSort()).orElse(new ArrayList<>()), res, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static List<String[]> customSort(List<String> custom, List<String[]> data, int index) {
|
||||
List<String[]> res = new ArrayList<>();
|
||||
|
||||
List<Integer> indexArr = new ArrayList<>();
|
||||
List<String[]> joinArr = new ArrayList<>();
|
||||
for (int i = 0; i < custom.size(); i++) {
|
||||
String ele = custom.get(i);
|
||||
for (int j = 0; j < data.size(); j++) {
|
||||
String[] d = data.get(j);
|
||||
if (StringUtils.equalsIgnoreCase(ele, d[index])) {
|
||||
joinArr.add(d);
|
||||
indexArr.add(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 取得 joinArr 就是两者的交集
|
||||
List<Integer> indexArrData = new ArrayList<>();
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
indexArrData.add(i);
|
||||
}
|
||||
List<Integer> indexResult = new ArrayList<>();
|
||||
for (int i = 0; i < indexArrData.size(); i++) {
|
||||
if (!indexArr.contains(indexArrData.get(i))) {
|
||||
indexResult.add(indexArrData.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
List<String[]> subArr = new ArrayList<>();
|
||||
for (int i = 0; i < indexResult.size(); i++) {
|
||||
subArr.add(data.get(indexResult.get(i)));
|
||||
}
|
||||
res.addAll(joinArr);
|
||||
res.addAll(subArr);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package io.dataease.extensions.view.util;
|
||||
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldBaseDTO;
|
||||
import io.dataease.extensions.view.dto.DatasetTableFieldDTO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FieldUtil {
|
||||
public static List<DatasetTableFieldDTO> transFields(List<? extends ChartViewFieldBaseDTO> list) {
|
||||
return list.stream().map(ele -> {
|
||||
DatasetTableFieldDTO dto = new DatasetTableFieldDTO();
|
||||
BeanUtils.copyProperties(dto, ele);
|
||||
return dto;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user